size <<= 1; /* twice the old size */
str = xrealloc (str, size);
}
- return NULL; /* unreached */
}
/* Concatenate the NULL-terminated list of string arguments into
}
#endif /* not WINDOWS */
\f
-/* "Touch" FILE, i.e. make its atime and mtime equal to the time
- specified with TM. */
+/* "Touch" FILE, i.e. make its mtime ("modified time") equal the time
+ specified with TM. The atime ("access time") is set to the current
+ time. */
+
void
touch (const char *file, time_t tm)
{
#ifdef HAVE_STRUCT_UTIMBUF
struct utimbuf times;
- times.actime = times.modtime = tm;
#else
- time_t times[2];
- times[0] = times[1] = tm;
+ struct {
+ time_t actime;
+ time_t modtime;
+ } times;
#endif
-
+ times.modtime = tm;
+ times.actime = time (NULL);
if (utime (file, ×) == -1)
logprintf (LOG_NOTQUIET, "utime(%s): %s\n", file, strerror (errno));
}
proclist (char **strlist, const char *s, enum accd flags)
{
char **x;
-
for (x = strlist; *x; x++)
- if (has_wildcards_p (*x))
- {
- if (fnmatch (*x, s, FNM_PATHNAME) == 0)
- break;
- }
- else
- {
- char *p = *x + ((flags & ALLABS) && (**x == '/')); /* Remove '/' */
- if (frontcmp (p, s))
- break;
- }
+ {
+ /* Remove leading '/' if ALLABS */
+ char *p = *x + ((flags & ALLABS) && (**x == '/'));
+ if (has_wildcards_p (p))
+ {
+ if (fnmatch (p, s, FNM_PATHNAME) == 0)
+ break;
+ }
+ else
+ {
+ if (frontcmp (p, s))
+ break;
+ }
+ }
return *x;
}
xfree (v2);
return v1;
}
+
+/* Append a freshly allocated copy of STR to VEC. If VEC is NULL, it
+ is allocated as needed. Return the new value of the vector. */
+
+char **
+vec_append (char **vec, const char *str)
+{
+ int cnt; /* count of vector elements, including
+ the one we're about to append */
+ if (vec != NULL)
+ {
+ for (cnt = 0; vec[cnt]; cnt++)
+ ;
+ ++cnt;
+ }
+ else
+ cnt = 1;
+ /* Reallocate the array to fit the new element and the NULL. */
+ vec = xrealloc (vec, (cnt + 1) * sizeof (char *));
+ /* Append a copy of STR to the vector. */
+ vec[cnt - 1] = xstrdup (str);
+ vec[cnt] = NULL;
+ return vec;
+}
\f
/* Sometimes it's useful to create "sets" of strings, i.e. special
hash tables where you want to store strings as keys and merely
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. */
+ original computer science meaning of "powers of 1024". Powers of
+ 1000 would be useless since Wget already displays sizes with
+ thousand separators. 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)
#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. */
+/* Encode the string STR of length LENGTH to base64 format and place it
+ to B64STORE. The output will be \0-terminated, and must point to a
+ writable buffer of at least 1+BASE64_LENGTH(length) bytes. It
+ returns the length of the resulting base64 data, not counting the
+ terminating zero.
-void
-base64_encode (const char *s, char *store, int length)
+ This implementation will not emit newlines after 76 characters of
+ base64 data. */
+
+int
+base64_encode (const char *str, int length, char *b64store)
{
/* Conversion table. */
static char tbl[64] = {
'4','5','6','7','8','9','+','/'
};
int i;
- unsigned char *p = (unsigned char *)store;
+ const unsigned char *s = (const unsigned char *) str;
+ char *p = b64store;
/* Transform the 3x8 bits to 4x6 bits, as required by base64. */
for (i = 0; i < length; i += 3)
*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';
+
+ return p - b64store;
}
#define IS_ASCII(c) (((c) & 0x80) == 0)
int
base64_decode (const char *base64, char *to)
{
- /* Table of base64 values for first 128 characters. */
+ /* Table of base64 values for first 128 characters. Note that this
+ assumes ASCII (but so does Wget in other places). */
static short base64_char_to_value[128] =
{
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0- 9 */
#undef IS_ASCII
#undef IS_BASE64
#undef NEXT_BASE64_CHAR
+\f
+/* Simple merge sort for use by stable_sort. Implementation courtesy
+ Zeljko Vrba with additional debugging by Nenad Barbutov. */
+
+static void
+mergesort_internal (void *base, void *temp, size_t size, size_t from, size_t to,
+ int (*cmpfun) PARAMS ((const void *, const void *)))
+{
+#define ELT(array, pos) ((char *)(array) + (pos) * size)
+ if (from < to)
+ {
+ size_t i, j, k;
+ size_t mid = (to + from) / 2;
+ mergesort_internal (base, temp, size, from, mid, cmpfun);
+ mergesort_internal (base, temp, size, mid + 1, to, cmpfun);
+ i = from;
+ j = mid + 1;
+ for (k = from; (i <= mid) && (j <= to); k++)
+ if (cmpfun (ELT (base, i), ELT (base, j)) <= 0)
+ memcpy (ELT (temp, k), ELT (base, i++), size);
+ else
+ memcpy (ELT (temp, k), ELT (base, j++), size);
+ while (i <= mid)
+ memcpy (ELT (temp, k++), ELT (base, i++), size);
+ while (j <= to)
+ memcpy (ELT (temp, k++), ELT (base, j++), size);
+ for (k = from; k <= to; k++)
+ memcpy (ELT (base, k), ELT (temp, k), size);
+ }
+#undef ELT
+}
+
+/* Stable sort with interface exactly like standard library's qsort.
+ Uses mergesort internally, allocating temporary storage with
+ alloca. */
+
+void
+stable_sort (void *base, size_t nmemb, size_t size,
+ int (*cmpfun) PARAMS ((const void *, const void *)))
+{
+ if (size > 1)
+ {
+ void *temp = alloca (nmemb * size * sizeof (void *));
+ mergesort_internal (base, temp, size, 0, nmemb - 1, cmpfun);
+ }
+}