mirror of
https://github.com/s3fs-fuse/s3fs-fuse.git
synced 2024-11-19 10:45:12 +00:00
commit
ae4ae88b6d
@ -71,9 +71,13 @@ this option can not be specified with use_sse.
|
||||
(can specify use_rrs=1 for old version)
|
||||
.TP
|
||||
\fB\-o\fR use_sse (default is disable)
|
||||
use Amazon's Server Site Encryption.
|
||||
this option can not be specified with use_rrs.
|
||||
(can specify use_sse=1 for old version)
|
||||
use Amazon<6F>fs Server-Site Encryption or Server-Side Encryption with Customer-Provided Encryption Keys.
|
||||
this option can not be specified with use_rrs. specifying only "use_sse" or "use_sse=1" enables Server-Side Encryption.(use_sse=1 for old version)
|
||||
specifying this option with file path which has some SSE-C secret key enables Server-Side Encryption with Customer-Provided Encryption Keys.(use_sse=file)
|
||||
the file must be 600 permission. the file can have some lines, each line is one SSE-C key. the first line in file is used as Customer-Provided Encryption Keys for uploading and change headers etc.
|
||||
if there are some keys after first line, those are used downloading object which are encripted by not first key.
|
||||
so that, you can keep all SSE-C keys in file, that is SSE-C key history.
|
||||
if AWSSSECKEYS environment is set, you can set SSE-C key instead of this option.
|
||||
.TP
|
||||
\fB\-o\fR passwd_file (default="")
|
||||
specify the path to the password file, which which takes precedence over the password in $HOME/.passwd-s3fs and /etc/passwd-s3fs
|
||||
|
387
src/curl.cpp
387
src/curl.cpp
@ -51,6 +51,63 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Utilities
|
||||
//-------------------------------------------------------------------
|
||||
// [TODO]
|
||||
// This function uses tempolary file, but should not use it.
|
||||
// For not using it, we implement function in each auth file(openssl, nss. gnutls).
|
||||
//
|
||||
static bool make_md5_from_string(const char* pstr, string& md5)
|
||||
{
|
||||
if(!pstr || '\0' == pstr[0]){
|
||||
DPRN("Parameter is wrong.");
|
||||
return false;
|
||||
}
|
||||
FILE* fp;
|
||||
if(NULL == (fp = tmpfile())){
|
||||
FPRN("Could not make tmpfile.");
|
||||
return false;
|
||||
}
|
||||
size_t length = strlen(pstr);
|
||||
if(length != fwrite(pstr, sizeof(char), length, fp)){
|
||||
FPRN("Failed to write tmpfile.");
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
int fd;
|
||||
if(0 != fflush(fp) || 0 != fseek(fp, 0L, SEEK_SET) || -1 == (fd = fileno(fp))){
|
||||
FPRN("Failed to make MD5.");
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
// base64 md5
|
||||
md5 = s3fs_get_content_md5(fd);
|
||||
if(0 == md5.length()){
|
||||
FPRN("Failed to make MD5.");
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0 // noused
|
||||
static string tolower_header_name(const char* head)
|
||||
{
|
||||
string::size_type pos;
|
||||
string name = head;
|
||||
string value("");
|
||||
if(string::npos != (pos = name.find(':'))){
|
||||
value= name.substr(pos);
|
||||
name = name.substr(0, pos);
|
||||
}
|
||||
name = lower(name);
|
||||
name += value;
|
||||
return name;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Class BodyData
|
||||
//-------------------------------------------------------------------
|
||||
@ -154,6 +211,7 @@ int S3fsCurl::retries = 3; // default
|
||||
bool S3fsCurl::is_public_bucket = false;
|
||||
string S3fsCurl::default_acl = "private";
|
||||
bool S3fsCurl::is_use_rrs = false;
|
||||
sseckeylist_t S3fsCurl::sseckeys;
|
||||
bool S3fsCurl::is_use_sse = false;
|
||||
bool S3fsCurl::is_content_md5 = false;
|
||||
bool S3fsCurl::is_verbose = false;
|
||||
@ -684,6 +742,126 @@ bool S3fsCurl::SetUseRrs(bool flag)
|
||||
return old;
|
||||
}
|
||||
|
||||
bool S3fsCurl::PushbackSseKeys(string& onekey)
|
||||
{
|
||||
onekey = trim(onekey);
|
||||
if(0 == onekey.size()){
|
||||
return false;
|
||||
}
|
||||
if('#' == onekey[0]){
|
||||
return false;
|
||||
}
|
||||
// make base64
|
||||
char* pbase64_key;
|
||||
if(NULL == (pbase64_key = s3fs_base64((unsigned char*)onekey.c_str(), onekey.length()))){
|
||||
FPRN("Failed to convert base64 from sse-c key %s", onekey.c_str());
|
||||
return false;
|
||||
}
|
||||
string base64_key = pbase64_key;
|
||||
free(pbase64_key);
|
||||
|
||||
// make MD5
|
||||
string strMd5;
|
||||
if(!make_md5_from_string(onekey.c_str(), strMd5)){
|
||||
FPRN("Could not make MD5 from SSE-C keys(%s).", onekey.c_str());
|
||||
return false;
|
||||
}
|
||||
// mapped MD5 = SSE Key
|
||||
sseckeymap_t md5map;
|
||||
md5map.clear();
|
||||
md5map[strMd5] = base64_key;
|
||||
S3fsCurl::sseckeys.push_back(md5map);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool S3fsCurl::SetSseKeys(const char* filepath)
|
||||
{
|
||||
if(!filepath){
|
||||
DPRN("SSE-C keys filepath is empty.");
|
||||
return false;
|
||||
}
|
||||
S3fsCurl::sseckeys.clear();
|
||||
|
||||
ifstream ssefs(filepath);
|
||||
if(!ssefs.good()){
|
||||
FPRN("Could not open SSE-C keys file(%s).", filepath);
|
||||
return false;
|
||||
}
|
||||
|
||||
string line;
|
||||
while(getline(ssefs, line)){
|
||||
S3fsCurl::PushbackSseKeys(line);
|
||||
}
|
||||
if(0 == S3fsCurl::sseckeys.size()){
|
||||
FPRN("There is no SSE Key in file(%s).", filepath);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool S3fsCurl::LoadEnvSseKeys(void)
|
||||
{
|
||||
char* envkeys = getenv("AWSSSECKEYS");
|
||||
if(NULL == envkeys){
|
||||
return false;
|
||||
}
|
||||
S3fsCurl::sseckeys.clear();
|
||||
|
||||
istringstream fullkeys(envkeys);
|
||||
string onekey;
|
||||
while(getline(fullkeys, onekey, ':')){
|
||||
S3fsCurl::PushbackSseKeys(onekey);
|
||||
}
|
||||
if(0 == S3fsCurl::sseckeys.size()){
|
||||
FPRN("There is no SSE Key in environment(AWSSSECKEYS=%s).", envkeys);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// If md5 is empty, returns first(current) sse key.
|
||||
//
|
||||
bool S3fsCurl::GetSseKey(string& md5, string& ssekey)
|
||||
{
|
||||
for(sseckeylist_t::const_iterator iter = S3fsCurl::sseckeys.begin(); iter != S3fsCurl::sseckeys.end(); iter++){
|
||||
if(0 == md5.length() || md5 == (*iter).begin()->first){
|
||||
md5 = iter->begin()->first;
|
||||
ssekey = iter->begin()->second;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool S3fsCurl::GetSseKeyMd5(int pos, string& md5)
|
||||
{
|
||||
if(pos < 0){
|
||||
return false;
|
||||
}
|
||||
if(S3fsCurl::sseckeys.size() <= static_cast<size_t>(pos)){
|
||||
return false;
|
||||
}
|
||||
int cnt = 0;
|
||||
for(sseckeylist_t::const_iterator iter = S3fsCurl::sseckeys.begin(); iter != S3fsCurl::sseckeys.end(); iter++, cnt++){
|
||||
if(pos == cnt){
|
||||
md5 = iter->begin()->first;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int S3fsCurl::GetSseKeyCount(void)
|
||||
{
|
||||
return S3fsCurl::sseckeys.size();
|
||||
}
|
||||
|
||||
bool S3fsCurl::IsSseCustomMode(void)
|
||||
{
|
||||
return (0 < S3fsCurl::sseckeys.size());
|
||||
}
|
||||
|
||||
bool S3fsCurl::SetUseSse(bool flag)
|
||||
{
|
||||
bool old = S3fsCurl::is_use_sse;
|
||||
@ -806,7 +984,7 @@ S3fsCurl* S3fsCurl::UploadMultipartPostRetryCallback(S3fsCurl* s3fscurl)
|
||||
return newcurl;
|
||||
}
|
||||
|
||||
int S3fsCurl::ParallelMultipartUploadRequest(const char* tpath, headers_t& meta, int fd, bool ow_sse_flg)
|
||||
int S3fsCurl::ParallelMultipartUploadRequest(const char* tpath, headers_t& meta, int fd)
|
||||
{
|
||||
int result;
|
||||
string upload_id;
|
||||
@ -832,7 +1010,7 @@ int S3fsCurl::ParallelMultipartUploadRequest(const char* tpath, headers_t& meta,
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if(0 != (result = s3fscurl.PreMultipartPostRequest(tpath, meta, upload_id, ow_sse_flg))){
|
||||
if(0 != (result = s3fscurl.PreMultipartPostRequest(tpath, meta, upload_id, false))){
|
||||
close(fd2);
|
||||
return result;
|
||||
}
|
||||
@ -911,7 +1089,7 @@ S3fsCurl* S3fsCurl::ParallelGetObjectRetryCallback(S3fsCurl* s3fscurl)
|
||||
// duplicate request(setup new curl object)
|
||||
S3fsCurl* newcurl = new S3fsCurl(s3fscurl->IsUseAhbe());
|
||||
if(0 != (result = newcurl->PreGetObjectRequest(
|
||||
s3fscurl->path.c_str(), s3fscurl->partdata.fd, s3fscurl->partdata.startpos, s3fscurl->partdata.size))){
|
||||
s3fscurl->path.c_str(), s3fscurl->partdata.fd, s3fscurl->partdata.startpos, s3fscurl->partdata.size, s3fscurl->b_ssekey_md5))){
|
||||
DPRN("failed downloading part setup(%d)", result);
|
||||
delete newcurl;
|
||||
return NULL;;
|
||||
@ -925,6 +1103,12 @@ int S3fsCurl::ParallelGetObjectRequest(const char* tpath, int fd, off_t start, s
|
||||
{
|
||||
FPRNNN("[tpath=%s][fd=%d]", SAFESTRPTR(tpath), fd);
|
||||
|
||||
string sseckeymd5("");
|
||||
char* psseckeymd5;
|
||||
if(NULL != (psseckeymd5 = get_object_sseckey_md5(tpath))){
|
||||
sseckeymd5 = psseckeymd5;
|
||||
free(psseckeymd5);
|
||||
}
|
||||
int result = 0;
|
||||
ssize_t remaining_bytes;
|
||||
|
||||
@ -945,7 +1129,7 @@ int S3fsCurl::ParallelGetObjectRequest(const char* tpath, int fd, off_t start, s
|
||||
|
||||
// s3fscurl sub object
|
||||
S3fsCurl* s3fscurl_para = new S3fsCurl();
|
||||
if(0 != (result = s3fscurl_para->PreGetObjectRequest(tpath, fd, (start + size - remaining_bytes), chunk))){
|
||||
if(0 != (result = s3fscurl_para->PreGetObjectRequest(tpath, fd, (start + size - remaining_bytes), chunk, sseckeymd5))){
|
||||
DPRN("failed downloading part setup(%d)", result);
|
||||
delete s3fscurl_para;
|
||||
return result;
|
||||
@ -1053,7 +1237,8 @@ bool S3fsCurl::CheckIAMCredentialUpdate(void)
|
||||
S3fsCurl::S3fsCurl(bool ahbe) :
|
||||
hCurl(NULL), path(""), base_path(""), saved_path(""), url(""), requestHeaders(NULL),
|
||||
bodydata(NULL), headdata(NULL), LastResponseCode(-1), postdata(NULL), postdata_remaining(0), is_use_ahbe(ahbe),
|
||||
retry_count(0), b_infile(NULL), b_postdata(NULL), b_postdata_remaining(0), b_partdata_startpos(0), b_partdata_size(0)
|
||||
retry_count(0), b_infile(NULL), b_postdata(NULL), b_postdata_remaining(0), b_partdata_startpos(0), b_partdata_size(0),
|
||||
b_ssekey_pos(-1), b_ssekey_md5("")
|
||||
{
|
||||
type = REQTYPE_UNSET;
|
||||
}
|
||||
@ -1728,12 +1913,38 @@ int S3fsCurl::GetIAMCredentials(void)
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// If md5 is empty, build by first(current) sse key
|
||||
//
|
||||
bool S3fsCurl::AddSseKeyRequestHead(string& md5, bool is_copy)
|
||||
{
|
||||
if(!S3fsCurl::IsSseCustomMode()){
|
||||
// Nothing to do
|
||||
return true;
|
||||
}
|
||||
string sseckey;
|
||||
if(S3fsCurl::GetSseKey(md5, sseckey)){
|
||||
if(is_copy){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, "x-amz-copy-source-server-side-encryption-customer-algorithm:AES256");
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, string("x-amz-copy-source-server-side-encryption-customer-key:" + sseckey).c_str());
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, string("x-amz-copy-source-server-side-encryption-customer-key-md5:" + md5).c_str());
|
||||
}else{
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, "x-amz-server-side-encryption-customer-algorithm:AES256");
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, string("x-amz-server-side-encryption-customer-key:" + sseckey).c_str());
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, string("x-amz-server-side-encryption-customer-key-md5:" + md5).c_str());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// tpath : target path for head request
|
||||
// bpath : saved into base_path
|
||||
// savedpath : saved into saved_path
|
||||
// ssekey_pos : -1 means "not use sse", 0 - X means "use sseckey" and "sseckey position".
|
||||
// sseckey position 0 is latest key.
|
||||
//
|
||||
bool S3fsCurl::PreHeadRequest(const char* tpath, const char* bpath, const char* savedpath)
|
||||
bool S3fsCurl::PreHeadRequest(const char* tpath, const char* bpath, const char* savedpath, int ssekey_pos)
|
||||
{
|
||||
FPRNINFO("[tpath=%s][bpath=%s][save=%s]", SAFESTRPTR(tpath), SAFESTRPTR(bpath), SAFESTRPTR(savedpath));
|
||||
|
||||
@ -1759,6 +1970,15 @@ bool S3fsCurl::PreHeadRequest(const char* tpath, const char* bpath, const char*
|
||||
string date = get_date();
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, string("Date: " + date).c_str());
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, "Content-Type: ");
|
||||
|
||||
if(0 <= ssekey_pos && S3fsCurl::IsSseCustomMode()){
|
||||
string md5;
|
||||
if(!S3fsCurl::GetSseKeyMd5(ssekey_pos, md5) || !AddSseKeyRequestHead(md5, false)){
|
||||
DPRN("Failed to set SSE-C headers for md5(%s).", md5.c_str());
|
||||
}
|
||||
}
|
||||
b_ssekey_pos = ssekey_pos;
|
||||
|
||||
if(!S3fsCurl::IsPublicBucket()){
|
||||
requestHeaders = curl_slist_sort_insert(
|
||||
requestHeaders,
|
||||
@ -1782,32 +2002,53 @@ bool S3fsCurl::PreHeadRequest(const char* tpath, const char* bpath, const char*
|
||||
|
||||
int S3fsCurl::HeadRequest(const char* tpath, headers_t& meta)
|
||||
{
|
||||
int result;
|
||||
int result = -1;
|
||||
|
||||
FPRNNN("[tpath=%s]", SAFESTRPTR(tpath));
|
||||
|
||||
if(!PreHeadRequest(tpath)){
|
||||
return -1;
|
||||
}
|
||||
// Requests
|
||||
if(0 != (result = RequestPerform())){
|
||||
return result;
|
||||
if(S3fsCurl::IsSseCustomMode()){
|
||||
// SSE-C mode, check all sse-c key at first
|
||||
int pos;
|
||||
for(pos = 0; static_cast<size_t>(pos) < S3fsCurl::sseckeys.size(); pos++){
|
||||
if(0 != pos && !DestroyCurlHandle()){
|
||||
return result;
|
||||
}
|
||||
if(!PreHeadRequest(tpath, NULL, NULL, pos)){
|
||||
return result;
|
||||
}
|
||||
if(0 == (result = RequestPerform())){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(S3fsCurl::sseckeys.size() <= static_cast<size_t>(pos)){
|
||||
// If sse-c mode is enable, s3fs fails to get head request for normal and sse object.
|
||||
// So try to get head without sse-c header.
|
||||
if(!DestroyCurlHandle() || !PreHeadRequest(tpath, NULL, NULL, -1) || 0 != (result = RequestPerform())){
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// Not sse-c mode
|
||||
if(!PreHeadRequest(tpath) || 0 != (result = RequestPerform())){
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// file exists in s3
|
||||
// fixme: clean this up.
|
||||
meta.clear();
|
||||
for(headers_t::iterator iter = responseHeaders.begin(); iter != responseHeaders.end(); ++iter){
|
||||
string key = (*iter).first;
|
||||
string value = (*iter).second;
|
||||
if(key == "Content-Type"){
|
||||
if(0 == strcasecmp(key.c_str(), "Content-Type")){
|
||||
meta[key] = value;
|
||||
}else if(key == "Content-Length"){
|
||||
}else if(0 == strcasecmp(key.c_str(), "Content-Length")){
|
||||
meta[key] = value;
|
||||
}else if(key == "ETag"){
|
||||
}else if(0 == strcasecmp(key.c_str(), "ETag")){
|
||||
meta[key] = value;
|
||||
}else if(key == "Last-Modified"){
|
||||
}else if(0 == strcasecmp(key.c_str(), "Last-Modified")){
|
||||
meta[key] = value;
|
||||
}else if(key.substr(0, 5) == "x-amz"){
|
||||
}else if(0 == strcasecmp(key.substr(0, 5).c_str(), "x-amz")){
|
||||
meta[key] = value;
|
||||
}else{
|
||||
// Check for upper case
|
||||
@ -1820,7 +2061,7 @@ int S3fsCurl::HeadRequest(const char* tpath, headers_t& meta)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int S3fsCurl::PutHeadRequest(const char* tpath, headers_t& meta, bool ow_sse_flg)
|
||||
int S3fsCurl::PutHeadRequest(const char* tpath, headers_t& meta, bool is_copy)
|
||||
{
|
||||
FPRNNN("[tpath=%s]", SAFESTRPTR(tpath));
|
||||
|
||||
@ -1848,18 +2089,24 @@ int S3fsCurl::PutHeadRequest(const char* tpath, headers_t& meta, bool ow_sse_flg
|
||||
for(headers_t::iterator iter = meta.begin(); iter != meta.end(); ++iter){
|
||||
string key = (*iter).first;
|
||||
string value = (*iter).second;
|
||||
if(key == "Content-Type"){
|
||||
if(0 == strcasecmp(key.c_str(), "Content-Type")){
|
||||
ContentType = value;
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, string(key + ":" + value).c_str());
|
||||
}else if(key.substr(0,9) == "x-amz-acl"){
|
||||
}else if(0 == strcasecmp(key.substr(0,9).c_str(), "x-amz-acl")){
|
||||
// not set value, but after set it.
|
||||
}else if(key.substr(0,10) == "x-amz-meta"){
|
||||
}else if(0 == strcasecmp(key.substr(0,10).c_str(), "x-amz-meta")){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, string(key + ":" + value).c_str());
|
||||
}else if(key == "x-amz-copy-source"){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, string(key + ":" + value).c_str());
|
||||
}else if(!ow_sse_flg && key == "x-amz-server-side-encryption"){
|
||||
// If ow_sse_flg is false, SSE inherit from meta.
|
||||
}else if(0 == strcasecmp(key.c_str(), "x-amz-copy-source")){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, string(key + ":" + value).c_str());
|
||||
}else if(0 == strcasecmp(key.c_str(), "x-amz-server-side-encryption")){
|
||||
// skip this header, because this header is specified after logic.
|
||||
}else if(0 == strcasecmp(key.c_str(), "x-amz-server-side-encryption-customer-algorithm")){
|
||||
// skip this header, because this header is specified with "x-amz-...-customer-key-md5".
|
||||
}else if(is_copy && 0 == strcasecmp(key.c_str(), "x-amz-server-side-encryption-customer-key-md5")){
|
||||
// Only copy mode.
|
||||
if(!AddSseKeyRequestHead(value, is_copy)){
|
||||
DPRNNN("Failed to insert sse(-c) header.");
|
||||
}
|
||||
}
|
||||
}
|
||||
// "x-amz-acl", rrs, sse
|
||||
@ -1867,8 +2114,13 @@ int S3fsCurl::PutHeadRequest(const char* tpath, headers_t& meta, bool ow_sse_flg
|
||||
if(S3fsCurl::is_use_rrs){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, "x-amz-storage-class:REDUCED_REDUNDANCY");
|
||||
}
|
||||
if(ow_sse_flg && S3fsCurl::is_use_sse){
|
||||
if(S3fsCurl::is_use_sse){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, "x-amz-server-side-encryption:AES256");
|
||||
}else if(S3fsCurl::IsSseCustomMode()){
|
||||
string md5;
|
||||
if(!AddSseKeyRequestHead(md5, false)){
|
||||
DPRNNN("Failed to insert sse(-c) header.");
|
||||
}
|
||||
}
|
||||
if(is_use_ahbe){
|
||||
// set additional header by ahbe conf
|
||||
@ -1900,7 +2152,7 @@ int S3fsCurl::PutHeadRequest(const char* tpath, headers_t& meta, bool ow_sse_flg
|
||||
return result;
|
||||
}
|
||||
|
||||
int S3fsCurl::PutRequest(const char* tpath, headers_t& meta, int fd, bool ow_sse_flg)
|
||||
int S3fsCurl::PutRequest(const char* tpath, headers_t& meta, int fd)
|
||||
{
|
||||
struct stat st;
|
||||
FILE* file = NULL;
|
||||
@ -1953,16 +2205,19 @@ int S3fsCurl::PutRequest(const char* tpath, headers_t& meta, int fd, bool ow_sse
|
||||
for(headers_t::iterator iter = meta.begin(); iter != meta.end(); ++iter){
|
||||
string key = (*iter).first;
|
||||
string value = (*iter).second;
|
||||
if(key == "Content-Type"){
|
||||
if(0 == strcasecmp(key.c_str(), "Content-Type")){
|
||||
ContentType = value;
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, string(key + ":" + value).c_str());
|
||||
}else if(key.substr(0,9) == "x-amz-acl"){
|
||||
}else if(0 == strcasecmp(key.substr(0,9).c_str(), "x-amz-acl")){
|
||||
// not set value, but after set it.
|
||||
}else if(key.substr(0,10) == "x-amz-meta"){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, string(key + ":" + value).c_str());
|
||||
}else if(!ow_sse_flg && key == "x-amz-server-side-encryption"){
|
||||
// If ow_sse_flg is false, SSE inherit from meta.
|
||||
}else if(0 == strcasecmp(key.substr(0,10).c_str(), "x-amz-meta")){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, string(key + ":" + value).c_str());
|
||||
}else if(0 == strcasecmp(key.c_str(), "x-amz-server-side-encryption")){
|
||||
// skip this header, because this header is specified after logic.
|
||||
}else if(0 == strcasecmp(key.c_str(), "x-amz-server-side-encryption-customer-algorithm")){
|
||||
// skip this header, because this header is specified after logic.
|
||||
}else if(0 == strcasecmp(key.c_str(), "x-amz-server-side-encryption-customer-key-md5")){
|
||||
// skip this header, because this header is specified after logic.
|
||||
}
|
||||
}
|
||||
// "x-amz-acl", rrs, sse
|
||||
@ -1970,8 +2225,13 @@ int S3fsCurl::PutRequest(const char* tpath, headers_t& meta, int fd, bool ow_sse
|
||||
if(S3fsCurl::is_use_rrs){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, "x-amz-storage-class:REDUCED_REDUNDANCY");
|
||||
}
|
||||
if(ow_sse_flg && S3fsCurl::is_use_sse){
|
||||
if(S3fsCurl::is_use_sse){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, "x-amz-server-side-encryption:AES256");
|
||||
}else if(S3fsCurl::IsSseCustomMode()){
|
||||
string md5;
|
||||
if(!AddSseKeyRequestHead(md5, false)){
|
||||
DPRNNN("Failed to insert sse(-c) header.");
|
||||
}
|
||||
}
|
||||
if(is_use_ahbe){
|
||||
// set additional header by ahbe conf
|
||||
@ -2011,7 +2271,7 @@ int S3fsCurl::PutRequest(const char* tpath, headers_t& meta, int fd, bool ow_sse
|
||||
return result;
|
||||
}
|
||||
|
||||
int S3fsCurl::PreGetObjectRequest(const char* tpath, int fd, off_t start, ssize_t size)
|
||||
int S3fsCurl::PreGetObjectRequest(const char* tpath, int fd, off_t start, ssize_t size, string& ssekeymd5)
|
||||
{
|
||||
FPRNNN("[tpath=%s][start=%jd][size=%zd]", SAFESTRPTR(tpath), (intmax_t)start, size);
|
||||
|
||||
@ -2041,6 +2301,11 @@ int S3fsCurl::PreGetObjectRequest(const char* tpath, int fd, off_t start, ssize_
|
||||
range += str(start + size - 1);
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, range.c_str());
|
||||
}
|
||||
if(0 < ssekeymd5.length()){
|
||||
if(!AddSseKeyRequestHead(ssekeymd5, false)){
|
||||
DPRNNN("Failed to insert sse(-c) header.");
|
||||
}
|
||||
}
|
||||
|
||||
if(!S3fsCurl::IsPublicBucket()){
|
||||
requestHeaders = curl_slist_sort_insert(
|
||||
@ -2063,6 +2328,7 @@ int S3fsCurl::PreGetObjectRequest(const char* tpath, int fd, off_t start, ssize_
|
||||
partdata.size = size;
|
||||
b_partdata_startpos = start;
|
||||
b_partdata_size = size;
|
||||
b_ssekey_md5 = ssekeymd5;
|
||||
|
||||
type = REQTYPE_GET;
|
||||
|
||||
@ -2078,7 +2344,13 @@ int S3fsCurl::GetObjectRequest(const char* tpath, int fd, off_t start, ssize_t s
|
||||
if(!tpath){
|
||||
return -1;
|
||||
}
|
||||
if(0 != (result = PreGetObjectRequest(tpath, fd, start, size))){
|
||||
string sseckeymd5("");
|
||||
char* psseckeymd5;
|
||||
if(NULL != (psseckeymd5 = get_object_sseckey_md5(tpath))){
|
||||
sseckeymd5 = psseckeymd5;
|
||||
free(psseckeymd5);
|
||||
}
|
||||
if(0 != (result = PreGetObjectRequest(tpath, fd, start, size, sseckeymd5))){
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -2187,7 +2459,7 @@ int S3fsCurl::ListBucketRequest(const char* tpath, const char* query)
|
||||
// Date: Mon, 1 Nov 2010 20:34:56 GMT
|
||||
// Authorization: AWS VGhpcyBtZXNzYWdlIHNpZ25lZCBieSBlbHZpbmc=
|
||||
//
|
||||
int S3fsCurl::PreMultipartPostRequest(const char* tpath, headers_t& meta, string& upload_id, bool ow_sse_flg)
|
||||
int S3fsCurl::PreMultipartPostRequest(const char* tpath, headers_t& meta, string& upload_id, bool is_copy)
|
||||
{
|
||||
FPRNNN("[tpath=%s]", SAFESTRPTR(tpath));
|
||||
|
||||
@ -2220,13 +2492,19 @@ int S3fsCurl::PreMultipartPostRequest(const char* tpath, headers_t& meta, string
|
||||
string key = (*iter).first;
|
||||
string value = (*iter).second;
|
||||
|
||||
if(key.substr(0,9) == "x-amz-acl"){
|
||||
if(0 == strcasecmp(key.substr(0,9).c_str(), "x-amz-acl")){
|
||||
// not set value, but after set it.
|
||||
}else if(key.substr(0,10) == "x-amz-meta"){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, string(key + ":" + value).c_str());
|
||||
}else if(!ow_sse_flg && key == "x-amz-server-side-encryption"){
|
||||
// If ow_sse_flg is false, SSE inherit from meta.
|
||||
}else if(0 == strcasecmp(key.substr(0,10).c_str(), "x-amz-meta")){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, string(key + ":" + value).c_str());
|
||||
}else if(0 == strcasecmp(key.c_str(), "x-amz-server-side-encryption")){
|
||||
// skip this header, because this header is specified after logic.
|
||||
}else if(0 == strcasecmp(key.c_str(), "x-amz-server-side-encryption-customer-algorithm")){
|
||||
// skip this header, because this header is specified with "x-amz-...-customer-key-md5".
|
||||
}else if(is_copy && 0 == strcasecmp(key.c_str(), "x-amz-server-side-encryption-customer-key-md5")){
|
||||
// Only copy mode.
|
||||
if(!AddSseKeyRequestHead(value, is_copy)){
|
||||
DPRNNN("Failed to insert sse(-c) header.");
|
||||
}
|
||||
}
|
||||
}
|
||||
// "x-amz-acl", rrs, sse
|
||||
@ -2234,8 +2512,13 @@ int S3fsCurl::PreMultipartPostRequest(const char* tpath, headers_t& meta, string
|
||||
if(S3fsCurl::is_use_rrs){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, "x-amz-storage-class:REDUCED_REDUNDANCY");
|
||||
}
|
||||
if(ow_sse_flg && S3fsCurl::is_use_sse){
|
||||
if(S3fsCurl::is_use_sse){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, "x-amz-server-side-encryption:AES256");
|
||||
}else if(S3fsCurl::IsSseCustomMode()){
|
||||
string md5;
|
||||
if(!AddSseKeyRequestHead(md5, false)){
|
||||
DPRNNN("Failed to insert sse(-c) header.");
|
||||
}
|
||||
}
|
||||
if(is_use_ahbe){
|
||||
// set additional header by ahbe conf
|
||||
@ -2584,12 +2867,12 @@ int S3fsCurl::CopyMultipartPostRequest(const char* from, const char* to, int par
|
||||
for(headers_t::iterator iter = meta.begin(); iter != meta.end(); ++iter){
|
||||
string key = (*iter).first;
|
||||
string value = (*iter).second;
|
||||
if(key == "Content-Type"){
|
||||
if(0 == strcasecmp(key.c_str(), "Content-Type")){
|
||||
ContentType = value;
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, string(key + ":" + value).c_str());
|
||||
}else if(key == "x-amz-copy-source"){
|
||||
}else if(0 == strcasecmp(key.c_str(), "x-amz-copy-source")){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, string(key + ":" + value).c_str());
|
||||
}else if(key == "x-amz-copy-source-range"){
|
||||
}else if(0 == strcasecmp(key.c_str(), "x-amz-copy-source-range")){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, string(key + ":" + value).c_str());
|
||||
}
|
||||
// NOTICE: x-amz-acl, x-amz-server-side-encryption is not set!
|
||||
@ -2632,7 +2915,7 @@ int S3fsCurl::CopyMultipartPostRequest(const char* from, const char* to, int par
|
||||
return result;
|
||||
}
|
||||
|
||||
int S3fsCurl::MultipartHeadRequest(const char* tpath, off_t size, headers_t& meta)
|
||||
int S3fsCurl::MultipartHeadRequest(const char* tpath, off_t size, headers_t& meta, bool is_copy)
|
||||
{
|
||||
int result;
|
||||
string upload_id;
|
||||
@ -2643,7 +2926,7 @@ int S3fsCurl::MultipartHeadRequest(const char* tpath, off_t size, headers_t& met
|
||||
|
||||
FPRNNN("[tpath=%s]", SAFESTRPTR(tpath));
|
||||
|
||||
if(0 != (result = PreMultipartPostRequest(tpath, meta, upload_id, false))){
|
||||
if(0 != (result = PreMultipartPostRequest(tpath, meta, upload_id, is_copy))){
|
||||
return result;
|
||||
}
|
||||
DestroyCurlHandle();
|
||||
@ -2669,7 +2952,7 @@ int S3fsCurl::MultipartHeadRequest(const char* tpath, off_t size, headers_t& met
|
||||
return 0;
|
||||
}
|
||||
|
||||
int S3fsCurl::MultipartUploadRequest(const char* tpath, headers_t& meta, int fd, bool ow_sse_flg)
|
||||
int S3fsCurl::MultipartUploadRequest(const char* tpath, headers_t& meta, int fd, bool is_copy)
|
||||
{
|
||||
int result;
|
||||
string upload_id;
|
||||
@ -2695,7 +2978,7 @@ int S3fsCurl::MultipartUploadRequest(const char* tpath, headers_t& meta, int fd,
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if(0 != (result = PreMultipartPostRequest(tpath, meta, upload_id, ow_sse_flg))){
|
||||
if(0 != (result = PreMultipartPostRequest(tpath, meta, upload_id, is_copy))){
|
||||
close(fd2);
|
||||
return result;
|
||||
}
|
||||
@ -2748,7 +3031,7 @@ int S3fsCurl::MultipartRenameRequest(const char* from, const char* to, headers_t
|
||||
meta["Content-Type"] = S3fsCurl::LookupMimeType(string(to));
|
||||
meta["x-amz-copy-source"] = srcresource;
|
||||
|
||||
if(0 != (result = PreMultipartPostRequest(to, meta, upload_id, false))){
|
||||
if(0 != (result = PreMultipartPostRequest(to, meta, upload_id, true))){
|
||||
return result;
|
||||
}
|
||||
DestroyCurlHandle();
|
||||
|
34
src/curl.h
34
src/curl.h
@ -100,6 +100,8 @@ class S3fsMultiCurl;
|
||||
// class S3fsCurl
|
||||
//----------------------------------------------
|
||||
typedef std::map<std::string, std::string> iamcredmap_t;
|
||||
typedef std::map<std::string, std::string> sseckeymap_t;
|
||||
typedef std::list<sseckeymap_t> sseckeylist_t;
|
||||
|
||||
// share
|
||||
#define SHARE_MUTEX_DNS 0
|
||||
@ -144,6 +146,7 @@ class S3fsCurl
|
||||
static bool is_public_bucket;
|
||||
static std::string default_acl; // TODO: to enum
|
||||
static bool is_use_rrs;
|
||||
static sseckeylist_t sseckeys;
|
||||
static bool is_use_sse;
|
||||
static bool is_content_md5;
|
||||
static bool is_verbose;
|
||||
@ -182,6 +185,8 @@ class S3fsCurl
|
||||
int b_postdata_remaining; // backup for retrying
|
||||
off_t b_partdata_startpos; // backup for retrying
|
||||
ssize_t b_partdata_size; // backup for retrying
|
||||
bool b_ssekey_pos; // backup for retrying
|
||||
std::string b_ssekey_md5; // backup for retrying
|
||||
|
||||
public:
|
||||
// constructor/destructor
|
||||
@ -214,6 +219,7 @@ class S3fsCurl
|
||||
|
||||
static bool ParseIAMCredentialResponse(const char* response, iamcredmap_t& keyval);
|
||||
static bool SetIAMCredentials(const char* response);
|
||||
static bool PushbackSseKeys(std::string& onekey);
|
||||
|
||||
// methods
|
||||
bool ResetHandle(void);
|
||||
@ -223,7 +229,7 @@ class S3fsCurl
|
||||
bool GetUploadId(std::string& upload_id);
|
||||
int GetIAMCredentials(void);
|
||||
|
||||
int PreMultipartPostRequest(const char* tpath, headers_t& meta, std::string& upload_id, bool ow_sse_flg);
|
||||
int PreMultipartPostRequest(const char* tpath, headers_t& meta, std::string& upload_id, bool is_copy);
|
||||
int CompleteMultipartPostRequest(const char* tpath, std::string& upload_id, etaglist_t& parts);
|
||||
int UploadMultipartPostSetup(const char* tpath, int part_num, std::string& upload_id);
|
||||
int UploadMultipartPostRequest(const char* tpath, int part_num, std::string& upload_id);
|
||||
@ -233,7 +239,7 @@ class S3fsCurl
|
||||
// class methods
|
||||
static bool InitS3fsCurl(const char* MimeFile = NULL);
|
||||
static bool DestroyS3fsCurl(void);
|
||||
static int ParallelMultipartUploadRequest(const char* tpath, headers_t& meta, int fd, bool ow_sse_flg);
|
||||
static int ParallelMultipartUploadRequest(const char* tpath, headers_t& meta, int fd);
|
||||
static int ParallelGetObjectRequest(const char* tpath, int fd, off_t start, ssize_t size);
|
||||
static bool CheckIAMCredentialUpdate(void);
|
||||
|
||||
@ -250,6 +256,12 @@ class S3fsCurl
|
||||
static std::string SetDefaultAcl(const char* acl);
|
||||
static bool SetUseRrs(bool flag);
|
||||
static bool GetUseRrs(void) { return S3fsCurl::is_use_rrs; }
|
||||
static bool SetSseKeys(const char* filepath);
|
||||
static bool LoadEnvSseKeys(void);
|
||||
static bool GetSseKey(std::string& md5, std::string& ssekey);
|
||||
static bool GetSseKeyMd5(int pos, std::string& md5);
|
||||
static int GetSseKeyCount(void);
|
||||
static bool IsSseCustomMode(void);
|
||||
static bool SetUseSse(bool flag);
|
||||
static bool GetUseSse(void) { return S3fsCurl::is_use_sse; }
|
||||
static bool SetContentMd5(bool flag);
|
||||
@ -272,24 +284,25 @@ class S3fsCurl
|
||||
bool CreateCurlHandle(bool force = false);
|
||||
bool DestroyCurlHandle(void);
|
||||
|
||||
bool AddSseKeyRequestHead(std::string& md5, bool is_copy);
|
||||
bool GetResponseCode(long& responseCode);
|
||||
int RequestPerform(void);
|
||||
int DeleteRequest(const char* tpath);
|
||||
bool PreHeadRequest(const char* tpath, const char* bpath = NULL, const char* savedpath = NULL);
|
||||
bool PreHeadRequest(std::string& tpath, std::string& bpath, std::string& savedpath) {
|
||||
return PreHeadRequest(tpath.c_str(), bpath.c_str(), savedpath.c_str());
|
||||
bool PreHeadRequest(const char* tpath, const char* bpath = NULL, const char* savedpath = NULL, int ssekey_pos = -1);
|
||||
bool PreHeadRequest(std::string& tpath, std::string& bpath, std::string& savedpath, int ssekey_pos = -1) {
|
||||
return PreHeadRequest(tpath.c_str(), bpath.c_str(), savedpath.c_str(), ssekey_pos);
|
||||
}
|
||||
int HeadRequest(const char* tpath, headers_t& meta);
|
||||
int PutHeadRequest(const char* tpath, headers_t& meta, bool ow_sse_flg);
|
||||
int PutRequest(const char* tpath, headers_t& meta, int fd, bool ow_sse_flg);
|
||||
int PreGetObjectRequest(const char* tpath, int fd, off_t start, ssize_t size);
|
||||
int PutHeadRequest(const char* tpath, headers_t& meta, bool is_copy);
|
||||
int PutRequest(const char* tpath, headers_t& meta, int fd);
|
||||
int PreGetObjectRequest(const char* tpath, int fd, off_t start, ssize_t size, std::string& ssekeymd5);
|
||||
int GetObjectRequest(const char* tpath, int fd, off_t start = -1, ssize_t size = -1);
|
||||
int CheckBucket(void);
|
||||
int ListBucketRequest(const char* tpath, const char* query);
|
||||
int MultipartListRequest(std::string& body);
|
||||
int AbortMultipartUpload(const char* tpath, std::string& upload_id);
|
||||
int MultipartHeadRequest(const char* tpath, off_t size, headers_t& meta);
|
||||
int MultipartUploadRequest(const char* tpath, headers_t& meta, int fd, bool ow_sse_flg);
|
||||
int MultipartHeadRequest(const char* tpath, off_t size, headers_t& meta, bool is_copy);
|
||||
int MultipartUploadRequest(const char* tpath, headers_t& meta, int fd, bool is_copy);
|
||||
int MultipartRenameRequest(const char* from, const char* to, headers_t& meta, off_t size);
|
||||
|
||||
// methods(valiables)
|
||||
@ -309,6 +322,7 @@ class S3fsCurl
|
||||
int GetMultipartRetryCount(void) const { return retry_count; }
|
||||
void SetMultipartRetryCount(int retrycnt) { retry_count = retrycnt; }
|
||||
bool IsOverMultipartRetryCount(void) const { return (retry_count >= S3fsCurl::retries); }
|
||||
int GetLastPreHeadSeecKeyPos(void) const { return b_ssekey_pos; }
|
||||
};
|
||||
|
||||
//----------------------------------------------
|
||||
|
@ -855,7 +855,7 @@ bool FdEntity::LoadFull(off_t* size, bool force_load)
|
||||
return true;
|
||||
}
|
||||
|
||||
int FdEntity::RowFlush(const char* tpath, headers_t& meta, bool ow_sse_flg, bool force_sync)
|
||||
int FdEntity::RowFlush(const char* tpath, headers_t& meta, bool force_sync)
|
||||
{
|
||||
int result;
|
||||
|
||||
@ -902,13 +902,13 @@ int FdEntity::RowFlush(const char* tpath, headers_t& meta, bool ow_sse_flg, bool
|
||||
if(120 > S3fsCurl::GetReadwriteTimeout()){
|
||||
backup = S3fsCurl::SetReadwriteTimeout(120);
|
||||
}
|
||||
result = S3fsCurl::ParallelMultipartUploadRequest(tpath ? tpath : path.c_str(), meta, fd, ow_sse_flg);
|
||||
result = S3fsCurl::ParallelMultipartUploadRequest(tpath ? tpath : path.c_str(), meta, fd);
|
||||
if(0 != backup){
|
||||
S3fsCurl::SetReadwriteTimeout(backup);
|
||||
}
|
||||
}else{
|
||||
S3fsCurl s3fscurl(true);
|
||||
result = s3fscurl.PutRequest(tpath ? tpath : path.c_str(), meta, fd, ow_sse_flg);
|
||||
result = s3fscurl.PutRequest(tpath ? tpath : path.c_str(), meta, fd);
|
||||
}
|
||||
|
||||
// seek to head of file.
|
||||
|
@ -110,8 +110,8 @@ class FdEntity
|
||||
bool SetAllDisable(void) { return SetAllStatus(false); }
|
||||
bool LoadFull(off_t* size = NULL, bool force_load = false);
|
||||
int Load(off_t start, off_t size);
|
||||
int RowFlush(const char* tpath, headers_t& meta, bool ow_sse_flg, bool force_sync = false);
|
||||
int Flush(headers_t& meta, bool ow_sse_flg, bool force_sync = false) { return RowFlush(NULL, meta, ow_sse_flg, force_sync); }
|
||||
int RowFlush(const char* tpath, headers_t& meta, bool force_sync = false);
|
||||
int Flush(headers_t& meta, bool force_sync = false) { return RowFlush(NULL, meta, force_sync); }
|
||||
ssize_t Read(char* bytes, off_t start, size_t size, bool force_load = false);
|
||||
ssize_t Write(const char* bytes, off_t start, size_t size);
|
||||
};
|
||||
|
127
src/s3fs.cpp
127
src/s3fs.cpp
@ -135,7 +135,7 @@ static xmlChar* get_base_exp(xmlDocPtr doc, const char* exp);
|
||||
static xmlChar* get_prefix(xmlDocPtr doc);
|
||||
static xmlChar* get_next_marker(xmlDocPtr doc);
|
||||
static char* get_object_name(xmlDocPtr doc, xmlNodePtr node, const char* path);
|
||||
static int put_headers(const char* path, headers_t& meta, bool ow_sse_flg);
|
||||
static int put_headers(const char* path, headers_t& meta, bool is_copy);
|
||||
static int rename_large_object(const char* from, const char* to);
|
||||
static int create_file_object(const char* path, mode_t mode, uid_t uid, gid_t gid);
|
||||
static int create_directory_object(const char* path, mode_t mode, time_t time, uid_t uid, gid_t gid);
|
||||
@ -610,6 +610,30 @@ static int check_parent_object_access(const char* path, int mask)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// This function is global, is called fom curl class(GetObject).
|
||||
//
|
||||
char* get_object_sseckey_md5(const char* path)
|
||||
{
|
||||
if(!path){
|
||||
return NULL;
|
||||
}
|
||||
headers_t meta;
|
||||
|
||||
if(0 != get_object_attribute(path, NULL, &meta)){
|
||||
DPRNNN("Failed to get object(%s) headers", path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(headers_t::iterator iter = meta.begin(); iter != meta.end(); ++iter){
|
||||
string key = (*iter).first;
|
||||
if(0 == strcasecmp(key.c_str(), "x-amz-server-side-encryption-customer-key-md5")){
|
||||
return strdup((*iter).second.c_str());
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static FdEntity* get_local_fent(const char* path, bool is_load)
|
||||
{
|
||||
struct stat stobj;
|
||||
@ -644,7 +668,7 @@ static FdEntity* get_local_fent(const char* path, bool is_load)
|
||||
* ow_sse_flg is for over writing sse header by use_sse option.
|
||||
* @return fuse return code
|
||||
*/
|
||||
static int put_headers(const char* path, headers_t& meta, bool ow_sse_flg)
|
||||
static int put_headers(const char* path, headers_t& meta, bool is_copy)
|
||||
{
|
||||
int result;
|
||||
S3fsCurl s3fscurl(true);
|
||||
@ -659,11 +683,11 @@ static int put_headers(const char* path, headers_t& meta, bool ow_sse_flg)
|
||||
|
||||
if(buf.st_size >= FIVE_GB){
|
||||
// multipart
|
||||
if(0 != (result = s3fscurl.MultipartHeadRequest(path, buf.st_size, meta))){
|
||||
if(0 != (result = s3fscurl.MultipartHeadRequest(path, buf.st_size, meta, is_copy))){
|
||||
return result;
|
||||
}
|
||||
}else{
|
||||
if(0 != (result = s3fscurl.PutHeadRequest(path, meta, ow_sse_flg))){
|
||||
if(0 != (result = s3fscurl.PutHeadRequest(path, meta, is_copy))){
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -767,7 +791,7 @@ static int create_file_object(const char* path, mode_t mode, uid_t uid, gid_t gi
|
||||
meta["x-amz-meta-mtime"] = str(time(NULL));
|
||||
|
||||
S3fsCurl s3fscurl(true);
|
||||
return s3fscurl.PutRequest(path, meta, -1, false); // fd=-1 means for creating zero byte object.
|
||||
return s3fscurl.PutRequest(path, meta, -1); // fd=-1 means for creating zero byte object.
|
||||
}
|
||||
|
||||
static int s3fs_mknod(const char *path, mode_t mode, dev_t rdev)
|
||||
@ -852,7 +876,7 @@ static int create_directory_object(const char* path, mode_t mode, time_t time, u
|
||||
meta["x-amz-meta-mtime"] = str(time);
|
||||
|
||||
S3fsCurl s3fscurl;
|
||||
return s3fscurl.PutRequest(tpath.c_str(), meta, -1, false); // fd=-1 means for creating zero byte object.
|
||||
return s3fscurl.PutRequest(tpath.c_str(), meta, -1); // fd=-1 means for creating zero byte object.
|
||||
}
|
||||
|
||||
static int s3fs_mkdir(const char* path, mode_t mode)
|
||||
@ -1014,7 +1038,7 @@ static int s3fs_symlink(const char* from, const char* to)
|
||||
return -errno;
|
||||
}
|
||||
// upload
|
||||
if(0 != (result = ent->Flush(headers, true, true))){
|
||||
if(0 != (result = ent->Flush(headers, true))){
|
||||
DPRN("could not upload tmpfile(result=%d)", result);
|
||||
}
|
||||
FdManager::get()->Close(ent);
|
||||
@ -1050,7 +1074,7 @@ static int rename_object(const char* from, const char* to)
|
||||
meta["Content-Type"] = S3fsCurl::LookupMimeType(string(to));
|
||||
meta["x-amz-metadata-directive"] = "REPLACE";
|
||||
|
||||
if(0 != (result = put_headers(to, meta, false))){
|
||||
if(0 != (result = put_headers(to, meta, true))){
|
||||
return result;
|
||||
}
|
||||
result = s3fs_unlink(from);
|
||||
@ -1091,7 +1115,7 @@ static int rename_object_nocopy(const char* from, const char* to)
|
||||
}
|
||||
|
||||
// upload
|
||||
if(0 != (result = ent->RowFlush(to, meta, false, true))){
|
||||
if(0 != (result = ent->RowFlush(to, meta, true))){
|
||||
DPRN("could not upload file(%s): result=%d", to, result);
|
||||
FdManager::get()->Close(ent);
|
||||
return result;
|
||||
@ -1391,7 +1415,7 @@ static int s3fs_chmod(const char* path, mode_t mode)
|
||||
meta["x-amz-copy-source"] = urlEncode(service_path + bucket + get_realpath(strpath.c_str()));
|
||||
meta["x-amz-metadata-directive"] = "REPLACE";
|
||||
|
||||
if(put_headers(strpath.c_str(), meta, false) != 0){
|
||||
if(put_headers(strpath.c_str(), meta, true) != 0){
|
||||
return -EIO;
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
@ -1467,7 +1491,7 @@ static int s3fs_chmod_nocopy(const char* path, mode_t mode)
|
||||
}
|
||||
|
||||
// upload
|
||||
if(0 != (result = ent->Flush(meta, false, true))){
|
||||
if(0 != (result = ent->Flush(meta, true))){
|
||||
DPRN("could not upload file(%s): result=%d", strpath.c_str(), result);
|
||||
FdManager::get()->Close(ent);
|
||||
return result;
|
||||
@ -1553,7 +1577,7 @@ static int s3fs_chown(const char* path, uid_t uid, gid_t gid)
|
||||
meta["x-amz-copy-source"] = urlEncode(service_path + bucket + get_realpath(strpath.c_str()));
|
||||
meta["x-amz-metadata-directive"] = "REPLACE";
|
||||
|
||||
if(put_headers(strpath.c_str(), meta, false) != 0){
|
||||
if(put_headers(strpath.c_str(), meta, true) != 0){
|
||||
return -EIO;
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
@ -1639,7 +1663,7 @@ static int s3fs_chown_nocopy(const char* path, uid_t uid, gid_t gid)
|
||||
}
|
||||
|
||||
// upload
|
||||
if(0 != (result = ent->Flush(meta, false, true))){
|
||||
if(0 != (result = ent->Flush(meta, true))){
|
||||
DPRN("could not upload file(%s): result=%d", strpath.c_str(), result);
|
||||
FdManager::get()->Close(ent);
|
||||
return result;
|
||||
@ -1711,7 +1735,7 @@ static int s3fs_utimens(const char* path, const struct timespec ts[2])
|
||||
meta["x-amz-copy-source"] = urlEncode(service_path + bucket + get_realpath(strpath.c_str()));
|
||||
meta["x-amz-metadata-directive"] = "REPLACE";
|
||||
|
||||
if(put_headers(strpath.c_str(), meta, false) != 0){
|
||||
if(put_headers(strpath.c_str(), meta, true) != 0){
|
||||
return -EIO;
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(nowcache);
|
||||
@ -1796,7 +1820,7 @@ static int s3fs_utimens_nocopy(const char* path, const struct timespec ts[2])
|
||||
}
|
||||
|
||||
// upload
|
||||
if(0 != (result = ent->Flush(meta, false, true))){
|
||||
if(0 != (result = ent->Flush(meta, true))){
|
||||
DPRN("could not upload file(%s): result=%d", strpath.c_str(), result);
|
||||
FdManager::get()->Close(ent);
|
||||
return result;
|
||||
@ -1847,7 +1871,7 @@ static int s3fs_truncate(const char* path, off_t size)
|
||||
}
|
||||
|
||||
// upload
|
||||
if(0 != (result = ent->Flush(meta, false, true))){
|
||||
if(0 != (result = ent->Flush(meta, true))){
|
||||
DPRN("could not upload file(%s): result=%d", path, result);
|
||||
FdManager::get()->Close(ent);
|
||||
return result;
|
||||
@ -2002,7 +2026,7 @@ static int s3fs_flush(const char* path, struct fuse_file_info* fi)
|
||||
meta["x-amz-meta-mtime"] = str(ent_mtime);
|
||||
}
|
||||
}
|
||||
result = ent->Flush(meta, true, false);
|
||||
result = ent->Flush(meta, false);
|
||||
FdManager::get()->Close(ent);
|
||||
}
|
||||
S3FS_MALLOCTRIM(0);
|
||||
@ -2078,9 +2102,23 @@ static S3fsCurl* multi_head_retry_callback(S3fsCurl* s3fscurl)
|
||||
if(!s3fscurl){
|
||||
return NULL;
|
||||
}
|
||||
int ssec_key_pos = s3fscurl->GetLastPreHeadSeecKeyPos();
|
||||
int next_retry_count = s3fscurl->GetMultipartRetryCount() + 1;
|
||||
|
||||
if(s3fscurl->IsOverMultipartRetryCount()){
|
||||
DPRN("Over retry count(%d) limit(%s).", s3fscurl->GetMultipartRetryCount(), s3fscurl->GetSpacialSavedPath().c_str());
|
||||
return NULL;
|
||||
if(S3fsCurl::IsSseCustomMode()){
|
||||
// If sse-c mode, start check not sse-c(ssec_key_pos = -1).
|
||||
// do increment ssec_key_pos for checking all sse-c key.
|
||||
next_retry_count = 0;
|
||||
ssec_key_pos++;
|
||||
if(S3fsCurl::GetSseKeyCount() <= ssec_key_pos){
|
||||
DPRN("Over retry count(%d) limit(%s).", s3fscurl->GetMultipartRetryCount(), s3fscurl->GetSpacialSavedPath().c_str());
|
||||
return NULL;
|
||||
}
|
||||
}else{
|
||||
DPRN("Over retry count(%d) limit(%s).", s3fscurl->GetMultipartRetryCount(), s3fscurl->GetSpacialSavedPath().c_str());
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
S3fsCurl* newcurl = new S3fsCurl(s3fscurl->IsUseAhbe());
|
||||
@ -2088,12 +2126,12 @@ static S3fsCurl* multi_head_retry_callback(S3fsCurl* s3fscurl)
|
||||
string base_path = s3fscurl->GetBasePath();
|
||||
string saved_path = s3fscurl->GetSpacialSavedPath();
|
||||
|
||||
if(!newcurl->PreHeadRequest(path, base_path, saved_path)){
|
||||
if(!newcurl->PreHeadRequest(path, base_path, saved_path, ssec_key_pos)){
|
||||
DPRN("Could not duplicate curl object(%s).", saved_path.c_str());
|
||||
delete newcurl;
|
||||
return NULL;
|
||||
}
|
||||
newcurl->SetMultipartRetryCount(s3fscurl->GetMultipartRetryCount() + 1);
|
||||
newcurl->SetMultipartRetryCount(next_retry_count);
|
||||
|
||||
return newcurl;
|
||||
}
|
||||
@ -2135,6 +2173,8 @@ static int readdir_multi_head(const char* path, S3ObjList& head, void* buf, fuse
|
||||
continue;
|
||||
}
|
||||
|
||||
// First check for directory, start checking "not sse-c".
|
||||
// If checking failed, retry to check with "sse-c" by retry callback func when sse-c mode.
|
||||
S3fsCurl* s3fscurl = new S3fsCurl();
|
||||
if(!s3fscurl->PreHeadRequest(disppath, (*iter), disppath)){ // target path = cache key path.(ex "dir/")
|
||||
DPRNNN("Could not make curl object for head request(%s).", disppath.c_str());
|
||||
@ -3522,22 +3562,44 @@ static int my_fuse_opt_proc(void* data, const char* arg, int key, struct fuse_ar
|
||||
return 0;
|
||||
}
|
||||
if(0 == strcmp(arg, "use_sse") || 0 == STR2NCMP(arg, "use_sse=")){
|
||||
off_t sse = 1;
|
||||
// for an old format.
|
||||
if(0 == STR2NCMP(arg, "use_sse=")){
|
||||
sse = s3fs_strtoofft(strchr(arg, '=') + sizeof(char));
|
||||
}
|
||||
if(0 == sse){
|
||||
S3fsCurl::SetUseSse(false);
|
||||
}else if(1 == sse){
|
||||
if(S3fsCurl::GetUseRrs()){
|
||||
fprintf(stderr, "%s: use_sse option could not be specified with use_rrs.\n", program_name.c_str());
|
||||
return -1;
|
||||
}
|
||||
S3fsCurl::SetUseSse(true);
|
||||
const char* ssecfile = &arg[strlen("use_sse=")];
|
||||
if(0 == strcmp(ssecfile, "1")){
|
||||
if(S3fsCurl::IsSseCustomMode()){
|
||||
fprintf (stderr, "%s: already set SSE-C key by environment, and confrict use_sse option.\n", program_name.c_str());
|
||||
return -1;
|
||||
}
|
||||
S3fsCurl::SetUseSse(true);
|
||||
}else{
|
||||
// testing sse-c, try to load AES256 keys
|
||||
struct stat st;
|
||||
if(0 != stat(ssecfile, &st)){
|
||||
fprintf (stderr, "%s: could not open use_sse keys file(%s)\n", program_name.c_str(), ssecfile);
|
||||
return -1;
|
||||
}
|
||||
if(st.st_mode & (S_IXUSR | S_IRWXG | S_IRWXO)){
|
||||
fprintf (stderr, "%s: use_sse keys file %s should be 0600 permissions\n", program_name.c_str(), ssecfile);
|
||||
return -1;
|
||||
}
|
||||
if(!S3fsCurl::SetSseKeys(ssecfile)){
|
||||
fprintf (stderr, "%s: failed to load use_sse keys file %s\n", program_name.c_str(), ssecfile);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
fprintf(stderr, "%s: poorly formed argument to option: use_sse\n", program_name.c_str());
|
||||
return -1;
|
||||
if(S3fsCurl::GetUseRrs()){
|
||||
fprintf(stderr, "%s: use_sse option could not be specified with use_rrs.\n", program_name.c_str());
|
||||
return -1;
|
||||
}
|
||||
if(S3fsCurl::IsSseCustomMode()){
|
||||
fprintf (stderr, "%s: already set SSE-C key by environment, and confrict use_sse option.\n", program_name.c_str());
|
||||
return -1;
|
||||
}
|
||||
S3fsCurl::SetUseSse(true);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -3790,6 +3852,9 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
}
|
||||
|
||||
// Load SSE-C Key from env
|
||||
S3fsCurl::LoadEnvSseKeys();
|
||||
|
||||
// clear this structure
|
||||
memset(&s3fs_oper, 0, sizeof(s3fs_oper));
|
||||
|
||||
|
@ -65,4 +65,6 @@
|
||||
|
||||
#endif // HAVE_MALLOC_TRIM
|
||||
|
||||
char* get_object_sseckey_md5(const char* path);
|
||||
|
||||
#endif // S3FS_S3_H_
|
||||
|
@ -875,7 +875,24 @@ void show_help (void)
|
||||
" - this option makes Amazon's Reduced Redundancy Storage enable.\n"
|
||||
"\n"
|
||||
" use_sse (default is disable)\n"
|
||||
" - this option makes Amazon's Server Site Encryption enable.\n"
|
||||
" - use Amazon<6F>fs Server-Site Encryption or Server-Side Encryption\n"
|
||||
" with Customer-Provided Encryption Keys.\n"
|
||||
" this option can not be specified with use_rrs. specifying only \n"
|
||||
" \"use_sse\" or \"use_sse=1\" enables Server-Side Encryption.\n"
|
||||
" (use_sse=1 for old version)\n"
|
||||
" specifying this option with file path which has some SSE-C\n"
|
||||
" secret key enables Server-Side Encryption with Customer-Provided\n"
|
||||
" Encryption Keys.(use_sse=file)\n"
|
||||
" the file must be 600 permission. the file can have some lines,\n"
|
||||
" each line is one SSE-C key. the first line in file is used as\n"
|
||||
" Customer-Provided Encryption Keys for uploading and changing\n"
|
||||
" headers etc.\n"
|
||||
" if there are some keys after first line, those are used\n"
|
||||
" downloading object which are encripted by not first key.\n"
|
||||
" so that, you can keep all SSE-C keys in file, that is SSE-C\n"
|
||||
" key history.\n"
|
||||
" if AWSSSECKEYS environment is set, you can set SSE-C key instead\n"
|
||||
" of this option.\n"
|
||||
"\n"
|
||||
" public_bucket (default=\"\" which means disabled)\n"
|
||||
" - anonymously mount a public bucket when set to 1\n"
|
||||
|
Loading…
Reference in New Issue
Block a user