aboutsummaryrefslogtreecommitdiff
path: root/src/tool_operate.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tool_operate.c')
-rw-r--r--src/tool_operate.c117
1 files changed, 82 insertions, 35 deletions
diff --git a/src/tool_operate.c b/src/tool_operate.c
index ffb37ff1b..c9dda40b2 100644
--- a/src/tool_operate.c
+++ b/src/tool_operate.c
@@ -406,11 +406,26 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
char *outfiles;
int infilenum;
URLGlob *inglob;
+ int metalink; /* nonzero for metalink download */
+ struct metalinkfile *mlfile;
+ metalink_resource_t **mlres;
outfiles = NULL;
infilenum = 1;
inglob = NULL;
+ if(urlnode->flags & GETOUT_METALINK) {
+ metalink = 1;
+ mlfile = config->metalinkfile_last;
+ mlres = mlfile->file->resources;
+ config->metalinkfile_last = config->metalinkfile_last->next;
+ }
+ else {
+ metalink = 0;
+ mlfile = NULL;
+ mlres = NULL;
+ }
+
/* urlnode->url is the full URL (it might be NULL) */
if(!urlnode->url) {
@@ -444,24 +459,6 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
}
}
- /* process metalink download in the separate function */
- if(urlnode->flags & GETOUT_METALINK) {
- struct OutStruct outs;
- long retry_sleep_default;
- struct getout *nextnode;
-
- retry_sleep_default = (config->retry_delay) ?
- config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */
- /* default output stream is stdout */
- memset(&outs, 0, sizeof(struct OutStruct));
- outs.stream = stdout;
- outs.config = config;
- operatemetalink(curl, urlnode, retry_sleep_default, outs, heads,
- outfiles, config);
- /* move on to the next URL */
- continue;
- }
-
/* 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 < infilenum; up++) {
@@ -497,7 +494,12 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
break;
}
- if(!config->globoff) {
+ if(metalink) {
+ /* For Metalink download, we don't use glob. Instead we use
+ the number of resources as urlnum. */
+ urlnum = count_next_metalink_resource(mlfile);
+ }
+ else if(!config->globoff) {
/* Unless explicitly shut off, we expand '{...}' and '[...]'
expressions and return total number of URLs in pattern set */
res = glob_url(&urls, urlnode->url, &urlnum,
@@ -528,39 +530,55 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
long retry_sleep;
char *this_url;
HeaderData hdrdata;
+ int metalink_next_res;
outfile = NULL;
infdopen = FALSE;
infd = STDIN_FILENO;
uploadfilesize = -1; /* -1 means unknown */
+ metalink_next_res = 0;
/* default output stream is stdout */
memset(&outs, 0, sizeof(struct OutStruct));
outs.stream = stdout;
outs.config = config;
- if(urls) {
- res = glob_next_url(&this_url, urls);
- if(res)
+ if(metalink) {
+ outfile = strdup(mlfile->file->name);
+ if(!outfile) {
+ res = CURLE_OUT_OF_MEMORY;
goto show_error;
- }
- else if(!i) {
- this_url = strdup(urlnode->url);
+ }
+ this_url = strdup((*mlres)->url);
if(!this_url) {
res = CURLE_OUT_OF_MEMORY;
goto show_error;
}
}
- else
- this_url = NULL;
- if(!this_url)
- break;
+ else {
+ if(urls) {
+ res = glob_next_url(&this_url, urls);
+ if(res)
+ goto show_error;
+ }
+ else if(!i) {
+ this_url = strdup(urlnode->url);
+ if(!this_url) {
+ res = CURLE_OUT_OF_MEMORY;
+ goto show_error;
+ }
+ }
+ else
+ this_url = NULL;
+ if(!this_url)
+ break;
- if(outfiles) {
- outfile = strdup(outfiles);
- if(!outfile) {
- res = CURLE_OUT_OF_MEMORY;
- goto show_error;
+ if(outfiles) {
+ outfile = strdup(outfiles);
+ if(!outfile) {
+ res = CURLE_OUT_OF_MEMORY;
+ goto show_error;
+ }
}
}
@@ -1408,6 +1426,28 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
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;
+ }
+ }
+ }
+ else
+ metalink_next_res = 1;
+ }
/* In all ordinary cases, just break out of loop here */
break; /* curl_easy_perform loop */
@@ -1532,7 +1572,14 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
infd = STDIN_FILENO;
}
- if(urlnum > 1) {
+ if(metalink) {
+ if(is_fatal_error(res)) {
+ break;
+ }
+ if(!metalink_next_res || *(++mlres) == NULL)
+ break;
+ }
+ else if(urlnum > 1) {
/* when url globbing, exit loop upon critical error */
if(is_fatal_error(res))
break;