aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2009-04-28 11:19:10 +0000
committerDaniel Stenberg <daniel@haxx.se>2009-04-28 11:19:10 +0000
commite01b7c1ede6f8b91f458259dbed96acce7bf3779 (patch)
tree5f9fd06a14d6ed451463c9e9d3efa36325abbeb3 /lib
parentdd8d472318d6346f98f366438c7a49f3b2d02503 (diff)
- 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!
Diffstat (limited to 'lib')
-rw-r--r--lib/ftp.c56
-rw-r--r--lib/http.c58
-rw-r--r--lib/ssh.c59
3 files changed, 92 insertions, 81 deletions
diff --git a/lib/ftp.c b/lib/ftp.c
index c9991f12c..ca14b977d 100644
--- a/lib/ftp.c
+++ b/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 SessionHandle *data = conn->data;
struct ftp_conn *ftpc = &conn->proto.ftpc;
+ int seekerr = CURL_SEEKFUNC_OK;
if((data->state.resume_from && !sizechecked) ||
((data->state.resume_from > 0) && sizechecked)) {
@@ -1548,38 +1549,39 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
/* Let's read off the proper amount of bytes from the input. */
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,
- readthisamountnow, SEEK_SET) != 0) {
+ if(seekerr != CURL_SEEKFUNC_OK) {
+ if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
failf(data, "Could not seek stream");
return CURLE_FTP_COULDNT_USE_REST;
}
+ /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
+ else {
+ curl_off_t passed=0;
+ do {
+ curl_off_t readthisamountnow = (data->state.resume_from - passed);
+ curl_off_t actuallyread;
+
+ if(readthisamountnow > BUFSIZE)
+ readthisamountnow = BUFSIZE;
+
+ actuallyread = (curl_off_t)
+ conn->fread_func(data->state.buffer, 1, (size_t)readthisamountnow,
+ conn->fread_in);
+
+ passed += actuallyread;
+ if((actuallyread <= 0) || (actuallyread > readthisamountnow)) {
+ /* this checks for greater-than only to make sure that the
+ CURL_READFUNC_ABORT return code still aborts */
+ failf(data, "Failed to read data");
+ return CURLE_FTP_COULDNT_USE_REST;
+ }
+ } while(passed < data->state.resume_from);
+ }
}
-
- else {
- curl_off_t passed=0;
- do {
- curl_off_t readthisamountnow = (data->state.resume_from - passed);
- curl_off_t actuallyread;
-
- if(readthisamountnow > BUFSIZE)
- readthisamountnow = BUFSIZE;
-
- actuallyread = (curl_off_t)
- conn->fread_func(data->state.buffer, 1, (size_t)readthisamountnow,
- conn->fread_in);
-
- passed += actuallyread;
- if((actuallyread <= 0) || (actuallyread > readthisamountnow)) {
- /* this checks for greater-than only to make sure that the
- CURL_READFUNC_ABORT return code still aborts */
- failf(data, "Failed to read data");
- return CURLE_FTP_COULDNT_USE_REST;
- }
- } while(passed < data->state.resume_from);
- }
-
/* now, decrease the size of the read */
if(data->set.infilesize>0) {
data->set.infilesize -= data->state.resume_from;
diff --git a/lib/http.c b/lib/http.c
index 2e3798f65..c6ff5f50f 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -2054,7 +2054,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
const char *httpstring;
send_buffer *req_buffer;
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
may be parts of the request that is not yet sent, since we can deal with
@@ -2335,36 +2335,40 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* Now, let's read off the proper amount of bytes from the
input. */
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,
- readthisamountnow, SEEK_SET) != 0) {
+ if(seekerr != CURL_SEEKFUNC_OK) {
+ if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
failf(data, "Could not seek stream");
return CURLE_READ_ERROR;
}
- }
- else {
- curl_off_t passed=0;
-
- do {
- size_t readthisamountnow = (size_t)(data->state.resume_from - passed);
- size_t actuallyread;
-
- if(readthisamountnow > BUFSIZE)
- readthisamountnow = BUFSIZE;
-
- actuallyread = data->set.fread_func(data->state.buffer, 1,
- (size_t)readthisamountnow,
- data->set.in);
-
- passed += actuallyread;
- if(actuallyread != readthisamountnow) {
- failf(data, "Could only read %" FORMAT_OFF_T
- " bytes from the input",
- passed);
- return CURLE_READ_ERROR;
- }
- } while(passed != data->state.resume_from); /* loop until done */
+ /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
+ else {
+ curl_off_t passed=0;
+
+ do {
+ size_t readthisamountnow = (size_t)(data->state.resume_from -
+ passed);
+ size_t actuallyread;
+
+ if(readthisamountnow > BUFSIZE)
+ readthisamountnow = BUFSIZE;
+
+ actuallyread = data->set.fread_func(data->state.buffer, 1,
+ (size_t)readthisamountnow,
+ data->set.in);
+
+ passed += actuallyread;
+ if(actuallyread != readthisamountnow) {
+ failf(data, "Could only read %" FORMAT_OFF_T
+ " bytes from the input",
+ passed);
+ return CURLE_READ_ERROR;
+ }
+ } while(passed != data->state.resume_from); /* loop until done */
+ }
}
/* now, decrease the size of the read */
diff --git a/lib/ssh.c b/lib/ssh.c
index 2de1cf86d..d473d1400 100644
--- a/lib/ssh.c
+++ b/lib/ssh.c
@@ -463,6 +463,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
const char *host_public_key_md5;
int rc = LIBSSH2_ERROR_NONE, i;
int err;
+ int seekerr = CURL_SEEKFUNC_OK;
*block = 0; /* we're not blocking by default */
switch(sshc->state) {
@@ -1315,37 +1316,41 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(data->state.resume_from > 0) {
/* Let's read off the proper amount of bytes from the input. */
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(seekerr != CURL_SEEKFUNC_OK){
- if(conn->seek_func(conn->seek_client,
- readthisamountnow, SEEK_SET) != 0) {
+ if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
failf(data, "Could not seek stream");
return CURLE_FTP_COULDNT_USE_REST;
}
- }
- else {
- curl_off_t passed=0;
- curl_off_t readthisamountnow;
- curl_off_t actuallyread;
- do {
- readthisamountnow = (data->state.resume_from - passed);
-
- if(readthisamountnow > BUFSIZE)
- readthisamountnow = BUFSIZE;
-
- actuallyread =
- (curl_off_t) conn->fread_func(data->state.buffer, 1,
- (size_t)readthisamountnow,
- conn->fread_in);
-
- passed += actuallyread;
- if((actuallyread <= 0) || (actuallyread > readthisamountnow)) {
- /* this checks for greater-than only to make sure that the
- CURL_READFUNC_ABORT return code still aborts */
- failf(data, "Failed to read data");
- return CURLE_FTP_COULDNT_USE_REST;
- }
- } while(passed < data->state.resume_from);
+ /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
+ else {
+ curl_off_t passed=0;
+ curl_off_t readthisamountnow;
+ curl_off_t actuallyread;
+ do {
+ readthisamountnow = (data->state.resume_from - passed);
+
+ if(readthisamountnow > BUFSIZE)
+ readthisamountnow = BUFSIZE;
+
+ actuallyread =
+ (curl_off_t) conn->fread_func(data->state.buffer, 1,
+ (size_t)readthisamountnow,
+ conn->fread_in);
+
+ passed += actuallyread;
+ if((actuallyread <= 0) || (actuallyread > readthisamountnow)) {
+ /* this checks for greater-than only to make sure that the
+ CURL_READFUNC_ABORT return code still aborts */
+ failf(data, "Failed to read data");
+ return CURLE_FTP_COULDNT_USE_REST;
+ }
+ } while(passed < data->state.resume_from);
+ }
}
/* now, decrease the size of the read */