diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ftp.c | 53 | ||||
-rw-r--r-- | lib/http.c | 55 | ||||
-rw-r--r-- | lib/transfer.c | 15 | ||||
-rw-r--r-- | lib/url.c | 18 | ||||
-rw-r--r-- | lib/urldata.h | 5 |
5 files changed, 99 insertions, 47 deletions
@@ -1525,7 +1525,6 @@ 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; - curl_off_t passed=0; if((data->state.resume_from && !sizechecked) || ((data->state.resume_from > 0) && sizechecked)) { @@ -1552,31 +1551,39 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn, /* enable append */ data->set.ftp_append = TRUE; - /* Let's read off the proper amount of bytes from the input. If we knew it - was a proper file we could've just fseek()ed but we only have a stream - here */ + /* Let's read off the proper amount of bytes from the input. */ + if(conn->seek_func) { + curl_off_t readthisamountnow = data->state.resume_from; - /* TODO: allow the ioctlfunction to provide a fast forward function that - can be used here and use this method only as a fallback! */ - 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"); + if(conn->seek_func(conn->seek_client, + readthisamountnow, SEEK_SET) != 0) { + failf(data, "Could not seek stream"); 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) { diff --git a/lib/http.c b/lib/http.c index e41a8f750..fd58c06cc 100644 --- a/lib/http.c +++ b/lib/http.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -1793,6 +1793,8 @@ CURLcode Curl_http_done(struct connectdata *conn, /* set the proper values (possibly modified on POST) */ conn->fread_func = data->set.fread_func; /* restore */ conn->fread_in = data->set.in; /* restore */ + conn->seek_func = data->set.seek_func; /* restore */ + conn->seek_client = data->set.seek_client; /* restore */ if(http == NULL) return CURLE_OK; @@ -2186,30 +2188,41 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(data->state.resume_from && !data->state.this_is_a_follow) { /* do we still game? */ - curl_off_t passed=0; /* Now, let's read off the proper amount of bytes from the - input. If we knew it was a proper file we could've just - fseek()ed but we only have a stream here */ - 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); + input. */ + if(conn->seek_func) { + curl_off_t readthisamountnow = data->state.resume_from; + + if(conn->seek_func(conn->seek_client, + readthisamountnow, SEEK_SET) != 0) { + failf(data, "Could not seek stream"); return CURLE_READ_ERROR; } - } while(passed != data->state.resume_from); /* loop until done */ + } + 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 */ if(data->set.infilesize>0) { diff --git a/lib/transfer.c b/lib/transfer.c index 77146dd6e..512eceff0 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -245,11 +245,20 @@ CURLcode Curl_readrewind(struct connectdata *conn) (data->set.httpreq == HTTPREQ_POST_FORM)) ; /* do nothing */ else { - if(data->set.ioctl_func) { + if(data->set.seek_func) { + int err; + + err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET); + if(err) { + failf(data, "seek callback returned error %d\n", (int)err); + return CURLE_SEND_FAIL_REWIND; + } + } + else if(data->set.ioctl_func) { curlioerr err; - err = (data->set.ioctl_func) (data, CURLIOCMD_RESTARTREAD, - data->set.ioctl_client); + err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD, + data->set.ioctl_client); infof(data, "the ioctl callback returned %d\n", (int)err); if(err) { @@ -685,6 +685,10 @@ CURLcode Curl_open(struct SessionHandle **curl) /* use fread as default function to read input */ data->set.fread_func = (curl_read_callback)fread; + /* don't use a seek function by default */ + data->set.seek_func = ZERO_NULL; + data->set.seek_client = ZERO_NULL; + /* conversion callbacks for non-ASCII hosts */ data->set.convfromnetwork = ZERO_NULL; data->set.convtonetwork = ZERO_NULL; @@ -1627,6 +1631,18 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, /* When set to NULL, reset to our internal default function */ data->set.fread_func = (curl_read_callback)fread; break; + case CURLOPT_SEEKFUNCTION: + /* + * Seek callback. Might be NULL. + */ + data->set.seek_func = va_arg(param, curl_seek_callback); + break; + case CURLOPT_SEEKDATA: + /* + * Seek control callback. Might be NULL. + */ + data->set.seek_client = va_arg(param, void *); + break; case CURLOPT_CONV_FROM_NETWORK_FUNCTION: /* * "Convert from network encoding" callback @@ -4038,6 +4054,8 @@ static CURLcode CreateConnection(struct SessionHandle *data, * the persistent connection stuff */ conn->fread_func = data->set.fread_func; conn->fread_in = data->set.in; + conn->seek_func = data->set.seek_func; + conn->seek_client = data->set.seek_client; if((conn->protocol&PROT_HTTP) && data->set.upload && diff --git a/lib/urldata.h b/lib/urldata.h index 976bc3771..e918cd61d 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -961,6 +961,9 @@ struct connectdata { size_t buf_len; /* Length of the buffer?? */ + curl_seek_callback seek_func; /* function that seeks the input */ + void *seek_client; /* pointer to pass to the seek() above */ + /*************** Request - specific items ************/ /* previously this was in the urldata struct */ @@ -1324,6 +1327,7 @@ struct UserDefined { bool free_referer; /* set TRUE if 'referer' points to a string we allocated */ void *postfields; /* if POST, set the fields' values here */ + curl_seek_callback seek_func; /* function that seeks the input */ curl_off_t postfieldsize; /* if POST, this might have a size to use instead of strlen(), and then the data *may* be binary (contain zero bytes) */ @@ -1342,6 +1346,7 @@ struct UserDefined { the address and opening the socket */ void* opensocket_client; + void *seek_client; /* pointer to pass to the seek callback */ /* the 3 curl_conv_callback functions below are used on non-ASCII hosts */ /* function to convert from the network encoding: */ curl_conv_callback convfromnetwork; |