/* 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.
You should have received a copy of the GNU General Public License
along with Wget. If not, see <http://www.gnu.org/licenses/>.
-In addition, as a special exception, the Free Software Foundation
-gives permission to link the code of its release of Wget with the
-OpenSSL project's "OpenSSL" library (or with modified versions of it
-that use the same license as the "OpenSSL" library), and distribute
-the linked executables. You must obey the GNU General Public License
-in all respects for all of the code used other than "OpenSSL". If you
-modify this file, you may extend this exception to your version of the
-file, but you are not obligated to do so. If you do not wish to do
-so, delete this exception statement from your version. */
+Additional permission under GNU GPL version 3 section 7
-#include <config.h>
+If you modify this program, or any covered work, by linking or
+combining it with the OpenSSL project's OpenSSL library (or a
+modified version of that library), containing parts covered by the
+terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
+grants you additional permission to convey the resulting work.
+Corresponding Source for a non-source form of such a combination
+shall include the source code for the parts of OpenSSL used as well
+as that of the covered work. */
+
+#include "wget.h"
#include <stdio.h>
#include <stdlib.h>
# 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)