mirror of
https://github.com/s3fs-fuse/s3fs-fuse.git
synced 2025-02-02 10:38:25 +00:00
Store and retrieve file change time
This introduces a new header with the change time; existing objects will report modification time. Fixes #771.
This commit is contained in:
parent
b68d97c6bf
commit
2c43b1e12b
@ -620,6 +620,9 @@ bool convert_header_to_stat(const char* path, headers_t& meta, struct stat* pst,
|
||||
// mtime
|
||||
pst->st_mtime = get_mtime(meta);
|
||||
|
||||
// ctime
|
||||
pst->st_ctime = get_ctime(meta);
|
||||
|
||||
// size
|
||||
pst->st_size = get_size(meta);
|
||||
|
||||
|
@ -1050,11 +1050,23 @@ int FdEntity::SetMtime(time_t time)
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
orgmeta["x-amz-meta-ctime"] = str(time);
|
||||
orgmeta["x-amz-meta-mtime"] = str(time);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool FdEntity::UpdateCtime(void)
|
||||
{
|
||||
AutoLock auto_lock(&fdent_lock);
|
||||
struct stat st;
|
||||
if(!GetStats(st)){
|
||||
return false;
|
||||
}
|
||||
orgmeta["x-amz-meta-ctime"] = str(st.st_ctime);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FdEntity::UpdateMtime(void)
|
||||
{
|
||||
AutoLock auto_lock(&fdent_lock);
|
||||
@ -1062,6 +1074,7 @@ bool FdEntity::UpdateMtime(void)
|
||||
if(!GetStats(st)){
|
||||
return false;
|
||||
}
|
||||
orgmeta["x-amz-meta-ctime"] = str(st.st_ctime);
|
||||
orgmeta["x-amz-meta-mtime"] = str(st.st_mtime);
|
||||
return true;
|
||||
}
|
||||
|
@ -155,6 +155,7 @@ class FdEntity
|
||||
|
||||
bool GetStats(struct stat& st);
|
||||
int SetMtime(time_t time);
|
||||
bool UpdateCtime(void);
|
||||
bool UpdateMtime(void);
|
||||
bool GetSize(size_t& size);
|
||||
bool SetMode(mode_t mode);
|
||||
|
17
src/s3fs.cpp
17
src/s3fs.cpp
@ -963,12 +963,14 @@ 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;
|
||||
meta["Content-Type"] = S3fsCurl::LookupMimeType(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-mtime"] = str(time(NULL));
|
||||
meta["x-amz-meta-ctime"] = str(now);
|
||||
meta["x-amz-meta-mtime"] = str(now);
|
||||
|
||||
S3fsCurl s3fscurl(true);
|
||||
return s3fscurl.PutRequest(path, meta, -1); // fd=-1 means for creating zero byte object.
|
||||
@ -1055,6 +1057,7 @@ static int create_directory_object(const char* path, mode_t mode, time_t time, u
|
||||
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-ctime"] = str(time);
|
||||
meta["x-amz-meta-mtime"] = str(time);
|
||||
|
||||
S3fsCurl s3fscurl;
|
||||
@ -1199,10 +1202,12 @@ static int s3fs_symlink(const char* from, const char* to)
|
||||
return result;
|
||||
}
|
||||
|
||||
time_t now = time(NULL);
|
||||
headers_t headers;
|
||||
headers["Content-Type"] = string("application/octet-stream"); // Static
|
||||
headers["x-amz-meta-mode"] = str(S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
headers["x-amz-meta-mtime"] = str(time(NULL));
|
||||
headers["x-amz-meta-ctime"] = str(now);
|
||||
headers["x-amz-meta-mtime"] = str(now);
|
||||
headers["x-amz-meta-uid"] = str(pcxt->uid);
|
||||
headers["x-amz-meta-gid"] = str(pcxt->gid);
|
||||
|
||||
@ -1591,6 +1596,7 @@ static int s3fs_chmod(const char* path, mode_t mode)
|
||||
}
|
||||
}else{
|
||||
// normal object or directory object of newer version
|
||||
meta["x-amz-meta-ctime"] = str(time(NULL));
|
||||
meta["x-amz-meta-mode"] = str(mode);
|
||||
meta["x-amz-copy-source"] = urlEncode(service_path + bucket + get_realpath(strpath.c_str()));
|
||||
meta["x-amz-metadata-directive"] = "REPLACE";
|
||||
@ -1607,6 +1613,7 @@ static int s3fs_chmod(const char* path, mode_t mode)
|
||||
//
|
||||
FdEntity* ent;
|
||||
if(NULL != (ent = FdManager::get()->ExistOpen(path))){
|
||||
ent->UpdateCtime();
|
||||
ent->SetMode(mode); // Set new mode to opened fd.
|
||||
FdManager::get()->Close(ent);
|
||||
}
|
||||
@ -1747,6 +1754,7 @@ static int s3fs_chown(const char* path, uid_t uid, gid_t gid)
|
||||
return result;
|
||||
}
|
||||
}else{
|
||||
meta["x-amz-meta-ctime"] = str(time(NULL));
|
||||
meta["x-amz-meta-uid"] = str(uid);
|
||||
meta["x-amz-meta-gid"] = str(gid);
|
||||
meta["x-amz-copy-source"] = urlEncode(service_path + bucket + get_realpath(strpath.c_str()));
|
||||
@ -2032,9 +2040,11 @@ static int s3fs_truncate(const char* path, off_t size)
|
||||
if(NULL == (pcxt = fuse_get_context())){
|
||||
return -EIO;
|
||||
}
|
||||
time_t now = time(NULL);
|
||||
meta["Content-Type"] = string("application/octet-stream"); // Static
|
||||
meta["x-amz-meta-mode"] = str(S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
meta["x-amz-meta-mtime"] = str(time(NULL));
|
||||
meta["x-amz-meta-ctime"] = str(now);
|
||||
meta["x-amz-meta-mtime"] = str(now);
|
||||
meta["x-amz-meta-uid"] = str(pcxt->uid);
|
||||
meta["x-amz-meta-gid"] = str(pcxt->gid);
|
||||
|
||||
@ -3103,6 +3113,7 @@ static int s3fs_setxattr(const char* path, const char* name, const char* value,
|
||||
}
|
||||
|
||||
// set xattr all object
|
||||
meta["x-amz-meta-ctime"] = str(time(NULL));
|
||||
meta["x-amz-copy-source"] = urlEncode(service_path + bucket + get_realpath(strpath.c_str()));
|
||||
meta["x-amz-metadata-directive"] = "REPLACE";
|
||||
|
||||
|
@ -753,10 +753,10 @@ time_t get_mtime(const char *s)
|
||||
return static_cast<time_t>(s3fs_strtoofft(s));
|
||||
}
|
||||
|
||||
time_t get_mtime(headers_t& meta, bool overcheck)
|
||||
static time_t get_time(headers_t& meta, bool overcheck, const char *header)
|
||||
{
|
||||
headers_t::const_iterator iter;
|
||||
if(meta.end() == (iter = meta.find("x-amz-meta-mtime"))){
|
||||
if(meta.end() == (iter = meta.find(header))){
|
||||
if(overcheck){
|
||||
return get_lastmodified(meta);
|
||||
}
|
||||
@ -765,6 +765,16 @@ time_t get_mtime(headers_t& meta, bool overcheck)
|
||||
return get_mtime((*iter).second.c_str());
|
||||
}
|
||||
|
||||
time_t get_mtime(headers_t& meta, bool overcheck)
|
||||
{
|
||||
return get_time(meta, overcheck, "x-amz-meta-mtime");
|
||||
}
|
||||
|
||||
time_t get_ctime(headers_t& meta, bool overcheck)
|
||||
{
|
||||
return get_time(meta, overcheck, "x-amz-meta-ctime");
|
||||
}
|
||||
|
||||
off_t get_size(const char *s)
|
||||
{
|
||||
return s3fs_strtoofft(s);
|
||||
|
@ -119,6 +119,7 @@ bool delete_files_in_dir(const char* dir, bool is_remove_own);
|
||||
|
||||
time_t get_mtime(const char *s);
|
||||
time_t get_mtime(headers_t& meta, bool overcheck = true);
|
||||
time_t get_ctime(headers_t& meta, bool overcheck = true);
|
||||
off_t get_size(const char *s);
|
||||
off_t get_size(headers_t& meta);
|
||||
mode_t get_mode(const char *s);
|
||||
|
@ -400,13 +400,8 @@ function test_mtime_file {
|
||||
|
||||
#copy the test file with preserve mode
|
||||
cp -p $TEST_TEXT_FILE $ALT_TEST_TEXT_FILE
|
||||
if [ `uname` = "Darwin" ]; then
|
||||
testmtime=`stat -f "%m" $TEST_TEXT_FILE`
|
||||
altmtime=`stat -f "%m" $ALT_TEST_TEXT_FILE`
|
||||
else
|
||||
testmtime=`stat -c %Y $TEST_TEXT_FILE`
|
||||
altmtime=`stat -c %Y $ALT_TEST_TEXT_FILE`
|
||||
fi
|
||||
testmtime=`get_mtime $TEST_TEXT_FILE`
|
||||
altmtime=`get_mtime $ALT_TEST_TEXT_FILE`
|
||||
if [ "$testmtime" -ne "$altmtime" ]
|
||||
then
|
||||
echo "File times do not match: $testmtime != $altmtime"
|
||||
@ -414,6 +409,61 @@ function test_mtime_file {
|
||||
fi
|
||||
}
|
||||
|
||||
function test_update_time() {
|
||||
describe "Testing update time function ..."
|
||||
|
||||
# create the test
|
||||
mk_test_file
|
||||
mtime=`get_ctime $TEST_TEXT_FILE`
|
||||
ctime=`get_mtime $TEST_TEXT_FILE`
|
||||
|
||||
sleep 2
|
||||
chmod +x $TEST_TEXT_FILE
|
||||
|
||||
ctime2=`get_ctime $TEST_TEXT_FILE`
|
||||
mtime2=`get_mtime $TEST_TEXT_FILE`
|
||||
if [ $ctime -eq $ctime2 -o $mtime -ne $mtime2 ]; then
|
||||
echo "Expected updated ctime: $ctime != $ctime2 and same mtime: $mtime == $mtime2"
|
||||
return 1
|
||||
fi
|
||||
|
||||
sleep 2
|
||||
chown $UID:$UID $TEST_TEXT_FILE;
|
||||
|
||||
ctime3=`get_ctime $TEST_TEXT_FILE`
|
||||
mtime3=`get_mtime $TEST_TEXT_FILE`
|
||||
if [ $ctime2 -eq $ctime3 -o $mtime2 -ne $mtime3 ]; then
|
||||
echo "Expected updated ctime: $ctime2 != $ctime3 and same mtime: $mtime2 == $mtime3"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if command -v setfattr >/dev/null 2>&1; then
|
||||
sleep 2
|
||||
setfattr -n key -v value $TEST_TEXT_FILE
|
||||
|
||||
ctime4=`get_ctime $TEST_TEXT_FILE`
|
||||
mtime4=`get_mtime $TEST_TEXT_FILE`
|
||||
if [ $ctime3 -eq $ctime4 -o $mtime3 -ne $mtime4 ]; then
|
||||
echo "Expected updated ctime: $ctime3 != $ctime4 and same mtime: $mtime3 == $mtime4"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
echo "Skipping extended attribute test"
|
||||
ctime4=`get_ctime $TEST_TEXT_FILE`
|
||||
mtime4=`get_mtime $TEST_TEXT_FILE`
|
||||
fi
|
||||
|
||||
sleep 2
|
||||
echo foo >> $TEST_TEXT_FILE
|
||||
|
||||
ctime5=`get_ctime $TEST_TEXT_FILE`
|
||||
mtime5=`get_mtime $TEST_TEXT_FILE`
|
||||
if [ $ctime4 -eq $ctime5 -o $mtime4 -eq $mtime5 ]; then
|
||||
echo "Expected updated ctime: $ctime4 != $ctime5 and updated mtime: $mtime4 != $mtime5"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
function test_rm_rf_dir {
|
||||
describe "Test that rm -rf will remove directory with contents"
|
||||
# Create a dir with some files and directories
|
||||
@ -458,6 +508,7 @@ function add_all_tests {
|
||||
add_tests test_symlink
|
||||
add_tests test_extended_attributes
|
||||
add_tests test_mtime_file
|
||||
add_tests test_update_time
|
||||
add_tests test_rm_rf_dir
|
||||
add_tests test_write_after_seek_ahead
|
||||
}
|
||||
|
@ -169,3 +169,19 @@ function run_suite {
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
function get_ctime() {
|
||||
if [ `uname` = "Darwin" ]; then
|
||||
stat -f "%c" "$1"
|
||||
else
|
||||
stat -c %Z "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
function get_mtime() {
|
||||
if [ `uname` = "Darwin" ]; then
|
||||
stat -f "%m" "$1"
|
||||
else
|
||||
stat -c %Y "$1"
|
||||
fi
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user