diff -ruN curl-7.17.1/include/curl/curl.h curl-7.17.1.local/include/curl/curl.h
--- curl-7.17.1/include/curl/curl.h	2007-10-22 16:30:17.000000000 +0200
+++ curl-7.17.1.local/include/curl/curl.h	2007-12-07 20:15:42.000000000 +0100
@@ -238,6 +238,9 @@
                                       size_t nitems,
                                       void *instream);
 
+typedef int (*curl_fastforward_callback)(void *instream,
+                                         curl_off_t offset);
+
 typedef enum  {
   CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */
   CURLSOCKTYPE_LAST   /* never use */
@@ -1159,6 +1162,10 @@
   /* POST volatile input fields. */
   CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165),
 
+  /* Callback function for fast forwarding (seeking) input after
+     a resume */
+  CINIT(FASTFORWARDFUNCTION, FUNCTIONPOINT, 166),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
diff -ruN curl-7.17.1/lib/ftp.c curl-7.17.1.local/lib/ftp.c
--- curl-7.17.1/lib/ftp.c	2007-10-27 00:25:19.000000000 +0200
+++ curl-7.17.1.local/lib/ftp.c	2007-12-07 20:12:09.000000000 +0100
@@ -1525,7 +1525,6 @@
   struct FTP *ftp = conn->data->reqdata.proto.ftp;
   struct SessionHandle *data = conn->data;
   struct ftp_conn *ftpc = &conn->proto.ftpc;
-  curl_off_t passed=0;
 
   if((data->reqdata.resume_from && !sizechecked) ||
      ((data->reqdata.resume_from > 0) && sizechecked)) {
@@ -1552,30 +1551,37 @@
     /* 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->reqdata.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 != readthisamountnow) {
-        failf(data, "Could only read %" FORMAT_OFF_T
-              " bytes from the input", passed);
+    /* Let's read off the proper amount of bytes from the input. */
+    if(conn->ff_func) {
+      curl_off_t readthisamountnow = data->reqdata.resume_from;
+
+      if(conn->ff_func(conn->fread_in, readthisamountnow) != 0) {
+        failf(data, "Could not fast forward stream");
         return CURLE_FTP_COULDNT_USE_REST;
       }
-    } while(passed != data->reqdata.resume_from);
+    }
+
+    else {
+      curl_off_t passed=0;
+      do {
+        curl_off_t readthisamountnow = (data->reqdata.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 != readthisamountnow) {
+          failf(data, "Could only read %" FORMAT_OFF_T
+                " bytes from the input", passed);
+          return CURLE_FTP_COULDNT_USE_REST;
+        }
+      } while(passed != data->reqdata.resume_from);
+    }
 
     /* now, decrease the size of the read */
     if(data->set.infilesize>0) {
diff -ruN curl-7.17.1/lib/http.c curl-7.17.1.local/lib/http.c
--- curl-7.17.1/lib/http.c	2007-10-23 16:43:03.000000000 +0200
+++ curl-7.17.1.local/lib/http.c	2007-12-07 20:13:38.000000000 +0100
@@ -1765,6 +1765,7 @@
   /* set the proper values (possibly modified on POST) */
   conn->fread_func = data->set.fread_func; /* restore */
   conn->fread_in = data->set.in; /* restore */
+  conn->ff_func = data->set.ff_func; /* restore */
 
   if (http == NULL)
     return CURLE_OK;
@@ -2156,30 +2157,40 @@
 
     if(data->reqdata.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->reqdata.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->ff_func) {
+        curl_off_t readthisamountnow = data->reqdata.resume_from;
+
+        if(conn->ff_func(conn->fread_in, readthisamountnow) != 0) {
+          failf(data, "Could not fast forward stream");
           return CURLE_READ_ERROR;
         }
-      } while(passed != data->reqdata.resume_from); /* loop until done */
+      }
+
+      else {
+        curl_off_t passed=0;
+        do {
+          curl_off_t readthisamountnow = (size_t)(data->reqdata.resume_from - passed);
+          curl_off_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->reqdata.resume_from); /* loop until done */
+      }
 
       /* now, decrease the size of the read */
       if(data->set.infilesize>0) {
diff -ruN curl-7.17.1/lib/url.c curl-7.17.1.local/lib/url.c
--- curl-7.17.1/lib/url.c	2007-10-27 00:25:19.000000000 +0200
+++ curl-7.17.1.local/lib/url.c	2007-12-06 22:29:30.000000000 +0100
@@ -682,6 +682,9 @@
     /* use fread as default function to read input */
     data->set.fread_func = (curl_read_callback)fread;
 
+    /* don't use a fast forward function by default */
+    data->set.ff_func = ZERO_NULL;
+
     /* conversion callbacks for non-ASCII hosts */
     data->set.convfromnetwork = ZERO_NULL;
     data->set.convtonetwork   = ZERO_NULL;
@@ -1624,6 +1627,12 @@
       /* When set to NULL, reset to our internal default function */
       data->set.fread_func = (curl_read_callback)fread;
     break;
+  case CURLOPT_FASTFORWARDFUNCTION:
+    /*
+     * Fast forward callback
+     */
+    data->set.ff_func = va_arg(param, curl_fastforward_callback);
+    break;
   case CURLOPT_CONV_FROM_NETWORK_FUNCTION:
     /*
      * "Convert from network encoding" callback
@@ -4010,6 +4019,7 @@
    * the persistent connection stuff */
   conn->fread_func = data->set.fread_func;
   conn->fread_in = data->set.in;
+  conn->ff_func = data->set.ff_func;
 
   if ((conn->protocol&PROT_HTTP) &&
       data->set.upload &&
diff -ruN curl-7.17.1/lib/urldata.h curl-7.17.1.local/lib/urldata.h
--- curl-7.17.1/lib/urldata.h	2007-10-24 23:09:59.000000000 +0200
+++ curl-7.17.1.local/lib/urldata.h	2007-12-06 22:23:08.000000000 +0100
@@ -1010,6 +1010,9 @@
   curl_read_callback fread_func; /* function that reads the input */
   void *fread_in;           /* pointer to pass to the fread() above */
 
+  curl_fastforward_callback ff_func; /* function that seeks (fast forwards)
+                                        the input after resume */
+
   struct ntlmdata ntlm;     /* NTLM differs from other authentication schemes
                                because it authenticates connections, not
                                single requests! */
@@ -1342,6 +1345,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_fastforward_callback ff_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 */

