mirror of
https://github.com/s3fs-fuse/s3fs-fuse.git
synced 2025-02-09 05:58:27 +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
|
// mtime
|
||||||
pst->st_mtime = get_mtime(meta);
|
pst->st_mtime = get_mtime(meta);
|
||||||
|
|
||||||
|
// ctime
|
||||||
|
pst->st_ctime = get_ctime(meta);
|
||||||
|
|
||||||
// size
|
// size
|
||||||
pst->st_size = get_size(meta);
|
pst->st_size = get_size(meta);
|
||||||
|
|
||||||
|
@ -1050,11 +1050,23 @@ int FdEntity::SetMtime(time_t time)
|
|||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
orgmeta["x-amz-meta-ctime"] = str(time);
|
||||||
orgmeta["x-amz-meta-mtime"] = str(time);
|
orgmeta["x-amz-meta-mtime"] = str(time);
|
||||||
|
|
||||||
return 0;
|
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)
|
bool FdEntity::UpdateMtime(void)
|
||||||
{
|
{
|
||||||
AutoLock auto_lock(&fdent_lock);
|
AutoLock auto_lock(&fdent_lock);
|
||||||
@ -1062,6 +1074,7 @@ bool FdEntity::UpdateMtime(void)
|
|||||||
if(!GetStats(st)){
|
if(!GetStats(st)){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
orgmeta["x-amz-meta-ctime"] = str(st.st_ctime);
|
||||||
orgmeta["x-amz-meta-mtime"] = str(st.st_mtime);
|
orgmeta["x-amz-meta-mtime"] = str(st.st_mtime);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -155,6 +155,7 @@ class FdEntity
|
|||||||
|
|
||||||
bool GetStats(struct stat& st);
|
bool GetStats(struct stat& st);
|
||||||
int SetMtime(time_t time);
|
int SetMtime(time_t time);
|
||||||
|
bool UpdateCtime(void);
|
||||||
bool UpdateMtime(void);
|
bool UpdateMtime(void);
|
||||||
bool GetSize(size_t& size);
|
bool GetSize(size_t& size);
|
||||||
bool SetMode(mode_t mode);
|
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);
|
S3FS_PRN_INFO2("[path=%s][mode=%04o]", path, mode);
|
||||||
|
|
||||||
|
time_t now = time(NULL);
|
||||||
headers_t meta;
|
headers_t meta;
|
||||||
meta["Content-Type"] = S3fsCurl::LookupMimeType(string(path));
|
meta["Content-Type"] = S3fsCurl::LookupMimeType(string(path));
|
||||||
meta["x-amz-meta-uid"] = str(uid);
|
meta["x-amz-meta-uid"] = str(uid);
|
||||||
meta["x-amz-meta-gid"] = str(gid);
|
meta["x-amz-meta-gid"] = str(gid);
|
||||||
meta["x-amz-meta-mode"] = str(mode);
|
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);
|
S3fsCurl s3fscurl(true);
|
||||||
return s3fscurl.PutRequest(path, meta, -1); // fd=-1 means for creating zero byte object.
|
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-uid"] = str(uid);
|
||||||
meta["x-amz-meta-gid"] = str(gid);
|
meta["x-amz-meta-gid"] = str(gid);
|
||||||
meta["x-amz-meta-mode"] = str(mode);
|
meta["x-amz-meta-mode"] = str(mode);
|
||||||
|
meta["x-amz-meta-ctime"] = str(time);
|
||||||
meta["x-amz-meta-mtime"] = str(time);
|
meta["x-amz-meta-mtime"] = str(time);
|
||||||
|
|
||||||
S3fsCurl s3fscurl;
|
S3fsCurl s3fscurl;
|
||||||
@ -1199,10 +1202,12 @@ static int s3fs_symlink(const char* from, const char* to)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time_t now = time(NULL);
|
||||||
headers_t headers;
|
headers_t headers;
|
||||||
headers["Content-Type"] = string("application/octet-stream"); // Static
|
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-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-uid"] = str(pcxt->uid);
|
||||||
headers["x-amz-meta-gid"] = str(pcxt->gid);
|
headers["x-amz-meta-gid"] = str(pcxt->gid);
|
||||||
|
|
||||||
@ -1591,6 +1596,7 @@ static int s3fs_chmod(const char* path, mode_t mode)
|
|||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
// normal object or directory object of newer version
|
// 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-meta-mode"] = str(mode);
|
||||||
meta["x-amz-copy-source"] = urlEncode(service_path + bucket + get_realpath(strpath.c_str()));
|
meta["x-amz-copy-source"] = urlEncode(service_path + bucket + get_realpath(strpath.c_str()));
|
||||||
meta["x-amz-metadata-directive"] = "REPLACE";
|
meta["x-amz-metadata-directive"] = "REPLACE";
|
||||||
@ -1607,6 +1613,7 @@ static int s3fs_chmod(const char* path, mode_t mode)
|
|||||||
//
|
//
|
||||||
FdEntity* ent;
|
FdEntity* ent;
|
||||||
if(NULL != (ent = FdManager::get()->ExistOpen(path))){
|
if(NULL != (ent = FdManager::get()->ExistOpen(path))){
|
||||||
|
ent->UpdateCtime();
|
||||||
ent->SetMode(mode); // Set new mode to opened fd.
|
ent->SetMode(mode); // Set new mode to opened fd.
|
||||||
FdManager::get()->Close(ent);
|
FdManager::get()->Close(ent);
|
||||||
}
|
}
|
||||||
@ -1747,6 +1754,7 @@ static int s3fs_chown(const char* path, uid_t uid, gid_t gid)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
|
meta["x-amz-meta-ctime"] = str(time(NULL));
|
||||||
meta["x-amz-meta-uid"] = str(uid);
|
meta["x-amz-meta-uid"] = str(uid);
|
||||||
meta["x-amz-meta-gid"] = str(gid);
|
meta["x-amz-meta-gid"] = str(gid);
|
||||||
meta["x-amz-copy-source"] = urlEncode(service_path + bucket + get_realpath(strpath.c_str()));
|
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())){
|
if(NULL == (pcxt = fuse_get_context())){
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
time_t now = time(NULL);
|
||||||
meta["Content-Type"] = string("application/octet-stream"); // Static
|
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-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-uid"] = str(pcxt->uid);
|
||||||
meta["x-amz-meta-gid"] = str(pcxt->gid);
|
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
|
// 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-copy-source"] = urlEncode(service_path + bucket + get_realpath(strpath.c_str()));
|
||||||
meta["x-amz-metadata-directive"] = "REPLACE";
|
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));
|
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;
|
headers_t::const_iterator iter;
|
||||||
if(meta.end() == (iter = meta.find("x-amz-meta-mtime"))){
|
if(meta.end() == (iter = meta.find(header))){
|
||||||
if(overcheck){
|
if(overcheck){
|
||||||
return get_lastmodified(meta);
|
return get_lastmodified(meta);
|
||||||
}
|
}
|
||||||
@ -765,6 +765,16 @@ time_t get_mtime(headers_t& meta, bool overcheck)
|
|||||||
return get_mtime((*iter).second.c_str());
|
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)
|
off_t get_size(const char *s)
|
||||||
{
|
{
|
||||||
return s3fs_strtoofft(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(const char *s);
|
||||||
time_t get_mtime(headers_t& meta, bool overcheck = true);
|
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(const char *s);
|
||||||
off_t get_size(headers_t& meta);
|
off_t get_size(headers_t& meta);
|
||||||
mode_t get_mode(const char *s);
|
mode_t get_mode(const char *s);
|
||||||
|
@ -400,13 +400,8 @@ function test_mtime_file {
|
|||||||
|
|
||||||
#copy the test file with preserve mode
|
#copy the test file with preserve mode
|
||||||
cp -p $TEST_TEXT_FILE $ALT_TEST_TEXT_FILE
|
cp -p $TEST_TEXT_FILE $ALT_TEST_TEXT_FILE
|
||||||
if [ `uname` = "Darwin" ]; then
|
testmtime=`get_mtime $TEST_TEXT_FILE`
|
||||||
testmtime=`stat -f "%m" $TEST_TEXT_FILE`
|
altmtime=`get_mtime $ALT_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
|
|
||||||
if [ "$testmtime" -ne "$altmtime" ]
|
if [ "$testmtime" -ne "$altmtime" ]
|
||||||
then
|
then
|
||||||
echo "File times do not match: $testmtime != $altmtime"
|
echo "File times do not match: $testmtime != $altmtime"
|
||||||
@ -414,6 +409,61 @@ function test_mtime_file {
|
|||||||
fi
|
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 {
|
function test_rm_rf_dir {
|
||||||
describe "Test that rm -rf will remove directory with contents"
|
describe "Test that rm -rf will remove directory with contents"
|
||||||
# Create a dir with some files and directories
|
# Create a dir with some files and directories
|
||||||
@ -458,6 +508,7 @@ function add_all_tests {
|
|||||||
add_tests test_symlink
|
add_tests test_symlink
|
||||||
add_tests test_extended_attributes
|
add_tests test_extended_attributes
|
||||||
add_tests test_mtime_file
|
add_tests test_mtime_file
|
||||||
|
add_tests test_update_time
|
||||||
add_tests test_rm_rf_dir
|
add_tests test_rm_rf_dir
|
||||||
add_tests test_write_after_seek_ahead
|
add_tests test_write_after_seek_ahead
|
||||||
}
|
}
|
||||||
|
@ -169,3 +169,19 @@ function run_suite {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
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