diff options
Diffstat (limited to 'src/pathchk.c')
-rw-r--r-- | src/pathchk.c | 303 |
1 files changed, 146 insertions, 157 deletions
diff --git a/src/pathchk.c b/src/pathchk.c index 2fc55d3..bd4254a 100644 --- a/src/pathchk.c +++ b/src/pathchk.c @@ -1,10 +1,10 @@ /* pathchk -- check whether file names are valid or portable - Copyright (C) 1991-2006 Free Software Foundation, Inc. + Copyright (C) 1991-2016 Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or modify + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -12,32 +12,25 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <config.h> #include <stdio.h> #include <getopt.h> #include <sys/types.h> -#if HAVE_WCHAR_H -# include <wchar.h> -#endif +#include <wchar.h> #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). */ +/* The official name of this program (e.g., no 'g' prefix). */ #define PROGRAM_NAME "pathchk" -#define AUTHORS "Paul Eggert", "David MacKenzie", "Jim Meyering" +#define AUTHORS \ + proper_name ("Paul Eggert"), \ + proper_name ("David MacKenzie"), \ + proper_name ("Jim Meyering") #ifndef _POSIX_PATH_MAX # define _POSIX_PATH_MAX 256 @@ -70,9 +63,6 @@ static bool validate_file_name (char *, bool, bool); -/* The name this program was run with. */ -char *program_name; - /* For long options that have no equivalent short option, use a non-character as a pseudo short option, starting with CHAR_MAX + 1. */ enum @@ -92,13 +82,12 @@ void usage (int status) { if (status != EXIT_SUCCESS) - fprintf (stderr, _("Try `%s --help' for more information.\n"), - program_name); + emit_try_help (); else { printf (_("Usage: %s [OPTION]... NAME...\n"), program_name); fputs (_("\ -Diagnose unportable constructs in NAME.\n\ +Diagnose invalid or unportable file names.\n\ \n\ -p check for most POSIX systems\n\ -P check for empty names and leading \"-\"\n\ @@ -106,7 +95,7 @@ Diagnose unportable constructs in NAME.\n\ "), stdout); fputs (HELP_OPTION_DESCRIPTION, stdout); fputs (VERSION_OPTION_DESCRIPTION, stdout); - printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT); + emit_ancillary_info (PROGRAM_NAME); } exit (status); } @@ -120,7 +109,7 @@ main (int argc, char **argv) int optc; initialize_main (&argc, &argv); - program_name = argv[0]; + set_program_name (argv[0]); setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); @@ -130,27 +119,27 @@ main (int argc, char **argv) while ((optc = getopt_long (argc, argv, "+pP", longopts, NULL)) != -1) { switch (optc) - { - case PORTABILITY_OPTION: - check_basic_portability = true; - check_extra_portability = true; - break; + { + case PORTABILITY_OPTION: + check_basic_portability = true; + check_extra_portability = true; + break; - case 'p': - check_basic_portability = true; - break; + case 'p': + check_basic_portability = true; + break; - case 'P': - check_extra_portability = true; - break; + case 'P': + check_extra_portability = true; + break; - case_GETOPT_HELP_CHAR; + case_GETOPT_HELP_CHAR; - case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); + case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); - default: - usage (EXIT_FAILURE); - } + default: + usage (EXIT_FAILURE); + } } if (optind == argc) @@ -161,9 +150,9 @@ main (int argc, char **argv) for (; optind < argc; ++optind) ok &= validate_file_name (argv[optind], - check_basic_portability, check_extra_portability); + check_basic_portability, check_extra_portability); - exit (ok ? EXIT_SUCCESS : EXIT_FAILURE); + return ok ? EXIT_SUCCESS : EXIT_FAILURE; } /* If FILE contains a component with a leading "-", report an error @@ -177,9 +166,9 @@ no_leading_hyphen (char const *file) for (p = file; (p = strchr (p, '-')); p++) if (p == file || p[-1] == '/') { - error (0, 0, _("leading `-' in a component of file name %s"), - quote (file)); - return false; + error (0, 0, _("leading '-' in a component of file name %s"), + quoteaf (file)); + return false; } return true; @@ -192,10 +181,10 @@ static bool portable_chars_only (char const *file, size_t filelen) { size_t validlen = strspn (file, - ("/" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789._-")); + ("/" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789._-")); char const *invalid = file + validlen; if (*invalid) @@ -203,10 +192,10 @@ portable_chars_only (char const *file, size_t filelen) 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)); + _("nonportable character %s in file name %s"), + quotearg_n_style_mem (1, locale_quoting_style, invalid, + (charlen <= MB_LEN_MAX ? charlen : 1)), + quoteaf_n (0, file)); return false; } @@ -215,7 +204,7 @@ portable_chars_only (char const *file, size_t filelen) /* Return the address of the start of the next file name component in F. */ -static char * +static char * _GL_ATTRIBUTE_PURE component_start (char *f) { while (*f == '/') @@ -225,7 +214,7 @@ component_start (char *f) /* Return the size of the file name component F. F must be nonempty. */ -static size_t +static size_t _GL_ATTRIBUTE_PURE component_len (char const *f) { size_t len; @@ -256,7 +245,7 @@ component_len (char const *f) static bool validate_file_name (char *file, bool check_basic_portability, - bool check_extra_portability) + bool check_extra_portability) { size_t filelen = strlen (file); @@ -272,13 +261,13 @@ validate_file_name (char *file, bool check_basic_portability, if (check_extra_portability && ! no_leading_hyphen (file)) return false; - if ((check_basic_portability | check_extra_portability) + if ((check_basic_portability || check_extra_portability) && filelen == 0) { /* Fail, since empty names are not portable. As of - 2005-01-06 POSIX does not address whether "pathchk -p ''" - should (or is allowed to) fail, so this is not a - conformance violation. */ + 2005-01-06 POSIX does not address whether "pathchk -p ''" + should (or is allowed to) fail, so this is not a + conformance violation. */ error (0, 0, _("empty file name")); return false; } @@ -286,23 +275,23 @@ validate_file_name (char *file, bool check_basic_portability, if (check_basic_portability) { if (! portable_chars_only (file, filelen)) - return false; + return false; } else { /* Check whether a file name component is in a directory that - is not searchable, or has some other serious problem. - POSIX does not allow "" as a file name, but some non-POSIX - hosts do (as an alias for "."), so allow "" if lstat does. */ + is not searchable, or has some other serious problem. + POSIX does not allow "" as a file name, but some non-POSIX + hosts do (as an alias for "."), so allow "" if lstat does. */ struct stat st; if (lstat (file, &st) == 0) - file_exists = true; + file_exists = true; else if (errno != ENOENT || filelen == 0) - { - error (0, errno, "%s", file); - return false; - } + { + error (0, errno, "%s", quotef (file)); + return false; + } } if (check_basic_portability @@ -311,31 +300,31 @@ validate_file_name (char *file, bool check_basic_portability, size_t maxsize; if (check_basic_portability) - maxsize = _POSIX_PATH_MAX; + maxsize = _POSIX_PATH_MAX; else - { - long int size; - char const *dir = (*file == '/' ? "/" : "."); - errno = 0; - size = pathconf (dir, _PC_PATH_MAX); - if (size < 0 && errno != 0) - { - error (0, errno, - _("%s: unable to determine maximum file name length"), - dir); - return false; - } - maxsize = MIN (size, SIZE_MAX); - } + { + long int size; + char const *dir = (*file == '/' ? "/" : "."); + errno = 0; + size = pathconf (dir, _PC_PATH_MAX); + if (size < 0 && errno != 0) + { + error (0, errno, + _("%s: unable to determine maximum file name length"), + dir); + return false; + } + maxsize = MIN (size, SSIZE_MAX); + } if (maxsize <= filelen) - { - 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; - } + { + 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, quoteaf (file)); + return false; + } } /* Check whether pathconf (..., _PC_NAME_MAX) can be avoided, i.e., @@ -347,17 +336,17 @@ validate_file_name (char *file, bool check_basic_portability, if (! check_component_lengths && ! file_exists) { for (start = file; *(start = component_start (start)); ) - { - size_t length = component_len (start); + { + size_t length = component_len (start); - if (NAME_MAX_MINIMUM < length) - { - check_component_lengths = true; - break; - } + if (NAME_MAX_MINIMUM < length) + { + check_component_lengths = true; + break; + } - start += length; - } + start += length; + } } if (check_component_lengths) @@ -372,61 +361,61 @@ validate_file_name (char *file, bool check_basic_portability, size_t known_name_max = (check_basic_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; - } + { + 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, SSIZE_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", quotef (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; |