Newer
Older
/* new in libcurl 7.21.6 */
if(config->tr_encoding)
my_setopt(curl, CURLOPT_TRANSFER_ENCODING, 1L);
} /* (built_in_protos & CURLPROTO_HTTP) */
my_setopt_str(curl, CURLOPT_FTPPORT, config->ftpport);
my_setopt(curl, CURLOPT_LOW_SPEED_LIMIT,
config->low_speed_limit);
my_setopt(curl, CURLOPT_LOW_SPEED_TIME, config->low_speed_time);
my_setopt(curl, CURLOPT_MAX_SEND_SPEED_LARGE,
config->sendpersecond);
my_setopt(curl, CURLOPT_MAX_RECV_SPEED_LARGE,
config->recvpersecond);
if(config->use_resume)
my_setopt(curl, CURLOPT_RESUME_FROM_LARGE, config->resume_from);
else
my_setopt(curl, CURLOPT_RESUME_FROM_LARGE, CURL_OFF_T_C(0));
my_setopt_str(curl, CURLOPT_SSLCERT, config->cert);
my_setopt_str(curl, CURLOPT_SSLCERTTYPE, config->cert_type);
my_setopt_str(curl, CURLOPT_SSLKEY, config->key);
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
my_setopt_str(curl, CURLOPT_SSLKEYTYPE, config->key_type);
my_setopt_str(curl, CURLOPT_KEYPASSWD, config->key_passwd);
if(built_in_protos & (CURLPROTO_SCP|CURLPROTO_SFTP)) {
/* SSH and SSL private key uses same command-line option */
/* new in libcurl 7.16.1 */
my_setopt_str(curl, CURLOPT_SSH_PRIVATE_KEYFILE, config->key);
/* new in libcurl 7.16.1 */
my_setopt_str(curl, CURLOPT_SSH_PUBLIC_KEYFILE, config->pubkey);
/* new in libcurl 7.17.1: SSH host key md5 checking allows us
to fail if we are not talking to who we think we should */
my_setopt_str(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
config->hostpubmd5);
}
if(config->cacert)
my_setopt_str(curl, CURLOPT_CAINFO, config->cacert);
if(config->capath)
my_setopt_str(curl, CURLOPT_CAPATH, config->capath);
if(config->crlfile)
my_setopt_str(curl, CURLOPT_CRLFILE, config->crlfile);
if(curlinfo->features & CURL_VERSION_SSL) {
if(config->insecure_ok) {
my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
}
else {
my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
/* libcurl default is strict verifyhost -> 2L */
/* my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); */
}
}
if(built_in_protos & (CURLPROTO_SCP|CURLPROTO_SFTP)) {
if(!config->insecure_ok) {
char *home;
char *file;
res = CURLE_OUT_OF_MEMORY;
home = homedir();
if(home) {
file = aprintf("%s/%sssh/known_hosts", home, DOT_CHAR);
if(file) {
/* new in curl 7.19.6 */
res = res_setopt_str(curl, CURLOPT_SSH_KNOWNHOSTS, file);
curl_free(file);
if(res == CURLE_UNKNOWN_OPTION)
/* libssh2 version older than 1.1.1 */
res = CURLE_OK;
}
}
if(res)
goto show_error;
}
}
if(config->no_body || config->remote_time) {
/* no body or use remote time */
my_setopt(curl, CURLOPT_FILETIME, 1L);
my_setopt(curl, CURLOPT_CRLF, config->crlf?1L:0L);
my_setopt_slist(curl, CURLOPT_QUOTE, config->quote);
my_setopt_slist(curl, CURLOPT_POSTQUOTE, config->postquote);
my_setopt_slist(curl, CURLOPT_PREQUOTE, config->prequote);
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
{
/* TODO: Make this a run-time check instead of compile-time one. */
if(config->cookie)
my_setopt_str(curl, CURLOPT_COOKIE, config->cookie);
if(config->cookiefile)
my_setopt_str(curl, CURLOPT_COOKIEFILE, config->cookiefile);
/* new in libcurl 7.9 */
if(config->cookiejar)
my_setopt_str(curl, CURLOPT_COOKIEJAR, config->cookiejar);
/* new in libcurl 7.9.7 */
my_setopt(curl, CURLOPT_COOKIESESSION, config->cookiesession?1L:0L);
my_setopt_enum(curl, CURLOPT_SSLVERSION, config->ssl_version);
my_setopt_enum(curl, CURLOPT_TIMECONDITION, (long)config->timecond);
my_setopt(curl, CURLOPT_TIMEVALUE, (long)config->condtime);
my_setopt_str(curl, CURLOPT_CUSTOMREQUEST, config->customrequest);
my_setopt(curl, CURLOPT_STDERR, config->errors);
/* three new ones in libcurl 7.3: */
my_setopt_str(curl, CURLOPT_INTERFACE, config->iface);
my_setopt_str(curl, CURLOPT_KRBLEVEL, config->krblevel);
progressbarinit(&progressbar, config);
if((config->progressmode == CURL_PROGRESS_BAR) &&
!config->noprogress && !config->mute) {
/* we want the alternative style, then we have to implement it
ourselves! */
my_setopt(curl, CURLOPT_XFERINFOFUNCTION, tool_progress_cb);
my_setopt(curl, CURLOPT_XFERINFODATA, &progressbar);
/* new in libcurl 7.24.0: */
if(config->dns_servers)
my_setopt_str(curl, CURLOPT_DNS_SERVERS, config->dns_servers);
/* new in libcurl 7.33.0: */
if(config->dns_interface)
my_setopt_str(curl, CURLOPT_DNS_INTERFACE, config->dns_interface);
if(config->dns_ipv4_addr)
my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP4, config->dns_ipv4_addr);
if(config->dns_ipv6_addr)
my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP6, config->dns_ipv6_addr);
my_setopt_slist(curl, CURLOPT_TELNETOPTIONS, config->telnet_options);
/* new in libcurl 7.7: */
my_setopt_str(curl, CURLOPT_RANDOM_FILE, config->random_file);
my_setopt_str(curl, CURLOPT_EGDSOCKET, config->egd_file);
my_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS,
(long)(config->connecttimeout * 1000));
if(config->cipher_list)
my_setopt_str(curl, CURLOPT_SSL_CIPHER_LIST, config->cipher_list);
/* new in libcurl 7.9.2: */
if(config->disable_epsv)
/* disable it */
my_setopt(curl, CURLOPT_FTP_USE_EPSV, 0L);
/* new in libcurl 7.10.5 */
if(config->disable_eprt)
/* disable it */
my_setopt(curl, CURLOPT_FTP_USE_EPRT, 0L);
if(config->tracetype != TRACE_NONE) {
my_setopt(curl, CURLOPT_DEBUGFUNCTION, tool_debug_cb);
my_setopt(curl, CURLOPT_DEBUGDATA, config);
my_setopt(curl, CURLOPT_VERBOSE, 1L);
}
/* new in curl 7.9.3 */
if(config->engine) {
res = res_setopt_str(curl, CURLOPT_SSLENGINE, config->engine);
if(res)
goto show_error;
my_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1L);
}
/* new in curl 7.10.7, extended in 7.19.4 but this only sets 0 or 1 */
my_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS,
config->ftp_create_dirs?1L:0L);
/* new in curl 7.10.8 */
if(config->max_filesize)
my_setopt(curl, CURLOPT_MAXFILESIZE_LARGE,
config->max_filesize);
if(4 == config->ip_version)
my_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
else if(6 == config->ip_version)
my_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
else
my_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER);
/* new in curl 7.15.5 */
if(config->ftp_ssl_reqd)
my_setopt_enum(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
/* new in curl 7.11.0 */
else if(config->ftp_ssl)
my_setopt_enum(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_TRY);
/* new in curl 7.16.0 */
else if(config->ftp_ssl_control)
my_setopt_enum(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_CONTROL);
/* new in curl 7.16.1 */
if(config->ftp_ssl_ccc)
my_setopt_enum(curl, CURLOPT_FTP_SSL_CCC,
(long)config->ftp_ssl_ccc_mode);
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
{
/* TODO: Make this a run-time check instead of compile-time one. */
/* new in curl 7.19.4 */
if(config->socks5_gssapi_service)
my_setopt_str(curl, CURLOPT_SOCKS5_GSSAPI_SERVICE,
config->socks5_gssapi_service);
/* new in curl 7.19.4 */
if(config->socks5_gssapi_nec)
my_setopt_str(curl, CURLOPT_SOCKS5_GSSAPI_NEC,
config->socks5_gssapi_nec);
}
#endif
/* curl 7.13.0 */
my_setopt_str(curl, CURLOPT_FTP_ACCOUNT, config->ftp_account);
my_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, config->ignorecl?1L:0L);
my_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP, config->ftp_skip_ip?1L:0L);
my_setopt(curl, CURLOPT_FTP_FILEMETHOD, (long)config->ftp_filemethod);
/* curl 7.15.2 */
if(config->localport) {
my_setopt(curl, CURLOPT_LOCALPORT, (long)config->localport);
my_setopt_str(curl, CURLOPT_LOCALPORTRANGE,
(long)config->localportrange);
}
/* curl 7.15.5 */
my_setopt_str(curl, CURLOPT_FTP_ALTERNATIVE_TO_USER,
config->ftp_alternative_to_user);
/* curl 7.16.0 */
if(config->disable_sessionid)
/* disable it */
my_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE, 0L);
/* curl 7.16.2 */
if(config->raw) {
my_setopt(curl, CURLOPT_HTTP_CONTENT_DECODING, 0L);
my_setopt(curl, CURLOPT_HTTP_TRANSFER_DECODING, 0L);
}
/* curl 7.17.1 */
if(!config->nokeepalive) {
my_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
if(config->alivetime != 0) {
#if !defined(TCP_KEEPIDLE) || !defined(TCP_KEEPINTVL)
warnf(config, "Keep-alive functionality somewhat crippled due to "
"missing support in your operating system!\n");
#endif
my_setopt(curl, CURLOPT_TCP_KEEPIDLE, config->alivetime);
my_setopt(curl, CURLOPT_TCP_KEEPINTVL, config->alivetime);
}
else
my_setopt(curl, CURLOPT_TCP_KEEPALIVE, 0L);
/* curl 7.20.0 */
if(config->tftp_blksize)
my_setopt(curl, CURLOPT_TFTP_BLKSIZE, config->tftp_blksize);
if(config->mail_from)
my_setopt_str(curl, CURLOPT_MAIL_FROM, config->mail_from);
if(config->mail_rcpt)
my_setopt_slist(curl, CURLOPT_MAIL_RCPT, config->mail_rcpt);
/* curl 7.20.x */
if(config->ftp_pret)
my_setopt(curl, CURLOPT_FTP_USE_PRET, 1L);
my_setopt_flags(curl, CURLOPT_PROTOCOLS, config->proto);
my_setopt_flags(curl, CURLOPT_REDIR_PROTOCOLS, config->proto_redir);
if(config->content_disposition
&& (urlnode->flags & GETOUT_USEREMOTE)
&& (checkprefix("http://", this_url) ||
checkprefix("https://", this_url)))
hdrcbdata.honor_cd_filename = TRUE;
else
hdrcbdata.honor_cd_filename = FALSE;
hdrcbdata.outs = &outs;
hdrcbdata.heads = &heads;
my_setopt(curl, CURLOPT_HEADERFUNCTION, tool_header_cb);
my_setopt(curl, CURLOPT_HEADERDATA, &hdrcbdata);
if(config->resolve)
/* new in 7.21.3 */
my_setopt_slist(curl, CURLOPT_RESOLVE, config->resolve);
/* new in 7.21.4 */
if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
if(config->tls_username)
my_setopt_str(curl, CURLOPT_TLSAUTH_USERNAME,
config->tls_username);
if(config->tls_password)
my_setopt_str(curl, CURLOPT_TLSAUTH_PASSWORD,
config->tls_password);
if(config->tls_authtype)
my_setopt_str(curl, CURLOPT_TLSAUTH_TYPE,
config->tls_authtype);
}
/* new in 7.22.0 */
if(config->gssapi_delegation)
my_setopt_str(curl, CURLOPT_GSSAPI_DELEGATION,
config->gssapi_delegation);
/* new in 7.25.0 */
if(config->ssl_allow_beast)
my_setopt(curl, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_ALLOW_BEAST);
if(config->mail_auth)
my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth);
if(config->sasl_ir)
my_setopt(curl, CURLOPT_SASL_IR, 1L);
if(config->nonpn) {
my_setopt(curl, CURLOPT_SSL_ENABLE_NPN, 0L);
}
if(config->noalpn) {
my_setopt(curl, CURLOPT_SSL_ENABLE_ALPN, 0L);
}
/* initialize retry vars for loop below */
retry_sleep_default = (config->retry_delay) ?
config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */
retry_numretries = config->req_retry;
retry_sleep = retry_sleep_default; /* ms */
#ifndef CURL_DISABLE_LIBCURL_OPTION
res = easysrc_perform();
if(res) {
#ifdef USE_METALINK
if(!metalink && config->use_metalink) {
/* If outs.metalink_parser is non-NULL, delete it first. */
if(outs.metalink_parser)
metalink_parser_context_delete(outs.metalink_parser);
outs.metalink_parser = metalink_parser_context_new();
if(outs.metalink_parser == NULL) {
res = CURLE_OUT_OF_MEMORY;
goto show_error;
}
fprintf(config->errors, "Metalink: parsing (%s) metalink/XML...\n",
this_url);
else if(metalink)
fprintf(config->errors, "Metalink: fetching (%s) from (%s)...\n",
mlfile->filename, this_url);
#endif /* USE_METALINK */
#ifdef CURLDEBUG
if(config->test_event_based)
res = curl_easy_perform_ev(curl);
else
#endif
res = curl_easy_perform(curl);
if(outs.is_cd_filename && outs.stream && !config->mute &&
outs.filename)
printf("curl: Saved to filename '%s'\n", outs.filename);
/* if retry-max-time is non-zero, make sure we haven't exceeded the
time */
if(retry_numretries &&
(!config->retry_maxtime ||
(tvdiff(tvnow(), retrystart) <
config->retry_maxtime*1000L)) ) {
enum {
RETRY_NO,
RETRY_TIMEOUT,
RETRY_HTTP,
RETRY_FTP,
RETRY_LAST /* not used */
} retry = RETRY_NO;
long response;
if((CURLE_OPERATION_TIMEDOUT == res) ||
(CURLE_COULDNT_RESOLVE_HOST == res) ||
(CURLE_COULDNT_RESOLVE_PROXY == res) ||
(CURLE_FTP_ACCEPT_TIMEOUT == res))
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
/* retry timeout always */
retry = RETRY_TIMEOUT;
else if((CURLE_OK == res) ||
(config->failonerror &&
(CURLE_HTTP_RETURNED_ERROR == res))) {
/* If it returned OK. _or_ failonerror was enabled and it
returned due to such an error, check for HTTP transient
errors to retry on. */
char *effective_url = NULL;
curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &effective_url);
if(effective_url &&
checkprefix("http", effective_url)) {
/* This was HTTP(S) */
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
switch(response) {
case 500: /* Internal Server Error */
case 502: /* Bad Gateway */
case 503: /* Service Unavailable */
case 504: /* Gateway Timeout */
retry = RETRY_HTTP;
/*
* At this point, we have already written data to the output
* file (or terminal). If we write to a file, we must rewind
* or close/re-open the file so that the next attempt starts
* over from the beginning.
*
* TODO: similar action for the upload case. We might need
* to start over reading from a previous point if we have
* uploaded something when this was returned.
*/
break;
}
}
} /* if CURLE_OK */
else if(res) {
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
if(response/100 == 4)
/*
* This is typically when the FTP server only allows a certain
* amount of users and we are not one of them. All 4xx codes
* are transient.
*/
retry = RETRY_FTP;
}
if(retry) {
static const char * const m[]={
NULL, "timeout", "HTTP error", "FTP error"
};
warnf(config, "Transient problem: %s "
"Will retry in %ld seconds. "
"%ld retries left.\n",
m[retry], retry_sleep/1000L, retry_numretries);
tool_go_sleep(retry_sleep);
retry_numretries--;
if(!config->retry_delay) {
retry_sleep *= 2;
if(retry_sleep > RETRY_SLEEP_MAX)
retry_sleep = RETRY_SLEEP_MAX;
}
if(outs.bytes && outs.filename) {
/* We have written data to a output file, we truncate file
*/
if(!config->mute)
fprintf(config->errors, "Throwing away %"
CURL_FORMAT_CURL_OFF_T " bytes\n",
outs.bytes);
fflush(outs.stream);
/* truncate file at the position where we started appending */
#ifdef HAVE_FTRUNCATE
if(ftruncate( fileno(outs.stream), outs.init)) {
/* when truncate fails, we can't just append as then we'll
create something strange, bail out */
if(!config->mute)
fprintf(config->errors,
"failed to truncate, exiting\n");
res = CURLE_WRITE_ERROR;
goto quit_urls;
}
/* now seek to the end of the file, the position where we
just truncated the file in a large file-safe way */
fseek(outs.stream, 0, SEEK_END);
#else
/* ftruncate is not available, so just reposition the file
to the location we would have truncated it. This won't
work properly with large files on 32-bit systems, but
most of those will have ftruncate. */
fseek(outs.stream, (long)outs.init, SEEK_SET);
#endif
outs.bytes = 0; /* clear for next round */
}
continue; /* curl_easy_perform loop */
}
} /* if retry_numretries */
else if(metalink) {
/* Metalink: Decide to try the next resource or
not. Basically, we want to try the next resource if
download was not successful. */
long response;
if(CURLE_OK == res) {
/* TODO We want to try next resource when download was
not successful. How to know that? */
char *effective_url = NULL;
curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &effective_url);
if(effective_url &&
curlx_strnequal(effective_url, "http", 4)) {
/* This was HTTP(S) */
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
if(response != 200 && response != 206) {
metalink_next_res = 1;
fprintf(config->errors,
"Metalink: fetching (%s) from (%s) FAILED "
"(HTTP status code %d)\n",
mlfile->filename, this_url, response);
metalink_next_res = 1;
fprintf(config->errors,
"Metalink: fetching (%s) from (%s) FAILED (%s)\n",
mlfile->filename, this_url,
(errorbuffer[0]) ?
errorbuffer : curl_easy_strerror((CURLcode)res));
}
if(metalink && !metalink_next_res)
fprintf(config->errors, "Metalink: fetching (%s) from (%s) OK\n",
mlfile->filename, this_url);
/* In all ordinary cases, just break out of loop here */
break; /* curl_easy_perform loop */
}
if((config->progressmode == CURL_PROGRESS_BAR) &&
progressbar.calls)
/* if the custom progress bar has been displayed, we output a
newline here */
fputs("\n", progressbar.out);
if(config->writeout)
ourWriteOut(curl, &outs, config->writeout);
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
if(config->writeenv)
ourWriteEnv(curl);
/*
** Code within this loop may jump directly here to label 'show_error'
** in order to display an error message for CURLcode stored in 'res'
** variable and exit loop once that necessary writing and cleanup
** in label 'quit_urls' has been done.
*/
show_error:
#ifdef __VMS
if(is_vms_shell()) {
/* VMS DCL shell behavior */
if(!config->showerror)
vms_show = VMSSTS_HIDE;
}
else
#endif
if(res && config->showerror) {
fprintf(config->errors, "curl: (%d) %s\n", res, (errorbuffer[0]) ?
errorbuffer : curl_easy_strerror((CURLcode)res));
if(res == CURLE_SSL_CACERT)
fprintf(config->errors, "%s%s",
CURL_CA_CERT_ERRORMSG1, CURL_CA_CERT_ERRORMSG2);
}
/* Fall through comment to 'quit_urls' label */
/*
** Upon error condition and always that a message has already been
** displayed, code within this loop may jump directly here to label
** 'quit_urls' otherwise it should jump to 'show_error' label above.
**
** When 'res' variable is _not_ CURLE_OK loop will exit once that
** all code following 'quit_urls' has been executed. Otherwise it
** will loop to the beginning from where it may exit if there are
** no more urls left.
*/
quit_urls:
/* Set file extended attributes */
if(!res && config->xattr && outs.fopened && outs.stream) {
int rc = fwrite_xattr(curl, fileno(outs.stream));
if(rc)
warnf(config, "Error setting extended attributes: %s\n",
strerror(errno));
}
/* Close the file */
if(outs.fopened && outs.stream) {
int rc = fclose(outs.stream);
if(!res && rc) {
/* something went wrong in the writing process */
res = CURLE_WRITE_ERROR;
fprintf(config->errors, "(%d) Failed writing body\n", res);
}
}
else if(!outs.s_isreg && outs.stream) {
/* Dump standard stream buffered data */
int rc = fflush(outs.stream);
if(!res && rc) {
/* something went wrong in the writing process */
res = CURLE_WRITE_ERROR;
fprintf(config->errors, "(%d) Failed writing body\n", res);
}
}
#ifdef __AMIGA__
if(!res && outs.s_isreg && outs.filename) {
/* Set the url (up to 80 chars) as comment for the file */
if(strlen(url) > 78)
url[79] = '\0';
SetComment(outs.filename, url);
}
#endif
#ifdef HAVE_UTIME
/* File time can only be set _after_ the file has been closed */
if(!res && config->remote_time && outs.s_isreg && outs.filename) {
/* Ask libcurl if we got a remote file time */
long filetime = -1;
curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime);
if(filetime >= 0) {
struct utimbuf times;
times.actime = (time_t)filetime;
times.modtime = (time_t)filetime;
utime(outs.filename, ×); /* set the time we got */
}
}
#endif
if(!metalink && config->use_metalink && res == CURLE_OK) {
int rv = parse_metalink(config, &outs, this_url);
if(rv == 0)
fprintf(config->errors, "Metalink: parsing (%s) OK\n", this_url);
else if(rv == -1)
fprintf(config->errors, "Metalink: parsing (%s) FAILED\n",
this_url);
else if(metalink && res == CURLE_OK && !metalink_next_res) {
int rv = metalink_check_hash(config, mlfile, outs.filename);
if(rv == 0) {
metalink_next_res = 1;
}
}
/* No more business with this output struct */
if(outs.alloc_filename)
Curl_safefree(outs.filename);
#ifdef USE_METALINK
if(outs.metalink_parser)
metalink_parser_context_delete(outs.metalink_parser);
#endif /* USE_METALINK */
memset(&outs, 0, sizeof(struct OutStruct));
hdrcbdata.outs = NULL;
/* Free loop-local allocated memory and close loop-local opened fd */
Curl_safefree(outfile);
Curl_safefree(this_url);
if(infdopen)
/* Should exit if error is fatal. */
if(is_fatal_error(res)) {
break;
}
if(!metalink_next_res)
break;
mlres = mlres->next;
if(mlres == NULL)
/* TODO If metalink_next_res is 1 and mlres is NULL,
* set res to error code
*/
else
if(urlnum > 1) {
/* when url globbing, exit loop upon critical error */
if(is_fatal_error(res))
break;
}
else if(res)
/* when not url globbing, exit loop upon any error */
break;
} /* loop to the next URL */
/* Free loop-local allocated memory */
Curl_safefree(uploadfile);
if(urls) {
/* Free list of remaining URLs */
glob_cleanup(urls);
urls = NULL;
}
if(infilenum > 1) {
/* when file globbing, exit loop upon critical error */
if(is_fatal_error(res))
break;
}
else if(res)
/* when not file globbing, exit loop upon any error */
break;
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
} /* loop to the next globbed upload file */
/* Free loop-local allocated memory */
Curl_safefree(outfiles);
if(inglob) {
/* Free list of globbed upload files */
glob_cleanup(inglob);
inglob = NULL;
}
/* Free this URL node data without destroying the
the node itself nor modifying next pointer. */
Curl_safefree(urlnode->url);
Curl_safefree(urlnode->outfile);
Curl_safefree(urlnode->infile);
urlnode->flags = 0;
/*
** Bail out upon critical errors
*/
if(is_fatal_error(res))
goto quit_curl;
} /* for-loop through all URLs */
/*
** Nested loops end here.
*/
quit_curl:
/* Free function-local referenced allocated memory */
Curl_safefree(httpgetfields);
/* Free list of given URLs */
clean_getout(config);
#ifndef CURL_DISABLE_LIBCURL_OPTION
easysrc_cleanup();
hdrcbdata.heads = NULL;
/* Close function-local opened file descriptors */
if(heads.fopened && heads.stream)
fclose(heads.stream);
if(heads.alloc_filename)
Curl_safefree(heads.filename);
#ifndef CURL_DISABLE_LIBCURL_OPTION
/* Dump the libcurl code if previously enabled.
NOTE: that this function relies on config->errors amongst other things
so not everything can be closed and cleaned before this is called */
dumpeasysrc(config);
return (CURLcode)res;
static void operate_free(struct OperationConfig *config)
if(config->easy) {
curl_easy_cleanup(config->easy);
config->easy = NULL;
}
/* Release metalink related resources here */
clean_metalink(config);
CURLcode operate(struct OperationConfig *config, int argc, argv_item_t argv[])
CURLcode result = CURLE_OK;
/* Initialize the easy interface */
result = operate_init(config);
if(result)
return result;
/* Parse .curlrc if necessary */
if((argc == 1) || (!curlx_strequal(argv[1], "-q"))) {
parseconfig(NULL, config); /* ignore possible failure */
/* If we had no arguments then make sure a url was specified in .curlrc */
if((argc < 2) && (!config->url_list)) {
helpf(config->errors, NULL);
result = CURLE_FAILED_INIT;
}
}
if(!result) {
/* Parse the command line arguments */
ParameterError res = parse_args(config, argc, argv);
if(res) {
result = CURLE_OK;
/* Check if we were asked for the help */
if(res == PARAM_HELP_REQUESTED)
tool_help();
/* Check if we were asked for the manual */
else if(res == PARAM_MANUAL_REQUESTED)
/* Check if we were asked for the version information */
else if(res == PARAM_VERSION_INFO_REQUESTED)
tool_version_info();
/* Check if we were asked to list the SSL engines */
else if(res == PARAM_ENGINES_REQUESTED)
tool_list_engines(config->easy);
result = CURLE_FAILED_INIT;
/* Perform the main operations */
else {
size_t count = 0;
struct OperationConfig *operation = config;
/* Get the required aguments for each operation */
while(!result && operation) {
result = get_args(operation, count++);
operation = operation->next;
}
/* Reset the operation pointer */
operation = config;
/* Perform each operation */
while(!result && operation) {
result = operate_do(operation);
operation = operation->next;
}
}
/* Perform the cleanup */
operate_free(config);
return result;