mirror of
https://github.com/s3fs-fuse/s3fs-fuse.git
synced 2024-12-22 16:58:55 +00:00
Set mtime/ctime/atime of all objects as nanosecond
This commit is contained in:
parent
ccfc119e45
commit
4b2f3fecb5
@ -796,13 +796,7 @@ bool convert_header_to_stat(const char* path, const headers_t& meta, struct stat
|
||||
mtime.tv_sec = 0;
|
||||
mtime.tv_nsec = 0;
|
||||
}
|
||||
#if defined(__APPLE__)
|
||||
pst->st_mtime = mtime.tv_sec;
|
||||
pst->st_mtimespec.tv_nsec = mtime.tv_nsec;
|
||||
#else
|
||||
pst->st_mtim.tv_sec = mtime.tv_sec;
|
||||
pst->st_mtim.tv_nsec = mtime.tv_nsec;
|
||||
#endif
|
||||
set_timespec_to_stat(*pst, ST_TYPE_MTIME, mtime);
|
||||
}
|
||||
|
||||
// ctime
|
||||
@ -814,13 +808,7 @@ bool convert_header_to_stat(const char* path, const headers_t& meta, struct stat
|
||||
ctime.tv_sec = 0;
|
||||
ctime.tv_nsec = 0;
|
||||
}
|
||||
#if defined(__APPLE__)
|
||||
pst->st_ctime = ctime.tv_sec;
|
||||
pst->st_ctimespec.tv_nsec = ctime.tv_nsec;
|
||||
#else
|
||||
pst->st_ctim.tv_sec = ctime.tv_sec;
|
||||
pst->st_ctim.tv_nsec = ctime.tv_nsec;
|
||||
#endif
|
||||
set_timespec_to_stat(*pst, ST_TYPE_CTIME, ctime);
|
||||
}
|
||||
|
||||
// atime
|
||||
@ -832,13 +820,7 @@ bool convert_header_to_stat(const char* path, const headers_t& meta, struct stat
|
||||
atime.tv_sec = 0;
|
||||
atime.tv_nsec = 0;
|
||||
}
|
||||
#if defined(__APPLE__)
|
||||
pst->st_atime = atime.tv_sec;
|
||||
pst->st_atimespec.tv_nsec = atime.tv_nsec;
|
||||
#else
|
||||
pst->st_atim.tv_sec = atime.tv_sec;
|
||||
pst->st_atim.tv_nsec = atime.tv_nsec;
|
||||
#endif
|
||||
set_timespec_to_stat(*pst, ST_TYPE_ATIME, atime);
|
||||
}
|
||||
|
||||
// size
|
||||
|
@ -533,9 +533,9 @@ FdEntity* FdManager::GetFdEntity(const char* path, int& existfd, bool newfd, boo
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FdEntity* FdManager::Open(int& fd, const char* path, headers_t* pmeta, off_t size, time_t time, int flags, bool force_tmpfile, bool is_create, bool ignore_modify, AutoLock::Type type)
|
||||
FdEntity* FdManager::Open(int& fd, const char* path, headers_t* pmeta, off_t size, const struct timespec& ts_mctime, int flags, bool force_tmpfile, bool is_create, bool ignore_modify, AutoLock::Type type)
|
||||
{
|
||||
S3FS_PRN_DBG("[path=%s][size=%lld][time=%lld][flags=0x%x][force_tmpfile=%s][create=%s][ignore_modify=%s]", SAFESTRPTR(path), static_cast<long long>(size), static_cast<long long>(time), flags, (force_tmpfile ? "yes" : "no"), (is_create ? "yes" : "no"), (ignore_modify ? "yes" : "no"));
|
||||
S3FS_PRN_DBG("[path=%s][size=%lld][ts_mctime=%s][flags=0x%x][force_tmpfile=%s][create=%s][ignore_modify=%s]", SAFESTRPTR(path), static_cast<long long>(size), str(ts_mctime).c_str(), flags, (force_tmpfile ? "yes" : "no"), (is_create ? "yes" : "no"), (ignore_modify ? "yes" : "no"));
|
||||
|
||||
if(!path || '\0' == path[0]){
|
||||
return NULL;
|
||||
@ -578,7 +578,7 @@ FdEntity* FdManager::Open(int& fd, const char* path, headers_t* pmeta, off_t siz
|
||||
}
|
||||
|
||||
// (re)open
|
||||
if(-1 == (fd = ent->Open(pmeta, size, time, flags, type))){
|
||||
if(-1 == (fd = ent->Open(pmeta, size, ts_mctime, flags, type))){
|
||||
S3FS_PRN_ERR("failed to (re)open and create new pseudo fd for path(%s).", path);
|
||||
return NULL;
|
||||
}
|
||||
@ -594,7 +594,7 @@ FdEntity* FdManager::Open(int& fd, const char* path, headers_t* pmeta, off_t siz
|
||||
ent = new FdEntity(path, cache_path.c_str());
|
||||
|
||||
// open
|
||||
if(-1 == (fd = ent->Open(pmeta, size, time, flags, type))){
|
||||
if(-1 == (fd = ent->Open(pmeta, size, ts_mctime, flags, type))){
|
||||
delete ent;
|
||||
return NULL;
|
||||
}
|
||||
@ -646,7 +646,7 @@ FdEntity* FdManager::OpenExistFdEntity(const char* path, int& fd, int flags)
|
||||
S3FS_PRN_DBG("[path=%s][flags=0x%x]", SAFESTRPTR(path), flags);
|
||||
|
||||
// search entity by path, and create pseudo fd
|
||||
FdEntity* ent = Open(fd, path, NULL, -1, -1, flags, false, false, false, AutoLock::NONE);
|
||||
FdEntity* ent = Open(fd, path, NULL, -1, S3FS_OMIT_TS, flags, false, false, false, AutoLock::NONE);
|
||||
if(!ent){
|
||||
// Not found entity
|
||||
return NULL;
|
||||
|
@ -87,7 +87,7 @@ class FdManager
|
||||
|
||||
// Return FdEntity associated with path, returning NULL on error. This operation increments the reference count; callers must decrement via Close after use.
|
||||
FdEntity* GetFdEntity(const char* path, int& existfd, bool newfd = true, bool lock_already_held = false);
|
||||
FdEntity* Open(int& fd, const char* path, headers_t* pmeta, off_t size, time_t time, int flags, bool force_tmpfile, bool is_create, bool ignore_modify, AutoLock::Type type);
|
||||
FdEntity* Open(int& fd, const char* path, headers_t* pmeta, off_t size, const struct timespec& ts_mctime, int flags, bool force_tmpfile, bool is_create, bool ignore_modify, AutoLock::Type type);
|
||||
FdEntity* GetExistFdEntity(const char* path, int existfd = -1);
|
||||
FdEntity* OpenExistFdEntity(const char* path, int& fd, int flags = O_RDONLY);
|
||||
void Rename(const std::string &from, const std::string &to);
|
||||
|
@ -98,11 +98,11 @@ FdEntity* AutoFdEntity::Attach(const char* path, int existfd)
|
||||
return pFdEntity;
|
||||
}
|
||||
|
||||
FdEntity* AutoFdEntity::Open(const char* path, headers_t* pmeta, off_t size, time_t time, int flags, bool force_tmpfile, bool is_create, bool ignore_modify, AutoLock::Type type)
|
||||
FdEntity* AutoFdEntity::Open(const char* path, headers_t* pmeta, off_t size, const struct timespec& ts_mctime, int flags, bool force_tmpfile, bool is_create, bool ignore_modify, AutoLock::Type type)
|
||||
{
|
||||
Close();
|
||||
|
||||
if(NULL == (pFdEntity = FdManager::get()->Open(pseudo_fd, path, pmeta, size, time, flags, force_tmpfile, is_create, ignore_modify, type))){
|
||||
if(NULL == (pFdEntity = FdManager::get()->Open(pseudo_fd, path, pmeta, size, ts_mctime, flags, force_tmpfile, is_create, ignore_modify, type))){
|
||||
pseudo_fd = -1;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ class AutoFdEntity
|
||||
FdEntity* Attach(const char* path, int existfd);
|
||||
int GetPseudoFd() const { return pseudo_fd; }
|
||||
|
||||
FdEntity* Open(const char* path, headers_t* pmeta, off_t size, time_t time, int flags, bool force_tmpfile, bool is_create, bool ignore_modify, AutoLock::Type type);
|
||||
FdEntity* Open(const char* path, headers_t* pmeta, off_t size, const struct timespec& ts_mctime, int flags, bool force_tmpfile, bool is_create, bool ignore_modify, AutoLock::Type type);
|
||||
FdEntity* GetExistFdEntity(const char* path, int existfd = -1);
|
||||
FdEntity* OpenExistFdEntity(const char* path, int flags = O_RDONLY);
|
||||
};
|
||||
|
@ -412,11 +412,17 @@ bool FdEntity::IsUploading(bool lock_already_held)
|
||||
// If the open is successful, returns pseudo fd.
|
||||
// If it fails, it returns an error code with a negative value.
|
||||
//
|
||||
int FdEntity::Open(const headers_t* pmeta, off_t size, time_t time, int flags, AutoLock::Type type)
|
||||
// ts_mctime argument is a variable for mtime/ctime.
|
||||
// If you want to disable this variable, specify UTIME_OMIT for
|
||||
// tv_nsec in timespec member(in this case tv_sec member is ignored).
|
||||
// This is similar to utimens operation.
|
||||
// You can use "S3FS_OMIT_TS" global variable for UTIME_OMIT.
|
||||
//
|
||||
int FdEntity::Open(const headers_t* pmeta, off_t size, const struct timespec& ts_mctime, int flags, AutoLock::Type type)
|
||||
{
|
||||
AutoLock auto_lock(&fdent_lock, type);
|
||||
|
||||
S3FS_PRN_DBG("[path=%s][physical_fd=%d][size=%lld][time=%lld][flags=0x%x]", path.c_str(), physical_fd, static_cast<long long>(size), static_cast<long long>(time), flags);
|
||||
S3FS_PRN_DBG("[path=%s][physical_fd=%d][size=%lld][ts_mctime=%s][flags=0x%x]", path.c_str(), physical_fd, static_cast<long long>(size), str(ts_mctime).c_str(), flags);
|
||||
|
||||
if (!auto_lock.isLockAcquired()) {
|
||||
// had to wait for fd lock, return
|
||||
@ -480,7 +486,7 @@ int FdEntity::Open(const headers_t* pmeta, off_t size, time_t time, int flags, A
|
||||
// using cache
|
||||
struct stat st;
|
||||
if(stat(cachepath.c_str(), &st) == 0){
|
||||
if(st.st_mtime < time){
|
||||
if(0 > compare_timespec(st, ST_TYPE_MTIME, ts_mctime)){
|
||||
S3FS_PRN_DBG("cache file stale, removing: %s", cachepath.c_str());
|
||||
if(unlink(cachepath.c_str()) != 0){
|
||||
return (0 == errno ? -EIO : -errno);
|
||||
@ -547,13 +553,13 @@ int FdEntity::Open(const headers_t* pmeta, off_t size, time_t time, int flags, A
|
||||
}else{
|
||||
// [NOTE]
|
||||
// The modify flag must not be set when opening a file,
|
||||
// if the time parameter(mtime) is specified(not -1) and
|
||||
// the cache file does not exist.
|
||||
// if the ts_mctime parameter(mtime) is specified(tv_nsec != UTIME_OMIT)
|
||||
// and the cache file does not exist.
|
||||
// If mtime is specified for the file and the cache file
|
||||
// mtime is older than it, the cache file is removed and
|
||||
// the processing comes here.
|
||||
//
|
||||
pagelist.Resize(size, false, (0 <= time ? false : true));
|
||||
pagelist.Resize(size, false, (UTIME_OMIT == ts_mctime.tv_nsec ? true : false));
|
||||
|
||||
is_truncate = true;
|
||||
}
|
||||
@ -597,13 +603,14 @@ int FdEntity::Open(const headers_t* pmeta, off_t size, time_t time, int flags, A
|
||||
}else{
|
||||
// [NOTE]
|
||||
// The modify flag must not be set when opening a file,
|
||||
// if the time parameter(mtime) is specified(not -1) and
|
||||
// the cache file does not exist.
|
||||
// if the ts_mctime parameter(mtime) is specified(tv_nsec != UTIME_OMIT)
|
||||
// and the cache file does not exist.
|
||||
// If mtime is specified for the file and the cache file
|
||||
// mtime is older than it, the cache file is removed and
|
||||
// the processing comes here.
|
||||
//
|
||||
pagelist.Resize(size, false, (0 <= time ? false : true));
|
||||
pagelist.Resize(size, false, (UTIME_OMIT == ts_mctime.tv_nsec ? true : false));
|
||||
|
||||
is_truncate = true;
|
||||
}
|
||||
}
|
||||
@ -644,10 +651,9 @@ int FdEntity::Open(const headers_t* pmeta, off_t size, time_t time, int flags, A
|
||||
}
|
||||
|
||||
// set mtime and ctime(set "x-amz-meta-mtime" and "x-amz-meta-ctime" in orgmeta)
|
||||
if(-1 != time){
|
||||
struct timespec ts = {time, 0};
|
||||
if(0 != SetMCtime(ts, ts, /*lock_already_held=*/ true)){
|
||||
S3FS_PRN_ERR("failed to set mtime. errno(%d)", errno);
|
||||
if(UTIME_OMIT != ts_mctime.tv_nsec){
|
||||
if(0 != SetMCtime(ts_mctime, ts_mctime, /*lock_already_held=*/ true)){
|
||||
S3FS_PRN_ERR("failed to set mtime/ctime. errno(%d)", errno);
|
||||
fclose(pfile);
|
||||
pfile = NULL;
|
||||
physical_fd = -1;
|
||||
@ -787,7 +793,7 @@ int FdEntity::SetCtime(struct timespec time, bool lock_already_held)
|
||||
{
|
||||
AutoLock auto_lock(&fdent_lock, lock_already_held ? AutoLock::ALREADY_LOCKED : AutoLock::NONE);
|
||||
|
||||
S3FS_PRN_INFO3("[path=%s][physical_fd=%d][time=%lld]", path.c_str(), physical_fd, static_cast<long long>(time.tv_sec));
|
||||
S3FS_PRN_INFO3("[path=%s][physical_fd=%d][time=%s]", path.c_str(), physical_fd, str(time).c_str());
|
||||
|
||||
if(-1 == time.tv_sec){
|
||||
return 0;
|
||||
@ -800,7 +806,7 @@ int FdEntity::SetAtime(struct timespec time, bool lock_already_held)
|
||||
{
|
||||
AutoLock auto_lock(&fdent_lock, lock_already_held ? AutoLock::ALREADY_LOCKED : AutoLock::NONE);
|
||||
|
||||
S3FS_PRN_INFO3("[path=%s][physical_fd=%d][time=%lld]", path.c_str(), physical_fd, static_cast<long long>(time.tv_sec));
|
||||
S3FS_PRN_INFO3("[path=%s][physical_fd=%d][time=%s]", path.c_str(), physical_fd, str(time).c_str());
|
||||
|
||||
if(-1 == time.tv_sec){
|
||||
return 0;
|
||||
@ -816,34 +822,35 @@ int FdEntity::SetMCtime(struct timespec mtime, struct timespec ctime, bool lock_
|
||||
{
|
||||
AutoLock auto_lock(&fdent_lock, lock_already_held ? AutoLock::ALREADY_LOCKED : AutoLock::NONE);
|
||||
|
||||
S3FS_PRN_INFO3("[path=%s][physical_fd=%d][mtime=%lld][ctime=%lld]", path.c_str(), physical_fd, static_cast<long long>(mtime.tv_sec), static_cast<long long>(ctime.tv_sec));
|
||||
S3FS_PRN_INFO3("[path=%s][physical_fd=%d][mtime=%s][ctime=%s]", path.c_str(), physical_fd, str(mtime).c_str(), str(ctime).c_str());
|
||||
|
||||
if(mtime.tv_sec < 0 || ctime.tv_sec < 0){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(-1 != physical_fd){
|
||||
struct timeval tv[2];
|
||||
tv[0].tv_sec = mtime.tv_sec;
|
||||
tv[0].tv_usec = mtime.tv_nsec / 1000;
|
||||
tv[1].tv_sec = ctime.tv_sec;
|
||||
tv[1].tv_usec = ctime.tv_nsec / 1000;
|
||||
if(-1 == futimes(physical_fd, tv)){
|
||||
S3FS_PRN_ERR("futimes failed. errno(%d)", errno);
|
||||
struct timespec ts[2];
|
||||
ts[0].tv_sec = mtime.tv_sec;
|
||||
ts[0].tv_nsec = mtime.tv_nsec;
|
||||
ts[1].tv_sec = ctime.tv_sec;
|
||||
ts[1].tv_nsec = ctime.tv_nsec;
|
||||
if(-1 == futimens(physical_fd, ts)){
|
||||
S3FS_PRN_ERR("futimens failed. errno(%d)", errno);
|
||||
return -errno;
|
||||
}
|
||||
}else if(!cachepath.empty()){
|
||||
// not opened file yet.
|
||||
struct timeval n_time[2];
|
||||
n_time[0].tv_sec = ctime.tv_sec;
|
||||
n_time[0].tv_usec = ctime.tv_nsec / 1000;
|
||||
n_time[1].tv_sec = mtime.tv_sec;
|
||||
n_time[1].tv_usec = mtime.tv_nsec / 1000;
|
||||
if(-1 == utimes(cachepath.c_str(), n_time)){
|
||||
S3FS_PRN_ERR("utime failed. errno(%d)", errno);
|
||||
struct timespec ts[2];
|
||||
ts[0].tv_sec = ctime.tv_sec;
|
||||
ts[0].tv_nsec = ctime.tv_nsec;
|
||||
ts[1].tv_sec = mtime.tv_sec;
|
||||
ts[1].tv_nsec = mtime.tv_nsec;
|
||||
if(-1 == utimensat(AT_FDCWD, cachepath.c_str(), ts, 0)){
|
||||
S3FS_PRN_ERR("utimensat failed. errno(%d)", errno);
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
orgmeta["x-amz-meta-mtime"] = str(mtime);
|
||||
orgmeta["x-amz-meta-ctime"] = str(ctime);
|
||||
|
||||
@ -857,7 +864,9 @@ bool FdEntity::UpdateCtime()
|
||||
if(!GetStats(st, /*lock_already_held=*/ true)){
|
||||
return false;
|
||||
}
|
||||
orgmeta["x-amz-meta-ctime"] = str(st.st_ctime);
|
||||
|
||||
orgmeta["x-amz-meta-ctime"] = str_stat_time(st, ST_TYPE_CTIME);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -868,7 +877,9 @@ bool FdEntity::UpdateAtime()
|
||||
if(!GetStats(st, /*lock_already_held=*/ true)){
|
||||
return false;
|
||||
}
|
||||
orgmeta["x-amz-meta-atime"] = str(st.st_atime);
|
||||
|
||||
orgmeta["x-amz-meta-atime"] = str_stat_time(st, ST_TYPE_ATIME);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -896,7 +907,7 @@ bool FdEntity::UpdateMtime(bool clear_holding_mtime)
|
||||
if(!GetStats(st, /*lock_already_held=*/ true)){
|
||||
return false;
|
||||
}
|
||||
orgmeta["x-amz-meta-mtime"] = str(st.st_mtime);
|
||||
orgmeta["x-amz-meta-mtime"] = str_stat_time(st, ST_TYPE_MTIME);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -905,6 +916,8 @@ bool FdEntity::SetHoldingMtime(struct timespec mtime, bool lock_already_held)
|
||||
{
|
||||
AutoLock auto_lock(&fdent_lock, lock_already_held ? AutoLock::ALREADY_LOCKED : AutoLock::NONE);
|
||||
|
||||
S3FS_PRN_INFO3("[path=%s][physical_fd=%d][mtime=%s]", path.c_str(), physical_fd, str(mtime).c_str());
|
||||
|
||||
if(mtime.tv_sec < 0){
|
||||
return false;
|
||||
}
|
||||
@ -924,34 +937,33 @@ bool FdEntity::ClearHoldingMtime(bool lock_already_held)
|
||||
return false;
|
||||
}
|
||||
if(-1 != physical_fd){
|
||||
struct timeval tv[2];
|
||||
tv[0].tv_sec = holding_mtime.tv_sec;
|
||||
tv[0].tv_usec = holding_mtime.tv_nsec / 1000;
|
||||
#if defined(__APPLE__)
|
||||
tv[1].tv_sec = st.st_ctime;
|
||||
tv[1].tv_usec = st.st_ctimespec.tv_nsec / 1000;
|
||||
#else
|
||||
tv[1].tv_sec = st.st_ctim.tv_sec;
|
||||
tv[1].tv_usec = st.st_ctim.tv_nsec / 1000;
|
||||
#endif
|
||||
if(-1 == futimes(physical_fd, tv)){
|
||||
S3FS_PRN_ERR("futimes failed. errno(%d)", errno);
|
||||
struct timespec ts[2];
|
||||
struct timespec ts_ctime;
|
||||
|
||||
ts[0].tv_sec = holding_mtime.tv_sec;
|
||||
ts[0].tv_nsec = holding_mtime.tv_nsec;
|
||||
|
||||
set_stat_to_timespec(st, ST_TYPE_CTIME, ts_ctime);
|
||||
ts[1].tv_sec = ts_ctime.tv_sec;
|
||||
ts[1].tv_nsec = ts_ctime.tv_nsec;
|
||||
|
||||
if(-1 == futimens(physical_fd, ts)){
|
||||
S3FS_PRN_ERR("futimens failed. errno(%d)", errno);
|
||||
return false;
|
||||
}
|
||||
}else if(!cachepath.empty()){
|
||||
// not opened file yet.
|
||||
struct timeval n_time[2];
|
||||
#if defined(__APPLE__)
|
||||
n_time[0].tv_sec = st.st_ctime;
|
||||
n_time[0].tv_usec = st.st_ctimespec.tv_nsec / 1000;
|
||||
#else
|
||||
n_time[0].tv_sec = st.st_ctime;
|
||||
n_time[0].tv_usec = st.st_ctim.tv_nsec / 1000;
|
||||
#endif
|
||||
n_time[1].tv_sec = holding_mtime.tv_sec;
|
||||
n_time[1].tv_usec = holding_mtime.tv_nsec / 1000;
|
||||
if(-1 == utimes(cachepath.c_str(), n_time)){
|
||||
S3FS_PRN_ERR("utime failed. errno(%d)", errno);
|
||||
struct timespec ts[2];
|
||||
struct timespec ts_ctime;
|
||||
|
||||
set_stat_to_timespec(st, ST_TYPE_CTIME, ts_ctime);
|
||||
ts[0].tv_sec = ts_ctime.tv_sec;
|
||||
ts[0].tv_nsec = ts_ctime.tv_nsec;
|
||||
|
||||
ts[1].tv_sec = holding_mtime.tv_sec;
|
||||
ts[1].tv_nsec = holding_mtime.tv_nsec;
|
||||
if(-1 == utimensat(AT_FDCWD, cachepath.c_str(), ts, 0)){
|
||||
S3FS_PRN_ERR("utimensat failed. errno(%d)", errno);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ class FdEntity
|
||||
void Close(int fd);
|
||||
bool IsOpen() const { return (-1 != physical_fd); }
|
||||
bool FindPseudoFd(int fd, bool lock_already_held = false);
|
||||
int Open(const headers_t* pmeta, off_t size, time_t time, int flags, AutoLock::Type type);
|
||||
int Open(const headers_t* pmeta, off_t size, const struct timespec& ts_mctime, int flags, AutoLock::Type type);
|
||||
bool LoadAll(int fd, headers_t* pmeta = NULL, off_t* size = NULL, bool force_load = false);
|
||||
int Dup(int fd, bool lock_already_held = false);
|
||||
int OpenPseudoFd(int flags = O_RDONLY, bool lock_already_held = false);
|
||||
|
229
src/s3fs.cpp
229
src/s3fs.cpp
@ -121,7 +121,7 @@ static int list_bucket(const char* path, S3ObjList& head, const char* delimiter,
|
||||
static int directory_empty(const char* path);
|
||||
static int rename_large_object(const char* from, const char* to);
|
||||
static int create_file_object(const char* path, mode_t mode, uid_t uid, gid_t gid);
|
||||
static int create_directory_object(const char* path, mode_t mode, time_t atime, time_t mtime, time_t ctime, uid_t uid, gid_t gid);
|
||||
static int create_directory_object(const char* path, mode_t mode, const struct timespec& ts_atime, const struct timespec& ts_mtime, const struct timespec& ts_ctime, uid_t uid, gid_t gid);
|
||||
static int rename_object(const char* from, const char* to, bool update_ctime);
|
||||
static int rename_object_nocopy(const char* from, const char* to, bool update_ctime);
|
||||
static int clone_directory_object(const char* from, const char* to, bool update_ctime);
|
||||
@ -704,10 +704,15 @@ static int get_local_fent(AutoFdEntity& autoent, FdEntity **entity, const char*
|
||||
}
|
||||
|
||||
// open
|
||||
time_t mtime = (!S_ISREG(stobj.st_mode) && !S_ISLNK(stobj.st_mode)) ? -1 : stobj.st_mtime;
|
||||
struct timespec st_mctime;
|
||||
if(!S_ISREG(stobj.st_mode) && !S_ISLNK(stobj.st_mode)){
|
||||
st_mctime = S3FS_OMIT_TS;
|
||||
}else{
|
||||
set_stat_to_timespec(stobj, ST_TYPE_MTIME, st_mctime);
|
||||
}
|
||||
bool force_tmpfile = S_ISREG(stobj.st_mode) ? false : true;
|
||||
|
||||
if(NULL == (ent = autoent.Open(path, &meta, stobj.st_size, mtime, flags, force_tmpfile, true, false, AutoLock::NONE))){
|
||||
if(NULL == (ent = autoent.Open(path, &meta, stobj.st_size, st_mctime, flags, force_tmpfile, true, false, AutoLock::NONE))){
|
||||
S3FS_PRN_ERR("Could not open file. errno(%d)", errno);
|
||||
return -EIO;
|
||||
}
|
||||
@ -856,15 +861,15 @@ static int create_file_object(const char* path, mode_t mode, uid_t uid, gid_t gi
|
||||
{
|
||||
S3FS_PRN_INFO2("[path=%s][mode=%04o]", path, mode);
|
||||
|
||||
time_t now = time(NULL);
|
||||
headers_t meta;
|
||||
std::string strnow = s3fs_str_realtime();
|
||||
headers_t meta;
|
||||
meta["Content-Type"] = S3fsCurl::LookupMimeType(std::string(path));
|
||||
meta["x-amz-meta-uid"] = str(uid);
|
||||
meta["x-amz-meta-gid"] = str(gid);
|
||||
meta["x-amz-meta-mode"] = str(mode);
|
||||
meta["x-amz-meta-atime"] = str(now);
|
||||
meta["x-amz-meta-ctime"] = str(now);
|
||||
meta["x-amz-meta-mtime"] = str(now);
|
||||
meta["x-amz-meta-atime"] = strnow;
|
||||
meta["x-amz-meta-ctime"] = strnow;
|
||||
meta["x-amz-meta-mtime"] = strnow;
|
||||
|
||||
S3fsCurl s3fscurl(true);
|
||||
return s3fscurl.PutRequest(path, meta, -1); // fd=-1 means for creating zero byte object.
|
||||
@ -917,15 +922,15 @@ static int s3fs_create(const char* _path, mode_t mode, struct fuse_file_info* fi
|
||||
return result;
|
||||
}
|
||||
|
||||
time_t now = time(NULL);
|
||||
headers_t meta;
|
||||
std::string strnow = s3fs_str_realtime();
|
||||
headers_t meta;
|
||||
meta["Content-Length"] = "0";
|
||||
meta["x-amz-meta-uid"] = str(pcxt->uid);
|
||||
meta["x-amz-meta-gid"] = str(pcxt->gid);
|
||||
meta["x-amz-meta-mode"] = str(mode);
|
||||
meta["x-amz-meta-atime"] = str(now);
|
||||
meta["x-amz-meta-mtime"] = str(now);
|
||||
meta["x-amz-meta-ctime"] = str(now);
|
||||
meta["x-amz-meta-atime"] = strnow;
|
||||
meta["x-amz-meta-mtime"] = strnow;
|
||||
meta["x-amz-meta-ctime"] = strnow;
|
||||
|
||||
// [NOTE] set no_truncate flag
|
||||
// At this point, the file has not been created(uploaded) and
|
||||
@ -941,7 +946,7 @@ static int s3fs_create(const char* _path, mode_t mode, struct fuse_file_info* fi
|
||||
|
||||
AutoFdEntity autoent;
|
||||
FdEntity* ent;
|
||||
if(NULL == (ent = autoent.Open(path, &meta, 0, -1, fi->flags, false, true, false, AutoLock::NONE))){
|
||||
if(NULL == (ent = autoent.Open(path, &meta, 0, S3FS_OMIT_TS, fi->flags, false, true, false, AutoLock::NONE))){
|
||||
StatCache::getStatCacheData()->DelStat(path);
|
||||
return -EIO;
|
||||
}
|
||||
@ -953,9 +958,9 @@ static int s3fs_create(const char* _path, mode_t mode, struct fuse_file_info* fi
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int create_directory_object(const char* path, mode_t mode, time_t atime, time_t mtime, time_t ctime, uid_t uid, gid_t gid)
|
||||
static int create_directory_object(const char* path, mode_t mode, const struct timespec& ts_atime, const struct timespec& ts_mtime, const struct timespec& ts_ctime, uid_t uid, gid_t gid)
|
||||
{
|
||||
S3FS_PRN_INFO1("[path=%s][mode=%04o][atime=%lld][mtime=%lld][ctime=%lld][uid=%u][gid=%u]", path, mode, static_cast<long long>(atime), static_cast<long long>(ctime), static_cast<long long>(mtime), (unsigned int)uid, (unsigned int)gid);
|
||||
S3FS_PRN_INFO1("[path=%s][mode=%04o][atime=%s][mtime=%s][ctime=%s][uid=%u][gid=%u]", path, mode, str(ts_atime).c_str(), str(ts_mtime).c_str(), str(ts_ctime).c_str(), (unsigned int)uid, (unsigned int)gid);
|
||||
|
||||
if(!path || '\0' == path[0]){
|
||||
return -EINVAL;
|
||||
@ -969,9 +974,9 @@ static int create_directory_object(const char* path, mode_t mode, time_t atime,
|
||||
meta["x-amz-meta-uid"] = str(uid);
|
||||
meta["x-amz-meta-gid"] = str(gid);
|
||||
meta["x-amz-meta-mode"] = str(mode);
|
||||
meta["x-amz-meta-atime"] = str(atime);
|
||||
meta["x-amz-meta-mtime"] = str(mtime);
|
||||
meta["x-amz-meta-ctime"] = str(ctime);
|
||||
meta["x-amz-meta-atime"] = str(ts_atime);
|
||||
meta["x-amz-meta-mtime"] = str(ts_mtime);
|
||||
meta["x-amz-meta-ctime"] = str(ts_ctime);
|
||||
|
||||
S3fsCurl s3fscurl;
|
||||
return s3fscurl.PutRequest(tpath.c_str(), meta, -1); // fd=-1 means for creating zero byte object.
|
||||
@ -999,7 +1004,9 @@ static int s3fs_mkdir(const char* _path, mode_t mode)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
time_t now = time(NULL);
|
||||
|
||||
struct timespec now;
|
||||
s3fs_realtime(now);
|
||||
result = create_directory_object(path, mode, now, now, now, pcxt->uid, pcxt->gid);
|
||||
|
||||
StatCache::getStatCacheData()->DelStat(path);
|
||||
@ -1122,13 +1129,13 @@ static int s3fs_symlink(const char* _from, const char* _to)
|
||||
return result;
|
||||
}
|
||||
|
||||
time_t now = time(NULL);
|
||||
headers_t headers;
|
||||
std::string strnow = s3fs_str_realtime();
|
||||
headers_t headers;
|
||||
headers["Content-Type"] = std::string("application/octet-stream"); // Static
|
||||
headers["x-amz-meta-mode"] = str(S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
headers["x-amz-meta-atime"] = str(now);
|
||||
headers["x-amz-meta-ctime"] = str(now);
|
||||
headers["x-amz-meta-mtime"] = str(now);
|
||||
headers["x-amz-meta-atime"] = strnow;
|
||||
headers["x-amz-meta-ctime"] = strnow;
|
||||
headers["x-amz-meta-mtime"] = strnow;
|
||||
headers["x-amz-meta-uid"] = str(pcxt->uid);
|
||||
headers["x-amz-meta-gid"] = str(pcxt->gid);
|
||||
|
||||
@ -1137,7 +1144,7 @@ static int s3fs_symlink(const char* _from, const char* _to)
|
||||
{ // scope for AutoFdEntity
|
||||
AutoFdEntity autoent;
|
||||
FdEntity* ent;
|
||||
if(NULL == (ent = autoent.Open(to, &headers, 0, -1, O_RDWR, true, true, false, AutoLock::NONE))){
|
||||
if(NULL == (ent = autoent.Open(to, &headers, 0, S3FS_OMIT_TS, O_RDWR, true, true, false, AutoLock::NONE))){
|
||||
S3FS_PRN_ERR("could not open tmpfile(errno=%d)", errno);
|
||||
return -errno;
|
||||
}
|
||||
@ -1192,7 +1199,7 @@ static int rename_object(const char* from, const char* to, bool update_ctime)
|
||||
s3_realpath = get_realpath(from);
|
||||
|
||||
if(update_ctime){
|
||||
meta["x-amz-meta-ctime"] = str(time(NULL));
|
||||
meta["x-amz-meta-ctime"] = s3fs_str_realtime();
|
||||
}
|
||||
meta["x-amz-copy-source"] = urlEncode(service_path + S3fsCred::GetBucket() + s3_realpath);
|
||||
meta["Content-Type"] = S3fsCurl::LookupMimeType(std::string(to));
|
||||
@ -1210,7 +1217,7 @@ static int rename_object(const char* from, const char* to, bool update_ctime)
|
||||
// no opened fd
|
||||
if(FdManager::IsCacheDir()){
|
||||
// create cache file if be needed
|
||||
ent = autoent.Open(from, &meta, buf.st_size, -1, O_RDONLY, false, true, false, AutoLock::NONE);
|
||||
ent = autoent.Open(from, &meta, buf.st_size, S3FS_OMIT_TS, O_RDONLY, false, true, false, AutoLock::NONE);
|
||||
}
|
||||
if(ent){
|
||||
struct timespec mtime = get_mtime(meta);
|
||||
@ -1282,7 +1289,8 @@ static int rename_object_nocopy(const char* from, const char* to, bool update_ct
|
||||
|
||||
// update ctime
|
||||
if(update_ctime){
|
||||
struct timespec ts = {time(NULL), 0};
|
||||
struct timespec ts;
|
||||
s3fs_realtime(ts);
|
||||
ent->SetCtime(ts);
|
||||
}
|
||||
|
||||
@ -1349,7 +1357,18 @@ static int clone_directory_object(const char* from, const char* to, bool update_
|
||||
if(0 != (result = get_object_attribute(from, &stbuf))){
|
||||
return result;
|
||||
}
|
||||
result = create_directory_object(to, stbuf.st_mode, stbuf.st_atime, stbuf.st_mtime, (update_ctime ? time(NULL) : stbuf.st_ctime), stbuf.st_uid, stbuf.st_gid);
|
||||
|
||||
struct timespec ts_atime;
|
||||
struct timespec ts_mtime;
|
||||
struct timespec ts_ctime;
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_ATIME, ts_atime);
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_MTIME, ts_mtime);
|
||||
if(update_ctime){
|
||||
s3fs_realtime(ts_ctime);
|
||||
}else{
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_CTIME, ts_ctime);
|
||||
}
|
||||
result = create_directory_object(to, stbuf.st_mode, ts_atime, ts_mtime, ts_ctime, stbuf.st_uid, stbuf.st_gid);
|
||||
|
||||
StatCache::getStatCacheData()->DelStat(to);
|
||||
|
||||
@ -1605,13 +1624,20 @@ static int s3fs_chmod(const char* _path, mode_t mode)
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
|
||||
// Make new directory object("dir/")
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), mode, stbuf.st_atime, stbuf.st_mtime, time(NULL), stbuf.st_uid, stbuf.st_gid))){
|
||||
struct timespec ts_atime;
|
||||
struct timespec ts_mtime;
|
||||
struct timespec ts_ctime;
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_ATIME, ts_atime);
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_MTIME, ts_mtime);
|
||||
s3fs_realtime(ts_ctime);
|
||||
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), mode, ts_atime, ts_mtime, ts_ctime, stbuf.st_uid, stbuf.st_gid))){
|
||||
return result;
|
||||
}
|
||||
}else{
|
||||
// normal object or directory object of newer version
|
||||
headers_t updatemeta;
|
||||
updatemeta["x-amz-meta-ctime"] = str(time(NULL));
|
||||
updatemeta["x-amz-meta-ctime"] = s3fs_str_realtime();
|
||||
updatemeta["x-amz-meta-mode"] = str(mode);
|
||||
updatemeta["x-amz-copy-source"] = urlEncode(service_path + S3fsCred::GetBucket() + get_realpath(strpath.c_str()));
|
||||
updatemeta["x-amz-metadata-directive"] = "REPLACE";
|
||||
@ -1698,7 +1724,14 @@ static int s3fs_chmod_nocopy(const char* _path, mode_t mode)
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
|
||||
// Make new directory object("dir/")
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), mode, stbuf.st_atime, stbuf.st_mtime, time(NULL), stbuf.st_uid, stbuf.st_gid))){
|
||||
struct timespec ts_atime;
|
||||
struct timespec ts_mtime;
|
||||
struct timespec ts_ctime;
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_ATIME, ts_atime);
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_MTIME, ts_mtime);
|
||||
s3fs_realtime(ts_ctime);
|
||||
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), mode, ts_atime, ts_mtime, ts_ctime, stbuf.st_uid, stbuf.st_gid))){
|
||||
return result;
|
||||
}
|
||||
}else{
|
||||
@ -1712,7 +1745,8 @@ static int s3fs_chmod_nocopy(const char* _path, mode_t mode)
|
||||
return result;
|
||||
}
|
||||
|
||||
struct timespec ts = {time(NULL), 0};
|
||||
struct timespec ts;
|
||||
s3fs_realtime(ts);
|
||||
ent->SetCtime(ts);
|
||||
|
||||
// Change file mode
|
||||
@ -1782,12 +1816,19 @@ static int s3fs_chown(const char* _path, uid_t uid, gid_t gid)
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
|
||||
// Make new directory object("dir/")
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, stbuf.st_atime, stbuf.st_mtime, time(NULL), uid, gid))){
|
||||
struct timespec ts_atime;
|
||||
struct timespec ts_mtime;
|
||||
struct timespec ts_ctime;
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_ATIME, ts_atime);
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_MTIME, ts_mtime);
|
||||
s3fs_realtime(ts_ctime);
|
||||
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, ts_atime, ts_mtime, ts_ctime, uid, gid))){
|
||||
return result;
|
||||
}
|
||||
}else{
|
||||
headers_t updatemeta;
|
||||
updatemeta["x-amz-meta-ctime"] = str(time(NULL));
|
||||
updatemeta["x-amz-meta-ctime"] = s3fs_str_realtime();
|
||||
updatemeta["x-amz-meta-uid"] = str(uid);
|
||||
updatemeta["x-amz-meta-gid"] = str(gid);
|
||||
updatemeta["x-amz-copy-source"] = urlEncode(service_path + S3fsCred::GetBucket() + get_realpath(strpath.c_str()));
|
||||
@ -1882,7 +1923,14 @@ static int s3fs_chown_nocopy(const char* _path, uid_t uid, gid_t gid)
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
|
||||
// Make new directory object("dir/")
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, stbuf.st_atime, stbuf.st_mtime, time(NULL), uid, gid))){
|
||||
struct timespec ts_atime;
|
||||
struct timespec ts_mtime;
|
||||
struct timespec ts_ctime;
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_ATIME, ts_atime);
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_MTIME, ts_mtime);
|
||||
s3fs_realtime(ts_ctime);
|
||||
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, ts_atime, ts_mtime, ts_ctime, uid, gid))){
|
||||
return result;
|
||||
}
|
||||
}else{
|
||||
@ -1896,7 +1944,8 @@ static int s3fs_chown_nocopy(const char* _path, uid_t uid, gid_t gid)
|
||||
return result;
|
||||
}
|
||||
|
||||
struct timespec ts = {time(NULL), 0};
|
||||
struct timespec ts;
|
||||
s3fs_realtime(ts);
|
||||
ent->SetCtime(ts);
|
||||
|
||||
// Change owner
|
||||
@ -1937,7 +1986,7 @@ static int s3fs_utimens(const char* _path, const struct timespec ts[2])
|
||||
struct stat stbuf;
|
||||
dirtype nDirType = DIRTYPE_UNKNOWN;
|
||||
|
||||
S3FS_PRN_INFO("[path=%s][mtime=%lld][ctime/atime=%lld]", path, static_cast<long long>(ts[1].tv_sec), static_cast<long long>(ts[0].tv_sec));
|
||||
S3FS_PRN_INFO("[path=%s][mtime=%s][ctime/atime=%s]", path, str(ts[1]).c_str(), str(ts[0]).c_str());
|
||||
|
||||
if(0 == strcmp(path, "/")){
|
||||
S3FS_PRN_ERR("Could not change mtime for mount point.");
|
||||
@ -1953,16 +2002,18 @@ static int s3fs_utimens(const char* _path, const struct timespec ts[2])
|
||||
}
|
||||
|
||||
struct timespec now;
|
||||
if(-1 == clock_gettime(static_cast<clockid_t>(CLOCK_REALTIME), &now)){
|
||||
abort();
|
||||
}
|
||||
#if __APPLE__
|
||||
struct timespec actime = handle_utimens_special_values(ts[0], now, stbuf.st_ctimespec);
|
||||
struct timespec mtime = handle_utimens_special_values(ts[1], now, stbuf.st_mtimespec);
|
||||
#else
|
||||
struct timespec actime = handle_utimens_special_values(ts[0], now, stbuf.st_ctim);
|
||||
struct timespec mtime = handle_utimens_special_values(ts[1], now, stbuf.st_mtim);
|
||||
#endif
|
||||
struct timespec ts_atime;
|
||||
struct timespec ts_ctime;
|
||||
struct timespec ts_mtime;
|
||||
|
||||
s3fs_realtime(now);
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_ATIME, ts_atime);
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_CTIME, ts_ctime);
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_MTIME, ts_mtime);
|
||||
|
||||
struct timespec atime = handle_utimens_special_values(ts[0], now, ts_atime);
|
||||
struct timespec ctime = handle_utimens_special_values(ts[0], now, ts_ctime);
|
||||
struct timespec mtime = handle_utimens_special_values(ts[1], now, ts_mtime);
|
||||
|
||||
if(S_ISDIR(stbuf.st_mode)){
|
||||
result = chk_dir_object_type(path, newpath, strpath, nowcache, &meta, &nDirType);
|
||||
@ -1986,14 +2037,14 @@ static int s3fs_utimens(const char* _path, const struct timespec ts[2])
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
|
||||
// Make new directory object("dir/")
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, actime.tv_sec, mtime.tv_sec, actime.tv_sec, stbuf.st_uid, stbuf.st_gid))){
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, atime, mtime, ctime, stbuf.st_uid, stbuf.st_gid))){
|
||||
return result;
|
||||
}
|
||||
}else{
|
||||
headers_t updatemeta;
|
||||
updatemeta["x-amz-meta-mtime"] = str(mtime);
|
||||
updatemeta["x-amz-meta-ctime"] = str(actime);
|
||||
updatemeta["x-amz-meta-atime"] = str(actime);
|
||||
updatemeta["x-amz-meta-ctime"] = str(ctime);
|
||||
updatemeta["x-amz-meta-atime"] = str(atime);
|
||||
updatemeta["x-amz-copy-source"] = urlEncode(service_path + S3fsCred::GetBucket() + get_realpath(strpath.c_str()));
|
||||
updatemeta["x-amz-metadata-directive"] = "REPLACE";
|
||||
|
||||
@ -2059,7 +2110,7 @@ static int s3fs_utimens_nocopy(const char* _path, const struct timespec ts[2])
|
||||
struct stat stbuf;
|
||||
dirtype nDirType = DIRTYPE_UNKNOWN;
|
||||
|
||||
S3FS_PRN_INFO1("[path=%s][mtime=%lld][atime/ctime=%lld]", path, static_cast<long long>(ts[1].tv_sec), static_cast<long long>(ts[0].tv_sec));
|
||||
S3FS_PRN_INFO1("[path=%s][mtime=%s][atime/ctime=%s]", path, str(ts[1]).c_str(), str(ts[0]).c_str());
|
||||
|
||||
if(0 == strcmp(path, "/")){
|
||||
S3FS_PRN_ERR("Could not change mtime for mount point.");
|
||||
@ -2075,16 +2126,18 @@ static int s3fs_utimens_nocopy(const char* _path, const struct timespec ts[2])
|
||||
}
|
||||
|
||||
struct timespec now;
|
||||
if(-1 == clock_gettime(static_cast<clockid_t>(CLOCK_REALTIME), &now)){
|
||||
abort();
|
||||
}
|
||||
#if __APPLE__
|
||||
struct timespec actime = handle_utimens_special_values(ts[0], now, stbuf.st_ctimespec);
|
||||
struct timespec mtime = handle_utimens_special_values(ts[1], now, stbuf.st_mtimespec);
|
||||
#else
|
||||
struct timespec actime = handle_utimens_special_values(ts[0], now, stbuf.st_ctim);
|
||||
struct timespec mtime = handle_utimens_special_values(ts[1], now, stbuf.st_mtim);
|
||||
#endif
|
||||
struct timespec ts_atime;
|
||||
struct timespec ts_ctime;
|
||||
struct timespec ts_mtime;
|
||||
|
||||
s3fs_realtime(now);
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_ATIME, ts_atime);
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_CTIME, ts_ctime);
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_MTIME, ts_mtime);
|
||||
|
||||
struct timespec atime = handle_utimens_special_values(ts[0], now, ts_atime);
|
||||
struct timespec ctime = handle_utimens_special_values(ts[0], now, ts_ctime);
|
||||
struct timespec mtime = handle_utimens_special_values(ts[1], now, ts_mtime);
|
||||
|
||||
// Get attributes
|
||||
if(S_ISDIR(stbuf.st_mode)){
|
||||
@ -2109,7 +2162,7 @@ static int s3fs_utimens_nocopy(const char* _path, const struct timespec ts[2])
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
|
||||
// Make new directory object("dir/")
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, actime.tv_sec, mtime.tv_sec, actime.tv_sec, stbuf.st_uid, stbuf.st_gid))){
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, atime, mtime, ctime, stbuf.st_uid, stbuf.st_gid))){
|
||||
return result;
|
||||
}
|
||||
}else{
|
||||
@ -2124,13 +2177,13 @@ static int s3fs_utimens_nocopy(const char* _path, const struct timespec ts[2])
|
||||
}
|
||||
|
||||
// set mtime/ctime
|
||||
if(0 != (result = ent->SetMCtime(mtime, actime))){
|
||||
if(0 != (result = ent->SetMCtime(mtime, ctime))){
|
||||
S3FS_PRN_ERR("could not set mtime and ctime to file(%s): result=%d", strpath.c_str(), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// set atime
|
||||
if(0 != (result = ent->SetAtime(actime))){
|
||||
if(0 != (result = ent->SetAtime(atime))){
|
||||
S3FS_PRN_ERR("could not set atime to file(%s): result=%d", strpath.c_str(), result);
|
||||
return result;
|
||||
}
|
||||
@ -2198,7 +2251,7 @@ static int s3fs_truncate(const char* _path, off_t size)
|
||||
ignore_modify = true;
|
||||
}
|
||||
|
||||
if(NULL == (ent = autoent.Open(path, &meta, size, -1, O_RDWR, false, true, ignore_modify, AutoLock::NONE))){
|
||||
if(NULL == (ent = autoent.Open(path, &meta, size, S3FS_OMIT_TS, O_RDWR, false, true, ignore_modify, AutoLock::NONE))){
|
||||
S3FS_PRN_ERR("could not open file(%s): errno=%d", path, errno);
|
||||
return -EIO;
|
||||
}
|
||||
@ -2224,15 +2277,16 @@ static int s3fs_truncate(const char* _path, off_t size)
|
||||
if(NULL == (pcxt = fuse_get_context())){
|
||||
return -EIO;
|
||||
}
|
||||
time_t now = time(NULL);
|
||||
|
||||
std::string strnow = s3fs_str_realtime();
|
||||
meta["Content-Type"] = std::string("application/octet-stream"); // Static
|
||||
meta["x-amz-meta-mode"] = str(S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
meta["x-amz-meta-ctime"] = str(now);
|
||||
meta["x-amz-meta-mtime"] = str(now);
|
||||
meta["x-amz-meta-ctime"] = strnow;
|
||||
meta["x-amz-meta-mtime"] = strnow;
|
||||
meta["x-amz-meta-uid"] = str(pcxt->uid);
|
||||
meta["x-amz-meta-gid"] = str(pcxt->gid);
|
||||
|
||||
if(NULL == (ent = autoent.Open(path, &meta, size, -1, O_RDWR, true, true, false, AutoLock::NONE))){
|
||||
if(NULL == (ent = autoent.Open(path, &meta, size, S3FS_OMIT_TS, O_RDWR, true, true, false, AutoLock::NONE))){
|
||||
S3FS_PRN_ERR("could not open file(%s): errno=%d", path, errno);
|
||||
return -EIO;
|
||||
}
|
||||
@ -2302,15 +2356,20 @@ static int s3fs_open(const char* _path, struct fuse_file_info* fi)
|
||||
if(0 != (result = get_object_attribute(path, NULL, &meta, true, NULL, true))){ // no truncate cache
|
||||
return result;
|
||||
}
|
||||
if(NULL == (ent = autoent.Open(path, &meta, st.st_size, st.st_mtime, fi->flags, false, true, false, AutoLock::NONE))){
|
||||
|
||||
struct timespec st_mctime;
|
||||
set_stat_to_timespec(st, ST_TYPE_MTIME, st_mctime);
|
||||
|
||||
if(NULL == (ent = autoent.Open(path, &meta, st.st_size, st_mctime, fi->flags, false, true, false, AutoLock::NONE))){
|
||||
StatCache::getStatCacheData()->DelStat(path);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (needs_flush){
|
||||
time_t now = time(NULL);
|
||||
struct timespec ts = {now, 0};
|
||||
struct timespec ts;
|
||||
s3fs_realtime(ts);
|
||||
ent->SetMCtime(ts, ts);
|
||||
|
||||
if(0 != (result = ent->RowFlush(autoent.GetPseudoFd(), path, AutoLock::NONE, true))){
|
||||
S3FS_PRN_ERR("could not upload file(%s): result=%d", path, result);
|
||||
StatCache::getStatCacheData()->DelStat(path);
|
||||
@ -3070,8 +3129,15 @@ static int s3fs_setxattr(const char* path, const char* name, const char* value,
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
|
||||
// Make new directory object("dir/")
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, stbuf.st_atime, stbuf.st_mtime, stbuf.st_ctime, stbuf.st_uid, stbuf.st_gid))){
|
||||
return result;
|
||||
struct timespec ts_atime;
|
||||
struct timespec ts_mtime;
|
||||
struct timespec ts_ctime;
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_ATIME, ts_atime);
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_MTIME, ts_mtime);
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_CTIME, ts_ctime);
|
||||
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, ts_atime, ts_mtime, ts_ctime, stbuf.st_uid, stbuf.st_gid))){
|
||||
return result;
|
||||
}
|
||||
|
||||
// need to set xattr header for directory.
|
||||
@ -3081,7 +3147,7 @@ static int s3fs_setxattr(const char* path, const char* name, const char* value,
|
||||
|
||||
// set xattr all object
|
||||
headers_t updatemeta;
|
||||
updatemeta["x-amz-meta-ctime"] = str(time(NULL));
|
||||
updatemeta["x-amz-meta-ctime"] = s3fs_str_realtime();
|
||||
updatemeta["x-amz-copy-source"] = urlEncode(service_path + S3fsCred::GetBucket() + get_realpath(strpath.c_str()));
|
||||
updatemeta["x-amz-metadata-directive"] = "REPLACE";
|
||||
|
||||
@ -3351,7 +3417,14 @@ static int s3fs_removexattr(const char* path, const char* name)
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
|
||||
// Make new directory object("dir/")
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, stbuf.st_atime, stbuf.st_mtime, stbuf.st_ctime, stbuf.st_uid, stbuf.st_gid))){
|
||||
struct timespec ts_atime;
|
||||
struct timespec ts_mtime;
|
||||
struct timespec ts_ctime;
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_ATIME, ts_atime);
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_MTIME, ts_mtime);
|
||||
set_stat_to_timespec(stbuf, ST_TYPE_CTIME, ts_ctime);
|
||||
|
||||
if(0 != (result = create_directory_object(newpath.c_str(), stbuf.st_mode, ts_atime, ts_mtime, ts_ctime, stbuf.st_uid, stbuf.st_gid))){
|
||||
free_xattrs(xattrs);
|
||||
return result;
|
||||
}
|
||||
|
@ -447,6 +447,129 @@ void print_launch_message(int argc, char** argv)
|
||||
S3FS_PRN_LAUNCH_INFO("%s", message.c_str());
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Utility for nanosecond time(timespec)
|
||||
//-------------------------------------------------------------------
|
||||
const struct timespec S3FS_OMIT_TS = {0, UTIME_OMIT};
|
||||
|
||||
//
|
||||
// result: -1 ts1 < ts2
|
||||
// 0 ts1 == ts2
|
||||
// 1 ts1 > ts2
|
||||
//
|
||||
int compare_timespec(const struct timespec& ts1, const struct timespec& ts2)
|
||||
{
|
||||
if(ts1.tv_sec < ts2.tv_sec){
|
||||
return -1;
|
||||
}else if(ts1.tv_sec > ts2.tv_sec){
|
||||
return 1;
|
||||
}else{
|
||||
if(ts1.tv_nsec < ts2.tv_nsec){
|
||||
return -1;
|
||||
}else if(ts1.tv_nsec > ts2.tv_nsec){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// result: -1 st < ts
|
||||
// 0 st == ts
|
||||
// 1 st > ts
|
||||
//
|
||||
int compare_timespec(const struct stat& st, stat_time_type type, const struct timespec& ts)
|
||||
{
|
||||
struct timespec st_ts;
|
||||
set_stat_to_timespec(st, type, st_ts);
|
||||
|
||||
return compare_timespec(st_ts, ts);
|
||||
}
|
||||
|
||||
void set_timespec_to_stat(struct stat& st, stat_time_type type, const struct timespec& ts)
|
||||
{
|
||||
if(ST_TYPE_ATIME == type){
|
||||
#if defined(__APPLE__)
|
||||
st.st_atime = ts.tv_sec;
|
||||
st.st_atimespec.tv_nsec = ts.tv_nsec;
|
||||
#else
|
||||
st.st_atim.tv_sec = ts.tv_sec;
|
||||
st.st_atim.tv_nsec = ts.tv_nsec;
|
||||
#endif
|
||||
}else if(ST_TYPE_MTIME == type){
|
||||
#if defined(__APPLE__)
|
||||
st.st_mtime = ts.tv_sec;
|
||||
st.st_mtimespec.tv_nsec = ts.tv_nsec;
|
||||
#else
|
||||
st.st_mtim.tv_sec = ts.tv_sec;
|
||||
st.st_mtim.tv_nsec = ts.tv_nsec;
|
||||
#endif
|
||||
}else if(ST_TYPE_CTIME == type){
|
||||
#if defined(__APPLE__)
|
||||
st.st_ctime = ts.tv_sec;
|
||||
st.st_ctimespec.tv_nsec = ts.tv_nsec;
|
||||
#else
|
||||
st.st_ctim.tv_sec = ts.tv_sec;
|
||||
st.st_ctim.tv_nsec = ts.tv_nsec;
|
||||
#endif
|
||||
}else{
|
||||
S3FS_PRN_ERR("unknown type(%d), so skip to set value.", type);
|
||||
}
|
||||
}
|
||||
|
||||
struct timespec* set_stat_to_timespec(const struct stat& st, stat_time_type type, struct timespec& ts)
|
||||
{
|
||||
if(ST_TYPE_ATIME == type){
|
||||
#if defined(__APPLE__)
|
||||
ts.tv_sec = st.st_atime;
|
||||
ts.tv_nsec = st.st_atimespec.tv_nsec;
|
||||
#else
|
||||
ts = st.st_atim;
|
||||
#endif
|
||||
}else if(ST_TYPE_MTIME == type){
|
||||
#if defined(__APPLE__)
|
||||
ts.tv_sec = st.st_mtime;
|
||||
ts.tv_nsec = st.st_mtimespec.tv_nsec;
|
||||
#else
|
||||
ts = st.st_mtim;
|
||||
#endif
|
||||
}else if(ST_TYPE_CTIME == type){
|
||||
#if defined(__APPLE__)
|
||||
ts.tv_sec = st.st_ctime;
|
||||
ts.tv_nsec = st.st_ctimespec.tv_nsec;
|
||||
#else
|
||||
ts = st.st_ctim;
|
||||
#endif
|
||||
}else{
|
||||
S3FS_PRN_ERR("unknown type(%d), so use 0 as timespec.", type);
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 0;
|
||||
}
|
||||
return &ts;
|
||||
}
|
||||
|
||||
std::string str_stat_time(const struct stat& st, stat_time_type type)
|
||||
{
|
||||
struct timespec ts;
|
||||
return str(*set_stat_to_timespec(st, type, ts));
|
||||
}
|
||||
|
||||
struct timespec* s3fs_realtime(struct timespec& ts)
|
||||
{
|
||||
if(-1 == clock_gettime(static_cast<clockid_t>(CLOCK_REALTIME), &ts)){
|
||||
S3FS_PRN_WARN("failed to clock_gettime by errno(%d)", errno);
|
||||
ts.tv_sec = time(NULL);
|
||||
ts.tv_nsec = 0;
|
||||
}
|
||||
return &ts;
|
||||
}
|
||||
|
||||
std::string s3fs_str_realtime()
|
||||
{
|
||||
struct timespec ts;
|
||||
return str(*(s3fs_realtime(ts)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
|
@ -56,6 +56,24 @@ bool compare_sysname(const char* target);
|
||||
|
||||
void print_launch_message(int argc, char** argv);
|
||||
|
||||
//
|
||||
// Utility for nanosecond time(timespec)
|
||||
//
|
||||
enum stat_time_type{
|
||||
ST_TYPE_ATIME,
|
||||
ST_TYPE_MTIME,
|
||||
ST_TYPE_CTIME
|
||||
};
|
||||
extern const struct timespec S3FS_OMIT_TS;
|
||||
|
||||
int compare_timespec(const struct timespec& ts1, const struct timespec& ts2);
|
||||
int compare_timespec(const struct stat& st, stat_time_type type, const struct timespec& ts);
|
||||
void set_timespec_to_stat(struct stat& st, stat_time_type type, const struct timespec& ts);
|
||||
struct timespec* set_stat_to_timespec(const struct stat& st, stat_time_type type, struct timespec& ts);
|
||||
std::string str_stat_time(const struct stat& st, stat_time_type type);
|
||||
struct timespec* s3fs_realtime(struct timespec& ts);
|
||||
std::string s3fs_str_realtime();
|
||||
|
||||
#endif // S3FS_S3FS_UTIL_H_
|
||||
|
||||
/*
|
||||
|
@ -56,7 +56,8 @@ template std::string str(unsigned long value);
|
||||
template std::string str(long long value);
|
||||
template std::string str(unsigned long long value);
|
||||
|
||||
template<> std::string str(struct timespec value) {
|
||||
template<> std::string str(const struct timespec value)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << value.tv_sec;
|
||||
if(value.tv_nsec != 0){
|
||||
|
@ -824,16 +824,39 @@ function test_mtime_file {
|
||||
|
||||
# create the test file again
|
||||
mk_test_file
|
||||
sleep 1 # allow for some time to pass to compare the timestamps between test & alt
|
||||
|
||||
#copy the test file with preserve mode
|
||||
cp -p "${TEST_TEXT_FILE}" "${ALT_TEST_TEXT_FILE}"
|
||||
|
||||
local testmtime; testmtime=$(get_mtime "${TEST_TEXT_FILE}")
|
||||
local testctime; testctime=$(get_ctime "${TEST_TEXT_FILE}")
|
||||
local testatime; testatime=$(get_atime "${TEST_TEXT_FILE}")
|
||||
local altmtime; altmtime=$(get_mtime "${ALT_TEST_TEXT_FILE}")
|
||||
if [ "${testmtime}" != "${altmtime}" ]
|
||||
then
|
||||
echo "File times do not match: $testmtime != $altmtime"
|
||||
return 1
|
||||
local altctime; altctime=$(get_ctime "${ALT_TEST_TEXT_FILE}")
|
||||
local altatime; altatime=$(get_atime "${ALT_TEST_TEXT_FILE}")
|
||||
|
||||
if [ "${testmtime}" != "${altmtime}" ] || [ "${testctime}" = "${altctime}" ] || [ "${testatime}" != "${altatime}" ]; then
|
||||
# [NOTE]{FIXME]
|
||||
# On macos10, the mtime of the file copied by "cp -p" is
|
||||
# truncated to usec from nsec, and it cannot be solved.
|
||||
# This is because the timespec.tv_sec value of the mtime
|
||||
# of the original file is truncated in usec units at calling
|
||||
# s3fs_utimens.
|
||||
# (ex. "1658768609.505917125" vs "1658768609.505917000")
|
||||
# Now this workaround is not found, so for macos compare
|
||||
# mtime with only usec.
|
||||
#
|
||||
if ! uname | grep -q Darwin; then
|
||||
echo "cp(-p) expected times: mtime( ${testmtime} == ${altmtime} ), ctime( ${testctime} != ${altctime} ), atime( ${testatime} == ${altatime} )"
|
||||
return 1
|
||||
else
|
||||
testmtime=$(echo "${testmtime}" | cut -c 1-17)
|
||||
altmtime=$(echo "${altmtime}" | cut -c 1-17)
|
||||
if [ "${testmtime}" != "${altmtime}" ] || [ "${testctime}" = "${altctime}" ] || [ "${testatime}" != "${altatime}" ]; then
|
||||
echo "cp(-p) expected times: mtime( ${testmtime} == ${altmtime} ), ctime( ${testctime} != ${altctime} ), atime( ${testatime} == ${altatime} )"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
rm_test_file
|
||||
|
Loading…
Reference in New Issue
Block a user