@@ -73,6 +73,11 @@ struct sigaction cleanup_action, default_action;
73
73
char * file_to_delete_if_ctrl_C ;
74
74
#endif
75
75
76
+ struct LOCFILE_FP {
77
+ char * file ; /* Pointer to file name */
78
+ FILE * fp ; /* Open file pointer */
79
+ };
80
+
76
81
GMT_LOCAL void gmtremote_delete_file_then_exit (int sig_no ) {
77
82
/* If we catch a CTRL-C during CURL download we must assume file is corrupted and remove it before exiting */
78
83
gmt_M_unused (sig_no );
@@ -457,7 +462,7 @@ GMT_LOCAL int gmtremote_find_and_give_data_attribution (struct GMTAPI_CTRL *API,
457
462
return (match );
458
463
}
459
464
460
- GMT_LOCAL char * gmtremote_lockfile (struct GMTAPI_CTRL * API , char * file ) {
465
+ GMT_LOCAL char * gmtremote_lockfile (struct GMT_CTRL * GMT , char * file ) {
461
466
/* Create a dummy file in temp with extension .download and use as a lock file */
462
467
char * c = strrchr (file , '/' );
463
468
char Lfile [PATH_MAX ] = {"" };
@@ -466,7 +471,7 @@ GMT_LOCAL char *gmtremote_lockfile (struct GMTAPI_CTRL *API, char *file) {
466
471
else /* No path, just point to file */
467
472
c = file ;
468
473
if (c [0 ] == '@' ) c ++ ; /* Skip any leading @ sign */
469
- sprintf (Lfile , "%s/%s.download" , API -> tmp_dir , c );
474
+ sprintf (Lfile , "%s/%s.download" , GMT -> parent -> tmp_dir , c );
470
475
return (strdup (Lfile ));
471
476
}
472
477
@@ -515,68 +520,103 @@ GMT_LOCAL size_t gmtremote_skip_large_files (struct GMT_CTRL *GMT, char * URL, s
515
520
return action ;
516
521
}
517
522
518
- /* Deal with hash values of cache/data files */
519
-
520
- #define GMT_HASH_TIME_OUT 10L /* Not waiting longer than this to time out on getting the hash file */
521
-
522
- GMT_LOCAL int gmtremote_get_url (struct GMT_CTRL * GMT , char * url , char * file , char * orig , unsigned int index ) {
523
- bool query = gmt_M_file_is_query (url ), turn_off = false;
524
- int curl_err = 0 , error = 0 ;
525
- long time_spent ;
526
- char * Lfile = NULL ;
527
- FILE * fp = NULL ;
523
+ CURL * gmtremote_setup_curl (struct GMTAPI_CTRL * API , char * url , char * local_file , struct FtpFile * urlfile , unsigned int time_out ) {
524
+ /* Single function that sets up an impending CURL operation */
528
525
CURL * Curl = NULL ;
529
- struct FtpFile urlfile = {NULL , NULL };
530
- struct GMTAPI_CTRL * API = GMT -> parent ;
531
- time_t begin , end ;
532
-
533
- if (!query ) { /* Only make a filename if not a query */
534
- Lfile = gmtremote_lockfile (API , file );
535
- if ((fp = fopen (Lfile , "w" )) == NULL ) {
536
- GMT_Report (API , GMT_MSG_ERROR , "Failed to create lock file %s\n" , Lfile );
537
- gmt_M_str_free (Lfile );
538
- return 1 ;
539
- }
540
- gmtlib_file_lock (GMT , fileno (fp )); /* Attempt exclusive lock */
541
- }
542
-
543
526
if ((Curl = curl_easy_init ()) == NULL ) {
544
- GMT_Report (GMT -> parent , GMT_MSG_ERROR , "Failed to initiate curl - cannot obtain %s\n" , url );
545
- error = 1 ; goto unlocking1 ;
527
+ GMT_Report (API , GMT_MSG_ERROR , "Failed to initiate curl - cannot obtain %s\n" , url );
528
+ return NULL ;
546
529
}
547
530
if (curl_easy_setopt (Curl , CURLOPT_SSL_VERIFYPEER , 0L )) { /* Tell libcurl to not verify the peer */
548
- GMT_Report (GMT -> parent , GMT_MSG_ERROR , "Failed to set curl option to not verify the peer\n" );
549
- error = 1 ; goto unlocking1 ;
531
+ GMT_Report (API , GMT_MSG_ERROR , "Failed to set curl option to not verify the peer\n" );
532
+ return NULL ;
550
533
}
551
534
if (curl_easy_setopt (Curl , CURLOPT_FOLLOWLOCATION , 1L )) { /* Tell libcurl to follow 30x redirects */
552
- GMT_Report (GMT -> parent , GMT_MSG_ERROR , "Failed to set curl option to follow redirects\n" );
553
- error = 1 ; goto unlocking1 ;
535
+ GMT_Report (API , GMT_MSG_ERROR , "Failed to set curl option to follow redirects\n" );
536
+ return NULL ;
554
537
}
555
538
if (curl_easy_setopt (Curl , CURLOPT_FAILONERROR , 1L )) { /* Tell libcurl to fail on 4xx responses (e.g. 404) */
556
- GMT_Report (GMT -> parent , GMT_MSG_ERROR , "Failed to set curl option to fail for 4xx responses\n" );
557
- error = 1 ; goto unlocking1 ;
539
+ GMT_Report (API , GMT_MSG_ERROR , "Failed to set curl option to fail for 4xx responses\n" );
540
+ return NULL ;
558
541
}
559
542
if (curl_easy_setopt (Curl , CURLOPT_URL , url )) { /* Set the URL to copy */
560
- GMT_Report (GMT -> parent , GMT_MSG_ERROR , "Failed to set curl option to read from %s\n" , url );
561
- error = 1 ; goto unlocking1 ;
543
+ GMT_Report (API , GMT_MSG_ERROR , "Failed to set curl option to read from %s\n" , url );
544
+ return NULL ;
562
545
}
563
- if (curl_easy_setopt (Curl , CURLOPT_TIMEOUT , GMT_HASH_TIME_OUT )) { /* Set a max timeout */
564
- GMT_Report (GMT -> parent , GMT_MSG_ERROR , "Failed to set curl option to time out after %ld seconds\n" , GMT_HASH_TIME_OUT );
565
- error = 1 ; goto unlocking1 ;
546
+ if (time_out ) { /* Set a timeout limit */
547
+ if (curl_easy_setopt (Curl , CURLOPT_TIMEOUT , time_out )) {
548
+ GMT_Report (API , GMT_MSG_ERROR , "Failed to set curl option to time out after %d seconds\n" , time_out );
549
+ return NULL ;
550
+ }
566
551
}
567
- urlfile . filename = file ; /* Set pointer to local filename */
552
+ urlfile -> filename = local_file ; /* Set pointer to local filename */
568
553
/* Define our callback to get called when there's data to be written */
569
554
if (curl_easy_setopt (Curl , CURLOPT_WRITEFUNCTION , gmtremote_fwrite_callback )) {
570
- GMT_Report (GMT -> parent , GMT_MSG_ERROR , "Failed to set curl output callback function\n" );
571
- error = 1 ; goto unlocking1 ;
555
+ GMT_Report (API , GMT_MSG_ERROR , "Failed to set curl output callback function\n" );
556
+ return NULL ;
572
557
}
573
- /* Set a pointer to our struct to pass to the callback */
574
- if (curl_easy_setopt (Curl , CURLOPT_WRITEDATA , & urlfile )) {
575
- GMT_Report (GMT -> parent , GMT_MSG_ERROR , "Failed to set curl option to write to %s\n" , file );
576
- error = 1 ; goto unlocking1 ;
558
+ /* Set a pointer to our struct that will be passed to the callback function */
559
+ if (curl_easy_setopt (Curl , CURLOPT_WRITEDATA , urlfile )) {
560
+ GMT_Report (API , GMT_MSG_ERROR , "Failed to set curl option to write to %s\n" , local_file );
561
+ return NULL ;
562
+ }
563
+
564
+ return Curl ; /* Happily return the Curl pointer */
565
+ }
566
+
567
+ struct LOCFILE_FP * gmtremote_lock_on (struct GMT_CTRL * GMT , char * file ) {
568
+ /* Creates filename for lock and activates the lock */
569
+ struct LOCFILE_FP * P = gmt_M_memory (GMT , NULL , 1 , struct LOCFILE_FP );
570
+ P -> file = gmtremote_lockfile (GMT , file );
571
+ if ((P -> fp = fopen (P -> file , "w" )) == NULL ) {
572
+ GMT_Report (GMT -> parent , GMT_MSG_ERROR , "Failed to create lock file %s\n" , P -> file );
573
+ gmt_M_str_free (P -> file );
574
+ gmt_M_free (GMT , P );
575
+ return NULL ;
576
+ }
577
+ gmtlib_file_lock (GMT , fileno (P -> fp )); /* Attempt exclusive lock */
578
+ return P ;
579
+ }
580
+
581
+ void gmtremote_lock_off (struct GMT_CTRL * GMT , struct LOCFILE_FP * * P ) {
582
+ /* Deactivates the lock on the file */
583
+ gmtlib_file_unlock (GMT , fileno ((* P )-> fp ));
584
+ fclose ((* P )-> fp );
585
+ gmt_remove_file (GMT , (* P )-> file );
586
+ gmt_M_str_free ((* P )-> file );
587
+ gmt_M_free (GMT , * P );
588
+ }
589
+
590
+ /* Deal with hash values of cache/data files */
591
+
592
+ #define GMT_HASH_TIME_OUT 10L /* Not waiting longer than this to time out on getting the hash file */
593
+
594
+ GMT_LOCAL int gmtremote_get_url (struct GMT_CTRL * GMT , char * url , char * file , char * orig , unsigned int index ) {
595
+ bool turn_ctrl_C_off = false;
596
+ int curl_err = 0 , error = 0 ;
597
+ long time_spent ;
598
+ CURL * Curl = NULL ;
599
+ struct LOCFILE_FP * LF = NULL ;
600
+ struct FtpFile urlfile = {NULL , NULL };
601
+ struct GMTAPI_CTRL * API = GMT -> parent ;
602
+ time_t begin , end ;
603
+
604
+ if (GMT -> current .setting .auto_download == GMT_NO_DOWNLOAD ) { /* Not allowed to use remote copying */
605
+ GMT_Report (GMT -> parent , GMT_MSG_ERROR , "Remote download is currently deactivated\n" );
606
+ return 1 ;
577
607
}
608
+ if (GMT -> current .io .internet_error ) return 1 ; /* Not able to use remote copying in this session */
609
+
610
+ /* Make a lock */
611
+ if ((LF = gmtremote_lock_on (GMT , file )) == NULL )
612
+ return 1 ;
613
+
614
+ /* Initialize the curl session */
615
+ if ((Curl = gmtremote_setup_curl (API , url , file , & urlfile , GMT_HASH_TIME_OUT )) == NULL )
616
+ goto unlocking1 ;
617
+
578
618
GMT_Report (GMT -> parent , GMT_MSG_INFORMATION , "Downloading file %s ...\n" , url );
579
- gmtremote_turn_on_ctrl_C_check (file ); turn_off = true;
619
+ gmtremote_turn_on_ctrl_C_check (file ); turn_ctrl_C_off = true;
580
620
begin = time (NULL );
581
621
if ((curl_err = curl_easy_perform (Curl ))) { /* Failed, give error message */
582
622
end = time (NULL );
@@ -607,14 +647,11 @@ GMT_LOCAL int gmtremote_get_url (struct GMT_CTRL *GMT, char *url, char *file, ch
607
647
608
648
unlocking1 :
609
649
610
- if (!query ) { /* Remove lock file after successful download */
611
- gmtlib_file_unlock (GMT , fileno (fp ));
612
- fclose (fp );
613
- gmt_remove_file (GMT , Lfile );
614
- gmt_M_str_free (Lfile );
615
- }
650
+ /* Remove lock file after successful download */
651
+ gmtremote_lock_off (GMT , & LF );
652
+
653
+ if (turn_ctrl_C_off ) gmtremote_turn_off_ctrl_C_check ();
616
654
617
- if (turn_off ) gmtremote_turn_off_ctrl_C_check ();
618
655
return error ;
619
656
}
620
657
@@ -1114,20 +1151,19 @@ int gmtlib_file_is_jpeg2000_tile (struct GMTAPI_CTRL *API, char *file) {
1114
1151
}
1115
1152
1116
1153
int gmt_download_file (struct GMT_CTRL * GMT , const char * name , char * url , char * localfile , bool be_fussy ) {
1117
- bool query = gmt_M_file_is_query (url ), turn_off = false;
1154
+ bool query = gmt_M_file_is_query (url ), turn_ctrl_C_off = false;
1118
1155
int curl_err , error = 0 ;
1119
1156
size_t fsize ;
1120
- char * Lfile = NULL ;
1121
1157
CURL * Curl = NULL ;
1122
- FILE * fp = NULL ;
1123
1158
struct FtpFile urlfile = {NULL , NULL };
1159
+ struct LOCFILE_FP * LF = NULL ;
1124
1160
struct GMTAPI_CTRL * API = GMT -> parent ;
1125
1161
1126
1162
if (GMT -> current .setting .auto_download == GMT_NO_DOWNLOAD ) { /* Not allowed to use remote copying */
1127
1163
GMT_Report (GMT -> parent , GMT_MSG_ERROR , "Remote download is currently deactivated\n" );
1128
1164
return 1 ;
1129
1165
}
1130
- if (GMT -> current .io .internet_error ) return 1 ; /* Not able to use remote copying in this session */
1166
+ if (GMT -> current .io .internet_error ) return 1 ; /* Not able to use remote copying in this session */
1131
1167
1132
1168
/* Check if the file is too big for our current limit */
1133
1169
@@ -1140,52 +1176,19 @@ int gmt_download_file (struct GMT_CTRL *GMT, const char *name, char *url, char *
1140
1176
1141
1177
/* Here we will try to download a file */
1142
1178
1143
- if (!query ) { /* Only make a filename if not a query */
1144
- Lfile = gmtremote_lockfile (API , (char * )name );
1145
- if ((fp = fopen (Lfile , "w" )) == NULL ) {
1146
- GMT_Report (API , GMT_MSG_ERROR , "Failed to create lock file %s\n" , Lfile );
1147
- gmt_M_str_free (Lfile );
1148
- return 1 ;
1149
- }
1150
- gmtlib_file_lock (GMT , fileno (fp )); /* Attempt exclusive lock */
1151
- }
1152
-
1153
- if ((Curl = curl_easy_init ()) == NULL ) {
1154
- GMT_Report (API , GMT_MSG_ERROR , "Failed to initiate curl\n" );
1155
- error = 1 ; goto unlocking2 ;
1156
- }
1157
- if (curl_easy_setopt (Curl , CURLOPT_SSL_VERIFYPEER , 0L )) { /* Tell libcurl to not verify the peer */
1158
- GMT_Report (API , GMT_MSG_ERROR , "Failed to set curl option to not verify the peer\n" );
1159
- error = 1 ; goto unlocking2 ;
1160
- }
1161
- if (curl_easy_setopt (Curl , CURLOPT_FOLLOWLOCATION , 1L )) { /* Tell libcurl to follow 30x redirects */
1162
- GMT_Report (API , GMT_MSG_ERROR , "Failed to set curl option to follow redirects\n" );
1163
- error = 1 ; goto unlocking2 ;
1164
- }
1165
- if (curl_easy_setopt (Curl , CURLOPT_FAILONERROR , 1L )) { /* Tell libcurl to fail on 4xx responses (e.g. 404) */
1166
- error = 1 ; goto unlocking2 ;
1167
- }
1179
+ /* Only make a lock if not a query */
1180
+ if (!query && (LF = gmtremote_lock_on (GMT , (char * )name )) == NULL )
1181
+ return 1 ;
1168
1182
1169
- if (curl_easy_setopt (Curl , CURLOPT_URL , url )) { /* Set the URL to copy */
1170
- GMT_Report (API , GMT_MSG_ERROR , "Failed to set curl option to read from %s\n" , url );
1171
- error = 1 ; goto unlocking2 ;
1172
- }
1173
- urlfile .filename = localfile ; /* Set pointer to local filename */
1174
- /* Define our callback to get called when there's data to be written */
1175
- if (curl_easy_setopt (Curl , CURLOPT_WRITEFUNCTION , gmtremote_fwrite_callback )) {
1176
- GMT_Report (API , GMT_MSG_ERROR , "Failed to set curl output callback function\n" );
1177
- error = 1 ; goto unlocking2 ;
1178
- }
1179
- /* Set a pointer to our struct to pass to the callback */
1180
- if (curl_easy_setopt (Curl , CURLOPT_WRITEDATA , & urlfile )) {
1181
- GMT_Report (API , GMT_MSG_ERROR , "Failed to set curl option to write to %s\n" , localfile );
1182
- error = 1 ; goto unlocking2 ;
1183
- }
1183
+ /* Initialize the curl session */
1184
+ if ((Curl = gmtremote_setup_curl (API , url , localfile , & urlfile , 0 )) == NULL )
1185
+ goto unlocking2 ;
1184
1186
1185
1187
gmtremote_find_and_give_data_attribution (API , name );
1186
1188
1187
1189
GMT_Report (API , GMT_MSG_INFORMATION , "Downloading file %s ...\n" , url );
1188
- gmtremote_turn_on_ctrl_C_check (localfile ); turn_off = true;
1190
+ gmtremote_turn_on_ctrl_C_check (localfile );
1191
+ turn_ctrl_C_off = true;
1189
1192
if ((curl_err = curl_easy_perform (Curl ))) { /* Failed, give error message */
1190
1193
if (be_fussy || !(curl_err == CURLE_REMOTE_FILE_NOT_FOUND || curl_err == CURLE_HTTP_RETURNED_ERROR )) { /* Unexpected failure - want to bitch about it */
1191
1194
GMT_Report (API , GMT_MSG_ERROR , "Libcurl Error: %s\n" , curl_easy_strerror (curl_err ));
@@ -1206,14 +1209,10 @@ int gmt_download_file (struct GMT_CTRL *GMT, const char *name, char *url, char *
1206
1209
1207
1210
unlocking2 :
1208
1211
1209
- if (!query ) { /* Remove lock file after successful download */
1210
- gmtlib_file_unlock (GMT , fileno (fp ));
1211
- fclose (fp );
1212
- gmt_remove_file (GMT , Lfile );
1213
- gmt_M_str_free (Lfile );
1214
- }
1212
+ if (!query ) /* Remove lock file after successful download (unless query) */
1213
+ gmtremote_lock_off (GMT , & LF );
1215
1214
1216
- if (turn_off ) gmtremote_turn_off_ctrl_C_check ();
1215
+ if (turn_ctrl_C_off ) gmtremote_turn_off_ctrl_C_check ();
1217
1216
1218
1217
if (error == 0 ) error = gmtremote_convert_jp2_to_nc (API , localfile );
1219
1218
0 commit comments