diff options
Diffstat (limited to 'find/pred.c')
-rw-r--r-- | find/pred.c | 335 |
1 files changed, 0 insertions, 335 deletions
diff --git a/find/pred.c b/find/pred.c index 3b15a6e5..4aaebe24 100644 --- a/find/pred.c +++ b/find/pred.c @@ -20,7 +20,6 @@ #include "defs.h" #include <fnmatch.h> -#include <signal.h> #include <math.h> #include <pwd.h> #include <grp.h> @@ -40,7 +39,6 @@ #include "human.h" #include "filemode.h" #include "printquoted.h" -#include "buildcmd.h" #include "yesno.h" #include "listfile.h" #include "stat-time.h" @@ -48,10 +46,7 @@ #include "dircallback.h" #include "error.h" #include "verify.h" -#include "fdleak.h" #include "areadlink.h" -#include "cloexec.h" -#include "save-cwd.h" #include <selinux/selinux.h> @@ -68,11 +63,6 @@ # define N_(String) String #endif -#if defined SIGCLD && !defined SIGCHLD -# define SIGCHLD SIGCLD -#endif - - #ifdef CLOSEDIR_VOID /* Fake a return value. */ #define CLOSEDIR(d) (closedir (d), 0) @@ -425,166 +415,6 @@ pred_empty (const char *pathname, struct stat *stat_buf, struct predicate *pred_ } -/* Initialise exec->wd_for_exec. - - We save in exec->wd_for_exec the directory whose path relative to - cwd_df is dir. - */ -static bool -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; - set_cloexec_flag (execp->wd_for_exec->desc, true); - return true; -} - - -static bool -record_exec_dir (struct exec_val *execp) -{ - if (!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, - 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 bool -impl_pred_exec (const char *pathname, - struct stat *stat_buf, - struct predicate *pred_ptr) -{ - struct exec_val *execp = &pred_ptr->args.exec_vec; - char *buf = NULL; - const char *target; - bool result; - const bool local = is_exec_in_local_dir (pred_ptr->pred_func); - const char *prefix; - size_t pfxlen; - - (void) stat_buf; - if (local) - { - /* 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*/ - } - target = buf = base_name (state.rel_pathname); - if ('/' == target[0]) - { - /* find / execdir ls -d {} \; */ - prefix = NULL; - pfxlen = 0; - } - else - { - prefix = "./"; - pfxlen = 2u; - } - } - 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); - target = pathname; - prefix = NULL; - pfxlen = 0u; - } - - if (execp->multiple) - { - /* Push the argument onto the current list. - * The command may or may not be run at this point, - * depending on the command line length limits. - */ - bc_push_arg (&execp->ctl, - &execp->state, - target, strlen (target)+1, - prefix, pfxlen, - 0); - - /* remember that there are pending execdirs. */ - state.execdirs_outstanding = true; - - /* POSIX: If the primary expression is punctuated by a plus - * sign, the primary shall always evaluate as true - */ - result = true; - } - else - { - int i; - - for (i=0; i<execp->num_args; ++i) - { - bc_do_insert (&execp->ctl, - &execp->state, - execp->replace_vec[i], - strlen (execp->replace_vec[i]), - prefix, pfxlen, - target, strlen (target), - 0); - } - - /* Actually invoke the command. */ - bc_do_exec (&execp->ctl, &execp->state); - if (WIFEXITED(execp->last_child_status)) - { - if (0 == WEXITSTATUS(execp->last_child_status)) - result = true; /* The child succeeded. */ - else - result = false; - } - else - { - result = false; - } - } - if (buf) - { - assert (local); - free (buf); - } - return result; -} - - bool pred_exec (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr) { @@ -1915,172 +1745,7 @@ pred_context (const char *pathname, struct stat *stat_buf, } -/* 1) fork to get a child; parent remembers the child pid - 2) child execs the command requested - 3) parent waits for child; checks for proper pid of child - - Possible returns: - - ret errno status(h) status(l) - - pid x signal# 0177 stopped - pid x exit arg 0 term by _exit - pid x 0 signal # term by signal - -1 EINTR parent got signal - -1 other some other kind of error - - Return true only if the pid matches, status(l) is - zero, and the exit arg (status high) is 0. - Otherwise return false, possibly printing an error message. */ - - -static bool -prep_child_for_exec (bool close_stdin, const struct saved_cwd *wd) -{ - bool ok = true; - if (close_stdin) - { - const char inputfile[] = "/dev/null"; - - if (close (0) < 0) - { - error (0, errno, _("Cannot close standard input")); - ok = false; - } - else - { - if (open (inputfile, O_RDONLY -#if defined O_LARGEFILE - |O_LARGEFILE -#endif - ) < 0) - { - /* This is not entirely fatal, since - * executing the child with a closed - * stdin is almost as good as executing it - * with its stdin attached to /dev/null. - */ - error (0, errno, "%s", safely_quote_err_filename (0, inputfile)); - /* do not set ok=false, it is OK to continue anyway. */ - } - } - } - - /* Even if DebugSearch is set, don't announce our change of - * directory, since we're not going to emit a subsequent - * announcement of a call to stat() anyway, as we're about to exec - * something. - */ - if (0 != restore_cwd (wd)) - { - error (0, errno, _("Failed to change directory")); - ok = false; - } - return ok; -} - - - - - - -int -launch (struct buildcmd_control *ctl, void *usercontext, int argc, char **argv) -{ - pid_t child_pid; - static int first_time = 1; - struct exec_val *execp = usercontext; - - /* Make sure output of command doesn't get mixed with find output. */ - fflush (stdout); - fflush (stderr); - - /* Make sure to listen for the kids. */ - if (first_time) - { - first_time = 0; - signal (SIGCHLD, SIG_DFL); - } - - child_pid = fork (); - if (child_pid == -1) - error (EXIT_FAILURE, errno, _("cannot fork")); - if (child_pid == 0) - { - /* We are the child. */ - assert (NULL != execp->wd_for_exec); - if (!prep_child_for_exec (execp->close_stdin, execp->wd_for_exec)) - { - _exit (1); - } - else - { - if (fd_leak_check_is_enabled ()) - { - complain_about_leaky_fds (); - } - } - - if (bc_args_exceed_testing_limit (argv)) - errno = E2BIG; - else - execvp (argv[0], argv); - /* TODO: use a pipe to pass back the errno value, like xargs does */ - error (0, errno, "%s", - safely_quote_err_filename (0, argv[0])); - _exit (1); - } - - while (waitpid (child_pid, &(execp->last_child_status), 0) == (pid_t) -1) - { - if (errno != EINTR) - { - error (0, errno, _("error waiting for %s"), - safely_quote_err_filename (0, argv[0])); - state.exit_status = 1; - return 0; /* FAIL */ - } - } - - if (WIFSIGNALED (execp->last_child_status)) - { - error (0, 0, _("%s terminated by signal %d"), - quotearg_n_style (0, options.err_quoting_style, argv[0]), - WTERMSIG (execp->last_child_status)); - - if (execp->multiple) - { - /* -exec \; just returns false if the invoked command fails. - * -exec {} + returns true if the invoked command fails, but - * sets the program exit status. - */ - state.exit_status = 1; - } - - return 1; /* OK */ - } - - if (0 == WEXITSTATUS (execp->last_child_status)) - { - return 1; /* OK */ - } - else - { - if (execp->multiple) - { - /* -exec \; just returns false if the invoked command fails. - * -exec {} + returns true if the invoked command fails, but - * sets the program exit status. - */ - state.exit_status = 1; - } - /* The child failed, but this is the exec callback. We - * don't want to run the child again in this case anwyay. - */ - return 1; /* FAIL (but don't try again) */ - } -} static bool |