Commit 08adf679 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

Daniel Egger made CURLOPT_RANGE work on file:// URLs the very same way it

already worked for FTP:// URLs
parent e2c81773
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -7,6 +7,9 @@
                                  Changelog

Daniel S (11 Jan 2008)
- Daniel Egger made CURLOPT_RANGE work on file:// URLs the very same way it
  already worked for FTP:// URLs.

- 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
+1 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ This release includes the following bugfixes:
 o time zone offsets from -1400 to +1400 are now accepted by the date parser
 o allows more spaces in WWW/Proxy-Authenticate: headers
 o curl-config --libs skips /usr/lib64
 o range support for file:// transfers

This release includes the following known bugs:

+3 −3
Original line number Diff line number Diff line
@@ -974,9 +974,9 @@ This option can be used multiple times.
random data. The data is used to seed the random engine for SSL connections.
See also the \fI--egd-file\fP option.
.IP "-r/--range <range>"
(HTTP/FTP)
Retrieve a byte range (i.e a partial document) from a HTTP/1.1 or FTP
server. Ranges can be specified in a number of ways.
(HTTP/FTP/FILE) Retrieve a byte range (i.e a partial document) from a
HTTP/1.1, FTP server or a local FILE. Ranges can be specified in a number of
ways.
.RS
.TP 10
.B 0-499
+2 −0
Original line number Diff line number Diff line
@@ -1119,6 +1119,8 @@ transfers also support several intervals, separated with commas as in
\fI"X-Y,N-M"\fP. Using this kind of multiple intervals will cause the HTTP
server to send the response document in pieces (using standard MIME separation
techniques). Pass a NULL to this option to disable the use of ranges.

Ranges work on HTTP, FTP and FILE (since 7.18.0) transfers only.
.IP CURLOPT_RESUME_FROM
Pass a long as parameter. It contains the offset in number of bytes that you
want the transfer to start from. Set this option to 0 to make the transfer
+84 −5
Original line number Diff line number Diff line
@@ -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 @@ const struct Curl_handler Curl_handler_file = {
  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,20 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
    return result;
  }

  /* Check whether file range has been specified */
  file_range(conn);

  /* Adjust the start offset in case we want to get the N last bytes
   * of the stream iff the filesize could be determined */
  if(data->state.resume_from < 0) {
    if(!fstated) {
      failf(data, "Can't get the size of file.");
      return CURLE_READ_ERROR;
    }
    else
      data->state.resume_from += (curl_off_t)statbuf.st_size;
  }

  if(data->state.resume_from <= expected_size)
    expected_size -= data->state.resume_from;
  else {
@@ -441,6 +511,10 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
    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;

@@ -460,15 +534,20 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
  Curl_pgrsTime(data, TIMER_STARTTRANSFER);

  while(res == CURLE_OK) {
    /* Don't fill a whole buffer if we want less than all data */
    if (expected_size < BUFSIZE-1)
      nread = read(fd, buf, expected_size);
    else
      nread = read(fd, buf, BUFSIZE-1);

    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)
Loading