mirror of
https://github.com/moparisthebest/curl
synced 2024-11-11 12:05:06 -05:00
- Bug report #2709004 (http://curl.haxx.se/bug/view.cgi?id=2709004) by Tim
Chen pointed out how curl couldn't upload with resume when reading from a pipe. This ended up with the introduction of a new return code for the CURLOPT_SEEKFUNCTION callback that basically says that the seek failed but that libcurl may try to resolve the situation anyway. In our case this means libcurl will attempt to instead read that much data from the stream instead of seeking and that way curl can now upload with resume when data is read from a stream!
This commit is contained in:
parent
dd8d472318
commit
e01b7c1ede
12
CHANGES
12
CHANGES
@ -6,6 +6,18 @@
|
|||||||
|
|
||||||
Changelog
|
Changelog
|
||||||
|
|
||||||
|
Daniel Stenberg (28 Apr 2009)
|
||||||
|
- Bug report #2709004 (http://curl.haxx.se/bug/view.cgi?id=2709004) by Tim
|
||||||
|
Chen pointed out how curl couldn't upload with resume when reading from a
|
||||||
|
pipe.
|
||||||
|
|
||||||
|
This ended up with the introduction of a new return code for the
|
||||||
|
CURLOPT_SEEKFUNCTION callback that basically says that the seek failed but
|
||||||
|
that libcurl may try to resolve the situation anyway. In our case this means
|
||||||
|
libcurl will attempt to instead read that much data from the stream instead
|
||||||
|
of seeking and that way curl can now upload with resume when data is read
|
||||||
|
from a stream!
|
||||||
|
|
||||||
Daniel Stenberg (26 Apr 2009)
|
Daniel Stenberg (26 Apr 2009)
|
||||||
- Bug report #2779733 (http://curl.haxx.se/bug/view.cgi?id=2779733) by Sven
|
- Bug report #2779733 (http://curl.haxx.se/bug/view.cgi?id=2779733) by Sven
|
||||||
Wegener pointed out that CURLINFO_APPCONNECT_TIME didn't work with the multi
|
Wegener pointed out that CURLINFO_APPCONNECT_TIME didn't work with the multi
|
||||||
|
@ -13,6 +13,8 @@ This release includes the following changes:
|
|||||||
connection
|
connection
|
||||||
o libssh2's version number can now be figured out run-time instead of using
|
o libssh2's version number can now be figured out run-time instead of using
|
||||||
the build-time fixed number
|
the build-time fixed number
|
||||||
|
o CURLOPT_SEEKFUNCTION may now return CURL_SEEKFUNC_CANTSEEK
|
||||||
|
o curl can now upload with resume even when reading from a pipe
|
||||||
|
|
||||||
This release includes the following bugfixes:
|
This release includes the following bugfixes:
|
||||||
|
|
||||||
@ -43,6 +45,7 @@ advice from friends like these:
|
|||||||
Daniel Fandrich, Yang Tse, David James, Chris Deidun, Bill Egert,
|
Daniel Fandrich, Yang Tse, David James, Chris Deidun, Bill Egert,
|
||||||
Andre Guibert de Bruet, Andreas Farber, Frank Hempel, Pierre Brico,
|
Andre Guibert de Bruet, Andreas Farber, Frank Hempel, Pierre Brico,
|
||||||
Kamil Dudka, Jim Freeman, Daniel Johnson, Toshio Kuratomi, Martin Storsjo,
|
Kamil Dudka, Jim Freeman, Daniel Johnson, Toshio Kuratomi, Martin Storsjo,
|
||||||
Pramod Sharma, Gisle Vanem, Leanic Lefever, Rainer Koenig, Sven Wegener
|
Pramod Sharma, Gisle Vanem, Leanic Lefever, Rainer Koenig, Sven Wegener,
|
||||||
|
Tim Chen
|
||||||
|
|
||||||
Thanks! (and sorry if I forgot to mention someone)
|
Thanks! (and sorry if I forgot to mention someone)
|
||||||
|
@ -189,8 +189,11 @@ uploaded bytes with the normal read function/callback). It is also called to
|
|||||||
rewind a stream when doing a HTTP PUT or POST with a multi-pass authentication
|
rewind a stream when doing a HTTP PUT or POST with a multi-pass authentication
|
||||||
method. The function shall work like "fseek" or "lseek" and accepted SEEK_SET,
|
method. The function shall work like "fseek" or "lseek" and accepted SEEK_SET,
|
||||||
SEEK_CUR and SEEK_END as argument for origin, although (in 7.18.0) libcurl
|
SEEK_CUR and SEEK_END as argument for origin, although (in 7.18.0) libcurl
|
||||||
only passes SEEK_SET. The callback must return 0 on success as returning
|
only passes SEEK_SET. The callback must return 0 (CURL_SEEKFUNC_OK) on
|
||||||
something else will cause the upload operation to fail.
|
success, 1 (CURL_SEEKFUNC_FAIL) to cause the upload operation to fail or 2
|
||||||
|
(CURL_SEEKFUNC_CANTSEEK) to indicate that while the seek failed, libcurl is
|
||||||
|
free to work around the problem if possible. The latter can sometimes be done
|
||||||
|
by instead reading from the input or similar.
|
||||||
|
|
||||||
If you forward the input arguments directly to "fseek" or "lseek", note that
|
If you forward the input arguments directly to "fseek" or "lseek", note that
|
||||||
the data type for \fIoffset\fP is not the same as defined for curl_off_t on
|
the data type for \fIoffset\fP is not the same as defined for curl_off_t on
|
||||||
|
@ -186,15 +186,21 @@ typedef size_t (*curl_write_callback)(char *buffer,
|
|||||||
size_t nitems,
|
size_t nitems,
|
||||||
void *outstream);
|
void *outstream);
|
||||||
|
|
||||||
|
/* this is the return codes for the seek callbacks */
|
||||||
|
#define CURL_SEEKFUNC_OK 0
|
||||||
|
#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */
|
||||||
|
#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so
|
||||||
|
libcurl might try other means instead */
|
||||||
|
typedef int (*curl_seek_callback)(void *instream,
|
||||||
|
curl_off_t offset,
|
||||||
|
int origin); /* 'whence' */
|
||||||
|
|
||||||
/* This is a return code for the read callback that, when returned, will
|
/* This is a return code for the read callback that, when returned, will
|
||||||
signal libcurl to immediately abort the current transfer. */
|
signal libcurl to immediately abort the current transfer. */
|
||||||
#define CURL_READFUNC_ABORT 0x10000000
|
#define CURL_READFUNC_ABORT 0x10000000
|
||||||
/* This is a return code for the read callback that, when returned, will
|
/* This is a return code for the read callback that, when returned, will
|
||||||
signal libcurl to pause sending data on the current transfer. */
|
signal libcurl to pause sending data on the current transfer. */
|
||||||
#define CURL_READFUNC_PAUSE 0x10000001
|
#define CURL_READFUNC_PAUSE 0x10000001
|
||||||
typedef int (*curl_seek_callback)(void *instream,
|
|
||||||
curl_off_t offset,
|
|
||||||
int origin); /* 'whence' */
|
|
||||||
|
|
||||||
typedef size_t (*curl_read_callback)(char *buffer,
|
typedef size_t (*curl_read_callback)(char *buffer,
|
||||||
size_t size,
|
size_t size,
|
||||||
|
14
lib/ftp.c
14
lib/ftp.c
@ -1520,6 +1520,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
|
|||||||
struct FTP *ftp = conn->data->state.proto.ftp;
|
struct FTP *ftp = conn->data->state.proto.ftp;
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||||
|
int seekerr = CURL_SEEKFUNC_OK;
|
||||||
|
|
||||||
if((data->state.resume_from && !sizechecked) ||
|
if((data->state.resume_from && !sizechecked) ||
|
||||||
((data->state.resume_from > 0) && sizechecked)) {
|
((data->state.resume_from > 0) && sizechecked)) {
|
||||||
@ -1548,15 +1549,16 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
|
|||||||
|
|
||||||
/* Let's read off the proper amount of bytes from the input. */
|
/* Let's read off the proper amount of bytes from the input. */
|
||||||
if(conn->seek_func) {
|
if(conn->seek_func) {
|
||||||
curl_off_t readthisamountnow = data->state.resume_from;
|
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
|
||||||
|
SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
if(conn->seek_func(conn->seek_client,
|
if(seekerr != CURL_SEEKFUNC_OK) {
|
||||||
readthisamountnow, SEEK_SET) != 0) {
|
if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
|
||||||
failf(data, "Could not seek stream");
|
failf(data, "Could not seek stream");
|
||||||
return CURLE_FTP_COULDNT_USE_REST;
|
return CURLE_FTP_COULDNT_USE_REST;
|
||||||
}
|
}
|
||||||
}
|
/* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
|
||||||
|
|
||||||
else {
|
else {
|
||||||
curl_off_t passed=0;
|
curl_off_t passed=0;
|
||||||
do {
|
do {
|
||||||
@ -1579,7 +1581,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
} while(passed < data->state.resume_from);
|
} while(passed < data->state.resume_from);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/* now, decrease the size of the read */
|
/* now, decrease the size of the read */
|
||||||
if(data->set.infilesize>0) {
|
if(data->set.infilesize>0) {
|
||||||
data->set.infilesize -= data->state.resume_from;
|
data->set.infilesize -= data->state.resume_from;
|
||||||
|
16
lib/http.c
16
lib/http.c
@ -2054,7 +2054,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
|||||||
const char *httpstring;
|
const char *httpstring;
|
||||||
send_buffer *req_buffer;
|
send_buffer *req_buffer;
|
||||||
curl_off_t postsize; /* off_t type to be able to hold a large file size */
|
curl_off_t postsize; /* off_t type to be able to hold a large file size */
|
||||||
|
int seekerr = CURL_SEEKFUNC_OK;
|
||||||
|
|
||||||
/* Always consider the DO phase done after this function call, even if there
|
/* Always consider the DO phase done after this function call, even if there
|
||||||
may be parts of the request that is not yet sent, since we can deal with
|
may be parts of the request that is not yet sent, since we can deal with
|
||||||
@ -2335,19 +2335,22 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
|||||||
/* Now, let's read off the proper amount of bytes from the
|
/* Now, let's read off the proper amount of bytes from the
|
||||||
input. */
|
input. */
|
||||||
if(conn->seek_func) {
|
if(conn->seek_func) {
|
||||||
curl_off_t readthisamountnow = data->state.resume_from;
|
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
|
||||||
|
SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
if(conn->seek_func(conn->seek_client,
|
if(seekerr != CURL_SEEKFUNC_OK) {
|
||||||
readthisamountnow, SEEK_SET) != 0) {
|
if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
|
||||||
failf(data, "Could not seek stream");
|
failf(data, "Could not seek stream");
|
||||||
return CURLE_READ_ERROR;
|
return CURLE_READ_ERROR;
|
||||||
}
|
}
|
||||||
}
|
/* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
|
||||||
else {
|
else {
|
||||||
curl_off_t passed=0;
|
curl_off_t passed=0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
size_t readthisamountnow = (size_t)(data->state.resume_from - passed);
|
size_t readthisamountnow = (size_t)(data->state.resume_from -
|
||||||
|
passed);
|
||||||
size_t actuallyread;
|
size_t actuallyread;
|
||||||
|
|
||||||
if(readthisamountnow > BUFSIZE)
|
if(readthisamountnow > BUFSIZE)
|
||||||
@ -2366,6 +2369,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
|||||||
}
|
}
|
||||||
} while(passed != data->state.resume_from); /* loop until done */
|
} while(passed != data->state.resume_from); /* loop until done */
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* now, decrease the size of the read */
|
/* now, decrease the size of the read */
|
||||||
if(data->set.infilesize>0) {
|
if(data->set.infilesize>0) {
|
||||||
|
13
lib/ssh.c
13
lib/ssh.c
@ -463,6 +463,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
|||||||
const char *host_public_key_md5;
|
const char *host_public_key_md5;
|
||||||
int rc = LIBSSH2_ERROR_NONE, i;
|
int rc = LIBSSH2_ERROR_NONE, i;
|
||||||
int err;
|
int err;
|
||||||
|
int seekerr = CURL_SEEKFUNC_OK;
|
||||||
*block = 0; /* we're not blocking by default */
|
*block = 0; /* we're not blocking by default */
|
||||||
|
|
||||||
switch(sshc->state) {
|
switch(sshc->state) {
|
||||||
@ -1315,14 +1316,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
|||||||
if(data->state.resume_from > 0) {
|
if(data->state.resume_from > 0) {
|
||||||
/* Let's read off the proper amount of bytes from the input. */
|
/* Let's read off the proper amount of bytes from the input. */
|
||||||
if(conn->seek_func) {
|
if(conn->seek_func) {
|
||||||
curl_off_t readthisamountnow = data->state.resume_from;
|
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
|
||||||
|
SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
if(conn->seek_func(conn->seek_client,
|
if(seekerr != CURL_SEEKFUNC_OK){
|
||||||
readthisamountnow, SEEK_SET) != 0) {
|
|
||||||
|
if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
|
||||||
failf(data, "Could not seek stream");
|
failf(data, "Could not seek stream");
|
||||||
return CURLE_FTP_COULDNT_USE_REST;
|
return CURLE_FTP_COULDNT_USE_REST;
|
||||||
}
|
}
|
||||||
}
|
/* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
|
||||||
else {
|
else {
|
||||||
curl_off_t passed=0;
|
curl_off_t passed=0;
|
||||||
curl_off_t readthisamountnow;
|
curl_off_t readthisamountnow;
|
||||||
@ -1347,6 +1351,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
|||||||
}
|
}
|
||||||
} while(passed < data->state.resume_from);
|
} while(passed < data->state.resume_from);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* now, decrease the size of the read */
|
/* now, decrease the size of the read */
|
||||||
if(data->set.infilesize>0) {
|
if(data->set.infilesize>0) {
|
||||||
|
@ -3302,9 +3302,10 @@ static int my_seek(void *stream, curl_off_t offset, int whence)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if(-1 == lseek(in->fd, offset, whence))
|
if(-1 == lseek(in->fd, offset, whence))
|
||||||
/* couldn't rewind, the reason is in errno but errno is just not
|
/* couldn't rewind, the reason is in errno but errno is just not portable
|
||||||
portable enough and we don't actually care that much why we failed. */
|
enough and we don't actually care that much why we failed. We'll let
|
||||||
return 1;
|
libcurl know that it may try other means if it wants to. */
|
||||||
|
return CURL_SEEKFUNC_CANTSEEK;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user