1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel (at) haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.haxx.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22 #include "tool_setup.h" 23 24 #ifdef HAVE_FCNTL_H 25 # include <fcntl.h> 26 #endif 27 28 #ifdef HAVE_UTIME_H 29 # include <utime.h> 30 #elif defined(HAVE_SYS_UTIME_H) 31 # include <sys/utime.h> 32 #endif 33 34 #ifdef HAVE_LOCALE_H 35 # include <locale.h> 36 #endif 37 38 #ifdef __VMS 39 # include <fabdef.h> 40 #endif 41 42 #include "strcase.h" 43 44 #define ENABLE_CURLX_PRINTF 45 /* use our own printf() functions */ 46 #include "curlx.h" 47 48 #include "tool_binmode.h" 49 #include "tool_cfgable.h" 50 #include "tool_cb_dbg.h" 51 #include "tool_cb_hdr.h" 52 #include "tool_cb_prg.h" 53 #include "tool_cb_rea.h" 54 #include "tool_cb_see.h" 55 #include "tool_cb_wrt.h" 56 #include "tool_dirhie.h" 57 #include "tool_doswin.h" 58 #include "tool_easysrc.h" 59 #include "tool_getparam.h" 60 #include "tool_helpers.h" 61 #include "tool_homedir.h" 62 #include "tool_libinfo.h" 63 #include "tool_main.h" 64 #include "tool_metalink.h" 65 #include "tool_msgs.h" 66 #include "tool_operate.h" 67 #include "tool_operhlp.h" 68 #include "tool_paramhlp.h" 69 #include "tool_parsecfg.h" 70 #include "tool_setopt.h" 71 #include "tool_sleep.h" 72 #include "tool_urlglob.h" 73 #include "tool_util.h" 74 #include "tool_writeout.h" 75 #include "tool_xattr.h" 76 #include "tool_vms.h" 77 #include "tool_help.h" 78 #include "tool_hugehelp.h" 79 80 #include "memdebug.h" /* keep this as LAST include */ 81 82 #ifdef CURLDEBUG 83 /* libcurl's debug builds provide an extra function */ 84 CURLcode curl_easy_perform_ev(CURL *easy); 85 #endif 86 87 #define CURLseparator "--_curl_--" 88 89 #ifndef O_BINARY 90 /* since O_BINARY as used in bitmasks, setting it to zero makes it usable in 91 source code but yet it doesn't ruin anything */ 92 # define O_BINARY 0 93 #endif 94 95 #define CURL_CA_CERT_ERRORMSG \ 96 "More details here: https://curl.haxx.se/docs/sslcerts.html\n\n" \ 97 "curl failed to verify the legitimacy of the server and therefore " \ 98 "could not\nestablish a secure connection to it. To learn more about " \ 99 "this situation and\nhow to fix it, please visit the web page mentioned " \ 100 "above.\n" 101 102 static bool is_fatal_error(CURLcode code) 103 { 104 switch(code) { 105 /* TODO: Should CURLE_SSL_CACERT be included as critical error ? */ 106 case CURLE_FAILED_INIT: 107 case CURLE_OUT_OF_MEMORY: 108 case CURLE_UNKNOWN_OPTION: 109 case CURLE_FUNCTION_NOT_FOUND: 110 case CURLE_BAD_FUNCTION_ARGUMENT: 111 /* critical error */ 112 return TRUE; 113 default: 114 break; 115 } 116 117 /* no error or not critical */ 118 return FALSE; 119 } 120 121 #ifdef __VMS 122 /* 123 * get_vms_file_size does what it takes to get the real size of the file 124 * 125 * For fixed files, find out the size of the EOF block and adjust. 126 * 127 * For all others, have to read the entire file in, discarding the contents. 128 * Most posted text files will be small, and binary files like zlib archives 129 * and CD/DVD images should be either a STREAM_LF format or a fixed format. 130 * 131 */ 132 static curl_off_t vms_realfilesize(const char *name, 133 const struct_stat *stat_buf) 134 { 135 char buffer[8192]; 136 curl_off_t count; 137 int ret_stat; 138 FILE * file; 139 140 /* !checksrc! disable FOPENMODE 1 */ 141 file = fopen(name, "r"); /* VMS */ 142 if(file == NULL) { 143 return 0; 144 } 145 count = 0; 146 ret_stat = 1; 147 while(ret_stat > 0) { 148 ret_stat = fread(buffer, 1, sizeof(buffer), file); 149 if(ret_stat != 0) 150 count += ret_stat; 151 } 152 fclose(file); 153 154 return count; 155 } 156 157 /* 158 * 159 * VmsSpecialSize checks to see if the stat st_size can be trusted and 160 * if not to call a routine to get the correct size. 161 * 162 */ 163 static curl_off_t VmsSpecialSize(const char *name, 164 const struct_stat *stat_buf) 165 { 166 switch(stat_buf->st_fab_rfm) { 167 case FAB$C_VAR: 168 case FAB$C_VFC: 169 return vms_realfilesize(name, stat_buf); 170 break; 171 default: 172 return stat_buf->st_size; 173 } 174 } 175 #endif /* __VMS */ 176 177 #if defined(HAVE_UTIME) || \ 178 (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) 179 static void setfiletime(long filetime, const char *filename, 180 FILE *error_stream) 181 { 182 if(filetime >= 0) { 183 /* Windows utime() may attempt to adjust our unix gmt 'filetime' by a daylight 184 saving time offset and since it's GMT that is bad behavior. When we have 185 access to a 64-bit type we can bypass utime and set the times directly. */ 186 #if defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8) 187 HANDLE hfile; 188 189 #if (SIZEOF_LONG >= 8) 190 /* 910670515199 is the maximum unix filetime that can be used as a 191 Windows FILETIME without overflow: 30827-12-31T23:59:59. */ 192 if(filetime > CURL_OFF_T_C(910670515199)) { 193 fprintf(error_stream, 194 "Failed to set filetime %ld on outfile: overflow\n", 195 filetime); 196 return; 197 } 198 #endif /* SIZEOF_LONG >= 8 */ 199 200 hfile = CreateFileA(filename, FILE_WRITE_ATTRIBUTES, 201 (FILE_SHARE_READ | FILE_SHARE_WRITE | 202 FILE_SHARE_DELETE), 203 NULL, OPEN_EXISTING, 0, NULL); 204 if(hfile != INVALID_HANDLE_VALUE) { 205 curl_off_t converted = ((curl_off_t)filetime * 10000000) + 206 CURL_OFF_T_C(116444736000000000); 207 FILETIME ft; 208 ft.dwLowDateTime = (DWORD)(converted & 0xFFFFFFFF); 209 ft.dwHighDateTime = (DWORD)(converted >> 32); 210 if(!SetFileTime(hfile, NULL, &ft, &ft)) { 211 fprintf(error_stream, 212 "Failed to set filetime %ld on outfile: " 213 "SetFileTime failed: GetLastError %u\n", 214 filetime, GetLastError()); 215 } 216 CloseHandle(hfile); 217 } 218 else { 219 fprintf(error_stream, 220 "Failed to set filetime %ld on outfile: " 221 "CreateFile failed: GetLastError %u\n", 222 filetime, GetLastError()); 223 } 224 225 #elif defined(HAVE_UTIMES) 226 struct timeval times[2]; 227 times[0].tv_sec = times[1].tv_sec = filetime; 228 times[0].tv_usec = times[1].tv_usec = 0; 229 if(utimes(filename, times)) { 230 fprintf(error_stream, 231 "Failed to set filetime %ld on outfile: errno %d\n", 232 filetime, errno); 233 } 234 235 #elif defined(HAVE_UTIME) 236 struct utimbuf times; 237 times.actime = (time_t)filetime; 238 times.modtime = (time_t)filetime; 239 if(utime(filename, ×)) { 240 fprintf(error_stream, 241 "Failed to set filetime %ld on outfile: errno %d\n", 242 filetime, errno); 243 } 244 #endif 245 } 246 } 247 #endif /* defined(HAVE_UTIME) || \ 248 (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) */ 249 250 #define BUFFER_SIZE (100*1024) 251 252 static CURLcode operate_do(struct GlobalConfig *global, 253 struct OperationConfig *config) 254 { 255 char errorbuffer[CURL_ERROR_SIZE]; 256 struct ProgressData progressbar; 257 struct getout *urlnode; 258 259 struct HdrCbData hdrcbdata; 260 struct OutStruct heads; 261 262 metalinkfile *mlfile_last = NULL; 263 264 CURL *curl = config->easy; 265 char *httpgetfields = NULL; 266 267 CURLcode result = CURLE_OK; 268 unsigned long li; 269 bool capath_from_env; 270 271 /* Save the values of noprogress and isatty to restore them later on */ 272 bool orig_noprogress = global->noprogress; 273 bool orig_isatty = global->isatty; 274 275 errorbuffer[0] = '\0'; 276 277 /* default headers output stream is stdout */ 278 memset(&hdrcbdata, 0, sizeof(struct HdrCbData)); 279 memset(&heads, 0, sizeof(struct OutStruct)); 280 heads.stream = stdout; 281 heads.config = config; 282 283 /* 284 ** Beyond this point no return'ing from this function allowed. 285 ** Jump to label 'quit_curl' in order to abandon this function 286 ** from outside of nested loops further down below. 287 */ 288 289 /* Check we have a url */ 290 if(!config->url_list || !config->url_list->url) { 291 helpf(global->errors, "no URL specified!\n"); 292 result = CURLE_FAILED_INIT; 293 goto quit_curl; 294 } 295 296 /* On WIN32 we can't set the path to curl-ca-bundle.crt 297 * at compile time. So we look here for the file in two ways: 298 * 1: look at the environment variable CURL_CA_BUNDLE for a path 299 * 2: if #1 isn't found, use the windows API function SearchPath() 300 * to find it along the app's path (includes app's dir and CWD) 301 * 302 * We support the environment variable thing for non-Windows platforms 303 * too. Just for the sake of it. 304 */ 305 capath_from_env = false; 306 if(!config->cacert && 307 !config->capath && 308 !config->insecure_ok) { 309 char *env; 310 env = curlx_getenv("CURL_CA_BUNDLE"); 311 if(env) { 312 config->cacert = strdup(env); 313 if(!config->cacert) { 314 curl_free(env); 315 helpf(global->errors, "out of memory\n"); 316 result = CURLE_OUT_OF_MEMORY; 317 goto quit_curl; 318 } 319 } 320 else { 321 env = curlx_getenv("SSL_CERT_DIR"); 322 if(env) { 323 config->capath = strdup(env); 324 if(!config->capath) { 325 curl_free(env); 326 helpf(global->errors, "out of memory\n"); 327 result = CURLE_OUT_OF_MEMORY; 328 goto quit_curl; 329 } 330 capath_from_env = true; 331 } 332 else { 333 env = curlx_getenv("SSL_CERT_FILE"); 334 if(env) { 335 config->cacert = strdup(env); 336 if(!config->cacert) { 337 curl_free(env); 338 helpf(global->errors, "out of memory\n"); 339 result = CURLE_OUT_OF_MEMORY; 340 goto quit_curl; 341 } 342 } 343 } 344 } 345 346 if(env) 347 curl_free(env); 348 #ifdef WIN32 349 else { 350 result = FindWin32CACert(config, "curl-ca-bundle.crt"); 351 if(result) 352 goto quit_curl; 353 } 354 #endif 355 } 356 357 if(config->postfields) { 358 if(config->use_httpget) { 359 /* Use the postfields data for a http get */ 360 httpgetfields = strdup(config->postfields); 361 Curl_safefree(config->postfields); 362 if(!httpgetfields) { 363 helpf(global->errors, "out of memory\n"); 364 result = CURLE_OUT_OF_MEMORY; 365 goto quit_curl; 366 } 367 if(SetHTTPrequest(config, 368 (config->no_body?HTTPREQ_HEAD:HTTPREQ_GET), 369 &config->httpreq)) { 370 result = CURLE_FAILED_INIT; 371 goto quit_curl; 372 } 373 } 374 else { 375 if(SetHTTPrequest(config, HTTPREQ_SIMPLEPOST, &config->httpreq)) { 376 result = CURLE_FAILED_INIT; 377 goto quit_curl; 378 } 379 } 380 } 381 382 /* Single header file for all URLs */ 383 if(config->headerfile) { 384 /* open file for output: */ 385 if(strcmp(config->headerfile, "-")) { 386 FILE *newfile = fopen(config->headerfile, "wb"); 387 if(!newfile) { 388 warnf(config->global, "Failed to open %s\n", config->headerfile); 389 result = CURLE_WRITE_ERROR; 390 goto quit_curl; 391 } 392 else { 393 heads.filename = config->headerfile; 394 heads.s_isreg = TRUE; 395 heads.fopened = TRUE; 396 heads.stream = newfile; 397 } 398 } 399 else { 400 /* always use binary mode for protocol header output */ 401 set_binmode(heads.stream); 402 } 403 } 404 405 /* 406 ** Nested loops start here. 407 */ 408 409 /* loop through the list of given URLs */ 410 411 for(urlnode = config->url_list; urlnode; urlnode = urlnode->next) { 412 413 unsigned long up; /* upload file counter within a single upload glob */ 414 char *infiles; /* might be a glob pattern */ 415 char *outfiles; 416 unsigned long infilenum; 417 URLGlob *inglob; 418 419 int metalink = 0; /* nonzero for metalink download. */ 420 metalinkfile *mlfile; 421 metalink_resource *mlres; 422 423 outfiles = NULL; 424 infilenum = 1; 425 inglob = NULL; 426 427 if(urlnode->flags & GETOUT_METALINK) { 428 metalink = 1; 429 if(mlfile_last == NULL) { 430 mlfile_last = config->metalinkfile_list; 431 } 432 mlfile = mlfile_last; 433 mlfile_last = mlfile_last->next; 434 mlres = mlfile->resource; 435 } 436 else { 437 mlfile = NULL; 438 mlres = NULL; 439 } 440 441 /* urlnode->url is the full URL (it might be NULL) */ 442 443 if(!urlnode->url) { 444 /* This node has no URL. Free node data without destroying the 445 node itself nor modifying next pointer and continue to next */ 446 Curl_safefree(urlnode->outfile); 447 Curl_safefree(urlnode->infile); 448 urlnode->flags = 0; 449 continue; /* next URL please */ 450 } 451 452 /* save outfile pattern before expansion */ 453 if(urlnode->outfile) { 454 outfiles = strdup(urlnode->outfile); 455 if(!outfiles) { 456 helpf(global->errors, "out of memory\n"); 457 result = CURLE_OUT_OF_MEMORY; 458 break; 459 } 460 } 461 462 infiles = urlnode->infile; 463 464 if(!config->globoff && infiles) { 465 /* Unless explicitly shut off */ 466 result = glob_url(&inglob, infiles, &infilenum, 467 global->showerror?global->errors:NULL); 468 if(result) { 469 Curl_safefree(outfiles); 470 break; 471 } 472 } 473 474 /* Here's the loop for uploading multiple files within the same 475 single globbed string. If no upload, we enter the loop once anyway. */ 476 for(up = 0 ; up < infilenum; up++) { 477 478 char *uploadfile; /* a single file, never a glob */ 479 int separator; 480 URLGlob *urls; 481 unsigned long urlnum; 482 483 uploadfile = NULL; 484 urls = NULL; 485 urlnum = 0; 486 487 if(!up && !infiles) 488 Curl_nop_stmt; 489 else { 490 if(inglob) { 491 result = glob_next_url(&uploadfile, inglob); 492 if(result == CURLE_OUT_OF_MEMORY) 493 helpf(global->errors, "out of memory\n"); 494 } 495 else if(!up) { 496 uploadfile = strdup(infiles); 497 if(!uploadfile) { 498 helpf(global->errors, "out of memory\n"); 499 result = CURLE_OUT_OF_MEMORY; 500 } 501 } 502 else 503 uploadfile = NULL; 504 if(!uploadfile) 505 break; 506 } 507 508 if(metalink) { 509 /* For Metalink download, we don't use glob. Instead we use 510 the number of resources as urlnum. */ 511 urlnum = count_next_metalink_resource(mlfile); 512 } 513 else 514 if(!config->globoff) { 515 /* Unless explicitly shut off, we expand '{...}' and '[...]' 516 expressions and return total number of URLs in pattern set */ 517 result = glob_url(&urls, urlnode->url, &urlnum, 518 global->showerror?global->errors:NULL); 519 if(result) { 520 Curl_safefree(uploadfile); 521 break; 522 } 523 } 524 else 525 urlnum = 1; /* without globbing, this is a single URL */ 526 527 /* if multiple files extracted to stdout, insert separators! */ 528 separator = ((!outfiles || !strcmp(outfiles, "-")) && urlnum > 1); 529 530 /* Here's looping around each globbed URL */ 531 for(li = 0 ; li < urlnum; li++) { 532 533 int infd; 534 bool infdopen; 535 char *outfile; 536 struct OutStruct outs; 537 struct InStruct input; 538 struct timeval retrystart; 539 curl_off_t uploadfilesize; 540 long retry_numretries; 541 long retry_sleep_default; 542 long retry_sleep; 543 char *this_url = NULL; 544 int metalink_next_res = 0; 545 546 outfile = NULL; 547 infdopen = FALSE; 548 infd = STDIN_FILENO; 549 uploadfilesize = -1; /* -1 means unknown */ 550 551 /* default output stream is stdout */ 552 memset(&outs, 0, sizeof(struct OutStruct)); 553 outs.stream = stdout; 554 outs.config = config; 555 556 if(metalink) { 557 /* For Metalink download, use name in Metalink file as 558 filename. */ 559 outfile = strdup(mlfile->filename); 560 if(!outfile) { 561 result = CURLE_OUT_OF_MEMORY; 562 goto show_error; 563 } 564 this_url = strdup(mlres->url); 565 if(!this_url) { 566 result = CURLE_OUT_OF_MEMORY; 567 goto show_error; 568 } 569 } 570 else { 571 if(urls) { 572 result = glob_next_url(&this_url, urls); 573 if(result) 574 goto show_error; 575 } 576 else if(!li) { 577 this_url = strdup(urlnode->url); 578 if(!this_url) { 579 result = CURLE_OUT_OF_MEMORY; 580 goto show_error; 581 } 582 } 583 else 584 this_url = NULL; 585 if(!this_url) 586 break; 587 588 if(outfiles) { 589 outfile = strdup(outfiles); 590 if(!outfile) { 591 result = CURLE_OUT_OF_MEMORY; 592 goto show_error; 593 } 594 } 595 } 596 597 if(((urlnode->flags&GETOUT_USEREMOTE) || 598 (outfile && strcmp("-", outfile))) && 599 (metalink || !config->use_metalink)) { 600 601 /* 602 * We have specified a file name to store the result in, or we have 603 * decided we want to use the remote file name. 604 */ 605 606 if(!outfile) { 607 /* extract the file name from the URL */ 608 result = get_url_file_name(&outfile, this_url); 609 if(result) 610 goto show_error; 611 if(!*outfile && !config->content_disposition) { 612 helpf(global->errors, "Remote file name has no length!\n"); 613 result = CURLE_WRITE_ERROR; 614 goto quit_urls; 615 } 616 } 617 else if(urls) { 618 /* fill '#1' ... '#9' terms from URL pattern */ 619 char *storefile = outfile; 620 result = glob_match_url(&outfile, storefile, urls); 621 Curl_safefree(storefile); 622 if(result) { 623 /* bad globbing */ 624 warnf(config->global, "bad output glob!\n"); 625 goto quit_urls; 626 } 627 } 628 629 /* Create the directory hierarchy, if not pre-existent to a multiple 630 file output call */ 631 632 if(config->create_dirs || metalink) { 633 result = create_dir_hierarchy(outfile, global->errors); 634 /* create_dir_hierarchy shows error upon CURLE_WRITE_ERROR */ 635 if(result == CURLE_WRITE_ERROR) 636 goto quit_urls; 637 if(result) { 638 goto show_error; 639 } 640 } 641 642 if((urlnode->flags & GETOUT_USEREMOTE) 643 && config->content_disposition) { 644 /* Our header callback MIGHT set the filename */ 645 DEBUGASSERT(!outs.filename); 646 } 647 648 if(config->resume_from_current) { 649 /* We're told to continue from where we are now. Get the size 650 of the file as it is now and open it for append instead */ 651 struct_stat fileinfo; 652 /* VMS -- Danger, the filesize is only valid for stream files */ 653 if(0 == stat(outfile, &fileinfo)) 654 /* set offset to current file size: */ 655 config->resume_from = fileinfo.st_size; 656 else 657 /* let offset be 0 */ 658 config->resume_from = 0; 659 } 660 661 if(config->resume_from) { 662 #ifdef __VMS 663 /* open file for output, forcing VMS output format into stream 664 mode which is needed for stat() call above to always work. */ 665 FILE *file = fopen(outfile, config->resume_from?"ab":"wb", 666 "ctx=stm", "rfm=stmlf", "rat=cr", "mrs=0"); 667 #else 668 /* open file for output: */ 669 FILE *file = fopen(outfile, config->resume_from?"ab":"wb"); 670 #endif 671 if(!file) { 672 helpf(global->errors, "Can't open '%s'!\n", outfile); 673 result = CURLE_WRITE_ERROR; 674 goto quit_urls; 675 } 676 outs.fopened = TRUE; 677 outs.stream = file; 678 outs.init = config->resume_from; 679 } 680 else { 681 outs.stream = NULL; /* open when needed */ 682 } 683 outs.filename = outfile; 684 outs.s_isreg = TRUE; 685 } 686 687 if(uploadfile && !stdin_upload(uploadfile)) { 688 /* 689 * We have specified a file to upload and it isn't "-". 690 */ 691 struct_stat fileinfo; 692 693 this_url = add_file_name_to_url(curl, this_url, uploadfile); 694 if(!this_url) { 695 result = CURLE_OUT_OF_MEMORY; 696 goto show_error; 697 } 698 /* VMS Note: 699 * 700 * Reading binary from files can be a problem... Only FIXED, VAR 701 * etc WITHOUT implied CC will work Others need a \n appended to a 702 * line 703 * 704 * - Stat gives a size but this is UNRELIABLE in VMS As a f.e. a 705 * fixed file with implied CC needs to have a byte added for every 706 * record processed, this can by derived from Filesize & recordsize 707 * for VARiable record files the records need to be counted! for 708 * every record add 1 for linefeed and subtract 2 for the record 709 * header for VARIABLE header files only the bare record data needs 710 * to be considered with one appended if implied CC 711 */ 712 #ifdef __VMS 713 /* Calculate the real upload site for VMS */ 714 infd = -1; 715 if(stat(uploadfile, &fileinfo) == 0) { 716 fileinfo.st_size = VmsSpecialSize(uploadfile, &fileinfo); 717 switch(fileinfo.st_fab_rfm) { 718 case FAB$C_VAR: 719 case FAB$C_VFC: 720 case FAB$C_STMCR: 721 infd = open(uploadfile, O_RDONLY | O_BINARY); 722 break; 723 default: 724 infd = open(uploadfile, O_RDONLY | O_BINARY, 725 "rfm=stmlf", "ctx=stm"); 726 } 727 } 728 if(infd == -1) 729 #else 730 infd = open(uploadfile, O_RDONLY | O_BINARY); 731 if((infd == -1) || fstat(infd, &fileinfo)) 732 #endif 733 { 734 helpf(global->errors, "Can't open '%s'!\n", uploadfile); 735 if(infd != -1) { 736 close(infd); 737 infd = STDIN_FILENO; 738 } 739 result = CURLE_READ_ERROR; 740 goto quit_urls; 741 } 742 infdopen = TRUE; 743 744 /* we ignore file size for char/block devices, sockets, etc. */ 745 if(S_ISREG(fileinfo.st_mode)) 746 uploadfilesize = fileinfo.st_size; 747 748 } 749 else if(uploadfile && stdin_upload(uploadfile)) { 750 /* count to see if there are more than one auth bit set 751 in the authtype field */ 752 int authbits = 0; 753 int bitcheck = 0; 754 while(bitcheck < 32) { 755 if(config->authtype & (1UL << bitcheck++)) { 756 authbits++; 757 if(authbits > 1) { 758 /* more than one, we're done! */ 759 break; 760 } 761 } 762 } 763 764 /* 765 * If the user has also selected --anyauth or --proxy-anyauth 766 * we should warn him/her. 767 */ 768 if(config->proxyanyauth || (authbits>1)) { 769 warnf(config->global, 770 "Using --anyauth or --proxy-anyauth with upload from stdin" 771 " involves a big risk of it not working. Use a temporary" 772 " file or a fixed auth type instead!\n"); 773 } 774 775 DEBUGASSERT(infdopen == FALSE); 776 DEBUGASSERT(infd == STDIN_FILENO); 777 778 set_binmode(stdin); 779 if(!strcmp(uploadfile, ".")) { 780 if(curlx_nonblock((curl_socket_t)infd, TRUE) < 0) 781 warnf(config->global, 782 "fcntl failed on fd=%d: %s\n", infd, strerror(errno)); 783 } 784 } 785 786 if(uploadfile && config->resume_from_current) 787 config->resume_from = -1; /* -1 will then force get-it-yourself */ 788 789 if(output_expected(this_url, uploadfile) && outs.stream && 790 isatty(fileno(outs.stream))) 791 /* we send the output to a tty, therefore we switch off the progress 792 meter */ 793 global->noprogress = global->isatty = TRUE; 794 else { 795 /* progress meter is per download, so restore config 796 values */ 797 global->noprogress = orig_noprogress; 798 global->isatty = orig_isatty; 799 } 800 801 if(urlnum > 1 && !global->mute) { 802 fprintf(global->errors, "\n[%lu/%lu]: %s --> %s\n", 803 li + 1, urlnum, this_url, outfile ? outfile : "<stdout>"); 804 if(separator) 805 printf("%s%s\n", CURLseparator, this_url); 806 } 807 if(httpgetfields) { 808 char *urlbuffer; 809 /* Find out whether the url contains a file name */ 810 const char *pc = strstr(this_url, "://"); 811 char sep = '?'; 812 if(pc) 813 pc += 3; 814 else 815 pc = this_url; 816 817 pc = strrchr(pc, '/'); /* check for a slash */ 818 819 if(pc) { 820 /* there is a slash present in the URL */ 821 822 if(strchr(pc, '?')) 823 /* Ouch, there's already a question mark in the URL string, we 824 then append the data with an ampersand separator instead! */ 825 sep = '&'; 826 } 827 /* 828 * Then append ? followed by the get fields to the url. 829 */ 830 if(pc) 831 urlbuffer = aprintf("%s%c%s", this_url, sep, httpgetfields); 832 else 833 /* Append / before the ? to create a well-formed url 834 if the url contains a hostname only 835 */ 836 urlbuffer = aprintf("%s/?%s", this_url, httpgetfields); 837 838 if(!urlbuffer) { 839 result = CURLE_OUT_OF_MEMORY; 840 goto show_error; 841 } 842 843 Curl_safefree(this_url); /* free previous URL */ 844 this_url = urlbuffer; /* use our new URL instead! */ 845 } 846 847 if(!global->errors) 848 global->errors = stderr; 849 850 if((!outfile || !strcmp(outfile, "-")) && !config->use_ascii) { 851 /* We get the output to stdout and we have not got the ASCII/text 852 flag, then set stdout to be binary */ 853 set_binmode(stdout); 854 } 855 856 /* explicitly passed to stdout means okaying binary gunk */ 857 config->terminal_binary_ok = (outfile && !strcmp(outfile, "-")); 858 859 if(!config->tcp_nodelay) 860 my_setopt(curl, CURLOPT_TCP_NODELAY, 0L); 861 862 if(config->tcp_fastopen) 863 my_setopt(curl, CURLOPT_TCP_FASTOPEN, 1L); 864 865 /* where to store */ 866 my_setopt(curl, CURLOPT_WRITEDATA, &outs); 867 my_setopt(curl, CURLOPT_INTERLEAVEDATA, &outs); 868 if(metalink || !config->use_metalink) 869 /* what call to write */ 870 my_setopt(curl, CURLOPT_WRITEFUNCTION, tool_write_cb); 871 #ifdef USE_METALINK 872 else 873 /* Set Metalink specific write callback function to parse 874 XML data progressively. */ 875 my_setopt(curl, CURLOPT_WRITEFUNCTION, metalink_write_cb); 876 #endif /* USE_METALINK */ 877 878 /* for uploads */ 879 input.fd = infd; 880 input.config = config; 881 /* Note that if CURLOPT_READFUNCTION is fread (the default), then 882 * lib/telnet.c will Curl_poll() on the input file descriptor 883 * rather then calling the READFUNCTION at regular intervals. 884 * The circumstances in which it is preferable to enable this 885 * behaviour, by omitting to set the READFUNCTION & READDATA options, 886 * have not been determined. 887 */ 888 my_setopt(curl, CURLOPT_READDATA, &input); 889 /* what call to read */ 890 my_setopt(curl, CURLOPT_READFUNCTION, tool_read_cb); 891 892 /* in 7.18.0, the CURLOPT_SEEKFUNCTION/DATA pair is taking over what 893 CURLOPT_IOCTLFUNCTION/DATA pair previously provided for seeking */ 894 my_setopt(curl, CURLOPT_SEEKDATA, &input); 895 my_setopt(curl, CURLOPT_SEEKFUNCTION, tool_seek_cb); 896 897 if(config->recvpersecond && 898 (config->recvpersecond < BUFFER_SIZE)) 899 /* use a smaller sized buffer for better sleeps */ 900 my_setopt(curl, CURLOPT_BUFFERSIZE, (long)config->recvpersecond); 901 else 902 my_setopt(curl, CURLOPT_BUFFERSIZE, (long)BUFFER_SIZE); 903 904 /* size of uploaded file: */ 905 if(uploadfilesize != -1) 906 my_setopt(curl, CURLOPT_INFILESIZE_LARGE, uploadfilesize); 907 my_setopt_str(curl, CURLOPT_URL, this_url); /* what to fetch */ 908 my_setopt(curl, CURLOPT_NOPROGRESS, global->noprogress?1L:0L); 909 if(config->no_body) { 910 my_setopt(curl, CURLOPT_NOBODY, 1L); 911 my_setopt(curl, CURLOPT_HEADER, 1L); 912 } 913 /* If --metalink is used, we ignore --include (headers in 914 output) option because mixing headers to the body will 915 confuse XML parser and/or hash check will fail. */ 916 else if(!config->use_metalink) 917 my_setopt(curl, CURLOPT_HEADER, config->include_headers?1L:0L); 918 919 if(config->oauth_bearer) 920 my_setopt_str(curl, CURLOPT_XOAUTH2_BEARER, config->oauth_bearer); 921 922 #if !defined(CURL_DISABLE_PROXY) 923 { 924 /* TODO: Make this a run-time check instead of compile-time one. */ 925 926 my_setopt_str(curl, CURLOPT_PROXY, config->proxy); 927 /* new in libcurl 7.5 */ 928 if(config->proxy) 929 my_setopt_enum(curl, CURLOPT_PROXYTYPE, config->proxyver); 930 931 my_setopt_str(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd); 932 933 /* new in libcurl 7.3 */ 934 my_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel?1L:0L); 935 936 /* new in libcurl 7.52.0 */ 937 if(config->preproxy) 938 my_setopt_str(curl, CURLOPT_PRE_PROXY, config->preproxy); 939 940 /* new in libcurl 7.10.6 */ 941 if(config->proxyanyauth) 942 my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, 943 (long)CURLAUTH_ANY); 944 else if(config->proxynegotiate) 945 my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, 946 (long)CURLAUTH_GSSNEGOTIATE); 947 else if(config->proxyntlm) 948 my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, 949 (long)CURLAUTH_NTLM); 950 else if(config->proxydigest) 951 my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, 952 (long)CURLAUTH_DIGEST); 953 else if(config->proxybasic) 954 my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, 955 (long)CURLAUTH_BASIC); 956 957 /* new in libcurl 7.19.4 */ 958 my_setopt_str(curl, CURLOPT_NOPROXY, config->noproxy); 959 960 my_setopt(curl, CURLOPT_SUPPRESS_CONNECT_HEADERS, 961 config->suppress_connect_headers?1L:0L); 962 } 963 #endif /* !CURL_DISABLE_PROXY */ 964 965 my_setopt(curl, CURLOPT_FAILONERROR, config->failonerror?1L:0L); 966 my_setopt(curl, CURLOPT_REQUEST_TARGET, config->request_target); 967 my_setopt(curl, CURLOPT_UPLOAD, uploadfile?1L:0L); 968 my_setopt(curl, CURLOPT_DIRLISTONLY, config->dirlistonly?1L:0L); 969 my_setopt(curl, CURLOPT_APPEND, config->ftp_append?1L:0L); 970 971 if(config->netrc_opt) 972 my_setopt_enum(curl, CURLOPT_NETRC, (long)CURL_NETRC_OPTIONAL); 973 else if(config->netrc || config->netrc_file) 974 my_setopt_enum(curl, CURLOPT_NETRC, (long)CURL_NETRC_REQUIRED); 975 else 976 my_setopt_enum(curl, CURLOPT_NETRC, (long)CURL_NETRC_IGNORED); 977 978 if(config->netrc_file) 979 my_setopt_str(curl, CURLOPT_NETRC_FILE, config->netrc_file); 980 981 my_setopt(curl, CURLOPT_TRANSFERTEXT, config->use_ascii?1L:0L); 982 if(config->login_options) 983 my_setopt_str(curl, CURLOPT_LOGIN_OPTIONS, config->login_options); 984 my_setopt_str(curl, CURLOPT_USERPWD, config->userpwd); 985 my_setopt_str(curl, CURLOPT_RANGE, config->range); 986 my_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer); 987 my_setopt(curl, CURLOPT_TIMEOUT_MS, (long)(config->timeout * 1000)); 988 989 switch(config->httpreq) { 990 case HTTPREQ_SIMPLEPOST: 991 my_setopt_str(curl, CURLOPT_POSTFIELDS, 992 config->postfields); 993 my_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, 994 config->postfieldsize); 995 break; 996 case HTTPREQ_MIMEPOST: 997 my_setopt_mimepost(curl, CURLOPT_MIMEPOST, config->mimepost); 998 break; 999 default: 1000 break; 1001 } 1002 1003 /* new in libcurl 7.10.6 (default is Basic) */ 1004 if(config->authtype) 1005 my_setopt_bitmask(curl, CURLOPT_HTTPAUTH, (long)config->authtype); 1006 1007 my_setopt_slist(curl, CURLOPT_HTTPHEADER, config->headers); 1008 1009 if(built_in_protos & (CURLPROTO_HTTP | CURLPROTO_RTSP)) { 1010 my_setopt_str(curl, CURLOPT_REFERER, config->referer); 1011 my_setopt_str(curl, CURLOPT_USERAGENT, config->useragent); 1012 } 1013 1014 if(built_in_protos & CURLPROTO_HTTP) { 1015 1016 long postRedir = 0; 1017 1018 my_setopt(curl, CURLOPT_FOLLOWLOCATION, 1019 config->followlocation?1L:0L); 1020 my_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, 1021 config->unrestricted_auth?1L:0L); 1022 1023 my_setopt(curl, CURLOPT_AUTOREFERER, config->autoreferer?1L:0L); 1024 1025 /* new in libcurl 7.36.0 */ 1026 if(config->proxyheaders) { 1027 my_setopt_slist(curl, CURLOPT_PROXYHEADER, config->proxyheaders); 1028 my_setopt(curl, CURLOPT_HEADEROPT, CURLHEADER_SEPARATE); 1029 } 1030 1031 /* new in libcurl 7.5 */ 1032 my_setopt(curl, CURLOPT_MAXREDIRS, config->maxredirs); 1033 1034 if(config->httpversion) 1035 my_setopt_enum(curl, CURLOPT_HTTP_VERSION, config->httpversion); 1036 else if(curlinfo->features & CURL_VERSION_HTTP2) { 1037 my_setopt_enum(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS); 1038 } 1039 1040 /* curl 7.19.1 (the 301 version existed in 7.18.2), 1041 303 was added in 7.26.0 */ 1042 if(config->post301) 1043 postRedir |= CURL_REDIR_POST_301; 1044 if(config->post302) 1045 postRedir |= CURL_REDIR_POST_302; 1046 if(config->post303) 1047 postRedir |= CURL_REDIR_POST_303; 1048 my_setopt(curl, CURLOPT_POSTREDIR, postRedir); 1049 1050 /* new in libcurl 7.21.6 */ 1051 if(config->encoding) 1052 my_setopt_str(curl, CURLOPT_ACCEPT_ENCODING, ""); 1053 1054 /* new in libcurl 7.21.6 */ 1055 if(config->tr_encoding) 1056 my_setopt(curl, CURLOPT_TRANSFER_ENCODING, 1L); 1057 1058 } /* (built_in_protos & CURLPROTO_HTTP) */ 1059 1060 my_setopt_str(curl, CURLOPT_FTPPORT, config->ftpport); 1061 my_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1062 config->low_speed_limit); 1063 my_setopt(curl, CURLOPT_LOW_SPEED_TIME, config->low_speed_time); 1064 my_setopt(curl, CURLOPT_MAX_SEND_SPEED_LARGE, 1065 config->sendpersecond); 1066 my_setopt(curl, CURLOPT_MAX_RECV_SPEED_LARGE, 1067 config->recvpersecond); 1068 1069 if(config->use_resume) 1070 my_setopt(curl, CURLOPT_RESUME_FROM_LARGE, config->resume_from); 1071 else 1072 my_setopt(curl, CURLOPT_RESUME_FROM_LARGE, CURL_OFF_T_C(0)); 1073 1074 my_setopt_str(curl, CURLOPT_KEYPASSWD, config->key_passwd); 1075 my_setopt_str(curl, CURLOPT_PROXY_KEYPASSWD, config->proxy_key_passwd); 1076 1077 if(built_in_protos & (CURLPROTO_SCP|CURLPROTO_SFTP)) { 1078 1079 /* SSH and SSL private key uses same command-line option */ 1080 /* new in libcurl 7.16.1 */ 1081 my_setopt_str(curl, CURLOPT_SSH_PRIVATE_KEYFILE, config->key); 1082 /* new in libcurl 7.16.1 */ 1083 my_setopt_str(curl, CURLOPT_SSH_PUBLIC_KEYFILE, config->pubkey); 1084 1085 /* new in libcurl 7.17.1: SSH host key md5 checking allows us 1086 to fail if we are not talking to who we think we should */ 1087 my_setopt_str(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, 1088 config->hostpubmd5); 1089 1090 /* new in libcurl 7.56.0 */ 1091 if(config->ssh_compression) 1092 my_setopt(curl, CURLOPT_SSH_COMPRESSION, 1L); 1093 } 1094 1095 if(config->cacert) 1096 my_setopt_str(curl, CURLOPT_CAINFO, config->cacert); 1097 if(config->proxy_cacert) 1098 my_setopt_str(curl, CURLOPT_PROXY_CAINFO, config->proxy_cacert); 1099 1100 if(config->capath) { 1101 result = res_setopt_str(curl, CURLOPT_CAPATH, config->capath); 1102 if(result == CURLE_NOT_BUILT_IN) { 1103 warnf(config->global, "ignoring %s, not supported by libcurl\n", 1104 capath_from_env? 1105 "SSL_CERT_DIR environment variable":"--capath"); 1106 } 1107 else if(result) 1108 goto show_error; 1109 } 1110 /* For the time being if --proxy-capath is not set then we use the 1111 --capath value for it, if any. See #1257 */ 1112 if(config->proxy_capath || config->capath) { 1113 result = res_setopt_str(curl, CURLOPT_PROXY_CAPATH, 1114 (config->proxy_capath ? 1115 config->proxy_capath : 1116 config->capath)); 1117 if(result == CURLE_NOT_BUILT_IN) { 1118 if(config->proxy_capath) { 1119 warnf(config->global, 1120 "ignoring --proxy-capath, not supported by libcurl\n"); 1121 } 1122 } 1123 else if(result) 1124 goto show_error; 1125 } 1126 1127 if(config->crlfile) 1128 my_setopt_str(curl, CURLOPT_CRLFILE, config->crlfile); 1129 if(config->proxy_crlfile) 1130 my_setopt_str(curl, CURLOPT_PROXY_CRLFILE, config->proxy_crlfile); 1131 else if(config->crlfile) /* CURLOPT_PROXY_CRLFILE default is crlfile */ 1132 my_setopt_str(curl, CURLOPT_PROXY_CRLFILE, config->crlfile); 1133 1134 if(config->pinnedpubkey) 1135 my_setopt_str(curl, CURLOPT_PINNEDPUBLICKEY, config->pinnedpubkey); 1136 1137 if(curlinfo->features & CURL_VERSION_SSL) { 1138 my_setopt_str(curl, CURLOPT_SSLCERT, config->cert); 1139 my_setopt_str(curl, CURLOPT_PROXY_SSLCERT, config->proxy_cert); 1140 my_setopt_str(curl, CURLOPT_SSLCERTTYPE, config->cert_type); 1141 my_setopt_str(curl, CURLOPT_PROXY_SSLCERTTYPE, 1142 config->proxy_cert_type); 1143 my_setopt_str(curl, CURLOPT_SSLKEY, config->key); 1144 my_setopt_str(curl, CURLOPT_PROXY_SSLKEY, config->proxy_key); 1145 my_setopt_str(curl, CURLOPT_SSLKEYTYPE, config->key_type); 1146 my_setopt_str(curl, CURLOPT_PROXY_SSLKEYTYPE, 1147 config->proxy_key_type); 1148 1149 if(config->insecure_ok) { 1150 my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); 1151 my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); 1152 } 1153 else { 1154 my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); 1155 /* libcurl default is strict verifyhost -> 2L */ 1156 /* my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); */ 1157 } 1158 if(config->proxy_insecure_ok) { 1159 my_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 0L); 1160 my_setopt(curl, CURLOPT_PROXY_SSL_VERIFYHOST, 0L); 1161 } 1162 else { 1163 my_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 1L); 1164 } 1165 1166 if(config->verifystatus) 1167 my_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 1L); 1168 1169 if(config->falsestart) 1170 my_setopt(curl, CURLOPT_SSL_FALSESTART, 1L); 1171 1172 my_setopt_enum(curl, CURLOPT_SSLVERSION, 1173 config->ssl_version | config->ssl_version_max); 1174 my_setopt_enum(curl, CURLOPT_PROXY_SSLVERSION, 1175 config->proxy_ssl_version); 1176 } 1177 if(config->path_as_is) 1178 my_setopt(curl, CURLOPT_PATH_AS_IS, 1L); 1179 1180 if(built_in_protos & (CURLPROTO_SCP|CURLPROTO_SFTP)) { 1181 if(!config->insecure_ok) { 1182 char *home; 1183 char *file; 1184 result = CURLE_OUT_OF_MEMORY; 1185 home = homedir(); 1186 if(home) { 1187 file = aprintf("%s/%sssh/known_hosts", home, DOT_CHAR); 1188 if(file) { 1189 /* new in curl 7.19.6 */ 1190 result = res_setopt_str(curl, CURLOPT_SSH_KNOWNHOSTS, file); 1191 curl_free(file); 1192 if(result == CURLE_UNKNOWN_OPTION) 1193 /* libssh2 version older than 1.1.1 */ 1194 result = CURLE_OK; 1195 } 1196 Curl_safefree(home); 1197 } 1198 if(result) 1199 goto show_error; 1200 } 1201 } 1202 1203 if(config->no_body || config->remote_time) { 1204 /* no body or use remote time */ 1205 my_setopt(curl, CURLOPT_FILETIME, 1L); 1206 } 1207 1208 my_setopt(curl, CURLOPT_CRLF, config->crlf?1L:0L); 1209 my_setopt_slist(curl, CURLOPT_QUOTE, config->quote); 1210 my_setopt_slist(curl, CURLOPT_POSTQUOTE, config->postquote); 1211 my_setopt_slist(curl, CURLOPT_PREQUOTE, config->prequote); 1212 1213 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) 1214 if(config->cookie) 1215 my_setopt_str(curl, CURLOPT_COOKIE, config->cookie); 1216 1217 if(config->cookiefile) 1218 my_setopt_str(curl, CURLOPT_COOKIEFILE, config->cookiefile); 1219 1220 /* new in libcurl 7.9 */ 1221 if(config->cookiejar) 1222 my_setopt_str(curl, CURLOPT_COOKIEJAR, config->cookiejar); 1223 1224 /* new in libcurl 7.9.7 */ 1225 my_setopt(curl, CURLOPT_COOKIESESSION, config->cookiesession?1L:0L); 1226 #else 1227 if(config->cookie || config->cookiefile || config->cookiejar) { 1228 warnf(config->global, "cookie option(s) used even though cookie " 1229 "support is disabled!\n"); 1230 return CURLE_NOT_BUILT_IN; 1231 } 1232 #endif 1233 1234 my_setopt_enum(curl, CURLOPT_TIMECONDITION, (long)config->timecond); 1235 my_setopt(curl, CURLOPT_TIMEVALUE, (long)config->condtime); 1236 my_setopt_str(curl, CURLOPT_CUSTOMREQUEST, config->customrequest); 1237 customrequest_helper(config, config->httpreq, config->customrequest); 1238 my_setopt(curl, CURLOPT_STDERR, global->errors); 1239 1240 /* three new ones in libcurl 7.3: */ 1241 my_setopt_str(curl, CURLOPT_INTERFACE, config->iface); 1242 my_setopt_str(curl, CURLOPT_KRBLEVEL, config->krblevel); 1243 1244 progressbarinit(&progressbar, config); 1245 if((global->progressmode == CURL_PROGRESS_BAR) && 1246 !global->noprogress && !global->mute) { 1247 /* we want the alternative style, then we have to implement it 1248 ourselves! */ 1249 my_setopt(curl, CURLOPT_XFERINFOFUNCTION, tool_progress_cb); 1250 my_setopt(curl, CURLOPT_XFERINFODATA, &progressbar); 1251 } 1252 1253 /* new in libcurl 7.24.0: */ 1254 if(config->dns_servers) 1255 my_setopt_str(curl, CURLOPT_DNS_SERVERS, config->dns_servers); 1256 1257 /* new in libcurl 7.33.0: */ 1258 if(config->dns_interface) 1259 my_setopt_str(curl, CURLOPT_DNS_INTERFACE, config->dns_interface); 1260 if(config->dns_ipv4_addr) 1261 my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP4, config->dns_ipv4_addr); 1262 if(config->dns_ipv6_addr) 1263 my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP6, config->dns_ipv6_addr); 1264 1265 /* new in libcurl 7.6.2: */ 1266 my_setopt_slist(curl, CURLOPT_TELNETOPTIONS, config->telnet_options); 1267 1268 /* new in libcurl 7.7: */ 1269 my_setopt_str(curl, CURLOPT_RANDOM_FILE, config->random_file); 1270 my_setopt_str(curl, CURLOPT_EGDSOCKET, config->egd_file); 1271 my_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, 1272 (long)(config->connecttimeout * 1000)); 1273 1274 if(config->cipher_list) 1275 my_setopt_str(curl, CURLOPT_SSL_CIPHER_LIST, config->cipher_list); 1276 1277 if(config->proxy_cipher_list) 1278 my_setopt_str(curl, CURLOPT_PROXY_SSL_CIPHER_LIST, 1279 config->proxy_cipher_list); 1280 1281 /* new in libcurl 7.9.2: */ 1282 if(config->disable_epsv) 1283 /* disable it */ 1284 my_setopt(curl, CURLOPT_FTP_USE_EPSV, 0L); 1285 1286 /* new in libcurl 7.10.5 */ 1287 if(config->disable_eprt) 1288 /* disable it */ 1289 my_setopt(curl, CURLOPT_FTP_USE_EPRT, 0L); 1290 1291 if(global->tracetype != TRACE_NONE) { 1292 my_setopt(curl, CURLOPT_DEBUGFUNCTION, tool_debug_cb); 1293 my_setopt(curl, CURLOPT_DEBUGDATA, config); 1294 my_setopt(curl, CURLOPT_VERBOSE, 1L); 1295 } 1296 1297 /* new in curl 7.9.3 */ 1298 if(config->engine) { 1299 result = res_setopt_str(curl, CURLOPT_SSLENGINE, config->engine); 1300 if(result) 1301 goto show_error; 1302 } 1303 1304 /* new in curl 7.10.7, extended in 7.19.4. Modified to use 1305 CREATE_DIR_RETRY in 7.49.0 */ 1306 my_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS, 1307 (long)(config->ftp_create_dirs? 1308 CURLFTP_CREATE_DIR_RETRY: 1309 CURLFTP_CREATE_DIR_NONE)); 1310 1311 /* new in curl 7.10.8 */ 1312 if(config->max_filesize) 1313 my_setopt(curl, CURLOPT_MAXFILESIZE_LARGE, 1314 config->max_filesize); 1315 1316 if(4 == config->ip_version) 1317 my_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); 1318 else if(6 == config->ip_version) 1319 my_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); 1320 else 1321 my_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER); 1322 1323 /* new in curl 7.15.5 */ 1324 if(config->ftp_ssl_reqd) 1325 my_setopt_enum(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL); 1326 1327 /* new in curl 7.11.0 */ 1328 else if(config->ftp_ssl) 1329 my_setopt_enum(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_TRY); 1330 1331 /* new in curl 7.16.0 */ 1332 else if(config->ftp_ssl_control) 1333 my_setopt_enum(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_CONTROL); 1334 1335 /* new in curl 7.16.1 */ 1336 if(config->ftp_ssl_ccc) 1337 my_setopt_enum(curl, CURLOPT_FTP_SSL_CCC, 1338 (long)config->ftp_ssl_ccc_mode); 1339 1340 /* new in curl 7.19.4 */ 1341 if(config->socks5_gssapi_nec) 1342 my_setopt_str(curl, CURLOPT_SOCKS5_GSSAPI_NEC, 1343 config->socks5_gssapi_nec); 1344 1345 /* new in curl 7.55.0 */ 1346 if(config->socks5_auth) 1347 my_setopt_bitmask(curl, CURLOPT_SOCKS5_AUTH, 1348 (long)config->socks5_auth); 1349 1350 /* new in curl 7.43.0 */ 1351 if(config->proxy_service_name) 1352 my_setopt_str(curl, CURLOPT_PROXY_SERVICE_NAME, 1353 config->proxy_service_name); 1354 1355 /* new in curl 7.43.0 */ 1356 if(config->service_name) 1357 my_setopt_str(curl, CURLOPT_SERVICE_NAME, 1358 config->service_name); 1359 1360 /* curl 7.13.0 */ 1361 my_setopt_str(curl, CURLOPT_FTP_ACCOUNT, config->ftp_account); 1362 1363 my_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, config->ignorecl?1L:0L); 1364 1365 /* curl 7.14.2 */ 1366 my_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP, config->ftp_skip_ip?1L:0L); 1367 1368 /* curl 7.15.1 */ 1369 my_setopt(curl, CURLOPT_FTP_FILEMETHOD, (long)config->ftp_filemethod); 1370 1371 /* curl 7.15.2 */ 1372 if(config->localport) { 1373 my_setopt(curl, CURLOPT_LOCALPORT, (long)config->localport); 1374 my_setopt_str(curl, CURLOPT_LOCALPORTRANGE, 1375 (long)config->localportrange); 1376 } 1377 1378 /* curl 7.15.5 */ 1379 my_setopt_str(curl, CURLOPT_FTP_ALTERNATIVE_TO_USER, 1380 config->ftp_alternative_to_user); 1381 1382 /* curl 7.16.0 */ 1383 if(config->disable_sessionid) 1384 /* disable it */ 1385 my_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE, 0L); 1386 1387 /* curl 7.16.2 */ 1388 if(config->raw) { 1389 my_setopt(curl, CURLOPT_HTTP_CONTENT_DECODING, 0L); 1390 my_setopt(curl, CURLOPT_HTTP_TRANSFER_DECODING, 0L); 1391 } 1392 1393 /* curl 7.17.1 */ 1394 if(!config->nokeepalive) { 1395 my_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L); 1396 if(config->alivetime != 0) { 1397 my_setopt(curl, CURLOPT_TCP_KEEPIDLE, config->alivetime); 1398 my_setopt(curl, CURLOPT_TCP_KEEPINTVL, config->alivetime); 1399 } 1400 } 1401 else 1402 my_setopt(curl, CURLOPT_TCP_KEEPALIVE, 0L); 1403 1404 /* curl 7.20.0 */ 1405 if(config->tftp_blksize) 1406 my_setopt(curl, CURLOPT_TFTP_BLKSIZE, config->tftp_blksize); 1407 1408 if(config->mail_from) 1409 my_setopt_str(curl, CURLOPT_MAIL_FROM, config->mail_from); 1410 1411 if(config->mail_rcpt) 1412 my_setopt_slist(curl, CURLOPT_MAIL_RCPT, config->mail_rcpt); 1413 1414 /* curl 7.20.x */ 1415 if(config->ftp_pret) 1416 my_setopt(curl, CURLOPT_FTP_USE_PRET, 1L); 1417 1418 if(config->proto_present) 1419 my_setopt_flags(curl, CURLOPT_PROTOCOLS, config->proto); 1420 if(config->proto_redir_present) 1421 my_setopt_flags(curl, CURLOPT_REDIR_PROTOCOLS, config->proto_redir); 1422 1423 if(config->content_disposition 1424 && (urlnode->flags & GETOUT_USEREMOTE)) 1425 hdrcbdata.honor_cd_filename = TRUE; 1426 else 1427 hdrcbdata.honor_cd_filename = FALSE; 1428 1429 hdrcbdata.outs = &outs; 1430 hdrcbdata.heads = &heads; 1431 1432 my_setopt(curl, CURLOPT_HEADERFUNCTION, tool_header_cb); 1433 my_setopt(curl, CURLOPT_HEADERDATA, &hdrcbdata); 1434 1435 if(config->resolve) 1436 /* new in 7.21.3 */ 1437 my_setopt_slist(curl, CURLOPT_RESOLVE, config->resolve); 1438 1439 if(config->connect_to) 1440 /* new in 7.49.0 */ 1441 my_setopt_slist(curl, CURLOPT_CONNECT_TO, config->connect_to); 1442 1443 /* new in 7.21.4 */ 1444 if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) { 1445 if(config->tls_username) 1446 my_setopt_str(curl, CURLOPT_TLSAUTH_USERNAME, 1447 config->tls_username); 1448 if(config->tls_password) 1449 my_setopt_str(curl, CURLOPT_TLSAUTH_PASSWORD, 1450 config->tls_password); 1451 if(config->tls_authtype) 1452 my_setopt_str(curl, CURLOPT_TLSAUTH_TYPE, 1453 config->tls_authtype); 1454 if(config->proxy_tls_username) 1455 my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_USERNAME, 1456 config->proxy_tls_username); 1457 if(config->proxy_tls_password) 1458 my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_PASSWORD, 1459 config->proxy_tls_password); 1460 if(config->proxy_tls_authtype) 1461 my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_TYPE, 1462 config->proxy_tls_authtype); 1463 } 1464 1465 /* new in 7.22.0 */ 1466 if(config->gssapi_delegation) 1467 my_setopt_str(curl, CURLOPT_GSSAPI_DELEGATION, 1468 config->gssapi_delegation); 1469 1470 /* new in 7.25.0 and 7.44.0 */ 1471 { 1472 long mask = (config->ssl_allow_beast ? CURLSSLOPT_ALLOW_BEAST : 0) | 1473 (config->ssl_no_revoke ? CURLSSLOPT_NO_REVOKE : 0); 1474 if(mask) 1475 my_setopt_bitmask(curl, CURLOPT_SSL_OPTIONS, mask); 1476 } 1477 1478 if(config->proxy_ssl_allow_beast) 1479 my_setopt(curl, CURLOPT_PROXY_SSL_OPTIONS, 1480 (long)CURLSSLOPT_ALLOW_BEAST); 1481 1482 if(config->mail_auth) 1483 my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth); 1484 1485 /* new in 7.31.0 */ 1486 if(config->sasl_ir) 1487 my_setopt(curl, CURLOPT_SASL_IR, 1L); 1488 1489 if(config->nonpn) { 1490 my_setopt(curl, CURLOPT_SSL_ENABLE_NPN, 0L); 1491 } 1492 1493 if(config->noalpn) { 1494 my_setopt(curl, CURLOPT_SSL_ENABLE_ALPN, 0L); 1495 } 1496 1497 /* new in 7.40.0, abstract support added in 7.53.0 */ 1498 if(config->unix_socket_path) { 1499 if(config->abstract_unix_socket) { 1500 my_setopt_str(curl, CURLOPT_ABSTRACT_UNIX_SOCKET, 1501 config->unix_socket_path); 1502 } 1503 else { 1504 my_setopt_str(curl, CURLOPT_UNIX_SOCKET_PATH, 1505 config->unix_socket_path); 1506 } 1507 } 1508 /* new in 7.45.0 */ 1509 if(config->proto_default) 1510 my_setopt_str(curl, CURLOPT_DEFAULT_PROTOCOL, config->proto_default); 1511 1512 /* new in 7.47.0 */ 1513 if(config->expect100timeout > 0) 1514 my_setopt_str(curl, CURLOPT_EXPECT_100_TIMEOUT_MS, 1515 (long)(config->expect100timeout*1000)); 1516 1517 /* new in 7.48.0 */ 1518 if(config->tftp_no_options) 1519 my_setopt(curl, CURLOPT_TFTP_NO_OPTIONS, 1L); 1520 1521 /* initialize retry vars for loop below */ 1522 retry_sleep_default = (config->retry_delay) ? 1523 config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */ 1524 1525 retry_numretries = config->req_retry; 1526 retry_sleep = retry_sleep_default; /* ms */ 1527 retrystart = tvnow(); 1528 1529 #ifndef CURL_DISABLE_LIBCURL_OPTION 1530 if(global->libcurl) { 1531 result = easysrc_perform(); 1532 if(result) 1533 goto show_error; 1534 } 1535 #endif 1536 1537 for(;;) { 1538 #ifdef USE_METALINK 1539 if(!metalink && config->use_metalink) { 1540 /* If outs.metalink_parser is non-NULL, delete it first. */ 1541 if(outs.metalink_parser) 1542 metalink_parser_context_delete(outs.metalink_parser); 1543 outs.metalink_parser = metalink_parser_context_new(); 1544 if(outs.metalink_parser == NULL) { 1545 result = CURLE_OUT_OF_MEMORY; 1546 goto show_error; 1547 } 1548 fprintf(config->global->errors, 1549 "Metalink: parsing (%s) metalink/XML...\n", this_url); 1550 } 1551 else if(metalink) 1552 fprintf(config->global->errors, 1553 "Metalink: fetching (%s) from (%s)...\n", 1554 mlfile->filename, this_url); 1555 #endif /* USE_METALINK */ 1556 1557 #ifdef CURLDEBUG 1558 if(config->test_event_based) 1559 result = curl_easy_perform_ev(curl); 1560 else 1561 #endif 1562 result = curl_easy_perform(curl); 1563 1564 if(!result && !outs.stream && !outs.bytes) { 1565 /* we have received no data despite the transfer was successful 1566 ==> force cration of an empty output file (if an output file 1567 was specified) */ 1568 long cond_unmet = 0L; 1569 /* do not create (or even overwrite) the file in case we get no 1570 data because of unmet condition */ 1571 curl_easy_getinfo(curl, CURLINFO_CONDITION_UNMET, &cond_unmet); 1572 if(!cond_unmet && !tool_create_output_file(&outs)) 1573 result = CURLE_WRITE_ERROR; 1574 } 1575 1576 if(outs.is_cd_filename && outs.stream && !global->mute && 1577 outs.filename) 1578 printf("curl: Saved to filename '%s'\n", outs.filename); 1579 1580 /* if retry-max-time is non-zero, make sure we haven't exceeded the 1581 time */ 1582 if(retry_numretries && 1583 (!config->retry_maxtime || 1584 (tvdiff(tvnow(), retrystart) < 1585 config->retry_maxtime*1000L)) ) { 1586 enum { 1587 RETRY_NO, 1588 RETRY_TIMEOUT, 1589 RETRY_CONNREFUSED, 1590 RETRY_HTTP, 1591 RETRY_FTP, 1592 RETRY_LAST /* not used */ 1593 } retry = RETRY_NO; 1594 long response; 1595 if((CURLE_OPERATION_TIMEDOUT == result) || 1596 (CURLE_COULDNT_RESOLVE_HOST == result) || 1597 (CURLE_COULDNT_RESOLVE_PROXY == result) || 1598 (CURLE_FTP_ACCEPT_TIMEOUT == result)) 1599 /* retry timeout always */ 1600 retry = RETRY_TIMEOUT; 1601 else if(config->retry_connrefused && 1602 (CURLE_COULDNT_CONNECT == result)) { 1603 long oserrno; 1604 curl_easy_getinfo(curl, CURLINFO_OS_ERRNO, &oserrno); 1605 if(ECONNREFUSED == oserrno) 1606 retry = RETRY_CONNREFUSED; 1607 } 1608 else if((CURLE_OK == result) || 1609 (config->failonerror && 1610 (CURLE_HTTP_RETURNED_ERROR == result))) { 1611 /* If it returned OK. _or_ failonerror was enabled and it 1612 returned due to such an error, check for HTTP transient 1613 errors to retry on. */ 1614 char *effective_url = NULL; 1615 curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &effective_url); 1616 if(effective_url && 1617 checkprefix("http", effective_url)) { 1618 /* This was HTTP(S) */ 1619 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response); 1620 1621 switch(response) { 1622 case 500: /* Internal Server Error */ 1623 case 502: /* Bad Gateway */ 1624 case 503: /* Service Unavailable */ 1625 case 504: /* Gateway Timeout */ 1626 retry = RETRY_HTTP; 1627 /* 1628 * At this point, we have already written data to the output 1629 * file (or terminal). If we write to a file, we must rewind 1630 * or close/re-open the file so that the next attempt starts 1631 * over from the beginning. 1632 * 1633 * TODO: similar action for the upload case. We might need 1634 * to start over reading from a previous point if we have 1635 * uploaded something when this was returned. 1636 */ 1637 break; 1638 } 1639 } 1640 } /* if CURLE_OK */ 1641 else if(result) { 1642 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response); 1643 1644 if(response/100 == 4) 1645 /* 1646 * This is typically when the FTP server only allows a certain 1647 * amount of users and we are not one of them. All 4xx codes 1648 * are transient. 1649 */ 1650 retry = RETRY_FTP; 1651 } 1652 1653 if(retry) { 1654 static const char * const m[]={ 1655 NULL, 1656 "timeout", 1657 "connection refused", 1658 "HTTP error", 1659 "FTP error" 1660 }; 1661 1662 warnf(config->global, "Transient problem: %s " 1663 "Will retry in %ld seconds. " 1664 "%ld retries left.\n", 1665 m[retry], retry_sleep/1000L, retry_numretries); 1666 1667 tool_go_sleep(retry_sleep); 1668 retry_numretries--; 1669 if(!config->retry_delay) { 1670 retry_sleep *= 2; 1671 if(retry_sleep > RETRY_SLEEP_MAX) 1672 retry_sleep = RETRY_SLEEP_MAX; 1673 } 1674 if(outs.bytes && outs.filename && outs.stream) { 1675 int rc; 1676 /* We have written data to a output file, we truncate file 1677 */ 1678 if(!global->mute) 1679 fprintf(global->errors, "Throwing away %" 1680 CURL_FORMAT_CURL_OFF_T " bytes\n", 1681 outs.bytes); 1682 fflush(outs.stream); 1683 /* truncate file at the position where we started appending */ 1684 #ifdef HAVE_FTRUNCATE 1685 if(ftruncate(fileno(outs.stream), outs.init)) { 1686 /* when truncate fails, we can't just append as then we'll 1687 create something strange, bail out */ 1688 if(!global->mute) 1689 fprintf(global->errors, 1690 "failed to truncate, exiting\n"); 1691 result = CURLE_WRITE_ERROR; 1692 goto quit_urls; 1693 } 1694 /* now seek to the end of the file, the position where we 1695 just truncated the file in a large file-safe way */ 1696 rc = fseek(outs.stream, 0, SEEK_END); 1697 #else 1698 /* ftruncate is not available, so just reposition the file 1699 to the location we would have truncated it. This won't 1700 work properly with large files on 32-bit systems, but 1701 most of those will have ftruncate. */ 1702 rc = fseek(outs.stream, (long)outs.init, SEEK_SET); 1703 #endif 1704 if(rc) { 1705 if(!global->mute) 1706 fprintf(global->errors, 1707 "failed seeking to end of file, exiting\n"); 1708 result = CURLE_WRITE_ERROR; 1709 goto quit_urls; 1710 } 1711 outs.bytes = 0; /* clear for next round */ 1712 } 1713 continue; /* curl_easy_perform loop */ 1714 } 1715 } /* if retry_numretries */ 1716 else if(metalink) { 1717 /* Metalink: Decide to try the next resource or 1718 not. Basically, we want to try the next resource if 1719 download was not successful. */ 1720 long response; 1721 if(CURLE_OK == result) { 1722 /* TODO We want to try next resource when download was 1723 not successful. How to know that? */ 1724 char *effective_url = NULL; 1725 curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &effective_url); 1726 if(effective_url && 1727 curl_strnequal(effective_url, "http", 4)) { 1728 /* This was HTTP(S) */ 1729 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response); 1730 if(response != 200 && response != 206) { 1731 metalink_next_res = 1; 1732 fprintf(global->errors, 1733 "Metalink: fetching (%s) from (%s) FAILED " 1734 "(HTTP status code %ld)\n", 1735 mlfile->filename, this_url, response); 1736 } 1737 } 1738 } 1739 else { 1740 metalink_next_res = 1; 1741 fprintf(global->errors, 1742 "Metalink: fetching (%s) from (%s) FAILED (%s)\n", 1743 mlfile->filename, this_url, 1744 (errorbuffer[0]) ? 1745 errorbuffer : curl_easy_strerror(result)); 1746 } 1747 } 1748 if(metalink && !metalink_next_res) 1749 fprintf(global->errors, "Metalink: fetching (%s) from (%s) OK\n", 1750 mlfile->filename, this_url); 1751 1752 /* In all ordinary cases, just break out of loop here */ 1753 break; /* curl_easy_perform loop */ 1754 1755 } 1756 1757 if((global->progressmode == CURL_PROGRESS_BAR) && 1758 progressbar.calls) 1759 /* if the custom progress bar has been displayed, we output a 1760 newline here */ 1761 fputs("\n", progressbar.out); 1762 1763 if(config->writeout) 1764 ourWriteOut(curl, &outs, config->writeout); 1765 1766 /* 1767 ** Code within this loop may jump directly here to label 'show_error' 1768 ** in order to display an error message for CURLcode stored in 'res' 1769 ** variable and exit loop once that necessary writing and cleanup 1770 ** in label 'quit_urls' has been done. 1771 */ 1772 1773 show_error: 1774 1775 #ifdef __VMS 1776 if(is_vms_shell()) { 1777 /* VMS DCL shell behavior */ 1778 if(!global->showerror) 1779 vms_show = VMSSTS_HIDE; 1780 } 1781 else 1782 #endif 1783 if(config->synthetic_error) { 1784 ; 1785 } 1786 else if(result && global->showerror) { 1787 fprintf(global->errors, "curl: (%d) %s\n", result, (errorbuffer[0]) ? 1788 errorbuffer : curl_easy_strerror(result)); 1789 if(result == CURLE_SSL_CACERT) 1790 fputs(CURL_CA_CERT_ERRORMSG, global->errors); 1791 } 1792 1793 /* Fall through comment to 'quit_urls' label */ 1794 1795 /* 1796 ** Upon error condition and always that a message has already been 1797 ** displayed, code within this loop may jump directly here to label 1798 ** 'quit_urls' otherwise it should jump to 'show_error' label above. 1799 ** 1800 ** When 'res' variable is _not_ CURLE_OK loop will exit once that 1801 ** all code following 'quit_urls' has been executed. Otherwise it 1802 ** will loop to the beginning from where it may exit if there are 1803 ** no more urls left. 1804 */ 1805 1806 quit_urls: 1807 1808 /* Set file extended attributes */ 1809 if(!result && config->xattr && outs.fopened && outs.stream) { 1810 int rc = fwrite_xattr(curl, fileno(outs.stream)); 1811 if(rc) 1812 warnf(config->global, "Error setting extended attributes: %s\n", 1813 strerror(errno)); 1814 } 1815 1816 /* Close the file */ 1817 if(outs.fopened && outs.stream) { 1818 int rc = fclose(outs.stream); 1819 if(!result && rc) { 1820 /* something went wrong in the writing process */ 1821 result = CURLE_WRITE_ERROR; 1822 fprintf(global->errors, "(%d) Failed writing body\n", result); 1823 } 1824 } 1825 else if(!outs.s_isreg && outs.stream) { 1826 /* Dump standard stream buffered data */ 1827 int rc = fflush(outs.stream); 1828 if(!result && rc) { 1829 /* something went wrong in the writing process */ 1830 result = CURLE_WRITE_ERROR; 1831 fprintf(global->errors, "(%d) Failed writing body\n", result); 1832 } 1833 } 1834 1835 #ifdef __AMIGA__ 1836 if(!result && outs.s_isreg && outs.filename) { 1837 /* Set the url (up to 80 chars) as comment for the file */ 1838 if(strlen(url) > 78) 1839 url[79] = '\0'; 1840 SetComment(outs.filename, url); 1841 } 1842 #endif 1843 1844 #if defined(HAVE_UTIME) || \ 1845 (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) 1846 /* File time can only be set _after_ the file has been closed */ 1847 if(!result && config->remote_time && outs.s_isreg && outs.filename) { 1848 /* Ask libcurl if we got a remote file time */ 1849 long filetime = -1; 1850 curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime); 1851 if(filetime >= 0) 1852 setfiletime(filetime, outs.filename, config->global->errors); 1853 } 1854 #endif /* defined(HAVE_UTIME) || \ 1855 (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) */ 1856 1857 #ifdef USE_METALINK 1858 if(!metalink && config->use_metalink && result == CURLE_OK) { 1859 int rv = parse_metalink(config, &outs, this_url); 1860 if(rv == 0) 1861 fprintf(config->global->errors, "Metalink: parsing (%s) OK\n", 1862 this_url); 1863 else if(rv == -1) 1864 fprintf(config->global->errors, "Metalink: parsing (%s) FAILED\n", 1865 this_url); 1866 } 1867 else if(metalink && result == CURLE_OK && !metalink_next_res) { 1868 int rv = metalink_check_hash(global, mlfile, outs.filename); 1869 if(rv == 0) { 1870 metalink_next_res = 1; 1871 } 1872 } 1873 #endif /* USE_METALINK */ 1874 1875 /* No more business with this output struct */ 1876 if(outs.alloc_filename) 1877 Curl_safefree(outs.filename); 1878 #ifdef USE_METALINK 1879 if(outs.metalink_parser) 1880 metalink_parser_context_delete(outs.metalink_parser); 1881 #endif /* USE_METALINK */ 1882 memset(&outs, 0, sizeof(struct OutStruct)); 1883 hdrcbdata.outs = NULL; 1884 1885 /* Free loop-local allocated memory and close loop-local opened fd */ 1886 1887 Curl_safefree(outfile); 1888 Curl_safefree(this_url); 1889 1890 if(infdopen) 1891 close(infd); 1892 1893 if(metalink) { 1894 /* Should exit if error is fatal. */ 1895 if(is_fatal_error(result)) { 1896 break; 1897 } 1898 if(!metalink_next_res) 1899 break; 1900 mlres = mlres->next; 1901 if(mlres == NULL) 1902 /* TODO If metalink_next_res is 1 and mlres is NULL, 1903 * set res to error code 1904 */ 1905 break; 1906 } 1907 else 1908 if(urlnum > 1) { 1909 /* when url globbing, exit loop upon critical error */ 1910 if(is_fatal_error(result)) 1911 break; 1912 } 1913 else if(result) 1914 /* when not url globbing, exit loop upon any error */ 1915 break; 1916 1917 } /* loop to the next URL */ 1918 1919 /* Free loop-local allocated memory */ 1920 1921 Curl_safefree(uploadfile); 1922 1923 if(urls) { 1924 /* Free list of remaining URLs */ 1925 glob_cleanup(urls); 1926 urls = NULL; 1927 } 1928 1929 if(infilenum > 1) { 1930 /* when file globbing, exit loop upon critical error */ 1931 if(is_fatal_error(result)) 1932 break; 1933 } 1934 else if(result) 1935 /* when not file globbing, exit loop upon any error */ 1936 break; 1937 1938 } /* loop to the next globbed upload file */ 1939 1940 /* Free loop-local allocated memory */ 1941 1942 Curl_safefree(outfiles); 1943 1944 if(inglob) { 1945 /* Free list of globbed upload files */ 1946 glob_cleanup(inglob); 1947 inglob = NULL; 1948 } 1949 1950 /* Free this URL node data without destroying the 1951 the node itself nor modifying next pointer. */ 1952 Curl_safefree(urlnode->url); 1953 Curl_safefree(urlnode->outfile); 1954 Curl_safefree(urlnode->infile); 1955 urlnode->flags = 0; 1956 1957 /* 1958 ** Bail out upon critical errors or --fail-early 1959 */ 1960 if(is_fatal_error(result) || (result && global->fail_early)) 1961 goto quit_curl; 1962 1963 } /* for-loop through all URLs */ 1964 1965 /* 1966 ** Nested loops end here. 1967 */ 1968 1969 quit_curl: 1970 1971 /* Reset the global config variables */ 1972 global->noprogress = orig_noprogress; 1973 global->isatty = orig_isatty; 1974 1975 /* Free function-local referenced allocated memory */ 1976 Curl_safefree(httpgetfields); 1977 1978 /* Free list of given URLs */ 1979 clean_getout(config); 1980 1981 hdrcbdata.heads = NULL; 1982 1983 /* Close function-local opened file descriptors */ 1984 if(heads.fopened && heads.stream) 1985 fclose(heads.stream); 1986 1987 if(heads.alloc_filename) 1988 Curl_safefree(heads.filename); 1989 1990 /* Release metalink related resources here */ 1991 clean_metalink(config); 1992 1993 return result; 1994 } 1995 1996 CURLcode operate(struct GlobalConfig *config, int argc, argv_item_t argv[]) 1997 { 1998 CURLcode result = CURLE_OK; 1999 2000 /* Setup proper locale from environment */ 2001 #ifdef HAVE_SETLOCALE 2002 setlocale(LC_ALL, ""); 2003 #endif 2004 2005 /* Parse .curlrc if necessary */ 2006 if((argc == 1) || 2007 (!curl_strequal(argv[1], "-q") && 2008 !curl_strequal(argv[1], "--disable"))) { 2009 parseconfig(NULL, config); /* ignore possible failure */ 2010 2011 /* If we had no arguments then make sure a url was specified in .curlrc */ 2012 if((argc < 2) && (!config->first->url_list)) { 2013 helpf(config->errors, NULL); 2014 result = CURLE_FAILED_INIT; 2015 } 2016 } 2017 2018 if(!result) { 2019 /* Parse the command line arguments */ 2020 ParameterError res = parse_args(config, argc, argv); 2021 if(res) { 2022 result = CURLE_OK; 2023 2024 /* Check if we were asked for the help */ 2025 if(res == PARAM_HELP_REQUESTED) 2026 tool_help(); 2027 /* Check if we were asked for the manual */ 2028 else if(res == PARAM_MANUAL_REQUESTED) 2029 hugehelp(); 2030 /* Check if we were asked for the version information */ 2031 else if(res == PARAM_VERSION_INFO_REQUESTED) 2032 tool_version_info(); 2033 /* Check if we were asked to list the SSL engines */ 2034 else if(res == PARAM_ENGINES_REQUESTED) 2035 tool_list_engines(config->easy); 2036 else if(res == PARAM_LIBCURL_UNSUPPORTED_PROTOCOL) 2037 result = CURLE_UNSUPPORTED_PROTOCOL; 2038 else 2039 result = CURLE_FAILED_INIT; 2040 } 2041 else { 2042 #ifndef CURL_DISABLE_LIBCURL_OPTION 2043 if(config->libcurl) { 2044 /* Initialise the libcurl source output */ 2045 result = easysrc_init(); 2046 } 2047 #endif 2048 2049 /* Perform the main operations */ 2050 if(!result) { 2051 size_t count = 0; 2052 struct OperationConfig *operation = config->first; 2053 2054 /* Get the required aguments for each operation */ 2055 while(!result && operation) { 2056 result = get_args(operation, count++); 2057 2058 operation = operation->next; 2059 } 2060 2061 /* Set the current operation pointer */ 2062 config->current = config->first; 2063 2064 /* Perform each operation */ 2065 while(!result && config->current) { 2066 result = operate_do(config, config->current); 2067 2068 config->current = config->current->next; 2069 2070 if(config->current && config->current->easy) 2071 curl_easy_reset(config->current->easy); 2072 } 2073 2074 #ifndef CURL_DISABLE_LIBCURL_OPTION 2075 if(config->libcurl) { 2076 /* Cleanup the libcurl source output */ 2077 easysrc_cleanup(); 2078 2079 /* Dump the libcurl code if previously enabled */ 2080 dumpeasysrc(config); 2081 } 2082 #endif 2083 } 2084 else 2085 helpf(config->errors, "out of memory\n"); 2086 } 2087 } 2088 2089 return result; 2090 } 2091