mirror of
https://github.com/curl/curl.git
synced 2024-12-15 06:40:09 +08:00
curl: count uploaded data to stop at the originally given size
Closes #11223 Fixes #11222 Reported-by: JustAnotherArchivist on github
This commit is contained in:
parent
6661bd588d
commit
1f85420a28
@ -35,6 +35,7 @@
|
||||
#include "tool_cb_rea.h"
|
||||
#include "tool_operate.h"
|
||||
#include "tool_util.h"
|
||||
#include "tool_msgs.h"
|
||||
|
||||
#include "memdebug.h" /* keep this as LAST include */
|
||||
|
||||
@ -45,12 +46,18 @@
|
||||
size_t tool_read_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
|
||||
{
|
||||
ssize_t rc = 0;
|
||||
struct InStruct *in = userdata;
|
||||
struct OperationConfig *config = in->config;
|
||||
struct per_transfer *per = userdata;
|
||||
struct OperationConfig *config = per->config;
|
||||
|
||||
if((per->uploadfilesize != -1) &&
|
||||
(per->uploadedsofar == per->uploadfilesize)) {
|
||||
/* done */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(config->timeout_ms) {
|
||||
struct timeval now = tvnow();
|
||||
long msdelta = tvdiff(now, in->per->start);
|
||||
long msdelta = tvdiff(now, per->start);
|
||||
|
||||
if(msdelta > config->timeout_ms)
|
||||
/* timeout */
|
||||
@ -68,24 +75,33 @@ size_t tool_read_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
|
||||
timeout.tv_usec = (int)((wait%1000)*1000);
|
||||
|
||||
FD_ZERO(&bits);
|
||||
FD_SET(in->fd, &bits);
|
||||
if(!select(in->fd + 1, &bits, NULL, NULL, &timeout))
|
||||
FD_SET(per->infd, &bits);
|
||||
if(!select(per->infd + 1, &bits, NULL, NULL, &timeout))
|
||||
return 0; /* timeout */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
rc = read(in->fd, buffer, sz*nmemb);
|
||||
rc = read(per->infd, buffer, sz*nmemb);
|
||||
if(rc < 0) {
|
||||
if(errno == EAGAIN) {
|
||||
errno = 0;
|
||||
in->config->readbusy = TRUE;
|
||||
config->readbusy = TRUE;
|
||||
return CURL_READFUNC_PAUSE;
|
||||
}
|
||||
/* since size_t is unsigned we can't return negative values fine */
|
||||
rc = 0;
|
||||
}
|
||||
in->config->readbusy = FALSE;
|
||||
if((per->uploadfilesize != -1) &&
|
||||
(per->uploadedsofar + rc > per->uploadfilesize)) {
|
||||
/* do not allow uploading more than originally set out to do */
|
||||
curl_off_t delta = per->uploadedsofar + rc - per->uploadfilesize;
|
||||
warnf(per->config->global, "File size larger in the end than when "
|
||||
"started. Dropping at least %" CURL_FORMAT_CURL_OFF_T " bytes",
|
||||
delta);
|
||||
rc = (ssize_t)(per->uploadfilesize - per->uploadedsofar);
|
||||
}
|
||||
config->readbusy = FALSE;
|
||||
|
||||
/* when select() returned zero here, it timed out */
|
||||
return (size_t)rc;
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "curlx.h"
|
||||
|
||||
#include "tool_cfgable.h"
|
||||
#include "tool_operate.h"
|
||||
#include "tool_cb_see.h"
|
||||
|
||||
#include "memdebug.h" /* keep this as LAST include */
|
||||
@ -48,7 +49,7 @@
|
||||
|
||||
int tool_seek_cb(void *userdata, curl_off_t offset, int whence)
|
||||
{
|
||||
struct InStruct *in = userdata;
|
||||
struct per_transfer *per = userdata;
|
||||
|
||||
#if(SIZEOF_CURL_OFF_T > SIZEOF_OFF_T) && !defined(USE_WIN32_LARGE_FILES)
|
||||
|
||||
@ -81,7 +82,7 @@ int tool_seek_cb(void *userdata, curl_off_t offset, int whence)
|
||||
}
|
||||
#endif
|
||||
|
||||
if(LSEEK_ERROR == lseek(in->fd, offset, whence))
|
||||
if(LSEEK_ERROR == lseek(per->infd, offset, whence))
|
||||
/* couldn't rewind, the reason is in errno but errno is just not portable
|
||||
enough and we don't actually care that much why we failed. We'll let
|
||||
libcurl know that it may try other means if it wants to. */
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "tool_setup.h"
|
||||
|
||||
#include "tool_cfgable.h"
|
||||
#include "tool_formparse.h"
|
||||
#include "tool_main.h"
|
||||
|
||||
#include "memdebug.h" /* keep this as LAST include */
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "tool_setup.h"
|
||||
#include "tool_sdecls.h"
|
||||
#include "tool_urlglob.h"
|
||||
#include "tool_formparse.h"
|
||||
|
||||
struct GlobalConfig;
|
||||
|
||||
|
@ -327,8 +327,8 @@ static CURLcode pre_transfer(struct GlobalConfig *global,
|
||||
#endif
|
||||
my_setopt(per->curl, CURLOPT_INFILESIZE_LARGE, uploadfilesize);
|
||||
}
|
||||
per->input.fd = per->infd;
|
||||
}
|
||||
per->uploadfilesize = uploadfilesize;
|
||||
per->start = tvnow();
|
||||
return result;
|
||||
}
|
||||
@ -845,7 +845,6 @@ 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;
|
||||
@ -1004,7 +1003,6 @@ static CURLcode single_transfer(struct GlobalConfig *global,
|
||||
hdrcbdata = &per->hdrcbdata;
|
||||
|
||||
outs = &per->outs;
|
||||
input = &per->input;
|
||||
|
||||
per->outfile = NULL;
|
||||
per->infdopen = FALSE;
|
||||
@ -1274,9 +1272,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;
|
||||
input->per = per;
|
||||
/* 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.
|
||||
@ -1284,13 +1279,13 @@ 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);
|
||||
|
||||
{
|
||||
|
@ -50,7 +50,6 @@ struct per_transfer {
|
||||
struct OutStruct outs;
|
||||
struct OutStruct heads;
|
||||
struct OutStruct etag_save;
|
||||
struct InStruct input;
|
||||
struct HdrCbData hdrcbdata;
|
||||
long num_headers;
|
||||
bool was_last_header_empty;
|
||||
@ -68,6 +67,8 @@ struct per_transfer {
|
||||
curl_off_t dlnow;
|
||||
curl_off_t ultotal;
|
||||
curl_off_t ulnow;
|
||||
curl_off_t uploadfilesize; /* expected total amount */
|
||||
curl_off_t uploadedsofar; /* amount delivered from the callback */
|
||||
bool dltotal_added; /* if the total has been added from this */
|
||||
bool ultotal_added;
|
||||
|
||||
|
@ -70,24 +70,6 @@ struct OutStruct {
|
||||
curl_off_t init;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* InStruct variables keep track of information relative to curl's
|
||||
* input reading, which may take place from stdin or from some file.
|
||||
*
|
||||
* 'fd' member is either 'stdin' file descriptor number STDIN_FILENO
|
||||
* or a file descriptor as returned from an 'open' call for some file.
|
||||
*
|
||||
* 'config' member is a pointer to associated 'OperationConfig' struct.
|
||||
*/
|
||||
|
||||
struct InStruct {
|
||||
int fd;
|
||||
struct OperationConfig *config;
|
||||
struct per_transfer *per;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* A linked list of these 'getout' nodes contain URL's to fetch,
|
||||
* as well as information relative to where URL contents should
|
||||
|
Loading…
Reference in New Issue
Block a user