mirror of
https://github.com/moparisthebest/curl
synced 2025-03-11 07:39:50 -04:00
Now offering support for multiple -T on the same command line, just make
sure you have one URL for each -T. A -T file name can also be "globbed" like -T "{file1,file2}". Test case 149 verifies this functionality.
This commit is contained in:
parent
e92b7c73bc
commit
93a29c3c45
171
src/main.c
171
src/main.c
@ -143,7 +143,6 @@ typedef enum {
|
||||
#define CONF_NOPROGRESS (1<<10) /* shut off the progress meter */
|
||||
#define CONF_NOBODY (1<<11) /* use HEAD to get http document */
|
||||
#define CONF_FAILONERROR (1<<12) /* no output on http error codes >= 300 */
|
||||
#define CONF_UPLOAD (1<<14) /* this is an upload */
|
||||
#define CONF_FTPLISTONLY (1<<16) /* Use NLST when listing ftp dir */
|
||||
#define CONF_FTPAPPEND (1<<20) /* Append instead of overwrite on upload! */
|
||||
#define CONF_NETRC (1<<22) /* read user+password from .netrc */
|
||||
@ -353,14 +352,18 @@ static void helpf(const char *fmt, ...)
|
||||
* contents.
|
||||
*/
|
||||
struct getout {
|
||||
struct getout *next;
|
||||
char *url;
|
||||
char *outfile;
|
||||
int flags;
|
||||
struct getout *next; /* next one */
|
||||
char *url; /* the URL we deal with */
|
||||
char *outfile; /* where to store the output */
|
||||
char *infile; /* file to upload, if GETOUT_UPLOAD is set */
|
||||
int flags; /* options */
|
||||
};
|
||||
#define GETOUT_OUTFILE (1<<0) /* set when outfile is deemed done */
|
||||
#define GETOUT_URL (1<<1) /* set when URL is deemed done */
|
||||
#define GETOUT_USEREMOTE (1<<2) /* use remote file name locally */
|
||||
#define GETOUT_UPLOAD (1<<3) /* if set, -T has been used */
|
||||
#define GETOUT_NOUPLOAD (1<<4) /* if set, -T "" has been used */
|
||||
|
||||
|
||||
static void help(void)
|
||||
{
|
||||
@ -508,7 +511,6 @@ struct Configurable {
|
||||
int low_speed_limit;
|
||||
int low_speed_time;
|
||||
bool showerror;
|
||||
char *infile;
|
||||
char *userpwd;
|
||||
char *proxyuserpwd;
|
||||
char *proxy;
|
||||
@ -675,6 +677,8 @@ void clean_getout(struct Configurable *config)
|
||||
free(node->url);
|
||||
if(node->outfile)
|
||||
free(node->outfile);
|
||||
if(node->infile)
|
||||
free(node->infile);
|
||||
free(node);
|
||||
|
||||
node = next; /* GOTO next */
|
||||
@ -1756,10 +1760,34 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
break;
|
||||
case 'T':
|
||||
/* we are uploading */
|
||||
config->conf |= CONF_UPLOAD;
|
||||
if(!curl_strequal("-", nextarg))
|
||||
/* make - equal stdin */
|
||||
GetStr(&config->infile, nextarg);
|
||||
{
|
||||
struct getout *url;
|
||||
if(config->url_out || (config->url_out=config->url_list)) {
|
||||
/* there's a node here, if it already is filled-in continue to find
|
||||
an "empty" node */
|
||||
while(config->url_out && (config->url_out->flags&GETOUT_UPLOAD))
|
||||
config->url_out = config->url_out->next;
|
||||
}
|
||||
|
||||
/* now there might or might not be an available node to fill in! */
|
||||
|
||||
if(config->url_out)
|
||||
/* existing node */
|
||||
url = config->url_out;
|
||||
else
|
||||
/* there was no free node, create one! */
|
||||
url=new_getout(config);
|
||||
|
||||
if(url) {
|
||||
url->flags |= GETOUT_UPLOAD; /* mark -T used */
|
||||
if(!*nextarg)
|
||||
url->flags |= GETOUT_NOUPLOAD;
|
||||
else {
|
||||
/* "-" equals stdin, but keep the string around for now */
|
||||
GetStr(&url->infile, nextarg);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
/* user:password */
|
||||
@ -2408,8 +2436,6 @@ void free_config_fields(struct Configurable *config)
|
||||
free(config->headerfile);
|
||||
if(config->ftpport)
|
||||
free(config->ftpport);
|
||||
if(config->infile)
|
||||
free(config->infile);
|
||||
if(config->range)
|
||||
free(config->range);
|
||||
if(config->customrequest)
|
||||
@ -2479,14 +2505,20 @@ operate(struct Configurable *config, int argc, char *argv[])
|
||||
char *url = NULL;
|
||||
|
||||
URLGlob *urls=NULL;
|
||||
URLGlob *inglob=NULL;
|
||||
int urlnum;
|
||||
int infilenum;
|
||||
char *outfiles;
|
||||
char *infiles; /* might a glob pattern */
|
||||
char *uploadfile=NULL; /* a single file, never a glob */
|
||||
|
||||
int separator = 0;
|
||||
|
||||
FILE *infd = stdin;
|
||||
FILE *infd;
|
||||
bool infdfopen;
|
||||
FILE *headerfilep = NULL;
|
||||
char *urlbuffer=NULL;
|
||||
long infilesize=-1; /* -1 means unknown */
|
||||
long uploadfilesize; /* -1 means unknown */
|
||||
bool stillflags=TRUE;
|
||||
|
||||
bool allocuseragent=FALSE;
|
||||
@ -2496,6 +2528,7 @@ operate(struct Configurable *config, int argc, char *argv[])
|
||||
CURL *curl;
|
||||
int res = 0;
|
||||
int i;
|
||||
int up; /* upload file counter within a single upload glob */
|
||||
|
||||
char *env;
|
||||
#ifdef CURLDEBUG
|
||||
@ -2678,9 +2711,12 @@ operate(struct Configurable *config, int argc, char *argv[])
|
||||
|
||||
/* loop through the list of given URLs */
|
||||
while(urlnode && !res) {
|
||||
char *dourl;
|
||||
|
||||
/* get the full URL (it might be NULL) */
|
||||
url=urlnode->url;
|
||||
dourl=urlnode->url;
|
||||
|
||||
url = dourl;
|
||||
|
||||
if(NULL == url) {
|
||||
/* This node had no URL, skip it and continue to the next */
|
||||
@ -2698,10 +2734,14 @@ operate(struct Configurable *config, int argc, char *argv[])
|
||||
outs.stream = stdout;
|
||||
outs.config = config;
|
||||
|
||||
if(!config->globoff) {
|
||||
/* Unless explicitly shut off, we expand '{...}' and '[...]' expressions
|
||||
and return total number of URLs in pattern set */
|
||||
res = glob_url(&urls, url, &urlnum,
|
||||
/* save outfile pattern before expansion */
|
||||
outfiles = urlnode->outfile?strdup(urlnode->outfile):NULL;
|
||||
|
||||
infiles = urlnode->infile;
|
||||
|
||||
if(!config->globoff && infiles) {
|
||||
/* Unless explicitly shut off */
|
||||
res = glob_url(&inglob, infiles, &infilenum,
|
||||
config->showerror?
|
||||
(config->errors?config->errors:stderr):NULL);
|
||||
if(res != CURLE_OK) {
|
||||
@ -2710,14 +2750,31 @@ operate(struct Configurable *config, int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
/* Here's the loop for uploading multiple files within the same
|
||||
single globbed string. If no upload, we enter the loop once anyway. */
|
||||
for(up = 0;
|
||||
(!up && !infiles) ||
|
||||
(uploadfile = inglob?
|
||||
glob_next_url(inglob):
|
||||
(!up?strdup(infiles):NULL));
|
||||
up++) {
|
||||
uploadfilesize=-1;
|
||||
|
||||
/* save outfile pattern before expansion */
|
||||
outfiles = urlnode->outfile?strdup(urlnode->outfile):NULL;
|
||||
|
||||
if ((!outfiles || curl_strequal(outfiles, "-")) && urlnum > 1) {
|
||||
/* multiple files extracted to stdout, insert separators! */
|
||||
separator = 1;
|
||||
if(!config->globoff) {
|
||||
/* Unless explicitly shut off, we expand '{...}' and '[...]'
|
||||
expressions and return total number of URLs in pattern set */
|
||||
res = glob_url(&urls, dourl, &urlnum,
|
||||
config->showerror?
|
||||
(config->errors?config->errors:stderr):NULL);
|
||||
if(res != CURLE_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* if multiple files extracted to stdout, insert separators! */
|
||||
separator= ((!outfiles || curl_strequal(outfiles, "-")) && urlnum > 1);
|
||||
|
||||
/* Here's looping around each globbed URL */
|
||||
for(i = 0;
|
||||
(url = urls?glob_next_url(urls):(i?NULL:strdup(url)));
|
||||
i++) {
|
||||
@ -2813,9 +2870,10 @@ operate(struct Configurable *config, int argc, char *argv[])
|
||||
outs.stream = NULL; /* open when needed */
|
||||
}
|
||||
}
|
||||
if(config->infile) {
|
||||
infdfopen=FALSE;
|
||||
if(uploadfile && !curl_strequal(uploadfile, "-")) {
|
||||
/*
|
||||
* We have specified a file to upload
|
||||
* We have specified a file to upload and it isn't "-".
|
||||
*/
|
||||
struct stat fileinfo;
|
||||
|
||||
@ -2833,15 +2891,15 @@ operate(struct Configurable *config, int argc, char *argv[])
|
||||
|
||||
/* We only want the part of the local path that is on the right
|
||||
side of the rightmost slash and backslash. */
|
||||
char *filep = strrchr(config->infile, '/');
|
||||
char *file2 = strrchr(filep?filep:config->infile, '\\');
|
||||
char *filep = strrchr(uploadfile, '/');
|
||||
char *file2 = strrchr(filep?filep:uploadfile, '\\');
|
||||
|
||||
if(file2)
|
||||
filep = file2+1;
|
||||
else if(filep)
|
||||
filep++;
|
||||
else
|
||||
filep = config->infile;
|
||||
filep = uploadfile;
|
||||
|
||||
/* URL encode the file name */
|
||||
filep = curl_escape(filep, 0 /* use strlen */);
|
||||
@ -2876,24 +2934,26 @@ operate(struct Configurable *config, int argc, char *argv[])
|
||||
/*VMS?? for every record add 1 for linefeed and subtract 2 for the record header */
|
||||
/*VMS?? for VARIABLE header files only the bare record data needs to be considered with one appended if implied CC */
|
||||
|
||||
infd=(FILE *) fopen(config->infile, "rb");
|
||||
if (!infd || stat(config->infile, &fileinfo)) {
|
||||
helpf("Can't open '%s'!\n", config->infile);
|
||||
infd=(FILE *) fopen(uploadfile, "rb");
|
||||
if (!infd || stat(uploadfile, &fileinfo)) {
|
||||
helpf("Can't open '%s'!\n", uploadfile);
|
||||
return CURLE_READ_ERROR;
|
||||
}
|
||||
infilesize=fileinfo.st_size;
|
||||
infdfopen=TRUE;
|
||||
uploadfilesize=fileinfo.st_size;
|
||||
|
||||
}
|
||||
if((config->conf&CONF_UPLOAD) &&
|
||||
config->resume_from_current) {
|
||||
else if(uploadfile && curl_strequal(uploadfile, "-")) {
|
||||
infd = stdin;
|
||||
}
|
||||
|
||||
if(uploadfile && config->resume_from_current)
|
||||
config->resume_from = -1; /* -1 will then force get-it-yourself */
|
||||
}
|
||||
if(outs.stream && isatty(fileno(outs.stream)) &&
|
||||
!(config->conf&(CONF_UPLOAD|CONF_HTTPPOST)))
|
||||
/* we send the output to a tty and it isn't an upload operation,
|
||||
therefore we switch off the progress meter */
|
||||
config->conf |= CONF_NOPROGRESS;
|
||||
|
||||
if(outs.stream && isatty(fileno(outs.stream)))
|
||||
/* we send the output to a tty, therefore we switch off the progress
|
||||
meter */
|
||||
config->conf |= CONF_NOPROGRESS;
|
||||
|
||||
if (urlnum > 1 && !(config->conf&CONF_MUTE)) {
|
||||
fprintf(stderr, "\n[%d/%d]: %s --> %s\n",
|
||||
@ -2973,7 +3033,7 @@ operate(struct Configurable *config, int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* size of uploaded file: */
|
||||
curl_easy_setopt(curl, CURLOPT_INFILESIZE, infilesize);
|
||||
curl_easy_setopt(curl, CURLOPT_INFILESIZE, uploadfilesize);
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url); /* what to fetch */
|
||||
curl_easy_setopt(curl, CURLOPT_PROXY, config->proxy); /* proxy to use */
|
||||
curl_easy_setopt(curl, CURLOPT_HEADER, config->conf&CONF_HEADER);
|
||||
@ -2981,7 +3041,7 @@ operate(struct Configurable *config, int argc, char *argv[])
|
||||
curl_easy_setopt(curl, CURLOPT_NOBODY, config->conf&CONF_NOBODY);
|
||||
curl_easy_setopt(curl, CURLOPT_FAILONERROR,
|
||||
config->conf&CONF_FAILONERROR);
|
||||
curl_easy_setopt(curl, CURLOPT_UPLOAD, config->conf&CONF_UPLOAD);
|
||||
curl_easy_setopt(curl, CURLOPT_UPLOAD, uploadfile?TRUE:FALSE);
|
||||
curl_easy_setopt(curl, CURLOPT_FTPLISTONLY,
|
||||
config->conf&CONF_FTPLISTONLY);
|
||||
curl_easy_setopt(curl, CURLOPT_FTPAPPEND, config->conf&CONF_FTPAPPEND);
|
||||
@ -3201,8 +3261,6 @@ operate(struct Configurable *config, int argc, char *argv[])
|
||||
}
|
||||
#endif
|
||||
|
||||
if (config->infile)
|
||||
fclose(infd);
|
||||
if(headerfilep)
|
||||
fclose(headerfilep);
|
||||
|
||||
@ -3214,19 +3272,34 @@ operate(struct Configurable *config, int argc, char *argv[])
|
||||
|
||||
if(outfile)
|
||||
free(outfile);
|
||||
}
|
||||
if(outfiles)
|
||||
free(outfiles);
|
||||
|
||||
if(infdfopen)
|
||||
fclose(infd);
|
||||
|
||||
} /* loop to the next URL */
|
||||
|
||||
if(urls)
|
||||
/* cleanup memory used for URL globbing patterns */
|
||||
glob_cleanup(urls);
|
||||
|
||||
if(uploadfile)
|
||||
free(uploadfile);
|
||||
|
||||
} /* loop to the next globbed upload file */
|
||||
|
||||
if(inglob)
|
||||
glob_cleanup(inglob);
|
||||
|
||||
if(outfiles)
|
||||
free(outfiles);
|
||||
|
||||
/* empty this urlnode struct */
|
||||
if(urlnode->url)
|
||||
free(urlnode->url);
|
||||
if(urlnode->outfile)
|
||||
free(urlnode->outfile);
|
||||
if(urlnode->infile)
|
||||
free(urlnode->infile);
|
||||
|
||||
/* move on to the next URL */
|
||||
nextnode=urlnode->next;
|
||||
|
Loading…
x
Reference in New Issue
Block a user