]> sjero.net Git - wget/commitdiff
[svn] Support human-readable file size printing.
authorhniksic <devnull@localhost>
Tue, 22 Mar 2005 13:20:02 +0000 (05:20 -0800)
committerhniksic <devnull@localhost>
Tue, 22 Mar 2005 13:20:02 +0000 (05:20 -0800)
Don't use persistent connection over proxies.

src/ChangeLog
src/ftp-ls.c
src/ftp.c
src/http.c
src/main.c
src/progress.c
src/sysdep.h
src/utils.c
src/utils.h

index 5160c55831b5654dfc0e96e81e4a10d90f676e02..d306c41b975bdade2a6977430c3925951b317ae2 100644 (file)
@@ -1,3 +1,21 @@
+2005-03-21  Hrvoje Niksic  <hniksic@xemacs.org>
+
+       * http.c (gethttp): Print the human-readable size.
+
+       * ftp.c (getftp): Print the human-readable size of the file to be
+       downloaded.
+
+       * utils.c (human_readable): New function.
+
+       * utils.c: Renamed "legible" to "with_thousand_seps",
+       "legible_large_int" to "with_thousand_seps_large", and "legible_1"
+       to "add_thousand_seps".
+
+2005-03-21  Hrvoje Niksic  <hniksic@xemacs.org>
+
+       * http.c (gethttp): Inhibit persistent connections when talking to
+       proxies, as mandated by RFC 2068.
+
 2005-03-20  Hrvoje Niksic  <hniksic@xemacs.org>
 
        * url.c (unescape_single_char): New function.
index 71d8e837138089fa928f5cf9ab41732802471364..913302502b7d8d187fde973c9b755bb0506a9f95 100644 (file)
@@ -939,7 +939,7 @@ ftp_index (const char *file, struct url *u, struct fileinfo *f)
        putc ('/', fp);
       fprintf (fp, "</a> ");
       if (f->type == FT_PLAINFILE)
-       fprintf (fp, _(" (%s bytes)"), legible (f->size));
+       fprintf (fp, _(" (%s bytes)"), with_thousand_seps (f->size));
       else if (f->type == FT_SYMLINK)
        fprintf (fp, "-> %s", f->linkto ? f->linkto : "(nil)");
       putc ('\n', fp);
index d2e031e731f8b3e863cbc25be01e978a0ba5663c..e138896c4dc4b40e83c2333bbbec871ba2b10a9e 100644 (file)
--- a/src/ftp.c
+++ b/src/ftp.c
@@ -220,6 +220,26 @@ ftp_do_port (int csock, int *local_sock)
 }
 #endif
 
+static void
+print_length (wgint size, wgint start, int authoritative)
+{
+  logprintf (LOG_VERBOSE, _("Length: %s"), with_thousand_seps (size));
+  if (size >= 1024)
+    logprintf (LOG_VERBOSE, " (%s)", human_readable (size));
+  if (start > 0)
+    {
+      if (start >= 1024)
+       logprintf (LOG_VERBOSE, _(", %s (%s) remaining"),
+                  with_thousand_seps (size - start),
+                  human_readable (size - start));
+      else
+       logprintf (LOG_VERBOSE, _(", %s remaining"),
+                  with_thousand_seps (size - start));
+    }
+  if (!authoritative)
+    logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
+}
+
 /* Retrieves a file with denoted parameters through opening an FTP
    connection to the server.  It always closes the data connection,
    and closes the control connection in case of error.  */
@@ -993,20 +1013,11 @@ Error in server response, closing control connection.\n"));
 
   if (*len)
     {
-      logprintf (LOG_VERBOSE, _("Length: %s"), legible (*len));
-      if (restval)
-       logprintf (LOG_VERBOSE, _(" [%s to go]"), legible (*len - restval));
-      logputs (LOG_VERBOSE, "\n");
+      print_length (*len, restval, 1);
       expected_bytes = *len;   /* for get_contents/show_progress */
     }
   else if (expected_bytes)
-    {
-      logprintf (LOG_VERBOSE, _("Length: %s"), legible (expected_bytes));
-      if (restval)
-       logprintf (LOG_VERBOSE, _(" [%s to go]"),
-                  legible (expected_bytes - restval));
-      logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
-    }
+    print_length (expected_bytes, restval, 0);
 
   /* Get the contents of the document.  */
   flags = 0;
index d66b28ff498af1317ae85101673da216ba73079f..85d73404a315cd3ca13336c22eb159ef628ac273 100644 (file)
@@ -1089,8 +1089,15 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
      is done. */
   int keep_alive;
 
-  /* Whether keep-alive should be inhibited. */
-  int inhibit_keep_alive = !opt.http_keep_alive || opt.ignore_length;
+  /* Whether keep-alive should be inhibited.
+
+     RFC 2068 requests that 1.0 clients not send keep-alive requests
+     to proxies.  This is because many 1.0 proxies do not interpret
+     the Connection header and transfer it to the remote server,
+     causing it to not close the connection and leave both the proxy
+     and the client hanging.  */
+  int inhibit_keep_alive =
+    !opt.http_keep_alive || opt.ignore_length /*|| proxy != NULL*/;
 
   /* Headers sent when using POST. */
   wgint post_data_size = 0;
