curl tool: fix some more OOM handling
This commit is contained in:
136
src/main.c
136
src/main.c
@@ -3110,7 +3110,6 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
struct ProgressData progressbar;
|
struct ProgressData progressbar;
|
||||||
struct getout *urlnode;
|
struct getout *urlnode;
|
||||||
|
|
||||||
struct OutStruct outs;
|
|
||||||
struct OutStruct heads;
|
struct OutStruct heads;
|
||||||
|
|
||||||
CURL *curl = NULL;
|
CURL *curl = NULL;
|
||||||
@@ -3121,8 +3120,10 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
errorbuffer[0] = '\0';
|
errorbuffer[0] = '\0';
|
||||||
memset(&outs, 0, sizeof(struct OutStruct));
|
/* default headers output stream is stdout */
|
||||||
memset(&heads, 0, sizeof(struct OutStruct));
|
memset(&heads, 0, sizeof(struct OutStruct));
|
||||||
|
heads.stream = stdout;
|
||||||
|
heads.config = config;
|
||||||
|
|
||||||
memory_tracking_init();
|
memory_tracking_init();
|
||||||
|
|
||||||
@@ -3152,9 +3153,6 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
}
|
}
|
||||||
config->easy = curl;
|
config->easy = curl;
|
||||||
|
|
||||||
/* Store a pointer to our 'outs' struct used for output writing */
|
|
||||||
config->outs = &outs;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Beyond this point no return'ing from this function allowed.
|
** Beyond this point no return'ing from this function allowed.
|
||||||
** Jump to label 'quit_curl' in order to abandon this function
|
** Jump to label 'quit_curl' in order to abandon this function
|
||||||
@@ -3352,7 +3350,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
/* Single header file for all URLs */
|
/* Single header file for all URLs */
|
||||||
if(config->headerfile) {
|
if(config->headerfile) {
|
||||||
/* open file for output: */
|
/* open file for output: */
|
||||||
if(strcmp(config->headerfile, "-")) {
|
if(!curlx_strequal(config->headerfile, "-")) {
|
||||||
FILE *newfile = fopen(config->headerfile, "wb");
|
FILE *newfile = fopen(config->headerfile, "wb");
|
||||||
if(!newfile) {
|
if(!newfile) {
|
||||||
warnf(config, "Failed to open %s\n", config->headerfile);
|
warnf(config, "Failed to open %s\n", config->headerfile);
|
||||||
@@ -3361,17 +3359,11 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
heads.filename = config->headerfile;
|
heads.filename = config->headerfile;
|
||||||
heads.alloc_filename = FALSE;
|
heads.s_isreg = TRUE;
|
||||||
|
heads.fopened = TRUE;
|
||||||
heads.stream = newfile;
|
heads.stream = newfile;
|
||||||
heads.config = config;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
heads.filename = config->headerfile; /* "-" */
|
|
||||||
heads.alloc_filename = FALSE;
|
|
||||||
heads.stream = stdout;
|
|
||||||
heads.config = config;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3403,12 +3395,6 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
continue; /* next URL please */
|
continue; /* next URL please */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* default output stream is stdout */
|
|
||||||
outs.stream = stdout;
|
|
||||||
outs.config = config;
|
|
||||||
outs.bytes = 0; /* nothing written yet */
|
|
||||||
outs.filename = NULL;
|
|
||||||
|
|
||||||
/* save outfile pattern before expansion */
|
/* save outfile pattern before expansion */
|
||||||
if(urlnode->outfile) {
|
if(urlnode->outfile) {
|
||||||
outfiles = strdup(urlnode->outfile);
|
outfiles = strdup(urlnode->outfile);
|
||||||
@@ -3480,6 +3466,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
int infd;
|
int infd;
|
||||||
bool infdopen;
|
bool infdopen;
|
||||||
char *outfile;
|
char *outfile;
|
||||||
|
struct OutStruct outs;
|
||||||
struct InStruct input;
|
struct InStruct input;
|
||||||
struct timeval retrystart;
|
struct timeval retrystart;
|
||||||
curl_off_t uploadfilesize;
|
curl_off_t uploadfilesize;
|
||||||
@@ -3493,6 +3480,11 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
infd = STDIN_FILENO;
|
infd = STDIN_FILENO;
|
||||||
uploadfilesize = -1; /* -1 means unknown */
|
uploadfilesize = -1; /* -1 means unknown */
|
||||||
|
|
||||||
|
/* default output stream is stdout */
|
||||||
|
memset(&outs, 0, sizeof(struct OutStruct));
|
||||||
|
outs.stream = stdout;
|
||||||
|
outs.config = config;
|
||||||
|
|
||||||
if(urls)
|
if(urls)
|
||||||
this_url = glob_next_url(urls);
|
this_url = glob_next_url(urls);
|
||||||
else if(!i) {
|
else if(!i) {
|
||||||
@@ -3563,37 +3555,42 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(config->resume_from_current) {
|
if((urlnode->flags & GETOUT_USEREMOTE)
|
||||||
/* We're told to continue from where we are now. Get the
|
&& config->content_disposition) {
|
||||||
size of the file as it is now and open it for append instead */
|
/* Our header callback sets the filename */
|
||||||
|
DEBUGASSERT(!outs.filename);
|
||||||
struct_stat fileinfo;
|
|
||||||
|
|
||||||
/* VMS -- Danger, the filesize is only valid for stream files */
|
|
||||||
if(0 == stat(outfile, &fileinfo))
|
|
||||||
/* set offset to current file size: */
|
|
||||||
config->resume_from = fileinfo.st_size;
|
|
||||||
else
|
|
||||||
/* let offset be 0 */
|
|
||||||
config->resume_from = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
outs.filename = outfile;
|
|
||||||
outs.alloc_filename = FALSE;
|
|
||||||
|
|
||||||
if(config->resume_from) {
|
|
||||||
outs.init = config->resume_from;
|
|
||||||
/* open file for output: */
|
|
||||||
outs.stream = fopen(outfile, config->resume_from?"ab":"wb");
|
|
||||||
if(!outs.stream) {
|
|
||||||
helpf(config->errors, "Can't open '%s'!\n", outfile);
|
|
||||||
res = CURLE_WRITE_ERROR;
|
|
||||||
goto quit_urls;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
outs.stream = NULL; /* open when needed */
|
if(config->resume_from_current) {
|
||||||
outs.bytes = 0; /* reset byte counter */
|
/* We're told to continue from where we are now. Get the size
|
||||||
|
of the file as it is now and open it for append instead */
|
||||||
|
struct_stat fileinfo;
|
||||||
|
/* VMS -- Danger, the filesize is only valid for stream files */
|
||||||
|
if(0 == stat(outfile, &fileinfo))
|
||||||
|
/* set offset to current file size: */
|
||||||
|
config->resume_from = fileinfo.st_size;
|
||||||
|
else
|
||||||
|
/* let offset be 0 */
|
||||||
|
config->resume_from = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(config->resume_from) {
|
||||||
|
/* open file for output: */
|
||||||
|
FILE *file = fopen(outfile, config->resume_from?"ab":"wb");
|
||||||
|
if(!file) {
|
||||||
|
helpf(config->errors, "Can't open '%s'!\n", outfile);
|
||||||
|
res = CURLE_WRITE_ERROR;
|
||||||
|
goto quit_urls;
|
||||||
|
}
|
||||||
|
outs.fopened = TRUE;
|
||||||
|
outs.stream = file;
|
||||||
|
outs.init = config->resume_from;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
outs.stream = NULL; /* open when needed */
|
||||||
|
}
|
||||||
|
outs.filename = outfile;
|
||||||
|
outs.s_isreg = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4375,8 +4372,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
quit_urls:
|
quit_urls:
|
||||||
|
|
||||||
/* Set file extended attributes */
|
/* Set file extended attributes */
|
||||||
if(!res && config->xattr &&
|
if(!res && config->xattr && outs.fopened && outs.stream) {
|
||||||
outfile && !curlx_strequal(outfile, "-") && outs.stream) {
|
|
||||||
int rc = fwrite_xattr(curl, fileno(outs.stream));
|
int rc = fwrite_xattr(curl, fileno(outs.stream));
|
||||||
if(rc)
|
if(rc)
|
||||||
warnf(config, "Error setting extended attributes: %s\n",
|
warnf(config, "Error setting extended attributes: %s\n",
|
||||||
@@ -4384,30 +4380,36 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Close the file */
|
/* Close the file */
|
||||||
if(outfile && !curlx_strequal(outfile, "-") && outs.stream) {
|
if(outs.fopened && outs.stream) {
|
||||||
int rc = fclose(outs.stream);
|
int rc = fclose(outs.stream);
|
||||||
if(!res && rc) {
|
if(!res && rc) {
|
||||||
/* something went wrong in the writing process */
|
/* something went wrong in the writing process */
|
||||||
res = CURLE_WRITE_ERROR;
|
res = CURLE_WRITE_ERROR;
|
||||||
fprintf(config->errors, "(%d) Failed writing body\n", res);
|
fprintf(config->errors, "(%d) Failed writing body\n", res);
|
||||||
}
|
}
|
||||||
if(outs.alloc_filename)
|
}
|
||||||
Curl_safefree(outs.filename);
|
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__
|
#ifdef __AMIGA__
|
||||||
if(!res) {
|
if(!res && outs.s_isreg && outs.filename) {
|
||||||
/* Set the url (up to 80 chars) as comment for the file */
|
/* Set the url (up to 80 chars) as comment for the file */
|
||||||
if(strlen(url) > 78)
|
if(strlen(url) > 78)
|
||||||
url[79] = '\0';
|
url[79] = '\0';
|
||||||
SetComment( outs.filename, url);
|
SetComment(outs.filename, url);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_UTIME
|
#ifdef HAVE_UTIME
|
||||||
/* File time can only be set _after_ the file has been closed */
|
/* File time can only be set _after_ the file has been closed */
|
||||||
if(!res && config->remote_time &&
|
if(!res && config->remote_time && outs.s_isreg && outs.filename) {
|
||||||
outs.filename && !curlx_strequal("-", outs.filename)) {
|
|
||||||
/* Ask libcurl if we got a remote file time */
|
/* Ask libcurl if we got a remote file time */
|
||||||
long filetime = -1;
|
long filetime = -1;
|
||||||
curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime);
|
curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime);
|
||||||
@@ -4419,6 +4421,10 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
/* No more business with this output struct */
|
||||||
|
if(outs.alloc_filename)
|
||||||
|
Curl_safefree(outs.filename);
|
||||||
|
memset(&outs, 0, sizeof(struct OutStruct));
|
||||||
|
|
||||||
/* Free loop-local allocated memory and close loop-local opened fd */
|
/* Free loop-local allocated memory and close loop-local opened fd */
|
||||||
|
|
||||||
@@ -4437,7 +4443,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
|
|
||||||
} /* loop to the next URL */
|
} /* loop to the next URL */
|
||||||
|
|
||||||
/* Free loop-local allocated memory and close loop-local opened fd */
|
/* Free loop-local allocated memory */
|
||||||
|
|
||||||
Curl_safefree(uploadfile);
|
Curl_safefree(uploadfile);
|
||||||
|
|
||||||
@@ -4453,7 +4459,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
|
|
||||||
} /* loop to the next globbed upload file */
|
} /* loop to the next globbed upload file */
|
||||||
|
|
||||||
/* Free loop-local allocated memory and close loop-local opened fd */
|
/* Free loop-local allocated memory */
|
||||||
|
|
||||||
Curl_safefree(outfiles);
|
Curl_safefree(outfiles);
|
||||||
|
|
||||||
@@ -4511,12 +4517,10 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
|
|
||||||
/* Close function-local opened file descriptors */
|
/* Close function-local opened file descriptors */
|
||||||
|
|
||||||
if(config->headerfile) {
|
if(heads.fopened && heads.stream)
|
||||||
if(strcmp(heads.filename, "-") && heads.stream)
|
fclose(heads.stream);
|
||||||
fclose(heads.stream);
|
if(heads.alloc_filename)
|
||||||
if(heads.alloc_filename)
|
Curl_safefree(heads.filename);
|
||||||
Curl_safefree(heads.filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(config->trace_fopened && config->trace_stream)
|
if(config->trace_fopened && config->trace_stream)
|
||||||
fclose(config->trace_stream);
|
fclose(config->trace_stream);
|
||||||
|
|||||||
@@ -56,6 +56,9 @@ size_t tool_header_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
|
|||||||
*/
|
*/
|
||||||
size_t failure = (size * nmemb) ? 0 : 1;
|
size_t failure = (size * nmemb) ? 0 : 1;
|
||||||
|
|
||||||
|
if(!outs->config)
|
||||||
|
return failure;
|
||||||
|
|
||||||
#ifdef DEBUGBUILD
|
#ifdef DEBUGBUILD
|
||||||
if((size * nmemb > (size_t)CURL_MAX_WRITE_SIZE) ||
|
if((size * nmemb > (size_t)CURL_MAX_WRITE_SIZE) ||
|
||||||
(size * nmemb > (size_t)CURL_MAX_HTTP_HEADER)) {
|
(size * nmemb > (size_t)CURL_MAX_HTTP_HEADER)) {
|
||||||
@@ -64,7 +67,8 @@ size_t tool_header_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(cb > 20 && checkprefix("Content-disposition:", str)) {
|
if(!outs->filename && (cb > 20) &&
|
||||||
|
checkprefix("Content-disposition:", str)) {
|
||||||
const char *p = str + 20;
|
const char *p = str + 20;
|
||||||
|
|
||||||
/* look for the 'filename=' parameter
|
/* look for the 'filename=' parameter
|
||||||
@@ -94,6 +98,9 @@ size_t tool_header_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
|
|||||||
if(filename) {
|
if(filename) {
|
||||||
outs->filename = filename;
|
outs->filename = filename;
|
||||||
outs->alloc_filename = TRUE;
|
outs->alloc_filename = TRUE;
|
||||||
|
outs->s_isreg = TRUE;
|
||||||
|
outs->fopened = FALSE;
|
||||||
|
outs->stream = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -40,8 +40,8 @@
|
|||||||
size_t tool_write_cb(void *buffer, size_t sz, size_t nmemb, void *userdata)
|
size_t tool_write_cb(void *buffer, size_t sz, size_t nmemb, void *userdata)
|
||||||
{
|
{
|
||||||
size_t rc;
|
size_t rc;
|
||||||
struct OutStruct *out = userdata;
|
struct OutStruct *outs = userdata;
|
||||||
struct Configurable *config = out->config;
|
struct Configurable *config = outs->config;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Once that libcurl has called back tool_write_cb() the returned value
|
* Once that libcurl has called back tool_write_cb() the returned value
|
||||||
@@ -49,47 +49,85 @@ size_t tool_write_cb(void *buffer, size_t sz, size_t nmemb, void *userdata)
|
|||||||
* it does not match then it fails with CURLE_WRITE_ERROR. So at this
|
* it does not match then it fails with CURLE_WRITE_ERROR. So at this
|
||||||
* point returning a value different from sz*nmemb indicates failure.
|
* point returning a value different from sz*nmemb indicates failure.
|
||||||
*/
|
*/
|
||||||
const size_t err_rc = (sz * nmemb) ? 0 : 1;
|
const size_t failure = (sz * nmemb) ? 0 : 1;
|
||||||
|
|
||||||
|
if(!config)
|
||||||
|
return failure;
|
||||||
|
|
||||||
#ifdef DEBUGBUILD
|
#ifdef DEBUGBUILD
|
||||||
if(sz * nmemb > (size_t)CURL_MAX_WRITE_SIZE) {
|
if(sz * nmemb > (size_t)CURL_MAX_WRITE_SIZE) {
|
||||||
warnf(config, "Data size exceeds single call write limit!\n");
|
warnf(config, "Data size exceeds single call write limit!\n");
|
||||||
return err_rc; /* Failure */
|
return failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Some internal congruency checks on received OutStruct */
|
||||||
|
bool check_fails = FALSE;
|
||||||
|
if(outs->filename) {
|
||||||
|
/* regular file */
|
||||||
|
if(!*outs->filename)
|
||||||
|
check_fails = TRUE;
|
||||||
|
if(!outs->s_isreg)
|
||||||
|
check_fails = TRUE;
|
||||||
|
if(outs->fopened && !outs->stream)
|
||||||
|
check_fails = TRUE;
|
||||||
|
if(!outs->fopened && outs->stream)
|
||||||
|
check_fails = TRUE;
|
||||||
|
if(!outs->fopened && outs->bytes)
|
||||||
|
check_fails = TRUE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* standard stream */
|
||||||
|
if(!outs->stream || outs->s_isreg || outs->fopened)
|
||||||
|
check_fails = TRUE;
|
||||||
|
if(outs->alloc_filename || outs->init)
|
||||||
|
check_fails = TRUE;
|
||||||
|
}
|
||||||
|
if(check_fails) {
|
||||||
|
warnf(config, "Invalid output struct data for write callback\n");
|
||||||
|
return failure;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(!out->stream) {
|
if(!outs->stream) {
|
||||||
out->bytes = 0; /* nothing written yet */
|
FILE *file;
|
||||||
if(!out->filename) {
|
|
||||||
|
if(!outs->filename || !*outs->filename) {
|
||||||
warnf(config, "Remote filename has no length!\n");
|
warnf(config, "Remote filename has no length!\n");
|
||||||
return err_rc; /* Failure */
|
return failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(config->content_disposition) {
|
if(config->content_disposition) {
|
||||||
/* don't overwrite existing files */
|
/* don't overwrite existing files */
|
||||||
FILE* f = fopen(out->filename, "r");
|
file = fopen(outs->filename, "rb");
|
||||||
if(f) {
|
if(file) {
|
||||||
fclose(f);
|
fclose(file);
|
||||||
warnf(config, "Refusing to overwrite %s: %s\n", out->filename,
|
warnf(config, "Refusing to overwrite %s: %s\n", outs->filename,
|
||||||
strerror(EEXIST));
|
strerror(EEXIST));
|
||||||
return err_rc; /* Failure */
|
return failure;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* open file for writing */
|
/* open file for writing */
|
||||||
out->stream = fopen(out->filename, "wb");
|
file = fopen(outs->filename, "wb");
|
||||||
if(!out->stream) {
|
if(!file) {
|
||||||
warnf(config, "Failed to create the file %s: %s\n", out->filename,
|
warnf(config, "Failed to create the file %s: %s\n", outs->filename,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return err_rc; /* failure */
|
return failure;
|
||||||
}
|
}
|
||||||
|
outs->s_isreg = TRUE;
|
||||||
|
outs->fopened = TRUE;
|
||||||
|
outs->stream = file;
|
||||||
|
outs->bytes = 0;
|
||||||
|
outs->init = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = fwrite(buffer, sz, nmemb, out->stream);
|
rc = fwrite(buffer, sz, nmemb, outs->stream);
|
||||||
|
|
||||||
if((sz * nmemb) == rc)
|
if((sz * nmemb) == rc)
|
||||||
/* we added this amount of data to the output */
|
/* we added this amount of data to the output */
|
||||||
out->bytes += (sz * nmemb);
|
outs->bytes += (sz * nmemb);
|
||||||
|
|
||||||
if(config->readbusy) {
|
if(config->readbusy) {
|
||||||
config->readbusy = FALSE;
|
config->readbusy = FALSE;
|
||||||
@@ -97,12 +135,10 @@ size_t tool_write_cb(void *buffer, size_t sz, size_t nmemb, void *userdata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(config->nobuffer) {
|
if(config->nobuffer) {
|
||||||
/* disable output buffering */
|
/* output buffering disabled */
|
||||||
int res = fflush(out->stream);
|
int res = fflush(outs->stream);
|
||||||
if(res) {
|
if(res)
|
||||||
/* return a value that isn't the same as sz * nmemb */
|
return failure;
|
||||||
return err_rc; /* failure */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|||||||
@@ -127,7 +127,5 @@ void free_config_fields(struct Configurable *config)
|
|||||||
Curl_safefree(config->ftp_alternative_to_user);
|
Curl_safefree(config->ftp_alternative_to_user);
|
||||||
|
|
||||||
Curl_safefree(config->libcurl);
|
Curl_safefree(config->libcurl);
|
||||||
|
|
||||||
config->outs = NULL; /* closed elsewhere when appropriate */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ struct Configurable {
|
|||||||
|
|
||||||
int default_node_flags; /* default flags to search for each 'node', which
|
int default_node_flags; /* default flags to search for each 'node', which
|
||||||
is basically each given URL to transfer */
|
is basically each given URL to transfer */
|
||||||
struct OutStruct *outs;
|
|
||||||
bool xattr; /* store metadata in extended attributes */
|
bool xattr; /* store metadata in extended attributes */
|
||||||
long gssapi_delegation;
|
long gssapi_delegation;
|
||||||
|
|
||||||
|
|||||||
@@ -26,27 +26,43 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* OutStruct variables keep track of information relative to curl's
|
* OutStruct variables keep track of information relative to curl's
|
||||||
* output writing, which may take place to stdout or to some file.
|
* output writing, which may take place to a standard stream or a file.
|
||||||
*
|
*
|
||||||
* 'filename' member is a pointer to either a file name string or to
|
* 'filename' member is either a pointer to a file name string or NULL
|
||||||
* string "-" to indicate that output is written to stdout.
|
* when dealing with a standard stream.
|
||||||
*
|
*
|
||||||
* 'alloc_filename' member is TRUE when string pointed by 'filename' has been
|
* 'alloc_filename' member is TRUE when string pointed by 'filename' has been
|
||||||
* dynamically allocated and 'belongs' to this OutStruct, otherwise FALSE.
|
* dynamically allocated and 'belongs' to this OutStruct, otherwise FALSE.
|
||||||
*
|
*
|
||||||
* 'stream' member is a pointer to a stream controlling object as returned
|
* 's_isreg' member is TRUE when output goes to a regular file, this also
|
||||||
* from a 'fopen' call or stdout. When 'stdout' this shall not be closed.
|
* implies that output is 'seekable' and 'appendable' and also that member
|
||||||
|
* 'filename' points to file name's string. For any standard stream member
|
||||||
|
* 's_isreg' will be FALSE.
|
||||||
*
|
*
|
||||||
* 'bytes' member represents amount written, and 'init' initial file size.
|
* 'fopened' member is TRUE when output goes to a regular file and it
|
||||||
|
* has been fopen'ed, requiring it to be closed later on. In any other
|
||||||
|
* case this is FALSE.
|
||||||
|
*
|
||||||
|
* 'stream' member is a pointer to a stream controlling object as returned
|
||||||
|
* from a 'fopen' call or a standard stream.
|
||||||
|
*
|
||||||
|
* 'config' member is a pointer to associated 'Configurable' struct.
|
||||||
|
*
|
||||||
|
* 'bytes' member represents amount written so far.
|
||||||
|
*
|
||||||
|
* 'init' member holds original file size or offset at which truncation is
|
||||||
|
* taking place. Always zero unless appending to a non-empty regular file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct OutStruct {
|
struct OutStruct {
|
||||||
char *filename; /* pointer to file name or "-" string */
|
char *filename;
|
||||||
bool alloc_filename; /* allocated filename belongs to this */
|
bool alloc_filename;
|
||||||
FILE *stream; /* stdout or stream controlling object */
|
bool s_isreg;
|
||||||
struct Configurable *config; /* pointer back to Configurable struct */
|
bool fopened;
|
||||||
curl_off_t bytes; /* amount written so far */
|
FILE *stream;
|
||||||
curl_off_t init; /* original size (non-zero when appending) */
|
struct Configurable *config;
|
||||||
|
curl_off_t bytes;
|
||||||
|
curl_off_t init;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user