@@ -538,6 +538,8 @@ static int redirect_endpoint(hFILE_s3 *fp, kstring_t *header) {
538538 }
539539 }
540540
541+ if (hts_verbose >= HTS_LOG_INFO ) fprintf (stderr , "hfile_s3: redirect_endpoint: return %d\n" , ret );
542+
541543 return ret ;
542544}
543545
@@ -1120,9 +1122,9 @@ static int set_region(s3_auth_data *ad, kstring_t *region) {
11201122// Some common code
11211123
11221124#define S3_MOVED_PERMANENTLY 301
1125+ #define S3_TEMPORARY_REDIRECT 307
11231126#define S3_BAD_REQUEST 400
11241127
1125-
11261128static struct {
11271129 kstring_t useragent ;
11281130 CURLSH * share ;
@@ -1178,7 +1180,7 @@ static char *stristr(char *haystack, char *needle) {
11781180 char * h = haystack ;
11791181 char * n = needle ;
11801182
1181- while (toupper (* h ) == toupper (* n )) {
1183+ while (toupper_c (* h ) == toupper_c (* n )) {
11821184 h ++ , n ++ ;
11831185 if (!* h || !* n ) break ;
11841186 }
@@ -1319,6 +1321,15 @@ static struct curl_slist *set_html_headers(hFILE_s3 *fp, kstring_t *auth, kstrin
13191321 struct curl_slist * headers = NULL ;
13201322 int err = 0 ;
13211323
1324+ /* The next two lines have the effect of preventing curl from
1325+ adding these headers. If they exist it can lead to conflicts
1326+ in the signature calculations (not present in all S3 systems).
1327+ */
1328+ err = add_header (& headers , "Content-Type:" );
1329+ err |= add_header (& headers , "Expect:" );
1330+
1331+ if (err ) goto error ;
1332+
13221333 if (auth -> l )
13231334 if ((err = add_header (& headers , auth -> s )))
13241335 goto error ;
@@ -1407,11 +1418,13 @@ uploads and abandon the upload process.
14071418static int abort_upload (hFILE_s3 * fp ) {
14081419 kstring_t url = KS_INITIALIZE ;
14091420 kstring_t canonical_query_string = KS_INITIALIZE ;
1410- int ret = -1 ;
1421+ int ret = -1 , save_errno ;
14111422 struct curl_slist * headers = NULL ;
14121423 char http_request [] = "DELETE" ;
14131424 CURLcode err ;
14141425
1426+ save_errno = errno ; // keep the errno that caused the need to abort
1427+
14151428 clear_authorisation_values (fp );
14161429
14171430 if (ksprintf (& canonical_query_string , "uploadId=%s" , fp -> upload_id .s ) < 0 ) {
@@ -1459,6 +1472,7 @@ static int abort_upload(hFILE_s3 *fp) {
14591472 fp -> aborted = 1 ;
14601473 cleanup (fp );
14611474
1475+ errno = save_errno ;
14621476 return ret ;
14631477}
14641478
@@ -1497,6 +1511,7 @@ static int complete_upload(hFILE_s3 *fp, kstring_t *resp) {
14971511 curl_easy_reset (fp -> curl );
14981512
14991513 err = curl_easy_setopt (fp -> curl , CURLOPT_POST , 1L );
1514+
15001515 err |= curl_easy_setopt (fp -> curl , CURLOPT_POSTFIELDS , fp -> completion_message .s );
15011516 err |= curl_easy_setopt (fp -> curl , CURLOPT_POSTFIELDSIZE , (long ) fp -> completion_message .l );
15021517 err |= curl_easy_setopt (fp -> curl , CURLOPT_WRITEFUNCTION , response_callback );
@@ -1670,6 +1685,7 @@ static int s3_write_close(hFILE *fpv) {
16701685 kstring_t response = {0 , 0 , NULL };
16711686 int ret = 0 ;
16721687 CURLcode cret ;
1688+ long response_code ;
16731689
16741690 if (!fp -> aborted ) {
16751691
@@ -1679,7 +1695,6 @@ static int s3_write_close(hFILE *fpv) {
16791695 ret = upload_part (fp , & response );
16801696
16811697 if (!ret ) {
1682- long response_code ;
16831698 kstring_t etag = {0 , 0 , NULL };
16841699
16851700 cret = curl_easy_getinfo (fp -> curl , CURLINFO_RESPONSE_CODE , & response_code );
@@ -1715,6 +1730,17 @@ static int s3_write_close(hFILE *fpv) {
17151730 if (!ret ) {
17161731 if (strstr (response .s , "CompleteMultipartUploadResult" ) == NULL ) {
17171732 ret = -1 ;
1733+ cret = curl_easy_getinfo (fp -> curl , CURLINFO_RESPONSE_CODE , & response_code );
1734+
1735+ if (cret == CURLE_OK ) {
1736+ if (hts_verbose >= HTS_LOG_INFO ) {
1737+ if (report_s3_error (& response , response_code )) {
1738+ fprintf (stderr , "hfile_s3: warning, unable to report full S3 error status.\n" );
1739+ }
1740+ }
1741+
1742+ errno = http_status_errno (response_code );
1743+ }
17181744 }
17191745 }
17201746 } else {
@@ -1746,6 +1772,8 @@ static int handle_bad_request(hFILE_s3 *fp, kstring_t *resp) {
17461772
17471773 ks_free (& region );
17481774
1775+ if (hts_verbose >= HTS_LOG_INFO ) fprintf (stderr , "hfile_s3: handle_bad_request: return %d\n" , ret );
1776+
17491777 return ret ;
17501778}
17511779
@@ -1852,14 +1880,13 @@ static int get_part(hFILE_s3 *fp, kstring_t *resp) {
18521880 struct curl_slist * headers = NULL ;
18531881 int ret = -1 ;
18541882 char http_request [] = "GET" ;
1855- char canonical_query_string = 0 ;
18561883 CURLcode err ;
18571884
18581885 ks_clear (& fp -> buffer ); // reset storage buffer
18591886 clear_authorisation_values (fp );
18601887
18611888 if (fp -> au -> is_v4 ) {
1862- if (v4_authorisation (fp , http_request , NULL , & canonical_query_string , 0 ) != 0 ) {
1889+ if (v4_authorisation (fp , http_request , NULL , "" , 0 ) != 0 ) {
18631890 goto out ;
18641891 }
18651892
@@ -2077,7 +2104,7 @@ static hFILE *s3_write_open(const char *url, s3_auth_data *auth) {
20772104 hFILE_s3 * fp ;
20782105 kstring_t response = {0 , 0 , NULL };
20792106 kstring_t header = {0 , 0 , NULL };
2080- int ret , has_user_query = 0 ;
2107+ int has_user_query = 0 ;
20812108 char * query_start ;
20822109 const char * env ;
20832110 CURLcode cret ;
@@ -2125,30 +2152,35 @@ static hFILE *s3_write_open(const char *url, s3_auth_data *auth) {
21252152 has_user_query = 1 ;;
21262153 }
21272154
2128- ret = initialise_upload (fp , & header , & response , has_user_query );
2155+ if (initialise_upload (fp , & header , & response , has_user_query ))
2156+ goto error ;
2157+
21292158 cret = curl_easy_getinfo (fp -> curl , CURLINFO_RESPONSE_CODE , & response_code );
21302159
2131- if (ret == 0 ) {
2132- if (cret == CURLE_OK ) {
2133- if (response_code == S3_MOVED_PERMANENTLY ) {
2134- if (redirect_endpoint (fp , & header ) == 0 ) {
2135- ks_clear (& response );
2136- ks_clear (& header );
2160+ if (cret == CURLE_OK ) {
2161+ if (response_code == S3_MOVED_PERMANENTLY || response_code == S3_TEMPORARY_REDIRECT ) {
2162+ if (redirect_endpoint (fp , & header ) == 0 ) {
2163+ ks_clear (& response );
2164+ ks_clear (& header );
21372165
2138- ret = initialise_upload (fp , & header , & response , has_user_query );
2139- }
2140- } else if (response_code == S3_BAD_REQUEST ) {
2141- if (handle_bad_request (fp , & response ) == 0 ) {
2142- ks_clear (& response );
2143- ks_clear (& header );
2166+ if (initialise_upload (fp , & header , & response , has_user_query ))
2167+ goto error ;
2168+ }
2169+ } else if (response_code == S3_BAD_REQUEST ) {
2170+ if (handle_bad_request (fp , & response ) == 0 ) {
2171+ ks_clear (& response );
2172+ ks_clear (& header );
21442173
2145- ret = initialise_upload (fp , & header , & response , has_user_query );
2146- }
2174+ if ( initialise_upload (fp , & header , & response , has_user_query ))
2175+ goto error ;
21472176 }
2148- } else {
2149- // unable to get a response code from curl
2150- ret = -1 ;
21512177 }
2178+
2179+ // reget the response code (may not have changed)
2180+ cret = curl_easy_getinfo (fp -> curl , CURLINFO_RESPONSE_CODE , & response_code );
2181+ } else {
2182+ // unable to get a response code from curl
2183+ goto error ;
21522184 }
21532185
21542186 if (response_code >= 300 ) {
@@ -2164,11 +2196,9 @@ static hFILE *s3_write_open(const char *url, s3_auth_data *auth) {
21642196 errno = http_status_errno (response_code );
21652197 }
21662198
2167- ret = -1 ;
2199+ goto error ;
21682200 }
21692201
2170- if (ret ) goto error ;
2171-
21722202 if (get_upload_id (fp , & response )) goto error ;
21732203
21742204 // start the completion message (a formatted list of parts)
@@ -2203,7 +2233,6 @@ static hFILE *s3_read_open(const char *url, s3_auth_data *auth) {
22032233 const char * env ;
22042234 kstring_t response = {0 , 0 , NULL };
22052235 kstring_t file_range = {0 , 0 , NULL };
2206- int ret ;
22072236 CURLcode cret ;
22082237 long response_code = 0 ;
22092238
@@ -2240,31 +2269,33 @@ static hFILE *s3_read_open(const char *url, s3_auth_data *auth) {
22402269
22412270 kputs (url , & fp -> url );
22422271
2243- ret = initialise_download (fp , & response );
2244- cret = curl_easy_getinfo ( fp -> curl , CURLINFO_RESPONSE_CODE , & response_code ) ;
2272+ if ( initialise_download (fp , & response ))
2273+ goto error ;
22452274
2246- if (ret == 0 ) {
2247- if (cret == CURLE_OK ) {
2248- if (response_code == S3_MOVED_PERMANENTLY ) {
2249- ks_clear (& response );
2275+ cret = curl_easy_getinfo (fp -> curl , CURLINFO_RESPONSE_CODE , & response_code );
22502276
2251- if (redirect_endpoint (fp , & response ) == 0 ) {
2252- ret = initialise_download (fp , & response );
2253- }
2254- } else if (response_code == S3_BAD_REQUEST ) {
2255- ks_clear (& response );
2277+ if (cret == CURLE_OK ) {
2278+ if (response_code == S3_MOVED_PERMANENTLY || response_code == S3_TEMPORARY_REDIRECT ) {
2279+ ks_clear (& response );
22562280
2257- if (handle_bad_request (fp , & fp -> buffer ) == 0 ) {
2258- ret = initialise_download (fp , & response );
2259- }
2281+ if (redirect_endpoint (fp , & response ) == 0 ) {
2282+ if ( initialise_download (fp , & response ))
2283+ goto error ;
22602284 }
2285+ } else if (response_code == S3_BAD_REQUEST ) {
2286+ ks_clear (& response );
22612287
2262- // reget the response code (may not have changed)
2263- cret = curl_easy_getinfo (fp -> curl , CURLINFO_RESPONSE_CODE , & response_code );
2264- } else {
2265- // unable to get a response code from curl
2266- ret = -1 ;
2288+ if (handle_bad_request (fp , & fp -> buffer ) == 0 ) {
2289+ if (initialise_download (fp , & response ))
2290+ goto error ;
2291+ }
22672292 }
2293+
2294+ // reget the response code (may not have changed)
2295+ cret = curl_easy_getinfo (fp -> curl , CURLINFO_RESPONSE_CODE , & response_code );
2296+ } else {
2297+ // unable to get a response code from curl
2298+ goto error ;
22682299 }
22692300
22702301 if (response_code >= 300 ) {
@@ -2280,11 +2311,9 @@ static hFILE *s3_read_open(const char *url, s3_auth_data *auth) {
22802311 errno = http_status_errno (response_code );
22812312 }
22822313
2283- ret = -1 ;
2314+ goto error ;
22842315 }
22852316
2286- if (ret ) goto error ;
2287-
22882317 if (get_entry (response .s , "content-range: bytes " , "\n" , & file_range ) == EOF ) {
22892318 fprintf (stderr , "hfile_s3: warning: failed to read file size.\n" );
22902319 fp -> file_size = -1 ;
@@ -2373,7 +2402,7 @@ static hFILE *hopen_s3(const char *url, const char *mode)
23732402{
23742403 hFILE * fp ;
23752404
2376- if (getenv ("HTS_S3_V2" ) == NULL ) { // Force the v2 signature code
2405+ if (getenv ("HTS_S3_V2" ) == NULL ) {
23772406 fp = s3_open_v4 (url , mode , NULL );
23782407 } else {
23792408 fp = s3_open_v2 (url , mode , NULL );
0 commit comments