@@ -1733,9 +1740,20 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
          logputs (LOG_VERBOSE, _("Length: "));
          if (contlen != -1)
            {
-             logputs (LOG_VERBOSE, legible (contlen + contrange));
+             logputs (LOG_VERBOSE, with_thousand_seps (contlen + contrange));
+             if (contlen + contrange >= 1024)
+               logprintf (LOG_VERBOSE, " (%s)",
+                          human_readable (contlen + contrange));
              if (contrange)
-               logprintf (LOG_VERBOSE, _(" (%s to go)"), legible (contlen));
+               {
+                 if (contlen >= 1024)
+                   logprintf (LOG_VERBOSE, _(", %s (%s) remaining"),
+                              with_thousand_seps (contlen),
+                              human_readable (contlen));
+                 else
+                   logprintf (LOG_VERBOSE, _(", %s remaining"),
+                              with_thousand_seps (contlen));
+               }
            }
          else
            logputs (LOG_VERBOSE,
index 432c7d4804a673fdc090fd572fc29ee193298eae..065d215af7b39a4d2c1a9a0a58c8fcc5eb4693c5 100644 (file)
@@ -943,13 +943,13 @@ Can't timestamp and not clobber old files at the same time.\n"));
     {
       logprintf (LOG_NOTQUIET,
                 _("\nFINISHED --%s--\nDownloaded: %s bytes in %d files\n"),
-                time_str (NULL), legible_large_int (total_downloaded_bytes),
+                time_str (NULL), with_thousand_seps_large (total_downloaded_bytes),
                 opt.numurls);
       /* Print quota warning, if exceeded.  */
       if (opt.quota && total_downloaded_bytes > opt.quota)
        logprintf (LOG_NOTQUIET,
                   _("Download quota (%s bytes) EXCEEDED!\n"),
-                  legible (opt.quota));
+                  with_thousand_seps_large (opt.quota));
     }
 
   if (opt.cookies_output)
index 3da69852d3267ab2895a4d2ae3f4b9d27920ee19..2c6b5820782764f2d80883b8a0e73602ba9feaed 100644 (file)
@@ -721,7 +721,7 @@ create_image (struct bar_progress *bp, double dl_total_time)
   char *p = bp->buffer;
   wgint size = bp->initial_length + bp->count;
 
-  char *size_legible = legible (size);
+  char *size_legible = with_thousand_seps (size);
   int size_legible_len = strlen (size_legible);
 
   struct bar_progress_hist *hist = &bp->hist;
@@ -828,7 +828,7 @@ create_image (struct bar_progress *bp, double dl_total_time)
     }
 
   /* " 234,567,890" */
-  sprintf (p, " %-11s", legible (size));
+  sprintf (p, " %-11s", with_thousand_seps (size));
   p += strlen (p);
 
   /* " 1012.45K/s" */
index 2aaa757df485aa49c5b559018be8217bba60f7de..e93f257e78d9bb548c106505764bd9f1bce72fb3 100644 (file)
@@ -111,7 +111,9 @@ so, delete this exception statement from your version.  */
 /* Define a large integral type useful for storing large sizes that
    exceed sizes of one download, such as when printing the sum of all
    downloads.  Note that this has nothing to do with large file
-   support, which determines the wgint type.
+   support, which determines the wgint type.  This should be as large
+   as possible even on systems where when wgint is 32-bit; also,
+   unlike wgint, this can be a floating point type.
 
    We use a 64-bit integral type where available, `double' otherwise.
    It's hard to print LARGE_INT's portably, but fortunately it's
index eace57c3431b64dcf10182c11c5c5df1e926aeb5..2e8524edd9bf9e17366e181003adda4dd8e38d21 100644 (file)
@@ -1226,11 +1226,11 @@ free_keys_and_values (struct hash_table *ht)
 }
 
 \f
-/* Engine for legible and legible_large_int; add thousand separators
-   to numbers printed in strings.  */
+/* Add thousand separators to a number already in string form.  Used
+   by with_thousand_seps and with_thousand_seps_large.  */
 
 static char *
-legible_1 (const char *repr)
+add_thousand_seps (const char *repr)
 {
   static char outbuf[48];
   int i, i1, mod;
@@ -1266,41 +1266,106 @@ legible_1 (const char *repr)
   return outbuf;
 }
 
-/* Legible -- return a static pointer to the legibly printed wgint.  */
+/* Return a static pointer to the number printed with thousand
+   separators inserted at the right places.  */
 
 char *
