/* Various utility functions.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
This file is part of GNU Wget.
shall include the source code for the parts of OpenSSL used as well
as that of the covered work. */
-#include <config.h>
+#include "wget.h"
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_MMAP
# include <sys/mman.h>
#endif
+#ifdef HAVE_PROCESS_H
+# include <process.h> /* getpid() */
+#endif
#ifdef HAVE_UTIME_H
# include <utime.h>
#endif
# define USE_SIGNAL_TIMEOUT
#endif
-#include "wget.h"
#include "utils.h"
#include "hash.h"
#include "test.h"
#endif
+static void
+memfatal (const char *context, long attempted_size)
+{
+ /* Make sure we don't try to store part of the log line, and thus
+ call malloc. */
+ log_set_save_context (false);
+
+ /* We have different log outputs in different situations:
+ 1) output without bytes information
+ 2) output with bytes information */
+ if (attempted_size == UNKNOWN_ATTEMPTED_SIZE)
+ {
+ logprintf (LOG_ALWAYS,
+ _("%s: %s: Failed to allocate enough memory; memory exhausted.\n"),
+ exec_name, context);
+ }
+ else
+ {
+ logprintf (LOG_ALWAYS,
+ _("%s: %s: Failed to allocate %ld bytes; memory exhausted.\n"),
+ exec_name, context, attempted_size);
+ }
+
+ exit (1);
+}
+
/* Utility function: like xstrdup(), but also lowercases S. */
char *
char *copy = xstrdup (s);
char *p = copy;
for (; *p; p++)
- *p = TOLOWER (*p);
+ *p = c_tolower (*p);
return copy;
}
res[++i] = NULL;
++s;
/* Skip the blanks following the ','. */
- while (ISSPACE (*s))
+ while (c_isspace (*s))
++s;
p = s;
}
vsnprintf until the correct size is found. Since Wget also ships a
fallback implementation of vsnprintf, this should be portable. */
+/* Constant is using for limits memory allocation for text buffer.
+ Applicable in situation when: vasprintf is not available in the system
+ and vsnprintf return -1 when long line is truncated (in old versions of
+ glibc and in other system where C99 doesn`t support) */
+
+#define FMT_MAX_LENGTH 1048576
+
char *
aprintf (const char *fmt, ...)
{
ret = vasprintf (&str, fmt, args);
va_end (args);
if (ret < 0 && errno == ENOMEM)
- abort (); /* for consistency with xmalloc/xrealloc */
+ memfatal ("aprintf", UNKNOWN_ATTEMPTED_SIZE); /* for consistency
+ with xmalloc/xrealloc */
else if (ret < 0)
return NULL;
return str;
/* Else try again with a larger buffer. */
if (n > -1) /* C99 */
size = n + 1; /* precisely what is needed */
+ else if (size >= FMT_MAX_LENGTH) /* We have a huge buffer, */
+ { /* maybe we have some wrong
+ format string? */
+ logprintf (LOG_ALWAYS,
+ _("%s: aprintf: text buffer is too big (%ld bytes), "
+ "aborting.\n"),
+ exec_name, size); /* printout a log message */
+ abort (); /* and abort... */
+ }
else
- size <<= 1; /* twice the old size */
+ {
+ /* else, we continue to grow our
+ * buffer: Twice the old size. */
+ size <<= 1;
+ }
str = xrealloc (str, size);
}
#endif /* not HAVE_VASPRINTF */
const char *next_str;
int total_length = 0;
- int argcount;
+ size_t argcount;
/* Calculate the length of and allocate the resulting string. */
/* Whether we arrange our own version of opt.lfilename here. */
bool logfile_changed = false;
- if (!opt.lfilename)
+ if (!opt.lfilename && (!opt.quiet || opt.server_response))
{
/* We must create the file immediately to avoid either a race
condition (which arises from using unique_name and failing to
/* parent, no error */
printf (_("Continuing in background, pid %d.\n"), (int) pid);
if (logfile_changed)
- printf (_("Output will be written to `%s'.\n"), opt.lfilename);
+ printf (_("Output will be written to %s.\n"), quote (opt.lfilename));
exit (0); /* #### should we use _exit()? */
}
DEBUGP (("Unlinking %s (symlink).\n", file));
err = unlink (file);
if (err != 0)
- logprintf (LOG_VERBOSE, _("Failed to unlink symlink `%s': %s\n"),
- file, strerror (errno));
+ logprintf (LOG_VERBOSE, _("Failed to unlink symlink %s: %s\n"),
+ quote (file), strerror (errno));
}
return err;
}
char *strcopy = (char *) alloca (strlen (string) + 1);
char *p;
for (p = patcopy; *pattern; pattern++, p++)
- *p = TOLOWER (*pattern);
+ *p = c_tolower (*pattern);
*p = '\0';
for (p = strcopy; *string; string++, p++)
- *p = TOLOWER (*string);
+ *p = c_tolower (*string);
*p = '\0';
return fnmatch (patcopy, strcopy, flags);
#endif
bool
subdir_p (const char *d1, const char *d2)
{
+ if (*d1 == '\0')
+ return true;
if (!opt.ignore_case)
for (; *d1 && *d2 && (*d1 == *d2); ++d1, ++d2)
;
else
- for (; *d1 && *d2 && (TOLOWER (*d1) == TOLOWER (*d2)); ++d1, ++d2)
+ for (; *d1 && *d2 && (c_tolower (*d1) == c_tolower (*d2)); ++d1, ++d2)
;
return *d1 == '\0' && (*d2 == '\0' || *d2 == '/');
else
{
for (i = strlen (string), j = strlen (tail); i >= 0 && j >= 0; i--, j--)
- if (TOLOWER (string[i]) != TOLOWER (tail[j]))
+ if (c_tolower (string[i]) != c_tolower (tail[j]))
break;
}
struct lconv *lconv = localeconv ();
cached_sep = lconv->thousands_sep;
cached_grouping = lconv->grouping;
+#if ! USE_NLS_PROGRESS_BAR
+ /* We can't count column widths, so ensure that the separator
+ * is single-byte only (let check below determine what byte). */
+ if (strlen(cached_sep) > 1)
+ cached_sep = "";
+#endif
if (!*cached_sep)
{
/* Many locales (such as "C" or "hr_HR") don't specify
'E', /* exabyte, 2^60 bytes */
};
static char buf[8];
- int i;
+ size_t i;
/* If the quantity is smaller than 1K, just print it. */
if (n < 1024)
when end of string is reached. */
#define NEXT_CHAR(c, p) do { \
c = (unsigned char) *p++; \
-} while (ISSPACE (c))
+} while (c_isspace (c))
#define IS_ASCII(c) (((c) & 0x80) == 0)
{ { "/somedir", "/someotherdir", NULL }, "anotherdir", false },
{ { "/somedir", "/*otherdir", NULL }, "anotherdir", true },
{ { "/somedir/d1", "/someotherdir", NULL }, "somedir/d1", true },
+ { { "*/*d1", "/someotherdir", NULL }, "somedir/d1", true },
{ { "/somedir/d1", "/someotherdir", NULL }, "d1", false },
+ { { "!COMPLETE", NULL, NULL }, "!COMPLETE", true },
+ { { "*COMPLETE", NULL, NULL }, "!COMPLETE", true },
+ { { "*/!COMPLETE", NULL, NULL }, "foo/!COMPLETE", true },
+ { { "*COMPLETE", NULL, NULL }, "foo/!COMPLETE", false },
+ { { "*/*COMPLETE", NULL, NULL }, "foo/!COMPLETE", true },
+ { { "/dir with spaces", NULL, NULL }, "dir with spaces", true },
+ { { "/dir*with*spaces", NULL, NULL }, "dir with spaces", true },
+ { { "/Tmp/has", NULL, NULL }, "/Tmp/has space", false },
+ { { "/Tmp/has", NULL, NULL }, "/Tmp/has,comma", false },
};
for (i = 0; i < countof(test_array); ++i)