]> sjero.net Git - wget/blobdiff - src/utils.c
Restore string after function call.
[wget] / src / utils.c
index 63545a3274aec45b1067925c3453aa9b0411cf04..15e3f89ba392b726050e6ba7dccc4af502bca4a7 100644 (file)
@@ -1,6 +1,6 @@
 /* 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.
 
@@ -17,17 +17,18 @@ GNU General Public License for more details.
 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>
@@ -80,7 +81,6 @@ so, delete this exception statement from your version.  */
 # define USE_SIGNAL_TIMEOUT
 #endif
 
-#include "wget.h"
 #include "utils.h"
 #include "hash.h"
 
@@ -88,6 +88,32 @@ so, delete this exception statement from your version.  */
 #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 *
@@ -96,7 +122,7 @@ xstrdup_lower (const char *s)
   char *copy = xstrdup (s);
   char *p = copy;
   for (; *p; p++)
-    *p = TOLOWER (*p);
+    *p = c_tolower (*p);
   return copy;
 }
 
@@ -135,7 +161,7 @@ sepstring (const char *s)
           res[++i] = NULL;
           ++s;
           /* Skip the blanks following the ','.  */
-          while (ISSPACE (*s))
+          while (c_isspace (*s))
             ++s;
           p = s;
         }
@@ -159,6 +185,13 @@ sepstring (const char *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, ...)
 {
@@ -171,7 +204,8 @@ 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;
@@ -201,8 +235,21 @@ aprintf (const char *fmt, ...)
       /* 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 */
@@ -220,7 +267,7 @@ concat_strings (const char *str0, ...)
 
   const char *next_str;
   int total_length = 0;
-  int argcount;
+  size_t argcount;
 
   /* Calculate the length of and allocate the resulting string. */
 
@@ -301,7 +348,7 @@ fork_to_background (void)
   /* 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
@@ -327,7 +374,7 @@ fork_to_background (void)
       /* 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()? */
     }
 
@@ -373,8 +420,8 @@ remove_link (const char *file)
       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;
 }
@@ -636,10 +683,10 @@ fnmatch_nocase (const char *pattern, const char *string, int flags)
   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
@@ -677,11 +724,13 @@ acceptable (const char *s)
 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 == '/');
@@ -766,7 +815,7 @@ match_tail (const char *string, const char *tail, bool fold_case)
   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;
     }
 
@@ -1219,6 +1268,12 @@ get_grouping_data (const char **sep, const char **grouping)
       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
@@ -1331,7 +1386,7 @@ human_readable (HR_NUMTYPE n)
       '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)
@@ -1940,7 +1995,7 @@ base64_encode (const void *data, int length, char *dest)
    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)
 
@@ -2167,7 +2222,17 @@ test_dir_matches_p()
     { { "/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)