-legible (wgint l)
+with_thousand_seps (wgint l)
 {
   char inbuf[24];
   /* Print the number into the buffer.  */
   number_to_string (inbuf, l);
-  return legible_1 (inbuf);
+  return add_thousand_seps (inbuf);
 }
 
 /* Write a string representation of LARGE_INT NUMBER into the provided
-   buffer.  The buffer should be able to accept 24 characters,
-   including the terminating zero.
+   buffer.
 
    It would be dangerous to use sprintf, because the code wouldn't
    work on a machine with gcc-provided long long support, but without
-   libc support for "%lld".  However, such platforms will typically
-   not have snprintf and will use our version, which does support
-   "%lld" where long longs are available.  */
+   libc support for "%lld".  However, such old systems platforms
+   typically lack snprintf and will end up using our version, which
+   does support "%lld" whereever long longs are available.  */
 
 static void
-large_int_to_string (char *buffer, LARGE_INT number)
+large_int_to_string (char *buffer, int bufsize, LARGE_INT number)
 {
-  snprintf (buffer, 24, LARGE_INT_FMT, number);
+  snprintf (buffer, bufsize, LARGE_INT_FMT, number);
 }
 
-/* The same as legible(), but works on LARGE_INT.  */
+/* The same as with_thousand_seps, but works on LARGE_INT.  */
 
 char *
-legible_large_int (LARGE_INT l)
+with_thousand_seps_large (LARGE_INT l)
 {
   char inbuf[48];
-  large_int_to_string (inbuf, l);
-  return legible_1 (inbuf);
+  large_int_to_string (inbuf, sizeof (inbuf), l);
+  return add_thousand_seps (inbuf);
+}
+
+/* N, a byte quantity, is converted to a human-readable abberviated
+   form a la sizes printed by `ls -lh'.  The result is written to a
+   static buffer, a pointer to which is returned.
+
+   Unlike `with_thousand_seps', this approximates to the nearest unit.
+   Quoting GNU libit: "Most people visually process strings of 3-4
+   digits effectively, but longer strings of digits are more prone to
+   misinterpretation.  Hence, converting to an abbreviated form
+   usually improves readability."
+
+   This intentionally uses kilobyte (KB), megabyte (MB), etc. in their
+   original computer science meaning of "multiples of 1024".
+   Multiples of 1000 would be useless since Wget already adds thousand
+   separators for legibility.  We don't use the "*bibyte" names
+   invented in 1998, and seldom used in practice.  Wikipedia's entry
+   on kilobyte discusses this in some detail.  */
+
+char *
+human_readable (wgint n)
+{
+  /* These suffixes are compatible with those of GNU `ls -lh'. */
+  static char powers[] =
+    {
+      'K',                     /* kilobyte, 2^10 bytes */
+      'M',                     /* megabyte, 2^20 bytes */
+      'G',                     /* gigabyte, 2^30 bytes */
+      'T',                     /* terabyte, 2^40 bytes */
+      'P',                     /* petabyte, 2^50 bytes */
+      'E',                     /* exabyte,  2^60 bytes */
+    };
+  static char buf[8];
+  int i;
+
+  /* If the quantity is smaller than 1K, just print it. */
+  if (n < 1024)
+    {
+      snprintf (buf, sizeof (buf), "%d", (int) n);
+      return buf;
+    }
+
+  /* Loop over powers, dividing N with 1024 in each iteration.  This
+     works unchanged for all sizes of wgint, while still avoiding
+     non-portable `long double' arithmetic.  */
+  for (i = 0; i < countof (powers); i++)
+    {
+      /* At each iteration N is greater than the *subsequent* power.
+        That way N/1024.0 produces a decimal number in the units of
+        *this* power.  */
+      if ((n >> 10) < 1024 || i == countof (powers) - 1)
+       {
+         /* Must cast to long first because MS VC can't directly cast
+            __int64 to double.  (This is safe because N is known to
+            be <2**20.)  */
+         double val = (double) (long) n / 1024.0;
+         /* Print values smaller than 10 with one decimal digits, and
+            others without any decimals.  */
+         snprintf (buf, sizeof (buf), "%.*f%c",
+                   val < 10 ? 1 : 0, val, powers[i]);
+         return buf;
+       }
+      n >>= 10;
+    }
+  return NULL;                 /* unreached */
 }
 
 /* Count the digits in an integer number.  */
index 1b3da62831c1cadf095599164ab85cdf7ef9eadc..5845f80ffe47aee43d24017d775dfc49a8c3e8a2 100644 (file)
@@ -112,8 +112,9 @@ int string_set_contains PARAMS ((struct hash_table *, const char *));
 void string_set_free PARAMS ((struct hash_table *));
 void free_keys_and_values PARAMS ((struct hash_table *));
 
-char *legible PARAMS ((wgint));
-char *legible_large_int PARAMS ((LARGE_INT));
+char *with_thousand_seps PARAMS ((wgint));
+char *with_thousand_seps_large PARAMS ((LARGE_INT));
+char *human_readable PARAMS ((wgint));
 int numdigit PARAMS ((wgint));
 char *number_to_string PARAMS ((char *, wgint));
 char *number_to_static_string PARAMS ((wgint));