Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
7193b676ef | ||
|
89e5e78ea6 | ||
|
dc337378c1 | ||
|
6c45934950 | ||
|
6848c7e31b | ||
|
2b969d355f | ||
|
685e8366e3 | ||
|
ca73160123 | ||
|
0f19737980 | ||
|
723ddb7a97 | ||
|
11088d0573 |
0
.cvsignore → .gitignore
vendored
0
.cvsignore → .gitignore
vendored
21
Makefile
21
Makefile
@ -1,21 +0,0 @@
|
|||||||
# Makefile for source rpm: findutils
|
|
||||||
# $Id: Makefile,v 1.1 2004/09/09 04:42:40 cvsdist Exp $
|
|
||||||
NAME := findutils
|
|
||||||
SPECFILE = $(firstword $(wildcard *.spec))
|
|
||||||
|
|
||||||
define find-makefile-common
|
|
||||||
for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done
|
|
||||||
endef
|
|
||||||
|
|
||||||
MAKEFILE_COMMON := $(shell $(find-makefile-common))
|
|
||||||
|
|
||||||
ifeq ($(MAKEFILE_COMMON),)
|
|
||||||
# attempt a checkout
|
|
||||||
define checkout-makefile-common
|
|
||||||
test -f CVS/Root && { cvs -Q -d $$(cat CVS/Root) checkout common && echo "common/Makefile.common" ; } || { echo "ERROR: I can't figure out how to checkout the 'common' module." ; exit -1 ; } >&2
|
|
||||||
endef
|
|
||||||
|
|
||||||
MAKEFILE_COMMON := $(shell $(checkout-makefile-common))
|
|
||||||
endif
|
|
||||||
|
|
||||||
include $(MAKEFILE_COMMON)
|
|
@ -10,15 +10,3 @@ diff -up findutils-4.4.2/Makefile.am_old findutils-4.4.2/Makefile.am
|
|||||||
|
|
||||||
ACLOCAL_AMFLAGS = -I gnulib/m4 -I m4
|
ACLOCAL_AMFLAGS = -I gnulib/m4 -I m4
|
||||||
|
|
||||||
diff -up findutils-4.4.2/Makefile.in_old findutils-4.4.2/Makefile.in
|
|
||||||
--- findutils-4.4.2/Makefile.in_old 2009-06-30 14:54:00.000000000 +0200
|
|
||||||
+++ findutils-4.4.2/Makefile.in 2009-06-30 14:54:35.000000000 +0200
|
|
||||||
@@ -607,7 +607,7 @@ EXTRA_DIST = COPYING ChangeLog TODO conf
|
|
||||||
DISTCLEANFILES = tool-versions.txt
|
|
||||||
|
|
||||||
# "tests" is the gnulib unit test dir.
|
|
||||||
-SUBDIRS = gnulib tests build-aux lib find xargs locate doc po m4
|
|
||||||
+SUBDIRS = gnulib tests build-aux lib find xargs doc po m4
|
|
||||||
ACLOCAL_AMFLAGS = -I gnulib/m4 -I m4
|
|
||||||
TESTFILE_SUFFIXES = .exp .xo .xe .xi
|
|
||||||
all: config.h
|
|
||||||
|
@ -1,517 +0,0 @@
|
|||||||
diff -up findutils-4.4.2/configure.ac_old findutils-4.4.2/configure.ac
|
|
||||||
--- findutils-4.4.2/configure.ac_old 2009-07-01 10:24:04.000000000 +0200
|
|
||||||
+++ findutils-4.4.2/configure.ac 2009-07-01 10:24:46.000000000 +0200
|
|
||||||
@@ -114,6 +114,16 @@ AC_CHECK_LIB([m],[fabs],[FINDLIBS="-lm $
|
|
||||||
AC_DEFINE_UNQUOTED(HAVE_FABS_IN_LIBM,1,[fabs is defined in -lm]))
|
|
||||||
AC_SUBST([FINDLIBS])
|
|
||||||
|
|
||||||
+AC_ARG_WITH([selinux],
|
|
||||||
+ AS_HELP_STRING([--without-selinux], [disable SELinux support]),
|
|
||||||
+ [:],
|
|
||||||
+[AC_CHECK_LIB([selinux], [is_selinux_enabled],
|
|
||||||
+ [with_selinux=yes], [with_selinux=no])])
|
|
||||||
+if test x$with_selinux != xno; then
|
|
||||||
+ AC_DEFINE([WITH_SELINUX], [1], [Define to support SELinux])
|
|
||||||
+ AC_SUBST([LIBSELINUX], [-lselinux])
|
|
||||||
+fi
|
|
||||||
+
|
|
||||||
dnl Checks for header files.
|
|
||||||
AC_HEADER_STDC
|
|
||||||
dnl Assume unistd.h is present - coreutils does too.
|
|
||||||
diff -up findutils-4.4.2/doc/find.texi_old findutils-4.4.2/doc/find.texi
|
|
||||||
--- findutils-4.4.2/doc/find.texi_old 2009-07-01 10:25:09.000000000 +0200
|
|
||||||
+++ findutils-4.4.2/doc/find.texi 2009-07-01 10:26:37.000000000 +0200
|
|
||||||
@@ -7,7 +7,6 @@
|
|
||||||
@c %**end of header
|
|
||||||
|
|
||||||
@include version.texi
|
|
||||||
-@include ../locate/dblocation.texi
|
|
||||||
|
|
||||||
@iftex
|
|
||||||
@finalout
|
|
||||||
@@ -1242,6 +1241,14 @@ situation.
|
|
||||||
|
|
||||||
@end deffn
|
|
||||||
|
|
||||||
+@deffn Test -context pattern
|
|
||||||
+True if file's SELinux context matches the pattern @var{pattern}.
|
|
||||||
+The pattern uses shell glob matching.
|
|
||||||
+
|
|
||||||
+This predicate is supported only on @code{find} versions compiled with
|
|
||||||
+SELinux support and only when SELinux is enabled.
|
|
||||||
+@end deffn
|
|
||||||
+
|
|
||||||
@node Contents
|
|
||||||
@section Contents
|
|
||||||
|
|
||||||
@@ -1826,6 +1833,9 @@ value used for BLOCKSIZE is system-depen
|
|
||||||
bytes. If the file size is zero, the value printed is undefined. On
|
|
||||||
systems which lack support for st_blocks, a file's sparseness is
|
|
||||||
assumed to be 1.0.
|
|
||||||
+@item %Z
|
|
||||||
+File's SELinux context, or empty string if the file has no SELinux context
|
|
||||||
+or this version of find does not support SELinux.
|
|
||||||
@end table
|
|
||||||
|
|
||||||
@node Location Directives
|
|
||||||
diff -up findutils-4.4.2/find/defs.h_old findutils-4.4.2/find/defs.h
|
|
||||||
--- findutils-4.4.2/find/defs.h_old 2009-07-01 12:38:32.000000000 +0200
|
|
||||||
+++ findutils-4.4.2/find/defs.h 2009-07-01 12:52:47.000000000 +0200
|
|
||||||
@@ -91,6 +91,9 @@ int get_statinfo PARAMS((const char *pat
|
|
||||||
#define MODE_RWX (S_IXUSR | S_IXGRP | S_IXOTH | MODE_RW)
|
|
||||||
#define MODE_ALL (S_ISUID | S_ISGID | S_ISVTX | MODE_RWX)
|
|
||||||
|
|
||||||
+#ifdef WITH_SELINUX
|
|
||||||
+#include <selinux/selinux.h>
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
struct predicate;
|
|
||||||
struct options;
|
|
||||||
@@ -315,6 +318,9 @@ struct predicate
|
|
||||||
struct samefile_file_id samefileid; /* samefile */
|
|
||||||
mode_t type; /* type */
|
|
||||||
struct format_val printf_vec; /* printf fprintf fprint ls fls print0 fprint0 print */
|
|
||||||
+#ifdef WITH_SELINUX
|
|
||||||
+ security_context_t scontext; /* scontext */
|
|
||||||
+#endif
|
|
||||||
} args;
|
|
||||||
|
|
||||||
/* The next predicate in the user input sequence,
|
|
||||||
@@ -459,6 +465,9 @@ PREDICATEFUNCTION pred_used;
|
|
||||||
PREDICATEFUNCTION pred_user;
|
|
||||||
PREDICATEFUNCTION pred_writable;
|
|
||||||
PREDICATEFUNCTION pred_xtype;
|
|
||||||
+#ifdef WITH_SELINUX
|
|
||||||
+PREDICATEFUNCTION pred_context;
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -601,6 +610,10 @@ struct options
|
|
||||||
*/
|
|
||||||
int regex_options;
|
|
||||||
|
|
||||||
+#ifdef WITH_SELINUX
|
|
||||||
+ int (*x_getfilecon) ();
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
/* Optimisation level. One is the default.
|
|
||||||
*/
|
|
||||||
unsigned short optimisation_level;
|
|
||||||
diff -up findutils-4.4.2/find/find.1_old findutils-4.4.2/find/find.1
|
|
||||||
--- findutils-4.4.2/find/find.1_old 2009-07-01 10:30:04.000000000 +0200
|
|
||||||
+++ findutils-4.4.2/find/find.1 2009-07-01 10:30:59.000000000 +0200
|
|
||||||
@@ -933,6 +933,8 @@ if \fIc\fR is `l'. In other words, for
|
|
||||||
checks the type of the file that
|
|
||||||
.B \-type
|
|
||||||
does not check.
|
|
||||||
+.IP "\-context \fIpattern\fR"
|
|
||||||
+(SELinux only) Security context of the file matches glob \fIpattern\fR.
|
|
||||||
|
|
||||||
.SS ACTIONS
|
|
||||||
.IP "\-delete\fR"
|
|
||||||
@@ -1354,6 +1356,8 @@ File's type (like in
|
|
||||||
U=unknown type (shouldn't happen)
|
|
||||||
.IP %Y
|
|
||||||
File's type (like %y), plus follow symlinks: L=loop, N=nonexistent
|
|
||||||
+.IP %Z
|
|
||||||
+(SELinux only) file's security context.
|
|
||||||
.PP
|
|
||||||
A `%' character followed by any other character is discarded, but the
|
|
||||||
other character is printed (don't rely on this, as further format
|
|
||||||
diff -up findutils-4.4.2/find/find.c_old findutils-4.4.2/find/find.c
|
|
||||||
--- findutils-4.4.2/find/find.c_old 2009-07-01 10:26:53.000000000 +0200
|
|
||||||
+++ findutils-4.4.2/find/find.c 2009-07-01 10:29:52.000000000 +0200
|
|
||||||
@@ -120,6 +120,36 @@ int get_current_dirfd(void)
|
|
||||||
return AT_FDCWD;
|
|
||||||
}
|
|
||||||
|
|
||||||
+#ifdef WITH_SELINUX
|
|
||||||
+static int
|
|
||||||
+fallback_getfilecon(const char *name, security_context_t *p, int prev_rv)
|
|
||||||
+{
|
|
||||||
+ /* Our original getfilecon() call failed. Perhaps we can't follow a
|
|
||||||
+ * symbolic link. If that might be the problem, lgetfilecon() the link.
|
|
||||||
+ * Otherwise, admit defeat.
|
|
||||||
+ */
|
|
||||||
+ switch (errno)
|
|
||||||
+ {
|
|
||||||
+ case ENOENT:
|
|
||||||
+ case ENOTDIR:
|
|
||||||
+#ifdef DEBUG_STAT
|
|
||||||
+ fprintf(stderr, "fallback_getfilecon(): getfilecon(%s) failed; falling back on lgetfilecon()\n", name);
|
|
||||||
+#endif
|
|
||||||
+ return lgetfilecon(name, p);
|
|
||||||
+
|
|
||||||
+ case EACCES:
|
|
||||||
+ case EIO:
|
|
||||||
+ case ELOOP:
|
|
||||||
+ case ENAMETOOLONG:
|
|
||||||
+#ifdef EOVERFLOW
|
|
||||||
+ case EOVERFLOW: /* EOVERFLOW is not #defined on UNICOS. */
|
|
||||||
+#endif
|
|
||||||
+ default:
|
|
||||||
+ return prev_rv;
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+#endif /* WITH_SELINUX */
|
|
||||||
+
|
|
||||||
|
|
||||||
int
|
|
||||||
main (int argc, char **argv)
|
|
||||||
@@ -1270,7 +1300,7 @@ process_path (char *pathname, char *name
|
|
||||||
static void
|
|
||||||
process_dir (char *pathname, char *name, int pathlen, const struct stat *statp, char *parent)
|
|
||||||
{
|
|
||||||
- int subdirs_left; /* Number of unexamined subdirs in PATHNAME. */
|
|
||||||
+ int subdirs_left = 0; /* Number of unexamined subdirs in PATHNAME. */
|
|
||||||
boolean subdirs_unreliable; /* if true, cannot use dir link count as subdir limif (if false, it may STILL be unreliable) */
|
|
||||||
unsigned int idx; /* Which entry are we on? */
|
|
||||||
struct stat stat_buf;
|
|
||||||
diff -up findutils-4.4.2/find/Makefile.am_old findutils-4.4.2/find/Makefile.am
|
|
||||||
--- findutils-4.4.2/find/Makefile.am_old 2009-07-01 10:35:04.000000000 +0200
|
|
||||||
+++ findutils-4.4.2/find/Makefile.am 2009-07-01 10:35:37.000000000 +0200
|
|
||||||
@@ -26,7 +26,7 @@ endif
|
|
||||||
|
|
||||||
EXTRA_DIST = defs.h $(man_MANS)
|
|
||||||
INCLUDES = -I../gnulib/lib -I$(top_srcdir)/lib -I$(top_srcdir)/gnulib/lib -I../intl -DLOCALEDIR=\"$(localedir)\"
|
|
||||||
-LDADD = ./libfindtools.a ../lib/libfind.a ../gnulib/lib/libgnulib.a @INTLLIBS@ @LIB_CLOCK_GETTIME@ @FINDLIBS@
|
|
||||||
+LDADD = ./libfindtools.a ../lib/libfind.a ../gnulib/lib/libgnulib.a @INTLLIBS@ @LIB_CLOCK_GETTIME@ @FINDLIBS@ @LIBSELINUX@
|
|
||||||
man_MANS = find.1
|
|
||||||
SUBDIRS = . testsuite
|
|
||||||
|
|
||||||
diff -up findutils-4.4.2/find/parser.c_old findutils-4.4.2/find/parser.c
|
|
||||||
--- findutils-4.4.2/find/parser.c_old 2009-07-01 10:35:43.000000000 +0200
|
|
||||||
+++ findutils-4.4.2/find/parser.c 2009-07-01 12:38:19.000000000 +0200
|
|
||||||
@@ -53,6 +53,10 @@
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
+#ifdef WITH_SELINUX
|
|
||||||
+#include <selinux/selinux.h>
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
#if ENABLE_NLS
|
|
||||||
# include <libintl.h>
|
|
||||||
# define _(Text) gettext (Text)
|
|
||||||
@@ -155,6 +159,9 @@ static boolean parse_noignore_race PARAM
|
|
||||||
static boolean parse_warn PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
|
|
||||||
static boolean parse_xtype PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
|
|
||||||
static boolean parse_quit PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
|
|
||||||
+#ifdef WITH_SELINUX
|
|
||||||
+static boolean parse_context PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
boolean parse_print PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
|
|
||||||
|
|
||||||
@@ -251,6 +258,9 @@ static struct parser_table const parse_t
|
|
||||||
PARSE_TEST ("cmin", cmin), /* GNU */
|
|
||||||
PARSE_TEST ("cnewer", cnewer), /* GNU */
|
|
||||||
{ARG_TEST, "ctime", parse_time, pred_ctime}, /* POSIX */
|
|
||||||
+#ifdef WITH_SELINUX
|
|
||||||
+ PARSE_TEST ("context", context), /* GNU */
|
|
||||||
+#endif
|
|
||||||
PARSE_POSOPT ("daystart", daystart), /* GNU */
|
|
||||||
PARSE_ACTION ("delete", delete), /* GNU, Mac OS, FreeBSD */
|
|
||||||
PARSE_OPTION ("d", d), /* Mac OS X, FreeBSD, NetBSD, OpenBSD, but deprecated in favour of -depth */
|
|
||||||
@@ -347,6 +357,89 @@ static struct parser_table const parse_t
|
|
||||||
static const char *first_nonoption_arg = NULL;
|
|
||||||
static const struct parser_table *noop = NULL;
|
|
||||||
|
|
||||||
+#ifdef WITH_SELINUX
|
|
||||||
+static int
|
|
||||||
+fallback_getfilecon(const char *name, security_context_t *p, int prev_rv)
|
|
||||||
+{
|
|
||||||
+ /* Our original getfilecon() call failed. Perhaps we can't follow a
|
|
||||||
+ * symbolic link. If that might be the problem, lgetfilecon() the link.
|
|
||||||
+ * Otherwise, admit defeat.
|
|
||||||
+ */
|
|
||||||
+ switch (errno)
|
|
||||||
+ {
|
|
||||||
+ case ENOENT:
|
|
||||||
+ case ENOTDIR:
|
|
||||||
+#ifdef DEBUG_STAT
|
|
||||||
+ fprintf(stderr, "fallback_getfilecon(): getfilecon(%s) failed; falling back on lgetfilecon()\n", name);
|
|
||||||
+#endif
|
|
||||||
+ return lgetfilecon(name, p);
|
|
||||||
+
|
|
||||||
+ case EACCES:
|
|
||||||
+ case EIO:
|
|
||||||
+ case ELOOP:
|
|
||||||
+ case ENAMETOOLONG:
|
|
||||||
+#ifdef EOVERFLOW
|
|
||||||
+ case EOVERFLOW: /* EOVERFLOW is not #defined on UNICOS. */
|
|
||||||
+#endif
|
|
||||||
+ default:
|
|
||||||
+ return prev_rv;
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* optionh_getfilecon() implements the getfilecon operation when the
|
|
||||||
+ * -H option is in effect.
|
|
||||||
+ *
|
|
||||||
+ * If the item to be examined is a command-line argument, we follow
|
|
||||||
+ * symbolic links. If the getfilecon() call fails on the command-line
|
|
||||||
+ * item, we fall back on the properties of the symbolic link.
|
|
||||||
+ *
|
|
||||||
+ * If the item to be examined is not a command-line argument, we
|
|
||||||
+ * examine the link itself.
|
|
||||||
+ */
|
|
||||||
+int
|
|
||||||
+optionh_getfilecon(const char *name, security_context_t *p)
|
|
||||||
+{
|
|
||||||
+ if (0 == state.curdepth)
|
|
||||||
+ {
|
|
||||||
+ /* This file is from the command line; deference the link (if it
|
|
||||||
+ * is a link).
|
|
||||||
+ */
|
|
||||||
+ int rv = getfilecon(name, p);
|
|
||||||
+ if (0 == rv)
|
|
||||||
+ return 0; /* success */
|
|
||||||
+ else
|
|
||||||
+ return fallback_getfilecon(name, p, rv);
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ {
|
|
||||||
+ /* Not a file on the command line; do not derefernce the link.
|
|
||||||
+ */
|
|
||||||
+ return lgetfilecon(name, p);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+/* optionl_getfilecon() implements the getfilecon operation when the
|
|
||||||
+ * -L option is in effect. That option makes us examine the thing the
|
|
||||||
+ * symbolic link points to, not the symbolic link itself.
|
|
||||||
+ */
|
|
||||||
+int
|
|
||||||
+optionl_getfilecon(const char *name, security_context_t *p)
|
|
||||||
+{
|
|
||||||
+ int rv = getfilecon(name, p);
|
|
||||||
+ if (0 == rv)
|
|
||||||
+ return 0; /* normal case. */
|
|
||||||
+ else
|
|
||||||
+ return fallback_getfilecon(name, p, rv);
|
|
||||||
+}
|
|
||||||
+/* optionp_getfilecon() implements the stat operation when the -P
|
|
||||||
+ * option is in effect (this is also the default). That option makes
|
|
||||||
+ * us examine the symbolic link itself, not the thing it points to.
|
|
||||||
+ */
|
|
||||||
+int
|
|
||||||
+optionp_getfilecon(const char *name, security_context_t *p)
|
|
||||||
+{
|
|
||||||
+ return lgetfilecon(name, p);
|
|
||||||
+}
|
|
||||||
+#endif /* WITH_SELINUX */
|
|
||||||
|
|
||||||
void
|
|
||||||
check_option_combinations(const struct predicate *p)
|
|
||||||
@@ -450,11 +543,17 @@ set_follow_state(enum SymlinkOption opt)
|
|
||||||
{
|
|
||||||
case SYMLINK_ALWAYS_DEREF: /* -L */
|
|
||||||
options.xstat = optionl_stat;
|
|
||||||
+#ifdef WITH_SELINUX
|
|
||||||
+ options.x_getfilecon = optionl_getfilecon;
|
|
||||||
+#endif
|
|
||||||
options.no_leaf_check = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SYMLINK_NEVER_DEREF: /* -P (default) */
|
|
||||||
options.xstat = optionp_stat;
|
|
||||||
+#ifdef WITH_SELINUX
|
|
||||||
+ options.x_getfilecon = optionp_getfilecon;
|
|
||||||
+#endif
|
|
||||||
/* Can't turn no_leaf_check off because the user might have specified
|
|
||||||
* -noleaf anyway
|
|
||||||
*/
|
|
||||||
@@ -462,6 +561,9 @@ set_follow_state(enum SymlinkOption opt)
|
|
||||||
|
|
||||||
case SYMLINK_DEREF_ARGSONLY: /* -H */
|
|
||||||
options.xstat = optionh_stat;
|
|
||||||
+#ifdef WITH_SELINUX
|
|
||||||
+ options.x_getfilecon = optionh_getfilecon;
|
|
||||||
+#endif
|
|
||||||
options.no_leaf_check = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1127,8 +1229,12 @@ tests (N can be +N or -N or N): -amin N
|
|
||||||
-nouser -nogroup -path PATTERN -perm [+-]MODE -regex PATTERN\n\
|
|
||||||
-readable -writable -executable\n\
|
|
||||||
-wholename PATTERN -size N[bcwkMG] -true -type [bcdpflsD] -uid N\n\
|
|
||||||
- -used N -user NAME -xtype [bcdpfls]\n"));
|
|
||||||
+ -used N -user NAME -xtype [bcdpfls]"));
|
|
||||||
+#ifdef WITH_SELINUX
|
|
||||||
puts (_("\
|
|
||||||
+ -context CONTEXT\n"));
|
|
||||||
+#endif
|
|
||||||
+ puts (_("\n\
|
|
||||||
actions: -delete -print0 -printf FORMAT -fprintf FILE FORMAT -print \n\
|
|
||||||
-fprint0 FILE -fprint FILE -ls -fls FILE -prune -quit\n\
|
|
||||||
-exec COMMAND ; -exec COMMAND {} + -ok COMMAND ;\n\
|
|
||||||
@@ -2518,6 +2624,10 @@ parse_version (const struct parser_table
|
|
||||||
printf("LEAF_OPTIMISATION ");
|
|
||||||
++features;
|
|
||||||
#endif
|
|
||||||
+#if defined(WITH_SELINUX)
|
|
||||||
+ printf("SELINUX ");
|
|
||||||
+ ++features;
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
flags = 0;
|
|
||||||
if (is_fts_enabled(&flags))
|
|
||||||
@@ -2552,6 +2662,32 @@ parse_version (const struct parser_table
|
|
||||||
exit (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
+#ifdef WITH_SELINUX
|
|
||||||
+static boolean
|
|
||||||
+parse_context (const struct parser_table* entry, char **argv, int *arg_ptr)
|
|
||||||
+{
|
|
||||||
+ struct predicate *our_pred;
|
|
||||||
+
|
|
||||||
+ if ((argv == NULL) || (argv[*arg_ptr] == NULL))
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ if (is_selinux_enabled() <= 0)
|
|
||||||
+ {
|
|
||||||
+ error (1, 0, _("invalid predicate -context: SELinux is not enabled."));
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+ our_pred = insert_primary (entry);
|
|
||||||
+ our_pred->need_stat = false;
|
|
||||||
+#ifdef DEBUG
|
|
||||||
+ our_pred->p_name = find_pred_name (pred_context);
|
|
||||||
+#endif /*DEBUG*/
|
|
||||||
+ our_pred->args.scontext = argv[*arg_ptr];
|
|
||||||
+
|
|
||||||
+ (*arg_ptr)++;
|
|
||||||
+ return true;
|
|
||||||
+}
|
|
||||||
+#endif /* WITH_SELINUX */
|
|
||||||
+
|
|
||||||
static boolean
|
|
||||||
parse_xdev (const struct parser_table* entry, char **argv, int *arg_ptr)
|
|
||||||
{
|
|
||||||
@@ -2803,7 +2939,7 @@ insert_fprintf (struct format_val *vec,
|
|
||||||
if (*scan2 == '.')
|
|
||||||
for (scan2++; ISDIGIT (*scan2); scan2++)
|
|
||||||
/* Do nothing. */ ;
|
|
||||||
- if (strchr ("abcdDfFgGhHiklmMnpPsStuUyY", *scan2))
|
|
||||||
+ if (strchr ("abcdDfFgGhHiklmMnpPsStuUyYZ", *scan2))
|
|
||||||
{
|
|
||||||
segmentp = make_segment (segmentp, format, scan2 - format,
|
|
||||||
KIND_FORMAT, *scan2, 0,
|
|
||||||
@@ -2930,6 +3066,7 @@ make_segment (struct segment **segment,
|
|
||||||
case 'h': /* leading directories part of path */
|
|
||||||
case 'p': /* pathname */
|
|
||||||
case 'P': /* pathname with ARGV element stripped */
|
|
||||||
+ case 'Z': /* SELinux security context */
|
|
||||||
*fmt++ = 's';
|
|
||||||
break;
|
|
||||||
|
|
||||||
diff -up findutils-4.4.2/find/pred.c_old findutils-4.4.2/find/pred.c
|
|
||||||
--- findutils-4.4.2/find/pred.c_old 2009-07-01 10:31:11.000000000 +0200
|
|
||||||
+++ findutils-4.4.2/find/pred.c 2009-07-01 10:33:45.000000000 +0200
|
|
||||||
@@ -48,6 +48,10 @@
|
|
||||||
#include "error.h"
|
|
||||||
#include "verify.h"
|
|
||||||
|
|
||||||
+#ifdef WITH_SELINUX
|
|
||||||
+#include <selinux/selinux.h>
|
|
||||||
+#endif /*WITH_SELINUX*/
|
|
||||||
+
|
|
||||||
#if ENABLE_NLS
|
|
||||||
# include <libintl.h>
|
|
||||||
# define _(Text) gettext (Text)
|
|
||||||
@@ -230,6 +234,9 @@ struct pred_assoc pred_table[] =
|
|
||||||
{pred_user, "user "},
|
|
||||||
{pred_writable, "writable "},
|
|
||||||
{pred_xtype, "xtype "},
|
|
||||||
+#ifdef WITH_SELINUX
|
|
||||||
+ {pred_context, "context"},
|
|
||||||
+#endif /*WITH_SELINUX*/
|
|
||||||
{0, "none "}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
@@ -1054,6 +1061,27 @@ do_fprintf(struct format_val *dest,
|
|
||||||
mode_to_filetype(stat_buf->st_mode & S_IFMT));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
+ case 'Z': /* SELinux security context */
|
|
||||||
+#ifdef WITH_SELINUX
|
|
||||||
+ {
|
|
||||||
+ security_context_t scontext;
|
|
||||||
+ int rv;
|
|
||||||
+ rv = (*options.x_getfilecon) (state.rel_pathname, &scontext);
|
|
||||||
+
|
|
||||||
+ if (rv < 0)
|
|
||||||
+ {
|
|
||||||
+ fprintf (stderr, "getfilecon(%s): %s", pathname,
|
|
||||||
+ strerror(errno));
|
|
||||||
+ fflush (stderr);
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ {
|
|
||||||
+ checked_fprintf (dest, segment->text, scontext);
|
|
||||||
+ freecon (scontext);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+#endif /* WITH_SELINUX */
|
|
||||||
+ break;
|
|
||||||
}
|
|
||||||
/* end of KIND_FORMAT case */
|
|
||||||
break;
|
|
||||||
@@ -1844,6 +1872,32 @@ pred_xtype (const char *pathname, struct
|
|
||||||
*/
|
|
||||||
return (pred_type (pathname, &sbuf, pred_ptr));
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+#ifdef WITH_SELINUX
|
|
||||||
+
|
|
||||||
+boolean
|
|
||||||
+pred_context (const char *pathname, struct stat *stat_buf,
|
|
||||||
+ struct predicate *pred_ptr)
|
|
||||||
+{
|
|
||||||
+ int rv;
|
|
||||||
+ security_context_t scontext;
|
|
||||||
+
|
|
||||||
+ rv = (*options.x_getfilecon) (state.rel_pathname, &scontext);
|
|
||||||
+
|
|
||||||
+ if (rv < 0)
|
|
||||||
+ {
|
|
||||||
+ fprintf (stderr, "getfilecon(%s): %s\n", pathname, strerror(errno));
|
|
||||||
+ fflush (stderr);
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ rv = (fnmatch (pred_ptr->args.scontext, scontext, 0) == 0);
|
|
||||||
+ freecon (scontext);
|
|
||||||
+ return rv;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#endif /*WITH_SELINUX*/
|
|
||||||
+
|
|
||||||
|
|
||||||
/* 1) fork to get a child; parent remembers the child pid
|
|
||||||
2) child execs the command requested
|
|
||||||
diff -up findutils-4.4.2/find/tree.c_old findutils-4.4.2/find/tree.c
|
|
||||||
--- findutils-4.4.2/find/tree.c_old 2009-07-01 10:33:57.000000000 +0200
|
|
||||||
+++ findutils-4.4.2/find/tree.c 2009-07-01 10:34:54.000000000 +0200
|
|
||||||
@@ -953,7 +953,8 @@ static struct pred_cost_lookup costlooku
|
|
||||||
{ pred_used , NeedsStatInfo },
|
|
||||||
{ pred_user , NeedsStatInfo },
|
|
||||||
{ pred_writable , NeedsAccessInfo },
|
|
||||||
- { pred_xtype , NeedsType } /* roughly correct unless most files are symlinks */
|
|
||||||
+ { pred_xtype , NeedsType }, /* roughly correct unless most files are symlinks */
|
|
||||||
+ { pred_context , NeedsNothing } /* remove warning only:) */
|
|
||||||
};
|
|
||||||
static int pred_table_sorted = 0;
|
|
||||||
|
|
||||||
@@ -1434,6 +1435,9 @@ get_new_pred (const struct parser_table
|
|
||||||
last_pred->need_stat = true;
|
|
||||||
last_pred->need_type = true;
|
|
||||||
last_pred->args.str = NULL;
|
|
||||||
+#ifdef WITH_SELINUX
|
|
||||||
+ last_pred->args.scontext = NULL;
|
|
||||||
+#endif
|
|
||||||
last_pred->pred_next = NULL;
|
|
||||||
last_pred->pred_left = NULL;
|
|
||||||
last_pred->pred_right = NULL;
|
|
87
findutils-4.4.2-autofs.patch
Normal file
87
findutils-4.4.2-autofs.patch
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
diff -rup findutils-4.4.2.orig/find/fstype.c findutils-4.4.2/find/fstype.c
|
||||||
|
--- findutils-4.4.2.orig/find/fstype.c 2009-05-16 17:17:01.000000000 +0200
|
||||||
|
+++ findutils-4.4.2/find/fstype.c 2009-10-20 12:47:10.589871024 +0200
|
||||||
|
@@ -205,7 +205,72 @@ must_read_fs_list(bool need_fs_type)
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Return the device number from MOUNT_OPTIONS, if possible.
|
||||||
|
+ Otherwise return (dev_t) -1. Taken from 'mountlist' module
|
||||||
|
+ from gnulib. */
|
||||||
|
+static dev_t
|
||||||
|
+dev_from_mount_options (char const *mount_options)
|
||||||
|
+{
|
||||||
|
+ /* GNU/Linux allows file system implementations to define their own
|
||||||
|
+ meaning for "dev=" mount options, so don't trust the meaning
|
||||||
|
+ here. */
|
||||||
|
+# ifndef __linux__
|
||||||
|
+
|
||||||
|
+ static char const dev_pattern[] = ",dev=";
|
||||||
|
+ char const *devopt = strstr (mount_options, dev_pattern);
|
||||||
|
+
|
||||||
|
+ if (devopt)
|
||||||
|
+ {
|
||||||
|
+ char const *optval = devopt + sizeof dev_pattern - 1;
|
||||||
|
+ char *optvalend;
|
||||||
|
+ unsigned long int dev;
|
||||||
|
+ errno = 0;
|
||||||
|
+ dev = strtoul (optval, &optvalend, 16);
|
||||||
|
+ if (optval != optvalend
|
||||||
|
+ && (*optvalend == '\0' || *optvalend == ',')
|
||||||
|
+ && ! (dev == ULONG_MAX && errno == ERANGE)
|
||||||
|
+ && dev == (dev_t) dev)
|
||||||
|
+ return dev;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+# endif
|
||||||
|
+ (void) mount_options;
|
||||||
|
+ return -1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Return true if the file described by STATP is on autofs file system
|
||||||
|
+ and call set_fstype_devno () if the autofs file system is matched. */
|
||||||
|
+static bool
|
||||||
|
+filesystem_check_autofs (const struct stat *statp)
|
||||||
|
+{
|
||||||
|
+ FILE *fp;
|
||||||
|
+ struct mntent *mnt;
|
||||||
|
+ struct mount_entry entry;
|
||||||
|
+ bool match = false;
|
||||||
|
+
|
||||||
|
+ /* open /proc/mounts because autofs is not listed in /etc/mtab */
|
||||||
|
+ fp = setmntent ("/proc/mounts", "r");
|
||||||
|
+ if (fp == NULL)
|
||||||
|
+ return false;
|
||||||
|
|
||||||
|
+ while ((mnt = getmntent (fp)))
|
||||||
|
+ {
|
||||||
|
+ if (0 != strcmp ("autofs", mnt->mnt_type))
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ entry.me_mountdir = mnt->mnt_dir;
|
||||||
|
+ entry.me_dev = dev_from_mount_options (mnt->mnt_opts);
|
||||||
|
+ set_fstype_devno (&entry);
|
||||||
|
+ if (entry.me_dev == statp->st_dev)
|
||||||
|
+ {
|
||||||
|
+ match = true;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ endmntent (fp);
|
||||||
|
+ return match;
|
||||||
|
+}
|
||||||
|
|
||||||
|
/* Return a newly allocated string naming the type of file system that the
|
||||||
|
file PATH, described by STATP, is on.
|
||||||
|
@@ -244,6 +309,10 @@ file_system_type_uncached (const struct
|
||||||
|
}
|
||||||
|
free_file_system_list(entries);
|
||||||
|
|
||||||
|
+ /* check for autofs */
|
||||||
|
+ if (type == NULL && filesystem_check_autofs (statp))
|
||||||
|
+ type = xstrdup ("autofs");
|
||||||
|
+
|
||||||
|
/* Don't cache unknown values. */
|
||||||
|
fstype_known = (type != NULL);
|
||||||
|
|
27
findutils-4.4.2-fts-remount.patch
Normal file
27
findutils-4.4.2-fts-remount.patch
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
This patch is already applied on gnulib upstream git.
|
||||||
|
|
||||||
|
diff --git a/gnulib/lib/fts.c b/gnulib/lib/fts.c
|
||||||
|
index ceb8935..2f1eda4 100644
|
||||||
|
--- a/gnulib/lib/fts.c
|
||||||
|
+++ b/gnulib/lib/fts.c
|
||||||
|
@@ -974,6 +974,20 @@ fts_build (register FTS *sp, int type)
|
||||||
|
opening it. */
|
||||||
|
if (cur->fts_info == FTS_NSOK)
|
||||||
|
cur->fts_info = fts_stat(sp, cur, false);
|
||||||
|
+ else if (sp->fts_options & FTS_TIGHT_CYCLE_CHECK) {
|
||||||
|
+ /* Now read the stat info again after opening a directory to
|
||||||
|
+ * reveal eventual changes caused by a submount triggered by
|
||||||
|
+ * the traverse. But do it only for utilities which use
|
||||||
|
+ * FTS_TIGHT_CYCLE_CHECK. Therefore only find and du can
|
||||||
|
+ * benefit from this feature for now.
|
||||||
|
+ */
|
||||||
|
+ LEAVE_DIR (sp, cur, "4");
|
||||||
|
+ fts_stat (sp, cur, false);
|
||||||
|
+ if (! enter_dir (sp, cur)) {
|
||||||
|
+ __set_errno (ENOMEM);
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Nlinks is the number of possible entries of type directory in the
|
1143
findutils-4.4.2-selinux-gnulib.patch
Normal file
1143
findutils-4.4.2-selinux-gnulib.patch
Normal file
File diff suppressed because it is too large
Load Diff
463
findutils-4.4.2-selinux.patch
Normal file
463
findutils-4.4.2-selinux.patch
Normal file
@ -0,0 +1,463 @@
|
|||||||
|
NEWS | 6 +++
|
||||||
|
doc/find.texi | 18 +++++++-
|
||||||
|
find/Makefile.am | 2 +-
|
||||||
|
find/defs.h | 6 +++
|
||||||
|
find/find.1 | 4 ++
|
||||||
|
find/parser.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
|
||||||
|
find/pred.c | 47 ++++++++++++++++++++
|
||||||
|
find/tree.c | 2 +
|
||||||
|
8 files changed, 209 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/NEWS b/NEWS
|
||||||
|
index d00862f..6b8b725 100644
|
||||||
|
--- a/NEWS
|
||||||
|
+++ b/NEWS
|
||||||
|
@@ -1,5 +1,11 @@
|
||||||
|
GNU findutils NEWS - User visible changes. -*- outline -*- (allout)
|
||||||
|
|
||||||
|
+* Major changes in release 4.4.2, 2009-11-26
|
||||||
|
+
|
||||||
|
+** Functional Enhancements to find
|
||||||
|
+
|
||||||
|
+patch #4848: Patch - Support for SELinux
|
||||||
|
+
|
||||||
|
* Major changes in release 4.4.2, 2009-05-16
|
||||||
|
|
||||||
|
** Bug Fixes
|
||||||
|
diff --git a/doc/find.texi b/doc/find.texi
|
||||||
|
index 8944096..4d71066 100644
|
||||||
|
--- a/doc/find.texi
|
||||||
|
+++ b/doc/find.texi
|
||||||
|
@@ -7,7 +7,6 @@
|
||||||
|
@c %**end of header
|
||||||
|
|
||||||
|
@include version.texi
|
||||||
|
-@include ../locate/dblocation.texi
|
||||||
|
|
||||||
|
@iftex
|
||||||
|
@finalout
|
||||||
|
@@ -1242,6 +1241,14 @@ situation.
|
||||||
|
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
+@deffn Test -context pattern
|
||||||
|
+True if file's SELinux context matches the pattern @var{pattern}.
|
||||||
|
+The pattern uses shell glob matching.
|
||||||
|
+
|
||||||
|
+This predicate is supported only on @code{find} versions compiled with
|
||||||
|
+SELinux support and only when SELinux is enabled.
|
||||||
|
+@end deffn
|
||||||
|
+
|
||||||
|
@node Contents
|
||||||
|
@section Contents
|
||||||
|
|
||||||
|
@@ -1737,6 +1744,7 @@ from the novel you are reading.
|
||||||
|
* Size Directives::
|
||||||
|
* Location Directives::
|
||||||
|
* Time Directives::
|
||||||
|
+* Other Directives::
|
||||||
|
* Formatting Flags::
|
||||||
|
@end menu
|
||||||
|
|
||||||
|
@@ -1894,6 +1902,14 @@ File's last modification time in the format specified by @var{k}
|
||||||
|
(@pxref{Time Formats}).
|
||||||
|
@end table
|
||||||
|
|
||||||
|
+@node Other Directives
|
||||||
|
+@subsubsection Other Directives
|
||||||
|
+
|
||||||
|
+@table @code
|
||||||
|
+@item %Z
|
||||||
|
+File's SELinux context, or empty string if the file has no SELinux context.
|
||||||
|
+@end table
|
||||||
|
+
|
||||||
|
@node Time Formats
|
||||||
|
@subsection Time Formats
|
||||||
|
|
||||||
|
diff --git a/find/Makefile.am b/find/Makefile.am
|
||||||
|
index b001509..6fc7df3 100644
|
||||||
|
--- a/find/Makefile.am
|
||||||
|
+++ b/find/Makefile.am
|
||||||
|
@@ -26,7 +26,7 @@ endif
|
||||||
|
|
||||||
|
EXTRA_DIST = defs.h $(man_MANS)
|
||||||
|
INCLUDES = -I../gnulib/lib -I$(top_srcdir)/lib -I$(top_srcdir)/gnulib/lib -I../intl -DLOCALEDIR=\"$(localedir)\"
|
||||||
|
-LDADD = ./libfindtools.a ../lib/libfind.a ../gnulib/lib/libgnulib.a @INTLLIBS@ @LIB_CLOCK_GETTIME@ @FINDLIBS@
|
||||||
|
+LDADD = ./libfindtools.a ../lib/libfind.a ../gnulib/lib/libgnulib.a @INTLLIBS@ @LIB_CLOCK_GETTIME@ @FINDLIBS@ @LIB_SELINUX@
|
||||||
|
man_MANS = find.1
|
||||||
|
SUBDIRS = . testsuite
|
||||||
|
|
||||||
|
diff --git a/find/defs.h b/find/defs.h
|
||||||
|
index a0e7059..36d428d 100644
|
||||||
|
--- a/find/defs.h
|
||||||
|
+++ b/find/defs.h
|
||||||
|
@@ -48,6 +48,7 @@ Please stop compiling the program now
|
||||||
|
#include <stdbool.h> /* for bool/boolean */
|
||||||
|
#include <stdint.h> /* for uintmax_t */
|
||||||
|
#include <sys/stat.h> /* S_ISUID etc. */
|
||||||
|
+#include <selinux/selinux.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -315,6 +316,7 @@ struct predicate
|
||||||
|
struct samefile_file_id samefileid; /* samefile */
|
||||||
|
mode_t type; /* type */
|
||||||
|
struct format_val printf_vec; /* printf fprintf fprint ls fls print0 fprint0 print */
|
||||||
|
+ security_context_t scontext; /* security context */
|
||||||
|
} args;
|
||||||
|
|
||||||
|
/* The next predicate in the user input sequence,
|
||||||
|
@@ -459,6 +461,7 @@ PREDICATEFUNCTION pred_used;
|
||||||
|
PREDICATEFUNCTION pred_user;
|
||||||
|
PREDICATEFUNCTION pred_writable;
|
||||||
|
PREDICATEFUNCTION pred_xtype;
|
||||||
|
+PREDICATEFUNCTION pred_context;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -604,6 +607,9 @@ struct options
|
||||||
|
*/
|
||||||
|
int regex_options;
|
||||||
|
|
||||||
|
+ /* function used to get file context */
|
||||||
|
+ int (*x_getfilecon) (int, const char *, security_context_t *);
|
||||||
|
+
|
||||||
|
/* Optimisation level. One is the default.
|
||||||
|
*/
|
||||||
|
unsigned short optimisation_level;
|
||||||
|
diff --git a/find/find.1 b/find/find.1
|
||||||
|
index f9c61a3..27ad1da 100644
|
||||||
|
--- a/find/find.1
|
||||||
|
+++ b/find/find.1
|
||||||
|
@@ -936,6 +936,8 @@ if \fIc\fR is `l'. In other words, for symbolic links,
|
||||||
|
checks the type of the file that
|
||||||
|
.B \-type
|
||||||
|
does not check.
|
||||||
|
+.IP "\-context \fIpattern\fR"
|
||||||
|
+(SELinux only) Security context of the file matches glob \fIpattern\fR.
|
||||||
|
|
||||||
|
.SS ACTIONS
|
||||||
|
.IP "\-delete\fR"
|
||||||
|
@@ -1357,6 +1359,8 @@ File's type (like in
|
||||||
|
U=unknown type (shouldn't happen)
|
||||||
|
.IP %Y
|
||||||
|
File's type (like %y), plus follow symlinks: L=loop, N=nonexistent
|
||||||
|
+.IP %Z
|
||||||
|
+(SELinux only) file's security context.
|
||||||
|
.PP
|
||||||
|
A `%' character followed by any other character is discarded, but the
|
||||||
|
other character is printed (don't rely on this, as further format
|
||||||
|
diff --git a/find/parser.c b/find/parser.c
|
||||||
|
index 411fd96..3f237eb 100644
|
||||||
|
--- a/find/parser.c
|
||||||
|
+++ b/find/parser.c
|
||||||
|
@@ -53,6 +53,8 @@
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
+#include "selinux-at.h"
|
||||||
|
+
|
||||||
|
#if ENABLE_NLS
|
||||||
|
# include <libintl.h>
|
||||||
|
# define _(Text) gettext (Text)
|
||||||
|
@@ -156,6 +158,7 @@ static boolean parse_noignore_race PARAMS((const struct parser_table*, char *arg
|
||||||
|
static boolean parse_warn PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
|
||||||
|
static boolean parse_xtype PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
|
||||||
|
static boolean parse_quit PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
|
||||||
|
+static boolean parse_context PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
|
||||||
|
|
||||||
|
boolean parse_print PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
|
||||||
|
|
||||||
|
@@ -252,6 +255,7 @@ static struct parser_table const parse_table[] =
|
||||||
|
PARSE_TEST ("cmin", cmin), /* GNU */
|
||||||
|
PARSE_TEST ("cnewer", cnewer), /* GNU */
|
||||||
|
{ARG_TEST, "ctime", parse_time, pred_ctime}, /* POSIX */
|
||||||
|
+ PARSE_TEST ("context", context), /* GNU */
|
||||||
|
PARSE_POSOPT ("daystart", daystart), /* GNU */
|
||||||
|
PARSE_ACTION ("delete", delete), /* GNU, Mac OS, FreeBSD */
|
||||||
|
PARSE_OPTION ("d", d), /* Mac OS X, FreeBSD, NetBSD, OpenBSD, but deprecated in favour of -depth */
|
||||||
|
@@ -349,6 +353,86 @@ static struct parser_table const parse_table[] =
|
||||||
|
static const char *first_nonoption_arg = NULL;
|
||||||
|
static const struct parser_table *noop = NULL;
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+fallback_getfilecon (int fd, const char *name, security_context_t *p,
|
||||||
|
+ int prev_rv)
|
||||||
|
+{
|
||||||
|
+ /* Our original getfilecon () call failed. Perhaps we can't follow a
|
||||||
|
+ * symbolic link. If that might be the problem, lgetfilecon () the link.
|
||||||
|
+ * Otherwise, admit defeat. */
|
||||||
|
+ switch (errno)
|
||||||
|
+ {
|
||||||
|
+ case ENOENT:
|
||||||
|
+ case ENOTDIR:
|
||||||
|
+#ifdef DEBUG_STAT
|
||||||
|
+ fprintf (stderr, "fallback_getfilecon(): getfilecon(%s) failed; falling "
|
||||||
|
+ "back on lgetfilecon()\n", name);
|
||||||
|
+#endif
|
||||||
|
+ return lgetfileconat (fd, name, p);
|
||||||
|
+
|
||||||
|
+ case EACCES:
|
||||||
|
+ case EIO:
|
||||||
|
+ case ELOOP:
|
||||||
|
+ case ENAMETOOLONG:
|
||||||
|
+#ifdef EOVERFLOW
|
||||||
|
+ case EOVERFLOW: /* EOVERFLOW is not #defined on UNICOS. */
|
||||||
|
+#endif
|
||||||
|
+ default:
|
||||||
|
+ return prev_rv;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* optionh_getfilecon () implements the getfilecon operation when the
|
||||||
|
+ * -H option is in effect.
|
||||||
|
+ *
|
||||||
|
+ * If the item to be examined is a command-line argument, we follow
|
||||||
|
+ * symbolic links. If the getfilecon () call fails on the command-line
|
||||||
|
+ * item, we fall back on the properties of the symbolic link.
|
||||||
|
+ *
|
||||||
|
+ * If the item to be examined is not a command-line argument, we
|
||||||
|
+ * examine the link itself. */
|
||||||
|
+int
|
||||||
|
+optionh_getfilecon (int fd, const char *name, security_context_t *p)
|
||||||
|
+{
|
||||||
|
+ int rv;
|
||||||
|
+ if (0 == state.curdepth)
|
||||||
|
+ {
|
||||||
|
+ /* This file is from the command line; dereference the link (if it is
|
||||||
|
+ a link). */
|
||||||
|
+ rv = getfileconat (fd, name, p);
|
||||||
|
+ if (0 == rv)
|
||||||
|
+ return 0; /* success */
|
||||||
|
+ else
|
||||||
|
+ return fallback_getfilecon (fd, name, p, rv);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ /* Not a file on the command line; do not dereference the link. */
|
||||||
|
+ return lgetfileconat (fd, name, p);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* optionl_getfilecon () implements the getfilecon operation when the
|
||||||
|
+ * -L option is in effect. That option makes us examine the thing the
|
||||||
|
+ * symbolic link points to, not the symbolic link itself. */
|
||||||
|
+int
|
||||||
|
+optionl_getfilecon (int fd, const char *name, security_context_t *p)
|
||||||
|
+{
|
||||||
|
+ int rv = getfileconat (fd, name, p);
|
||||||
|
+ if (0 == rv)
|
||||||
|
+ return 0; /* normal case. */
|
||||||
|
+ else
|
||||||
|
+ return fallback_getfilecon (fd, name, p, rv);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* optionp_getfilecon () implements the stat operation when the -P
|
||||||
|
+ * option is in effect (this is also the default). That option makes
|
||||||
|
+ * us examine the symbolic link itself, not the thing it points to. */
|
||||||
|
+int
|
||||||
|
+optionp_getfilecon (int fd, const char *name, security_context_t *p)
|
||||||
|
+{
|
||||||
|
+ return lgetfileconat (fd, name, p);
|
||||||
|
+}
|
||||||
|
|
||||||
|
void
|
||||||
|
check_option_combinations(const struct predicate *p)
|
||||||
|
@@ -452,11 +536,13 @@ set_follow_state(enum SymlinkOption opt)
|
||||||
|
{
|
||||||
|
case SYMLINK_ALWAYS_DEREF: /* -L */
|
||||||
|
options.xstat = optionl_stat;
|
||||||
|
+ options.x_getfilecon = optionl_getfilecon;
|
||||||
|
options.no_leaf_check = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SYMLINK_NEVER_DEREF: /* -P (default) */
|
||||||
|
options.xstat = optionp_stat;
|
||||||
|
+ options.x_getfilecon = optionp_getfilecon;
|
||||||
|
/* Can't turn no_leaf_check off because the user might have specified
|
||||||
|
* -noleaf anyway
|
||||||
|
*/
|
||||||
|
@@ -464,6 +550,7 @@ set_follow_state(enum SymlinkOption opt)
|
||||||
|
|
||||||
|
case SYMLINK_DEREF_ARGSONLY: /* -H */
|
||||||
|
options.xstat = optionh_stat;
|
||||||
|
+ options.x_getfilecon = optionh_getfilecon;
|
||||||
|
options.no_leaf_check = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -1129,8 +1216,10 @@ tests (N can be +N or -N or N): -amin N -anewer FILE -atime N -cmin N\n\
|
||||||
|
-nouser -nogroup -path PATTERN -perm [+-]MODE -regex PATTERN\n\
|
||||||
|
-readable -writable -executable\n\
|
||||||
|
-wholename PATTERN -size N[bcwkMG] -true -type [bcdpflsD] -uid N\n\
|
||||||
|
- -used N -user NAME -xtype [bcdpfls]\n"));
|
||||||
|
+ -used N -user NAME -xtype [bcdpfls]"));
|
||||||
|
puts (_("\
|
||||||
|
+ -context CONTEXT\n"));
|
||||||
|
+ puts (_("\n\
|
||||||
|
actions: -delete -print0 -printf FORMAT -fprintf FILE FORMAT -print \n\
|
||||||
|
-fprint0 FILE -fprint FILE -ls -fls FILE -prune -quit\n\
|
||||||
|
-exec COMMAND ; -exec COMMAND {} + -ok COMMAND ;\n\
|
||||||
|
@@ -2520,6 +2609,11 @@ parse_version (const struct parser_table* entry, char **argv, int *arg_ptr)
|
||||||
|
printf("LEAF_OPTIMISATION ");
|
||||||
|
++features;
|
||||||
|
#endif
|
||||||
|
+ if (0 < is_selinux_enabled ())
|
||||||
|
+ {
|
||||||
|
+ printf ("SELINUX ");
|
||||||
|
+ ++features;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
flags = 0;
|
||||||
|
if (is_fts_enabled(&flags))
|
||||||
|
@@ -2555,6 +2649,31 @@ parse_version (const struct parser_table* entry, char **argv, int *arg_ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
+parse_context (const struct parser_table* entry, char **argv, int *arg_ptr)
|
||||||
|
+{
|
||||||
|
+ struct predicate *our_pred;
|
||||||
|
+
|
||||||
|
+ if ((argv == NULL) || (argv[*arg_ptr] == NULL))
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
+ if (is_selinux_enabled () <= 0)
|
||||||
|
+ {
|
||||||
|
+ error (1, 0, _("invalid predicate -context: SELinux is not enabled."));
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ our_pred = insert_primary (entry);
|
||||||
|
+ our_pred->est_success_rate = 0.01f;
|
||||||
|
+ our_pred->need_stat = false;
|
||||||
|
+#ifdef DEBUG
|
||||||
|
+ our_pred->p_name = find_pred_name (pred_context);
|
||||||
|
+#endif /*DEBUG*/
|
||||||
|
+ our_pred->args.scontext = argv[*arg_ptr];
|
||||||
|
+
|
||||||
|
+ (*arg_ptr)++;
|
||||||
|
+ return true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static boolean
|
||||||
|
parse_xdev (const struct parser_table* entry, char **argv, int *arg_ptr)
|
||||||
|
{
|
||||||
|
options.stay_on_filesystem = true;
|
||||||
|
@@ -2812,7 +2931,7 @@ insert_fprintf (struct format_val *vec,
|
||||||
|
if (*scan2 == '.')
|
||||||
|
for (scan2++; ISDIGIT (*scan2); scan2++)
|
||||||
|
/* Do nothing. */ ;
|
||||||
|
- if (strchr ("abcdDfFgGhHiklmMnpPsStuUyY", *scan2))
|
||||||
|
+ if (strchr ("abcdDfFgGhHiklmMnpPsStuUyYZ", *scan2))
|
||||||
|
{
|
||||||
|
segmentp = make_segment (segmentp, format, scan2 - format,
|
||||||
|
KIND_FORMAT, *scan2, 0,
|
||||||
|
@@ -2942,6 +3061,11 @@ make_segment (struct segment **segment,
|
||||||
|
*fmt++ = 's';
|
||||||
|
break;
|
||||||
|
|
||||||
|
+ case 'Z': /* SELinux security context */
|
||||||
|
+ mycost = NeedsAccessInfo;
|
||||||
|
+ *fmt++ = 's';
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
case 'H': /* ARGV element file was found under */
|
||||||
|
*fmt++ = 's';
|
||||||
|
break;
|
||||||
|
diff --git a/find/pred.c b/find/pred.c
|
||||||
|
index b1f48a0..7c34119 100644
|
||||||
|
--- a/find/pred.c
|
||||||
|
+++ b/find/pred.c
|
||||||
|
@@ -48,6 +48,8 @@
|
||||||
|
#include "error.h"
|
||||||
|
#include "verify.h"
|
||||||
|
|
||||||
|
+#include <selinux/selinux.h>
|
||||||
|
+
|
||||||
|
#if ENABLE_NLS
|
||||||
|
# include <libintl.h>
|
||||||
|
# define _(Text) gettext (Text)
|
||||||
|
@@ -230,6 +232,7 @@ struct pred_assoc pred_table[] =
|
||||||
|
{pred_user, "user "},
|
||||||
|
{pred_writable, "writable "},
|
||||||
|
{pred_xtype, "xtype "},
|
||||||
|
+ {pred_context, "context"},
|
||||||
|
{0, "none "}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
@@ -1054,6 +1057,30 @@ do_fprintf(struct format_val *dest,
|
||||||
|
mode_to_filetype(stat_buf->st_mode & S_IFMT));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
+
|
||||||
|
+ case 'Z': /* SELinux security context */
|
||||||
|
+ {
|
||||||
|
+ security_context_t scontext;
|
||||||
|
+ int rv = (*options.x_getfilecon) (state.cwd_dir_fd, state.rel_pathname,
|
||||||
|
+ &scontext);
|
||||||
|
+ if (rv < 0)
|
||||||
|
+ {
|
||||||
|
+ /* If getfilecon fails, there will in the general case
|
||||||
|
+ still be some text to print. We just make %Z expand
|
||||||
|
+ to an empty string. */
|
||||||
|
+ checked_fprintf (dest, segment->text, "");
|
||||||
|
+
|
||||||
|
+ error (0, errno, "getfilecon: %s",
|
||||||
|
+ safely_quote_err_filename (0, pathname));
|
||||||
|
+ state.exit_status = 1;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ checked_fprintf (dest, segment->text, scontext);
|
||||||
|
+ freecon (scontext);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
}
|
||||||
|
/* end of KIND_FORMAT case */
|
||||||
|
break;
|
||||||
|
@@ -1844,6 +1871,26 @@ pred_xtype (const char *pathname, struct stat *stat_buf, struct predicate *pred_
|
||||||
|
*/
|
||||||
|
return (pred_type (pathname, &sbuf, pred_ptr));
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+boolean
|
||||||
|
+pred_context (const char *pathname, struct stat *stat_buf,
|
||||||
|
+ struct predicate *pred_ptr)
|
||||||
|
+{
|
||||||
|
+ security_context_t scontext;
|
||||||
|
+ int rv = (*options.x_getfilecon) (state.cwd_dir_fd, state.rel_pathname,
|
||||||
|
+ &scontext);
|
||||||
|
+ if (rv < 0)
|
||||||
|
+ {
|
||||||
|
+ error (0, errno, "getfilecon: %s", safely_quote_err_filename (0, pathname));
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ rv = (fnmatch (pred_ptr->args.scontext, scontext, 0) == 0);
|
||||||
|
+ freecon (scontext);
|
||||||
|
+ return rv;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
|
||||||
|
/* 1) fork to get a child; parent remembers the child pid
|
||||||
|
2) child execs the command requested
|
||||||
|
diff --git a/find/tree.c b/find/tree.c
|
||||||
|
index 7420c60..ecdd4c9 100644
|
||||||
|
--- a/find/tree.c
|
||||||
|
+++ b/find/tree.c
|
||||||
|
@@ -904,6 +904,7 @@ static struct pred_cost_lookup costlookup[] =
|
||||||
|
{ pred_cmin , NeedsStatInfo, },
|
||||||
|
{ pred_cnewer , NeedsStatInfo, },
|
||||||
|
{ pred_comma , NeedsNothing, },
|
||||||
|
+ { pred_context , NeedsAccessInfo },
|
||||||
|
{ pred_ctime , NeedsStatInfo, },
|
||||||
|
{ pred_delete , NeedsSyncDiskHit },
|
||||||
|
{ pred_empty , NeedsStatInfo },
|
||||||
|
@@ -1434,6 +1435,7 @@ get_new_pred (const struct parser_table *entry)
|
||||||
|
last_pred->need_stat = true;
|
||||||
|
last_pred->need_type = true;
|
||||||
|
last_pred->args.str = NULL;
|
||||||
|
+ last_pred->args.scontext = NULL;
|
||||||
|
last_pred->pred_next = NULL;
|
||||||
|
last_pred->pred_left = NULL;
|
||||||
|
last_pred->pred_right = NULL;
|
123
findutils-4.4.2-xautofs.patch
Normal file
123
findutils-4.4.2-xautofs.patch
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
doc/find.texi | 4 ++++
|
||||||
|
find/defs.h | 3 +++
|
||||||
|
find/find.1 | 3 +++
|
||||||
|
find/ftsfind.c | 6 ++++++
|
||||||
|
find/parser.c | 11 ++++++++++-
|
||||||
|
find/util.c | 1 +
|
||||||
|
6 files changed, 27 insertions(+), 1 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/doc/find.texi b/doc/find.texi
|
||||||
|
index 2e5958d..8944096 100644
|
||||||
|
--- a/doc/find.texi
|
||||||
|
+++ b/doc/find.texi
|
||||||
|
@@ -1413,6 +1413,10 @@ them.
|
||||||
|
There are two ways to avoid searching certain filesystems. One way is
|
||||||
|
to tell @code{find} to only search one filesystem:
|
||||||
|
|
||||||
|
+@deffn Option -xautofs
|
||||||
|
+Don't descend directories on autofs filesystems.
|
||||||
|
+@end deffn
|
||||||
|
+
|
||||||
|
@deffn Option -xdev
|
||||||
|
@deffnx Option -mount
|
||||||
|
Don't descend directories on other filesystems. These options are
|
||||||
|
diff --git a/find/defs.h b/find/defs.h
|
||||||
|
index 1708d83..a0e7059 100644
|
||||||
|
--- a/find/defs.h
|
||||||
|
+++ b/find/defs.h
|
||||||
|
@@ -550,6 +550,9 @@ struct options
|
||||||
|
/* If true, don't cross filesystem boundaries. */
|
||||||
|
boolean stay_on_filesystem;
|
||||||
|
|
||||||
|
+ /* If true, don't descend directories on autofs filesystems. */
|
||||||
|
+ boolean bypass_autofs;
|
||||||
|
+
|
||||||
|
/* If true, we ignore the problem where we find that a directory entry
|
||||||
|
* no longer exists by the time we get around to processing it.
|
||||||
|
*/
|
||||||
|
diff --git a/find/find.1 b/find/find.1
|
||||||
|
index 8b67ae3..f9c61a3 100644
|
||||||
|
--- a/find/find.1
|
||||||
|
+++ b/find/find.1
|
||||||
|
@@ -451,6 +451,9 @@ if standard input is a tty, and to
|
||||||
|
.B \-nowarn
|
||||||
|
otherwise.
|
||||||
|
|
||||||
|
+.IP \-xautofs
|
||||||
|
+Don't descend directories on autofs filesystems.
|
||||||
|
+
|
||||||
|
.IP \-xdev
|
||||||
|
Don't descend directories on other filesystems.
|
||||||
|
|
||||||
|
diff --git a/find/ftsfind.c b/find/ftsfind.c
|
||||||
|
index b59d896..838b81f 100644
|
||||||
|
--- a/find/ftsfind.c
|
||||||
|
+++ b/find/ftsfind.c
|
||||||
|
@@ -525,6 +525,12 @@ consider_visiting(FTS *p, FTSENT *ent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (options.bypass_autofs &&
|
||||||
|
+ 0 == strcmp ("autofs", filesystem_type (&statbuf, ent->fts_name)))
|
||||||
|
+ {
|
||||||
|
+ fts_set(p, ent, FTS_SKIP); /* descend no further */
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if ( (ent->fts_info == FTS_D) && !options.do_dir_first )
|
||||||
|
{
|
||||||
|
/* this is the preorder visit, but user said -depth */
|
||||||
|
diff --git a/find/parser.c b/find/parser.c
|
||||||
|
index 534b670..411fd96 100644
|
||||||
|
--- a/find/parser.c
|
||||||
|
+++ b/find/parser.c
|
||||||
|
@@ -150,6 +150,7 @@ static boolean parse_user PARAMS((const struct parser_table*, char *arg
|
||||||
|
static boolean parse_version PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
|
||||||
|
static boolean parse_wholename PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
|
||||||
|
static boolean parse_xdev PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
|
||||||
|
+static boolean parse_xautofs PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
|
||||||
|
static boolean parse_ignore_race PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
|
||||||
|
static boolean parse_noignore_race PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
|
||||||
|
static boolean parse_warn PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
|
||||||
|
@@ -320,6 +321,7 @@ static struct parser_table const parse_table[] =
|
||||||
|
PARSE_TEST_NP ("wholename", wholename), /* GNU, replaced -path, but anyway -path will soon be in POSIX */
|
||||||
|
{ARG_TEST, "writable", parse_accesscheck, pred_writable}, /* GNU, 4.3.0+ */
|
||||||
|
PARSE_OPTION ("xdev", xdev), /* POSIX */
|
||||||
|
+ PARSE_OPTION ("xautofs", xautofs),
|
||||||
|
PARSE_TEST ("xtype", xtype), /* GNU */
|
||||||
|
#ifdef UNIMPLEMENTED_UNIX
|
||||||
|
/* It's pretty ugly for find to know about archive formats.
|
||||||
|
@@ -1117,7 +1119,7 @@ operators (decreasing precedence; -and is implicit where no others are given):\n
|
||||||
|
positional options (always true): -daystart -follow -regextype\n\n\
|
||||||
|
normal options (always true, specified before other expressions):\n\
|
||||||
|
-depth --help -maxdepth LEVELS -mindepth LEVELS -mount -noleaf\n\
|
||||||
|
- --version -xdev -ignore_readdir_race -noignore_readdir_race\n"));
|
||||||
|
+ --version -xautofs -xdev -ignore_readdir_race -noignore_readdir_race\n"));
|
||||||
|
puts (_("\
|
||||||
|
tests (N can be +N or -N or N): -amin N -anewer FILE -atime N -cmin N\n\
|
||||||
|
-cnewer FILE -ctime N -empty -false -fstype TYPE -gid N -group NAME\n\
|
||||||
|
@@ -2560,6 +2562,13 @@ parse_xdev (const struct parser_table* entry, char **argv, int *arg_ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
+parse_xautofs (const struct parser_table* entry, char **argv, int *arg_ptr)
|
||||||
|
+{
|
||||||
|
+ options.bypass_autofs = true;
|
||||||
|
+ return parse_noop(entry, argv, arg_ptr);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static boolean
|
||||||
|
parse_ignore_race (const struct parser_table* entry, char **argv, int *arg_ptr)
|
||||||
|
{
|
||||||
|
options.ignore_readdir_race = true;
|
||||||
|
diff --git a/find/util.c b/find/util.c
|
||||||
|
index a06eada..d3cb467 100644
|
||||||
|
--- a/find/util.c
|
||||||
|
+++ b/find/util.c
|
||||||
|
@@ -933,6 +933,7 @@ set_option_defaults(struct options *p)
|
||||||
|
|
||||||
|
p->full_days = false;
|
||||||
|
p->stay_on_filesystem = false;
|
||||||
|
+ p->bypass_autofs = false;
|
||||||
|
p->ignore_readdir_race = false;
|
||||||
|
|
||||||
|
if (p->posixly_correct)
|
192
findutils-4.5.8-0001-41896c7.patch
Normal file
192
findutils-4.5.8-0001-41896c7.patch
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
ChangeLog | 16 +++++++
|
||||||
|
find/testsuite/Makefile.am | 3 +
|
||||||
|
find/testsuite/config/unix.exp | 9 ++++
|
||||||
|
find/testsuite/find.gnu/execdir-multiple.exp | 55 ++++++++++++++++++++++++++
|
||||||
|
find/testsuite/find.gnu/execdir-multiple.xo | 24 +++++++++++
|
||||||
|
find/testsuite/find.gnu/execdir-pwd1.exp | 20 +++++++++
|
||||||
|
6 files changed, 127 insertions(+), 0 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/ChangeLog b/ChangeLog
|
||||||
|
index be93846..34552d5 100644
|
||||||
|
--- a/ChangeLog
|
||||||
|
+++ b/ChangeLog
|
||||||
|
@@ -1,3 +1,19 @@
|
||||||
|
+2010-04-10 James Youngman <jay@gnu.org>
|
||||||
|
+
|
||||||
|
+ Add a test which checks $CWD for find -execdir {} +/;
|
||||||
|
+ * find/testsuite/find.gnu/execdir-multiple.exp: New test; verifies
|
||||||
|
+ that for -execdir +, all the execs occur with the correct working
|
||||||
|
+ directory.
|
||||||
|
+ * find/testsuite/find.gnu/execdir-multiple.xo: Expected output for
|
||||||
|
+ this test.
|
||||||
|
+ * find/testsuite/Makefile.am (EXTRA_DIST_EXP): Add the new test.
|
||||||
|
+ (EXTRA_DIST_XO): Add the expected output file.
|
||||||
|
+ * find/testsuite/config/unix.exp (mkdir): Create proc "mkdir"
|
||||||
|
+ which creates a directory.
|
||||||
|
+ * find/testsuite/find.gnu/execdir-pwd1.exp: New test.
|
||||||
|
+ * find/testsuite/Makefile.am (EXTRA_DIST_EXP): Add
|
||||||
|
+ execdir-pwd1.exp.
|
||||||
|
+
|
||||||
|
2009-05-16 James Youngman <jay@gnu.org>
|
||||||
|
|
||||||
|
Apply typo fix from <petrosyan@gmail.com> (tiny change).
|
||||||
|
diff --git a/find/testsuite/Makefile.am b/find/testsuite/Makefile.am
|
||||||
|
index dca30e6..1447132 100644
|
||||||
|
--- a/find/testsuite/Makefile.am
|
||||||
|
+++ b/find/testsuite/Makefile.am
|
||||||
|
@@ -14,6 +14,7 @@ find.gnu/depth.xo \
|
||||||
|
find.gnu/depth-d.xo \
|
||||||
|
find.gnu/empty.xo \
|
||||||
|
find.gnu/execdir-hier.xo \
|
||||||
|
+find.gnu/execdir-multiple.xo \
|
||||||
|
find.gnu/execdir-one.xo \
|
||||||
|
find.gnu/execdir-root-only.xo \
|
||||||
|
find.gnu/exec-many-rtn-failure.xo \
|
||||||
|
@@ -114,8 +115,10 @@ find.gnu/depth-d.exp \
|
||||||
|
find.gnu/empty.exp \
|
||||||
|
find.gnu/execdir-hier.exp \
|
||||||
|
find.gnu/execdir-in-unreadable.exp \
|
||||||
|
+find.gnu/execdir-multiple.exp \
|
||||||
|
find.gnu/execdir-one.exp \
|
||||||
|
find.gnu/execdir-pwd.exp \
|
||||||
|
+find.gnu/execdir-pwd1.exp \
|
||||||
|
find.gnu/execdir-root-only.exp \
|
||||||
|
find.gnu/exec-many-rtn-failure.exp \
|
||||||
|
find.gnu/exec-many-rtn-success.exp \
|
||||||
|
diff --git a/find/testsuite/config/unix.exp b/find/testsuite/config/unix.exp
|
||||||
|
index 087aeb2..968eb9d 100644
|
||||||
|
--- a/find/testsuite/config/unix.exp
|
||||||
|
+++ b/find/testsuite/config/unix.exp
|
||||||
|
@@ -259,6 +259,15 @@ proc touch args {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+proc mkdir { dirname } {
|
||||||
|
+ # Not all versions of Tcl offer 'file mkdir'.
|
||||||
|
+ set failed [ catch "file mkdir $dirname" result ]
|
||||||
|
+ if $failed {
|
||||||
|
+ # Fall back on the external command.
|
||||||
|
+ send_log "file mkdir does not work, falling back on exec mkdir\n"
|
||||||
|
+ exec mkdir "$dirname"
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
|
||||||
|
|
||||||
|
proc safe_path [ ] {
|
||||||
|
diff --git a/find/testsuite/find.gnu/execdir-multiple.exp b/find/testsuite/find.gnu/execdir-multiple.exp
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..6d4bd66
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/find/testsuite/find.gnu/execdir-multiple.exp
|
||||||
|
@@ -0,0 +1,55 @@
|
||||||
|
+# tests for -execdir ... \+
|
||||||
|
+
|
||||||
|
+# Create 4 empty files in each of 6 directories.
|
||||||
|
+# Also create a shell script in each of those 6 directories.
|
||||||
|
+# Run a find command which runs the shell script for each empty file.
|
||||||
|
+# Check to make sure that each file is mentioned exactly once, and that
|
||||||
|
+# the command was run with the correct working directory.
|
||||||
|
+#
|
||||||
|
+# The output is a sequence of lines of this form:
|
||||||
|
+#
|
||||||
|
+# cwd ./basename
|
||||||
|
+#
|
||||||
|
+# cmd is the basename of the current directory at the time the command
|
||||||
|
+# is run by -execidr. ./basename is the name of the file that was matched
|
||||||
|
+# (that is, it's the value passed in {}).
|
||||||
|
+
|
||||||
|
+# $body is the body of a shell script we use for testing.
|
||||||
|
+# It prints a series of lines of the form described above.
|
||||||
|
+# One line is printed for each command-line argument.
|
||||||
|
+set body {#! /bin/sh
|
||||||
|
+set -e
|
||||||
|
+here=`pwd`
|
||||||
|
+d=`basename $here`
|
||||||
|
+
|
||||||
|
+for arg;
|
||||||
|
+do
|
||||||
|
+ echo "$d" "$arg"
|
||||||
|
+done | LC_ALL=C sort
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+if { [ safe_path ] } {
|
||||||
|
+ global SKIP_OLD
|
||||||
|
+
|
||||||
|
+ exec rm -rf tmp
|
||||||
|
+ mkdir tmp
|
||||||
|
+
|
||||||
|
+ # Put a copy of our shell script in each
|
||||||
|
+ # directory, plus some files.
|
||||||
|
+ foreach dir { a b c d e f } {
|
||||||
|
+ mkdir "tmp/$dir"
|
||||||
|
+ set script_name "tmp/$dir/runme"
|
||||||
|
+ set f [open "$script_name" "w" 0700 ]
|
||||||
|
+ puts $f "$body"
|
||||||
|
+ close $f
|
||||||
|
+ foreach item { one two three four } {
|
||||||
|
+ touch "tmp/$dir/$item"
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ set SKIP_OLD 1
|
||||||
|
+ find_start p {tmp -type f -empty -execdir sh ./runme \{\} + } ""
|
||||||
|
+ set SKIP_OLD 0
|
||||||
|
+ exec rm -rf tmp
|
||||||
|
+}
|
||||||
|
diff --git a/find/testsuite/find.gnu/execdir-multiple.xo b/find/testsuite/find.gnu/execdir-multiple.xo
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..a4f93d9
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/find/testsuite/find.gnu/execdir-multiple.xo
|
||||||
|
@@ -0,0 +1,24 @@
|
||||||
|
+a ./one
|
||||||
|
+a ./two
|
||||||
|
+a ./three
|
||||||
|
+a ./four
|
||||||
|
+b ./one
|
||||||
|
+b ./two
|
||||||
|
+b ./three
|
||||||
|
+b ./four
|
||||||
|
+c ./one
|
||||||
|
+c ./two
|
||||||
|
+c ./three
|
||||||
|
+c ./four
|
||||||
|
+d ./one
|
||||||
|
+d ./two
|
||||||
|
+d ./three
|
||||||
|
+d ./four
|
||||||
|
+e ./one
|
||||||
|
+e ./two
|
||||||
|
+e ./three
|
||||||
|
+e ./four
|
||||||
|
+f ./one
|
||||||
|
+f ./two
|
||||||
|
+f ./three
|
||||||
|
+f ./four
|
||||||
|
diff --git a/find/testsuite/find.gnu/execdir-pwd1.exp b/find/testsuite/find.gnu/execdir-pwd1.exp
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..e9863ac
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/find/testsuite/find.gnu/execdir-pwd1.exp
|
||||||
|
@@ -0,0 +1,20 @@
|
||||||
|
+# tests for working directory of -execdir {} \;
|
||||||
|
+if { [ safe_path ] } {
|
||||||
|
+ global SKIP_OLD
|
||||||
|
+
|
||||||
|
+ exec rm -rf tmp
|
||||||
|
+ exec mkdir tmp
|
||||||
|
+
|
||||||
|
+ # Create an empty shell script.
|
||||||
|
+ exec touch tmp/foo
|
||||||
|
+ exec chmod +x tmp/foo
|
||||||
|
+
|
||||||
|
+ # The -execdir should find the "foo" in the current directory.
|
||||||
|
+ # If not, the find command is probably executing the command
|
||||||
|
+ # built up by -execdir in the wrong directory.
|
||||||
|
+
|
||||||
|
+ set SKIP_OLD 1
|
||||||
|
+ find_start p {tmp -name foo -execdir sh ./foo \{\} \; } ""
|
||||||
|
+ set SKIP_OLD 0
|
||||||
|
+ exec rm -rf tmp
|
||||||
|
+}
|
945
findutils-4.5.8-0002-7dc7006.patch
Normal file
945
findutils-4.5.8-0002-7dc7006.patch
Normal file
@ -0,0 +1,945 @@
|
|||||||
|
ChangeLog | 83 +++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
find/defs.h | 14 ++++----
|
||||||
|
find/find.c | 69 +++++--------------------------------
|
||||||
|
find/finddata.c | 12 +-----
|
||||||
|
find/ftsfind.c | 49 ++-------------------------
|
||||||
|
find/parser.c | 35 ++++++------------
|
||||||
|
find/pred.c | 92 +++++++++++++++++++++++++++++++++-----------------
|
||||||
|
find/util.c | 89 +++++++++++++++++++++++++++++++++++++++---------
|
||||||
|
import-gnulib.config | 1 +
|
||||||
|
lib/dircallback.c | 36 +++++++++++++++++++-
|
||||||
|
lib/dircallback.h | 5 ++-
|
||||||
|
lib/listfile.c | 2 +-
|
||||||
|
12 files changed, 291 insertions(+), 196 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/ChangeLog b/ChangeLog
|
||||||
|
index 34552d5..fefc1b8 100644
|
||||||
|
--- a/ChangeLog
|
||||||
|
+++ b/ChangeLog
|
||||||
|
@@ -1,5 +1,88 @@
|
||||||
|
2010-04-10 James Youngman <jay@gnu.org>
|
||||||
|
|
||||||
|
+ Exec predicates now store which directory they want to run in.
|
||||||
|
+ * lib/dircallback.c (run_in_dirfd): New name for old run_in_dir
|
||||||
|
+ function.
|
||||||
|
+ (run_in_dir): Like the old function of the same name, but now
|
||||||
|
+ takes an argument const struct saved_cwd *.
|
||||||
|
+ * lib/dircallback.h: Update declarations of run_in_dirfd and
|
||||||
|
+ run_in_dir.
|
||||||
|
+ * find/util.c: Include dircallback.h, xalloc.h, save-cwd.h.
|
||||||
|
+ (do_complete_pending_execdirs): Remove dir_fd parameter, since the
|
||||||
|
+ per-predicate data structures now indicate what directory they
|
||||||
|
+ need to be run in. Instead of calling bc_do_exec directly, use a
|
||||||
|
+ callback 'exec_cb' that uses run_in_dir (which now takes a
|
||||||
|
+ saved_cwd* parameter instead of a file descriptor).
|
||||||
|
+ (do_exec): Called by do_complete_pending_execdirs, and simply uses
|
||||||
|
+ run_in_dir to call exec_cb, restoring the working directory
|
||||||
|
+ afterward.
|
||||||
|
+ (record_initial_cwd): New function, initialises the global
|
||||||
|
+ variable initial_wd.
|
||||||
|
+ (cleanup_initial_cwd): New function, cleans up the global variable
|
||||||
|
+ initial_wd.
|
||||||
|
+ (cleanup): Call cleanup_initial_cwd.
|
||||||
|
+ (get_start_dirfd): Remove.
|
||||||
|
+ (is_exec_in_local_dir): New function; true for predicates -execdir
|
||||||
|
+ and -okdir.
|
||||||
|
+ * find/pred.c: Include save-cwd.h.
|
||||||
|
+ (record_exec_dir): New function, sets the value of
|
||||||
|
+ execp->wd_for_exec if needed.
|
||||||
|
+ (new_impl_pred_exec): Remove the obsolete dir_fd parameter. Call
|
||||||
|
+ record_exec_dir.
|
||||||
|
+ (pred_exec): Don't pass the dir_fd parameter.
|
||||||
|
+ (pred_execdir): Likewise.
|
||||||
|
+ (pred_ok): Likewise.
|
||||||
|
+ (pred_okdir): Likewise.
|
||||||
|
+ (can_access): Call run_in_dirfd rather than run_in_dir (the
|
||||||
|
+ function was renamed).
|
||||||
|
+ (prep_child_for_exec): Remove dir_fd parameter; don't fchdir to
|
||||||
|
+ that. Call restore_cwd instead (passing a saved_cwd* parameter
|
||||||
|
+ which replaced dir_fd).
|
||||||
|
+ (launch): Remove references to execp->use_current_dir.
|
||||||
|
+ (launch): Change references to execp->dir_fd to execp->wd_for_exec.
|
||||||
|
+ * find/parser.c: Correct indentiation of declaration of
|
||||||
|
+ insert_exec_ok and remove the obsolete dir_fd parameter.
|
||||||
|
+ (parse_exec): Don't pass the dir_fd parameter to insert_exec_ok.
|
||||||
|
+ (parse_execdir): Likewise.
|
||||||
|
+ (parse_ok): Likewise.
|
||||||
|
+ (parse_okdir): Likewise.
|
||||||
|
+ (insert_exec_ok): Remove obsolete dir_fd paramter. Initialise
|
||||||
|
+ execp->wd_for_exec, either to NULL (for -*dir) or to the
|
||||||
|
+ initial_wd.
|
||||||
|
+ * find/ftsfind.c: Remove get_current_dirfd. Remove
|
||||||
|
+ complete_execdirs_cb.
|
||||||
|
+ (consider_visiting): Call complete_pending_execdirs directly.
|
||||||
|
+ (main): Call record_initial_cwd to record the initial working
|
||||||
|
+ directory, early on. Don't initialise starting_dir or
|
||||||
|
+ starting_desc, they have been removed.
|
||||||
|
+ * find/finddata.c: Include save-cwd.h. Remove starting_dir and
|
||||||
|
+ starting_desc. Add new global variable initial_wd. It is a struct
|
||||||
|
+ saved_wd* and represents find's initial working directory.
|
||||||
|
+ * find/find.c: Include save-cwd.h.
|
||||||
|
+ (main): Call record_initial_cwd in order to initialise the
|
||||||
|
+ global variable initial_wd Don't set starting_desc and
|
||||||
|
+ starting_dir, since those variables have been removed.
|
||||||
|
+ (safely_chdir): Don't pass an fd to complete_pending_execdirs.
|
||||||
|
+ (chdir_back): Remove the safety check (since we are using fchdir
|
||||||
|
+ and in any case no longer have all the data that the existing
|
||||||
|
+ wd_sanity_check function wants).
|
||||||
|
+ (do_process_top_dir): Don't pass an fd to
|
||||||
|
+ complete_pending_execdirs.
|
||||||
|
+ (process_dir): Likewise.
|
||||||
|
+ * find/defs.h (struct exec_val): Remove use_current_dir and
|
||||||
|
+ dir_fd. Replace with wd_for_exec, which is a struct saved_wd*.
|
||||||
|
+ (get_start_dirfd): Remove prototype.
|
||||||
|
+ (get_current_dirfd): Remove prototype.
|
||||||
|
+ (complete_pending_execdirs): No longer takes dir_fd parameter.
|
||||||
|
+ (record_initial_cwd): Add prototype.
|
||||||
|
+ (is_exec_in_local_dir): Add prototype.
|
||||||
|
+ (options): Declare.
|
||||||
|
+ (initial_wd): Add declaration. It is a struct saved_wd* and
|
||||||
|
+ represents find's initial working directory.
|
||||||
|
+ (starting_dir): Remove declaration of global variable.
|
||||||
|
+ (starting_desc): Remove declaration of global variable.
|
||||||
|
+ * import-gnulib.config (modules): Import module save-cwd.
|
||||||
|
+
|
||||||
|
Add a test which checks $CWD for find -execdir {} +/;
|
||||||
|
* find/testsuite/find.gnu/execdir-multiple.exp: New test; verifies
|
||||||
|
that for -execdir +, all the execs occur with the correct working
|
||||||
|
diff --git a/find/defs.h b/find/defs.h
|
||||||
|
index 36d428d..b4c1339 100644
|
||||||
|
--- a/find/defs.h
|
||||||
|
+++ b/find/defs.h
|
||||||
|
@@ -196,9 +196,8 @@ struct exec_val
|
||||||
|
struct buildcmd_state state;
|
||||||
|
char **replace_vec; /* Command arguments (for ";" style) */
|
||||||
|
int num_args;
|
||||||
|
- boolean use_current_dir; /* If nonzero, don't chdir to start dir */
|
||||||
|
boolean close_stdin; /* If true, close stdin in the child. */
|
||||||
|
- int dir_fd; /* The directory to do the exec in. */
|
||||||
|
+ struct saved_cwd *wd_for_exec;/* What directory to perform the exec in. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The format string for a -printf or -fprintf is chopped into one or
|
||||||
|
@@ -337,8 +336,6 @@ struct predicate
|
||||||
|
|
||||||
|
/* find.c, ftsfind.c */
|
||||||
|
boolean is_fts_enabled(int *ftsoptions);
|
||||||
|
-int get_start_dirfd(void);
|
||||||
|
-int get_current_dirfd(void);
|
||||||
|
|
||||||
|
/* find library function declarations. */
|
||||||
|
|
||||||
|
@@ -493,8 +490,11 @@ struct predicate *insert_primary_withpred PARAMS((const struct parser_table *ent
|
||||||
|
void usage PARAMS((FILE *fp, int status, char *msg));
|
||||||
|
extern boolean check_nofollow(void);
|
||||||
|
void complete_pending_execs(struct predicate *p);
|
||||||
|
-void complete_pending_execdirs(int dir_fd); /* Passing dir_fd is an unpleasant CodeSmell. */
|
||||||
|
+void complete_pending_execdirs(void);
|
||||||
|
const char *safely_quote_err_filename (int n, char const *arg);
|
||||||
|
+void record_initial_cwd (void);
|
||||||
|
+boolean is_exec_in_local_dir(const PRED_FUNC pred_func);
|
||||||
|
+
|
||||||
|
void fatal_file_error(const char *name) ATTRIBUTE_NORETURN;
|
||||||
|
void nonfatal_file_error(const char *name);
|
||||||
|
|
||||||
|
@@ -660,10 +660,10 @@ struct state
|
||||||
|
};
|
||||||
|
|
||||||
|
/* finddata.c */
|
||||||
|
+extern struct options options;
|
||||||
|
extern struct state state;
|
||||||
|
-extern char const *starting_dir;
|
||||||
|
-extern int starting_desc;
|
||||||
|
extern char *program_name;
|
||||||
|
+extern struct saved_cwd *initial_wd;
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
diff --git a/find/find.c b/find/find.c
|
||||||
|
index 171988f..badcf3c 100644
|
||||||
|
--- a/find/find.c
|
||||||
|
+++ b/find/find.c
|
||||||
|
@@ -52,6 +52,7 @@
|
||||||
|
#include "quotearg.h"
|
||||||
|
#include "xgetcwd.h"
|
||||||
|
#include "error.h"
|
||||||
|
+#include "save-cwd.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_LOCALE_H
|
||||||
|
#include <locale.h>
|
||||||
|
@@ -131,6 +132,8 @@ main (int argc, char **argv)
|
||||||
|
program_name = argv[0];
|
||||||
|
state.exit_status = 0;
|
||||||
|
|
||||||
|
+ record_initial_cwd ();
|
||||||
|
+
|
||||||
|
/* Set the option defaults before we do the locale
|
||||||
|
* initialisation as check_nofollow() needs to be executed in the
|
||||||
|
* POSIX locale.
|
||||||
|
@@ -183,23 +186,6 @@ main (int argc, char **argv)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- starting_desc = open (".", O_RDONLY
|
||||||
|
-#if defined O_LARGEFILE
|
||||||
|
- |O_LARGEFILE
|
||||||
|
-#endif
|
||||||
|
- );
|
||||||
|
- if (0 <= starting_desc && fchdir (starting_desc) != 0)
|
||||||
|
- {
|
||||||
|
- close (starting_desc);
|
||||||
|
- starting_desc = -1;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (starting_desc < 0)
|
||||||
|
- {
|
||||||
|
- starting_dir = xgetcwd ();
|
||||||
|
- if (! starting_dir)
|
||||||
|
- error (1, errno, _("cannot get current directory"));
|
||||||
|
- }
|
||||||
|
set_stat_placeholders(&starting_stat_buf);
|
||||||
|
if ((*options.xstat) (".", &starting_stat_buf) != 0)
|
||||||
|
error (1, errno, _("cannot stat current directory"));
|
||||||
|
@@ -876,7 +862,7 @@ safely_chdir(const char *dest,
|
||||||
|
* processed, do them now because they must be done in the same
|
||||||
|
* directory.
|
||||||
|
*/
|
||||||
|
- complete_pending_execdirs(get_current_dirfd());
|
||||||
|
+ complete_pending_execdirs ();
|
||||||
|
|
||||||
|
#if !defined(O_NOFOLLOW)
|
||||||
|
options.open_nofollow_available = false;
|
||||||
|
@@ -911,45 +897,10 @@ safely_chdir(const char *dest,
|
||||||
|
static void
|
||||||
|
chdir_back (void)
|
||||||
|
{
|
||||||
|
- struct stat stat_buf;
|
||||||
|
- boolean dummy;
|
||||||
|
-
|
||||||
|
- if (starting_desc < 0)
|
||||||
|
- {
|
||||||
|
- if (options.debug_options & DebugSearch)
|
||||||
|
- fprintf(stderr, "chdir_back(): chdir(\"%s\")\n", starting_dir);
|
||||||
|
-
|
||||||
|
-#ifdef STAT_MOUNTPOINTS
|
||||||
|
- /* We will need the mounted device list. Get it now if we don't
|
||||||
|
- * already have it.
|
||||||
|
- */
|
||||||
|
- if (NULL == mounted_devices)
|
||||||
|
- init_mounted_dev_list(1);
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
- if (chdir (starting_dir) != 0)
|
||||||
|
- fatal_file_error(starting_dir);
|
||||||
|
-
|
||||||
|
- wd_sanity_check(starting_dir,
|
||||||
|
- program_name,
|
||||||
|
- starting_dir,
|
||||||
|
- starting_stat_buf.st_dev,
|
||||||
|
- starting_stat_buf.st_ino,
|
||||||
|
- &stat_buf, 0, __LINE__,
|
||||||
|
- TraversingUp,
|
||||||
|
- FATAL_IF_SANITY_CHECK_FAILS,
|
||||||
|
- &dummy);
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- if (options.debug_options & DebugSearch)
|
||||||
|
- fprintf(stderr, "chdir_back(): chdir(<starting-point>)\n");
|
||||||
|
+ if (options.debug_options & DebugSearch)
|
||||||
|
+ fprintf (stderr, "chdir_back(): chdir to start point\n");
|
||||||
|
|
||||||
|
- if (fchdir (starting_desc) != 0)
|
||||||
|
- {
|
||||||
|
- fatal_file_error(starting_dir);
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ restore_cwd (initial_wd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move to the parent of a given directory and then call a function,
|
||||||
|
@@ -1038,7 +989,7 @@ static void do_process_top_dir(char *pathname,
|
||||||
|
(void) pstat;
|
||||||
|
|
||||||
|
process_path (pathname, base, false, ".", mode);
|
||||||
|
- complete_pending_execdirs(get_current_dirfd());
|
||||||
|
+ complete_pending_execdirs ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_process_predicate(char *pathname,
|
||||||
|
@@ -1326,7 +1277,7 @@ process_dir (char *pathname, char *name, int pathlen, const struct stat *statp,
|
||||||
|
* yet been processed, do them now because they must be done in
|
||||||
|
* the same directory.
|
||||||
|
*/
|
||||||
|
- complete_pending_execdirs(get_current_dirfd());
|
||||||
|
+ complete_pending_execdirs ();
|
||||||
|
|
||||||
|
if (strcmp (name, "."))
|
||||||
|
{
|
||||||
|
@@ -1464,7 +1415,7 @@ process_dir (char *pathname, char *name, int pathlen, const struct stat *statp,
|
||||||
|
* yet been processed, do them now because they must be done in
|
||||||
|
* the same directory.
|
||||||
|
*/
|
||||||
|
- complete_pending_execdirs(get_current_dirfd());
|
||||||
|
+ complete_pending_execdirs ();
|
||||||
|
|
||||||
|
if (strcmp (name, "."))
|
||||||
|
{
|
||||||
|
diff --git a/find/finddata.c b/find/finddata.c
|
||||||
|
index 373eb38..dcc8261 100644
|
||||||
|
--- a/find/finddata.c
|
||||||
|
+++ b/find/finddata.c
|
||||||
|
@@ -19,6 +19,7 @@
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include "defs.h"
|
||||||
|
+#include "save-cwd.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Name this program was run with. */
|
||||||
|
@@ -26,13 +27,4 @@ char *program_name;
|
||||||
|
|
||||||
|
struct options options;
|
||||||
|
struct state state;
|
||||||
|
-
|
||||||
|
-/* The full path of the initial working directory, or "." if
|
||||||
|
- STARTING_DESC is nonnegative. */
|
||||||
|
-char const *starting_dir = ".";
|
||||||
|
-
|
||||||
|
-/* A file descriptor open to the initial working directory.
|
||||||
|
- Doing it this way allows us to work when the i.w.d. has
|
||||||
|
- unreadable parents. */
|
||||||
|
-int starting_desc;
|
||||||
|
-
|
||||||
|
+struct saved_cwd *initial_wd = NULL;
|
||||||
|
diff --git a/find/ftsfind.c b/find/ftsfind.c
|
||||||
|
index 838b81f..9945abd 100644
|
||||||
|
--- a/find/ftsfind.c
|
||||||
|
+++ b/find/ftsfind.c
|
||||||
|
@@ -98,24 +98,6 @@ static int ftsoptions = FTS_NOSTAT|FTS_TIGHT_CYCLE_CHECK;
|
||||||
|
static int prev_depth = INT_MIN; /* fts_level can be < 0 */
|
||||||
|
static int curr_fd = -1;
|
||||||
|
|
||||||
|
-int get_current_dirfd(void)
|
||||||
|
-{
|
||||||
|
- if (ftsoptions & FTS_CWDFD)
|
||||||
|
- {
|
||||||
|
- assert (curr_fd != -1);
|
||||||
|
- assert ( (AT_FDCWD == curr_fd) || (curr_fd >= 0) );
|
||||||
|
-
|
||||||
|
- if (AT_FDCWD == curr_fd)
|
||||||
|
- return starting_desc;
|
||||||
|
- else
|
||||||
|
- return curr_fd;
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- return AT_FDCWD;
|
||||||
|
- }
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static void left_dir(void)
|
||||||
|
{
|
||||||
|
if (ftsoptions & FTS_CWDFD)
|
||||||
|
@@ -324,15 +306,6 @@ symlink_loop(const char *name)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-static int
|
||||||
|
-complete_execdirs_cb(void *context)
|
||||||
|
-{
|
||||||
|
- (void) context;
|
||||||
|
- /* By the tme this callback is called, the current directory is correct. */
|
||||||
|
- complete_pending_execdirs(AT_FDCWD);
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static void
|
||||||
|
show_outstanding_execdirs(FILE *fp)
|
||||||
|
{
|
||||||
|
@@ -566,7 +539,7 @@ consider_visiting(FTS *p, FTSENT *ent)
|
||||||
|
if (state.execdirs_outstanding)
|
||||||
|
{
|
||||||
|
show_outstanding_execdirs(stderr);
|
||||||
|
- run_in_dir(p->fts_cwd_fd, complete_execdirs_cb, NULL);
|
||||||
|
+ complete_pending_execdirs ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ent->fts_info == FTS_DP)
|
||||||
|
@@ -670,6 +643,8 @@ main (int argc, char **argv)
|
||||||
|
state.execdirs_outstanding = false;
|
||||||
|
state.cwd_dir_fd = AT_FDCWD;
|
||||||
|
|
||||||
|
+ record_initial_cwd ();
|
||||||
|
+
|
||||||
|
/* Set the option defaults before we do the locale initialisation as
|
||||||
|
* check_nofollow() needs to be executed in the POSIX locale.
|
||||||
|
*/
|
||||||
|
@@ -719,24 +694,6 @@ main (int argc, char **argv)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- starting_desc = open (".", O_RDONLY
|
||||||
|
-#if defined O_LARGEFILE
|
||||||
|
- |O_LARGEFILE
|
||||||
|
-#endif
|
||||||
|
- );
|
||||||
|
- if (0 <= starting_desc && fchdir (starting_desc) != 0)
|
||||||
|
- {
|
||||||
|
- close (starting_desc);
|
||||||
|
- starting_desc = -1;
|
||||||
|
- }
|
||||||
|
- if (starting_desc < 0)
|
||||||
|
- {
|
||||||
|
- starting_dir = xgetcwd ();
|
||||||
|
- if (! starting_dir)
|
||||||
|
- error (1, errno, _("cannot get current directory"));
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
-
|
||||||
|
process_all_startpoints(argc-end_of_leading_options, argv+end_of_leading_options);
|
||||||
|
|
||||||
|
/* If "-exec ... {} +" has been used, there may be some
|
||||||
|
diff --git a/find/parser.c b/find/parser.c
|
||||||
|
index 3f237eb..b96d317 100644
|
||||||
|
--- a/find/parser.c
|
||||||
|
+++ b/find/parser.c
|
||||||
|
@@ -181,7 +181,6 @@ static struct segment **make_segment PARAMS((struct segment **segment,
|
||||||
|
struct predicate *pred));
|
||||||
|
static boolean insert_exec_ok PARAMS((const char *action,
|
||||||
|
const struct parser_table *entry,
|
||||||
|
- int dir_fd,
|
||||||
|
char *argv[],
|
||||||
|
int *arg_ptr));
|
||||||
|
static boolean get_comp_type PARAMS((const char **str,
|
||||||
|
@@ -928,13 +927,13 @@ parse_empty (const struct parser_table* entry, char **argv, int *arg_ptr)
|
||||||
|
static boolean
|
||||||
|
parse_exec (const struct parser_table* entry, char **argv, int *arg_ptr)
|
||||||
|
{
|
||||||
|
- return insert_exec_ok ("-exec", entry, get_start_dirfd(), argv, arg_ptr);
|
||||||
|
+ return insert_exec_ok ("-exec", entry, argv, arg_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
parse_execdir (const struct parser_table* entry, char **argv, int *arg_ptr)
|
||||||
|
{
|
||||||
|
- return insert_exec_ok ("-execdir", entry, -1, argv, arg_ptr);
|
||||||
|
+ return insert_exec_ok ("-execdir", entry, argv, arg_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
@@ -1790,13 +1789,13 @@ parse_nowarn (const struct parser_table* entry, char **argv, int *arg_ptr)
|
||||||
|
static boolean
|
||||||
|
parse_ok (const struct parser_table* entry, char **argv, int *arg_ptr)
|
||||||
|
{
|
||||||
|
- return insert_exec_ok ("-ok", entry, get_start_dirfd(), argv, arg_ptr);
|
||||||
|
+ return insert_exec_ok ("-ok", entry, argv, arg_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
parse_okdir (const struct parser_table* entry, char **argv, int *arg_ptr)
|
||||||
|
{
|
||||||
|
- return insert_exec_ok ("-okdir", entry, -1, argv, arg_ptr);
|
||||||
|
+ return insert_exec_ok ("-okdir", entry, argv, arg_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean
|
||||||
|
@@ -3158,11 +3157,10 @@ check_path_safety(const char *action, char **argv)
|
||||||
|
|
||||||
|
/* handles both exec and ok predicate */
|
||||||
|
static boolean
|
||||||
|
-new_insert_exec_ok (const char *action,
|
||||||
|
- const struct parser_table *entry,
|
||||||
|
- int dir_fd,
|
||||||
|
- char **argv,
|
||||||
|
- int *arg_ptr)
|
||||||
|
+insert_exec_ok (const char *action,
|
||||||
|
+ const struct parser_table *entry,
|
||||||
|
+ char **argv,
|
||||||
|
+ int *arg_ptr)
|
||||||
|
{
|
||||||
|
int start, end; /* Indexes in ARGV of start & end of cmd. */
|
||||||
|
int i; /* Index into cmd args */
|
||||||
|
@@ -3183,6 +3181,7 @@ new_insert_exec_ok (const char *action,
|
||||||
|
our_pred->need_type = our_pred->need_stat = false;
|
||||||
|
|
||||||
|
execp = &our_pred->args.exec_vec;
|
||||||
|
+ execp->wd_for_exec = NULL;
|
||||||
|
|
||||||
|
if ((func != pred_okdir) && (func != pred_ok))
|
||||||
|
{
|
||||||
|
@@ -3202,13 +3201,14 @@ new_insert_exec_ok (const char *action,
|
||||||
|
|
||||||
|
if ((func == pred_execdir) || (func == pred_okdir))
|
||||||
|
{
|
||||||
|
+ execp->wd_for_exec = NULL;
|
||||||
|
options.ignore_readdir_race = false;
|
||||||
|
check_path_safety(action, argv);
|
||||||
|
- execp->use_current_dir = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
- execp->use_current_dir = false;
|
||||||
|
+ assert (NULL != initial_wd);
|
||||||
|
+ execp->wd_for_exec = initial_wd;
|
||||||
|
}
|
||||||
|
|
||||||
|
our_pred->args.exec_vec.multiple = 0;
|
||||||
|
@@ -3361,17 +3361,6 @@ new_insert_exec_ok (const char *action,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-static boolean
|
||||||
|
-insert_exec_ok (const char *action,
|
||||||
|
- const struct parser_table *entry,
|
||||||
|
- int dir_fd,
|
||||||
|
- char **argv,
|
||||||
|
- int *arg_ptr)
|
||||||
|
-{
|
||||||
|
- return new_insert_exec_ok(action, entry, dir_fd, argv, arg_ptr);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-
|
||||||
|
|
||||||
|
/* Get a timestamp and comparison type.
|
||||||
|
|
||||||
|
diff --git a/find/pred.c b/find/pred.c
|
||||||
|
index 7c34119..d057d48 100644
|
||||||
|
--- a/find/pred.c
|
||||||
|
+++ b/find/pred.c
|
||||||
|
@@ -47,6 +47,7 @@
|
||||||
|
#include "dircallback.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "verify.h"
|
||||||
|
+#include "save-cwd.h"
|
||||||
|
|
||||||
|
#include <selinux/selinux.h>
|
||||||
|
|
||||||
|
@@ -502,8 +503,30 @@ pred_empty (const char *pathname, struct stat *stat_buf, struct predicate *pred_
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
+
|
||||||
|
static boolean
|
||||||
|
-new_impl_pred_exec (int dir_fd, const char *pathname,
|
||||||
|
+record_exec_dir (struct exec_val *execp)
|
||||||
|
+{
|
||||||
|
+ if (!execp->wd_for_exec)
|
||||||
|
+ {
|
||||||
|
+ /* working directory not already known, so must be a *dir variant,
|
||||||
|
+ and this must be the first arg we added. However, this may
|
||||||
|
+ be -execdir foo {} \; (i.e. not multiple). */
|
||||||
|
+ assert (!execp->state.todo);
|
||||||
|
+
|
||||||
|
+ /* Record the WD. */
|
||||||
|
+ execp->wd_for_exec = xmalloc (sizeof (*execp->wd_for_exec));
|
||||||
|
+ execp->wd_for_exec->name = NULL;
|
||||||
|
+ execp->wd_for_exec->desc = openat (state.cwd_dir_fd, ".", O_RDONLY);
|
||||||
|
+ if (execp->wd_for_exec->desc < 0)
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ return true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static boolean
|
||||||
|
+new_impl_pred_exec (const char *pathname,
|
||||||
|
struct stat *stat_buf,
|
||||||
|
struct predicate *pred_ptr,
|
||||||
|
const char *prefix, size_t pfxlen)
|
||||||
|
@@ -512,7 +535,32 @@ new_impl_pred_exec (int dir_fd, const char *pathname,
|
||||||
|
size_t len = strlen(pathname);
|
||||||
|
|
||||||
|
(void) stat_buf;
|
||||||
|
- execp->dir_fd = dir_fd;
|
||||||
|
+
|
||||||
|
+ if (is_exec_in_local_dir (pred_ptr->pred_func))
|
||||||
|
+ {
|
||||||
|
+ /* For -execdir/-okdir predicates, the parser did not fill in
|
||||||
|
+ the wd_for_exec member of sturct exec_val. So for those
|
||||||
|
+ predicates, we do so now.
|
||||||
|
+ */
|
||||||
|
+ if (!record_exec_dir (execp))
|
||||||
|
+ {
|
||||||
|
+ error (EXIT_FAILURE, errno,
|
||||||
|
+ _("Failed to save working directory in order to "
|
||||||
|
+ "run a command on %s"),
|
||||||
|
+ safely_quote_err_filename (0, pathname));
|
||||||
|
+ /*NOTREACHED*/
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ /* For the others (-exec, -ok), the parser should
|
||||||
|
+ have set wd_for_exec to initial_wd, indicating
|
||||||
|
+ that the exec should take place from find's initial
|
||||||
|
+ working directory.
|
||||||
|
+ */
|
||||||
|
+ assert (execp->wd_for_exec == initial_wd);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (execp->multiple)
|
||||||
|
{
|
||||||
|
/* Push the argument onto the current list.
|
||||||
|
@@ -558,8 +606,7 @@ new_impl_pred_exec (int dir_fd, const char *pathname,
|
||||||
|
boolean
|
||||||
|
pred_exec (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
|
||||||
|
{
|
||||||
|
- return new_impl_pred_exec(get_start_dirfd(),
|
||||||
|
- pathname, stat_buf, pred_ptr, NULL, 0);
|
||||||
|
+ return new_impl_pred_exec(pathname, stat_buf, pred_ptr, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean
|
||||||
|
@@ -567,8 +614,7 @@ pred_execdir (const char *pathname, struct stat *stat_buf, struct predicate *pre
|
||||||
|
{
|
||||||
|
const char *prefix = (state.rel_pathname[0] == '/') ? NULL : "./";
|
||||||
|
(void) &pathname;
|
||||||
|
- return new_impl_pred_exec (get_current_dirfd(),
|
||||||
|
- state.rel_pathname, stat_buf, pred_ptr,
|
||||||
|
+ return new_impl_pred_exec (state.rel_pathname, stat_buf, pred_ptr,
|
||||||
|
prefix, (prefix ? 2 : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1460,8 +1506,7 @@ boolean
|
||||||
|
pred_ok (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
|
||||||
|
{
|
||||||
|
if (is_ok(pred_ptr->args.exec_vec.replace_vec[0], pathname))
|
||||||
|
- return new_impl_pred_exec (get_start_dirfd(),
|
||||||
|
- pathname, stat_buf, pred_ptr, NULL, 0);
|
||||||
|
+ return new_impl_pred_exec (pathname, stat_buf, pred_ptr, NULL, 0);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@@ -1471,8 +1516,7 @@ pred_okdir (const char *pathname, struct stat *stat_buf, struct predicate *pred_
|
||||||
|
{
|
||||||
|
const char *prefix = (state.rel_pathname[0] == '/') ? NULL : "./";
|
||||||
|
if (is_ok(pred_ptr->args.exec_vec.replace_vec[0], pathname))
|
||||||
|
- return new_impl_pred_exec (get_current_dirfd(),
|
||||||
|
- state.rel_pathname, stat_buf, pred_ptr,
|
||||||
|
+ return new_impl_pred_exec (state.rel_pathname, stat_buf, pred_ptr,
|
||||||
|
prefix, (prefix ? 2 : 0));
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
@@ -1573,7 +1617,7 @@ can_access(int access_type)
|
||||||
|
args.filename = state.rel_pathname;
|
||||||
|
args.access_type = access_type;
|
||||||
|
args.cb_errno = 0;
|
||||||
|
- return 0 == run_in_dir(state.cwd_dir_fd, access_callback, &args);
|
||||||
|
+ return 0 == run_in_dirfd (state.cwd_dir_fd, access_callback, &args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1912,7 +1956,7 @@ pred_context (const char *pathname, struct stat *stat_buf,
|
||||||
|
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
-prep_child_for_exec (boolean close_stdin, int dir_fd)
|
||||||
|
+prep_child_for_exec (boolean close_stdin, const struct saved_cwd *wd)
|
||||||
|
{
|
||||||
|
boolean ok = true;
|
||||||
|
if (close_stdin)
|
||||||
|
@@ -1948,17 +1992,10 @@ prep_child_for_exec (boolean close_stdin, int dir_fd)
|
||||||
|
* announcement of a call to stat() anyway, as we're about to exec
|
||||||
|
* something.
|
||||||
|
*/
|
||||||
|
- if (dir_fd != AT_FDCWD)
|
||||||
|
+ if (0 != restore_cwd (wd))
|
||||||
|
{
|
||||||
|
- assert (dir_fd >= 0);
|
||||||
|
- if (0 != fchdir(dir_fd))
|
||||||
|
- {
|
||||||
|
- /* If we cannot execute our command in the correct directory,
|
||||||
|
- * we should not execute it at all.
|
||||||
|
- */
|
||||||
|
- error(0, errno, _("Failed to change directory"));
|
||||||
|
- ok = false;
|
||||||
|
- }
|
||||||
|
+ error (0, errno, _("Failed to change directory"));
|
||||||
|
+ ok = false;
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
@@ -1974,13 +2011,6 @@ launch (const struct buildcmd_control *ctl,
|
||||||
|
static int first_time = 1;
|
||||||
|
const struct exec_val *execp = buildstate->usercontext;
|
||||||
|
|
||||||
|
- if (!execp->use_current_dir)
|
||||||
|
- {
|
||||||
|
- assert (starting_desc >= 0);
|
||||||
|
- assert (execp->dir_fd == starting_desc);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
-
|
||||||
|
/* Null terminate the arg list. */
|
||||||
|
bc_push_arg (ctl, buildstate, (char *) NULL, 0, NULL, 0, false);
|
||||||
|
|
||||||
|
@@ -2001,8 +2031,8 @@ launch (const struct buildcmd_control *ctl,
|
||||||
|
if (child_pid == 0)
|
||||||
|
{
|
||||||
|
/* We are the child. */
|
||||||
|
- assert (starting_desc >= 0);
|
||||||
|
- if (!prep_child_for_exec(execp->close_stdin, execp->dir_fd))
|
||||||
|
+ assert (NULL != execp->wd_for_exec);
|
||||||
|
+ if (!prep_child_for_exec (execp->close_stdin, execp->wd_for_exec))
|
||||||
|
{
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
diff --git a/find/util.c b/find/util.c
|
||||||
|
index d3cb467..da4fc62 100644
|
||||||
|
--- a/find/util.c
|
||||||
|
+++ b/find/util.c
|
||||||
|
@@ -36,6 +36,9 @@
|
||||||
|
#include "error.h"
|
||||||
|
#include "verify.h"
|
||||||
|
#include "openat.h"
|
||||||
|
+#include "dircallback.h"
|
||||||
|
+#include "xalloc.h"
|
||||||
|
+#include "save-cwd.h"
|
||||||
|
|
||||||
|
#if ENABLE_NLS
|
||||||
|
# include <libintl.h>
|
||||||
|
@@ -282,6 +285,26 @@ check_nofollow(void)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+exec_cb (void *context)
|
||||||
|
+{
|
||||||
|
+ struct exec_val *execp = context;
|
||||||
|
+ launch (&execp->ctl, &execp->state);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+do_exec (struct exec_val *execp)
|
||||||
|
+{
|
||||||
|
+ run_in_dir (execp->wd_for_exec, exec_cb, execp);
|
||||||
|
+ if (execp->wd_for_exec != initial_wd)
|
||||||
|
+ {
|
||||||
|
+ free_cwd (execp->wd_for_exec);
|
||||||
|
+ free (execp->wd_for_exec);
|
||||||
|
+ execp->wd_for_exec = NULL;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
|
||||||
|
/* Examine the predicate list for instances of -execdir or -okdir
|
||||||
|
* which have been terminated with '+' (build argument list) rather
|
||||||
|
@@ -289,14 +312,14 @@ check_nofollow(void)
|
||||||
|
* have no effect if there are no arguments waiting).
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
-do_complete_pending_execdirs(struct predicate *p, int dir_fd)
|
||||||
|
+do_complete_pending_execdirs(struct predicate *p)
|
||||||
|
{
|
||||||
|
if (NULL == p)
|
||||||
|
return;
|
||||||
|
|
||||||
|
assert (state.execdirs_outstanding);
|
||||||
|
|
||||||
|
- do_complete_pending_execdirs(p->pred_left, dir_fd);
|
||||||
|
+ do_complete_pending_execdirs(p->pred_left);
|
||||||
|
|
||||||
|
if (pred_is(p, pred_execdir) || pred_is(p, pred_okdir))
|
||||||
|
{
|
||||||
|
@@ -311,25 +334,24 @@ do_complete_pending_execdirs(struct predicate *p, int dir_fd)
|
||||||
|
if (execp->state.todo)
|
||||||
|
{
|
||||||
|
/* There are not-yet-executed arguments. */
|
||||||
|
- launch (&execp->ctl, &execp->state);
|
||||||
|
+ do_exec (execp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- do_complete_pending_execdirs(p->pred_right, dir_fd);
|
||||||
|
+ do_complete_pending_execdirs(p->pred_right);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
-complete_pending_execdirs(int dir_fd)
|
||||||
|
+complete_pending_execdirs (void)
|
||||||
|
{
|
||||||
|
if (state.execdirs_outstanding)
|
||||||
|
{
|
||||||
|
- do_complete_pending_execdirs(get_eval_tree(), dir_fd);
|
||||||
|
+ do_complete_pending_execdirs(get_eval_tree());
|
||||||
|
state.execdirs_outstanding = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-
|
||||||
|
|
||||||
|
/* Examine the predicate list for instances of -exec which have been
|
||||||
|
* terminated with '+' (build argument list) rather than ';' (singles
|
||||||
|
@@ -365,6 +387,37 @@ complete_pending_execs(struct predicate *p)
|
||||||
|
|
||||||
|
complete_pending_execs(p->pred_right);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+record_initial_cwd (void)
|
||||||
|
+{
|
||||||
|
+ initial_wd = xmalloc (sizeof (*initial_wd));
|
||||||
|
+ if (0 != save_cwd (initial_wd))
|
||||||
|
+ {
|
||||||
|
+ error (EXIT_FAILURE, errno,
|
||||||
|
+ _("failed to save initial working directory"));
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+cleanup_initial_cwd (void)
|
||||||
|
+{
|
||||||
|
+ if (0 == restore_cwd (initial_wd))
|
||||||
|
+ {
|
||||||
|
+ free_cwd (initial_wd);
|
||||||
|
+ free (initial_wd);
|
||||||
|
+ initial_wd = NULL;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ /* since we may already be in atexit, die with _exit(). */
|
||||||
|
+ error (0, errno,
|
||||||
|
+ _("failed to restore initial working directory"));
|
||||||
|
+ _exit (EXIT_FAILURE);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
|
||||||
|
static void
|
||||||
|
traverse_tree(struct predicate *tree,
|
||||||
|
@@ -424,9 +477,11 @@ cleanup(void)
|
||||||
|
if (eval_tree)
|
||||||
|
{
|
||||||
|
traverse_tree(eval_tree, complete_pending_execs);
|
||||||
|
- complete_pending_execdirs(get_current_dirfd());
|
||||||
|
+ complete_pending_execdirs ();
|
||||||
|
traverse_tree(eval_tree, flush_and_close_output_files);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ cleanup_initial_cwd ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Savannah bug #16378 manifests as an assertion failure in pred_type()
|
||||||
|
@@ -963,15 +1018,6 @@ set_option_defaults(struct options *p)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-/* get_start_dirfd
|
||||||
|
- *
|
||||||
|
- * Returns the fd for the directory we started in.
|
||||||
|
- */
|
||||||
|
-int get_start_dirfd(void)
|
||||||
|
-{
|
||||||
|
- return starting_desc;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
/* apply_predicate
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@@ -997,6 +1043,15 @@ apply_predicate(const char *pathname, struct stat *stat_buf, struct predicate *p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* is_exec_in_local_dir
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+bool
|
||||||
|
+is_exec_in_local_dir (const PRED_FUNC pred_func)
|
||||||
|
+{
|
||||||
|
+ return pred_execdir == pred_func || pred_okdir == pred_func;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
|
||||||
|
/* safely_quote_err_filename
|
||||||
|
*
|
||||||
|
diff --git a/import-gnulib.config b/import-gnulib.config
|
||||||
|
index f2e8998..b1f0851 100644
|
||||||
|
--- a/import-gnulib.config
|
||||||
|
+++ b/import-gnulib.config
|
||||||
|
@@ -67,6 +67,7 @@ quotearg
|
||||||
|
realloc
|
||||||
|
regex
|
||||||
|
rpmatch
|
||||||
|
+save-cwd
|
||||||
|
savedir
|
||||||
|
stat-macros
|
||||||
|
stat-time
|
||||||
|
diff --git a/lib/dircallback.c b/lib/dircallback.c
|
||||||
|
index 5dbf3b3..f96fccc 100644
|
||||||
|
--- a/lib/dircallback.c
|
||||||
|
+++ b/lib/dircallback.c
|
||||||
|
@@ -54,7 +54,41 @@
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
-run_in_dir (int dir_fd, int (*callback)(void*), void *usercontext)
|
||||||
|
+run_in_dir (const struct saved_cwd *there,
|
||||||
|
+ int (*callback)(void*), void *usercontext)
|
||||||
|
+{
|
||||||
|
+ int err = -1;
|
||||||
|
+ int saved_errno = 0;
|
||||||
|
+ struct saved_cwd here;
|
||||||
|
+ if (0 == save_cwd (&here))
|
||||||
|
+ {
|
||||||
|
+ if (0 == restore_cwd (there))
|
||||||
|
+ {
|
||||||
|
+ err = callback(usercontext);
|
||||||
|
+ saved_errno = (err < 0 ? errno : 0);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ openat_restore_fail (errno);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (restore_cwd (&here) != 0)
|
||||||
|
+ openat_restore_fail (errno);
|
||||||
|
+
|
||||||
|
+ free_cwd (&here);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ openat_save_fail (errno);
|
||||||
|
+ }
|
||||||
|
+ if (saved_errno)
|
||||||
|
+ errno = saved_errno;
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+run_in_dirfd (int dir_fd, int (*callback)(void*), void *usercontext)
|
||||||
|
{
|
||||||
|
if (dir_fd == AT_FDCWD)
|
||||||
|
{
|
||||||
|
diff --git a/lib/dircallback.h b/lib/dircallback.h
|
||||||
|
index 41ea282..3234113 100644
|
||||||
|
--- a/lib/dircallback.h
|
||||||
|
+++ b/lib/dircallback.h
|
||||||
|
@@ -19,6 +19,9 @@
|
||||||
|
#if !defined DIRCALLBACK_H
|
||||||
|
# define DIRCALLBACK_H
|
||||||
|
|
||||||
|
-int run_in_dir (int dir_fd, int (*callback)(void*), void *usercontext);
|
||||||
|
+struct saved_cwd;
|
||||||
|
+
|
||||||
|
+int run_in_dirfd (int fd, int (*callback)(void*), void *usercontext);
|
||||||
|
+int run_in_dir (struct saved_cwd*, int (*callback)(void*), void *usercontext);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
diff --git a/lib/listfile.c b/lib/listfile.c
|
||||||
|
index ca9eae2..b5bee54 100644
|
||||||
|
--- a/lib/listfile.c
|
||||||
|
+++ b/lib/listfile.c
|
||||||
|
@@ -424,7 +424,7 @@ get_link_name_at (const char *name, int dir_fd, char *relname)
|
||||||
|
args.result = NULL;
|
||||||
|
args.name = name;
|
||||||
|
args.relname = relname;
|
||||||
|
- if (0 == run_in_dir(dir_fd, get_link_name_cb, &args))
|
||||||
|
+ if (0 == run_in_dirfd (dir_fd, get_link_name_cb, &args))
|
||||||
|
return args.result;
|
||||||
|
else
|
||||||
|
return NULL;
|
107
findutils-4.5.8-0003-27a7e45.patch
Normal file
107
findutils-4.5.8-0003-27a7e45.patch
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
ChangeLog | 10 ++++++++++
|
||||||
|
NEWS | 15 +++++++++++++++
|
||||||
|
find/ftsfind.c | 37 +++++++++++++++++++------------------
|
||||||
|
3 files changed, 44 insertions(+), 18 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/ChangeLog b/ChangeLog
|
||||||
|
index fefc1b8..98d7962 100644
|
||||||
|
--- a/ChangeLog
|
||||||
|
+++ b/ChangeLog
|
||||||
|
@@ -1,5 +1,15 @@
|
||||||
|
2010-04-10 James Youngman <jay@gnu.org>
|
||||||
|
|
||||||
|
+ Fix Savannah bug #19593, -execdir .... {} + has suboptimal performance
|
||||||
|
+ * find/ftsfind.c (consider_visiting): Don't call
|
||||||
|
+ complete_pending_execdirs for every file we visit.
|
||||||
|
+ (find): Instead, call complete_pending_execdirs every time we
|
||||||
|
+ see a file which isn't at the same nesting level as the previous
|
||||||
|
+ file we saw. This is an improvement but not optimal (since
|
||||||
|
+ descending into a subdirectory will cause us to issue an exec
|
||||||
|
+ before we've finished with the current directory).
|
||||||
|
+ * NEWS: Mention this change.
|
||||||
|
+
|
||||||
|
Exec predicates now store which directory they want to run in.
|
||||||
|
* lib/dircallback.c (run_in_dirfd): New name for old run_in_dir
|
||||||
|
function.
|
||||||
|
diff --git a/NEWS b/NEWS
|
||||||
|
index 6b8b725..569ff51 100644
|
||||||
|
--- a/NEWS
|
||||||
|
+++ b/NEWS
|
||||||
|
@@ -1,5 +1,20 @@
|
||||||
|
GNU findutils NEWS - User visible changes. -*- outline -*- (allout)
|
||||||
|
|
||||||
|
+* Major changes in release 4.4.3-git, YYYY-MM-DD
|
||||||
|
+
|
||||||
|
+** Bug Fixes
|
||||||
|
+
|
||||||
|
+#19593: -execdir .... {} + has suboptimal performance (see below)
|
||||||
|
+
|
||||||
|
+** Performance changes
|
||||||
|
+
|
||||||
|
+The find program will once again build argument lists longer than 1
|
||||||
|
+with "-execdir ...+". The upper limit of 1 argument for execdir was
|
||||||
|
+introduced as a workaround in findutils-4.3.4. The limit is now
|
||||||
|
+removed, but find still does not issue the maximum possible number of
|
||||||
|
+arguments, since an exec will occur each time find encounters a
|
||||||
|
+subdirectory (if at least one argument is pending).
|
||||||
|
+
|
||||||
|
* Major changes in release 4.4.2, 2009-11-26
|
||||||
|
|
||||||
|
** Functional Enhancements to find
|
||||||
|
diff --git a/find/ftsfind.c b/find/ftsfind.c
|
||||||
|
index 9945abd..3c9ae1d 100644
|
||||||
|
--- a/find/ftsfind.c
|
||||||
|
+++ b/find/ftsfind.c
|
||||||
|
@@ -524,24 +524,6 @@ consider_visiting(FTS *p, FTSENT *ent)
|
||||||
|
visit(p, ent, &statbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* XXX: if we allow a build-up of pending arguments for "-execdir foo {} +"
|
||||||
|
- * we need to execute them in the same directory as we found the item.
|
||||||
|
- * If we are trying to do "find a -execdir echo {} +", we will need to
|
||||||
|
- * echo
|
||||||
|
- * a while in the original working directory
|
||||||
|
- * b while in a
|
||||||
|
- * c while in b (just before leaving b)
|
||||||
|
- *
|
||||||
|
- * These restrictions are hard to satisfy while using fts(). The reason is
|
||||||
|
- * that it doesn't tell us just before we leave a directory. For the moment,
|
||||||
|
- * we punt and don't allow the arguments to build up.
|
||||||
|
- */
|
||||||
|
- if (state.execdirs_outstanding)
|
||||||
|
- {
|
||||||
|
- show_outstanding_execdirs(stderr);
|
||||||
|
- complete_pending_execdirs ();
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
if (ent->fts_info == FTS_DP)
|
||||||
|
{
|
||||||
|
/* we're leaving a directory. */
|
||||||
|
@@ -591,8 +573,27 @@ find(char *arg)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
+ int level = INT_MIN;
|
||||||
|
+
|
||||||
|
while ( (ent=fts_read(p)) != NULL )
|
||||||
|
{
|
||||||
|
+ if (state.execdirs_outstanding)
|
||||||
|
+ {
|
||||||
|
+ /* If we changed level, perform any outstanding
|
||||||
|
+ * execdirs. If we see a sequence of directory entries
|
||||||
|
+ * like this: fffdfffdfff, we could build a command line
|
||||||
|
+ * of 9 files, but this simple-minded implementation
|
||||||
|
+ * builds a command line for only 3 files at a time
|
||||||
|
+ * (since fts descends into the directories).
|
||||||
|
+ */
|
||||||
|
+ if ((int)ent->fts_level != level)
|
||||||
|
+ {
|
||||||
|
+ show_outstanding_execdirs (stderr);
|
||||||
|
+ complete_pending_execdirs ();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ level = (int)ent->fts_level;
|
||||||
|
+
|
||||||
|
state.have_stat = false;
|
||||||
|
state.have_type = false;
|
||||||
|
state.type = 0;
|
277
findutils-4.5.8-0004-e1d0a99.patch
Normal file
277
findutils-4.5.8-0004-e1d0a99.patch
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
ChangeLog | 21 +++++++++
|
||||||
|
NEWS | 2 +
|
||||||
|
find/pred.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++-----------
|
||||||
|
3 files changed, 132 insertions(+), 24 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/ChangeLog b/ChangeLog
|
||||||
|
index 98d7962..8e5d0ce 100644
|
||||||
|
--- a/ChangeLog
|
||||||
|
+++ b/ChangeLog
|
||||||
|
@@ -1,3 +1,24 @@
|
||||||
|
+2010-04-11 James Youngman <jay@gnu.org>
|
||||||
|
+
|
||||||
|
+ Fix Savannah bug #27563, -L breaks -execdir.
|
||||||
|
+ * find/pred.c (mdir_name): New function, taken from newer gnulib.
|
||||||
|
+ (initialise_wd_for_exec): New function, factoring out part of the body
|
||||||
|
+ of record_exec_dir.
|
||||||
|
+ (record_exec_dir): If state.rel_pathname contains a /, extract the
|
||||||
|
+ directory part and initialise execp->wd_for_exec to point at that
|
||||||
|
+ directory.
|
||||||
|
+ (impl_pred_exec): Rename new_impl_pred_exec to impl_pred_exec.
|
||||||
|
+ Drop the prefix and pfxlen parameters. Compute the base name of
|
||||||
|
+ the target and pass that to the bc_push_arg function instead of
|
||||||
|
+ state.rel_pathname. Deal with state.rel_pathname being an
|
||||||
|
+ absolute path (e.g. find / -execdir...). Introduce a new
|
||||||
|
+ variable, result, allowing us to free the buffer used for the base
|
||||||
|
+ name in the return path.
|
||||||
|
+ (pred_exec): Don't pass the prefix and the prefix length any more.
|
||||||
|
+ (pred_execdir): Likewise.
|
||||||
|
+ (pred_ok): Likewise.
|
||||||
|
+ (pred_okdir): Likewise.
|
||||||
|
+
|
||||||
|
2010-04-10 James Youngman <jay@gnu.org>
|
||||||
|
|
||||||
|
Fix Savannah bug #19593, -execdir .... {} + has suboptimal performance
|
||||||
|
diff --git a/NEWS b/NEWS
|
||||||
|
index 569ff51..c8eb0bc 100644
|
||||||
|
--- a/NEWS
|
||||||
|
+++ b/NEWS
|
||||||
|
@@ -4,6 +4,8 @@ GNU findutils NEWS - User visible changes. -*- outline -*- (allout)
|
||||||
|
|
||||||
|
** Bug Fixes
|
||||||
|
|
||||||
|
+#27563: -L breaks -execdir
|
||||||
|
+
|
||||||
|
#19593: -execdir .... {} + has suboptimal performance (see below)
|
||||||
|
|
||||||
|
** Performance changes
|
||||||
|
diff --git a/find/pred.c b/find/pred.c
|
||||||
|
index d057d48..cf25184 100644
|
||||||
|
--- a/find/pred.c
|
||||||
|
+++ b/find/pred.c
|
||||||
|
@@ -504,6 +504,57 @@ pred_empty (const char *pathname, struct stat *stat_buf, struct predicate *pred_
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+/* In general, we can't use the builtin `dirname' function if available,
|
||||||
|
+ since it has different meanings in different environments.
|
||||||
|
+ In some environments the builtin `dirname' modifies its argument.
|
||||||
|
+
|
||||||
|
+ Return the leading directories part of FILE, allocated with malloc.
|
||||||
|
+ Works properly even if there are trailing slashes (by effectively
|
||||||
|
+ ignoring them). Return NULL on failure.
|
||||||
|
+
|
||||||
|
+ If lstat (FILE) would succeed, then { chdir (dir_name (FILE));
|
||||||
|
+ lstat (base_name (FILE)); } will access the same file. Likewise,
|
||||||
|
+ if the sequence { chdir (dir_name (FILE));
|
||||||
|
+ rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE
|
||||||
|
+ to "foo" in the same directory FILE was in. */
|
||||||
|
+
|
||||||
|
+static char *
|
||||||
|
+mdir_name (char const *file)
|
||||||
|
+{
|
||||||
|
+ size_t length = dir_len (file);
|
||||||
|
+ bool append_dot = (length == 0
|
||||||
|
+ || (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
|
||||||
|
+ && length == FILE_SYSTEM_PREFIX_LEN (file)
|
||||||
|
+ && file[2] != '\0' && ! ISSLASH (file[2])));
|
||||||
|
+ char *dir = malloc (length + append_dot + 1);
|
||||||
|
+ if (!dir)
|
||||||
|
+ return NULL;
|
||||||
|
+ memcpy (dir, file, length);
|
||||||
|
+ if (append_dot)
|
||||||
|
+ dir[length++] = '.';
|
||||||
|
+ dir[length] = '\0';
|
||||||
|
+ return dir;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/* Initialise exec->wd_for_exec.
|
||||||
|
+
|
||||||
|
+ We save in exec->wd_for_exec the directory whose path relative to
|
||||||
|
+ cwd_df is dir.
|
||||||
|
+ */
|
||||||
|
+static boolean
|
||||||
|
+initialise_wd_for_exec (struct exec_val *execp, int cwd_fd, const char *dir)
|
||||||
|
+{
|
||||||
|
+ execp->wd_for_exec = xmalloc (sizeof (*execp->wd_for_exec));
|
||||||
|
+ execp->wd_for_exec->name = NULL;
|
||||||
|
+ execp->wd_for_exec->desc = openat (cwd_fd, dir, O_RDONLY);
|
||||||
|
+ if (execp->wd_for_exec->desc < 0)
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
+ return true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
static boolean
|
||||||
|
record_exec_dir (struct exec_val *execp)
|
||||||
|
{
|
||||||
|
@@ -514,29 +565,46 @@ record_exec_dir (struct exec_val *execp)
|
||||||
|
be -execdir foo {} \; (i.e. not multiple). */
|
||||||
|
assert (!execp->state.todo);
|
||||||
|
|
||||||
|
- /* Record the WD. */
|
||||||
|
- execp->wd_for_exec = xmalloc (sizeof (*execp->wd_for_exec));
|
||||||
|
- execp->wd_for_exec->name = NULL;
|
||||||
|
- execp->wd_for_exec->desc = openat (state.cwd_dir_fd, ".", O_RDONLY);
|
||||||
|
- if (execp->wd_for_exec->desc < 0)
|
||||||
|
- return false;
|
||||||
|
+ /* Record the WD. If we're using -L or fts chooses to do so for
|
||||||
|
+ any other reason, state.cwd_dir_fd may in fact not be the
|
||||||
|
+ directory containing the target file. When this happens,
|
||||||
|
+ rel_path will contain directory components (since it is the
|
||||||
|
+ path from state.cwd_dir_fd to the target file).
|
||||||
|
+
|
||||||
|
+ We deal with this by extracting any directory part and using
|
||||||
|
+ that to adjust what goes into execp->wd_for_exec.
|
||||||
|
+ */
|
||||||
|
+ if (strchr (state.rel_pathname, '/'))
|
||||||
|
+ {
|
||||||
|
+ char *dir = mdir_name (state.rel_pathname);
|
||||||
|
+ bool result = initialise_wd_for_exec (execp, state.cwd_dir_fd, dir);
|
||||||
|
+ free (dir);
|
||||||
|
+ return result;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ return initialise_wd_for_exec (execp, state.cwd_dir_fd, ".");
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
-new_impl_pred_exec (const char *pathname,
|
||||||
|
- struct stat *stat_buf,
|
||||||
|
- struct predicate *pred_ptr,
|
||||||
|
- const char *prefix, size_t pfxlen)
|
||||||
|
+impl_pred_exec (const char *pathname,
|
||||||
|
+ struct stat *stat_buf,
|
||||||
|
+ struct predicate *pred_ptr)
|
||||||
|
{
|
||||||
|
struct exec_val *execp = &pred_ptr->args.exec_vec;
|
||||||
|
- size_t len = strlen(pathname);
|
||||||
|
+ char *target;
|
||||||
|
+ bool result;
|
||||||
|
+ const bool local = is_exec_in_local_dir (pred_ptr->pred_func);
|
||||||
|
+ char *prefix;
|
||||||
|
+ size_t pfxlen;
|
||||||
|
|
||||||
|
(void) stat_buf;
|
||||||
|
|
||||||
|
- if (is_exec_in_local_dir (pred_ptr->pred_func))
|
||||||
|
+ if (local)
|
||||||
|
{
|
||||||
|
/* For -execdir/-okdir predicates, the parser did not fill in
|
||||||
|
the wd_for_exec member of sturct exec_val. So for those
|
||||||
|
@@ -550,6 +618,18 @@ new_impl_pred_exec (const char *pathname,
|
||||||
|
safely_quote_err_filename (0, pathname));
|
||||||
|
/*NOTREACHED*/
|
||||||
|
}
|
||||||
|
+ target = base_name (state.rel_pathname);
|
||||||
|
+ if ('/' == target[0])
|
||||||
|
+ {
|
||||||
|
+ /* find / execdir ls -d {} \; */
|
||||||
|
+ prefix = NULL;
|
||||||
|
+ pfxlen = 0;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ prefix = "./";
|
||||||
|
+ pfxlen = 2u;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@@ -559,6 +639,9 @@ new_impl_pred_exec (const char *pathname,
|
||||||
|
working directory.
|
||||||
|
*/
|
||||||
|
assert (execp->wd_for_exec == initial_wd);
|
||||||
|
+ target = (char *) pathname;
|
||||||
|
+ prefix = NULL;
|
||||||
|
+ pfxlen = 0u;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (execp->multiple)
|
||||||
|
@@ -569,7 +652,7 @@ new_impl_pred_exec (const char *pathname,
|
||||||
|
*/
|
||||||
|
bc_push_arg(&execp->ctl,
|
||||||
|
&execp->state,
|
||||||
|
- pathname, len+1,
|
||||||
|
+ target, strlen (target)+1,
|
||||||
|
prefix, pfxlen,
|
||||||
|
0);
|
||||||
|
|
||||||
|
@@ -579,7 +662,7 @@ new_impl_pred_exec (const char *pathname,
|
||||||
|
/* POSIX: If the primary expression is punctuated by a plus
|
||||||
|
* sign, the primary shall always evaluate as true
|
||||||
|
*/
|
||||||
|
- return true;
|
||||||
|
+ result = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@@ -592,30 +675,34 @@ new_impl_pred_exec (const char *pathname,
|
||||||
|
execp->replace_vec[i],
|
||||||
|
strlen(execp->replace_vec[i]),
|
||||||
|
prefix, pfxlen,
|
||||||
|
- pathname, len,
|
||||||
|
+ target, strlen (target),
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Actually invoke the command. */
|
||||||
|
- return execp->ctl.exec_callback(&execp->ctl,
|
||||||
|
+ result = execp->ctl.exec_callback(&execp->ctl,
|
||||||
|
&execp->state);
|
||||||
|
}
|
||||||
|
+ if (target != pathname)
|
||||||
|
+ {
|
||||||
|
+ assert (local);
|
||||||
|
+ free (target);
|
||||||
|
+ }
|
||||||
|
+ return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
boolean
|
||||||
|
pred_exec (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
|
||||||
|
{
|
||||||
|
- return new_impl_pred_exec(pathname, stat_buf, pred_ptr, NULL, 0);
|
||||||
|
+ return impl_pred_exec(pathname, stat_buf, pred_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean
|
||||||
|
pred_execdir (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
|
||||||
|
{
|
||||||
|
- const char *prefix = (state.rel_pathname[0] == '/') ? NULL : "./";
|
||||||
|
(void) &pathname;
|
||||||
|
- return new_impl_pred_exec (state.rel_pathname, stat_buf, pred_ptr,
|
||||||
|
- prefix, (prefix ? 2 : 0));
|
||||||
|
+ return impl_pred_exec (state.rel_pathname, stat_buf, pred_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean
|
||||||
|
@@ -1506,7 +1593,7 @@ boolean
|
||||||
|
pred_ok (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
|
||||||
|
{
|
||||||
|
if (is_ok(pred_ptr->args.exec_vec.replace_vec[0], pathname))
|
||||||
|
- return new_impl_pred_exec (pathname, stat_buf, pred_ptr, NULL, 0);
|
||||||
|
+ return impl_pred_exec (pathname, stat_buf, pred_ptr);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@@ -1514,10 +1601,8 @@ pred_ok (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr
|
||||||
|
boolean
|
||||||
|
pred_okdir (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
|
||||||
|
{
|
||||||
|
- const char *prefix = (state.rel_pathname[0] == '/') ? NULL : "./";
|
||||||
|
if (is_ok(pred_ptr->args.exec_vec.replace_vec[0], pathname))
|
||||||
|
- return new_impl_pred_exec (state.rel_pathname, stat_buf, pred_ptr,
|
||||||
|
- prefix, (prefix ? 2 : 0));
|
||||||
|
+ return impl_pred_exec (state.rel_pathname, stat_buf, pred_ptr);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
103
findutils-4.5.8-0005-a1f5402.patch
Normal file
103
findutils-4.5.8-0005-a1f5402.patch
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
ChangeLog | 11 +++++++++++
|
||||||
|
find/testsuite/Makefile.am | 4 ++++
|
||||||
|
find/testsuite/find.gnu/sv-bug-27563-execdir.exp | 6 ++++++
|
||||||
|
find/testsuite/find.gnu/sv-bug-27563-execdir.xo | 1 +
|
||||||
|
find/testsuite/find.posix/sv-bug-27563-exec.exp | 6 ++++++
|
||||||
|
find/testsuite/find.posix/sv-bug-27563-exec.xo | 1 +
|
||||||
|
6 files changed, 29 insertions(+), 0 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/ChangeLog b/ChangeLog
|
||||||
|
index 8e5d0ce..5702e66 100644
|
||||||
|
--- a/ChangeLog
|
||||||
|
+++ b/ChangeLog
|
||||||
|
@@ -1,5 +1,16 @@
|
||||||
|
2010-04-11 James Youngman <jay@gnu.org>
|
||||||
|
|
||||||
|
+ Add a test case for Savannah bug 27563 (-L breaks -execdir).
|
||||||
|
+ * find/testsuite/Makefile.am (EXTRA_DIST_EXP): Add
|
||||||
|
+ find.gnu/sv-bug-27563-execdir.exp and
|
||||||
|
+ find.posix/sv-bug-27563-exec.exp.
|
||||||
|
+ (EXTRA_DIST_XO): Add find.gnu/sv-bug-27563-execdir.xo and
|
||||||
|
+ find.posix/sv-bug-27563-exec.xo.
|
||||||
|
+ * find/testsuite/find.gnu/sv-bug-27563-execdir.exp: New test.
|
||||||
|
+ * find/testsuite/find.posix/sv-bug-27563-exec.exp: New test.
|
||||||
|
+ * find/testsuite/find.gnu/sv-bug-27563-execdir.xo: Expected output.
|
||||||
|
+ * find/testsuite/find.posix/sv-bug-27563-exec.xo: Expected output.
|
||||||
|
+
|
||||||
|
Fix Savannah bug #27563, -L breaks -execdir.
|
||||||
|
* find/pred.c (mdir_name): New function, taken from newer gnulib.
|
||||||
|
(initialise_wd_for_exec): New function, factoring out part of the body
|
||||||
|
diff --git a/find/testsuite/Makefile.am b/find/testsuite/Makefile.am
|
||||||
|
index 1447132..aa32d4b 100644
|
||||||
|
--- a/find/testsuite/Makefile.am
|
||||||
|
+++ b/find/testsuite/Makefile.am
|
||||||
|
@@ -63,6 +63,7 @@ find.gnu/samefile-same.xo \
|
||||||
|
find.gnu/samefile-symlink.xo \
|
||||||
|
find.gnu/sv-bug-17782.xo \
|
||||||
|
find.gnu/sv-bug-18222.xo \
|
||||||
|
+find.gnu/sv-bug-27563-execdir.xo \
|
||||||
|
find.gnu/true.xo \
|
||||||
|
find.gnu/wholename.xo \
|
||||||
|
find.gnu/xtype-symlink.xo \
|
||||||
|
@@ -78,6 +79,7 @@ find.posix/grouping.xo \
|
||||||
|
find.posix/links.xo \
|
||||||
|
find.posix/sv-bug-11175.xo \
|
||||||
|
find.posix/sv-bug-12181.xo \
|
||||||
|
+find.posix/sv-bug-27563-exec.xo \
|
||||||
|
find.posix/depth1.xo \
|
||||||
|
find.posix/mtime0.xo \
|
||||||
|
find.posix/sizes.xo \
|
||||||
|
@@ -179,6 +181,7 @@ find.gnu/sv-bug-17490.exp \
|
||||||
|
find.gnu/sv-bug-17782.exp \
|
||||||
|
find.gnu/sv-bug-18222.exp \
|
||||||
|
find.gnu/sv-bug-24169.exp \
|
||||||
|
+find.gnu/sv-bug-27563-execdir.exp \
|
||||||
|
find.gnu/quit.exp \
|
||||||
|
find.gnu/used-invarg.exp \
|
||||||
|
find.gnu/used-missing.exp \
|
||||||
|
@@ -199,6 +202,7 @@ find.posix/links.exp \
|
||||||
|
find.posix/mtime0.exp \
|
||||||
|
find.posix/sv-bug-11175.exp \
|
||||||
|
find.posix/sv-bug-12181.exp \
|
||||||
|
+find.posix/sv-bug-27563-exec.exp \
|
||||||
|
find.posix/depth1.exp \
|
||||||
|
find.posix/sizes.exp \
|
||||||
|
find.posix/name.exp \
|
||||||
|
diff --git a/find/testsuite/find.gnu/sv-bug-27563-execdir.exp b/find/testsuite/find.gnu/sv-bug-27563-execdir.exp
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..c67fc88
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/find/testsuite/find.gnu/sv-bug-27563-execdir.exp
|
||||||
|
@@ -0,0 +1,6 @@
|
||||||
|
+# tests for Savannah bug 27563 (result of find -L -exec ls {} \;)
|
||||||
|
+exec rm -rf tmp
|
||||||
|
+exec mkdir tmp
|
||||||
|
+exec touch tmp/yyyy
|
||||||
|
+find_start p {-L tmp -name yyyy -execdir ls \{\} \; }
|
||||||
|
+exec rm -rf tmp
|
||||||
|
diff --git a/find/testsuite/find.gnu/sv-bug-27563-execdir.xo b/find/testsuite/find.gnu/sv-bug-27563-execdir.xo
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..285260b
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/find/testsuite/find.gnu/sv-bug-27563-execdir.xo
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+./yyyy
|
||||||
|
diff --git a/find/testsuite/find.posix/sv-bug-27563-exec.exp b/find/testsuite/find.posix/sv-bug-27563-exec.exp
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..d18b0c1
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/find/testsuite/find.posix/sv-bug-27563-exec.exp
|
||||||
|
@@ -0,0 +1,6 @@
|
||||||
|
+# tests for Savannah bug 27563 (result of find -L -exec ls {} \;)
|
||||||
|
+exec rm -rf tmp
|
||||||
|
+exec mkdir tmp
|
||||||
|
+exec touch tmp/yyyy
|
||||||
|
+find_start p {-L tmp -name yyyy -exec ls \{\} \; }
|
||||||
|
+exec rm -rf tmp
|
||||||
|
diff --git a/find/testsuite/find.posix/sv-bug-27563-exec.xo b/find/testsuite/find.posix/sv-bug-27563-exec.xo
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..cd491dd
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/find/testsuite/find.posix/sv-bug-27563-exec.xo
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+tmp/yyyy
|
70
findutils-4.5.8-0006-Fix-Savannah-bug-29949.patch
Normal file
70
findutils-4.5.8-0006-Fix-Savannah-bug-29949.patch
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
ChangeLog | 9 +++++++++
|
||||||
|
NEWS | 2 ++
|
||||||
|
find/pred.c | 10 ++++------
|
||||||
|
find/testsuite/find.gnu/execdir-multiple.exp | 1 +
|
||||||
|
4 files changed, 16 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/ChangeLog b/ChangeLog
|
||||||
|
index 5702e66..97b1b7c 100644
|
||||||
|
--- a/ChangeLog
|
||||||
|
+++ b/ChangeLog
|
||||||
|
@@ -1,3 +1,12 @@
|
||||||
|
+2010-05-24 Kamil Dudka <kdudka@redhat.com>
|
||||||
|
+
|
||||||
|
+ Fix Savannah bug #29949, -execdir does not change working directory
|
||||||
|
+ * find/pred.c (record_exec_dir): Do not throw the execdir when not
|
||||||
|
+ working in the cumulative mode.
|
||||||
|
+ * find/testsuite/find.gnu/execdir-multiple.exp: Add a test-case for
|
||||||
|
+ the bug #29949.
|
||||||
|
+ * NEWS: Mention this bugfix.
|
||||||
|
+
|
||||||
|
2010-04-11 James Youngman <jay@gnu.org>
|
||||||
|
|
||||||
|
Add a test case for Savannah bug 27563 (-L breaks -execdir).
|
||||||
|
diff --git a/NEWS b/NEWS
|
||||||
|
index c8eb0bc..2ba2111 100644
|
||||||
|
--- a/NEWS
|
||||||
|
+++ b/NEWS
|
||||||
|
@@ -4,6 +4,8 @@ GNU findutils NEWS - User visible changes. -*- outline -*- (allout)
|
||||||
|
|
||||||
|
** Bug Fixes
|
||||||
|
|
||||||
|
+#29949: find -execdir does not change working directory
|
||||||
|
+
|
||||||
|
#27563: -L breaks -execdir
|
||||||
|
|
||||||
|
#19593: -execdir .... {} + has suboptimal performance (see below)
|
||||||
|
diff --git a/find/pred.c b/find/pred.c
|
||||||
|
index cf25184..cac74d1 100644
|
||||||
|
--- a/find/pred.c
|
||||||
|
+++ b/find/pred.c
|
||||||
|
@@ -558,13 +558,11 @@ initialise_wd_for_exec (struct exec_val *execp, int cwd_fd, const char *dir)
|
||||||
|
static boolean
|
||||||
|
record_exec_dir (struct exec_val *execp)
|
||||||
|
{
|
||||||
|
- if (!execp->wd_for_exec)
|
||||||
|
+ /* working directory not already known, so must be a *dir variant,
|
||||||
|
+ and this must be the first arg we added. However, this may
|
||||||
|
+ be -execdir foo {} \; (i.e. not multiple). */
|
||||||
|
+ if (!execp->state.todo)
|
||||||
|
{
|
||||||
|
- /* working directory not already known, so must be a *dir variant,
|
||||||
|
- and this must be the first arg we added. However, this may
|
||||||
|
- be -execdir foo {} \; (i.e. not multiple). */
|
||||||
|
- assert (!execp->state.todo);
|
||||||
|
-
|
||||||
|
/* Record the WD. If we're using -L or fts chooses to do so for
|
||||||
|
any other reason, state.cwd_dir_fd may in fact not be the
|
||||||
|
directory containing the target file. When this happens,
|
||||||
|
diff --git a/find/testsuite/find.gnu/execdir-multiple.exp b/find/testsuite/find.gnu/execdir-multiple.exp
|
||||||
|
index 6d4bd66..495b93b 100644
|
||||||
|
--- a/find/testsuite/find.gnu/execdir-multiple.exp
|
||||||
|
+++ b/find/testsuite/find.gnu/execdir-multiple.exp
|
||||||
|
@@ -49,6 +49,7 @@ if { [ safe_path ] } {
|
||||||
|
}
|
||||||
|
|
||||||
|
set SKIP_OLD 1
|
||||||
|
+ find_start p {tmp -type f -empty -execdir sh ./runme \{\} \; } ""
|
||||||
|
find_start p {tmp -type f -empty -execdir sh ./runme \{\} + } ""
|
||||||
|
set SKIP_OLD 0
|
||||||
|
exec rm -rf tmp
|
@ -1,7 +1,7 @@
|
|||||||
Summary: The GNU versions of find utilities (find and xargs)
|
Summary: The GNU versions of find utilities (find and xargs)
|
||||||
Name: findutils
|
Name: findutils
|
||||||
Version: 4.4.2
|
Version: 4.4.2
|
||||||
Release: 3%{?dist}
|
Release: 8%{?dist}
|
||||||
Epoch: 1
|
Epoch: 1
|
||||||
License: GPLv3+
|
License: GPLv3+
|
||||||
Group: Applications/File
|
Group: Applications/File
|
||||||
@ -9,7 +9,30 @@ URL: http://www.gnu.org/software/findutils/
|
|||||||
Source0: ftp://ftp.gnu.org/gnu/findutils/%{name}-%{version}.tar.gz
|
Source0: ftp://ftp.gnu.org/gnu/findutils/%{name}-%{version}.tar.gz
|
||||||
Source1: ftp://ftp.gnu.org/gnu/findutils/%{name}-%{version}.tar.gz.sig
|
Source1: ftp://ftp.gnu.org/gnu/findutils/%{name}-%{version}.tar.gz.sig
|
||||||
Patch1: findutils-4.4.0-no-locate.patch
|
Patch1: findutils-4.4.0-no-locate.patch
|
||||||
Patch2: findutils-4.4.0-selinux.patch
|
Patch2: findutils-4.4.2-autofs.patch
|
||||||
|
Patch3: findutils-4.4.2-xautofs.patch
|
||||||
|
Patch4: findutils-4.4.2-fts-remount.patch
|
||||||
|
Patch5: findutils-4.4.2-selinux.patch
|
||||||
|
Patch6: findutils-4.4.2-selinux-gnulib.patch
|
||||||
|
|
||||||
|
# backport of upstream commit 41896c730790d6afa9feabc867aaa14198873a76
|
||||||
|
Patch7: findutils-4.5.8-0001-41896c7.patch
|
||||||
|
|
||||||
|
# backport of upstream commit 7dc70069a3095a42eadb22b24cb9260c243aff8f
|
||||||
|
Patch8: findutils-4.5.8-0002-7dc7006.patch
|
||||||
|
|
||||||
|
# backport of upstream commit 27a7e451b84808408bf23b3f8a0363acb36e1a96
|
||||||
|
Patch9: findutils-4.5.8-0003-27a7e45.patch
|
||||||
|
|
||||||
|
# backport of upstream commit e1d0a991e96ee164d74579efc027b09336e50c79
|
||||||
|
Patch10: findutils-4.5.8-0004-e1d0a99.patch
|
||||||
|
|
||||||
|
# backport of upstream commit a1f54022d1913a92ccb728211127d5c238397eb6
|
||||||
|
Patch11: findutils-4.5.8-0005-a1f5402.patch
|
||||||
|
|
||||||
|
# Fix Savannah bug #29949, -execdir does not change working directory
|
||||||
|
Patch12: findutils-4.5.8-0006-Fix-Savannah-bug-29949.patch
|
||||||
|
|
||||||
Requires(post): /sbin/install-info
|
Requires(post): /sbin/install-info
|
||||||
Requires(preun): /sbin/install-info
|
Requires(preun): /sbin/install-info
|
||||||
Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||||
@ -21,7 +44,7 @@ BuildRequires: libselinux-devel
|
|||||||
The findutils package contains programs which will help you locate
|
The findutils package contains programs which will help you locate
|
||||||
files on your system. The find utility searches through a hierarchy
|
files on your system. The find utility searches through a hierarchy
|
||||||
of directories looking for files which match a certain set of criteria
|
of directories looking for files which match a certain set of criteria
|
||||||
(such as a filename pattern). The xargs utility builds and executes
|
(such as a file name pattern). The xargs utility builds and executes
|
||||||
command lines from standard input arguments (usually lists of file
|
command lines from standard input arguments (usually lists of file
|
||||||
names generated by the find command).
|
names generated by the find command).
|
||||||
|
|
||||||
@ -30,8 +53,18 @@ useful for finding things on your system.
|
|||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -q
|
%setup -q
|
||||||
%patch1 -p1 -b .no-locate
|
%patch1 -p1
|
||||||
%patch2 -p1 -b .selinux
|
%patch2 -p1
|
||||||
|
%patch3 -p1
|
||||||
|
%patch4 -p1
|
||||||
|
%patch5 -p1
|
||||||
|
%patch6 -p1
|
||||||
|
%patch7 -p1
|
||||||
|
%patch8 -p1
|
||||||
|
%patch9 -p1
|
||||||
|
%patch10 -p1
|
||||||
|
%patch11 -p1
|
||||||
|
%patch12 -p1
|
||||||
|
|
||||||
autoreconf
|
autoreconf
|
||||||
|
|
||||||
@ -40,7 +73,7 @@ autoreconf
|
|||||||
%configure
|
%configure
|
||||||
%undefine optflags
|
%undefine optflags
|
||||||
|
|
||||||
make
|
make %{?_smp_mflags}
|
||||||
|
|
||||||
%check
|
%check
|
||||||
make check
|
make check
|
||||||
@ -77,7 +110,7 @@ fi
|
|||||||
rm -rf $RPM_BUILD_ROOT
|
rm -rf $RPM_BUILD_ROOT
|
||||||
|
|
||||||
%files -f %{name}.lang
|
%files -f %{name}.lang
|
||||||
%defattr(-,root,root)
|
%defattr(-,root,root,-)
|
||||||
%doc AUTHORS COPYING NEWS README THANKS TODO
|
%doc AUTHORS COPYING NEWS README THANKS TODO
|
||||||
/bin/find
|
/bin/find
|
||||||
%{_bindir}/find
|
%{_bindir}/find
|
||||||
@ -89,6 +122,24 @@ rm -rf $RPM_BUILD_ROOT
|
|||||||
%{_infodir}/find-maint.info.gz
|
%{_infodir}/find-maint.info.gz
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Tue Jun 01 2010 Kamil Dudka <kdudka@redhat.com> - 1:4.4.2-8
|
||||||
|
- fix Savannah bug #29949
|
||||||
|
|
||||||
|
* Mon May 10 2010 Kamil Dudka <kdudka@redhat.com> - 1:4.4.2-7
|
||||||
|
- backport of patches for upstream bugs #19593 and #27563 (rhbz #493143)
|
||||||
|
- mention -xautofs in the output of --help (#590166)
|
||||||
|
|
||||||
|
* Thu Nov 26 2009 Kamil Dudka <kdudka@redhat.com> - 1:4.4.2-6
|
||||||
|
- update SELinux patch to the latest upstream (gnulib based) version
|
||||||
|
|
||||||
|
* Wed Nov 18 2009 Kamil Dudka <kdudka@redhat.com> - 1:4.4.2-5
|
||||||
|
- do not fail silently on a remount during traverse (#538536)
|
||||||
|
|
||||||
|
* Tue Oct 20 2009 Kamil Dudka <kdudka@redhat.com> - 1:4.4.2-4
|
||||||
|
- make it possible to recognize an autofs filesystem by find
|
||||||
|
- add a new find's option -xautofs to not descend directories on autofs
|
||||||
|
filesystems
|
||||||
|
|
||||||
* Mon Sep 14 2009 Kamil Dudka <kdudka@redhat.com> - 1:4.4.2-3
|
* Mon Sep 14 2009 Kamil Dudka <kdudka@redhat.com> - 1:4.4.2-3
|
||||||
- do process install-info only without --excludedocs(#515914)
|
- do process install-info only without --excludedocs(#515914)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user