static int s3fs_check_service()

in src/s3fs.cpp [3742:3870]


static int s3fs_check_service()
{
    S3FS_PRN_INFO("check services.");

    // At first time for access OSS, we check IAM role if it sets.
    if(!ps3fscred->CheckIAMCredentialUpdate()){
        S3FS_PRN_CRIT("Failed to initialize IAM credential.");
        return EXIT_FAILURE;
    }

    S3fsCurl s3fscurl;
    int      res;
    if(0 > (res = s3fscurl.CheckBucket(get_realpath("/").c_str()))){
        // get response code
        long responseCode = s3fscurl.GetLastResponseCode();

        // check wrong endpoint, and automatically switch endpoint
        if(300 <= responseCode && responseCode < 500){

            // check region error(for putting message or retrying)
            const std::string* body = s3fscurl.GetBodyData();
            /*
            std::string expectregion;
            std::string expectendpoint;
            if(check_region_error(body->c_str(), body->size(), expectregion)){
                // [NOTE]
                // If endpoint is not specified(using us-east-1 region) and
                // an error is encountered accessing a different region, we
                // will retry the check on the expected region.
                // see) https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingBucket.html#access-bucket-intro
                //
                if(is_specified_endpoint){
                    const char* tmp_expect_ep = expectregion.c_str();
                    S3FS_PRN_CRIT("The bucket region is not '%s', it is correctly '%s'. You should specify 'endpoint=%s' option.", endpoint.c_str(), tmp_expect_ep, tmp_expect_ep);

                }else{
                    // current endpoint is wrong, so try to connect to expected region.
                    S3FS_PRN_CRIT("Failed to connect region '%s'(default), so retry to connect region '%s'.", endpoint.c_str(), expectregion.c_str());
                    endpoint = expectregion;
                    if(S3fsCurl::GetSignatureType() == V4_ONLY ||
                       S3fsCurl::GetSignatureType() == V1_OR_V4){
                        if(s3host == "http://s3.amazonaws.com"){
                            s3host = "http://s3-" + endpoint + ".amazonaws.com";
                        }else if(s3host == "https://s3.amazonaws.com"){
                            s3host = "https://s3-" + endpoint + ".amazonaws.com";
                        }
                    }

                    // retry to check with new endpoint
                    s3fscurl.DestroyCurlHandle();
                    res          = s3fscurl.CheckBucket();
                    responseCode = s3fscurl.GetLastResponseCode();
                }
            }else 
            */
            std::string expecthost;
            if(check_endpoint_error(body->c_str(), body->size(), expecthost)){
                S3FS_PRN_CRIT("Failed to connect host '%s'(default), so retry to connect host '%s'.", s3host.c_str(), expecthost.c_str());
                if(!strncasecmp(s3host.c_str(), "https://", 8)){
                    s3host = "https://" + expecthost;
                } else {
                    s3host = "http://" + expecthost;
                }
                // extract region from host for sigv4
                // The region of the government cloud/financial cloud may not be derived from the domain name
                // https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints?spm=a2c4g.11186623.0.0.13ad12c1N7PoaV
                if(!strncasecmp(expecthost.c_str(), "oss-", 4)){
                    std::size_t found;
                    if ((found = expecthost.find_first_of(".")) != std::string::npos) {
                        endpoint = expecthost.substr(4, found - 4);
                    }
                    S3FS_PRN_CRIT("Extract region '%s' from expecthost.", endpoint.c_str());
                }
                // retry to check with new host
                s3fscurl.DestroyCurlHandle();
                res          = s3fscurl.CheckBucket(get_realpath("/").c_str());
                responseCode = s3fscurl.GetLastResponseCode();
            }
        }

        // try signature v2
        /*
        if(0 > res && (responseCode == 400 || responseCode == 403) && S3fsCurl::GetSignatureType() == V1_OR_V4){
            // switch sigv2
            S3FS_PRN_CRIT("Failed to connect by sigv4, so retry to connect by signature version 2.");
            S3fsCurl::SetSignatureType(V1_ONLY);

            // retry to check with sigv2
            s3fscurl.DestroyCurlHandle();
            res          = s3fscurl.CheckBucket();
            responseCode = s3fscurl.GetLastResponseCode();
        }
        */
        // check errors(after retrying)
        // [NOTE]
        // When mounting a bucket, an error code is returned and the mount fails. 
        // However, when mounting a prefix, success should be returned if the prefix does not exist.
        // 
        if(0 > res && responseCode != 200 && responseCode != 301){
            // parse error message if existed
            std::string errMessage;
            const std::string* body = s3fscurl.GetBodyData();
            check_error_message(body->c_str(), body->size(), errMessage);
            bool is_failure = true;
            if(responseCode == 400){
                S3FS_PRN_CRIT("Failed to check bucket and directory for mount point : Bad Request(host=%s, message=%s)", s3host.c_str(), errMessage.c_str());
            }else if(responseCode == 403){
                 S3FS_PRN_CRIT("Failed to check bucket and directory for mount point : Invalid Credentials(host=%s, message=%s)", s3host.c_str(), errMessage.c_str());
            }else if (responseCode == 404) {
                std::string value;
                if(simple_parse_xml(body->c_str(), body->size(), "Code", value)) {
                    if(value == "NoSuchBucket") {
                        S3FS_PRN_CRIT("Failed to check bucket : Bucket not found(host=%s, message=%s)", s3host.c_str(), errMessage.c_str());
                    } else {
                        is_failure = false;
                    }
                }
            }else{
                S3FS_PRN_CRIT("Failed to check bucket and directory for mount point : Unable to connect(host=%s, message=%s)", s3host.c_str(), errMessage.c_str());
            }
            if (is_failure) {
                return EXIT_FAILURE;
            }
        }
    }
    S3FS_MALLOCTRIM(0);
    
    return EXIT_SUCCESS;
}