int S3fsCurl::PutRequest()

in src/curl.cpp [3118:3259]


int S3fsCurl::PutRequest(const char* tpath, headers_t& meta, int fd)
{
    struct stat st;
    FILE*       file = NULL;

    S3FS_PRN_INFO3("[tpath=%s]", SAFESTRPTR(tpath));

    if(!tpath){
        return -EINVAL;
    }
    if(-1 != fd){
        // duplicate fd
        int fd2;
        if(-1 == (fd2 = dup(fd)) || -1 == fstat(fd2, &st) || 0 != lseek(fd2, 0, SEEK_SET) || NULL == (file = fdopen(fd2, "rb"))){
            S3FS_PRN_ERR("Could not duplicate file descriptor(errno=%d)", errno);
            if(-1 != fd2){
                close(fd2);
            }
            return -errno;
        }
        b_infile = file;
    }else{
        // This case is creating zero byte object.(calling by create_file_object())
        S3FS_PRN_INFO3("create zero byte file object.");
    }

    if(!CreateCurlHandle()){
        if(file){
            fclose(file);
        }
        return -EIO;
    }
    std::string resource;
    std::string turl;
    MakeUrlResource(get_realpath(tpath).c_str(), resource, turl);

    url             = prepare_url(turl.c_str());
    path            = get_realpath(tpath);
    requestHeaders  = NULL;
    responseHeaders.clear();
    bodydata.clear();

    // Make request headers
    std::string strMD5;
    if(S3fsCurl::is_content_md5){
        if(-1 != fd){
            strMD5 = s3fs_get_content_md5(fd);
            if(0 == strMD5.length()){
                S3FS_PRN_ERR("Failed to make MD5.");
                return -EIO;
            }
        }else{
            strMD5 = EMPTY_MD5_BASE64_HASH;
        }
        requestHeaders = curl_slist_sort_insert(requestHeaders, "Content-MD5", strMD5.c_str());
    }

    std::string contype = S3fsCurl::LookupMimeType(std::string(tpath));
    requestHeaders = curl_slist_sort_insert(requestHeaders, "Content-Type", contype.c_str());

    for(headers_t::iterator iter = meta.begin(); iter != meta.end(); ++iter){
        std::string key   = lower(iter->first);
        std::string value = iter->second;
        if(is_prefix(key.c_str(), "x-oss-object-acl")){
            // not set value, but after set it.
        }else if(is_prefix(key.c_str(), "x-oss-meta")){
            requestHeaders = curl_slist_sort_insert(requestHeaders, iter->first.c_str(), value.c_str());
        }else if(key == "x-oss-server-side-encryption" && value != "KMS"){
            // skip this header, because this header is specified after logic.
        }else if(key == "x-oss-server-side-encryption-key-id"){
            // skip this header, because this header is specified after logic.
        }else if(key == "x-oss-server-side-encryption-customer-key-md5"){
            // skip this header, because this header is specified after logic.
        }
    }
    // "x-oss-object-acl", storage class, sse
    if(S3fsCurl::default_acl != acl_t::DEFAULT){
        requestHeaders = curl_slist_sort_insert(requestHeaders, "x-oss-object-acl", S3fsCurl::default_acl.str());
    }
    if(strcasecmp(GetStorageClass().c_str(), "STANDARD") != 0){
        requestHeaders = curl_slist_sort_insert(requestHeaders, "x-oss-storage-class", GetStorageClass().c_str());
    }
    // SSE
    std::string ssevalue;
    // do not add SSE for create bucket
    if(0 != strcmp(tpath, "/")){
        if(!AddSseRequestHead(S3fsCurl::GetSseType(), ssevalue, false, false)){
            S3FS_PRN_WARN("Failed to set SSE header, but continue...");
        }
    }
    if(is_use_ahbe){
        // set additional header by ahbe conf
        requestHeaders = AdditionalHeader::get()->AddHeader(requestHeaders, tpath);
    }
    if(S3fsCurl::upload_traffic_limit != 0) {
        char buff[64];
        sprintf(buff, "%ld", S3fsCurl::upload_traffic_limit);
        requestHeaders = curl_slist_sort_insert(requestHeaders, "x-oss-traffic-limit", buff);
    }

    op = "PUT";
    type = REQTYPE_PUT;

    // setopt
    if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_URL, url.c_str())){
        return -EIO;
    }
    if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_UPLOAD, true)){                // HTTP PUT
        return -EIO;
    }
    if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_WRITEDATA, (void*)&bodydata)){
        return -EIO;
    }
    if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback)){
        return -EIO;
    }
    if(file){
        if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_INFILESIZE_LARGE, static_cast<curl_off_t>(st.st_size))){ // Content-Length
            return -EIO;
        }
        if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_INFILE, file)){
            return -EIO;
        }
    }else{
        if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_INFILESIZE, 0)){             // Content-Length: 0
            return -EIO;
        }
    }
    if(!S3fsCurl::AddUserAgent(hCurl)){                            // put User-Agent
        return -EIO;
    }

    S3FS_PRN_INFO3("uploading... [path=%s][fd=%d][size=%lld]", tpath, fd, static_cast<long long int>(-1 != fd ? st.st_size : 0));

    int result = RequestPerform();
    result = MapPutErrorResponse(result);
    bodydata.clear();
    if(file){
        fclose(file);
    }
    return result;
}