summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Youngman <jay@gnu.org>2011-06-13 23:29:50 +0100
committerJames Youngman <jay@gnu.org>2011-06-13 23:54:48 +0100
commitfce18654244a4ad55ed51f5e8adae1db5ff7555b (patch)
treed51f86a09f7aa71b3a894895c389e3c644121e8a
parentb43a69932d4234e3d49cf22d7a756abfc2418132 (diff)
downloadfindutils-fce18654244a4ad55ed51f5e8adae1db5ff7555b.tar.gz
Split strings into fields nondestructively.
* lib/splitstring.c: New file; defines splitstring(), which will non-destructively locate character-separated fields in a string. * lib/splitstring.h: New file; declares splitstring. * lib/test_splitstring.c: New file; unit test for splitstring.c. * lib/nextelem.c: Delete (obsoleted by splitstring.c). * lib/nextelem.h: Delete (obsoleted by splitstring.h). * lib/Makefile.am (libfind_a_SOURCES): Add splitstring.c, splitstring.c. Remove nextelem.c, nextelem.h. (check_PROGRAMS): Add test_splitstring. (TESTS): Add test_splitstring. (test_splitstring_SOURCES): Sources for the test_splitstring unit test. * locate/locate.c: Include splitstring.h rather than nextelem.h. (dolocate): Use splitstring rather than next_element. In places where we need a nul-terminated string, use strndup() to create it. Convert some space-tab sequences to regular spacing. * find/parser.c: Include splitstring.h rather than nextelem.h. (check_path_safety): Use splitstring rather than next_element. * import-gnulib.config (modules): Depend on the module strndup. * cfg.mk: Exempt lib/test_splitstring.c from calling bindtextdomain or set_program_name.
-rw-r--r--ChangeLog25
-rw-r--r--cfg.mk4
-rw-r--r--find/parser.c32
-rw-r--r--import-gnulib.config1
-rw-r--r--lib/Makefile.am14
-rw-r--r--lib/nextelem.c85
-rw-r--r--lib/nextelem.h26
-rw-r--r--lib/splitstring.c60
-rw-r--r--lib/splitstring.h40
-rw-r--r--lib/test_splitstring.c201
-rw-r--r--locate/locate.c1307
11 files changed, 1019 insertions, 776 deletions
diff --git a/ChangeLog b/ChangeLog
index 827ea603..7b2dd521 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,30 @@
2011-06-13 James Youngman <jay@gnu.org>
+ Split strings into fields nondestructively.
+ * lib/splitstring.c: New file; defines splitstring(), which will
+ non-destructively locate character-separated fields in a string.
+ * lib/splitstring.h: New file; declares splitstring.
+ * lib/test_splitstring.c: New file; unit test for splitstring.c.
+ * lib/nextelem.c: Delete (obsoleted by splitstring.c).
+ * lib/nextelem.h: Delete (obsoleted by splitstring.h).
+ * lib/Makefile.am (libfind_a_SOURCES): Add splitstring.c,
+ splitstring.c. Remove nextelem.c, nextelem.h.
+ (check_PROGRAMS): Add test_splitstring.
+ (TESTS): Add test_splitstring.
+ (test_splitstring_SOURCES): Sources for the
+ test_splitstring unit test.
+ * locate/locate.c: Include splitstring.h rather than nextelem.h.
+ (dolocate): Use splitstring rather than next_element. In places
+ where we need a nul-terminated string, use strndup() to create it.
+ Convert some space-tab sequences to regular spacing.
+ * find/parser.c: Include splitstring.h rather than nextelem.h.
+ (check_path_safety): Use splitstring rather than next_element.
+ * import-gnulib.config (modules): Depend on the module strndup.
+ * cfg.mk: Exempt lib/test_splitstring.c from calling
+ bindtextdomain or set_program_name.
+
+2011-06-13 James Youngman <jay@gnu.org>
+
Fix compilation failure in bigram.c by including <locale.h>.
* locate/bigram.c: Include <locale.h>.
diff --git a/cfg.mk b/cfg.mk
index f3018842..121c3372 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -36,13 +36,15 @@ exclude_file_name_regexp--sc_trailing_blank = \
exclude_file_name_regexp--sc_prohibit_empty_lines_at_EOF = \
^(.*/testsuite/.*\.(xo|xi|xe))|COPYING|doc/regexprops\.texi|m4/order-(bad|good)\.bin$$
exclude_file_name_regexp--sc_bindtextdomain = \
- ^lib/regexprops\.c$$
+ ^lib/(regexprops|test_splitstring)\.c$$
exclude_file_name_regexp--sc_prohibit_always_true_header_tests = \
^(build-aux/src-sniff\.py)|ChangeLog$$
exclude_file_name_regexp--sc_prohibit_test_minus_ao = \
^(ChangeLog)|((find|locate|xargs)/testsuite/.*\.exp)$$
exclude_file_name_regexp--sc_prohibit_doubled_word = \
^(xargs/testsuite/xargs\.sysv/iquotes\.xo)|ChangeLog|po/.*\.po$$
+exclude_file_name_regexp--sc_program_name = \
+ ^lib/test_splitstring\.c$$
# sc_texinfo_acronym: perms.texi from coreutils uses @acronym{GNU}.
exclude_file_name_regexp--sc_texinfo_acronym = doc/perm\.texi
diff --git a/find/parser.c b/find/parser.c
index 7b82ae7a..ea676bd6 100644
--- a/find/parser.c
+++ b/find/parser.c
@@ -34,7 +34,6 @@
#include "xalloc.h"
#include "quotearg.h"
#include "buildcmd.h"
-#include "nextelem.h"
#include "regextype.h"
#include "stat-time.h"
#include "xstrtod.h"
@@ -44,6 +43,7 @@
#include "findutils-version.h"
#include "safe-atoi.h"
#include "fdleak.h"
+#include "splitstring.h"
#include <fcntl.h>
@@ -3227,11 +3227,16 @@ make_segment (struct segment **segment,
return &(*segment)->next;
}
+
+
+
static void
check_path_safety (const char *action, char **argv)
{
- char *s;
const char *path = getenv ("PATH");
+ const char *path_separators = ":";
+ size_t pos, len;
+
if (NULL == path)
{
/* $PATH is not set. Assume the OS default is safe.
@@ -3242,34 +3247,35 @@ check_path_safety (const char *action, char **argv)
return;
}
- (void)argv;
-
- s = next_element (path, 1);
- while ((s = next_element ((char *) NULL, 1)) != NULL)
+ splitstring (path, path_separators, true, &pos, &len);
+ do
{
- if (0 == strcmp (s, "."))
+ if (0 == len || (1 == len && path[pos] == '.'))
{
+ /* empty field signifies . */
error (EXIT_FAILURE, 0,
_("The current directory is included in the PATH "
"environment variable, which is insecure in "
"combination with the %s action of find. "
"Please remove the current directory from your "
- "$PATH (that is, remove \".\" or leading or trailing "
- "colons)"),
+ "$PATH (that is, remove \".\", doubled colons, "
+ "or leading or trailing colons)"),
action);
}
- else if ('/' != s[0])
+ else if (path[pos] != '/')
{
- /* Relative paths are also dangerous in $PATH. */
+ char *relpath = strndup (&path[pos], len);
error (EXIT_FAILURE, 0,
_("The relative path %s is included in the PATH "
"environment variable, which is insecure in "
"combination with the %s action of find. "
"Please remove that entry from $PATH"),
- safely_quote_err_filename (0, s),
+ safely_quote_err_filename (0, relpath ? relpath : &path[pos]),
action);
+ /*NOTREACHED*/
+ free (relpath);
}
- }
+ } while (splitstring (path, path_separators, false, &pos, &len));
}
diff --git a/import-gnulib.config b/import-gnulib.config
index 5fb46c21..567d66c5 100644
--- a/import-gnulib.config
+++ b/import-gnulib.config
@@ -132,6 +132,7 @@ strcasestr
strdup-posix
strftime
string
+strndup
strtol
strtoul
strtoull
diff --git a/lib/Makefile.am b/lib/Makefile.am
index f8ff625e..5450e9aa 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -6,7 +6,7 @@ AM_CFLAGS = $(WARN_CFLAGS)
noinst_LIBRARIES = libfind.a
-check_PROGRAMS = regexprops
+check_PROGRAMS = regexprops test_splitstring
check_SCRIPTS = check-regexprops
regexprops_SOURCES = regexprops.c regextype.c
@@ -15,7 +15,7 @@ if CROSS_COMPILING
# The regexprops program needs to be a native executable, so we
# can't build it with a cross-compiler.
else
-TESTS += check-regexprops
+TESTS += check-regexprops test_splitstring
endif
libfind_a_SOURCES = findutils-version.c
@@ -32,11 +32,11 @@ MAINTAINERCLEANFILES =
INCLUDES = -I../gl/lib -I$(top_srcdir)/gl/lib
LDADD = ../gl/lib/libgnulib.a $(LIBINTL)
-libfind_a_SOURCES += nextelem.h printquoted.h listfile.h \
- regextype.h dircallback.h safe-atoi.h
-libfind_a_SOURCES += listfile.c nextelem.c extendbuf.c buildcmd.c savedirinfo.c \
+libfind_a_SOURCES += printquoted.h listfile.h \
+ regextype.h dircallback.h safe-atoi.h splitstring.h
+libfind_a_SOURCES += listfile.c extendbuf.c buildcmd.c savedirinfo.c \
forcefindlib.c qmark.c printquoted.c regextype.c dircallback.c fdleak.c \
- safe-atoi.c
+ safe-atoi.c splitstring.c
EXTRA_DIST += waitpid.c forcefindlib.c
TESTS_ENVIRONMENT = REGEXPROPS=regexprops$(EXEEXT)
@@ -46,3 +46,5 @@ libfind_a_DEPENDENCIES = $(FINDLIBOBJS)
check-regexprops: check-regexprops.sh
cp $(srcdir)/check-regexprops.sh check-regexprops
chmod +x check-regexprops
+
+test_splitstring_SOURCES = test_splitstring.c splitstring.c
diff --git a/lib/nextelem.c b/lib/nextelem.c
deleted file mode 100644
index 3e9246cf..00000000
--- a/lib/nextelem.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Return the next element of a path.
- Copyright (C) 1992, 2005, 2010, 2011 Free Software Foundation, Inc.
-
- 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 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
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- 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, see <http://www.gnu.org/licenses/>.
-*/
-
-/* Written by David MacKenzie <djm@gnu.org>,
- inspired by John P. Rouillard <rouilj@cs.umb.edu>. */
-
-#include <config.h>
-
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-
-#include "nextelem.h"
-
-
-/* Return the next element of a colon-separated path.
- A null entry in the path is equivalent to "." (the current directory).
-
- If NEW_PATH is non-NULL, set the path and return NULL.
- If NEW_PATH is NULL, return the next item in the string, or
- return NULL if there are no more elements. */
-
-char *
-next_element (const char *new_path, int curdir_ok)
-{
- static char *path = NULL; /* Freshly allocated copy of NEW_PATH. */
- static char *end; /* Start of next element to return. */
- static int final_colon; /* If zero, path didn't end with a colon. */
- char *start; /* Start of path element to return. */
-
- if (new_path)
- {
- free (path);
- end = path = strdup (new_path);
- final_colon = 0;
- return NULL;
- }
-
- if (*end == '\0')
- {
- if (final_colon)
- {
- final_colon = 0;
- return curdir_ok ? "." : "";
- }
- return NULL;
- }
-
- start = end;
- final_colon = 1; /* Maybe there will be one. */
-
- end = strchr (start, ':');
- if (end == start)
- {
- /* An empty path element. */
- *end++ = '\0';
- return curdir_ok ? "." : "";
- }
- else if (end == NULL)
- {
- /* The last path element. */
- end = strchr (start, '\0');
- final_colon = 0;
- }
- else
- *end++ = '\0';
-
- return start;
-}
diff --git a/lib/nextelem.h b/lib/nextelem.h
deleted file mode 100644
index 00ffcfef..00000000
--- a/lib/nextelem.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Return the next element of a path.
- Copyright (C) 1992, 2010, 2011 Free Software Foundation, Inc.
-
- 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 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
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- 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, see <http://www.gnu.org/licenses/>.
-*/
-
-/* Written by David MacKenzie <djm@gnu.org>,
- inspired by John P. Rouillard <rouilj@cs.umb.edu>. */
-
-#ifndef INC_NEXTELEM_H
-#define INC_NEXTELEM_H 1
-
-char *next_element (const char *path, int curdir_ok);
-
-#endif
diff --git a/lib/splitstring.c b/lib/splitstring.c
new file mode 100644
index 00000000..e706d9c8
--- /dev/null
+++ b/lib/splitstring.c
@@ -0,0 +1,60 @@
+/* splitstring.c -- split a const string into fields.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+
+ 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 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
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+/*
+ * Written by James Youngman.
+ */
+
+#include <config.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "splitstring.h"
+
+static size_t
+field_length (const char *str, const char *separators)
+{
+ /* if there are no separators, the whole input is one field. */
+ if (*separators)
+ {
+ const char *end = strpbrk (str, separators);
+ if (end)
+ return end - str;
+ }
+ return strlen (str);
+}
+
+
+bool
+splitstring(const char *s, const char *separators, bool first,
+ size_t *pos, size_t *len)
+{
+ if (first)
+ {
+ *pos = 0u;
+ *len = 0u;
+ }
+ else
+ {
+ *pos += *len; /* advance to the next field. */
+ if (s[*pos])
+ ++*pos; /* skip the separator */
+ else
+ return false; /* we reached the end. */
+ }
+ *len = field_length (&s[*pos], separators);
+ return true;
+}
diff --git a/lib/splitstring.h b/lib/splitstring.h
new file mode 100644
index 00000000..c91f7e75
--- /dev/null
+++ b/lib/splitstring.h
@@ -0,0 +1,40 @@
+/* splitstring.h -- split a const string into fields.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+
+ 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 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
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+/*
+ * Written by James Youngman.
+ */
+
+/* Split a string into fields. The string is never modified.
+ *
+ * A false return value indicates that there are no more fields.
+ * Otherwise the next field is at the poisition indicated by *POS and
+ * has length *LEN.
+ *
+ * Set FIRST to true only on the first call for any given value of s.
+ * *POS and *LEN do not need to be initialised in this case.
+ * On subsequent calls, these values should be left at the values
+ * set by the last call.
+ *
+ * Any character in SEPARATORS is taken to be a field separator.
+ * Consecutive field separators are taken to indicate the presence of
+ * an empty field.
+ */
+#include <stdbool.h>
+#include <stddef.h>
+
+bool splitstring(const char *s, const char *separators,
+ bool first, size_t *pos, size_t *len);
diff --git a/lib/test_splitstring.c b/lib/test_splitstring.c
new file mode 100644
index 00000000..9dedb7cb
--- /dev/null
+++ b/lib/test_splitstring.c
@@ -0,0 +1,201 @@
+/* test_splitstring.c -- unit test for splitstring()
+ Copyright (C) 2011 Free Software Foundation, Inc.
+
+ 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 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
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+#include <config.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include "splitstring.h"
+
+static void
+assertEqualFunc(const char *file, int line, const char *label,
+ size_t expected, size_t got)
+{
+ if (expected != got)
+ fprintf(stderr, "%s line %d: %s: expected %lu, got %lu\n",
+ file, line, label, (unsigned long)expected, (unsigned long)got);
+}
+#define ASSERT_EQUAL(expected,got) \
+ do{ \
+ assertEqualFunc(__FILE__,__LINE__,"ASSERT_EQUAL",expected,got); \
+ assert (expected == got); \
+ } while (0);
+
+
+static void
+test_empty (void)
+{
+ size_t len, pos;
+ bool result;
+ const char *empty = "";
+
+ result = splitstring (empty, ":", true, &pos, &len);
+ assert (result);
+ ASSERT_EQUAL (0, pos);
+ ASSERT_EQUAL (0, len);
+ result = splitstring (empty, ":", false, &pos, &len);
+ assert (!result);
+}
+
+static void test_onefield (void)
+{
+ size_t len, pos;
+ bool result;
+ const char *input = "aaa";
+
+ result = splitstring (input, ":", true, &pos, &len);
+ assert (result);
+ ASSERT_EQUAL (0, pos);
+ ASSERT_EQUAL (3, len);
+ result = splitstring (input, ":", false, &pos, &len);
+ assert (!result);
+}
+
+static void test_not_colon (void)
+{
+ size_t len, pos;
+ bool result;
+ const char *separators = "!";
+ const char *input = "aa!b";
+
+ result = splitstring (input, separators, true, &pos, &len);
+ assert (result);
+ ASSERT_EQUAL (0, pos);
+ ASSERT_EQUAL (2, len);
+
+ result = splitstring (input, separators, false, &pos, &len);
+ assert (result);
+ ASSERT_EQUAL (3, pos);
+ ASSERT_EQUAL (1, len);
+
+ result = splitstring (input, separators, false, &pos, &len);
+ assert (!result);
+}
+
+static void test_empty_back (void)
+{
+ size_t len, pos;
+ bool result;
+ const char *input = "aa:";
+
+ result = splitstring (input, ":", true, &pos, &len);
+ assert (result);
+ ASSERT_EQUAL (0, pos);
+ ASSERT_EQUAL (2, len);
+ result = splitstring (input, ":", false, &pos, &len);
+ assert (result);
+ ASSERT_EQUAL (3, pos);
+ ASSERT_EQUAL (0, len);
+ result = splitstring (input, ":", false, &pos, &len);
+ assert (!result);
+}
+
+static void test_empty_front (void)
+{
+ size_t len, pos;
+ bool result;
+ const char *input = ":aaa";
+
+ result = splitstring (input, ":", true, &pos, &len);
+ assert (result);
+ ASSERT_EQUAL (0, pos);
+ ASSERT_EQUAL (0, len);
+ result = splitstring (input, ":", false, &pos, &len);
+ assert (result);
+ ASSERT_EQUAL (1, pos);
+ ASSERT_EQUAL (3, len);
+ result = splitstring (input, ":", false, &pos, &len);
+ assert (!result);
+}
+
+static void test_twofields (void)
+{
+ size_t len, pos;
+ bool result;
+ const char *input = "aaa:bb";
+
+ result = splitstring (input, ":", true, &pos, &len);
+ assert (result);
+ ASSERT_EQUAL (0, pos);
+ ASSERT_EQUAL (3, len);
+ result = splitstring (input, ":", false, &pos, &len);
+ assert (result);
+ ASSERT_EQUAL (4, pos);
+ ASSERT_EQUAL (2, len);
+ result = splitstring (input, ":", false, &pos, &len);
+ assert (!result);
+}
+
+static void test_twoseparators (void)
+{
+ size_t len, pos;
+ bool result;
+ const char *input = "a:bb!c";
+
+ result = splitstring (input, ":!", true, &pos, &len);
+ assert (result);
+ ASSERT_EQUAL (0, pos);
+ ASSERT_EQUAL (1, len);
+ result = splitstring (input, ":!", false, &pos, &len);
+ assert (result);
+ ASSERT_EQUAL (2, pos);
+ ASSERT_EQUAL (2, len);
+ result = splitstring (input, ":!", false, &pos, &len);
+ assert (result);
+ ASSERT_EQUAL (5, pos);
+ ASSERT_EQUAL (1, len);
+ result = splitstring (input, ":!", false, &pos, &len);
+ assert (!result);
+}
+
+static void test_consecutive_empty (void)
+{
+ size_t len, pos;
+ bool result;
+ const char *input = "a::b";
+ const char *separators = ":";
+
+ result = splitstring (input, separators, true, &pos, &len);
+ assert (result);
+ ASSERT_EQUAL (0, pos);
+ ASSERT_EQUAL (1, len);
+
+ result = splitstring (input, separators, false, &pos, &len);
+ assert (result);
+ ASSERT_EQUAL (2, pos);
+ ASSERT_EQUAL (0, len);
+
+ result = splitstring (input, separators, false, &pos, &len);
+ assert (result);
+ ASSERT_EQUAL (3, pos);
+ ASSERT_EQUAL (1, len);
+
+ result = splitstring (input, separators, false, &pos, &len);
+ assert (!result);
+}
+
+int main (int argc, char *argv[])
+{
+ test_empty ();
+ test_onefield ();
+ test_not_colon ();
+ test_empty_back ();
+ test_empty_front ();
+ test_twofields ();
+ test_twoseparators ();
+ test_consecutive_empty ();
+ return 0;
+}
diff --git a/locate/locate.c b/locate/locate.c
index ad7b56ae..42089eeb 100644
--- a/locate/locate.c
+++ b/locate/locate.c
@@ -26,8 +26,8 @@
bigram coded, which reduces space by a further 20-25% and uses the
following encoding of the database bytes:
- 0-28 likeliest differential counts + offset (14) to make nonnegative
- 30 escape code for out-of-range count to follow in next halfword
+ 0-28 likeliest differential counts + offset (14) to make nonnegative
+ 30 escape code for out-of-range count to follow in next halfword
128-255 bigram codes (the 128 most common, as determined by `updatedb')
32-127 single character (printable) ASCII remainder
@@ -64,7 +64,7 @@
#include <signal.h>
#include <ctype.h>
#include <sys/types.h>
-#include <grp.h> /* for setgroups() */
+#include <grp.h> /* for setgroups() */
#include <sys/stat.h>
#include <time.h>
#include <fnmatch.h>
@@ -123,11 +123,11 @@
#include "human.h"
#include "dirname.h"
#include "closeout.h"
-#include "nextelem.h"
#include "regex.h"
#include "quotearg.h"
#include "printquoted.h"
#include "regextype.h"
+#include "splitstring.h"
#include "findutils-version.h"
/* Note that this evaluates Ch many times. */
@@ -157,9 +157,9 @@ enum visit_result
enum ExistenceCheckType
{
- ACCEPT_EITHER, /* Corresponds to lack of -E/-e option */
- ACCEPT_EXISTING, /* Corresponds to option -e */
- ACCEPT_NON_EXISTING /* Corresponds to option -E */
+ ACCEPT_EITHER, /* Corresponds to lack of -E/-e option */
+ ACCEPT_EXISTING, /* Corresponds to option -e */
+ ACCEPT_NON_EXISTING /* Corresponds to option -E */
};
/* Check for existence of files before printing them out? */
@@ -191,7 +191,7 @@ set_max_db_age (const char *s)
if (0 == *s)
{
error (EXIT_FAILURE, 0,
- _("The argument for option --max-database-age must not be empty"));
+ _("The argument for option --max-database-age must not be empty"));
}
@@ -207,15 +207,15 @@ set_max_db_age (const char *s)
(0 == val && EINVAL == errno))
{
error (EXIT_FAILURE, errno,
- _("Invalid argument %s for option --max-database-age"),
- quotearg_n_style (0, locale_quoting_style, s));
+ _("Invalid argument %s for option --max-database-age"),
+ quotearg_n_style (0, locale_quoting_style, s));
}
else if (*end)
{
/* errno wasn't set, don't print its message */
error (EXIT_FAILURE, 0,
- _("Invalid argument %s for option --max-database-age"),
- quotearg_n_style (0, locale_quoting_style, s));
+ _("Invalid argument %s for option --max-database-age"),
+ quotearg_n_style (0, locale_quoting_style, s));
}
else
{
@@ -280,18 +280,18 @@ locate_read_str (char **buf, size_t *siz, FILE *fp, int delimiter, int offs)
needed = offs + nread + 1u;
if (needed > (*siz))
- {
- char *pnew = realloc (*buf, needed);
- if (NULL == pnew)
- {
- return -1; /* FAIL */
- }
- else
- {
- *siz = needed;
- *buf = pnew;
- }
- }
+ {
+ char *pnew = realloc (*buf, needed);
+ if (NULL == pnew)
+ {
+ return -1; /* FAIL */
+ }
+ else
+ {
+ *siz = needed;
+ *buf = pnew;
+ }
+ }
memcpy ((*buf)+offs, p, nread);
free (p);
}
@@ -327,16 +327,16 @@ struct regular_expression
struct process_data
{
- int c; /* An input byte. */
- char itemcount; /* Indicates we're at the beginning of an slocate db. */
+ int c; /* An input byte. */
+ char itemcount; /* Indicates we're at the beginning of an slocate db. */
int count; /* The length of the prefix shared with the previous database entry. */
int len;
- char *original_filename; /* The current input database entry. */
- size_t pathsize; /* Amount allocated for it. */
- char *munged_filename; /* path or basename(path) */
- FILE *fp; /* The pathname database. */
- const char *dbfile; /* Its name, or "<stdin>" */
- int slocatedb_format; /* Allows us to cope with slocate's format variant */
+ char *original_filename; /* The current input database entry. */
+ size_t pathsize; /* Amount allocated for it. */
+ char *munged_filename; /* path or basename(path) */
+ FILE *fp; /* The pathname database. */
+ const char *dbfile; /* Its name, or "<stdin>" */
+ int slocatedb_format; /* Allows us to cope with slocate's format variant */
GetwordEndianState endian_state;
/* for the old database format,
the first and second characters of the most common bigrams. */
@@ -346,7 +346,7 @@ struct process_data
typedef int (*visitfunc)(struct process_data *procdata,
- void *context);
+ void *context);
struct visitor
{
@@ -361,9 +361,9 @@ static struct visitor *lastinspector = NULL;
static struct visitor *past_pat_inspector = NULL;
static inline int visit (const struct visitor *p,
- int accept_flags,
- struct process_data *procdata,
- const struct visitor * const stop)
+ int accept_flags,
+ struct process_data *procdata,
+ const struct visitor * const stop)
{
register int result = accept_flags;
while ( (accept_flags & result) && (stop != p) )
@@ -447,8 +447,8 @@ visit_justprint_quoted (struct process_data *procdata, void *context)
{
(void) context;
print_quoted (stdout, quote_opts, stdout_is_a_tty,
- "%s",
- procdata->original_filename);
+ "%s",
+ procdata->original_filename);
putchar (separator);
return VISIT_CONTINUE;
}
@@ -466,9 +466,9 @@ static void
toolong (struct process_data *procdata)
{
error (EXIT_FAILURE, 0,
- _("locate database %s contains a "
- "filename longer than locate can handle"),
- procdata->dbfile);
+ _("locate database %s contains a "
+ "filename longer than locate can handle"),
+ procdata->dbfile);
}
static void
@@ -483,8 +483,8 @@ extend (struct process_data *procdata, size_t siz1, size_t siz2)
{
procdata->pathsize = siz1+siz2;
procdata->original_filename = x2nrealloc (procdata->original_filename,
- &procdata->pathsize,
- 1);
+ &procdata->pathsize,
+ 1);
}
}
@@ -506,11 +506,11 @@ visit_old_format (struct process_data *procdata, void *context)
procdata->count -= LOCATEDB_OLD_OFFSET;
minval = (0 - procdata->count);
if (procdata->count >= 0)
- maxval = (procdata->len - procdata->count);
+ maxval = (procdata->len - procdata->count);
else
- maxval = (procdata->len - 0);
+ maxval = (procdata->len - 0);
word = getword (procdata->fp, procdata->dbfile,
- minval, maxval, &procdata->endian_state);
+ minval, maxval, &procdata->endian_state);
procdata->count += word;
assert (procdata->count >= 0);
}
@@ -527,22 +527,22 @@ visit_old_format (struct process_data *procdata, void *context)
(procdata->c = getc (procdata->fp)) > LOCATEDB_OLD_ESCAPE;)
{
if (EOF == procdata->c)
- break;
+ break;
if (procdata->c < 0200)
- {
- /* An ordinary character. */
- extend (procdata, i, 1u);
- procdata->original_filename[i++] = procdata->c;
- }
+ {
+ /* An ordinary character. */
+ extend (procdata, i, 1u);
+ procdata->original_filename[i++] = procdata->c;
+ }
else
- {
- /* Bigram markers have the high bit set. */
- extend (procdata, i, 2u);
- procdata->c &= 0177;
- procdata->original_filename[i++] = procdata->bigram1[procdata->c];
- procdata->original_filename[i++] = procdata->bigram2[procdata->c];
- }
+ {
+ /* Bigram markers have the high bit set. */
+ extend (procdata, i, 2u);
+ procdata->c &= 0177;
+ procdata->original_filename[i++] = procdata->bigram1[procdata->c];
+ procdata->original_filename[i++] = procdata->bigram2[procdata->c];
+ }
}
/* Consider the case where we executed the loop body zero times; we
@@ -566,33 +566,33 @@ visit_locate02_format (struct process_data *procdata, void *context)
if (procdata->slocatedb_format)
{
if (procdata->itemcount == 0)
- {
- ungetc (procdata->c, procdata->fp);
- procdata->count = 0;
- procdata->len = 0;
- }
+ {
+ ungetc (procdata->c, procdata->fp);
+ procdata->count = 0;
+ procdata->len = 0;
+ }
else if (procdata->itemcount == 1)
- {
- procdata->count = procdata->len-1;
- }
+ {
+ procdata->count = procdata->len-1;
+ }
else
- {
- if (procdata->c == LOCATEDB_ESCAPE)
- procdata->count += (short)get_short (procdata->fp);
- else if (procdata->c > 127)
- procdata->count += procdata->c - 256;
- else
- procdata->count += procdata->c;
- }
+ {
+ if (procdata->c == LOCATEDB_ESCAPE)
+ procdata->count += (short)get_short (procdata->fp);
+ else if (procdata->c > 127)
+ procdata->count += procdata->c - 256;
+ else
+ procdata->count += procdata->c;
+ }
}
else
{
if (procdata->c == LOCATEDB_ESCAPE)
- procdata->count += (short)get_short (procdata->fp);
+ procdata->count += (short)get_short (procdata->fp);
else if (procdata->c > 127)
- procdata->count += procdata->c - 256;
+ procdata->count += procdata->c - 256;
else
- procdata->count += procdata->c;
+ procdata->count += procdata->c;
}
if (procdata->count > procdata->len || procdata->count < 0)
@@ -602,13 +602,13 @@ visit_locate02_format (struct process_data *procdata, void *context)
* cannot prevent it.
*/
error (EXIT_FAILURE, 0, _("locate database %s is corrupt or invalid"),
- quotearg_n_style (0, locale_quoting_style, procdata->dbfile));
+ quotearg_n_style (0, locale_quoting_style, procdata->dbfile));
}
/* Overlay the old path with the remainder of the new. */
nread = locate_read_str (&procdata->original_filename,
- &procdata->pathsize,
- procdata->fp, 0, procdata->count);
+ &procdata->pathsize,
+ procdata->fp, 0, procdata->count);
if (nread < 0)
return VISIT_ABORT;
procdata->c = getc (procdata->fp);
@@ -624,9 +624,9 @@ visit_locate02_format (struct process_data *procdata, void *context)
{
/* Don't increment indefinitely, it might overflow. */
if (procdata->itemcount < 6)
- {
- ++(procdata->itemcount);
- }
+ {
+ ++(procdata->itemcount);
+ }
}
@@ -807,15 +807,15 @@ visit_regex (struct process_data *procdata, void *context)
const size_t len = strlen (procdata->munged_filename);
int rv = re_search (&p->regex, procdata->munged_filename,
- len, 0, len,
- (struct re_registers *) NULL);
+ len, 0, len,
+ (struct re_registers *) NULL);
if (rv < 0)
{
- return VISIT_REJECTED; /* no match (-1), or internal error (-2) */
+ return VISIT_REJECTED; /* no match (-1), or internal error (-2) */
}
else
{
- return VISIT_ACCEPTED; /* match */
+ return VISIT_ACCEPTED; /* match */
}
}
@@ -835,15 +835,15 @@ visit_stats (struct process_data *procdata, void *context)
for (s=procdata->original_filename; *s; ++s)
{
if ( (int)(*s) & 128 )
- highbit = 1;
+ highbit = 1;
if ('\n' == *s)
- {
- newline = whitespace = 1;
- }
+ {
+ newline = whitespace = 1;
+ }
else if (isspace ((unsigned char)*s))
- {
- whitespace = 1;
- }
+ {
+ whitespace = 1;
+ }
}
if (highbit)
@@ -892,56 +892,56 @@ print_stats (int argc, size_t database_file_size)
char hbuf4[LONGEST_HUMAN_READABLE + 1];
printf (ngettext ("Locate database size: %s byte\n",
- "Locate database size: %s bytes\n",
- database_file_size),
- human_readable ((uintmax_t) database_file_size,
- hbuf1, human_ceiling, 1, 1));
+ "Locate database size: %s bytes\n",
+ database_file_size),
+ human_readable ((uintmax_t) database_file_size,
+ hbuf1, human_ceiling, 1, 1));
printf ( (results_were_filtered ?
- _("Matching Filenames: %s\n") :
- _("All Filenames: %s\n")),
- human_readable (statistics.total_filename_count,
- hbuf1, human_ceiling, 1, 1));
+ _("Matching Filenames: %s\n") :
+ _("All Filenames: %s\n")),
+ human_readable (statistics.total_filename_count,
+ hbuf1, human_ceiling, 1, 1));
/* XXX: We would ideally use ngettext () here, but I don't know
* how to use it to handle more than one possibly-plural thing/
*/
printf (_("File names have a cumulative length of %s bytes.\n"
- "Of those file names,\n"
- "\n\t%s contain whitespace, "
- "\n\t%s contain newline characters, "
- "\n\tand %s contain characters with the high bit set.\n"),
- human_readable (statistics.total_filename_length, hbuf1, human_ceiling, 1, 1),
- human_readable (statistics.whitespace_count, hbuf2, human_ceiling, 1, 1),
- human_readable (statistics.newline_count, hbuf3, human_ceiling, 1, 1),
- human_readable (statistics.highbit_filename_count, hbuf4, human_ceiling, 1, 1));
+ "Of those file names,\n"
+ "\n\t%s contain whitespace, "
+ "\n\t%s contain newline characters, "
+ "\n\tand %s contain characters with the high bit set.\n"),
+ human_readable (statistics.total_filename_length, hbuf1, human_ceiling, 1, 1),
+ human_readable (statistics.whitespace_count, hbuf2, human_ceiling, 1, 1),
+ human_readable (statistics.newline_count, hbuf3, human_ceiling, 1, 1),
+ human_readable (statistics.highbit_filename_count, hbuf4, human_ceiling, 1, 1));
if (!argc)
{
if (results_were_filtered)
- {
- printf (_("Some filenames may have been filtered out, "
- "so we cannot compute the compression ratio.\n"));
- }
+ {
+ printf (_("Some filenames may have been filtered out, "
+ "so we cannot compute the compression ratio.\n"));
+ }
else
- {
- if (statistics.total_filename_length)
- {
- /* A negative compression ratio just means that the
- * compressed database is larger than the list of
- * filenames. This can happen for example for
- * old-format databases containing a small list of short
- * filenames, because the bigram list is 256 bytes.
- */
- printf (_("Compression ratio %4.2f%% (higher is better)\n"),
- 100.0 * ((double)statistics.total_filename_length
- - (double) database_file_size)
- / (double) statistics.total_filename_length);
- }
- else
- {
- printf (_("Compression ratio is undefined\n"));
- }
- }
+ {
+ if (statistics.total_filename_length)
+ {
+ /* A negative compression ratio just means that the
+ * compressed database is larger than the list of
+ * filenames. This can happen for example for
+ * old-format databases containing a small list of short
+ * filenames, because the bigram list is 256 bytes.
+ */
+ printf (_("Compression ratio %4.2f%% (higher is better)\n"),
+ 100.0 * ((double)statistics.total_filename_length
+ - (double) database_file_size)
+ / (double) statistics.total_filename_length);
+ }
+ else
+ {
+ printf (_("Compression ratio is undefined\n"));
+ }
+ }
}
printf ("\n");
}
@@ -956,7 +956,7 @@ looking_at_gnu_locatedb (const char *data, size_t len)
if (len < sizeof (LOCATEDB_MAGIC))
return 0;
else if (0 == memcmp (data, LOCATEDB_MAGIC, sizeof (LOCATEDB_MAGIC)))
- return 1; /* We saw the magic byte sequence */
+ return 1; /* We saw the magic byte sequence */
else
return 0;
}
@@ -967,9 +967,9 @@ looking_at_gnu_locatedb (const char *data, size_t len)
*/
static int
looking_at_slocate_locatedb (const char *filename,
- const char *data,
- size_t len,
- int *seclevel)
+ const char *data,
+ size_t len,
+ int *seclevel)
{
assert (len <= 2);
@@ -981,42 +981,42 @@ looking_at_slocate_locatedb (const char *filename,
{
/* Check that the magic number is a one-byte string */
if (0 == data[1])
- {
- if (isdigit ((unsigned char)data[0]))
- {
- /* looks promising. */
- *seclevel = (data[0] - '0');
-
- if (*seclevel > 1)
- {
- /* Hmm, well it's probably an slocate database
- * of some awsomely huge security level, like 2.
- * We don't know how to handle those.
- */
- error (0, 0,
- _("locate database %s looks like an slocate "
- "database but it seems to have security level %c, "
- "which GNU findutils does not currently support"),
- quotearg_n_style (0, locale_quoting_style, filename),
- data[1]);
- return 1;
- }
- else
- {
- return 1;
- }
- }
- else
- {
- /* Not a digit. */
- return 0;
- }
- }
+ {
+ if (isdigit ((unsigned char)data[0]))
+ {
+ /* looks promising. */
+ *seclevel = (data[0] - '0');
+
+ if (*seclevel > 1)
+ {
+ /* Hmm, well it's probably an slocate database
+ * of some awsomely huge security level, like 2.
+ * We don't know how to handle those.
+ */
+ error (0, 0,
+ _("locate database %s looks like an slocate "
+ "database but it seems to have security level %c, "
+ "which GNU findutils does not currently support"),
+ quotearg_n_style (0, locale_quoting_style, filename),
+ data[1]);
+ return 1;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+ else
+ {
+ /* Not a digit. */
+ return 0;
+ }
+ }
else
- {
- /* Definitely not slocate. */
- return 0;
- }
+ {
+ /* Definitely not slocate. */
+ return 0;
+ }
}
}
@@ -1043,24 +1043,24 @@ i_am_little_endian (void)
static unsigned long
search_one_database (int argc,
- char **argv,
- const char *dbfile,
- FILE *fp,
- off_t filesize,
- int ignore_case,
- int enable_print,
- int basename_only,
- int use_limit,
- struct locate_limits *plimit,
- int stats,
- int op_and,
- int regex,
- int regex_options)
+ char **argv,
+ const char *dbfile,
+ FILE *fp,
+ off_t filesize,
+ int ignore_case,
+ int enable_print,
+ int basename_only,
+ int use_limit,
+ struct locate_limits *plimit,
+ int stats,
+ int op_and,
+ int regex,
+ int regex_options)
{
- char *pathpart; /* A pattern to consider. */
- int argn; /* Index to current pattern in argv. */
- int nread; /* number of bytes read from an entry. */
- struct process_data procdata; /* Storage for data shared with visitors. */
+ char *pathpart; /* A pattern to consider. */
+ int argn; /* Index to current pattern in argv. */
+ int nread; /* number of bytes read from an entry. */
+ struct process_data procdata; /* Storage for data shared with visitors. */
int slocate_seclevel;
int oldformat;
struct visitor* pvis; /* temp for determining past_pat_inspector. */
@@ -1094,68 +1094,68 @@ search_one_database (int argc,
lastinspector = NULL;
past_pat_inspector = NULL;
results_were_filtered = false;
- procdata.pathsize = 128; /* Increased as necessary by locate_read_str. */
+ procdata.pathsize = 128; /* Increased as necessary by locate_read_str. */
procdata.original_filename = xmalloc (procdata.pathsize);
nread = fread (procdata.original_filename, 1, SLOCATE_DB_MAGIC_LEN,
- procdata.fp);
+ procdata.fp);
slocate_seclevel = 0;
if (looking_at_slocate_locatedb (procdata.dbfile,
- procdata.original_filename,
- nread,
- &slocate_seclevel))
+ procdata.original_filename,
+ nread,
+ &slocate_seclevel))
{
error (0, 0,
- _("%s is an slocate database. "
- "Support for these is new, expect problems for now."),
- quotearg_n_style (0, locale_quoting_style, procdata.dbfile));
+ _("%s is an slocate database. "
+ "Support for these is new, expect problems for now."),
+ quotearg_n_style (0, locale_quoting_style, procdata.dbfile));
/* slocate also uses frcode, but with a different header.
* We handle the header here and then work with the data
* in the normal way.
*/
if (slocate_seclevel > 1)
- {
- /* We don't know what those security levels mean,
- * so do nothing further
- */
- error (0, 0,
- _("%s is an slocate database of unsupported security level %d; skipping it."),
- quotearg_n_style (0, locale_quoting_style, procdata.dbfile),
- slocate_seclevel);
- return 0;
- }
+ {
+ /* We don't know what those security levels mean,
+ * so do nothing further
+ */
+ error (0, 0,
+ _("%s is an slocate database of unsupported security level %d; skipping it."),
+ quotearg_n_style (0, locale_quoting_style, procdata.dbfile),
+ slocate_seclevel);
+ return 0;
+ }
else if (slocate_seclevel > 0)
- {
- /* Don't show the filenames to the user if they don't exist.
- * Showing stats is safe since filenames are only counted
- * after the existence check
- */
- if (ACCEPT_NON_EXISTING == check_existence)
- {
- /* Do not allow the user to see a list of filenames that they
- * cannot stat().
- */
- error (0, 0,
- _("You specified the -E option, but that option "
- "cannot be used with slocate-format databases "
- "with a non-zero security level. No results will be "
- "generated for this database.\n"));
- return 0;
- }
- if (ACCEPT_EXISTING != do_check_existence)
- {
- if (enable_print || stats)
- {
- error (0, 0,
- _("%s is an slocate database. "
- "Turning on the '-e' option."),
- quotearg_n_style (0, locale_quoting_style, procdata.dbfile));
- }
- do_check_existence = ACCEPT_EXISTING;
- }
- }
+ {
+ /* Don't show the filenames to the user if they don't exist.
+ * Showing stats is safe since filenames are only counted
+ * after the existence check
+ */
+ if (ACCEPT_NON_EXISTING == check_existence)
+ {
+ /* Do not allow the user to see a list of filenames that they
+ * cannot stat().
+ */
+ error (0, 0,
+ _("You specified the -E option, but that option "
+ "cannot be used with slocate-format databases "
+ "with a non-zero security level. No results will be "
+ "generated for this database.\n"));
+ return 0;
+ }
+ if (ACCEPT_EXISTING != do_check_existence)
+ {
+ if (enable_print || stats)
+ {
+ error (0, 0,
+ _("%s is an slocate database. "
+ "Turning on the '-e' option."),
+ quotearg_n_style (0, locale_quoting_style, procdata.dbfile));
+ }
+ do_check_existence = ACCEPT_EXISTING;
+ }
+ }
add_visitor (visit_locate02_format, NULL);
format_name = "slocate";
procdata.slocatedb_format = 1;
@@ -1167,42 +1167,42 @@ search_one_database (int argc,
procdata.slocatedb_format = 0;
extend (&procdata, sizeof (LOCATEDB_MAGIC), 0u);
nread2 = fread (procdata.original_filename+nread, 1, sizeof (LOCATEDB_MAGIC)-nread,
- procdata.fp);
+ procdata.fp);
if (looking_at_gnu_locatedb (procdata.original_filename, nread+nread2))
- {
- add_visitor (visit_locate02_format, NULL);
- format_name = "GNU LOCATE02";
- }
- else /* Use the old format */
- {
- int i;
-
- nread += nread2;
- extend (&procdata, 256u, 0u);
- /* Read the list of the most common bigrams in the database. */
- if (nread < 256)
- {
- int more_read = fread (procdata.original_filename + nread, 1,
- 256 - nread, procdata.fp);
- if ( (more_read + nread) != 256 )
- {
- error (EXIT_FAILURE, 0,
- _("Old-format locate database %s is "
- "too short to be valid"),
- quotearg_n_style (0, locale_quoting_style, dbfile));
-
- }
- }
-
- for (i = 0; i < 128; i++)
- {
- procdata.bigram1[i] = procdata.original_filename[i << 1];
- procdata.bigram2[i] = procdata.original_filename[(i << 1) + 1];
- }
- format_name = "old";
- oldformat = 1;
- add_visitor (visit_old_format, NULL);
- }
+ {
+ add_visitor (visit_locate02_format, NULL);
+ format_name = "GNU LOCATE02";
+ }
+ else /* Use the old format */
+ {
+ int i;
+
+ nread += nread2;
+ extend (&procdata, 256u, 0u);
+ /* Read the list of the most common bigrams in the database. */
+ if (nread < 256)
+ {
+ int more_read = fread (procdata.original_filename + nread, 1,
+ 256 - nread, procdata.fp);
+ if ( (more_read + nread) != 256 )
+ {
+ error (EXIT_FAILURE, 0,
+ _("Old-format locate database %s is "
+ "too short to be valid"),
+ quotearg_n_style (0, locale_quoting_style, dbfile));
+
+ }
+ }
+
+ for (i = 0; i < 128; i++)
+ {
+ procdata.bigram1[i] = procdata.original_filename[i << 1];
+ procdata.bigram2[i] = procdata.original_filename[(i << 1) + 1];
+ }
+ format_name = "old";
+ oldformat = 1;
+ add_visitor (visit_old_format, NULL);
+ }
}
if (basename_only)
@@ -1214,66 +1214,66 @@ search_one_database (int argc,
results_were_filtered = true;
pathpart = argv[argn];
if (regex)
- {
- struct regular_expression *p = xmalloc (sizeof (*p));
- const char *error_message = NULL;
-
- memset (&p->regex, 0, sizeof (p->regex));
-
- re_set_syntax (regex_options);
- p->regex.allocated = 100;
- p->regex.buffer = xmalloc (p->regex.allocated);
- p->regex.fastmap = NULL;
- p->regex.syntax = regex_options;
- p->regex.translate = NULL;
-
- error_message = re_compile_pattern (pathpart, strlen (pathpart),
- &p->regex);
- if (error_message)
- {
- error (EXIT_FAILURE, 0, "%s", error_message);
- }
- else
- {
- add_visitor (visit_regex, p);
- }
- }
+ {
+ struct regular_expression *p = xmalloc (sizeof (*p));
+ const char *error_message = NULL;
+
+ memset (&p->regex, 0, sizeof (p->regex));
+
+ re_set_syntax (regex_options);
+ p->regex.allocated = 100;
+ p->regex.buffer = xmalloc (p->regex.allocated);
+ p->regex.fastmap = NULL;
+ p->regex.syntax = regex_options;
+ p->regex.translate = NULL;
+
+ error_message = re_compile_pattern (pathpart, strlen (pathpart),
+ &p->regex);
+ if (error_message)
+ {
+ error (EXIT_FAILURE, 0, "%s", error_message);
+ }
+ else
+ {
+ add_visitor (visit_regex, p);
+ }
+ }
else if (contains_metacharacter (pathpart))
- {
- if (ignore_case)
- add_visitor (visit_globmatch_casefold, pathpart);
- else
- add_visitor (visit_globmatch_nofold, pathpart);
- }
+ {
+ if (ignore_case)
+ add_visitor (visit_globmatch_casefold, pathpart);
+ else
+ add_visitor (visit_globmatch_nofold, pathpart);
+ }
else
- {
- /* No glob characters used. Hence we match on
- * _any part_ of the filename, not just the
- * basename. This seems odd to me, but it is the
- * traditional behaviour.
- * James Youngman <jay@gnu.org>
- */
- visitfunc matcher;
- if (1 == MB_CUR_MAX)
- {
- /* As an optimisation, use a strstr () matcher if we are
- * in a unibyte locale. This can give a x2 speedup in
- * the C locale. Some light testing reveals that
- * glibc's strstr () is somewhere around 40% faster than
- * gnulib's, so we just use strstr ().
- */
- matcher = ignore_case ?
- visit_substring_match_casefold_narrow :
- visit_substring_match_nocasefold_narrow;
- }
- else
- {
- matcher = ignore_case ?
- visit_substring_match_casefold_wide :
- visit_substring_match_nocasefold_wide;
- }
- add_visitor (matcher, pathpart);
- }
+ {
+ /* No glob characters used. Hence we match on
+ * _any part_ of the filename, not just the
+ * basename. This seems odd to me, but it is the
+ * traditional behaviour.
+ * James Youngman <jay@gnu.org>
+ */
+ visitfunc matcher;
+ if (1 == MB_CUR_MAX)
+ {
+ /* As an optimisation, use a strstr () matcher if we are
+ * in a unibyte locale. This can give a x2 speedup in
+ * the C locale. Some light testing reveals that
+ * glibc's strstr () is somewhere around 40% faster than
+ * gnulib's, so we just use strstr ().
+ */
+ matcher = ignore_case ?
+ visit_substring_match_casefold_narrow :
+ visit_substring_match_nocasefold_narrow;
+ }
+ else
+ {
+ matcher = ignore_case ?
+ visit_substring_match_casefold_wide :
+ visit_substring_match_nocasefold_wide;
+ }
+ add_visitor (matcher, pathpart);
+ }
}
pvis = lastinspector;
@@ -1284,24 +1284,24 @@ search_one_database (int argc,
switch (do_check_existence)
{
case ACCEPT_EXISTING:
- results_were_filtered = true;
- if (follow_symlinks) /* -L, default */
- add_visitor (visit_existing_follow, NULL);
- else /* -P */
- add_visitor (visit_existing_nofollow, NULL);
- break;
+ results_were_filtered = true;
+ if (follow_symlinks) /* -L, default */
+ add_visitor (visit_existing_follow, NULL);
+ else /* -P */
+ add_visitor (visit_existing_nofollow, NULL);
+ break;
case ACCEPT_NON_EXISTING:
- results_were_filtered = true;
- if (follow_symlinks) /* -L, default */
- add_visitor (visit_non_existing_follow, NULL);
- else /* -P */
- add_visitor (visit_non_existing_nofollow, NULL);
- break;
-
- case ACCEPT_EITHER: /* Default, neither -E nor -e */
- /* do nothing; no extra processing. */
- break;
+ results_were_filtered = true;
+ if (follow_symlinks) /* -L, default */
+ add_visitor (visit_non_existing_follow, NULL);
+ else /* -P */
+ add_visitor (visit_non_existing_nofollow, NULL);
+ break;
+
+ case ACCEPT_EITHER: /* Default, neither -E nor -e */
+ /* do nothing; no extra processing. */
+ break;
}
/* Security issue: The stats visitor must be added immediately
@@ -1314,9 +1314,9 @@ search_one_database (int argc,
if (enable_print)
{
if (print_quoted_filename)
- add_visitor (visit_justprint_quoted, NULL);
+ add_visitor (visit_justprint_quoted, NULL);
else
- add_visitor (visit_justprint_unquoted, NULL);
+ add_visitor (visit_justprint_unquoted, NULL);
}
@@ -1340,8 +1340,8 @@ search_one_database (int argc,
if (stats)
{
printf (_("Database %s is in the %s format.\n"),
- procdata.dbfile,
- format_name);
+ procdata.dbfile,
+ format_name);
}
@@ -1358,35 +1358,35 @@ search_one_database (int argc,
if (stats)
{
if (oldformat)
- {
- int host_little_endian = i_am_little_endian ();
- const char *little = _("The database has little-endian "
- "machine-word encoding.\n");
- const char *big = _("The database has big-endian "
- "machine-word encoding.\n");
-
- if (GetwordEndianStateNative == procdata.endian_state)
- {
- printf ("%s", (host_little_endian ? little : big));
- }
- else if (GetwordEndianStateSwab == procdata.endian_state)
- {
- printf ("%s", (host_little_endian ? big : little));
- }
- else
- {
- printf (_("The database machine-word encoding order "
- "is not obvious.\n"));
- }
- }
+ {
+ int host_little_endian = i_am_little_endian ();
+ const char *little = _("The database has little-endian "
+ "machine-word encoding.\n");
+ const char *big = _("The database has big-endian "
+ "machine-word encoding.\n");
+
+ if (GetwordEndianStateNative == procdata.endian_state)
+ {
+ printf ("%s", (host_little_endian ? little : big));
+ }
+ else if (GetwordEndianStateSwab == procdata.endian_state)
+ {
+ printf ("%s", (host_little_endian ? big : little));
+ }
+ else
+ {
+ printf (_("The database machine-word encoding order "
+ "is not obvious.\n"));
+ }
+ }
if (filesize)
- print_stats (argc, filesize);
+ print_stats (argc, filesize);
}
if (ferror (procdata.fp))
{
error (0, errno, "%s",
- quotearg_n_style (0, locale_quoting_style, procdata.dbfile));
+ quotearg_n_style (0, locale_quoting_style, procdata.dbfile));
return 0;
}
return plimit->items_accepted;
@@ -1406,7 +1406,7 @@ Usage: %s [-d path | --database=path] [-e | -E | --[non-]existing]\n\
[-A | --all] [-p | --print] [-r | --regex] [--regextype=TYPE]\n\
[--max-database-age D] [--version] [--help]\n\
pattern...\n"),
- program_name);
+ program_name);
fputs (_("\nReport bugs to <bug-findutils@gnu.org>.\n"), stream);
}
enum
@@ -1460,10 +1460,10 @@ drop_privs (void)
gid_t groups[1];
groups[0] = gid;
if (0 != setgroups (1u, groups))
- {
- what = _("failed to drop group privileges");
- goto fail;
- }
+ {
+ what = _("failed to drop group privileges");
+ goto fail;
+ }
}
#endif
@@ -1471,40 +1471,40 @@ drop_privs (void)
if (uid != orig_euid)
{
if (0 == uid)
- {
- /* We're really root anyway, but are setuid to something else. Leave it. */
- }
+ {
+ /* We're really root anyway, but are setuid to something else. Leave it. */
+ }
else
- {
- errno = 0;
- if (0 != setuid (getuid ()))
- {
- what = _("failed to drop setuid privileges");
- goto fail;
- }
-
- /* Defend against the case where the attacker runs us with the
- * capability to call setuid () turned off, which on some systems
- * will cause the above attempt to drop privileges fail (leaving us
- * privileged).
- */
- else
- {
- /* Check that we can no longer switch bask to root */
- if (0 == setuid (0))
- {
- what = _("Failed to fully drop privileges");
- /* The errno value here is not interesting (since
- * the system call we are complaining about
- * succeeded when we wanted it to fail). Arrange
- * for the call to error () not to print the errno
- * value by setting errno=0.
- */
- errno = 0;
- goto fail;
- }
- }
- }
+ {
+ errno = 0;
+ if (0 != setuid (getuid ()))
+ {
+ what = _("failed to drop setuid privileges");
+ goto fail;
+ }
+
+ /* Defend against the case where the attacker runs us with the
+ * capability to call setuid () turned off, which on some systems
+ * will cause the above attempt to drop privileges fail (leaving us
+ * privileged).
+ */
+ else
+ {
+ /* Check that we can no longer switch bask to root */
+ if (0 == setuid (0))
+ {
+ what = _("Failed to fully drop privileges");
+ /* The errno value here is not interesting (since
+ * the system call we are complaining about
+ * succeeded when we wanted it to fail). Arrange
+ * for the call to error () not to print the errno
+ * value by setting errno=0.
+ */
+ errno = 0;
+ goto fail;
+ }
+ }
+ }
}
/* Drop any setgid privileges */
@@ -1520,7 +1520,7 @@ drop_privs (void)
fail:
error (EXIT_FAILURE, errno, "%s",
- quotearg_n_style (0, locale_quoting_style, what));
+ quotearg_n_style (0, locale_quoting_style, what));
abort ();
kill (0, SIGKILL);
_exit (1);
@@ -1537,17 +1537,17 @@ opendb (const char *name)
{
int fd = open (name, O_RDONLY
#if defined O_LARGEFILE
- |O_LARGEFILE
+ |O_LARGEFILE
#endif
- );
+ );
if (fd >= 0)
{
/* Make sure it won't survive an exec */
if (0 != fcntl (fd, F_SETFD, FD_CLOEXEC))
- {
- close (fd);
- fd = -1;
- }
+ {
+ close (fd);
+ fd = -1;
+ }
}
return fd;
}
@@ -1555,7 +1555,11 @@ opendb (const char *name)
int
dolocate (int argc, char **argv, int secure_db_fd)
{
- char *dbpath;
+ char *path_element;
+ size_t path_element_pos, path_element_len;
+ const char *locate_path;
+ const char *db_name;
+ const char *path_separators = ":";
unsigned long int found = 0uL;
int ignore_case = 0;
int print = 0;
@@ -1569,7 +1573,7 @@ dolocate (int argc, char **argv, int secure_db_fd)
const char *e;
FILE *fp;
int they_chose_db = 0;
- bool did_stdin = false; /* Set to prevent rereading stdin. */
+ bool did_stdin = false; /* Set to prevent rereading stdin. */
if (argv[0])
set_program_name (argv[0]);
@@ -1593,11 +1597,9 @@ dolocate (int argc, char **argv, int secure_db_fd)
* setuid-access-controlled database,, since that could cause a leak
* of private data.
*/
- dbpath = getenv ("LOCATE_PATH");
- if (dbpath)
- {
- they_chose_db = 1;
- }
+ locate_path = getenv ("LOCATE_PATH");
+ if (locate_path)
+ they_chose_db = 1;
check_existence = ACCEPT_EITHER;
@@ -1605,115 +1607,115 @@ dolocate (int argc, char **argv, int secure_db_fd)
{
int opti = -1;
int optc = getopt_long (argc, argv, "Abcd:eEil:prsm0SwHPL", longopts,
- &opti);
+ &opti);
if (optc == -1)
- break;
+ break;
switch (optc)
- {
- case '0':
- separator = 0;
- print_quoted_filename = false; /* print filename 'raw'. */
- break;
-
- case 'A':
- op_and = 1;
- break;
-
- case 'b':
- basename_only = 1;
- break;
-
- case 'c':
- just_count = 1;
- break;
-
- case 'd':
- dbpath = optarg;
- they_chose_db = 1;
- break;
-
- case 'e':
- check_existence = ACCEPT_EXISTING;
- break;
-
- case 'E':
- check_existence = ACCEPT_NON_EXISTING;
- break;
-
- case 'i':
- ignore_case = 1;
- break;
-
- case 'h':
- usage (stdout);
- return 0;
-
- case MAX_DB_AGE:
- /* XXX: nothing in the test suite for this option. */
- set_max_db_age (optarg);
- break;
-
- case 'p':
- print = 1;
- break;
-
- case 'v':
- display_findutils_version ("locate");
- return 0;
-
- case 'w':
- basename_only = 0;
- break;
-
- case 'r':
- regex = 1;
- break;
-
- case REGEXTYPE_OPTION:
- regex_options = get_regex_type (optarg);
- break;
-
- case 'S':
- stats = 1;
- break;
-
- case 'L':
- follow_symlinks = 1;
- break;
-
- /* In find, -P and -H differ in the way they handle paths
- * given on the command line. This is not relevant for
- * locate, but the -H option is supported because it is
- * probably more intuitive to do so.
- */
- case 'P':
- case 'H':
- follow_symlinks = 0;
- break;
-
- case 'l':
- {
- char *end = optarg;
- strtol_error err = xstrtoumax (optarg, &end, 10, &limits.limit,
- NULL);
- if (LONGINT_OK != err)
- xstrtol_fatal (err, opti, optc, longopts, optarg);
- use_limit = 1;
- }
- break;
-
- case 's': /* use stdio */
- case 'm': /* use mmap */
- /* These options are implemented simply for
- * compatibility with FreeBSD
- */
- break;
-
- default:
- usage (stderr);
- return 1;
- }
+ {
+ case '0':
+ separator = 0;
+ print_quoted_filename = false; /* print filename 'raw'. */
+ break;
+
+ case 'A':
+ op_and = 1;
+ break;
+
+ case 'b':
+ basename_only = 1;
+ break;
+
+ case 'c':
+ just_count = 1;
+ break;
+
+ case 'd':
+ locate_path = optarg;
+ they_chose_db = 1;
+ break;
+
+ case 'e':
+ check_existence = ACCEPT_EXISTING;
+ break;
+
+ case 'E':
+ check_existence = ACCEPT_NON_EXISTING;
+ break;
+
+ case 'i':
+ ignore_case = 1;
+ break;
+
+ case 'h':
+ usage (stdout);
+ return 0;
+
+ case MAX_DB_AGE:
+ /* XXX: nothing in the test suite for this option. */
+ set_max_db_age (optarg);
+ break;
+
+ case 'p':
+ print = 1;
+ break;
+
+ case 'v':
+ display_findutils_version ("locate");
+ return 0;
+
+ case 'w':
+ basename_only = 0;
+ break;
+
+ case 'r':
+ regex = 1;
+ break;
+
+ case REGEXTYPE_OPTION:
+ regex_options = get_regex_type (optarg);
+ break;
+
+ case 'S':
+ stats = 1;
+ break;
+
+ case 'L':
+ follow_symlinks = 1;
+ break;
+
+ /* In find, -P and -H differ in the way they handle paths
+ * given on the command line. This is not relevant for
+ * locate, but the -H option is supported because it is
+ * probably more intuitive to do so.
+ */
+ case 'P':
+ case 'H':
+ follow_symlinks = 0;
+ break;
+
+ case 'l':
+ {
+ char *end = optarg;
+ strtol_error err = xstrtoumax (optarg, &end, 10, &limits.limit,
+ NULL);
+ if (LONGINT_OK != err)
+ xstrtol_fatal (err, opti, optc, longopts, optarg);
+ use_limit = 1;
+ }
+ break;
+
+ case 's': /* use stdio */
+ case 'm': /* use mmap */
+ /* These options are implemented simply for
+ * compatibility with FreeBSD
+ */
+ break;
+
+ default:
+ usage (stderr);
+ return 1;
+ }
}
@@ -1723,10 +1725,10 @@ dolocate (int argc, char **argv, int secure_db_fd)
if (they_chose_db)
{
if (secure_db_fd >= 0)
- {
- close (secure_db_fd);
- secure_db_fd = -1;
- }
+ {
+ close (secure_db_fd);
+ secure_db_fd = -1;
+ }
}
if (!just_count && !stats)
@@ -1735,15 +1737,15 @@ dolocate (int argc, char **argv, int secure_db_fd)
if (stats)
{
if (optind == argc)
- use_limit = 0;
+ use_limit = 0;
}
else
{
if (!just_count && optind == argc)
- {
- usage (stderr);
- return 1;
- }
+ {
+ usage (stderr);
+ return 1;
+ }
}
@@ -1753,7 +1755,8 @@ dolocate (int argc, char **argv, int secure_db_fd)
stdout_is_a_tty = false;
if (they_chose_db)
- next_element (dbpath, 0); /* Initialize. */
+ splitstring (locate_path, path_separators, true,
+ &path_element_pos, &path_element_len);
/* Bail out early if limit already reached. */
while (!use_limit || limits.limit > limits.items_accepted)
@@ -1770,120 +1773,134 @@ dolocate (int argc, char **argv, int secure_db_fd)
statistics.highbit_filename_count = 0u;
if (they_chose_db)
- {
- /* Take the next element from the list of databases */
- e = next_element ((char *) NULL, 0);
- if (NULL == e)
- break;
-
- if (0 == strcmp (e, "-"))
- {
- if (did_stdin)
- {
- error (0, 0,
- _("warning: the locate database can only be read from stdin once."));
- return 0;
- }
- else
- {
- e = "<stdin>";
- fd = 0;
- did_stdin = true;
- }
- }
- else
- {
- if (0 == strlen (e) || 0 == strcmp (e, "."))
- {
- e = LOCATE_DB;
- }
-
- /* open the database */
- fd = opendb (e);
- if (fd < 0)
- {
- error (0, errno, "%s",
- quotearg_n_style (0, locale_quoting_style, e));
- return 0;
- }
- }
- }
+ {
+ /* Take the next element from the list of databases */
+ if (1 == path_element_len && '-' == locate_path[path_element_pos])
+ {
+ if (did_stdin)
+ {
+ error (0, 0,
+ _("warning: the locate database can only be read from stdin once."));
+ return 0;
+ }
+ else
+ {
+ e = "<stdin>";
+ fd = 0;
+ did_stdin = true;
+ }
+ }
+ else
+ {
+ if (0 == path_element_len
+ || (1 == path_element_len
+ && '.' == locate_path[path_element_pos]))
+ {
+ db_name = LOCATE_DB;
+ }
+ else
+ {
+ path_element = strndup (&locate_path[path_element_pos],
+ path_element_len);
+ db_name = path_element;
+ }
+
+ /* open the database */
+ fd = opendb (db_name);
+ if (fd < 0)
+ {
+ error (0, errno, "%s",
+ quotearg_n_style (0, locale_quoting_style, db_name));
+ return 0;
+ }
+ }
+ }
else
- {
- if (-1 == secure_db_fd)
- {
- /* Already searched the database, it's time to exit the loop */
- break;
- }
- else
- {
- e = selected_secure_db;
- fd = secure_db_fd;
- secure_db_fd = -1;
- }
- }
+ {
+ if (-1 == secure_db_fd)
+ {
+ /* Already searched the database, it's time to exit the loop */
+ break;
+ }
+ else
+ {
+ db_name = selected_secure_db;
+ fd = secure_db_fd;
+ secure_db_fd = -1;
+ }
+ }
/* Check the database to see if it is old. */
if (fstat (fd, &st))
- {
- error (0, errno, "%s",
- quotearg_n_style (0, locale_quoting_style, e));
- /* continue anyway */
- filesize = (off_t)0;
- }
+ {
+ error (0, errno, "%s",
+ quotearg_n_style (0, locale_quoting_style, db_name));
+ /* continue anyway */
+ filesize = (off_t)0;
+ }
else
- {
- time_t now;
-
- filesize = st.st_size;
-
- if ((time_t)-1 == time (&now))
- {
- /* If we can't tell the time, we don't know how old the
- * database is. But since the message is just advisory,
- * we continue anyway.
- */
- error (0, errno, _("time system call failed"));
- }
- else
- {
- double age = difftime (now, st.st_mtime);
- double warn_seconds = SECONDS_PER_UNIT * warn_number_units;
- if (age > warn_seconds)
- {
- /* For example:
- warning: database `fred' is more than 8 days old (actual age is 10 days)*/
- error (0, 0,
- _("warning: database %s is more than %d %s old (actual age is %.1f %s)"),
- quotearg_n_style (0, locale_quoting_style, e),
- warn_number_units, _(warn_name_units),
- (age/(double)SECONDS_PER_UNIT), _(warn_name_units));
- }
- }
- }
+ {
+ time_t now;
+
+ filesize = st.st_size;
+
+ if ((time_t)-1 == time (&now))
+ {
+ /* If we can't tell the time, we don't know how old the
+ * database is. But since the message is just advisory,
+ * we continue anyway.
+ */
+ error (0, errno, _("time system call failed"));
+ }
+ else
+ {
+ double age = difftime (now, st.st_mtime);
+ double warn_seconds = SECONDS_PER_UNIT * warn_number_units;
+ if (age > warn_seconds)
+ {
+ /* For example:
+ warning: database `fred' is more than 8 days old (actual age is 10 days)*/
+ error (0, 0,
+ _("warning: database %s is more than %d %s old (actual age is %.1f %s)"),
+ quotearg_n_style (0, locale_quoting_style, db_name),
+ warn_number_units, _(warn_name_units),
+ (age/(double)SECONDS_PER_UNIT), _(warn_name_units));
+ }
+ }
+ }
fp = fdopen (fd, "r");
if (NULL == fp)
- {
- error (0, errno, "%s",
- quotearg_n_style (0, locale_quoting_style, e));
- return 0;
- }
+ {
+ error (0, errno, "%s",
+ quotearg_n_style (0, locale_quoting_style, db_name));
+ return 0;
+ }
/* Search this database for all patterns simultaneously */
found = search_one_database (argc - optind, &argv[optind],
- e, fp, filesize,
- ignore_case, print, basename_only,
- use_limit, &limits, stats,
- op_and, regex, regex_options);
+ e, fp, filesize,
+ ignore_case, print, basename_only,
+ use_limit, &limits, stats,
+ op_and, regex, regex_options);
/* Close the databsase (even if it is stdin) */
if (fclose (fp) == EOF)
- {
- error (0, errno, "%s",
- quotearg_n_style (0, locale_quoting_style, e));
- return 0;
- }
+ {
+ error (0, errno, "%s",
+ quotearg_n_style (0, locale_quoting_style, db_name));
+ return 0;
+ }
+ if (path_element)
+ {
+ free (path_element);
+ path_element = NULL;
+ }
+ if (!splitstring (locate_path, path_separators, false,
+ &path_element_pos, &path_element_len))
+ {
+ break;
+ }
}
if (just_count)
@@ -1913,10 +1930,10 @@ open_secure_db (void)
{
fd = opendb (secure_db_list[i]);
if (fd >= 0)
- {
- selected_secure_db = secure_db_list[i];
- return fd;
- }
+ {
+ selected_secure_db = secure_db_list[i];
+ return fd;
+ }
}
return -1;
}