static int list_bucket()

in src/s3fs.cpp [2905:3016]


static int list_bucket(const char* path, S3ObjList& head, const char* delimiter, bool check_content_only)
{
    std::string s3_realpath;
    std::string query_delimiter;
    std::string query_prefix;
    std::string query_maxkey;
    std::string next_continuation_token;
    std::string next_marker;
    bool truncated = true;
    S3fsCurl  s3fscurl;
    xmlDocPtr doc;

    S3FS_PRN_INFO1("[path=%s]", path);

    if(delimiter && 0 < strlen(delimiter)){
        query_delimiter += "delimiter=";
        query_delimiter += delimiter;
        query_delimiter += "&";
    }

    query_prefix += "&prefix=";
    s3_realpath = get_realpath(path);
    if(s3_realpath.empty() || '/' != *s3_realpath.rbegin()){
        // last word must be "/"
        query_prefix += urlEncode(s3_realpath.substr(1) + "/");
    }else{
        query_prefix += urlEncode(s3_realpath.substr(1));
    }
    if (check_content_only){
        // Just need to know if there are child objects in dir
        // For dir with children, expect "dir/" and "dir/child"
        query_maxkey += "max-keys=2";
    }else{
        query_maxkey += "max-keys=" + str(max_keys_list_object);
    }

    while(truncated){
        // append parameters to query in alphabetical order
        std::string each_query;
        if(!next_continuation_token.empty()){
            each_query += "continuation-token=" + urlEncode(next_continuation_token) + "&";
            next_continuation_token = "";
        }
        each_query += query_delimiter;
        if(S3fsCurl::IsListObjectsV2()){
            each_query += "list-type=2&";
        }
        if(!next_marker.empty()){
            each_query += "marker=" + urlEncode(next_marker) + "&";
            next_marker = "";
        }
        each_query += query_maxkey;
        each_query += query_prefix;

        // request
        int result; 
        if(0 != (result = s3fscurl.ListBucketRequest(path, each_query.c_str()))){
            S3FS_PRN_ERR("ListBucketRequest returns with error.");
            return result;
        }
        const std::string* body = s3fscurl.GetBodyData();

        // xmlDocPtr
        if(NULL == (doc = xmlReadMemory(body->c_str(), static_cast<int>(body->size()), "", NULL, 0))){
            S3FS_PRN_ERR("xmlReadMemory returns with error.");
            return -EIO;
        }
        if(0 != append_objects_from_xml(path, doc, head)){
            S3FS_PRN_ERR("append_objects_from_xml returns with error.");
            xmlFreeDoc(doc);
            return -EIO;
        }
        if(true == (truncated = is_truncated(doc))){
            xmlChar* tmpch;
            if(NULL != (tmpch = get_next_continuation_token(doc))){
                next_continuation_token = (char*)tmpch;
                xmlFree(tmpch);
            }else if(NULL != (tmpch = get_next_marker(doc))){
                next_marker = (char*)tmpch;
                xmlFree(tmpch);
            }

            if(next_continuation_token.empty() && next_marker.empty()){
                // If did not specify "delimiter", s3 did not return "NextMarker".
                // On this case, can use last name for next marker.
                //
                std::string lastname;
                if(!head.GetLastName(lastname)){
                    S3FS_PRN_WARN("Could not find next marker, thus break loop.");
                    truncated = false;
                }else{
                    next_marker = s3_realpath.substr(1);
                    if(s3_realpath.empty() || '/' != *s3_realpath.rbegin()){
                        next_marker += "/";
                    }
                    next_marker += lastname;
                }
            }
        }
        S3FS_XMLFREEDOC(doc);

        // reset(initialize) curl object
        s3fscurl.DestroyCurlHandle();

        if(check_content_only){
            break;
        }
    }
    S3FS_MALLOCTRIM(0);

    return 0;
}