diff --git a/CHANGES b/CHANGES
index a9b86d674259444ea7da1fa7e60fbc6e6a867e44..032aac0a08022dd5be8c138718823c4c6b07755e 100644
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,15 @@
 
                                   Changelog
 
+Daniel S (11 Jan 2008)
+- I made the curl tool switch from using CURLOPT_IOCTLFUNCTION to now use the
+  spanking new CURLOPT_SEEKFUNCTION simply to take advantage of the improved
+  performance for the upload resume cases where you want to upload the last
+  few bytes of a very large file. To implement this decently, I had to switch
+  the client code for uploading from fopen()/fread() to plain open()/read() so
+  that we can use lseek() to do >32bit seeks (as fseek() doesn't allow that)
+  on systems that offer support for that.
+
 Daniel S (10 Jan 2008)
 - Michal Marek made curl-config --libs not include /usr/lib64 in the output
   (it already before skipped /usr/lib).  /usr/lib64 is the default library
diff --git a/configure.ac b/configure.ac
index c8a4ed3c407c6c093b25d3a29248a5a5e6751780..58a3a9a7817327224615de11736164f1e625ac8a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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
@@ -1893,6 +1893,7 @@ AC_CHECK_SIZEOF(curl_off_t, ,[
 AC_CHECK_SIZEOF(size_t)
 AC_CHECK_SIZEOF(long)
 AC_CHECK_SIZEOF(time_t)
+AC_CHECK_SIZEOF(off_t)
 
 AC_CHECK_TYPE(long long,
    [AC_DEFINE(HAVE_LONGLONG, 1, [if your compiler supports long long])]
diff --git a/src/main.c b/src/main.c
index 2b6cf4ab8c9ff9027143023810db7a861fd029d7..7801c345f5480fda173063215a0e289699d3e9d8 100644
--- a/src/main.c
+++ b/src/main.c
@@ -127,6 +127,12 @@
   #define SET_BINMODE(file)   ((void)0)
 #endif
 
+#ifndef O_BINARY
+/* since O_BINARY as used in bitmasks, setting it to zero makes it usable in
+   source code but yet it doesn't ruin anything */
+#define O_BINARY 0
+#endif
+
 #ifdef MSDOS
 #include <dos.h>
 
@@ -201,6 +207,7 @@ typedef enum {
 /* Support uploading and resuming of >2GB files
  */
 #if defined(WIN32) && (SIZEOF_CURL_OFF_T > 4)
+#define lseek(x,y,z) _lseeki64(x, y, z)
 #define struct_stat struct _stati64
 #define stat(file,st) _stati64(file,st)
 #else
@@ -605,6 +612,8 @@ struct getout {
 static void help(void)
 {
   int i;
+  /* A few of these source lines are >80 columns wide, but that's only because
+     breaking the strings narrower makes this chunk look even worse! */
   static const char * const helptext[]={
     "Usage: curl [options...] <url>",
     "Options: (H) means HTTP/HTTPS only, (F) means FTP only",
@@ -1854,7 +1863,8 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
         break;
       case 'x': /* --krb */
         /* kerberos level string */
-        if(curlinfo->features & (CURL_VERSION_KERBEROS4 | CURL_VERSION_GSSNEGOTIATE))
+        if(curlinfo->features & (CURL_VERSION_KERBEROS4 |
+                                 CURL_VERSION_GSSNEGOTIATE))
           GetStr(&config->krblevel, nextarg);
         else
           return PARAM_LIBCURL_DOESNT_SUPPORT;
@@ -3016,41 +3026,56 @@ static size_t my_fwrite(void *buffer, size_t sz, size_t nmemb, void *stream)
 }
 
 struct InStruct {
-  FILE *stream;
+  int fd;
   struct Configurable *config;
 };
 
-#if 1
-static curlioerr my_ioctl(CURL *handle, curliocmd cmd, void *userp)
-{
-  struct InStruct *in=(struct InStruct *)userp;
-  (void)handle; /* not used in here */
-
-  switch(cmd) {
-  case CURLIOCMD_RESTARTREAD:
-    /* mr libcurl kindly asks as to rewind the read data stream to start */
-    if(-1 == fseek(in->stream, 0, SEEK_SET))
-      /* couldn't rewind, the reason is in errno but errno is just not
-         portable enough and we don't actually care that much why we failed. */
-      return CURLIOE_FAILRESTART;
-
-    break;
+#define MAX_SEEK 2147483647
 
-  default: /* ignore unknown commands */
-    return CURLIOE_UNKNOWNCMD;
-  }
-  return CURLIOE_OK;
-}
-#else
+#ifndef SIZEOF_OFF_T
+/* (Jan 11th 2008) this is a reasonably new define in the config.h so there
+   might be older handicrafted configs that don't define it properly and then
+   we assume 32bit off_t */
+#define SIZEOF_OFF_T 4
+#endif
+/*
+ * my_seek() is the CURLOPT_SEEKFUNCTION we use
+ */
 static int my_seek(void *stream, curl_off_t offset, int whence)
 {
   struct InStruct *in=(struct InStruct *)stream;
 
-  /* We can't use fseek() here since it can't do 64bit seeks on Windows and
-     possibly elsewhere. We need to switch to the lseek family of tricks. For
-     that to work, we need to switch from fread() to plain read() etc */
+#if (SIZEOF_CURL_OFF_T > SIZEOF_OFF_T) && !defined(lseek)
+  /* The sizeof check following here is only interesting if curl_off_t is
+     larger than off_t, but also not on windows-like systems for which lseek
+     is a defined macro that works around the 32bit off_t-problem and thus do
+     64bit seeks correctly anyway */
+
+  if(offset > MAX_SEEK) {
+    /* Some precaution code to work around problems with different data sizes
+       to allow seeking >32bit even if off_t is 32bit. Should be very rare and
+       is really valid on weirdo-systems. */
+    curl_off_t left = offset;
 
-  if(-1 == fseek(in->stream, (off_t)offset, whence))
+    if(whence != SEEK_SET)
+      /* this code path doesn't support other types */
+      return 1;
+
+    if(-1 == lseek(in->fd, 0, SEEK_SET))
+      /* couldn't rewind to beginning */
+      return 1;
+
+    while(left) {
+      long step = (left>MAX_SEEK ? MAX_SEEK : (long)left);
+      if(-1 == lseek(in->fd, step, SEEK_CUR))
+        /* couldn't seek forwards the desired amount */
+        return 1;
+      left -= step;
+    }
+    return 0;
+  }
+#endif
+  if(-1 == lseek(in->fd, offset, whence))
     /* couldn't rewind, the reason is in errno but errno is just not
        portable enough and we don't actually care that much why we failed. */
     return 1;
@@ -3058,15 +3083,16 @@ static int my_seek(void *stream, curl_off_t offset, int whence)
   return 0;
 }
 
-#endif
-
 static size_t my_fread(void *buffer, size_t sz, size_t nmemb, void *userp)
 {
-  size_t rc;
+  ssize_t rc;
   struct InStruct *in=(struct InStruct *)userp;
 
-  rc = fread(buffer, sz, nmemb, in->stream);
-  return rc;
+  rc = read(in->fd, buffer, sz*nmemb);
+  if(rc < 0)
+    /* since size_t is unsigned we can't return negative values fine */
+    return 0;
+  return (size_t)rc;
 }
 
 struct ProgressData {
@@ -3689,8 +3715,8 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
   int infilenum;
   char *uploadfile=NULL; /* a single file, never a glob */
 
-  FILE *infd = stdin;
-  bool infdfopen;
+  int infd = STDIN_FILENO;
+  bool infdopen;
   FILE *headerfilep = NULL;
   curl_off_t uploadfilesize; /* -1 means unknown */
   bool stillflags=TRUE;
@@ -4112,7 +4138,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
             outs.stream = NULL; /* open when needed */
           }
         }
-        infdfopen=FALSE;
+        infdopen=FALSE;
         if(uploadfile && !curlx_strequal(uploadfile, "-")) {
           /*
            * We have specified a file to upload and it isn't "-".
@@ -4180,11 +4206,11 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
            * to be considered with one appended if implied CC
            */
 
-          infd=(FILE *) fopen(uploadfile, "rb");
-          if (!infd || stat(uploadfile, &fileinfo)) {
+          infd= open(uploadfile, O_RDONLY | O_BINARY);
+          if ((infd == -1) || stat(uploadfile, &fileinfo)) {
             helpf("Can't open '%s'!\n", uploadfile);
-            if(infd)
-              fclose(infd);
+            if(infd != -1)
+              close(infd);
 
             /* Free the list of remaining URLs and globbed upload files
              * to force curl to exit immediately
@@ -4201,13 +4227,13 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
             res = CURLE_READ_ERROR;
             goto quit_urls;
           }
-          infdfopen=TRUE;
+          infdopen=TRUE;
           uploadfilesize=fileinfo.st_size;
 
         }
         else if(uploadfile && curlx_strequal(uploadfile, "-")) {
           SET_BINMODE(stdin);
-          infd = stdin;
+          infd = STDIN_FILENO;
         }
 
         if(uploadfile && config->resume_from_current)
@@ -4269,8 +4295,8 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
           config->errors = stderr;
 
         if(!outfile && !(config->conf & CONF_GETTEXT)) {
-          /* We get the output to stdout and we have not got the ASCII/text flag,
-             then set stdout to be binary */
+          /* We get the output to stdout and we have not got the ASCII/text
+             flag, then set stdout to be binary */
           SET_BINMODE(stdout);
         }
 
@@ -4283,23 +4309,16 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
         my_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
 
         /* for uploads */
-        input.stream = infd;
+        input.fd = infd;
         input.config = config;
         my_setopt(curl, CURLOPT_READDATA, &input);
         /* what call to read */
         my_setopt(curl, CURLOPT_READFUNCTION, my_fread);
 
-#if 1
-        /* the ioctl function is at this point only used to rewind files
-           that are posted when using NTLM etc */
-        my_setopt(curl, CURLOPT_IOCTLDATA, &input);
-        my_setopt(curl, CURLOPT_IOCTLFUNCTION, my_ioctl);
-#else
-        /* in 7.18.0, the SEEKFUNCTION/DATA pair is taking over what IOCTL*
-           previously provided for seeking */
+        /* in 7.18.0, the CURLOPT_SEEKFUNCTION/DATA pair is taking over what
+           CURLOPT_IOCTLFUNCTION/DATA pair previously provided for seeking */
         my_setopt(curl, CURLOPT_SEEKDATA, &input);
         my_setopt(curl, CURLOPT_SEEKFUNCTION, my_seek);
-#endif
 
         if(config->recvpersecond)
           /* tell libcurl to use a smaller sized buffer as it allows us to
@@ -4371,7 +4390,8 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
         my_setopt(curl, CURLOPT_SSLKEYTYPE, config->key_type);
         my_setopt(curl, CURLOPT_KEYPASSWD, config->key_passwd);
 
-        /* SSH private key uses the same command-line option as SSL private key */
+        /* SSH private key uses the same command-line option as SSL private
+           key */
         my_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE, config->key);
         my_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE, config->pubkey);
 
@@ -4780,8 +4800,8 @@ quit_urls:
         if(outfile)
           free(outfile);
 
-        if(infdfopen)
-          fclose(infd);
+        if(infdopen)
+          close(infd);
 
       } /* loop to the next URL */