diff --git a/doc/man/s3fs.1 b/doc/man/s3fs.1 index 7f76fb9..635f5f7 100644 --- a/doc/man/s3fs.1 +++ b/doc/man/s3fs.1 @@ -337,6 +337,9 @@ When s3fs catch the signal SIGUSR2, the debug level is bumpup. .TP \fB\-o\fR curldbg - put curl debug message Put the debug message from libcurl when this option is specified. +Specify "normal" or "body" for the parameter. +If the parameter is omitted, it is the same as "normal". +If "body" is specified, some API communication body data will be output in addition to the debug message output as "normal". .SS "utility mode options" .TP \fB\-u\fR or \fB\-\-incomplete\-mpu\-list\fR diff --git a/src/common.h b/src/common.h index 63f32e6..a740f18 100644 --- a/src/common.h +++ b/src/common.h @@ -97,6 +97,15 @@ enum s3fs_log_level{ } \ }while(0) +#define S3FS_LOW_CURLDBG(fmt, ...) \ + do{ \ + if(foreground){ \ + fprintf(stdout, "[CURL DBG] " fmt "%s\n", __VA_ARGS__); \ + }else{ \ + syslog(S3FS_LOG_LEVEL_TO_SYSLOG(S3FS_LOG_CRIT), "%s" fmt "%s", instance_name.c_str(), __VA_ARGS__); \ + } \ + }while(0) + #define S3FS_LOW_LOGPRN_EXIT(fmt, ...) \ do{ \ if(foreground){ \ @@ -130,7 +139,7 @@ enum s3fs_log_level{ #define S3FS_PRN_INFO1(fmt, ...) S3FS_LOW_LOGPRN2(S3FS_LOG_INFO, 1, fmt, ##__VA_ARGS__, "") #define S3FS_PRN_INFO2(fmt, ...) S3FS_LOW_LOGPRN2(S3FS_LOG_INFO, 2, fmt, ##__VA_ARGS__, "") #define S3FS_PRN_INFO3(fmt, ...) S3FS_LOW_LOGPRN2(S3FS_LOG_INFO, 3, fmt, ##__VA_ARGS__, "") -#define S3FS_PRN_CURL(fmt, ...) S3FS_LOW_LOGPRN2(S3FS_LOG_CRIT, 0, fmt, ##__VA_ARGS__, "") +#define S3FS_PRN_CURL(fmt, ...) S3FS_LOW_CURLDBG(fmt, ##__VA_ARGS__, "") // // Typedef diff --git a/src/curl.cpp b/src/curl.cpp index f3cbb7e..4662865 100644 --- a/src/curl.cpp +++ b/src/curl.cpp @@ -154,6 +154,29 @@ static string tolower_header_name(const char* head) } #endif +static const char* getCurlDebugHead(curl_infotype type) +{ + const char* unknown = ""; + const char* dataIn = "BODY <"; + const char* dataOut = "BODY >"; + const char* headIn = "<"; + const char* headOut = ">"; + + switch(type){ + case CURLINFO_DATA_IN: + return dataIn; + case CURLINFO_DATA_OUT: + return dataOut; + case CURLINFO_HEADER_IN: + return headIn; + case CURLINFO_HEADER_OUT: + return headOut; + default: + break; + } + return unknown; +} + //------------------------------------------------------------------- // Class BodyData //------------------------------------------------------------------- @@ -383,6 +406,7 @@ std::string S3fsCurl::ssekmsid; sse_type_t S3fsCurl::ssetype = SSE_DISABLE; bool S3fsCurl::is_content_md5 = false; bool S3fsCurl::is_verbose = false; +bool S3fsCurl::is_dump_body = false; string S3fsCurl::AWSAccessKeyId; string S3fsCurl::AWSSecretAccessKey; string S3fsCurl::AWSAccessToken; @@ -1240,6 +1264,13 @@ bool S3fsCurl::SetVerbose(bool flag) return old; } +bool S3fsCurl::SetDumpBody(bool flag) +{ + bool old = S3fsCurl::is_dump_body; + S3fsCurl::is_dump_body = flag; + return old; +} + bool S3fsCurl::SetAccessKey(const char* AccessKeyId, const char* SecretAccessKey) { if((!S3fsCurl::is_ibm_iam_auth && (!AccessKeyId || '\0' == AccessKeyId[0])) || !SecretAccessKey || '\0' == SecretAccessKey[0]){ @@ -2004,6 +2035,21 @@ bool S3fsCurl::AddUserAgent(CURL* hCurl) } int S3fsCurl::CurlDebugFunc(CURL* hcurl, curl_infotype type, char* data, size_t size, void* userptr) +{ + return S3fsCurl::RawCurlDebugFunc(hcurl, type, data, size, userptr, CURLINFO_END); +} + +int S3fsCurl::CurlDebugBodyInFunc(CURL* hcurl, curl_infotype type, char* data, size_t size, void* userptr) +{ + return S3fsCurl::RawCurlDebugFunc(hcurl, type, data, size, userptr, CURLINFO_DATA_IN); +} + +int S3fsCurl::CurlDebugBodyOutFunc(CURL* hcurl, curl_infotype type, char* data, size_t size, void* userptr) +{ + return S3fsCurl::RawCurlDebugFunc(hcurl, type, data, size, userptr, CURLINFO_DATA_OUT); +} + +int S3fsCurl::RawCurlDebugFunc(CURL* hcurl, curl_infotype type, char* data, size_t size, void* userptr, curl_infotype datatype) { if(!hcurl){ // something wrong... @@ -2019,8 +2065,17 @@ int S3fsCurl::CurlDebugFunc(CURL* hcurl, curl_infotype type, char* data, size_t size--; data++; } + if(foreground && 0 < size && '\n' == data[size - 1]){ + size--; + } S3FS_PRN_CURL("* %*s%.*s", indent, "", (int)size, data); break; + case CURLINFO_DATA_IN: + case CURLINFO_DATA_OUT: + if(type != datatype || !S3fsCurl::is_dump_body){ + // not put + break; + } case CURLINFO_HEADER_IN: case CURLINFO_HEADER_OUT: size_t remaining; @@ -2042,13 +2097,11 @@ int S3fsCurl::CurlDebugFunc(CURL* hcurl, curl_infotype type, char* data, size_t eol++; } size_t length = eol - p; - S3FS_PRN_CURL("%c %.*s", CURLINFO_HEADER_IN == type ? '<' : '>', (int)length - newline, p); + S3FS_PRN_CURL("%s %.*s", getCurlDebugHead(type), (int)length - newline, p); remaining -= length; p = eol; } while (p != NULL && remaining > 0); break; - case CURLINFO_DATA_IN: - case CURLINFO_DATA_OUT: case CURLINFO_SSL_DATA_IN: case CURLINFO_SSL_DATA_OUT: // not put @@ -2118,9 +2171,7 @@ bool S3fsCurl::ResetHandle() } if(S3fsCurl::is_verbose){ curl_easy_setopt(hCurl, CURLOPT_VERBOSE, true); - if(!foreground){ - curl_easy_setopt(hCurl, CURLOPT_DEBUGFUNCTION, S3fsCurl::CurlDebugFunc); - } + curl_easy_setopt(hCurl, CURLOPT_DEBUGFUNCTION, S3fsCurl::CurlDebugFunc); } if(!cipher_suites.empty()) { curl_easy_setopt(hCurl, CURLOPT_SSL_CIPHER_LIST, cipher_suites.c_str()); @@ -3529,6 +3580,9 @@ int S3fsCurl::ListBucketRequest(const char* tpath, const char* query) curl_easy_setopt(hCurl, CURLOPT_URL, url.c_str()); curl_easy_setopt(hCurl, CURLOPT_WRITEDATA, (void*)&bodydata); curl_easy_setopt(hCurl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); + if(S3fsCurl::is_verbose){ + curl_easy_setopt(hCurl, CURLOPT_DEBUGFUNCTION, S3fsCurl::CurlDebugBodyInFunc); // replace debug function + } S3fsCurl::AddUserAgent(hCurl); // put User-Agent return RequestPerform(); @@ -3708,6 +3762,9 @@ int S3fsCurl::CompleteMultipartPostRequest(const char* tpath, const string& uplo curl_easy_setopt(hCurl, CURLOPT_POSTFIELDSIZE, static_cast(postdata_remaining)); curl_easy_setopt(hCurl, CURLOPT_READDATA, (void*)this); curl_easy_setopt(hCurl, CURLOPT_READFUNCTION, S3fsCurl::ReadCallback); + if(S3fsCurl::is_verbose){ + curl_easy_setopt(hCurl, CURLOPT_DEBUGFUNCTION, S3fsCurl::CurlDebugBodyOutFunc); // replace debug function + } S3fsCurl::AddUserAgent(hCurl); // put User-Agent // request diff --git a/src/curl.h b/src/curl.h index 44dc0c3..99f3859 100644 --- a/src/curl.h +++ b/src/curl.h @@ -279,6 +279,7 @@ class S3fsCurl static sse_type_t ssetype; static bool is_content_md5; static bool is_verbose; + static bool is_dump_body; static std::string AWSAccessKeyId; static std::string AWSSecretAccessKey; static std::string AWSAccessToken; @@ -386,6 +387,9 @@ class S3fsCurl static bool AddUserAgent(CURL* hCurl); static int CurlDebugFunc(CURL* hcurl, curl_infotype type, char* data, size_t size, void* userptr); + static int CurlDebugBodyInFunc(CURL* hcurl, curl_infotype type, char* data, size_t size, void* userptr); + static int CurlDebugBodyOutFunc(CURL* hcurl, curl_infotype type, char* data, size_t size, void* userptr); + static int RawCurlDebugFunc(CURL* hcurl, curl_infotype type, char* data, size_t size, void* userptr, curl_infotype datatype); // methods bool ResetHandle(void); @@ -448,6 +452,8 @@ class S3fsCurl static bool SetContentMd5(bool flag); static bool SetVerbose(bool flag); static bool GetVerbose(void) { return S3fsCurl::is_verbose; } + static bool SetDumpBody(bool flag); + static bool IsDumpBody(void) { return S3fsCurl::is_dump_body; } static bool SetAccessKey(const char* AccessKeyId, const char* SecretAccessKey); static bool SetAccessKeyWithSessionToken(const char* AccessKeyId, const char* SecretAccessKey, const char * SessionToken); static bool IsSetAccessKeyID(void){ diff --git a/src/s3fs.cpp b/src/s3fs.cpp index 4b107b4..e9d4d54 100644 --- a/src/s3fs.cpp +++ b/src/s3fs.cpp @@ -5077,6 +5077,18 @@ static int my_fuse_opt_proc(void* data, const char* arg, int key, struct fuse_ar if(0 == strcmp(arg, "curldbg")){ S3fsCurl::SetVerbose(true); return 0; + }else if(0 == STR2NCMP(arg, "curldbg=")){ + const char* strlevel = strchr(arg, '=') + sizeof(char); + if(0 == strcasecmp(strlevel, "normal")){ + S3fsCurl::SetVerbose(true); + }else if(0 == strcasecmp(strlevel, "body")){ + S3fsCurl::SetVerbose(true); + S3fsCurl::SetDumpBody(true); + }else{ + S3FS_PRN_EXIT("option curldbg has unknown parameter(%s).", strlevel); + return -1; + } + return 0; } if(0 == STR2NCMP(arg, "accessKeyId=")){ diff --git a/src/s3fs_util.cpp b/src/s3fs_util.cpp index 06b5218..de97f4a 100644 --- a/src/s3fs_util.cpp +++ b/src/s3fs_util.cpp @@ -1497,6 +1497,10 @@ void show_help () "\n" " curldbg - put curl debug message\n" " Put the debug message from libcurl when this option is specified.\n" + " Specify \"normal\" or \"body\" for the parameter.\n" + " If the parameter is omitted, it is the same as \"normal\".\n" + " If \"body\" is specified, some API communication body data will be\n" + " output in addition to the debug message output as \"normal\".\n" "\n" "FUSE/mount Options:\n" "\n"