in src/s3fs.cpp [345:493]
static int get_object_attribute(const char* path, struct stat* pstbuf, headers_t* pmeta, bool overcheck, bool* pisforce, bool add_no_truncate_cache, bool refresh_fakemeta)
{
int result = -1;
struct stat tmpstbuf;
struct stat* pstat = pstbuf ? pstbuf : &tmpstbuf;
headers_t tmpHead;
headers_t* pheader = pmeta ? pmeta : &tmpHead;
std::string strpath;
S3fsCurl s3fscurl;
bool forcedir = false;
bool fakemeta = false;
std::string::size_type Pos;
S3FS_PRN_DBG("[path=%s]", path);
if(!path || '\0' == path[0]){
return -ENOENT;
}
memset(pstat, 0, sizeof(struct stat));
if(0 == strcmp(path, "/") || 0 == strcmp(path, ".")){
pstat->st_nlink = 1; // see fuse faq
pstat->st_mode = mp_mode;
pstat->st_uid = is_s3fs_uid ? s3fs_uid : mp_uid;
pstat->st_gid = is_s3fs_gid ? s3fs_gid : mp_gid;
return 0;
}
// Check cache.
pisforce = (NULL != pisforce ? pisforce : &forcedir);
(*pisforce) = false;
strpath = path;
if(support_compat_dir && overcheck && std::string::npos != (Pos = strpath.find("_$folder$", 0))){
strpath.erase(Pos);
strpath += "/";
}
if(StatCache::getStatCacheData()->GetStat(strpath, pstat, pheader, overcheck, pisforce, &fakemeta)){
if (refresh_fakemeta && fakemeta) {
// igrone the fake meta
} else {
return 0;
}
}
if(StatCache::getStatCacheData()->IsNoObjectCache(strpath)){
// there is the path in the cache for no object, it is no object.
return -ENOENT;
}
// At first, check path
strpath = path;
result = s3fscurl.HeadRequest(strpath.c_str(), (*pheader));
s3fscurl.DestroyCurlHandle();
// if not found target path object, do over checking
if(0 != result){
if(overcheck){
// when support_compat_dir is disabled, strpath maybe have "_$folder$".
if('/' != *strpath.rbegin() && std::string::npos == strpath.find("_$folder$", 0)){
// now path is "object", do check "object/" for over checking
strpath += "/";
result = s3fscurl.HeadRequest(strpath.c_str(), (*pheader));
s3fscurl.DestroyCurlHandle();
}
if(support_compat_dir && 0 != result){
// now path is "object/", do check "object_$folder$" for over checking
strpath.erase(strpath.length() - 1);
strpath += "_$folder$";
result = s3fscurl.HeadRequest(strpath.c_str(), (*pheader));
s3fscurl.DestroyCurlHandle();
if(0 != result){
// cut "_$folder$" for over checking "no dir object" after here
if(std::string::npos != (Pos = strpath.find("_$folder$", 0))){
strpath.erase(Pos);
}
}
}
}
if(support_compat_dir && 0 != result && std::string::npos == strpath.find("_$folder$", 0)){
// now path is "object" or "object/", do check "no dir object" which is not object but has only children.
if('/' == *strpath.rbegin()){
strpath.erase(strpath.length() - 1);
}
if(-ENOTEMPTY == directory_empty(strpath.c_str())){
// found "no dir object".
strpath += "/";
*pisforce = true;
result = 0;
}
}
}else{
if(support_compat_dir && '/' != *strpath.rbegin() && std::string::npos == strpath.find("_$folder$", 0) && is_need_check_obj_detail(*pheader)){
// check a case of that "object" does not have attribute and "object" is possible to be directory.
if(-ENOTEMPTY == directory_empty(strpath.c_str())){
// found "no dir object".
strpath += "/";
*pisforce = true;
result = 0;
}
}
}
// [NOTE]
// If the file is listed but not allowed access, put it in
// the positive cache instead of the negative cache.
//
if(0 != result){
// finally, "path" object did not find. Add no object cache.
strpath = path; // reset original
StatCache::getStatCacheData()->AddNoObjectCache(strpath);
return result;
}
// if path has "_$folder$", need to cut it.
if(std::string::npos != (Pos = strpath.find("_$folder$", 0))){
strpath.erase(Pos);
strpath += "/";
}
// Set into cache
//
// [NOTE]
// When add_no_truncate_cache is true, the stats is always cached.
// This cached stats is only removed by DelStat().
// This is necessary for the case to access the attribute of opened file.
// (ex. getxattr() is called while writing to the opened file.)
//
if(add_no_truncate_cache || 0 != StatCache::getStatCacheData()->GetCacheSize()){
// add into stat cache
if(!StatCache::getStatCacheData()->AddStat(strpath, (*pheader), forcedir, add_no_truncate_cache)){
S3FS_PRN_ERR("failed adding stat cache [path=%s]", strpath.c_str());
return -ENOENT;
}
if(!StatCache::getStatCacheData()->GetStat(strpath, pstat, pheader, overcheck, pisforce)){
// There is not in cache.(why?) -> retry to convert.
if(!StatCache::getStatCacheData()->ConvertMetaToStat(strpath, (*pheader), pstat, forcedir)){
S3FS_PRN_ERR("failed convert headers to stat[path=%s]", strpath.c_str());
return -ENOENT;
}
}
}else{
// cache size is Zero -> only convert.
if(!StatCache::getStatCacheData()->ConvertMetaToStat(strpath, (*pheader), pstat, forcedir)){
S3FS_PRN_ERR("failed convert headers to stat[path=%s]", strpath.c_str());
return -ENOENT;
}
}
return 0;
}