@@ -148,29 +148,31 @@ FILE *get_dnld_stream(char const *const fname) {
148148 return fp ;
149149}
150150
151- size_t write_cb (const void * buffer , size_t sz , size_t nmemb , void * userdata ) {
152- size_t ret = 0 ;
153- struct dnld_params_t * dnld_params = ( struct dnld_params_t * ) userdata ;
151+ size_t write_cb (const void * buffer , const size_t sz , size_t nmemb ,
152+ void * userdata ) {
153+ struct dnld_params_t * dnld_params = userdata ;
154154
155155 if (!dnld_params -> dnld_remote_fname [0 ]) {
156- ret = get_oname_from_url (dnld_params -> dnld_url ,
157- dnld_params -> dnld_remote_fname );
156+ get_oname_from_url (dnld_params -> dnld_url , dnld_params -> dnld_remote_fname );
158157 }
159158
160- if (ret != 0 )
161- return ret ;
162-
163159 if (!dnld_params -> dnld_stream ) {
164160 dnld_params -> dnld_stream =
165161 get_dnld_stream (dnld_params -> dnld_full_local_fname );
162+ if (!dnld_params -> dnld_stream )
163+ return 0 ;
166164 }
167165
168- ret = fwrite (buffer , sz , nmemb , dnld_params -> dnld_stream );
169-
170- if (ret == (sz * nmemb )) {
171- dnld_params -> dnld_file_sz += ret ;
166+ {
167+ const size_t bytes_written =
168+ fwrite (buffer , sz , nmemb , dnld_params -> dnld_stream );
169+ if (bytes_written == sz * nmemb ) {
170+ dnld_params -> dnld_file_sz += bytes_written ;
171+ return bytes_written ;
172+ }
172173 }
173- return ret ;
174+
175+ return 0 ;
174176}
175177
176178int download (const char * url , enum Checksum checksum , const char * hash ,
@@ -179,34 +181,47 @@ int download(const char *url, enum Checksum checksum, const char *hash,
179181 CURL * curl ;
180182 CURLcode cerr = CURLE_OK ;
181183 struct dnld_params_t dnld_params ;
182- size_t i ;
183184 const char * path ;
184185
185186 memset (& dnld_params , 0 , sizeof (dnld_params ));
186187
187188 if (is_file (target_location )) {
188- /* This next branch subsumes the `is_downloaded` function? */
189- if (filesize (target_location ) > 0 /* && check checksum */ ) {
190- return EEXIST /*CURLE_ALREADY_COMPLETE*/ ;
191- } else
192- set_remote_fname_to_target_location : {
193- const size_t target_location_n = strlen (target_location );
189+ if (filesize (target_location ) > 0 ) {
190+ return EEXIST ;
191+ } else {
192+ /* treat target_location as a filename */
194193 strncpy (dnld_params .dnld_remote_fname , target_location ,
195- target_location_n );
194+ sizeof (dnld_params .dnld_remote_fname ) - 1 );
195+ dnld_params .dnld_remote_fname [sizeof (dnld_params .dnld_remote_fname ) - 1 ] =
196+ '\0' ;
196197 strncpy (dnld_params .dnld_full_local_fname , target_location ,
197- target_location_n );
198+ sizeof (dnld_params .dnld_full_local_fname ) - 1 );
199+ dnld_params
200+ .dnld_full_local_fname [sizeof (dnld_params .dnld_full_local_fname ) -
201+ 1 ] = '\0' ;
198202 }
199203 } else if (is_relative (target_location )) {
200- goto set_remote_fname_to_target_location ;
204+ /* same as above */
205+ strncpy (dnld_params .dnld_remote_fname , target_location ,
206+ sizeof (dnld_params .dnld_remote_fname ) - 1 );
207+ dnld_params .dnld_remote_fname [sizeof (dnld_params .dnld_remote_fname ) - 1 ] =
208+ '\0' ;
209+ strncpy (dnld_params .dnld_full_local_fname , target_location ,
210+ sizeof (dnld_params .dnld_full_local_fname ) - 1 );
211+ dnld_params
212+ .dnld_full_local_fname [sizeof (dnld_params .dnld_full_local_fname ) - 1 ] =
213+ '\0' ;
201214 } else if (!is_directory (target_location )) {
202- fprintf (stderr , "Create \"%s\" and ensure its accessible, then try again\n" ,
215+ fprintf (stderr ,
216+ "Create \"%s\" and ensure it's accessible, then try again\n" ,
203217 target_location );
204218 return CURLINFO_OS_ERRNO + 2 ;
205219 }
206220
207- curl_global_init ((size_t )CURL_GLOBAL_ALL );
221+ strncpy (dnld_params .dnld_url , url , sizeof (dnld_params .dnld_url ) - 1 );
222+ dnld_params .dnld_url [sizeof (dnld_params .dnld_url ) - 1 ] = '\0' ;
208223
209- strncpy ( dnld_params . dnld_url , url , strlen ( url ) );
224+ curl_global_init ( CURL_GLOBAL_ALL );
210225
211226 curl = curl_easy_init ();
212227 if (!curl ) {
@@ -215,84 +230,93 @@ int download(const char *url, enum Checksum checksum, const char *hash,
215230 return EXIT_FAILURE ;
216231 }
217232
218- #define handle_curl_error (cerr , name ) \
219- if ((cerr) != CURLE_OK) { \
220- fprintf(stderr, "%s: failed with err %d\n", name, cerr); \
233+ #define handle_curl_error (cerr_ , name ) \
234+ if ((cerr_) != CURLE_OK) { \
235+ fprintf(stderr, "%s: failed with err %d: %s\n", name, cerr_, \
236+ curl_easy_strerror(cerr_)); \
221237 goto bail; \
222238 } else
239+
223240 cerr = curl_easy_setopt (curl , CURLOPT_URL , url );
224241 handle_curl_error (cerr , "CURLOPT_URL" );
225242
226- if (url [ 0 ] == 'f' && url [ 1 ] == 't' && url [ 2 ] == 'p' && url [ 3 ] == 's' )
227- curl_easy_setopt (curl , CURLOPT_USE_SSL , CURLUSESSL_ALL );
228- else
243+ if (strncmp ( url , "ftps" , 4 ) == 0 ) {
244+ curl_easy_setopt (curl , CURLOPT_USE_SSL , ( long ) CURLUSESSL_ALL );
245+ } else {
229246 curl_easy_setopt (curl , CURLOPT_HTTPGET , 1L );
247+ }
230248
231249 /* ask libcurl to use TLS version 1.2 or later */
232250 curl_easy_setopt (curl , CURLOPT_SSLVERSION , CURL_SSLVERSION_TLSv1_2 );
233251
234- curl_easy_setopt (curl , CURLOPT_VERBOSE , verbosity );
252+ curl_easy_setopt (curl , CURLOPT_VERBOSE , ( long ) verbosity );
235253
236- /* disable progress meter, set to 0L to enable it */
254+ /* disable progress meter by default */
237255 curl_easy_setopt (curl , CURLOPT_NOPROGRESS , 1L );
238256
239257 cerr = curl_easy_setopt (curl , CURLOPT_HEADERFUNCTION , dnld_header_parse );
240- handle_curl_error (cerr , "CURLOPT_HEADERFUNCTION" )
258+ handle_curl_error (cerr , "CURLOPT_HEADERFUNCTION" );
241259
242- cerr = curl_easy_setopt (curl , CURLOPT_HEADERDATA , & dnld_params );
260+ cerr = curl_easy_setopt (curl , CURLOPT_HEADERDATA , ( void * ) & dnld_params );
243261 handle_curl_error (cerr , "CURLOPT_HEADERDATA" );
244262
245263 if (strlen (dnld_params .dnld_remote_fname ) == 0 ||
246264 strcmp (dnld_params .dnld_remote_fname , "/" ) == 0 ) {
247265 path = get_path_from_url (url );
248- for (i = 0 ; i < strlen (path ); i ++ )
249- dnld_params .dnld_remote_fname [i ] = path [i ];
250- dnld_params .dnld_remote_fname [i + 1 ] = '\0' ;
266+ if (strlen (path ) >= sizeof (dnld_params .dnld_remote_fname ))
267+ path = "" ; /* fail silently, will error below */
268+
269+ strncpy (dnld_params .dnld_remote_fname , path ,
270+ sizeof (dnld_params .dnld_remote_fname ) - 1 );
271+ dnld_params .dnld_remote_fname [sizeof (dnld_params .dnld_remote_fname ) - 1 ] =
272+ '\0' ;
251273 }
252274
253- if (dnld_params .dnld_full_local_fname [0 ] != 0 )
254- /*pass*/ ;
255- else if (strlen (dnld_params .dnld_remote_fname ) == 0 ||
256- strcmp (dnld_params .dnld_remote_fname , "/" ) == 0 ) {
257- fprintf (stderr , "unable to derive a filename to save to, from: %s\n" , url );
258- goto bail ;
259- } else {
260- snprintf (dnld_params .dnld_full_local_fname , NAME_MAX + 1 , "%s/%s" ,
261- target_location , dnld_params .dnld_remote_fname );
275+ if (dnld_params .dnld_full_local_fname [0 ] == '\0' ) {
276+ if (strlen (dnld_params .dnld_remote_fname ) == 0 ||
277+ strcmp (dnld_params .dnld_remote_fname , "/" ) == 0 ) {
278+ fprintf (stderr , "unable to derive a filename to save to, from: %s\n" ,
279+ url );
280+ goto bail ;
281+ } else {
282+ snprintf (dnld_params .dnld_full_local_fname ,
283+ sizeof (dnld_params .dnld_full_local_fname ), "%s%c%s" ,
284+ target_location , '/' , dnld_params .dnld_remote_fname );
285+ }
262286 }
263287
264- /* fold this condition into one `stat` call? */
265288 if (is_file (dnld_params .dnld_full_local_fname ) &&
266289 filesize (dnld_params .dnld_full_local_fname ) > 0 ) {
267- cerr = CURLE_ALREADY_COMPLETE ;
290+ cerr = CURLE_OK /* simulate CURLE_ALREADY_COMPLETE */ ;
268291 goto bail ;
269292 }
270293
271294 cerr = curl_easy_setopt (curl , CURLOPT_WRITEFUNCTION , write_cb );
272295 handle_curl_error (cerr , "CURLOPT_WRITEFUNCTION" );
273296
274- cerr = curl_easy_setopt (curl , CURLOPT_WRITEDATA , & dnld_params );
297+ cerr = curl_easy_setopt (curl , CURLOPT_WRITEDATA , ( void * ) & dnld_params );
275298 handle_curl_error (cerr , "CURLOPT_WRITEDATA" );
276299
277300 cerr = curl_easy_perform (curl );
278301 if (cerr != CURLE_OK )
279302 fprintf (stderr , "curl_easy_perform() failed: %s\n" ,
280303 curl_easy_strerror (cerr ));
281304
282- fclose (dnld_params .dnld_stream );
305+ if (dnld_params .dnld_stream ) {
306+ fclose (dnld_params .dnld_stream );
307+ dnld_params .dnld_stream = NULL ;
308+ }
283309
284310 if (dnld_params .dnld_file_sz < 1 ) {
285311 fprintf (stderr , "Downloaded an empty file\n" );
286312 cerr = CURLE_GOT_NOTHING ;
287313 }
288314
289315bail :
290-
291- /* always cleanup */
292316 curl_easy_cleanup (curl );
293317 curl_global_cleanup ();
294318
295- if (cerr != CURLE_OK && cerr != CURLE_ALREADY_COMPLETE ) {
319+ if (cerr != CURLE_OK ) {
296320 fprintf (stderr , "curl failed with: %s\n" , curl_easy_strerror (cerr ));
297321 return EXIT_FAILURE ;
298322 }
0 commit comments