in src/metaheader.cpp [135:231]
mode_t get_mode(const headers_t& meta, const std::string& strpath, bool checkdir, bool forcedir, bool noextendedmeta)
{
mode_t mode = 0;
bool isS3sync = false;
headers_t::const_iterator iter;
if(noextendedmeta){
//get file type from mode
if(meta.end() != (iter = meta.find("x-oss-meta-mode"))){
mode = get_mode((*iter).second.c_str());
}
// remove permissions
mode &= S_IFMT;
// set permissions to default
if(mode & S_IFMT){
if(S_ISLNK(mode)){
mode |= 0777;
}else if(S_ISDIR(mode)){
mode |= 0750;
}else if(S_ISCHR(mode) || S_ISBLK(mode)){
mode |= 0644;
}else{
mode |= 0640;
}
}else{
mode = (!strpath.empty() && '/' == *strpath.rbegin()) ? 0750 : 0640;
}
}else if(meta.end() != (iter = meta.find("x-oss-meta-mode"))){
mode = get_mode((*iter).second.c_str());
}else if(meta.end() != (iter = meta.find("x-oss-meta-permissions"))){ // for s3sync
mode = get_mode((*iter).second.c_str());
isS3sync = true;
}else if(meta.end() != (iter = meta.find("x-oss-meta-goog-reserved-posix-mode"))){ // for GCS
mode = get_mode((*iter).second.c_str(), 8);
}else{
// If another tool creates an object without permissions, default to owner
// read-write and group readable.
mode = (!strpath.empty() && '/' == *strpath.rbegin()) ? 0750 : 0640;
}
// Checking the new ossfs symlink format
if(!(mode & S_IFMT)){
if(meta.end() != meta.find("x-oss-meta-symlink-target")) {
mode |= (S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
}
}
// Checking the bitmask, if the last 3 bits are all zero then process as a regular
// file type (S_IFDIR or S_IFREG), otherwise return mode unmodified so that S_IFIFO,
// S_IFSOCK, S_IFCHR, S_IFLNK and S_IFBLK devices can be processed properly by fuse.
if(!(mode & S_IFMT)){
if(!isS3sync){
if(checkdir){
if(forcedir){
mode |= S_IFDIR;
}else{
if(meta.end() != (iter = meta.find("Content-Type"))){
std::string strConType = (*iter).second;
// Leave just the mime type, remove any optional parameters (eg charset)
std::string::size_type pos = strConType.find(';');
if(std::string::npos != pos){
strConType.erase(pos);
}
if(strConType == "application/x-directory" || strConType == "httpd/unix-directory"){
// Nextcloud uses this MIME type for directory objects when mounting bucket as external Storage
mode |= S_IFDIR;
}else if(!strpath.empty() && '/' == *strpath.rbegin()){
// If complement lack stat mode, when the object has '/' character at end of name
// it should be directory. This follows ossfs's behavior.
if(complement_stat || strConType == "binary/octet-stream" || strConType == "application/octet-stream"){
mode |= S_IFDIR;
}else{
mode |= S_IFREG;
}
}else{
mode |= S_IFREG;
}
}else{
mode |= S_IFREG;
}
}
}
// If complement lack stat mode, when it's mode is not set any permission,
// the object is added minimal mode only for read permission.
if(complement_stat && 0 == (mode & (S_IRWXU | S_IRWXG | S_IRWXO))){
mode |= (S_IRUSR | (0 == (mode & S_IFDIR) ? 0 : S_IXUSR));
}
}else{
if(!checkdir){
// cut dir/reg flag.
mode &= ~S_IFDIR;
mode &= ~S_IFREG;
}
}
}
return mode;
}