aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/curl/src/tool_operate.c
diff options
context:
space:
mode:
authorAlexSm <alex@ydb.tech>2024-01-18 11:28:56 +0100
committerGitHub <noreply@github.com>2024-01-18 11:28:56 +0100
commit9d0a3761b3201e0d9db879a7adf91876ebdb0564 (patch)
tree541d11ac878c18efd7ebca81e35112aa0fef995b /contrib/libs/curl/src/tool_operate.c
parent404ef8886ecc9736bc58ade6da2fbd83b486a408 (diff)
downloadydb-9d0a3761b3201e0d9db879a7adf91876ebdb0564.tar.gz
Library import 8 (#1074)
* Library import 8 * Add contrib/libs/cxxsupp/libcxx/include/__verbose_abort
Diffstat (limited to 'contrib/libs/curl/src/tool_operate.c')
-rw-r--r--contrib/libs/curl/src/tool_operate.c466
1 files changed, 285 insertions, 181 deletions
diff --git a/contrib/libs/curl/src/tool_operate.c b/contrib/libs/curl/src/tool_operate.c
index 43c1c5e6c4..c805b7732b 100644
--- a/contrib/libs/curl/src/tool_operate.c
+++ b/contrib/libs/curl/src/tool_operate.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -45,8 +45,6 @@
# include <proto/dos.h>
#endif
-#include "strcase.h"
-
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
#include "curlx.h"
@@ -83,6 +81,7 @@
#include "tool_help.h"
#include "tool_hugehelp.h"
#include "tool_progress.h"
+#include "tool_ipfs.h"
#include "dynbuf.h"
#include "memdebug.h" /* keep this as LAST include */
@@ -205,14 +204,14 @@ static curl_off_t VmsSpecialSize(const char *name,
struct per_transfer *transfers; /* first node */
static struct per_transfer *transfersl; /* last node */
-static long all_pers;
+static curl_off_t all_pers;
/* add_per_transfer creates a new 'per_transfer' node in the linked
list of transfers */
static CURLcode add_per_transfer(struct per_transfer **per)
{
struct per_transfer *p;
- p = calloc(sizeof(struct per_transfer), 1);
+ p = calloc(1, sizeof(struct per_transfer));
if(!p)
return CURLE_OUT_OF_MEMORY;
if(!transfers)
@@ -306,7 +305,7 @@ static CURLcode pre_transfer(struct GlobalConfig *global,
if((per->infd == -1) || fstat(per->infd, &fileinfo))
#endif
{
- helpf(global->errors, "Can't open '%s'!\n", per->uploadfile);
+ helpf(tool_stderr, "Can't open '%s'", per->uploadfile);
if(per->infd != -1) {
close(per->infd);
per->infd = STDIN_FILENO;
@@ -319,15 +318,28 @@ static CURLcode pre_transfer(struct GlobalConfig *global,
if(S_ISREG(fileinfo.st_mode))
uploadfilesize = fileinfo.st_size;
+#ifdef DEBUGBUILD
+ /* allow dedicated test cases to override */
+ {
+ char *ev = getenv("CURL_UPLOAD_SIZE");
+ if(ev) {
+ int sz = atoi(ev);
+ uploadfilesize = (curl_off_t)sz;
+ }
+ }
+#endif
+
if(uploadfilesize != -1) {
struct OperationConfig *config = per->config; /* for the macro below */
#ifdef CURL_DISABLE_LIBCURL_OPTION
(void)config;
+ (void)global;
#endif
my_setopt(per->curl, CURLOPT_INFILESIZE_LARGE, uploadfilesize);
}
- per->input.fd = per->infd;
}
+ per->uploadfilesize = uploadfilesize;
+ per->start = tvnow();
return result;
}
@@ -382,6 +394,7 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
struct OutStruct *outs = &per->outs;
CURL *curl = per->curl;
struct OperationConfig *config = per->config;
+ int rc;
if(!curl || !config)
return result;
@@ -395,25 +408,26 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
#ifdef __VMS
if(is_vms_shell()) {
/* VMS DCL shell behavior */
- if(!global->showerror)
+ if(global->silent && !global->showerror)
vms_show = VMSSTS_HIDE;
}
else
#endif
- if(!config->synthetic_error && result && global->showerror) {
+ if(!config->synthetic_error && result &&
+ (!global->silent || global->showerror)) {
const char *msg = per->errorbuffer;
- fprintf(global->errors, "curl: (%d) %s\n", result,
+ fprintf(tool_stderr, "curl: (%d) %s\n", result,
(msg && msg[0]) ? msg : curl_easy_strerror(result));
if(result == CURLE_PEER_FAILED_VERIFICATION)
- fputs(CURL_CA_CERT_ERRORMSG, global->errors);
+ fputs(CURL_CA_CERT_ERRORMSG, tool_stderr);
}
else if(config->failwithbody) {
/* if HTTP response >= 400, return error */
long code = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
if(code >= 400) {
- if(global->showerror)
- fprintf(global->errors,
+ if(!global->silent || global->showerror)
+ fprintf(tool_stderr,
"curl: (%d) The requested URL returned error: %ld\n",
CURLE_HTTP_RETURNED_ERROR, code);
result = CURLE_HTTP_RETURNED_ERROR;
@@ -421,9 +435,9 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
}
/* Set file extended attributes */
if(!result && config->xattr && outs->fopened && outs->stream) {
- int rc = fwrite_xattr(curl, per->this_url, fileno(outs->stream));
+ rc = fwrite_xattr(curl, per->this_url, fileno(outs->stream));
if(rc)
- warnf(config->global, "Error setting extended attributes on '%s': %s\n",
+ warnf(config->global, "Error setting extended attributes on '%s': %s",
outs->filename, strerror(errno));
}
@@ -441,15 +455,20 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
if(!outs->s_isreg && outs->stream) {
/* Dump standard stream buffered data */
- int rc = fflush(outs->stream);
+ rc = fflush(outs->stream);
if(!result && rc) {
/* something went wrong in the writing process */
result = CURLE_WRITE_ERROR;
- if(global->showerror)
- fprintf(global->errors, "curl: (%d) Failed writing body\n", result);
+ errorf(global, "Failed writing body");
}
}
+#ifdef _WIN32
+ /* Discard incomplete UTF-8 sequence buffered from body */
+ if(outs->utf8seq[0])
+ memset(outs->utf8seq, 0, sizeof(outs->utf8seq));
+#endif
+
/* if retry-max-time is non-zero, make sure we haven't exceeded the
time */
if(per->retry_numretries &&
@@ -573,7 +592,7 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
}
warnf(config->global, "Problem %s. "
"Will retry in %ld seconds. "
- "%ld retries left.\n",
+ "%ld retries left.",
m[retry], sleeptime/1000L, per->retry_numretries);
per->retry_numretries--;
@@ -583,22 +602,18 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
per->retry_sleep = RETRY_SLEEP_MAX;
}
if(outs->bytes && outs->filename && outs->stream) {
- int rc;
/* We have written data to an output file, we truncate file
*/
- if(!global->mute)
- fprintf(global->errors, "Throwing away %"
- CURL_FORMAT_CURL_OFF_T " bytes\n",
- outs->bytes);
+ notef(config->global,
+ "Throwing away %" CURL_FORMAT_CURL_OFF_T " bytes",
+ 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(global->showerror)
- fprintf(global->errors,
- "curl: (23) Failed to truncate file\n");
+ errorf(config->global, "Failed to truncate file");
return CURLE_WRITE_ERROR;
}
/* now seek to the end of the file, the position where we
@@ -612,9 +627,7 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
rc = fseek(outs->stream, (long)outs->init, SEEK_SET);
#endif
if(rc) {
- if(global->showerror)
- fprintf(global->errors,
- "curl: (23) Failed seeking to end of file\n");
+ errorf(config->global, "Failed seeking to end of file");
return CURLE_WRITE_ERROR;
}
outs->bytes = 0; /* clear for next round */
@@ -624,7 +637,7 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
return CURLE_OK;
}
} /* if retry_numretries */
- noretry:
+noretry:
if((global->progressmode == CURL_PROGRESS_BAR) &&
per->progressbar.calls)
@@ -634,15 +647,14 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
/* Close the outs file */
if(outs->fopened && outs->stream) {
- int rc = fclose(outs->stream);
+ rc = fclose(outs->stream);
if(!result && rc) {
/* something went wrong in the writing process */
result = CURLE_WRITE_ERROR;
- if(global->showerror)
- fprintf(global->errors, "curl: (%d) Failed writing body\n", result);
+ errorf(config->global, "curl: (%d) Failed writing body", result);
}
if(result && config->rm_partial) {
- notef(global, "Removing output file: %s\n", outs->filename);
+ notef(global, "Removing output file: %s", outs->filename);
unlink(outs->filename);
}
}
@@ -659,7 +671,7 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
/* Write the --write-out data before cleanup but after result is final */
if(config->writeout)
- ourWriteOut(config->writeout, per, result);
+ ourWriteOut(config, per, result);
/* Close function-local opened file descriptors */
if(per->heads.fopened && per->heads.stream)
@@ -689,27 +701,45 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
/*
* Return the protocol token for the scheme used in the given URL
*/
-static const char *url_proto(char *url)
+static CURLcode url_proto(char **url,
+ struct OperationConfig *config,
+ char **scheme)
{
+ CURLcode result = CURLE_OK;
CURLU *uh = curl_url();
const char *proto = NULL;
+ *scheme = NULL;
if(uh) {
- if(url) {
- if(!curl_url_set(uh, CURLUPART_URL, url,
- CURLU_GUESS_SCHEME | CURLU_NON_SUPPORT_SCHEME)) {
- char *schemep = NULL;
- if(!curl_url_get(uh, CURLUPART_SCHEME, &schemep,
- CURLU_DEFAULT_SCHEME) &&
- schemep) {
- proto = proto_token(schemep);
- curl_free(schemep);
+ if(*url) {
+ char *schemep = NULL;
+
+ if(!curl_url_set(uh, CURLUPART_URL, *url,
+ CURLU_GUESS_SCHEME | CURLU_NON_SUPPORT_SCHEME) &&
+ !curl_url_get(uh, CURLUPART_SCHEME, &schemep,
+ CURLU_DEFAULT_SCHEME)) {
+ if(curl_strequal(schemep, proto_ipfs) ||
+ curl_strequal(schemep, proto_ipns)) {
+ result = ipfs_url_rewrite(uh, schemep, url, config);
+ /* short-circuit proto_token, we know it's ipfs or ipns */
+ if(curl_strequal(schemep, proto_ipfs))
+ proto = proto_ipfs;
+ else if(curl_strequal(schemep, proto_ipns))
+ proto = proto_ipns;
+ if(result)
+ config->synthetic_error = TRUE;
}
+ else
+ proto = proto_token(schemep);
+
+ curl_free(schemep);
}
}
curl_url_cleanup(uh);
}
- return proto? proto: "???"; /* Never match if not found. */
+
+ *scheme = (char *) (proto? proto: "???"); /* Never match if not found. */
+ return result;
}
/* create the next (singular) transfer */
@@ -725,16 +755,17 @@ static CURLcode single_transfer(struct GlobalConfig *global,
bool orig_isatty = global->isatty;
struct State *state = &config->state;
char *httpgetfields = state->httpgetfields;
+
*added = FALSE; /* not yet */
if(config->postfields) {
if(config->use_httpget) {
if(!httpgetfields) {
- /* Use the postfields data for a http get */
+ /* Use the postfields data for an HTTP get */
httpgetfields = state->httpgetfields = strdup(config->postfields);
Curl_safefree(config->postfields);
if(!httpgetfields) {
- errorf(global, "out of memory\n");
+ errorf(global, "out of memory");
result = CURLE_OUT_OF_MEMORY;
}
else if(SetHTTPrequest(config,
@@ -777,7 +808,7 @@ static CURLcode single_transfer(struct GlobalConfig *global,
state->up = 0;
if(!warn_more_options) {
/* only show this once */
- warnf(config->global, "Got more output options than URLs\n");
+ warnf(config->global, "Got more output options than URLs");
warn_more_options = TRUE;
}
continue; /* next URL please */
@@ -787,7 +818,7 @@ static CURLcode single_transfer(struct GlobalConfig *global,
if(urlnode->outfile && !state->outfiles) {
state->outfiles = strdup(urlnode->outfile);
if(!state->outfiles) {
- errorf(global, "out of memory\n");
+ errorf(global, "out of memory");
result = CURLE_OUT_OF_MEMORY;
break;
}
@@ -798,14 +829,15 @@ static CURLcode single_transfer(struct GlobalConfig *global,
if(!config->globoff && infiles && !inglob) {
/* Unless explicitly shut off */
result = glob_url(&inglob, infiles, &state->infilenum,
- global->showerror?global->errors:NULL);
+ (!global->silent || global->showerror)?
+ tool_stderr:NULL);
if(result)
break;
config->state.inglob = inglob;
}
{
- unsigned long urlnum;
+ curl_off_t urlnum;
if(!state->up && !infiles)
Curl_nop_stmt;
@@ -814,12 +846,12 @@ static CURLcode single_transfer(struct GlobalConfig *global,
if(inglob) {
result = glob_next_url(&state->uploadfile, inglob);
if(result == CURLE_OUT_OF_MEMORY)
- errorf(global, "out of memory\n");
+ errorf(global, "out of memory");
}
else if(!state->up) {
state->uploadfile = strdup(infiles);
if(!state->uploadfile) {
- errorf(global, "out of memory\n");
+ errorf(global, "out of memory");
result = CURLE_OUT_OF_MEMORY;
}
}
@@ -833,7 +865,8 @@ static CURLcode single_transfer(struct GlobalConfig *global,
/* Unless explicitly shut off, we expand '{...}' and '[...]'
expressions and return total number of URLs in pattern set */
result = glob_url(&state->urls, urlnode->url, &state->urlnum,
- global->showerror?global->errors:NULL);
+ (!global->silent || global->showerror)?
+ tool_stderr:NULL);
if(result)
break;
urlnum = state->urlnum;
@@ -847,12 +880,11 @@ static CURLcode single_transfer(struct GlobalConfig *global,
if(state->up < state->infilenum) {
struct per_transfer *per = NULL;
struct OutStruct *outs;
- struct InStruct *input;
struct OutStruct *heads;
struct OutStruct *etag_save;
struct HdrCbData *hdrcbdata = NULL;
struct OutStruct etag_first;
- const char *use_proto;
+ char *use_proto;
CURL *curl;
/* --etag-save */
@@ -870,7 +902,7 @@ static CURLcode single_transfer(struct GlobalConfig *global,
FILE *file = fopen(config->etag_compare_file, FOPEN_READTEXT);
if(!file && !config->etag_save_file) {
errorf(global,
- "Failed to open %s\n", config->etag_compare_file);
+ "Failed to open %s", config->etag_compare_file);
result = CURLE_READ_ERROR;
break;
}
@@ -887,7 +919,7 @@ static CURLcode single_transfer(struct GlobalConfig *global,
if(file)
fclose(file);
errorf(global,
- "Failed to allocate memory for custom etag header\n");
+ "Failed to allocate memory for custom etag header");
result = CURLE_OUT_OF_MEMORY;
break;
}
@@ -910,7 +942,7 @@ static CURLcode single_transfer(struct GlobalConfig *global,
FILE *newfile = fopen(config->etag_save_file, "wb");
if(!newfile) {
warnf(global, "Failed creating file for saving etags: \"%s\". "
- "Skip this transfer\n", config->etag_save_file);
+ "Skip this transfer", config->etag_save_file);
Curl_safefree(state->outfiles);
glob_cleanup(state->urls);
return CURLE_OK;
@@ -968,9 +1000,25 @@ static CURLcode single_transfer(struct GlobalConfig *global,
/* open file for output: */
if(strcmp(config->headerfile, "-")) {
FILE *newfile;
- newfile = fopen(config->headerfile, per->prev == NULL?"wb":"ab");
+
+ /*
+ * Since every transfer has its own file handle for dumping
+ * the headers, we need to open it in append mode, since transfers
+ * might finish in any order.
+ * The first transfer just clears the file.
+ * TODO: Consider placing the file handle inside the
+ * OperationConfig, so that it does not need to be opened/closed
+ * for every transfer.
+ */
+ if(!per->prev || per->prev->config != config) {
+ newfile = fopen(config->headerfile, "wb");
+ if(newfile)
+ fclose(newfile);
+ }
+ newfile = fopen(config->headerfile, "ab");
+
if(!newfile) {
- warnf(global, "Failed to open %s\n", config->headerfile);
+ errorf(global, "Failed to open %s", config->headerfile);
result = CURLE_WRITE_ERROR;
break;
}
@@ -990,7 +1038,6 @@ static CURLcode single_transfer(struct GlobalConfig *global,
hdrcbdata = &per->hdrcbdata;
outs = &per->outs;
- input = &per->input;
per->outfile = NULL;
per->infdopen = FALSE;
@@ -1037,11 +1084,11 @@ static CURLcode single_transfer(struct GlobalConfig *global,
result = get_url_file_name(&per->outfile, per->this_url);
if(result) {
errorf(global, "Failed to extract a sensible file name"
- " from the URL to use for storage!\n");
+ " from the URL to use for storage");
break;
}
if(!*per->outfile && !config->content_disposition) {
- errorf(global, "Remote file name has no length!\n");
+ errorf(global, "Remote file name has no length");
result = CURLE_WRITE_ERROR;
break;
}
@@ -1053,11 +1100,11 @@ static CURLcode single_transfer(struct GlobalConfig *global,
Curl_safefree(storefile);
if(result) {
/* bad globbing */
- warnf(global, "bad output glob!\n");
+ warnf(global, "bad output glob");
break;
}
if(!*per->outfile) {
- warnf(global, "output glob produces empty string!\n");
+ warnf(global, "output glob produces empty string");
result = CURLE_WRITE_ERROR;
break;
}
@@ -1076,7 +1123,7 @@ static CURLcode single_transfer(struct GlobalConfig *global,
file output call */
if(config->create_dirs) {
- result = create_dir_hierarchy(per->outfile, global->errors);
+ result = create_dir_hierarchy(per->outfile, global);
/* create_dir_hierarchy shows error upon CURLE_WRITE_ERROR */
if(result)
break;
@@ -1112,7 +1159,7 @@ static CURLcode single_transfer(struct GlobalConfig *global,
FILE *file = fopen(per->outfile, "ab");
#endif
if(!file) {
- errorf(global, "Can't open '%s'!\n", per->outfile);
+ errorf(global, "Can't open '%s'", per->outfile);
result = CURLE_WRITE_ERROR;
break;
}
@@ -1159,7 +1206,7 @@ static CURLcode single_transfer(struct GlobalConfig *global,
warnf(global,
"Using --anyauth or --proxy-anyauth with upload from stdin"
" involves a big risk of it not working. Use a temporary"
- " file or a fixed auth type instead!\n");
+ " file or a fixed auth type instead");
}
DEBUGASSERT(per->infdopen == FALSE);
@@ -1169,7 +1216,7 @@ static CURLcode single_transfer(struct GlobalConfig *global,
if(!strcmp(per->uploadfile, ".")) {
if(curlx_nonblock((curl_socket_t)per->infd, TRUE) < 0)
warnf(global,
- "fcntl failed on fd=%d: %s\n", per->infd, strerror(errno));
+ "fcntl failed on fd=%d: %s", per->infd, strerror(errno));
}
}
@@ -1188,28 +1235,38 @@ static CURLcode single_transfer(struct GlobalConfig *global,
global->isatty = orig_isatty;
}
- if(httpgetfields) {
+ if(httpgetfields || config->query) {
+ char *q = httpgetfields ? httpgetfields : config->query;
CURLU *uh = curl_url();
if(uh) {
- char *updated;
- if(curl_url_set(uh, CURLUPART_URL, per->this_url,
- CURLU_GUESS_SCHEME) ||
- curl_url_set(uh, CURLUPART_QUERY, httpgetfields,
- CURLU_APPENDQUERY) ||
- curl_url_get(uh, CURLUPART_URL, &updated, CURLU_GUESS_SCHEME)) {
- curl_url_cleanup(uh);
- result = CURLE_OUT_OF_MEMORY;
- break;
+ CURLUcode uerr;
+ uerr = curl_url_set(uh, CURLUPART_URL, per->this_url,
+ CURLU_GUESS_SCHEME);
+ if(uerr) {
+ result = urlerr_cvt(uerr);
+ errorf(global, "(%d) Could not parse the URL, "
+ "failed to set query", result);
+ config->synthetic_error = TRUE;
+ }
+ else {
+ char *updated = NULL;
+ uerr = curl_url_set(uh, CURLUPART_QUERY, q, CURLU_APPENDQUERY);
+ if(!uerr)
+ uerr = curl_url_get(uh, CURLUPART_URL, &updated,
+ CURLU_GUESS_SCHEME);
+ if(uerr)
+ result = urlerr_cvt(uerr);
+ else {
+ Curl_safefree(per->this_url); /* free previous URL */
+ per->this_url = updated; /* use our new URL instead! */
+ }
}
- Curl_safefree(per->this_url); /* free previous URL */
- per->this_url = updated; /* use our new URL instead! */
curl_url_cleanup(uh);
+ if(result)
+ break;
}
}
- if(!global->errors)
- global->errors = stderr;
-
if((!per->outfile || !strcmp(per->outfile, "-")) &&
!config->use_ascii) {
/* We get the output to stdout and we have not got the ASCII/text
@@ -1226,7 +1283,19 @@ static CURLcode single_transfer(struct GlobalConfig *global,
if(result)
break;
- use_proto = url_proto(per->this_url);
+ /* result is only used when for ipfs and ipns, ignored otherwise */
+ result = url_proto(&per->this_url, config, &use_proto);
+ if(result && (use_proto == proto_ipfs || use_proto == proto_ipns))
+ break;
+
+ /* On most modern OSes, exiting works thoroughly,
+ we'll clean everything up via exit(), so don't bother with
+ slow cleanups. Crappy ones might need to skip this.
+ Note: avoid having this setopt added to the --libcurl source
+ output. */
+ result = curl_easy_setopt(curl, CURLOPT_QUICK_EXIT, 1L);
+ if(result)
+ break;
if(!config->tcp_nodelay)
my_setopt(curl, CURLOPT_TCP_NODELAY, 0L);
@@ -1241,8 +1310,6 @@ static CURLcode single_transfer(struct GlobalConfig *global,
/* what call to write */
my_setopt(curl, CURLOPT_WRITEFUNCTION, tool_write_cb);
- /* for uploads */
- input->config = config;
/* Note that if CURLOPT_READFUNCTION is fread (the default), then
* lib/telnet.c will Curl_poll() on the input file descriptor
* rather than calling the READFUNCTION at regular intervals.
@@ -1250,24 +1317,36 @@ static CURLcode single_transfer(struct GlobalConfig *global,
* behavior, by omitting to set the READFUNCTION & READDATA options,
* have not been determined.
*/
- my_setopt(curl, CURLOPT_READDATA, input);
+ my_setopt(curl, CURLOPT_READDATA, per);
/* what call to read */
my_setopt(curl, CURLOPT_READFUNCTION, tool_read_cb);
/* in 7.18.0, the CURLOPT_SEEKFUNCTION/DATA pair is taking over what
CURLOPT_IOCTLFUNCTION/DATA pair previously provided for seeking */
- my_setopt(curl, CURLOPT_SEEKDATA, input);
+ my_setopt(curl, CURLOPT_SEEKDATA, per);
my_setopt(curl, CURLOPT_SEEKFUNCTION, tool_seek_cb);
- if(config->recvpersecond &&
- (config->recvpersecond < BUFFER_SIZE))
- /* use a smaller sized buffer for better sleeps */
- my_setopt(curl, CURLOPT_BUFFERSIZE, (long)config->recvpersecond);
- else
- my_setopt(curl, CURLOPT_BUFFERSIZE, (long)BUFFER_SIZE);
+ {
+#ifdef CURLDEBUG
+ char *env = getenv("CURL_BUFFERSIZE");
+ if(env) {
+ long size = strtol(env, NULL, 10);
+ if(size)
+ my_setopt(curl, CURLOPT_BUFFERSIZE, size);
+ }
+ else
+#endif
+ if(config->recvpersecond &&
+ (config->recvpersecond < BUFFER_SIZE))
+ /* use a smaller sized buffer for better sleeps */
+ my_setopt(curl, CURLOPT_BUFFERSIZE, (long)config->recvpersecond);
+ else
+ my_setopt(curl, CURLOPT_BUFFERSIZE, (long)BUFFER_SIZE);
+ }
my_setopt_str(curl, CURLOPT_URL, per->this_url);
- my_setopt(curl, CURLOPT_NOPROGRESS, global->noprogress?1L:0L);
+ my_setopt(curl, CURLOPT_NOPROGRESS,
+ global->noprogress || global->silent?1L:0L);
if(config->no_body)
my_setopt(curl, CURLOPT_NOBODY, 1L);
@@ -1277,7 +1356,7 @@ static CURLcode single_transfer(struct GlobalConfig *global,
my_setopt_str(curl, CURLOPT_PROXY, config->proxy);
if(config->proxy && result) {
- errorf(global, "proxy support is disabled in this libcurl\n");
+ errorf(global, "proxy support is disabled in this libcurl");
config->synthetic_error = TRUE;
result = CURLE_NOT_BUILT_IN;
break;
@@ -1344,23 +1423,34 @@ static CURLcode single_transfer(struct GlobalConfig *global,
per->errorbuffer = global_errorbuffer;
my_setopt(curl, CURLOPT_ERRORBUFFER, global_errorbuffer);
}
- my_setopt(curl, CURLOPT_TIMEOUT_MS, (long)(config->timeout * 1000));
+ my_setopt(curl, CURLOPT_TIMEOUT_MS, config->timeout_ms);
switch(config->httpreq) {
case HTTPREQ_SIMPLEPOST:
- my_setopt_str(curl, CURLOPT_POSTFIELDS,
- config->postfields);
- my_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE,
- config->postfieldsize);
+ if(config->resume_from) {
+ errorf(global, "cannot mix --continue-at with --data");
+ result = CURLE_FAILED_INIT;
+ }
+ else {
+ my_setopt_str(curl, CURLOPT_POSTFIELDS,
+ config->postfields);
+ my_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE,
+ config->postfieldsize);
+ }
break;
case HTTPREQ_MIMEPOST:
/* free previous remainders */
curl_mime_free(config->mimepost);
config->mimepost = NULL;
- result = tool2curlmime(curl, config->mimeroot, &config->mimepost);
- if(result)
- break;
- my_setopt_mimepost(curl, CURLOPT_MIMEPOST, config->mimepost);
+ if(config->resume_from) {
+ errorf(global, "cannot mix --continue-at with --form");
+ result = CURLE_FAILED_INIT;
+ }
+ else {
+ result = tool2curlmime(curl, config->mimeroot, &config->mimepost);
+ if(!result)
+ my_setopt_mimepost(curl, CURLOPT_MIMEPOST, config->mimepost);
+ }
break;
default:
break;
@@ -1390,13 +1480,13 @@ static CURLcode single_transfer(struct GlobalConfig *global,
config->followlocation?1L:0L);
my_setopt(curl, CURLOPT_UNRESTRICTED_AUTH,
config->unrestricted_auth?1L:0L);
-
+ my_setopt_str(curl, CURLOPT_AWS_SIGV4, config->aws_sigv4);
my_setopt(curl, CURLOPT_AUTOREFERER, config->autoreferer?1L:0L);
/* new in libcurl 7.36.0 */
if(config->proxyheaders) {
my_setopt_slist(curl, CURLOPT_PROXYHEADER, config->proxyheaders);
- my_setopt(curl, CURLOPT_HEADEROPT, CURLHEADER_SEPARATE);
+ my_setopt(curl, CURLOPT_HEADEROPT, (long)CURLHEADER_SEPARATE);
}
/* new in libcurl 7.5 */
@@ -1404,9 +1494,8 @@ static CURLcode single_transfer(struct GlobalConfig *global,
if(config->httpversion)
my_setopt_enum(curl, CURLOPT_HTTP_VERSION, config->httpversion);
- else if(curlinfo->features & CURL_VERSION_HTTP2) {
+ else if(feature_http2)
my_setopt_enum(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
- }
/* curl 7.19.1 (the 301 version existed in 7.18.2),
303 was added in 7.26.0 */
@@ -1429,7 +1518,7 @@ static CURLcode single_transfer(struct GlobalConfig *global,
my_setopt(curl, CURLOPT_HTTP09_ALLOWED,
config->http09_allowed ? 1L : 0L);
if(result) {
- errorf(global, "HTTP/0.9 is not supported in this build!\n");
+ errorf(global, "HTTP/0.9 is not supported in this build");
return result;
}
@@ -1454,7 +1543,6 @@ static CURLcode single_transfer(struct GlobalConfig *global,
my_setopt_str(curl, CURLOPT_PROXY_KEYPASSWD, config->proxy_key_passwd);
if(use_proto == proto_scp || use_proto == proto_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);
@@ -1484,7 +1572,7 @@ static CURLcode single_transfer(struct GlobalConfig *global,
if(config->capath) {
result = res_setopt_str(curl, CURLOPT_CAPATH, config->capath);
if(result == CURLE_NOT_BUILT_IN) {
- warnf(global, "ignoring %s, not supported by libcurl\n",
+ warnf(global, "ignoring %s, not supported by libcurl",
capath_from_env?
"SSL_CERT_DIR environment variable":"--capath");
}
@@ -1498,10 +1586,11 @@ static CURLcode single_transfer(struct GlobalConfig *global,
(config->proxy_capath ?
config->proxy_capath :
config->capath));
- if(result == CURLE_NOT_BUILT_IN) {
+ if((result == CURLE_NOT_BUILT_IN) ||
+ (result == CURLE_UNKNOWN_OPTION)) {
if(config->proxy_capath) {
warnf(global,
- "ignoring --proxy-capath, not supported by libcurl\n");
+ "ignoring --proxy-capath, not supported by libcurl");
}
}
else if(result)
@@ -1521,7 +1610,10 @@ static CURLcode single_transfer(struct GlobalConfig *global,
if(config->ssl_ec_curves)
my_setopt_str(curl, CURLOPT_SSL_EC_CURVES, config->ssl_ec_curves);
- if(curlinfo->features & CURL_VERSION_SSL) {
+ if(config->writeout)
+ my_setopt_str(curl, CURLOPT_CERTINFO, 1L);
+
+ if(feature_ssl) {
/* Check if config->cert is a PKCS#11 URI and set the
* config->cert_type if necessary */
if(config->cert) {
@@ -1651,9 +1743,6 @@ static CURLcode single_transfer(struct GlobalConfig *global,
my_setopt_str(curl, CURLOPT_SSLKEYTYPE, config->key_type);
my_setopt_str(curl, CURLOPT_PROXY_SSLKEYTYPE,
config->proxy_key_type);
- my_setopt_str(curl, CURLOPT_AWS_SIGV4,
- config->aws_sigv4);
-
if(config->insecure_ok) {
my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
@@ -1714,7 +1803,9 @@ static CURLcode single_transfer(struct GlobalConfig *global,
(config->proxy_ssl_allow_beast ?
CURLSSLOPT_ALLOW_BEAST : 0) |
(config->proxy_ssl_auto_client_cert ?
- CURLSSLOPT_AUTO_CLIENT_CERT : 0);
+ CURLSSLOPT_AUTO_CLIENT_CERT : 0) |
+ (config->proxy_native_ca_store ?
+ CURLSSLOPT_NATIVE_CA : 0);
if(mask)
my_setopt_bitmask(curl, CURLOPT_PROXY_SSL_OPTIONS, mask);
@@ -1738,7 +1829,7 @@ static CURLcode single_transfer(struct GlobalConfig *global,
break;
}
else
- warnf(global, "Couldn't find a known_hosts file!");
+ warnf(global, "Couldn't find a known_hosts file");
}
if(config->no_body || config->remote_time) {
@@ -1756,7 +1847,7 @@ static CURLcode single_transfer(struct GlobalConfig *global,
struct curl_slist *cl;
/* The maximum size needs to match MAX_NAME in cookie.h */
-#define MAX_COOKIE_LINE 4096
+#define MAX_COOKIE_LINE 8200
curlx_dyn_init(&cookies, MAX_COOKIE_LINE);
for(cl = config->cookies; cl; cl = cl->next) {
if(cl == config->cookies)
@@ -1767,7 +1858,7 @@ static CURLcode single_transfer(struct GlobalConfig *global,
if(result) {
warnf(global,
"skipped provided cookie, the cookie header "
- "would go over %u bytes\n", MAX_COOKIE_LINE);
+ "would go over %u bytes", MAX_COOKIE_LINE);
break;
}
}
@@ -1794,7 +1885,7 @@ static CURLcode single_transfer(struct GlobalConfig *global,
my_setopt(curl, CURLOPT_TIMEVALUE_LARGE, config->condtime);
my_setopt_str(curl, CURLOPT_CUSTOMREQUEST, config->customrequest);
customrequest_helper(config, config->httpreq, config->customrequest);
- my_setopt(curl, CURLOPT_STDERR, global->errors);
+ my_setopt(curl, CURLOPT_STDERR, tool_stderr);
/* three new ones in libcurl 7.3: */
my_setopt_str(curl, CURLOPT_INTERFACE, config->iface);
@@ -1802,7 +1893,7 @@ static CURLcode single_transfer(struct GlobalConfig *global,
progressbarinit(&per->progressbar, config);
if((global->progressmode == CURL_PROGRESS_BAR) &&
- !global->noprogress && !global->mute) {
+ !global->noprogress && !global->silent) {
/* we want the alternative style, then we have to implement it
ourselves! */
my_setopt(curl, CURLOPT_XFERINFOFUNCTION, tool_progress_cb);
@@ -1826,14 +1917,13 @@ static CURLcode single_transfer(struct GlobalConfig *global,
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_str(curl, CURLOPT_DNS_LOCAL_IP6, config->dns_ipv6_addr);
/* new in libcurl 7.6.2: */
my_setopt_slist(curl, CURLOPT_TELNETOPTIONS, config->telnet_options);
/* new in libcurl 7.7: */
- my_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS,
- (long)(config->connecttimeout * 1000));
+ my_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, config->connecttimeout_ms);
if(config->doh_url)
my_setopt_str(curl, CURLOPT_DOH_URL, config->doh_url);
@@ -1908,8 +1998,7 @@ static CURLcode single_transfer(struct GlobalConfig *global,
/* new in curl 7.19.4 */
if(config->socks5_gssapi_nec)
- my_setopt_str(curl, CURLOPT_SOCKS5_GSSAPI_NEC,
- config->socks5_gssapi_nec);
+ my_setopt_str(curl, CURLOPT_SOCKS5_GSSAPI_NEC, 1L);
/* new in curl 7.55.0 */
if(config->socks5_auth)
@@ -1981,8 +2070,8 @@ static CURLcode single_transfer(struct GlobalConfig *global,
my_setopt_slist(curl, CURLOPT_MAIL_RCPT, config->mail_rcpt);
/* curl 7.69.x */
- my_setopt(curl, CURLOPT_MAIL_RCPT_ALLLOWFAILS,
- config->mail_rcpt_allowfails ? 1L : 0L);
+ my_setopt(curl, CURLOPT_MAIL_RCPT_ALLOWFAILS,
+ config->mail_rcpt_allowfails ? 1L : 0L);
/* curl 7.20.x */
if(config->ftp_pret)
@@ -2021,7 +2110,7 @@ static CURLcode single_transfer(struct GlobalConfig *global,
my_setopt_slist(curl, CURLOPT_CONNECT_TO, config->connect_to);
/* new in 7.21.4 */
- if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
+ if(feature_tls_srp) {
if(config->tls_username)
my_setopt_str(curl, CURLOPT_TLSAUTH_USERNAME,
config->tls_username);
@@ -2079,9 +2168,9 @@ static CURLcode single_transfer(struct GlobalConfig *global,
my_setopt_str(curl, CURLOPT_DEFAULT_PROTOCOL, config->proto_default);
/* new in 7.47.0 */
- if(config->expect100timeout > 0)
+ if(config->expect100timeout_ms > 0)
my_setopt_str(curl, CURLOPT_EXPECT_100_TIMEOUT_MS,
- (long)(config->expect100timeout*1000));
+ config->expect100timeout_ms);
/* new in 7.48.0 */
if(config->tftp_no_options && proto_tftp)
@@ -2096,6 +2185,11 @@ static CURLcode single_transfer(struct GlobalConfig *global,
if(config->haproxy_protocol)
my_setopt(curl, CURLOPT_HAPROXYPROTOCOL, 1L);
+ /* new in 8.2.0 */
+ if(config->haproxy_clientip)
+ my_setopt_str(curl, CURLOPT_HAPROXY_CLIENT_IP,
+ config->haproxy_clientip);
+
if(config->disallow_username_in_url)
my_setopt(curl, CURLOPT_DISALLOW_USERNAME_IN_URL, 1L);
@@ -2298,7 +2392,8 @@ static CURLcode parallel_transfers(struct GlobalConfig *global,
curl_easy_getinfo(easy, CURLINFO_PRIVATE, (void *)&ended);
curl_multi_remove_handle(multi, easy);
- if(ended->abort && tres == CURLE_ABORTED_BY_CALLBACK) {
+ if(ended->abort && (tres == CURLE_ABORTED_BY_CALLBACK) &&
+ ended->errorbuffer) {
msnprintf(ended->errorbuffer, CURL_ERROR_SIZE,
"Transfer aborted due to critical error "
"in another transfer");
@@ -2379,7 +2474,7 @@ static CURLcode serial_transfers(struct GlobalConfig *global,
if(result)
return result;
if(!added) {
- errorf(global, "no transfer performed\n");
+ errorf(global, "no transfer performed");
return CURLE_READ_ERROR;
}
for(per = transfers; per;) {
@@ -2396,7 +2491,6 @@ static CURLcode serial_transfers(struct GlobalConfig *global,
if(result)
break;
}
-
start = tvnow();
#ifdef CURLDEBUG
if(global->test_event_based)
@@ -2417,8 +2511,10 @@ static CURLcode serial_transfers(struct GlobalConfig *global,
else {
/* setup the next one just before we delete this */
result = create_transfer(global, share, &added);
- if(result)
+ if(result) {
+ returncode = result;
bailout = TRUE;
+ }
}
per = del_per_transfer(per);
@@ -2431,7 +2527,7 @@ static CURLcode serial_transfers(struct GlobalConfig *global,
milliseconds */
long milli = tvdiff(tvnow(), start);
if(milli < global->ms_per_transfer) {
- notef(global, "Transfer took %ld ms, waits %ldms as set by --rate\n",
+ notef(global, "Transfer took %ld ms, waits %ldms as set by --rate",
milli, global->ms_per_transfer - milli);
/* The transfer took less time than wanted. Wait a little. */
tool_go_sleep(global->ms_per_transfer - milli);
@@ -2460,7 +2556,7 @@ static CURLcode transfer_per_config(struct GlobalConfig *global,
/* Check we have a url */
if(!config->url_list || !config->url_list->url) {
- helpf(global->errors, "no URL specified!\n");
+ helpf(tool_stderr, "(%d) no URL specified", CURLE_FAILED_INIT);
return CURLE_FAILED_INIT;
}
@@ -2507,7 +2603,7 @@ static CURLcode transfer_per_config(struct GlobalConfig *global,
if(!config->cacert) {
curl_free(env);
curl_easy_cleanup(curltls);
- errorf(global, "out of memory\n");
+ errorf(global, "out of memory");
return CURLE_OUT_OF_MEMORY;
}
}
@@ -2518,28 +2614,29 @@ static CURLcode transfer_per_config(struct GlobalConfig *global,
if(!config->capath) {
curl_free(env);
curl_easy_cleanup(curltls);
- helpf(global->errors, "out of memory\n");
+ errorf(global, "out of memory");
return CURLE_OUT_OF_MEMORY;
}
+ curl_free(env);
capath_from_env = true;
}
- else {
- env = curlx_getenv("SSL_CERT_FILE");
- if(env) {
- config->cacert = strdup(env);
- if(!config->cacert) {
- curl_free(env);
- curl_easy_cleanup(curltls);
- errorf(global, "out of memory\n");
- return CURLE_OUT_OF_MEMORY;
- }
+ env = curlx_getenv("SSL_CERT_FILE");
+ if(env) {
+ config->cacert = strdup(env);
+ if(!config->cacert) {
+ curl_free(env);
+ if(capath_from_env)
+ free(config->capath);
+ curl_easy_cleanup(curltls);
+ errorf(global, "out of memory");
+ return CURLE_OUT_OF_MEMORY;
}
}
}
if(env)
curl_free(env);
-#ifdef WIN32
+#ifdef _WIN32
else {
result = FindWin32CACert(config, tls_backend_info->backend,
TEXT("curl-ca-bundle.crt"));
@@ -2622,9 +2719,10 @@ CURLcode operate(struct GlobalConfig *global, int argc, argv_item_t argv[])
CURLcode result = CURLE_OK;
char *first_arg = argc > 1 ? curlx_convert_tchar_to_UTF8(argv[1]) : NULL;
- /* Setup proper locale from environment */
#ifdef HAVE_SETLOCALE
+ /* Override locale for number parsing (only) */
setlocale(LC_ALL, "");
+ setlocale(LC_NUMERIC, "C");
#endif
/* Parse .curlrc if necessary */
@@ -2635,7 +2733,7 @@ CURLcode operate(struct GlobalConfig *global, int argc, argv_item_t argv[])
/* If we had no arguments then make sure a url was specified in .curlrc */
if((argc < 2) && (!global->first->url_list)) {
- helpf(global->errors, NULL);
+ helpf(tool_stderr, NULL);
result = CURLE_FAILED_INIT;
}
}
@@ -2683,41 +2781,47 @@ CURLcode operate(struct GlobalConfig *global, int argc, argv_item_t argv[])
/* Cleanup the libcurl source output */
easysrc_cleanup();
}
- return CURLE_OUT_OF_MEMORY;
+ result = CURLE_OUT_OF_MEMORY;
}
- curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
- curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
- curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
- curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
- curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_PSL);
+ if(!result) {
+ curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
+ curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
+ curl_share_setopt(share, CURLSHOPT_SHARE,
+ CURL_LOCK_DATA_SSL_SESSION);
+ curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
+ curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_PSL);
+ curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_HSTS);
- /* Get the required arguments for each operation */
- do {
- result = get_args(operation, count++);
+ /* Get the required arguments for each operation */
+ do {
+ result = get_args(operation, count++);
- operation = operation->next;
- } while(!result && operation);
+ operation = operation->next;
+ } while(!result && operation);
- /* Set the current operation pointer */
- global->current = global->first;
+ /* Set the current operation pointer */
+ global->current = global->first;
- /* now run! */
- result = run_all_transfers(global, share, result);
+ /* now run! */
+ result = run_all_transfers(global, share, result);
- curl_share_cleanup(share);
- if(global->libcurl) {
- /* Cleanup the libcurl source output */
- easysrc_cleanup();
+ curl_share_cleanup(share);
+ if(global->libcurl) {
+ /* Cleanup the libcurl source output */
+ easysrc_cleanup();
- /* Dump the libcurl code if previously enabled */
- dumpeasysrc(global);
+ /* Dump the libcurl code if previously enabled */
+ dumpeasysrc(global);
+ }
}
}
else
- errorf(global, "out of memory\n");
+ errorf(global, "out of memory");
}
}
+ varcleanup(global);
+
return result;
}