in src/s3fs.cpp [3438:3567]
static int s3fs_removexattr(const char* path, const char* name)
{
S3FS_PRN_INFO("[path=%s][name=%s]", path, name);
if(!path || !name){
return -EIO;
}
int result;
std::string strpath;
std::string newpath;
std::string nowcache;
headers_t meta;
xattrs_t xattrs;
struct stat stbuf;
dirtype nDirType = DIRTYPE_UNKNOWN;
if(0 == strcmp(path, "/")){
S3FS_PRN_ERR("Could not change mode for mount point.");
return -EIO;
}
if(0 != (result = check_parent_object_access(path, X_OK))){
return result;
}
if(0 != (result = check_object_owner(path, &stbuf))){
return result;
}
if(S_ISDIR(stbuf.st_mode)){
result = chk_dir_object_type(path, newpath, strpath, nowcache, &meta, &nDirType);
}else{
strpath = path;
nowcache = strpath;
result = get_object_attribute(strpath.c_str(), NULL, &meta);
}
if(0 != result){
return result;
}
// get xattrs
headers_t::iterator hiter = meta.find("x-oss-meta-xattr");
if(meta.end() == hiter){
// object does not have xattrs
return -ENOATTR;
}
std::string strxattrs = hiter->second;
parse_xattrs(strxattrs, xattrs);
// check name xattrs
std::string strname = name;
xattrs_t::iterator xiter = xattrs.find(strname);
if(xattrs.end() == xiter){
free_xattrs(xattrs);
return -ENOATTR;
}
// make new header_t after deleting name xattr
delete xiter->second;
xattrs.erase(xiter);
if(S_ISDIR(stbuf.st_mode) && IS_REPLACEDIR(nDirType)){
// Should rebuild directory object(except new type)
// Need to remove old dir("dir" etc) and make new dir("dir/")
// At first, remove directory old object
if(0 != (result = remove_old_type_dir(strpath, nDirType))){
return result;
}
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))){
free_xattrs(xattrs);
return result;
}
// need to set xattr header for directory.
strpath = newpath;
nowcache = strpath;
}
// set xattr all object
headers_t updatemeta;
updatemeta["x-oss-copy-source"] = urlEncode(service_path + S3fsCred::GetBucket() + get_realpath(strpath.c_str()));
updatemeta["x-oss-metadata-directive"] = "REPLACE";
if(!xattrs.empty()){
updatemeta["x-oss-meta-xattr"] = build_xattrs(xattrs);
}else{
updatemeta["x-oss-meta-xattr"] = std::string(""); // This is a special case. If empty, this header will eventually be removed.
}
free_xattrs(xattrs);
// check opened file handle.
//
// If the file starts uploading by multipart when the disk capacity is insufficient,
// we need to put these header after finishing upload.
// Or if the file is only open, we must update to FdEntity's internal meta.
//
AutoFdEntity autoent;
FdEntity* ent;
bool need_put_header = true;
if(NULL != (ent = autoent.OpenExistFdEntity(path))){
if(ent->MergeOrgMeta(updatemeta)){
// meta is changed, but now uploading.
// then the meta is pending and accumulated to be put after the upload is complete.
S3FS_PRN_INFO("meta pending until upload is complete");
need_put_header = false;
// If there is data in the Stats cache, update the Stats cache.
StatCache::getStatCacheData()->UpdateMetaStats(strpath, updatemeta);
}
}
if(need_put_header){
// not found opened file.
if(updatemeta["x-oss-meta-xattr"].empty()){
updatemeta.erase("x-oss-meta-xattr");
}
merge_headers(meta, updatemeta, true);
// upload meta directly.
if(0 != (result = put_headers(strpath.c_str(), meta, true))){
return result;
}
StatCache::getStatCacheData()->DelStat(nowcache);
}
return 0;
}