--- curl-7.15.3/lib/file.c 2006-01-09 14:09:40 +0100 +++ curl-7.15.3-modified/lib/file.c 2007-12-28 18:27:56 +0100 @@ -76,6 +76,7 @@ #endif +#include "strtoofft.h" #include "urldata.h" #include #include "progress.h" @@ -260,6 +261,58 @@ } /* + 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; + + if(conn->bits.use_range && conn->range) { + from=curlx_strtoofft(conn->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 - */ + conn->resume_from = from; + DEBUGF(infof(conn->data, "RANGE %" FORMAT_OFF_T " to end of file\n", + from)); + } + else if(from < 0) { + /* -Y */ + totalsize = -from; + conn->maxdownload = -from; + conn->resume_from = from; + DEBUGF(infof(conn->data, "RANGE the last %" FORMAT_OFF_T " bytes\n", + totalsize)); + } + else { + /* X-Y */ + totalsize = to-from; + conn->maxdownload = totalsize+1; /* include the last mentioned byte */ + conn->resume_from = from; + DEBUGF(infof(conn->data, "RANGE from %" FORMAT_OFF_T + " getting %" FORMAT_OFF_T " bytes\n", + from, conn->maxdownload)); + } + DEBUGF(infof(conn->data, "range-download from %" FORMAT_OFF_T + " to %" FORMAT_OFF_T ", totally %" FORMAT_OFF_T " bytes\n", + from, to, conn->maxdownload)); + } + return CURLE_OK; +} + +/* * Curl_file() is the protocol-specific function for the do-phase, separated * from the connect-phase above. Other protocols merely setup the transfer in * the do-phase, to have it done in the main transfer loop but since some @@ -346,6 +399,9 @@ return result; } + /* Check whether file range has been specified */ + file_range (conn); + if (conn->resume_from <= expected_size) expected_size -= conn->resume_from; else { @@ -353,6 +409,10 @@ return CURLE_BAD_DOWNLOAD_RESUME; } + /* A high water mark has been specified so we obey... */ + if (conn->maxdownload > 0) + expected_size = conn->maxdownload; + if (fstated && (expected_size == 0)) return CURLE_OK; @@ -369,15 +429,20 @@ Curl_pgrsTime(data, TIMER_STARTTRANSFER); while (res == CURLE_OK) { - nread = read(fd, buf, BUFSIZE-1); + /* Don't full a whole buffer if we want need 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(data, CLIENTWRITE_BODY, buf, nread); if(res)