]> sjero.net Git - wget/blobdiff - src/retr.c
[svn] Declare the pointers to literal strings as `const'.
[wget] / src / retr.c
index c395939688fcb974d73ba447ca0353b54d892b86..1aae6e23702c77f0103e8d6a294f9078fe60f796 100644 (file)
@@ -63,12 +63,16 @@ so, delete this exception statement from your version.  */
 extern int errno;
 #endif
 
-/* See the comment in gethttp() why this is needed. */
-int global_download_count;
-
 /* Total size of downloaded files.  Used to enforce quota.  */
 LARGE_INT total_downloaded_bytes;
 
+/* If non-NULL, the stream to which output should be written.  This
+   stream is initialized when `-O' is used.  */
+FILE *output_stream;
+
+/* Whether output_document is a regular file we can manipulate,
+   i.e. not `-' or a device file. */
+int output_stream_regular;
 \f
 static struct {
   long chunk_bytes;
@@ -133,27 +137,63 @@ limit_bandwidth (long bytes, struct wget_timer *timer)
 # define MIN(i, j) ((i) <= (j) ? (i) : (j))
 #endif
 
+/* Write data in BUF to OUT.  However, if *SKIP is non-zero, skip that
+   amount of data and decrease SKIP.  Increment *TOTAL by the amount
+   of data written.  */
+
+static int
+write_data (FILE *out, const char *buf, int bufsize, long *skip,
+           long *written)
+{
+  if (!out)
+    return 1;
+  if (*skip > bufsize)
+    {
+      *skip -= bufsize;
+      return 1;
+    }
+  if (*skip)
+    {
+      buf += *skip;
+      bufsize -= *skip;
+      *skip = 0;
+      if (bufsize == 0)
+       return 1;
+    }
+
+  fwrite (buf, 1, bufsize, out);
+  *written += bufsize;
+
+  /* Immediately flush the downloaded data.  This should not hinder
+     performance: fast downloads will arrive in large 16K chunks
+     (which stdio would write out immediately anyway), and slow
+     downloads wouldn't be limited by disk speed.  */
+  fflush (out);
+  return !ferror (out);
+}
+
 /* Read the contents of file descriptor FD until it the connection
    terminates or a read error occurs.  The data is read in portions of
    up to 16K and written to OUT as it arrives.  If opt.verbose is set,
    the progress is shown.
 
    TOREAD is the amount of data expected to arrive, normally only used
-   by the progress gauge.  However, if EXACT is set, no more than
-   TOREAD octets will be read.
+   by the progress gauge.
 
    STARTPOS is the position from which the download starts, used by
-   the progress gauge.  The amount of data read gets stored to
-   *AMOUNT_READ.  The time it took to download the data (in
-   milliseconds) is stored to *ELAPSED.
+   the progress gauge.  If QTYREAD is non-NULL, the value it points to
+   is incremented by the amount of data read from the network.  If
+   QTYWRITTEN is non-NULL, the value it points to is incremented by
+   the amount of data written to disk.  The time it took to download
+   the data (in milliseconds) is stored to ELAPSED.
 
    The function exits and returns the amount of data read.  In case of
    error while reading data, -1 is returned.  In case of error while
    writing data, -2 is returned.  */
 
 int
-fd_read_body (int fd, FILE *out, long toread, int exact, long startpos,
-             long *amount_read, double *elapsed)
+fd_read_body (int fd, FILE *out, long toread, long startpos,
+             long *qtyread, long *qtywritten, double *elapsed, int flags)
 {
   int ret = 0;
 
@@ -172,11 +212,22 @@ fd_read_body (int fd, FILE *out, long toread, int exact, long startpos,
      data arrives slowly. */
   int progress_interactive = 0;
 
-  *amount_read = 0;
+  int exact = flags & rb_read_exactly;
+  long skip = 0;
+
+  /* How much data we've read/written.  */
+  long sum_read = 0;
+  long sum_written = 0;
+
+  if (flags & rb_skip_startpos)
+    skip = startpos;
 
   if (opt.verbose)
     {
-      progress = progress_create (startpos, toread);
+      /* If we're skipping STARTPOS bytes, pass 0 as the INITIAL
+        argument to progress_create because the indicator doesn't
+        (yet) know about "skipping" data.  */
+      progress = progress_create (skip ? 0 : startpos, startpos + toread);
       progress_interactive = progress_interactive_p (progress);
     }
 
@@ -203,36 +254,39 @@ fd_read_body (int fd, FILE *out, long toread, int exact, long startpos,
      means that it is unknown how much data is to arrive.  However, if
      EXACT is set, then toread==0 means what it says: that no data
      should be read.  */
-  while (!exact || (*amount_read < toread))
+  while (!exact || (sum_read < toread))
     {
-      int rdsize = exact ? MIN (toread - *amount_read, dlbufsize) : dlbufsize;
+      int rdsize = exact ? MIN (toread - sum_read, dlbufsize) : dlbufsize;
       double tmout = opt.read_timeout;
       if (progress_interactive)
        {
-         double waittm;
          /* For interactive progress gauges, always specify a ~1s
             timeout, so that the gauge can be updated regularly even
             when the data arrives very slowly or stalls.  */
          tmout = 0.95;
-         waittm = (wtimer_read (timer) - last_successful_read_tm) / 1000;
-         if (waittm + tmout > opt.read_timeout)
+         if (opt.read_timeout)
            {
-             /* Don't allow waiting time to exceed read timeout. */
-             tmout = opt.read_timeout - waittm;
-             if (tmout < 0)
+             double waittm;
+             waittm = (wtimer_read (timer) - last_successful_read_tm) / 1000;
+             if (waittm + tmout > opt.read_timeout)
                {
-                 /* We've already exceeded the timeout. */
-                 ret = -1, errno = ETIMEDOUT;
-                 break;
+                 /* Don't let total idle time exceed read timeout. */
+                 tmout = opt.read_timeout - waittm;
+                 if (tmout < 0)
+                   {
+                     /* We've already exceeded the timeout. */
+                     ret = -1, errno = ETIMEDOUT;
+                     break;
+                   }
                }
            }
        }
       ret = fd_read (fd, dlbuf, rdsize, tmout);
 
       if (ret == 0 || (ret < 0 && errno != ETIMEDOUT))
-       break;
+       break;                  /* read error */
       else if (ret < 0)
-       ret = 0;                /* timeout */
+       ret = 0;                /* read timeout */
 
       if (progress || opt.limit_rate)
        {
@@ -241,15 +295,10 @@ fd_read_body (int fd, FILE *out, long toread, int exact, long startpos,
            last_successful_read_tm = wtimer_read (timer);
        }
 
-      if (ret > 0 && out != NULL)
+      if (ret > 0)
        {
-         fwrite (dlbuf, 1, ret, out);
-         /* Immediately flush the downloaded data.  This should not
-            hinder performance: fast downloads will arrive in large
-            16K chunks (which stdio would write out anyway), and slow
-            downloads wouldn't be limited by disk speed.  */
-         fflush (out);
-         if (ferror (out))
+         sum_read += ret;
+         if (!write_data (out, dlbuf, ret, &skip, &sum_written))
            {
              ret = -2;
              goto out;
@@ -259,13 +308,12 @@ fd_read_body (int fd, FILE *out, long toread, int exact, long startpos,
       if (opt.limit_rate)
        limit_bandwidth (ret, timer);
 
-      *amount_read += ret;
       if (progress)
        progress_update (progress, ret, wtimer_read (timer));
 #ifdef WINDOWS
       if (toread > 0)
        ws_percenttitle (100.0 *
-                        (startpos + *amount_read) / (startpos + toread));
+                        (startpos + sum_read) / (startpos + toread));
 #endif
     }
   if (ret < -1)
@@ -274,11 +322,17 @@ fd_read_body (int fd, FILE *out, long toread, int exact, long startpos,
  out:
   if (progress)
     progress_finish (progress, wtimer_read (timer));
+
   if (elapsed)
     *elapsed = wtimer_read (timer);
   if (timer)
     wtimer_delete (timer);
 
+  if (qtyread)
+    *qtyread += sum_read;
+  if (qtywritten)
+    *qtywritten += sum_written;
+
   return ret;
 }
 \f
@@ -431,7 +485,7 @@ char *
 retr_rate (long bytes, double msecs, int pad)
 {
   static char res[20];
-  static char *rate_names[] = {"B/s", "KB/s", "MB/s", "GB/s" };
+  static const char *rate_names[] = {"B/s", "KB/s", "MB/s", "GB/s" };
   int units = 0;
 
   double dlrate = calc_rate (bytes, msecs, &units);
@@ -713,7 +767,6 @@ retrieve_url (const char *origurl, char **file, char **newloc,
       xfree (url);
     }
 
-  ++global_download_count;
   RESTORE_POST_DATA;
 
   return result;