bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

pathchk fixes


From: Paul Eggert
Subject: pathchk fixes
Date: Sun, 17 Oct 2004 23:39:30 -0700
User-agent: Gnus/5.1006 (Gnus v5.10.6) Emacs/21.3 (gnu/linux)

I installed the following patch to fix some bugs in pathchk.
It was easier to rewrite most of the guts rather than to fix
each bug one by one, so I took the liberty of adding m'self
to the credits.

2004-10-17  Paul Eggert  <address@hidden>

        * AUTHORS: Add self to pathchk.
        * doc/coreutils.texi (pathchk invocation): Overall lengths are
        OS limits, not file system limits.  Component length checks
        apply to all components, not merely to existing ones.  Say
        that nonexistent names are not errors.  For -p, omit all
        checks based on the underlying file system, not merely length
        checks.  Explain what the portabile file name character set is.
        * m4/jm-macros.m4 (gl_MACROS): Check for mbrlen, for pathchk.
        (gl_CHECK_ALL_TYPES): Require AC_TYPE_MBSTATE_T, for pathchk.
        * src/pathchk.c (AUTHORS): Add self.
        Change "path" to "file name" whenever possible.
        Remove usage comment, as it was a duplication of the code or doc.
        Include <wchar.h> if available.
        (mbrlen, mbstate_t) [! (HAVE_MBRLEN && HAVE_MBSTATE_T)]: Define.
        (NEED_PATHCONF_WRAPPER, PATH_MAX, PATH_MAX_FOR, NAME_MAX,
        pathconf_wrapper, portable_chars, dir_ok): Remove.
        (NAME_MAX_MINIMUM, PATH_MAX_MINIMUM): New macros.
        (pathconf, _PC_NAME_MAX, _PC_PATH_MAX): Define if nonexistent.
        (portable_chars_only): New arg FILELEN.
        Don't assume ASCII; we might be on an EBCDIC host.
        Don't assume unibyte locale in diagnostic.
        (component_start, component_len): New functions.
        (validate_file_name): Renamed from validate_path.  All uses changed.
        Pretty much a complete rewrite.
        Don't make copy of file arg.  Always append trailing slash to
        pathconf arg, just in case it's a symlink (this is pure paranoia;
        we don't know of any hosts where the trailing slash is required).
        Use size_t instead of long int when possible.
        Avoid need to call pathconf in most practical cases.
        Don't use euidaccess several times to test searchability;
        just use lstat once.  Reword diagnostic to put the (often very long)
        file names last.

Index: AUTHORS
===================================================================
RCS file: /fetish/cu/AUTHORS,v
retrieving revision 1.5
diff -p -u -r1.5 AUTHORS
--- AUTHORS     22 Sep 2004 20:03:50 -0000      1.5
+++ AUTHORS     18 Oct 2004 06:12:04 -0000
@@ -52,7 +52,7 @@ nl: Scott Bartram, David MacKenzie
 nohup: Jim Meyering
 od: Jim Meyering
 paste: David M. Ihnat, David MacKenzie
-pathchk: David MacKenzie, Jim Meyering
+pathchk: Paul Eggert, David MacKenzie, Jim Meyering
 pinky: Joseph Arceneaux, David MacKenzie, Kaveh Ghazi
 pinky: Joseph Arceneaux, David MacKenzie, Kaveh Ghazi
 pr: Pete TerMaat, Roland Huebner
Index: doc/coreutils.texi
===================================================================
RCS file: /fetish/cu/doc/coreutils.texi,v
retrieving revision 1.220
diff -p -u -r1.220 coreutils.texi
--- doc/coreutils.texi  15 Oct 2004 19:31:08 -0000      1.220
+++ doc/coreutils.texi  18 Oct 2004 06:12:08 -0000
@@ -10161,19 +10161,22 @@ pathchk address@hidden@dots{} @var{name}
 
 For each @var{name}, @command{pathchk} prints a message if any of
 these conditions is true:
