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