[svn] Support human-readable file size printing.

Don't use persistent connection over proxies.
This commit is contained in:
hniksic 2005-03-22 05:20:02 -08:00
parent 7c044778bc
commit b9a31d78dd
9 changed files with 155 additions and 40 deletions

View 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.

View 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);

View File

@ -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;

View 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,

View 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)

View 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" */

View 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

View File

@ -1226,11 +1226,11 @@ free_keys_and_values (struct hash_table *ht)
}
/* 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. */

View 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));