static int s3fs_symlink()

in src/s3fs.cpp [1132:1212]


static int s3fs_symlink(const char* _from, const char* _to)
{
    WTF8_ENCODE(from)
    WTF8_ENCODE(to)
    int result;
    struct fuse_context* pcxt;

    S3FS_PRN_INFO("[from=%s][to=%s]", from, to);

    if(NULL == (pcxt = fuse_get_context())){
        return -EIO;
    }
    if(0 != (result = check_parent_object_access(to, W_OK | X_OK))){
        return result;
    }
    if(-ENOENT != (result = check_object_access(to, F_OK, NULL))){
        if(0 == result){
            result = -EEXIST;
        }
        return result;
    }

    time_t now = time(NULL);
    headers_t headers;
    headers["Content-Type"]     = std::string("application/octet-stream"); // Static
    headers["x-oss-meta-mode"]  = str(S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
    headers["x-oss-meta-atime"] = str(now);
    headers["x-oss-meta-ctime"] = str(now);
    headers["x-oss-meta-mtime"] = str(now);
    headers["x-oss-meta-uid"]   = str(pcxt->uid);
    headers["x-oss-meta-gid"]   = str(pcxt->gid);

    // open tmpfile
    std::string strFrom;
    {   // scope for AutoFdEntity
        AutoFdEntity autoent;
        FdEntity*    ent;
        if(NULL == (ent = autoent.Open(to, &headers, 0, -1, O_RDWR, true, true, false, AutoLock::NONE))){
            S3FS_PRN_ERR("could not open tmpfile(errno=%d)", errno);
            return -errno;
        }
        // write(without space words)
        strFrom           = trim(std::string(from));
        ssize_t from_size = static_cast<ssize_t>(strFrom.length());
        ssize_t ressize;
        // new symlink format
        if (is_new_symlink_format) {
            // If the target's path is less 2K, save it into header in new symlink format
            if (from_size < 2*1024) {
                ent->SetSymlinkAttr("header", strFrom);
                from_size = 0;
            } else {
                ent->SetSymlinkAttr("body", "");
            }
        } else {
            // allways remove
            ent->SetSymlinkAttr("", "");
        }
        if(from_size != (ressize = ent->Write(autoent.GetPseudoFd(), strFrom.c_str(), 0, from_size))){
            if(ressize < 0){
                S3FS_PRN_ERR("could not write tmpfile(errno=%d)", static_cast<int>(ressize));
                return static_cast<int>(ressize);
            }else{
                S3FS_PRN_ERR("could not write tmpfile %zd byte(errno=%d)", ressize, errno);
                return (0 == errno ? -EIO : -errno);
            }
        }
        // upload
        if(0 != (result = ent->Flush(autoent.GetPseudoFd(), true))){
            S3FS_PRN_WARN("could not upload tmpfile(result=%d)", result);
        }
    }

    StatCache::getStatCacheData()->DelStat(to);
    if(!StatCache::getStatCacheData()->AddSymlink(std::string(to), strFrom)){
        S3FS_PRN_ERR("failed to add symbolic link cache for %s", to);
    }
    S3FS_MALLOCTRIM(0);

    return result;
}