mode_t get_mode()

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