in src/s3fs.cpp [1214:1297]
static int rename_object(const char* from, const char* to, bool update_ctime)
{
int result;
std::string s3_realpath;
headers_t meta;
struct stat buf;
S3FS_PRN_INFO1("[from=%s][to=%s]", from , to);
if(0 != (result = check_parent_object_access(to, W_OK | X_OK))){
// not permit writing "to" object parent dir.
return result;
}
if(0 != (result = check_parent_object_access(from, W_OK | X_OK))){
// not permit removing "from" object parent dir.
return result;
}
if(0 != (result = get_object_attribute(from, &buf, &meta, true, NULL, false, is_refresh_fakemeta))){
return result;
}
s3_realpath = get_realpath(from);
if(update_ctime){
meta["x-oss-meta-ctime"] = str(time(NULL));
}
meta["x-oss-copy-source"] = urlEncode(service_path + S3fsCred::GetBucket() + s3_realpath);
meta["Content-Type"] = S3fsCurl::LookupMimeType(std::string(to));
meta["x-oss-metadata-directive"] = "REPLACE";
// [NOTE]
// If it has a cache, open it first and leave it open until rename.
// The cache is renamed after put_header, because it must be open
// at the time of renaming.
{
// update time
AutoFdEntity autoent;
FdEntity* ent;
if(NULL == (ent = autoent.OpenExistFdEntity(from))){
// 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);
}
if(ent){
struct timespec mtime = get_mtime(meta);
struct timespec ctime = get_ctime(meta);
struct timespec atime = get_atime(meta);
if(mtime.tv_sec < 0){
mtime.tv_sec = 0L;
mtime.tv_nsec = 0L;
}
if(ctime.tv_sec < 0){
ctime.tv_sec = 0L;
ctime.tv_nsec = 0L;
}
if(atime.tv_sec < 0){
atime.tv_sec = 0L;
atime.tv_nsec = 0L;
}
ent->SetMCtime(mtime, ctime);
ent->SetAtime(atime);
}
}
if(ent) ent->CheckAndExitDirectReadIfNeeded();
// copy
if(0 != (result = put_headers(to, meta, true, /* use_st_size= */ false))){
return result;
}
// rename
FdManager::get()->Rename(from, to);
}
// Remove file
result = s3fs_unlink(from);
StatCache::getStatCacheData()->DelStat(to);
if (S_ISLNK(buf.st_mode)) {
StatCache::getStatCacheData()->DelSymlink(to);
}
return result;
}