mirror of https://github.com/trapexit/mergerfs.git
Antonio SJ Musumeci
8 years ago
9 changed files with 456 additions and 209 deletions
-
40src/fs_base_utime.hpp
-
298src/fs_base_utime_generic.hpp
-
19src/fs_base_utime_utimensat.hpp
-
190src/fs_clonefile.cpp
-
38src/fs_clonepath.cpp
-
21src/fs_time.cpp
-
22src/fs_time.hpp
-
33src/fs_time_futimes.icpp
-
4src/utimens.cpp
@ -0,0 +1,298 @@ |
|||
/*
|
|||
ISC License |
|||
|
|||
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link> |
|||
|
|||
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 <string>
|
|||
|
|||
#include <fcntl.h>
|
|||
#include <sys/stat.h>
|
|||
#include <sys/time.h>
|
|||
|
|||
#ifndef UTIME_NOW
|
|||
# define UTIME_NOW ((1l << 30) - 1l)
|
|||
#endif
|
|||
|
|||
#ifndef UTIME_OMIT
|
|||
# define UTIME_OMIT ((1l << 30) - 2l)
|
|||
#endif
|
|||
|
|||
static |
|||
inline |
|||
bool |
|||
_can_call_lutimes(const int dirfd, |
|||
const std::string &path, |
|||
const int flags) |
|||
{ |
|||
return ((flags == AT_SYMLINK_NOFOLLOW) && |
|||
((dirfd == AT_FDCWD) || |
|||
(path[0] == '/'))); |
|||
} |
|||
|
|||
static |
|||
inline |
|||
bool |
|||
_should_ignore(const struct timespec ts[2]) |
|||
{ |
|||
return ((ts != NULL) && |
|||
(ts[0].tv_nsec == UTIME_OMIT) && |
|||
(ts[1].tv_nsec == UTIME_OMIT)); |
|||
} |
|||
|
|||
static |
|||
inline |
|||
bool |
|||
_should_be_set_to_now(const struct timespec ts[2]) |
|||
{ |
|||
return ((ts == NULL) || |
|||
((ts[0].tv_nsec == UTIME_NOW) && |
|||
(ts[1].tv_nsec == UTIME_NOW))); |
|||
} |
|||
|
|||
static |
|||
inline |
|||
bool |
|||
_timespec_invalid(const struct timespec &ts) |
|||
{ |
|||
return (((ts.tv_nsec < 0) || |
|||
(ts.tv_nsec > 999999999)) && |
|||
((ts.tv_nsec != UTIME_NOW) && |
|||
(ts.tv_nsec != UTIME_OMIT))); |
|||
} |
|||
|
|||
static |
|||
inline |
|||
bool |
|||
_timespec_invalid(const struct timespec ts[2]) |
|||
{ |
|||
return ((ts != NULL) && |
|||
(_timespec_invalid(ts[0]) || |
|||
_timespec_invalid(ts[1]))); |
|||
} |
|||
|
|||
static |
|||
inline |
|||
bool |
|||
_flags_invalid(const int flags) |
|||
{ |
|||
return ((flags & ~AT_SYMLINK_NOFOLLOW) != 0); |
|||
} |
|||
|
|||
static |
|||
inline |
|||
bool |
|||
_any_timespec_is_utime_omit(const struct timespec ts[2]) |
|||
{ |
|||
return ((ts[0].tv_nsec == UTIME_OMIT) || |
|||
(ts[1].tv_nsec == UTIME_OMIT)); |
|||
} |
|||
|
|||
static |
|||
inline |
|||
bool |
|||
_any_timespec_is_utime_now(const struct timespec ts[2]) |
|||
{ |
|||
return ((ts[0].tv_nsec == UTIME_NOW) || |
|||
(ts[1].tv_nsec == UTIME_NOW)); |
|||
} |
|||
|
|||
static |
|||
inline |
|||
int |
|||
_set_utime_omit_to_current_value(const int dirfd, |
|||
const std::string &path, |
|||
const struct timespec ts[2], |
|||
struct timeval tv[2], |
|||
const int flags) |
|||
{ |
|||
int rv; |
|||
struct stat st; |
|||
|
|||
if(!_any_timespec_is_utime_omit(ts)) |
|||
return 0; |
|||
|
|||
rv = ::fstatat(dirfd,path.c_str(),&st,flags); |
|||
if(rv == -1) |
|||
return -1; |
|||
|
|||
if(ts[0].tv_nsec == UTIME_OMIT) |
|||
TIMESPEC_TO_TIMEVAL(&tv[0],&st.st_atim); |
|||
if(ts[1].tv_nsec == UTIME_OMIT) |
|||
TIMESPEC_TO_TIMEVAL(&tv[1],&st.st_mtim); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
static |
|||
inline |
|||
int |
|||
_set_utime_omit_to_current_value(const int fd, |
|||
const struct timespec ts[2], |
|||
struct timeval tv[2]) |
|||
{ |
|||
int rv; |
|||
struct stat st; |
|||
|
|||
if(!_any_timespec_is_utime_omit(ts)) |
|||
return 0; |
|||
|
|||
rv = ::fstat(fd,&st); |
|||
if(rv == -1) |
|||
return -1; |
|||
|
|||
if(ts[0].tv_nsec == UTIME_OMIT) |
|||
TIMESPEC_TO_TIMEVAL(&tv[0],&st.st_atim); |
|||
if(ts[1].tv_nsec == UTIME_OMIT) |
|||
TIMESPEC_TO_TIMEVAL(&tv[1],&st.st_mtim); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
static |
|||
inline |
|||
int |
|||
_set_utime_now_to_now(const struct timespec ts[2], |
|||
struct timeval tv[2]) |
|||
{ |
|||
int rv; |
|||
struct timeval now; |
|||
|
|||
if(_any_timespec_is_utime_now(ts)) |
|||
return 0; |
|||
|
|||
rv = ::gettimeofday(&now,NULL); |
|||
if(rv == -1) |
|||
return -1; |
|||
|
|||
if(ts[0].tv_nsec == UTIME_NOW) |
|||
tv[0] = now; |
|||
if(ts[1].tv_nsec == UTIME_NOW) |
|||
tv[1] = now; |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
static |
|||
inline |
|||
int |
|||
_convert_timespec_to_timeval(const int dirfd, |
|||
const std::string &path, |
|||
const struct timespec ts[2], |
|||
struct timeval tv[2], |
|||
struct timeval *&tvp, |
|||
const int flags) |
|||
{ |
|||
int rv; |
|||
|
|||
if(_should_be_set_to_now(ts)) |
|||
return (tvp=NULL,0); |
|||
|
|||
TIMESPEC_TO_TIMEVAL(&tv[0],&ts[0]); |
|||
TIMESPEC_TO_TIMEVAL(&tv[1],&ts[1]); |
|||
|
|||
rv = _set_utime_omit_to_current_value(dirfd,path,ts,tv,flags); |
|||
if(rv == -1) |
|||
return -1; |
|||
|
|||
rv = _set_utime_now_to_now(ts,tv); |
|||
if(rv == -1) |
|||
return -1; |
|||
|
|||
return (tvp=tv,0); |
|||
} |
|||
|
|||
static |
|||
inline |
|||
int |
|||
_convert_timespec_to_timeval(const int fd, |
|||
const struct timespec ts[2], |
|||
struct timeval tv[2], |
|||
struct timeval *&tvp) |
|||
{ |
|||
int rv; |
|||
|
|||
if(_should_be_set_to_now(ts)) |
|||
return (tvp=NULL,0); |
|||
|
|||
TIMESPEC_TO_TIMEVAL(&tv[0],&ts[0]); |
|||
TIMESPEC_TO_TIMEVAL(&tv[1],&ts[1]); |
|||
|
|||
rv = _set_utime_omit_to_current_value(fd,ts,tv); |
|||
if(rv == -1) |
|||
return -1; |
|||
|
|||
rv = _set_utime_now_to_now(ts,tv); |
|||
if(rv == -1) |
|||
return -1; |
|||
|
|||
return (tvp=tv,0); |
|||
} |
|||
|
|||
namespace fs |
|||
{ |
|||
static |
|||
inline |
|||
int |
|||
utime(const int dirfd, |
|||
const std::string &path, |
|||
const struct timespec ts[2], |
|||
const int flags) |
|||
{ |
|||
int rv; |
|||
struct timeval tv[2]; |
|||
struct timeval *tvp; |
|||
|
|||
if(_flags_invalid(flags)) |
|||
return (errno=EINVAL,-1); |
|||
if(_timespec_invalid(ts)) |
|||
return (errno=EINVAL,-1); |
|||
if(_should_ignore(ts)) |
|||
return 0; |
|||
|
|||
rv = _convert_timespec_to_timeval(dirfd,path,ts,tv,tvp,flags); |
|||
if(rv == -1) |
|||
return -1; |
|||
|
|||
if((flags & AT_SYMLINK_NOFOLLOW) == 0) |
|||
return ::futimesat(dirfd,path.c_str(),tvp); |
|||
if(_can_call_lutimes(dirfd,path,flags)) |
|||
return ::lutimes(path.c_str(),tvp); |
|||
|
|||
return (errno=ENOTSUP,-1); |
|||
} |
|||
|
|||
static |
|||
inline |
|||
int |
|||
utime(const int fd, |
|||
const struct timespec ts[2]) |
|||
{ |
|||
int rv; |
|||
struct timeval tv[2]; |
|||
struct timeval *tvp; |
|||
|
|||
if(_timespec_invalid(ts)) |
|||
return (errno=EINVAL,-1); |
|||
if(_should_ignore(ts)) |
|||
return 0; |
|||
|
|||
rv = _convert_timespec_to_timeval(fd,ts,tv,tvp); |
|||
if(rv == -1) |
|||
return -1; |
|||
|
|||
return ::futimes(fd,tvp); |
|||
} |
|||
} |
@ -1,21 +0,0 @@ |
|||
/*
|
|||
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link> |
|||
|
|||
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. |
|||
*/ |
|||
|
|||
#ifdef __linux__
|
|||
# include "fs_time_futimens.icpp"
|
|||
#else
|
|||
# include "fs_time_futimes.icpp"
|
|||
#endif
|
@ -1,22 +0,0 @@ |
|||
/*
|
|||
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link> |
|||
|
|||
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. |
|||
*/ |
|||
|
|||
namespace fs |
|||
{ |
|||
int |
|||
utimes(const int fd, |
|||
const struct stat &st); |
|||
} |
@ -1,33 +0,0 @@ |
|||
/* |
|||
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link> |
|||
|
|||
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 <sys/stat.h> |
|||
#include <sys/time.h> |
|||
|
|||
namespace fs |
|||
{ |
|||
int |
|||
utimes(const int fd, |
|||
const struct stat &st) |
|||
{ |
|||
struct timeval times[2]; |
|||
|
|||
TIMESPEC_TO_TIMEVAL(×[0],&st.st_atim); |
|||
TIMESPEC_TO_TIMEVAL(×[1],&st.st_mtim); |
|||
|
|||
return ::futimes(fd,times); |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue