in src/s3fs.cpp [801:881]
static int s3fs_readlink(const char* _path, char* buf, size_t size)
{
if(!_path || !buf || 0 == size){
return 0;
}
WTF8_ENCODE(path)
std::string strValue;
S3FS_PRN_INFO("[path=%s]", path);
// check symbolic link cache
if(!StatCache::getStatCacheData()->GetSymlink(std::string(path), strValue)){
// not found in cache, then open the path
{ // scope for AutoFdEntity
AutoFdEntity autoent;
FdEntity* ent;
int result;
if(0 != (result = get_local_fent(autoent, &ent, path, O_RDONLY))){
S3FS_PRN_ERR("could not get fent(file=%s)", path);
return result;
}
// Get symlink attr
std::string strType;
std::string strTarget;
if (!ent->GetSymlinkAttr(strType, strTarget)) {
// Do nothing
}
off_t readsize;
if (strType == "header") {
if(strTarget.empty()){
S3FS_PRN_ERR("could not get symlink target");
return -EIO;
}
readsize = strTarget.length();
if(static_cast<off_t>(size) <= readsize){
readsize = size - 1;
}
memcpy(buf, strTarget.c_str(), readsize);
buf[readsize] = '\0';
} else {
// Get size
if(!ent->GetSize(readsize)){
S3FS_PRN_ERR("could not get file size(file=%s)", path);
return -EIO;
}
if(static_cast<off_t>(size) <= readsize){
readsize = size - 1;
}
// Read
ssize_t ressize;
if(0 > (ressize = ent->Read(autoent.GetPseudoFd(), buf, 0, readsize))){
S3FS_PRN_ERR("could not read file(file=%s, ressize=%zd)", path, ressize);
return static_cast<int>(ressize);
}
buf[ressize] = '\0';
}
}
// check buf if it has space words.
strValue = trim(std::string(buf));
// decode wtf8. This will always be shorter
if(use_wtf8){
strValue = s3fs_wtf8_decode(strValue);
}
// add symbolic link cache
if(!StatCache::getStatCacheData()->AddSymlink(std::string(path), strValue)){
S3FS_PRN_ERR("failed to add symbolic link cache for %s", path);
}
}
// copy result
strncpy(buf, strValue.c_str(), size - 1);
buf[size - 1] = '\0';
S3FS_MALLOCTRIM(0);
return 0;
}