static int s3fs_removexattr()

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;
}