X-Git-Url: http://sjero.net/git/?p=wget;a=blobdiff_plain;f=src%2Futils.c;h=dc16d55afc5940d095b9ada5d33f4d6d77deb809;hp=e5098be38a5cbc4780d0381068adb873973b27eb;hb=2219d47ba301c3ea47b36291dda8eabead0fc75d;hpb=c36e9a5272e8ec394625dfa0f63bf9c1722eeaef diff --git a/src/utils.c b/src/utils.c index e5098be3..dc16d55a 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,5 +1,5 @@ /* Various utility functions. - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2005 Free Software Foundation, Inc. This file is part of GNU Wget. @@ -120,19 +120,6 @@ xstrdup_lower (const char *s) return copy; } -/* Return a count of how many times CHR occurs in STRING. */ - -int -count_char (const char *string, char chr) -{ - const char *p; - int count = 0; - for (p = string; *p; p++) - if (*p == chr) - ++count; - return count; -} - /* Copy the string formed by two pointers (one on the beginning, other on the char after the last char) to a new, malloc-ed location. 0-terminate it. */ @@ -571,6 +558,14 @@ fopen_excl (const char *fname, int binary) return NULL; return fdopen (fd, binary ? "wb" : "w"); #else /* not O_EXCL */ + /* Manually check whether the file exists. This is prone to race + conditions, but systems without O_EXCL haven't deserved + better. */ + if (file_exists_p (fname)) + { + errno = EEXIST; + return NULL; + } return fopen (fname, binary ? "wb" : "w"); #endif /* not O_EXCL */ } @@ -1085,91 +1080,6 @@ merge_vecs (char **v1, char **v2) xfree (v2); return v1; } - -/* A set of simple-minded routines to store strings in a linked list. - This used to also be used for searching, but now we have hash - tables for that. */ - -/* It's a shame that these simple things like linked lists and hash - tables (see hash.c) need to be implemented over and over again. It - would be nice to be able to use the routines from glib -- see - www.gtk.org for details. However, that would make Wget depend on - glib, and I want to avoid dependencies to external libraries for - reasons of convenience and portability (I suspect Wget is more - portable than anything ever written for Gnome). */ - -/* Append an element to the list. If the list has a huge number of - elements, this can get slow because it has to find the list's - ending. If you think you have to call slist_append in a loop, - think about calling slist_prepend() followed by slist_nreverse(). */ - -slist * -slist_append (slist *l, const char *s) -{ - slist *newel = xnew (slist); - slist *beg = l; - - newel->string = xstrdup (s); - newel->next = NULL; - - if (!l) - return newel; - /* Find the last element. */ - while (l->next) - l = l->next; - l->next = newel; - return beg; -} - -/* Prepend S to the list. Unlike slist_append(), this is O(1). */ - -slist * -slist_prepend (slist *l, const char *s) -{ - slist *newel = xnew (slist); - newel->string = xstrdup (s); - newel->next = l; - return newel; -} - -/* Destructively reverse L. */ - -slist * -slist_nreverse (slist *l) -{ - slist *prev = NULL; - while (l) - { - slist *next = l->next; - l->next = prev; - prev = l; - l = next; - } - return prev; -} - -/* Is there a specific entry in the list? */ -int -slist_contains (slist *l, const char *s) -{ - for (; l; l = l->next) - if (!strcmp (l->string, s)) - return 1; - return 0; -} - -/* Free the whole slist. */ -void -slist_free (slist *l) -{ - while (l) - { - slist *n = l->next; - xfree (l->string); - xfree (l); - l = n; - } -} /* Sometimes it's useful to create "sets" of strings, i.e. special hash tables where you want to store strings as keys and merely @@ -1200,6 +1110,22 @@ string_set_contains (struct hash_table *ht, const char *s) return hash_table_contains (ht, s); } +static int +string_set_to_array_mapper (void *key, void *value_ignored, void *arg) +{ + char ***arrayptr = (char ***) arg; + *(*arrayptr)++ = (char *) key; + return 0; +} + +/* Convert the specified string set to array. ARRAY should be large + enough to hold hash_table_count(ht) char pointers. */ + +void string_set_to_array (struct hash_table *ht, char **array) +{ + hash_table_map (ht, string_set_to_array_mapper, &array); +} + static int string_set_free_mapper (void *key, void *value_ignored, void *arg_ignored) { @@ -1231,11 +1157,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; @@ -1271,145 +1197,176 @@ 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); } -/* Count the digits in an integer number. */ +/* 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 the provided number. Used to allocate space + when printing numbers. */ + int numdigit (wgint number) { int cnt = 1; if (number < 0) - { - number = -number; - ++cnt; - } - while ((number /= 10) > 0) + ++cnt; /* accomodate '-' */ + while ((number /= 10) != 0) ++cnt; return cnt; } -#define ONE_DIGIT(figure) *p++ = n / (figure) + '0' -#define ONE_DIGIT_ADVANCE(figure) (ONE_DIGIT (figure), n %= (figure)) - -#define DIGITS_1(figure) ONE_DIGIT (figure) -#define DIGITS_2(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_1 ((figure) / 10) -#define DIGITS_3(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_2 ((figure) / 10) -#define DIGITS_4(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_3 ((figure) / 10) -#define DIGITS_5(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_4 ((figure) / 10) -#define DIGITS_6(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_5 ((figure) / 10) -#define DIGITS_7(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_6 ((figure) / 10) -#define DIGITS_8(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_7 ((figure) / 10) -#define DIGITS_9(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_8 ((figure) / 10) -#define DIGITS_10(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_9 ((figure) / 10) - -/* DIGITS_<11-20> are only used on machines with 64-bit numbers. */ - -#define DIGITS_11(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_10 ((figure) / 10) -#define DIGITS_12(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_11 ((figure) / 10) -#define DIGITS_13(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_12 ((figure) / 10) -#define DIGITS_14(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_13 ((figure) / 10) -#define DIGITS_15(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_14 ((figure) / 10) -#define DIGITS_16(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_15 ((figure) / 10) -#define DIGITS_17(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_16 ((figure) / 10) -#define DIGITS_18(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_17 ((figure) / 10) -#define DIGITS_19(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_18 ((figure) / 10) - -/* It is annoying that we have three different syntaxes for 64-bit constants: - - nnnL for 64-bit systems, where they are of type long; - - nnnLL for 32-bit systems that support long long; - - nnnI64 for MS compiler on Windows, which doesn't support long long. */ - -#if SIZEOF_LONG > 4 -/* If long is large enough, use long constants. */ -# define C10000000000 10000000000L -# define C100000000000 100000000000L -# define C1000000000000 1000000000000L -# define C10000000000000 10000000000000L -# define C100000000000000 100000000000000L -# define C1000000000000000 1000000000000000L -# define C10000000000000000 10000000000000000L -# define C100000000000000000 100000000000000000L -# define C1000000000000000000 1000000000000000000L -#else -# if SIZEOF_LONG_LONG != 0 -/* Otherwise, if long long is available, use long long constants. */ -# define C10000000000 10000000000LL -# define C100000000000 100000000000LL -# define C1000000000000 1000000000000LL -# define C10000000000000 10000000000000LL -# define C100000000000000 100000000000000LL -# define C1000000000000000 1000000000000000LL -# define C10000000000000000 10000000000000000LL -# define C100000000000000000 100000000000000000LL -# define C1000000000000000000 1000000000000000000LL -# else -# if defined(WINDOWS) -/* Use __int64 constants under Windows. */ -# define C10000000000 10000000000I64 -# define C100000000000 100000000000I64 -# define C1000000000000 1000000000000I64 -# define C10000000000000 10000000000000I64 -# define C100000000000000 100000000000000I64 -# define C1000000000000000 1000000000000000I64 -# define C10000000000000000 10000000000000000I64 -# define C100000000000000000 100000000000000000I64 -# define C1000000000000000000 1000000000000000000I64 -# endif -# endif -#endif +#define PR(mask) *p++ = n / (mask) + '0' + +/* DIGITS_ is used to print a D-digit number and should be called + with mask==10^(D-1). It prints n/mask (the first digit), reducing + n to n%mask (the remaining digits), and calling DIGITS_. + Recursively this continues until DIGITS_1 is invoked. */ + +#define DIGITS_1(mask) PR (mask) +#define DIGITS_2(mask) PR (mask), n %= (mask), DIGITS_1 ((mask) / 10) +#define DIGITS_3(mask) PR (mask), n %= (mask), DIGITS_2 ((mask) / 10) +#define DIGITS_4(mask) PR (mask), n %= (mask), DIGITS_3 ((mask) / 10) +#define DIGITS_5(mask) PR (mask), n %= (mask), DIGITS_4 ((mask) / 10) +#define DIGITS_6(mask) PR (mask), n %= (mask), DIGITS_5 ((mask) / 10) +#define DIGITS_7(mask) PR (mask), n %= (mask), DIGITS_6 ((mask) / 10) +#define DIGITS_8(mask) PR (mask), n %= (mask), DIGITS_7 ((mask) / 10) +#define DIGITS_9(mask) PR (mask), n %= (mask), DIGITS_8 ((mask) / 10) +#define DIGITS_10(mask) PR (mask), n %= (mask), DIGITS_9 ((mask) / 10) + +/* DIGITS_<11-20> are only used on machines with 64-bit wgints. */ + +#define DIGITS_11(mask) PR (mask), n %= (mask), DIGITS_10 ((mask) / 10) +#define DIGITS_12(mask) PR (mask), n %= (mask), DIGITS_11 ((mask) / 10) +#define DIGITS_13(mask) PR (mask), n %= (mask), DIGITS_12 ((mask) / 10) +#define DIGITS_14(mask) PR (mask), n %= (mask), DIGITS_13 ((mask) / 10) +#define DIGITS_15(mask) PR (mask), n %= (mask), DIGITS_14 ((mask) / 10) +#define DIGITS_16(mask) PR (mask), n %= (mask), DIGITS_15 ((mask) / 10) +#define DIGITS_17(mask) PR (mask), n %= (mask), DIGITS_16 ((mask) / 10) +#define DIGITS_18(mask) PR (mask), n %= (mask), DIGITS_17 ((mask) / 10) +#define DIGITS_19(mask) PR (mask), n %= (mask), DIGITS_18 ((mask) / 10) /* SPRINTF_WGINT is used by number_to_string to handle pathological - cases and to portably support strange sizes of wgint. */ + cases and to portably support strange sizes of wgint. Ideally this + would just use "%j" and intmax_t, but many systems don't support + it, so it's used only if nothing else works. */ #if SIZEOF_LONG >= SIZEOF_WGINT -# define SPRINTF_WGINT(buf, n) sprintf(buf, "%ld", (long) (n)) +# define SPRINTF_WGINT(buf, n) sprintf (buf, "%ld", (long) (n)) #else # if SIZEOF_LONG_LONG >= SIZEOF_WGINT -# define SPRINTF_WGINT(buf, n) sprintf(buf, "%lld", (long long) (n)) +# define SPRINTF_WGINT(buf, n) sprintf (buf, "%lld", (long long) (n)) # else # ifdef WINDOWS -# define SPRINTF_WGINT(buf, n) sprintf(buf, "%I64", (__int64) (n)) +# define SPRINTF_WGINT(buf, n) sprintf (buf, "%I64", (__int64) (n)) +# else +# define SPRINTF_WGINT(buf, n) sprintf (buf, "%j", (intmax_t) (n)) # endif # endif #endif +/* Shorthand for casting to wgint. */ +#define W wgint + /* Print NUMBER to BUFFER in base 10. This is equivalent to - `sprintf(buffer, "%lld", (long long) number)', only much faster and - portable to machines without long long. + `sprintf(buffer, "%lld", (long long) number)', only typically much + faster and portable to machines without long long. The speedup may make a difference in programs that frequently convert numbers to strings. Some implementations of sprintf, @@ -1443,8 +1400,7 @@ number_to_string (char *buffer, wgint number) { if (n < -WGINT_MAX) { - /* We cannot print a '-' and assign -n to n because -n would - overflow. Let sprintf deal with this border case. */ + /* -n would overflow. Have sprintf deal with this. */ SPRINTF_WGINT (buffer, n); p += strlen (buffer); return p; @@ -1454,31 +1410,37 @@ number_to_string (char *buffer, wgint number) n = -n; } - if (n < 10) { DIGITS_1 (1); } - else if (n < 100) { DIGITS_2 (10); } - else if (n < 1000) { DIGITS_3 (100); } - else if (n < 10000) { DIGITS_4 (1000); } - else if (n < 100000) { DIGITS_5 (10000); } - else if (n < 1000000) { DIGITS_6 (100000); } - else if (n < 10000000) { DIGITS_7 (1000000); } - else if (n < 100000000) { DIGITS_8 (10000000); } - else if (n < 1000000000) { DIGITS_9 (100000000); } + /* Use the DIGITS_ macro appropriate for N's number of digits. That + way printing any N is fully open-coded without a loop or jump. + (Also see description of DIGITS_*.) */ + + if (n < 10) DIGITS_1 (1); + else if (n < 100) DIGITS_2 (10); + else if (n < 1000) DIGITS_3 (100); + else if (n < 10000) DIGITS_4 (1000); + else if (n < 100000) DIGITS_5 (10000); + else if (n < 1000000) DIGITS_6 (100000); + else if (n < 10000000) DIGITS_7 (1000000); + else if (n < 100000000) DIGITS_8 (10000000); + else if (n < 1000000000) DIGITS_9 (100000000); #if SIZEOF_WGINT == 4 - /* wgint is four bytes long: we're done. */ - /* ``if (1)'' serves only to preserve editor indentation. */ - else if (1) { DIGITS_10 (1000000000); } + /* wgint is 32 bits wide: no number has more than 10 digits. */ + else DIGITS_10 (1000000000); #else - /* wgint is 64 bits long -- make sure to process all the digits. */ - else if (n < C10000000000) { DIGITS_10 (1000000000); } - else if (n < C100000000000) { DIGITS_11 (C10000000000); } - else if (n < C1000000000000) { DIGITS_12 (C100000000000); } - else if (n < C10000000000000) { DIGITS_13 (C1000000000000); } - else if (n < C100000000000000) { DIGITS_14 (C10000000000000); } - else if (n < C1000000000000000) { DIGITS_15 (C100000000000000); } - else if (n < C10000000000000000) { DIGITS_16 (C1000000000000000); } - else if (n < C100000000000000000) { DIGITS_17 (C10000000000000000); } - else if (n < C1000000000000000000) { DIGITS_18 (C100000000000000000); } - else { DIGITS_19 (C1000000000000000000); } + /* wgint is 64 bits wide: handle numbers with more than 9 decimal + digits. Constants are constructed by compile-time multiplication + to avoid dealing with different notations for 64-bit constants + (nnnL, nnnLL, and nnnI64, depending on the compiler). */ + else if (n < 10*(W)1000000000) DIGITS_10 (1000000000); + else if (n < 100*(W)1000000000) DIGITS_11 (10*(W)1000000000); + else if (n < 1000*(W)1000000000) DIGITS_12 (100*(W)1000000000); + else if (n < 10000*(W)1000000000) DIGITS_13 (1000*(W)1000000000); + else if (n < 100000*(W)1000000000) DIGITS_14 (10000*(W)1000000000); + else if (n < 1000000*(W)1000000000) DIGITS_15 (100000*(W)1000000000); + else if (n < 10000000*(W)1000000000) DIGITS_16 (1000000*(W)1000000000); + else if (n < 100000000*(W)1000000000) DIGITS_17 (10000000*(W)1000000000); + else if (n < 1000000000*(W)1000000000) DIGITS_18 (100000000*(W)1000000000); + else DIGITS_19 (1000000000*(W)1000000000); #endif *p = '\0'; @@ -1487,9 +1449,8 @@ number_to_string (char *buffer, wgint number) return p; } -#undef ONE_DIGIT -#undef ONE_DIGIT_ADVANCE - +#undef PR +#undef W #undef DIGITS_1 #undef DIGITS_2 #undef DIGITS_3 @@ -1554,322 +1515,6 @@ number_to_static_string (wgint number) return buf; } -/* Support for timers. */ - -#undef TIMER_WINDOWS -#undef TIMER_GETTIMEOFDAY -#undef TIMER_TIME - -/* Depending on the OS and availability of gettimeofday(), one and - only one of the above constants will be defined. Virtually all - modern Unix systems will define TIMER_GETTIMEOFDAY; Windows will - use TIMER_WINDOWS. TIMER_TIME is a catch-all method for - non-Windows systems without gettimeofday. - - #### Perhaps we should also support ftime(), which exists on old - BSD 4.2-influenced systems? (It also existed under MS DOS Borland - C, if memory serves me.) */ - -#ifdef WINDOWS -# define TIMER_WINDOWS -#else /* not WINDOWS */ -# ifdef HAVE_GETTIMEOFDAY -# define TIMER_GETTIMEOFDAY -# else -# define TIMER_TIME -# endif -#endif /* not WINDOWS */ - -#ifdef TIMER_GETTIMEOFDAY -typedef struct timeval wget_sys_time; -#endif - -#ifdef TIMER_TIME -typedef time_t wget_sys_time; -#endif - -#ifdef TIMER_WINDOWS -typedef ULARGE_INTEGER wget_sys_time; -#endif - -struct wget_timer { - /* Whether the start time has been initialized. */ - int initialized; - - /* The starting point in time which, subtracted from the current - time, yields elapsed time. */ - wget_sys_time start; - - /* The most recent elapsed time, calculated by wtimer_elapsed(). - Measured in milliseconds. */ - double elapsed_last; - - /* Approximately, the time elapsed between the true start of the - measurement and the time represented by START. */ - double elapsed_pre_start; -}; - -/* Allocate a timer. Calling wtimer_read on the timer will return - zero. It is not legal to call wtimer_update with a freshly - allocated timer -- use wtimer_reset first. */ - -struct wget_timer * -wtimer_allocate (void) -{ - struct wget_timer *wt = xnew (struct wget_timer); - xzero (*wt); - return wt; -} - -/* Allocate a new timer and reset it. Return the new timer. */ - -struct wget_timer * -wtimer_new (void) -{ - struct wget_timer *wt = wtimer_allocate (); - wtimer_reset (wt); - return wt; -} - -/* Free the resources associated with the timer. Its further use is - prohibited. */ - -void -wtimer_delete (struct wget_timer *wt) -{ - xfree (wt); -} - -/* Store system time to WST. */ - -static void -wtimer_sys_set (wget_sys_time *wst) -{ -#ifdef TIMER_GETTIMEOFDAY - gettimeofday (wst, NULL); -#endif - -#ifdef TIMER_TIME - time (wst); -#endif - -#ifdef TIMER_WINDOWS - /* We use GetSystemTime to get the elapsed time. MSDN warns that - system clock adjustments can skew the output of GetSystemTime - when used as a timer and gives preference to GetTickCount and - high-resolution timers. But GetTickCount can overflow, and hires - timers are typically used for profiling, not for regular time - measurement. Since we handle clock skew anyway, we just use - GetSystemTime. */ - FILETIME ft; - SYSTEMTIME st; - GetSystemTime (&st); - - /* As recommended by MSDN, we convert SYSTEMTIME to FILETIME, copy - FILETIME to ULARGE_INTEGER, and use regular 64-bit integer - arithmetic on that. */ - SystemTimeToFileTime (&st, &ft); - wst->HighPart = ft.dwHighDateTime; - wst->LowPart = ft.dwLowDateTime; -#endif -} - -/* Reset timer WT. This establishes the starting point from which - wtimer_elapsed() will return the number of elapsed milliseconds. - It is allowed to reset a previously used timer. - - If a non-zero value is used as START, the timer's values will be - offset by START. */ - -void -wtimer_reset (struct wget_timer *wt) -{ - /* Set the start time to the current time. */ - wtimer_sys_set (&wt->start); - wt->elapsed_last = 0; - wt->elapsed_pre_start = 0; - wt->initialized = 1; -} - -static double -wtimer_sys_diff (wget_sys_time *wst1, wget_sys_time *wst2) -{ -#ifdef TIMER_GETTIMEOFDAY - return ((double)(wst1->tv_sec - wst2->tv_sec) * 1000 - + (double)(wst1->tv_usec - wst2->tv_usec) / 1000); -#endif - -#ifdef TIMER_TIME - return 1000 * (*wst1 - *wst2); -#endif - -#ifdef WINDOWS - /* VC++ 6 doesn't support direct cast of uint64 to double. To work - around this, we subtract, then convert to signed, then finally to - double. */ - return (double)(signed __int64)(wst1->QuadPart - wst2->QuadPart) / 10000; -#endif -} - -/* Update the timer's elapsed interval. This function causes the - timer to call gettimeofday (or time(), etc.) to update its idea of - current time. To get the elapsed interval in milliseconds, use - wtimer_read. - - This function handles clock skew, i.e. time that moves backwards is - ignored. */ - -void -wtimer_update (struct wget_timer *wt) -{ - wget_sys_time now; - double elapsed; - - assert (wt->initialized != 0); - - wtimer_sys_set (&now); - elapsed = wt->elapsed_pre_start + wtimer_sys_diff (&now, &wt->start); - - /* Ideally we'd just return the difference between NOW and - wt->start. However, the system timer can be set back, and we - could return a value smaller than when we were last called, even - a negative value. Both of these would confuse the callers, which - expect us to return monotonically nondecreasing values. - - Therefore: if ELAPSED is smaller than its previous known value, - we reset wt->start to the current time and effectively start - measuring from this point. But since we don't want the elapsed - value to start from zero, we set elapsed_pre_start to the last - elapsed time and increment all future calculations by that - amount. */ - - if (elapsed < wt->elapsed_last) - { - wt->start = now; - wt->elapsed_pre_start = wt->elapsed_last; - elapsed = wt->elapsed_last; - } - - wt->elapsed_last = elapsed; -} - -/* Return the elapsed time in milliseconds between the last call to - wtimer_reset and the last call to wtimer_update. - - A typical use of the timer interface would be: - - struct wtimer *timer = wtimer_new (); - ... do something that takes a while ... - wtimer_update (); - double msecs = wtimer_read (); */ - -double -wtimer_read (const struct wget_timer *wt) -{ - return wt->elapsed_last; -} - -/* Return the assessed granularity of the timer implementation, in - milliseconds. This is used by code that tries to substitute a - better value for timers that have returned zero. */ - -double -wtimer_granularity (void) -{ -#ifdef TIMER_GETTIMEOFDAY - /* Granularity of gettimeofday varies wildly between architectures. - However, it appears that on modern machines it tends to be better - than 1ms. Assume 100 usecs. (Perhaps the configure process - could actually measure this?) */ - return 0.1; -#endif - -#ifdef TIMER_TIME - return 1000; -#endif - -#ifdef TIMER_WINDOWS - /* According to MSDN, GetSystemTime returns a broken-down time - structure the smallest member of which are milliseconds. */ - return 1; -#endif -} - -/* This should probably be at a better place, but it doesn't really - fit into html-parse.c. */ - -/* The function returns the pointer to the malloc-ed quoted version of - string s. It will recognize and quote numeric and special graphic - entities, as per RFC1866: - - `&' -> `&' - `<' -> `<' - `>' -> `>' - `"' -> `"' - SP -> ` ' - - No other entities are recognized or replaced. */ -char * -html_quote_string (const char *s) -{ - const char *b = s; - char *p, *res; - int i; - - /* Pass through the string, and count the new size. */ - for (i = 0; *s; s++, i++) - { - if (*s == '&') - i += 4; /* `amp;' */ - else if (*s == '<' || *s == '>') - i += 3; /* `lt;' and `gt;' */ - else if (*s == '\"') - i += 5; /* `quot;' */ - else if (*s == ' ') - i += 4; /* #32; */ - } - res = (char *)xmalloc (i + 1); - s = b; - for (p = res; *s; s++) - { - switch (*s) - { - case '&': - *p++ = '&'; - *p++ = 'a'; - *p++ = 'm'; - *p++ = 'p'; - *p++ = ';'; - break; - case '<': case '>': - *p++ = '&'; - *p++ = (*s == '<' ? 'l' : 'g'); - *p++ = 't'; - *p++ = ';'; - break; - case '\"': - *p++ = '&'; - *p++ = 'q'; - *p++ = 'u'; - *p++ = 'o'; - *p++ = 't'; - *p++ = ';'; - break; - case ' ': - *p++ = '&'; - *p++ = '#'; - *p++ = '3'; - *p++ = '2'; - *p++ = ';'; - break; - default: - *p++ = *s; - } - } - *p = '\0'; - return res; -} - /* Determine the width of the terminal we're running on. If that's not possible, return 0. */ @@ -1964,40 +1609,6 @@ random_float (void) int rnd3 = random_number (1000); return rnd1 / 1000.0 + rnd2 / 1000000.0 + rnd3 / 1000000000.0; } - -#if 0 -/* A debugging function for checking whether an MD5 library works. */ - -#include "gen-md5.h" - -char * -debug_test_md5 (char *buf) -{ - unsigned char raw[16]; - static char res[33]; - unsigned char *p1; - char *p2; - int cnt; - ALLOCA_MD5_CONTEXT (ctx); - - gen_md5_init (ctx); - gen_md5_update ((unsigned char *)buf, strlen (buf), ctx); - gen_md5_finish (ctx, raw); - - p1 = raw; - p2 = res; - cnt = 16; - while (cnt--) - { - *p2++ = XNUM_TO_digit (*p1 >> 4); - *p2++ = XNUM_TO_digit (*p1 & 0xf); - ++p1; - } - *p2 = '\0'; - - return res; -} -#endif /* Implementation of run_with_timeout, a generic timeout-forcing routine for systems with Unix-like signal handling. */ @@ -2051,7 +1662,7 @@ alarm_set (double timeout) struct itimerval itv; xzero (itv); itv.it_value.tv_sec = (long) timeout; - itv.it_value.tv_usec = 1000000L * (timeout - (long)timeout); + itv.it_value.tv_usec = 1000000 * (timeout - (long)timeout); if (itv.it_value.tv_sec == 0 && itv.it_value.tv_usec == 0) /* Ensure that we wait for at least the minimum interval. Specifying zero would mean "wait forever". */ @@ -2103,8 +1714,8 @@ alarm_cancel (void) * It works with both SYSV and BSD signals because it doesn't depend on the default setting of SA_RESTART. - * It doesn't special handler setup beyond a simple call to - signal(). (It does use sigsetjmp/siglongjmp, but they're + * It doesn't require special handler setup beyond a simple call + to signal(). (It does use sigsetjmp/siglongjmp, but they're optional.) The only downside is that, if FUN allocates internal resources that @@ -2168,11 +1779,12 @@ xsleep (double seconds) #ifdef HAVE_NANOSLEEP /* nanosleep is the preferred interface because it offers high accuracy and, more importantly, because it allows us to reliably - restart after having been interrupted by a signal such as - SIGWINCH. */ + restart receiving a signal such as SIGWINCH. (There was an + actual Debian bug report about --limit-rate malfunctioning while + the terminal was being resized.) */ struct timespec sleep, remaining; sleep.tv_sec = (long) seconds; - sleep.tv_nsec = 1000000000L * (seconds - (long) seconds); + sleep.tv_nsec = 1000000000 * (seconds - (long) seconds); while (nanosleep (&sleep, &remaining) < 0 && errno == EINTR) /* If nanosleep has been interrupted by a signal, adjust the sleeping period and return to sleep. */ @@ -2188,12 +1800,17 @@ xsleep (double seconds) sleep (seconds); seconds -= (long) seconds; } - usleep (seconds * 1000000L); + usleep (seconds * 1000000); #else /* not HAVE_USLEEP */ #ifdef HAVE_SELECT + /* Note that, although Windows supports select, this sleeping + strategy doesn't work there because Winsock's select doesn't + implement timeout when it is passed NULL pointers for all fd + sets. (But it does work under Cygwin, which implements its own + select.) */ struct timeval sleep; sleep.tv_sec = (long) seconds; - sleep.tv_usec = 1000000L * (seconds - (long) seconds); + sleep.tv_usec = 1000000 * (seconds - (long) seconds); select (0, NULL, NULL, NULL, &sleep); /* If select returns -1 and errno is EINTR, it means we were interrupted by a signal. But without knowing how long we've @@ -2207,3 +1824,143 @@ xsleep (double seconds) } #endif /* not WINDOWS */ + +/* Encode the string S of length LENGTH to base64 format and place it + to STORE. STORE will be 0-terminated, and must point to a writable + buffer of at least 1+BASE64_LENGTH(length) bytes. */ + +void +base64_encode (const char *s, char *store, int length) +{ + /* Conversion table. */ + static char tbl[64] = { + 'A','B','C','D','E','F','G','H', + 'I','J','K','L','M','N','O','P', + 'Q','R','S','T','U','V','W','X', + 'Y','Z','a','b','c','d','e','f', + 'g','h','i','j','k','l','m','n', + 'o','p','q','r','s','t','u','v', + 'w','x','y','z','0','1','2','3', + '4','5','6','7','8','9','+','/' + }; + int i; + unsigned char *p = (unsigned char *)store; + + /* Transform the 3x8 bits to 4x6 bits, as required by base64. */ + for (i = 0; i < length; i += 3) + { + *p++ = tbl[s[0] >> 2]; + *p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)]; + *p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)]; + *p++ = tbl[s[2] & 0x3f]; + s += 3; + } + /* Pad the result if necessary... */ + if (i == length + 1) + *(p - 1) = '='; + else if (i == length + 2) + *(p - 1) = *(p - 2) = '='; + /* ...and zero-terminate it. */ + *p = '\0'; +} + +#define IS_ASCII(c) (((c) & 0x80) == 0) +#define IS_BASE64(c) ((IS_ASCII (c) && base64_char_to_value[c] >= 0) || c == '=') + +/* Get next character from the string, except that non-base64 + characters are ignored, as mandated by rfc2045. */ +#define NEXT_BASE64_CHAR(c, p) do { \ + c = *p++; \ +} while (c != '\0' && !IS_BASE64 (c)) + +/* Decode data from BASE64 (assumed to be encoded as base64) into + memory pointed to by TO. TO should be large enough to accomodate + the decoded data, which is guaranteed to be less than + strlen(base64). + + Since TO is assumed to contain binary data, it is not + NUL-terminated. The function returns the length of the data + written to TO. -1 is returned in case of error caused by malformed + base64 input. */ + +int +base64_decode (const char *base64, char *to) +{ + /* Table of base64 values for first 128 characters. */ + static short base64_char_to_value[128] = + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0- 9 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10- 19 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 20- 29 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 30- 39 */ + -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, /* 40- 49 */ + 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, /* 50- 59 */ + -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, /* 60- 69 */ + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 70- 79 */ + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, /* 80- 89 */ + 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, /* 90- 99 */ + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, /* 100-109 */ + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, /* 110-119 */ + 49, 50, 51, -1, -1, -1, -1, -1 /* 120-127 */ + }; + + const char *p = base64; + char *q = to; + + while (1) + { + unsigned char c; + unsigned long value; + + /* Process first byte of a quadruplet. */ + NEXT_BASE64_CHAR (c, p); + if (!c) + break; + if (c == '=') + return -1; /* illegal '=' while decoding base64 */ + value = base64_char_to_value[c] << 18; + + /* Process scond byte of a quadruplet. */ + NEXT_BASE64_CHAR (c, p); + if (!c) + return -1; /* premature EOF while decoding base64 */ + if (c == '=') + return -1; /* illegal `=' while decoding base64 */ + value |= base64_char_to_value[c] << 12; + *q++ = value >> 16; + + /* Process third byte of a quadruplet. */ + NEXT_BASE64_CHAR (c, p); + if (!c) + return -1; /* premature EOF while decoding base64 */ + + if (c == '=') + { + NEXT_BASE64_CHAR (c, p); + if (!c) + return -1; /* premature EOF while decoding base64 */ + if (c != '=') + return -1; /* padding `=' expected but not found */ + continue; + } + + value |= base64_char_to_value[c] << 6; + *q++ = 0xff & value >> 8; + + /* Process fourth byte of a quadruplet. */ + NEXT_BASE64_CHAR (c, p); + if (!c) + return -1; /* premature EOF while decoding base64 */ + if (c == '=') + continue; + + value |= base64_char_to_value[c]; + *q++ = 0xff & value; + } + + return q - to; +} + +#undef IS_ASCII +#undef IS_BASE64 +#undef NEXT_BASE64_CHAR