aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/ftp.c53
-rw-r--r--lib/http.c55
-rw-r--r--lib/transfer.c15
-rw-r--r--lib/url.c18
-rw-r--r--lib/urldata.h5
5 files changed, 99 insertions, 47 deletions
diff --git a/lib/ftp.c b/lib/ftp.c
index 29cbcb0f8..af0fc2f00 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -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) {
diff --git a/lib/url.c b/lib/url.c
index d7b4c512a..a5e4565ad 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -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;