From 3b0d3715a1336e21aa05ac37015fc94b8ccb5e3c Mon Sep 17 00:00:00 2001 From: Antonio SJ Musumeci Date: Thu, 6 Apr 2017 10:02:07 -0400 Subject: [PATCH] abstract futimesat and getting of atime/mtime --- src/fs_base_futimesat.cpp | 23 +++++++++ src/fs_base_futimesat.hpp | 30 +++++++++++ src/fs_base_futimesat_generic.icpp | 31 +++++++++++ src/fs_base_futimesat_osx.icpp | 82 ++++++++++++++++++++++++++++++ src/fs_base_stat.hpp | 50 ++++++++++++++++++ src/fs_base_utime.hpp | 20 +++----- src/fs_base_utime_generic.hpp | 39 +++++--------- 7 files changed, 236 insertions(+), 39 deletions(-) create mode 100644 src/fs_base_futimesat.cpp create mode 100644 src/fs_base_futimesat.hpp create mode 100644 src/fs_base_futimesat_generic.icpp create mode 100644 src/fs_base_futimesat_osx.icpp diff --git a/src/fs_base_futimesat.cpp b/src/fs_base_futimesat.cpp new file mode 100644 index 000000000..c254f4b93 --- /dev/null +++ b/src/fs_base_futimesat.cpp @@ -0,0 +1,23 @@ +/* + ISC License + + Copyright (c) 2017, Antonio SJ Musumeci + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#if __APPLE__ +# include "fs_base_futimesat_osx.icpp" +#else +# include "fs_base_futimesat_generic.icpp" +#endif diff --git a/src/fs_base_futimesat.hpp b/src/fs_base_futimesat.hpp new file mode 100644 index 000000000..20f0938a4 --- /dev/null +++ b/src/fs_base_futimesat.hpp @@ -0,0 +1,30 @@ +/* + ISC License + + Copyright (c) 2017, Antonio SJ Musumeci + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#ifndef __FS_BASE_FUTIMESAT_HPP__ +#define __FS_BASE_FUTIMESAT_HPP__ + +namespace fs +{ + int + futimesat(const int dirfd, + const char *pathname, + const struct timeval times[2]); +} + +#endif diff --git a/src/fs_base_futimesat_generic.icpp b/src/fs_base_futimesat_generic.icpp new file mode 100644 index 000000000..bfcd5e57e --- /dev/null +++ b/src/fs_base_futimesat_generic.icpp @@ -0,0 +1,31 @@ +/* + ISC License + + Copyright (c) 2017, Antonio SJ Musumeci + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include +#include + +namespace fs +{ + int + futimesat(const int dirfd, + const char *pathname, + const struct timeval times[2]) + { + return ::futimesat(dirfd,pathname,times); + } +} diff --git a/src/fs_base_futimesat_osx.icpp b/src/fs_base_futimesat_osx.icpp new file mode 100644 index 000000000..ab81453fa --- /dev/null +++ b/src/fs_base_futimesat_osx.icpp @@ -0,0 +1,82 @@ +/* + ISC License + + Copyright (c) 2017, Antonio SJ Musumeci + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static +int +getpath(const int dirfd, + const char *path, + char *fullpath) +{ + int rv; + struct stat st; + + rv = ::fstat(dirfd,&st); + if(rv == -1) + return -1; + + if(!S_ISDIR(st.st_mode)) + return (errno=ENOTDIR,-1); + + rv = ::fcntl(dirfd,F_GETPATH,fullpath); + if(rv == -1) + return -1; + + rv = ::strlcat(fullpath,"/",MAXPATHLEN); + if(rv > MAXPATHLEN) + return (errno=ENAMETOOLONG,-1); + + rv = ::strlcat(fullpath,path,MAXPATHLEN); + if(rv > MAXPATHLEN) + return (errno=ENAMETOOLONG,-1); + + return 0; +} + +namespace fs +{ + int + futimesat(const int dirfd, + const char *path, + const struct timeval times[2]) + { + char fullpath[MAXPATHLEN]; + + if((dirfd == AT_FDCWD) || + ((path != NULL) && (path[0] == '/'))) + return ::utimes(path,times); + + if(dirfd < 0) + return (errno=EBADF,-1); + + rv = getpath(dirfd,path,fullpath); + if(rv == -1) + return -1; + + return ::utimes(fullpath,times); + } +} diff --git a/src/fs_base_stat.hpp b/src/fs_base_stat.hpp index e67d52673..696327392 100644 --- a/src/fs_base_stat.hpp +++ b/src/fs_base_stat.hpp @@ -62,6 +62,56 @@ namespace fs { return ::fstat(fd,&st); } + + static + inline + timespec * + stat_atime(struct stat &st) + { +#if __APPLE__ + return &st.st_atimespec; +#else + return &st.st_atim; +#endif + } + + static + inline + const + timespec * + stat_atime(const struct stat &st) + { +#if __APPLE__ + return &st.st_atimespec; +#else + return &st.st_atim; +#endif + } + + static + inline + timespec * + stat_mtime(struct stat &st) + { +#if __APPLE__ + return &st.st_mtimespec; +#else + return &st.st_mtim; +#endif + } + + static + inline + const + timespec * + stat_mtime(const struct stat &st) + { +#if __APPLE__ + return &st.st_mtimespec; +#else + return &st.st_mtim; +#endif + } } #endif diff --git a/src/fs_base_utime.hpp b/src/fs_base_utime.hpp index b57ae9f18..2def8d5c5 100644 --- a/src/fs_base_utime.hpp +++ b/src/fs_base_utime.hpp @@ -25,6 +25,8 @@ # include "fs_base_utime_generic.hpp" #endif +#include "fs_base_stat.hpp" + namespace fs { static @@ -35,13 +37,8 @@ namespace fs { struct timespec times[2]; -#if __APPLE__ - times[0] = st.st_atimespec; - times[1] = st.st_mtimespec; -#else - times[0] = st.st_atim; - times[1] = st.st_mtim; -#endif + times[0] = *fs::stat_atime(st); + times[1] = *fs::stat_mtime(st); return fs::utime(AT_FDCWD,path,times,0); } @@ -54,13 +51,8 @@ namespace fs { struct timespec times[2]; -#if __APPLE__ - times[0] = st.st_atimespec; - times[1] = st.st_mtimespec; -#else - times[0] = st.st_atim; - times[1] = st.st_mtim; -#endif + times[0] = *fs::stat_atime(st); + times[1] = *fs::stat_mtime(st); return fs::utime(fd,times); } diff --git a/src/fs_base_utime_generic.hpp b/src/fs_base_utime_generic.hpp index bd4fd0d00..b8acdca49 100644 --- a/src/fs_base_utime_generic.hpp +++ b/src/fs_base_utime_generic.hpp @@ -25,7 +25,8 @@ #include #include -#include "futimesat.hpp" /* futimesat replacement */ +#include "fs_base_futimesat.hpp" +#include "fs_base_stat.hpp" #ifndef UTIME_NOW # define UTIME_NOW ((1l << 30) - 1l) @@ -125,7 +126,8 @@ _set_utime_omit_to_current_value(const int dirfd, { int rv; struct stat st; - timespec *atime, *mtime; + timespec *atime; + timespec *mtime; if(!_any_timespec_is_utime_omit(ts)) return 0; @@ -134,14 +136,9 @@ _set_utime_omit_to_current_value(const int dirfd, if(rv == -1) return -1; -#if __APPLE__ - atime = &st.st_atimespec; - mtime = &st.st_mtimespec; -#else - atime = &st.st_atim; - mtime = &st.st_mtim; -#endif - + atime = fs::stat_atime(st); + mtime = fs::stat_mtime(st); + if(ts[0].tv_nsec == UTIME_OMIT) TIMESPEC_TO_TIMEVAL(&tv[0],atime); if(ts[1].tv_nsec == UTIME_OMIT) @@ -159,7 +156,8 @@ _set_utime_omit_to_current_value(const int fd, { int rv; struct stat st; - timespec *atime, *mtime; + timespec *atime; + timespec *mtime; if(!_any_timespec_is_utime_omit(ts)) return 0; @@ -168,13 +166,8 @@ _set_utime_omit_to_current_value(const int fd, if(rv == -1) return -1; -#if __APPLE__ - atime = &st.st_atimespec; - mtime = &st.st_mtimespec; -#else - atime = &st.st_atim; - mtime = &st.st_mtim; -#endif + atime = fs::stat_atime(st); + mtime = fs::stat_mtime(st); if(ts[0].tv_nsec == UTIME_OMIT) TIMESPEC_TO_TIMEVAL(&tv[0],atime); @@ -289,13 +282,9 @@ namespace fs if(rv == -1) return -1; - if((flags & AT_SYMLINK_NOFOLLOW) == 0) { -#if __APPLE__ - return _futimesat(dirfd,path.c_str(),tvp); -#else - return ::futimesat(dirfd,path.c_str(),tvp); -#endif - } + if((flags & AT_SYMLINK_NOFOLLOW) == 0) + return fs::futimesat(dirfd,path.c_str(),tvp); + if(_can_call_lutimes(dirfd,path,flags)) return ::lutimes(path.c_str(),tvp);