]> sjero.net Git - wget/blobdiff - src/retr.c
[svn] Display smaller download rate numbers with more digits of precision.
[wget] / src / retr.c
index 0285a57a90c2b12f503d6e08bb285ccf8e232fe6..60106efaa1b11717bced71301d3a81aba76579ef 100644 (file)
@@ -45,6 +45,7 @@ so, delete this exception statement from your version.  */
 #include "url.h"
 #include "recur.h"
 #include "ftp.h"
+#include "http.h"
 #include "host.h"
 #include "connect.h"
 #include "hash.h"
@@ -54,6 +55,9 @@ so, delete this exception statement from your version.  */
 /* Total size of downloaded files.  Used to enforce quota.  */
 SUM_SIZE_INT total_downloaded_bytes;
 
+/* Total download time in milliseconds. */
+double total_download_time;
+
 /* If non-NULL, the stream to which output should be written.  This
    stream is initialized when `-O' is used.  */
 FILE *output_stream;
@@ -332,22 +336,35 @@ fd_read_body (int fd, FILE *out, wgint toread, wgint startpos,
   return ret;
 }
 \f
-/* Read a hunk of data from FD, up until a terminator.  The terminator
-   is whatever the TERMINATOR function determines it to be; for
-   example, it can be a line of data, or the head of an HTTP response.
-   The function returns the data read allocated with malloc.
-
-   In case of error, NULL is returned.  In case of EOF and no data
-   read, NULL is returned and errno set to 0.  In case of EOF with
-   data having been read, the data is returned, but it will
-   (obviously) not contain the terminator.
+/* Read a hunk of data from FD, up until a terminator.  The hunk is
+   limited by whatever the TERMINATOR callback chooses as its
+   terminator.  For example, if terminator stops at newline, the hunk
+   will consist of a line of data; if terminator stops at two
+   newlines, it can be used to read the head of an HTTP response.
+   Upon determining the boundary, the function returns the data (up to
+   the terminator) in malloc-allocated storage.
+
+   In case of read error, NULL is returned.  In case of EOF and no
+   data read, NULL is returned and errno set to 0.  In case of having
+   read some data, but encountering EOF before seeing the terminator,
+   the data that has been read is returned, but it will (obviously)
+   not contain the terminator.
+
+   The TERMINATOR function is called with three arguments: the
+   beginning of the data read so far, the beginning of the current
+   block of peeked-at data, and the length of the current block.
+   Depending on its needs, the function is free to choose whether to
+   analyze all data or just the newly arrived data.  If TERMINATOR
+   returns NULL, it means that the terminator has not been seen.
+   Otherwise it should return a pointer to the charactre immediately
+   following the terminator.
 
    The idea is to be able to read a line of input, or otherwise a hunk
    of text, such as the head of an HTTP request, without crossing the
    boundary, so that the next call to fd_read etc. reads the data
    after the hunk.  To achieve that, this function does the following:
 
-   1. Peek at available data.
+   1. Peek at incoming data.
 
    2. Determine whether the peeked data, along with the previously
       read data, includes the terminator.
@@ -392,12 +409,13 @@ fd_read_hunk (int fd, hunk_terminator_t terminator, long sizehint, long maxsize)
          xfree (hunk);
          return NULL;
        }
-      end = terminator (hunk, tail, pklen);
+      end = terminator (hunk, hunk + tail, pklen);
       if (end)
        {
          /* The data contains the terminator: we'll drain the data up
             to the end of the terminator.  */
          remain = end - (hunk + tail);
+         assert (remain >= 0);
          if (remain == 0)
            {
              /* No more data needs to be read. */
@@ -467,11 +485,11 @@ fd_read_hunk (int fd, hunk_terminator_t terminator, long sizehint, long maxsize)
 }
 
 static const char *
-line_terminator (const char *hunk, int oldlen, int peeklen)
+line_terminator (const char *start, const char *peeked, int peeklen)
 {
-  const char *p = memchr (hunk + oldlen, '\n', peeklen);
+  const char *p = memchr (peeked, '\n', peeklen);
   if (p)
-    /* p+1 because we want the line to include '\n' */
+    /* p+1 because the line must include '\n' */
     return p + 1;
   return NULL;
 }
@@ -495,18 +513,22 @@ fd_read_line (int fd)
   return fd_read_hunk (fd, line_terminator, 128, FD_READ_LINE_MAX);
 }
 \f
-/* Return a printed representation of the download rate, as
-   appropriate for the speed.  If PAD is true, strings will be padded
-   to the width of 7 characters (xxxx.xx).  */
-char *
-retr_rate (wgint bytes, double msecs, bool pad)
+/* Return a printed representation of the download rate, along with
+   the units appropriate for the download speed.  */
+
+const char *
+retr_rate (wgint bytes, double msecs)
 {
   static char res[20];
   static const char *rate_names[] = {"B/s", "KB/s", "MB/s", "GB/s" };
-  int units = 0;
+  int units;
 
   double dlrate = calc_rate (bytes, msecs, &units);
-  sprintf (res, pad ? "%7.2f %s" : "%.2f %s", dlrate, rate_names[units]);
+  /* Use more digits for smaller numbers (regardless of unit used),
+     e.g. "1022", "247", "12.5", "2.38".  */
+  sprintf (res, "%.*f %s",
+          dlrate >= 99.95 ? 0 : dlrate >= 9.995 ? 1 : 2,
+          dlrate, rate_names[units]);
 
   return res;
 }
@@ -660,14 +682,16 @@ retrieve_url (const char *origurl, char **file, char **newloc,
     }
   else if (u->scheme == SCHEME_FTP)
     {
-      /* If this is a redirection, we must not allow recursive FTP
-        retrieval, so we save recursion to oldrec, and restore it
-        later.  */
-      bool oldrec = opt.recursive;
+      /* If this is a redirection, temporarily turn off opt.ftp_glob
+        and opt.recursive, both being undesirable when following
+        redirects.  */
+      bool oldrec = opt.recursive, oldglob = opt.ftp_glob;
       if (redirection_count)
-       opt.recursive = false;
+       opt.recursive = opt.ftp_glob = false;
+
       result = ftp_loop (u, dt, proxy_url);
       opt.recursive = oldrec;
+      opt.ftp_glob = oldglob;
 
       /* There is a possibility of having HTTP being redirected to
         FTP.  In these cases we must decide whether the text is HTML