+
 @enumerate
 @item
-one of the existing directories in @var{name} does not have search
+One of the existing directories in @var{name} does not have search
 (execute) permission,
 @item
-the length of @var{name} is larger than its file system's maximum
-file name length,
+The length of @var{name} is larger than the maximum supported by the
+operating system.
 @item
-the length of one component of @var{name}, corresponding to an
-existing directory name, is larger than its file system's maximum
-length for a file name component.
+The length of one component of @var{name} is longer than
+its file system's maximum.
 @end enumerate
 
+A nonexistent @var{name} is not an error, so long a file with that
+name could be created under the above conditions.
+
 The program accepts the following option.  Also see @ref{Common options}.
 
 @table @samp
@@ -10182,10 +10185,12 @@ The program accepts the following option
 @itemx --portability
 @opindex -p
 @opindex --portability
-Instead of performing length checks on the underlying file system,
-test the length of each file name and its components against the
+Do not perform checks based on the underlying file system.  Instead,
+check the length of each file name and its components against the
 @acronym{POSIX} minimum limits for portability.  Also check that the file
-name contains no characters not in the portable file name character set.
+name contains only characters that are in the portable file name
+character set, namely, the ASCII letters and digits, @samp{-},
address@hidden, @samp{/}, and @samp{_}.
 
 @end table
 
@@ -10193,7 +10198,7 @@ name contains no characters not in the p
 Exit status:
 
 @display
-0 if all specified file names passed all of the tests,
+0 if all specified file names passed all checks,
 1 otherwise.
 @end display
 
Index: m4/jm-macros.m4
===================================================================
RCS file: /fetish/cu/m4/jm-macros.m4,v
retrieving revision 1.198
diff -p -u -r1.198 jm-macros.m4
--- m4/jm-macros.m4     4 Aug 2004 22:27:12 -0000       1.198
+++ m4/jm-macros.m4     18 Oct 2004 06:12:08 -0000
@@ -1,4 +1,4 @@
-#serial 75   -*- autoconf -*-
+#serial 76   -*- autoconf -*-
 
 dnl Misc type-related macros for coreutils.
 
