diff -ru curl/include/curl/curl.h curl.local/include/curl/curl.h
--- curl/include/curl/curl.h	2008-01-05 23:04:18.000000000 +0100
+++ curl.local/include/curl/curl.h	2008-01-07 22:20:14.000000000 +0100
@@ -244,6 +244,10 @@
                                       size_t nitems,
                                       void *instream);
 
+typedef int (*curl_seek_callback)(void *instream,
+                                  curl_off_t offset,
+				  int origin);
+
 typedef enum  {
   CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */
   CURLSOCKTYPE_LAST   /* never use */
@@ -1175,6 +1179,10 @@
   /* set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy */
   CINIT(PROXY_TRANSFER_MODE, LONG, 166),
 
+  /* Callback function for seeking input */
+  CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167),
+  CINIT(SEEKDATA, OBJECTPOINT, 168),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
diff -ru curl/lib/ftp.c curl.local/lib/ftp.c
--- curl/lib/ftp.c	2008-01-06 22:41:38.000000000 +0100
+++ curl.local/lib/ftp.c	2008-01-07 22:28:14.000000000 +0100
@@ -1525,7 +1525,6 @@
   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 @@
     /* 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 */
-
-    /* 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");
+    /* Let's read off the proper amount of bytes from the input. */
+    if(conn->seek_func) {
+      curl_off_t readthisamountnow = data->reqdata.resume_from;
+
+      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 -ru curl/lib/http.c curl.local/lib/http.c
--- curl/lib/http.c	2007-12-13 11:00:06.000000000 +0100
+++ curl.local/lib/http.c	2008-01-07 22:35:05.000000000 +0100
@@ -1793,6 +1793,8 @@
   /* 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,40 @@
 
     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;
+         input. */
+      if(conn->seek_func) {
+        curl_off_t readthisamountnow = data->reqdata.resume_from;
+
+        if(conn->seek_func(conn->seek_client,
+			   readthisamountnow, SEEK_SET) != 0) {
+          failf(data, "Could not seek stream");
+          return CURLE_READ_ERROR;
+        }
+      }
+
+      else {
+        do {
+	  size_t readthisamountnow = (size_t)(data->state.resume_from - passed);
+          size_t actuallyread;
 
-        if(readthisamountnow > BUFSIZE)
-          readthisamountnow = BUFSIZE;
+          if(readthisamountnow > BUFSIZE)
+            readthisamountnow = BUFSIZE;
 
-        actuallyread =
-          data->set.fread_func(data->state.buffer, 1, (size_t)readthisamountnow,
+          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 */
+          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 -ru curl/lib/transfer.c curl.local/lib/transfer.c
--- curl/lib/transfer.c	2007-12-08 23:50:55.000000000 +0100
+++ curl.local/lib/transfer.c	2008-01-07 22:39:04.000000000 +0100
@@ -237,7 +237,18 @@
      (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,
diff -ru curl/lib/url.c curl.local/lib/url.c
--- curl/lib/url.c	2008-01-06 22:41:38.000000000 +0100
+++ curl.local/lib/url.c	2008-01-07 22:41:19.000000000 +0100
@@ -685,6 +685,10 @@
     /* 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 @@
       /* 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 @@
    * 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 -ru curl/lib/urldata.h curl.local/lib/urldata.h
--- curl/lib/urldata.h	2008-01-05 23:04:18.000000000 +0100
+++ curl.local/lib/urldata.h	2008-01-07 22:44:29.000000000 +0100
@@ -961,6 +961,9 @@
   curl_read_callback fread_func; /* function that reads the input */
   void *fread_in;           /* pointer to pass to the fread() above */
 
+  curl_seek_callback seek_func; /* function that seeks the input */
+  void *seek_client;            /* pointer to pass to the seek() above */
+
   struct ntlmdata ntlm;     /* NTLM differs from other authentication schemes
                                because it authenticates connections, not
                                single requests! */
@@ -1324,6 +1327,7 @@
   curl_write_callback fwrite_func;   /* function that stores the output */
   curl_write_callback fwrite_header; /* function that stores headers */
   curl_read_callback fread_func;     /* function that reads the input */
+  curl_seek_callback seek_func;      /* function that seeks the input */
   curl_progress_callback fprogress;  /* function for progress information */
   curl_debug_callback fdebug;      /* function that write informational data */
   curl_ioctl_callback ioctl_func;  /* function for I/O control */
@@ -1342,6 +1346,7 @@
   curl_conv_callback convfromutf8;
 
   void *progress_client; /* pointer to pass to the progress callback */
+  void *seek_client;    /* pointer to pass to the seek callback */
   void *ioctl_client;   /* pointer to pass to the ioctl callback */
   long timeout;         /* in milliseconds, 0 means no timeout */
   long connecttimeout;  /* in milliseconds, 0 means no timeout */

