Commit e01b7c1e authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

- Bug report #2709004 (http://curl.haxx.se/bug/view.cgi?id=2709004) by Tim

  Chen pointed out how curl couldn't upload with resume when reading from a
  pipe.

  This ended up with the introduction of a new return code for the
  CURLOPT_SEEKFUNCTION callback that basically says that the seek failed but
  that libcurl may try to resolve the situation anyway. In our case this means
  libcurl will attempt to instead read that much data from the stream instead
  of seeking and that way curl can now upload with resume when data is read
  from a stream!
parent dd8d4723
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -6,6 +6,18 @@

                                  Changelog

Daniel Stenberg (28 Apr 2009)
- Bug report #2709004 (http://curl.haxx.se/bug/view.cgi?id=2709004) by Tim
  Chen pointed out how curl couldn't upload with resume when reading from a
  pipe.

  This ended up with the introduction of a new return code for the
  CURLOPT_SEEKFUNCTION callback that basically says that the seek failed but
  that libcurl may try to resolve the situation anyway. In our case this means
  libcurl will attempt to instead read that much data from the stream instead
  of seeking and that way curl can now upload with resume when data is read
  from a stream!

Daniel Stenberg (26 Apr 2009)
- Bug report #2779733 (http://curl.haxx.se/bug/view.cgi?id=2779733) by Sven
  Wegener pointed out that CURLINFO_APPCONNECT_TIME didn't work with the multi
+4 −1
Original line number Diff line number Diff line
@@ -13,6 +13,8 @@ This release includes the following changes:
   connection
 o libssh2's version number can now be figured out run-time instead of using
   the build-time fixed number
 o CURLOPT_SEEKFUNCTION may now return CURL_SEEKFUNC_CANTSEEK
 o curl can now upload with resume even when reading from a pipe

This release includes the following bugfixes:

@@ -43,6 +45,7 @@ advice from friends like these:
 Daniel Fandrich, Yang Tse, David James, Chris Deidun, Bill Egert,
 Andre Guibert de Bruet, Andreas Farber, Frank Hempel, Pierre Brico,
 Kamil Dudka, Jim Freeman, Daniel Johnson, Toshio Kuratomi, Martin Storsjo,
 Pramod Sharma, Gisle Vanem, Leanic Lefever, Rainer Koenig, Sven Wegener
 Pramod Sharma, Gisle Vanem, Leanic Lefever, Rainer Koenig, Sven Wegener,
 Tim Chen

        Thanks! (and sorry if I forgot to mention someone)
+5 −2
Original line number Diff line number Diff line
@@ -189,8 +189,11 @@ uploaded bytes with the normal read function/callback). It is also called to
rewind a stream when doing a HTTP PUT or POST with a multi-pass authentication
method. The function shall work like "fseek" or "lseek" and accepted SEEK_SET,
SEEK_CUR and SEEK_END as argument for origin, although (in 7.18.0) libcurl
only passes SEEK_SET. The callback must return 0 on success as returning
something else will cause the upload operation to fail.
only passes SEEK_SET. The callback must return 0 (CURL_SEEKFUNC_OK) on
success, 1 (CURL_SEEKFUNC_FAIL) to cause the upload operation to fail or 2
(CURL_SEEKFUNC_CANTSEEK) to indicate that while the seek failed, libcurl is
free to work around the problem if possible. The latter can sometimes be done
by instead reading from the input or similar.

If you forward the input arguments directly to "fseek" or "lseek", note that
the data type for \fIoffset\fP is not the same as defined for curl_off_t on
+9 −3
Original line number Diff line number Diff line
@@ -186,15 +186,21 @@ typedef size_t (*curl_write_callback)(char *buffer,
                                      size_t nitems,
                                      void *outstream);

/* this is the return codes for the seek callbacks */
#define CURL_SEEKFUNC_OK       0
#define CURL_SEEKFUNC_FAIL     1 /* fail the entire transfer */
#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so
                                    libcurl might try other means instead */
typedef int (*curl_seek_callback)(void *instream,
                                  curl_off_t offset,
                                  int origin); /* 'whence' */

/* This is a return code for the read callback that, when returned, will
   signal libcurl to immediately abort the current transfer. */
#define CURL_READFUNC_ABORT 0x10000000
/* This is a return code for the read callback that, when returned, will
   signal libcurl to pause sending data on the current transfer. */
#define CURL_READFUNC_PAUSE 0x10000001
typedef int (*curl_seek_callback)(void *instream,
                                  curl_off_t offset,
                                  int origin); /* 'whence' */

typedef size_t (*curl_read_callback)(char *buffer,
                                      size_t size,
+29 −27
Original line number Diff line number Diff line
@@ -1520,6 +1520,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
  struct FTP *ftp = conn->data->state.proto.ftp;
  struct SessionHandle *data = conn->data;
  struct ftp_conn *ftpc = &conn->proto.ftpc;
  int seekerr = CURL_SEEKFUNC_OK;

  if((data->state.resume_from && !sizechecked) ||
     ((data->state.resume_from > 0) && sizechecked)) {
@@ -1548,15 +1549,16 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,

    /* Let's read off the proper amount of bytes from the input. */
    if(conn->seek_func) {
      curl_off_t readthisamountnow = data->state.resume_from;
      seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
                                SEEK_SET);
    }

      if(conn->seek_func(conn->seek_client,
                         readthisamountnow, SEEK_SET) != 0) {
    if(seekerr != CURL_SEEKFUNC_OK) {
      if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
        failf(data, "Could not seek stream");
        return CURLE_FTP_COULDNT_USE_REST;
      }
    }

      /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
      else {
        curl_off_t passed=0;
        do {
@@ -1579,7 +1581,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
          }
        } while(passed < data->state.resume_from);
      }

    }
    /* now, decrease the size of the read */
    if(data->set.infilesize>0) {
      data->set.infilesize -= data->state.resume_from;
Loading