@@ -113,6 +113,7 @@ AC_DEFUN([gl_MACROS],
     memcpy \
     mempcpy \
     mkfifo \
+    mbrlen \
     realpath \
     sethostname \
     strchr \
@@ -263,6 +264,7 @@ AC_DEFUN([gl_CHECK_ALL_TYPES],
   AC_REQUIRE([AC_STRUCT_ST_DM_MODE])
 
   AC_REQUIRE([AC_TYPE_GETGROUPS])
+  AC_REQUIRE([AC_TYPE_MBSTATE_T])
   AC_REQUIRE([AC_TYPE_MODE_T])
   AC_REQUIRE([AC_TYPE_OFF_T])
   AC_REQUIRE([AC_TYPE_PID_T])
Index: src/pathchk.c
===================================================================
RCS file: /fetish/cu/src/pathchk.c,v
retrieving revision 1.81
diff -p -u -r1.81 pathchk.c
--- src/pathchk.c       21 Sep 2004 22:11:28 -0000      1.81
+++ src/pathchk.c       18 Oct 2004 06:12:08 -0000
@@ -1,4 +1,4 @@
-/* pathchk -- check whether pathnames are valid or portable
+/* pathchk -- check whether file names are valid or portable
    Copyright (C) 1991-2004 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
@@ -15,75 +15,29 @@
    along with this program; if not, write to the Free Software Foundation,
    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
-/* Usage: pathchk [-p] [--portability] path...
-
-   For each PATH, print a message if any of these conditions are false:
-   * all existing leading directories in PATH have search (execute) permission
-   * strlen (PATH) <= PATH_MAX
-   * strlen (each_directory_in_PATH) <= NAME_MAX
-
-   Exit status:
-   0                   All PATH names passed all of the tests.
-   1                   An error occurred.
-
-   Options:
-   -p, --portability   Instead of performing length checks on the
-                       underlying file system, test the length of the
-                       pathname and its components against the POSIX
-                       minimum limits for portability, _POSIX_NAME_MAX
-                       and _POSIX_PATH_MAX in 2.9.2.  Also check that
-                       the pathname contains no character not in the
-                       portable filename character set.
-
-   David MacKenzie <address@hidden>
-   and Jim Meyering <address@hidden> */
-
 #include <config.h>
 #include <stdio.h>
 #include <getopt.h>
 #include <sys/types.h>
+#if HAVE_WCHAR_H
+# include <wchar.h>
+#endif
 
 #include "system.h"
 #include "error.h"
 #include "euidaccess.h"
+#include "quote.h"
+#include "quotearg.h"
+
+#if ! (HAVE_MBRLEN && HAVE_MBSTATE_T)
+# define mbrlen(s, n, ps) 1
+# define mbstate_t int
+#endif
 
 /* The official name of this program (e.g., no `g' prefix).  */
 #define PROGRAM_NAME "pathchk"
 
-#define AUTHORS "David MacKenzie", "Jim Meyering"
-
-#define NEED_PATHCONF_WRAPPER 0
-#if HAVE_PATHCONF
-# ifndef PATH_MAX
-#  define PATH_MAX_FOR(p) pathconf_wrapper ((p), _PC_PATH_MAX)
-#  define NEED_PATHCONF_WRAPPER 1
-# endif /* not PATH_MAX */
-# ifndef NAME_MAX
-#  define NAME_MAX_FOR(p) pathconf_wrapper ((p), _PC_NAME_MAX);
-#  undef NEED_PATHCONF_WRAPPER
-#  define NEED_PATHCONF_WRAPPER 1
-# endif /* not NAME_MAX */
-
-#else
-
-# include <sys/param.h>
-# ifndef PATH_MAX
-#  ifdef MAXPATHLEN
-#   define PATH_MAX MAXPATHLEN
-#  else /* not MAXPATHLEN */
-#   define PATH_MAX _POSIX_PATH_MAX
-#  endif /* not MAXPATHLEN */
-# endif /* not PATH_MAX */
-
-# ifndef NAME_MAX
-#  ifdef MAXNAMLEN
-#   define NAME_MAX MAXNAMLEN
-#  else /* not MAXNAMLEN */
-#   define NAME_MAX _POSIX_NAME_MAX
-#  endif /* not MAXNAMLEN */
-# endif /* not NAME_MAX */
-
-#endif
+#define AUTHORS "Paul Eggert", "David MacKenzie", "Jim Meyering"
 
 #ifndef _POSIX_PATH_MAX
 # define _POSIX_PATH_MAX 255
@@ -92,14 +46,29 @@
 # define _POSIX_NAME_MAX 14
 #endif
 
-#ifndef PATH_MAX_FOR
-# define PATH_MAX_FOR(p) PATH_MAX
+#ifdef _XOPEN_NAME_MAX
+# define NAME_MAX_MINIMUM _XOPEN_NAME_MAX
+#else
+# define NAME_MAX_MINIMUM _POSIX_NAME_MAX
 #endif
-#ifndef NAME_MAX_FOR
-# define NAME_MAX_FOR(p) NAME_MAX
+#ifdef _XOPEN_PATH_MAX
+# define PATH_MAX_MINIMUM _XOPEN_PATH_MAX
+#else
+# define PATH_MAX_MINIMUM _POSIX_PATH_MAX
 #endif
 
-static bool validate_path (char *path, bool portability);
+#if ! (HAVE_PATHCONF && defined _PC_NAME_MAX && defined _PC_PATH_MAX)
+# ifndef _PC_NAME_MAX
+#  define _PC_NAME_MAX 0
+#  define _PC_PATH_MAX 1
+# endif
+# ifndef pathconf
+#  define pathconf(file, flag) \
+     (flag == _PC_NAME_MAX ? NAME_MAX_MINIMUM : PATH_MAX_MINIMUM)
+# endif
+#endif
+
+static bool validate_file_name (char *file, bool portability);
 
 /* The name this program was run with. */
 char *program_name;
@@ -112,25 +81,6 @@ static struct option const longopts[] =
   {NULL, 0, NULL, 0}
 };
 
-#if NEED_PATHCONF_WRAPPER
-/* Distinguish between the cases when pathconf fails and when it reports there
-   is no limit (the latter is the case for PATH_MAX on the Hurd).  When there
-   is no limit, return LONG_MAX.  Otherwise, return pathconf's return value.  
*/
-
-static long int
-pathconf_wrapper (const char *filename, int param)
-{
-  long int ret;
-
-  errno = 0;
-  ret = pathconf (filename, param);
-  if (ret < 0 && errno == 0)
-    return LONG_MAX;
-
-  return ret;
-}
-#endif
-
 void
 usage (int status)
 {
@@ -191,190 +141,223 @@ main (int argc, char **argv)
     }
 
   for (; optind < argc; ++optind)
-    ok &= validate_path (argv[optind], check_portability);
+    ok &= validate_file_name (argv[optind], check_portability);
 
   exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
 }
 
