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