Index: lib/file.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/file.c,v
retrieving revision 1.103
diff -u -r1.103 file.c
--- lib/file.c	8 Dec 2007 22:50:55 -0000	1.103
+++ lib/file.c	5 Jan 2008 12:17:48 -0000
@@ -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
@@ -70,6 +70,7 @@
 
 #endif
 
+#include "strtoofft.h"
 #include "urldata.h"
 #include <curl/curl.h>
 #include "progress.h"
@@ -119,6 +120,61 @@
   PROT_FILE                             /* protocol */
 };
 
+
+ /*
+  Check if this is a range download, and if so, set the internal variables
+  properly. This code is copied from the FTP implementation and might as
+  well be factored out.
+ */
+static CURLcode file_range(struct connectdata *conn)
+{
+  curl_off_t from, to;
+  curl_off_t totalsize=-1;
+  char *ptr;
+  char *ptr2;
+  struct SessionHandle *data = conn->data;
+
+  if(data->state.use_range && data->state.range) {
+    from=curlx_strtoofft(data->state.range, &ptr, 0);
+    while(ptr && *ptr && (isspace((int)*ptr) || (*ptr=='-')))
+      ptr++;
+    to=curlx_strtoofft(ptr, &ptr2, 0);
+    if(ptr == ptr2) {
+      /* we didn't get any digit */
+      to=-1;
+    }
+    if((-1 == to) && (from>=0)) {
+      /* X - */
+      data->state.resume_from = from;
+      DEBUGF(infof(data, "RANGE %" FORMAT_OFF_T " to end of file\n",
+                   from));
+    }
+    else if(from < 0) {
+      /* -Y */
+      totalsize = -from;
+      data->req.maxdownload = -from;
+      data->state.resume_from = from;
+      DEBUGF(infof(data, "RANGE the last %" FORMAT_OFF_T " bytes\n",
+                   totalsize));
+    }
+    else {
+      /* X-Y */
+      totalsize = to-from;
+      data->req.maxdownload = totalsize+1; /* include last byte */
+      data->state.resume_from = from;
+      DEBUGF(infof(data, "RANGE from %" FORMAT_OFF_T
+                   " getting %" FORMAT_OFF_T " bytes\n",
+                   from, data->req.maxdownload));
+    }
+    DEBUGF(infof(data, "range-download from %" FORMAT_OFF_T
+                 " to %" FORMAT_OFF_T ", totally %" FORMAT_OFF_T " bytes\n",
+                 from, to, data->req.maxdownload));
+  }
+  else
+    data->req.maxdownload = -1;
+  return CURLE_OK;
+}
+
 /*
  * file_connect() gets called from Curl_protocol_connect() to allow us to
  * do protocol-specific actions at connect-time.  We emulate a
@@ -434,6 +490,9 @@
     return result;
   }
 
+  /* Check whether file range has been specified */
+  file_range(conn);
+
   if(data->state.resume_from <= expected_size)
     expected_size -= data->state.resume_from;
   else {
@@ -441,6 +500,10 @@
     return CURLE_BAD_DOWNLOAD_RESUME;
   }
 
+  /* A high water mark has been specified so we obey... */
+  if (data->req.maxdownload > 0)
+    expected_size = data->req.maxdownload;
+
   if(fstated && (expected_size == 0))
     return CURLE_OK;
 
@@ -465,10 +528,11 @@
     if( nread > 0)
       buf[nread] = 0;
 
-    if(nread <= 0)
+    if (nread <= 0 || expected_size == 0)
       break;
 
     bytecount += nread;
+    expected_size -= nread;
 
     res = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread);
     if(res)
Index: tests/data/test1016
===================================================================
RCS file: tests/data/test1016
diff -N tests/data/test1016
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/data/test1016	5 Jan 2008 12:17:48 -0000
@@ -0,0 +1,35 @@
+<testcase>
+<info>
+<keywords>
+FILE
+</keywords>
+</info>
+
+<reply>
+<data>
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+none
+</server>
+ <name>
+range of a file:// URL to stdout
+ </name>
+ <command>
+-r 1-4 file://localhost/%PWD/log/test1016.txt 
+</command>
+<file name="log/test1016.txt">
+1234567890
+</file>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<stdout nonewline="yes">
+2345
+</stdout>
+</verify>
+</testcase>
Index: tests/data/test1017
===================================================================
RCS file: tests/data/test1017
diff -N tests/data/test1017
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/data/test1017	5 Jan 2008 12:17:48 -0000
@@ -0,0 +1,35 @@
+<testcase>
+<info>
+<keywords>
+FILE
+</keywords>
+</info>
+# Server-side
+<reply>
+<data>
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+none
+</server>
+ <name>
+range at the beginning of file specified by a file:// URL to stdout
+ </name>
+ <command>
+-r 0-3 file://localhost/%PWD/log/test1017.txt 
+</command>
+<file name="log/test1017.txt">
+1234567890
+</file>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<stdout nonewline="yes">
+1234
+</stdout>
+</verify>
+</testcase>
Index: tests/data/test1019
===================================================================
RCS file: tests/data/test1019
diff -N tests/data/test1019
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/data/test1019	5 Jan 2008 12:17:48 -0000
@@ -0,0 +1,37 @@
+<testcase>
+<info>
+<keywords>
+FILE
+</keywords>
+</info>
+# Server-side
+<reply>
+<data>
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+none
+</server>
+ <name>
+end open range specified on a file:// URL to stdout
+ </name>
+ <command>
+-r 7- file://localhost/%PWD/log/test1019.txt 
+</command>
+<file name="log/test1019.txt">
+1234567890
+1234567890
+</file>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<stdout>
+890
+1234567890
+</stdout>
+</verify>
+</testcase>
Index: tests/data/test1020
===================================================================
RCS file: tests/data/test1020
diff -N tests/data/test1020
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/data/test1020	5 Jan 2008 12:17:48 -0000
@@ -0,0 +1,36 @@
+<testcase>
+<info>
+<keywords>
+FILE
+</keywords>
+</info>
+# Server-side
+<reply>
+<data>
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+none
+</server>
+ <name>
+beginning open range specified on a file:// URL to stdout
+ </name>
+ <command>
+-r -9 file://localhost/%PWD/log/test1020.txt 
+</command>
+<file name="log/test1020.txt">
+1234567890
+1234567890
+</file>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<stdout nonewline="yes">
+123456789
+</stdout>
+</verify>
+</testcase>