-/* Each element is nonzero if the corresponding ASCII character is
-   in the POSIX portable character set, and zero if it is not.
-   In addition, the entry for `/' is nonzero to simplify checking. */
-static char const portable_chars[256] =
-{
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0-15 */
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16-31 */
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, /* 32-47 */
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 48-63 */
-  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 64-79 */
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 80-95 */
-  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 96-111 */
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 112-127 */
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/* If PATH contains only portable characters, return true, else false.  */
+/* If FILE (of length FILELEN) contains only portable characters,
+   return true, else report an error and return false.  */
 
 static bool
-portable_chars_only (const char *path)
+portable_chars_only (char const *file, size_t filelen)
 {
-  const char *p;
+  size_t validlen = strspn (file,
+                           ("/"
+                            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                            "abcdefghijklmnopqrstuvwxyz"
+                            "0123456789._-"));
+  char const *invalid = file + validlen;
+
+  if (*invalid)
+    {
+      mbstate_t mbstate = {0};
+      size_t charlen = mbrlen (invalid, filelen - validlen, &mbstate);
+      error (0, 0,
+            _("nonportable character %s in file name %s"),
+            quotearg_n_style_mem (1, locale_quoting_style, invalid,
+                                  (charlen <= MB_LEN_MAX ? charlen : 1)),
+            quote_n (0, file));
+      return false;
+    }
 
-  for (p = path; *p; ++p)
-    if (portable_chars[to_uchar (*p)] == 0)
-      {
-       error (0, 0, _("path `%s' contains nonportable character `%c'"),
-              path, *p);
-       return false;
-      }
   return true;
 }
 
-/* Return 1 if PATH is a usable leading directory, 0 if not,
-   2 if it doesn't exist.  */
+/* Return the address of the start of the next file name component in F.  */
 
-static int
-dir_ok (const char *path)
+static char *
+component_start (char *f)
 {
-  struct stat stats;
-
-  if (stat (path, &stats))
-    return 2;
-
-  if (!S_ISDIR (stats.st_mode))
-    {
-      error (0, 0, _("`%s' is not a directory"), path);
-      return 0;
-    }
+  while (*f == '/')
+    f++;
+  return f;
+}
 
-  /* Use access to test for search permission because
-     testing permission bits of st_mode can lose with new
-     access control mechanisms.  */
-  if (euidaccess (path, X_OK) != 0)
-    {
-      if (errno == EACCES)
-       error (0, 0, _("directory `%s' is not searchable"), path);
-      else
-       error (0, errno, "%s", path);
-      return 0;
-    }
+/* Return the size of the file name component F.  F must be nonempty.  */
 
-  return 1;
+static size_t
+component_len (char const *f)
+{
+  size_t len;
+  for (len = 1; f[len] != '/' && f[len]; len++)
+    continue;
+  return len;
 }
 
 /* Make sure that
-   strlen (PATH) <= PATH_MAX
-   && strlen (each-existing-directory-in-PATH) <= NAME_MAX
+   strlen (FILE) <= PATH_MAX
+   && strlen (each-existing-directory-in-FILE) <= NAME_MAX
 
    If PORTABILITY is true, compare against _POSIX_PATH_MAX and
-   _POSIX_NAME_MAX instead, and make sure that PATH contains no
+   _POSIX_NAME_MAX instead, and make sure that FILE contains no
    characters not in the POSIX portable filename character set, which
-   consists of A-Z, a-z, 0-9, ., _, -.
+   consists of A-Z, a-z, 0-9, ., _, - (plus / for separators).
 
-   Make sure that all leading directories along PATH that exist have
-   `x' permission.
+   If PORTABILITY is false, make sure that all leading directories
+   along FILE that exist are searchable.
 
    Return true if all of these tests are successful, false if any fail.  */
 
 static bool
-validate_path (char *path, bool portability)
+validate_file_name (char *file, bool portability)
 {
-  long int path_max;
-  int last_elem;               /* Nonzero if checking last element of path. */
-  int exists IF_LINT (= 0);    /* 2 if the path element exists.  */
-  char *slash;
-  char *parent;                        /* Last existing leading directory so 
far.  */
+  size_t filelen = strlen (file);
+
+  /* Start of file name component being checked.  */
+  char *start;
+
+  /* True if component lengths need to be checked.  */
+  bool check_component_lengths;
 
-  if (portability && !portable_chars_only (path))
+  if (portability && ! portable_chars_only (file, filelen))
     return false;
 
-  if (*path == '\0')
+  if (*file == '\0')
     return true;
 
-  /* Figure out the parent of the first element in PATH.  */
-  parent = xstrdup (*path == '/' ? "/" : ".");
-
-  slash = path;
-  last_elem = 0;
-  while (1)
+  if (portability || PATH_MAX_MINIMUM <= filelen)
     {
-      long int name_max;
-      long int length;         /* Length of partial path being checked. */
-      char *start;             /* Start of path element being checked. */
-
-      /* Find the end of this element of the path.
-        Then chop off the rest of the path after this element. */
-      while (*slash == '/')
-       slash++;
-      start = slash;
-      slash = strchr (slash, '/');
-      if (slash != NULL)
-       *slash = '\0';
-      else
-       {
-         last_elem = 1;
-         slash = strchr (start, '\0');
-       }
+      size_t maxsize;
 
-      if (!last_elem)
+      if (portability)
+       maxsize = _POSIX_PATH_MAX;
+      else
        {
-         exists = dir_ok (path);
-         if (exists == 0)
+         long int size;
+         char const *dir = (*file == '/' ? "/" : ".");
+         errno = 0;
+         size = pathconf (dir, _PC_PATH_MAX);
+         if (size < 0 && errno != 0)
            {
-             free (parent);
+             error (0, errno, dir);
              return false;
            }
+         maxsize = MIN (size, SIZE_MAX);
        }
 
-      length = slash - start;
-      /* Since we know that `parent' is a directory, it's ok to call
-        pathconf with it as the argument.  (If `parent' isn't a directory
-        or doesn't exist, the behavior of pathconf is undefined.)
-        But if `parent' is a directory and is on a remote file system,
-        it's likely that pathconf can't give us a reasonable value
-        and will return -1.  (NFS and tempfs are not POSIX . . .)
-        In that case, we have no choice but to assume the pessimal
-        POSIX minimums.  */
-      name_max = portability ? _POSIX_NAME_MAX : NAME_MAX_FOR (parent);
-      if (name_max < 0)
-       name_max = _POSIX_NAME_MAX;
-      if (length > name_max)
+      if (maxsize <= filelen)
        {
-         error (0, 0, _("name `%s' has length %ld; exceeds limit of %ld"),
-                start, length, name_max);
-         free (parent);
+         unsigned long int len = filelen;
+         unsigned long int maxlen = maxsize - 1;
+         error (0, 0, _("limit %lu exceeded by length %lu of file name %s"),
+                maxlen, len, quote (file));
          return false;
        }
+    }
 
-      if (last_elem)
-       break;
+  if (! portability)
+    {
+      /* Check whether a file name component is in a directory that
+        is not searchable, or has some other serious problem.  */
 
-      if (exists == 1)
+      struct stat st;
+      if (lstat (file, &st) != 0 && errno != ENOENT)
        {
-         free (parent);
-         parent = xstrdup (path);
+         error (0, errno, "%s", file);
+         return false;
        }
+    }
+
+  /* Check whether pathconf (..., _PC_NAME_MAX) can be avoided, i.e.,
+     whether all file name components are so short that they are valid
+     in any file system on this platform.  If PORTABILITY, though,
+     it's more convenient to check component lengths below.  */
+
+  check_component_lengths = portability;
+  if (! check_component_lengths)
+    {
+      for (start = file; *(start = component_start (start)); )
+       {
+         size_t length = component_len (start);
 
-      *slash++ = '/';
+         if (NAME_MAX_MINIMUM < length)
+           {
+             check_component_lengths = true;
+             break;
+           }
+
+         start += length;
+       }
     }
 
-  /* `parent' is now the last existing leading directory in the whole path,
-     so it's ok to call pathconf with it as the argument.  */
-  path_max = portability ? _POSIX_PATH_MAX : PATH_MAX_FOR (parent);
-  if (path_max < 0)
-    path_max = _POSIX_PATH_MAX;
-  free (parent);
-  if (strlen (path) > (size_t) path_max)
+  if (check_component_lengths)
     {
-      error (0, 0, _("path `%s' has length %lu; exceeds limit of %ld"),
-            path, (unsigned long int) strlen (path), path_max);
-      return false;
+      /* The limit on file name components for the current component.
+         This defaults to NAME_MAX_MINIMUM, for the sake of non-POSIX
+         systems (NFS, say?) where pathconf fails on "." or "/" with
+         errno == ENOENT.  */
+      size_t name_max = NAME_MAX_MINIMUM;
+
+      /* If nonzero, the known limit on file name components.  */
+      size_t known_name_max = (portability ? _POSIX_NAME_MAX : 0);
+
+      for (start = file; *(start = component_start (start)); )
+       {
+         size_t length;
+
+         if (known_name_max)
+           name_max = known_name_max;
+         else
+           {
+             long int len;
+             char const *dir = (start == file ? "." : file);
+             char c = *start;
+             errno = 0;
+             *start = '\0';
+             len = pathconf (dir, _PC_NAME_MAX);
+             *start = c;
+             if (0 <= len)
+               name_max = MIN (len, SIZE_MAX);
+             else
+               switch (errno)
+                 {
+                 case 0:
+                   /* There is no limit.  */
+                   name_max = SIZE_MAX;
+                   break;
+
+                 case ENOENT:
+                   /* DIR does not exist; use its parent's maximum.  */
+                   known_name_max = name_max;
+                   break;
+
+                 default:
+                   *start = '\0';
+                   error (0, errno, "%s", dir);
+                   *start = c;
+                   return false;
+                 }
+           }
+
+         length = component_len (start);
+
+         if (name_max < length)
+           {
+             unsigned long int len = length;
+             unsigned long int maxlen = name_max;
+             char c = start[len];
+             start[len] = '\0';
+             error (0, 0,
+                    _("limit %lu exceeded by length %lu "
+                      "of file name component %s"),
+                    maxlen, len, quote (start));
+             start[len] = c;
+             return false;
+           }
+
+         start += length;
+       }
     }
 
   return true;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]