summaryrefslogtreecommitdiff
path: root/src/pathchk.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pathchk.c')
-rw-r--r--src/pathchk.c303
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;