find: add optional support for '-exec ... {} +'
function old new delta do_exec - 309 +309 parse_params 1416 1487 +71 find_main 342 406 +64 packed_usage 29958 30014 +56 func_exec 138 127 -11 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 3/1 up/down: 500/-11) Total: 489 bytes Signed-off-by: Bartosz Golaszewski <bartekgola@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
85090c162b
commit
14158b4127
152
findutils/find.c
152
findutils/find.c
@ -137,6 +137,16 @@
|
|||||||
//config: Support the 'find -exec' option for executing commands based upon
|
//config: Support the 'find -exec' option for executing commands based upon
|
||||||
//config: the files matched.
|
//config: the files matched.
|
||||||
//config:
|
//config:
|
||||||
|
//config:config FEATURE_FIND_EXEC_PLUS
|
||||||
|
//config: bool "Enable -exec ... {} +"
|
||||||
|
//config: default y
|
||||||
|
//config: depends on FEATURE_FIND_EXEC
|
||||||
|
//config: help
|
||||||
|
//config: Support the 'find -exec ... {} +' option for executing commands
|
||||||
|
//config: for all matched files at once.
|
||||||
|
//config: Without this option, -exec + is a synonym for -exec ;
|
||||||
|
//config: (IOW: it works correctly, but without expected speedup)
|
||||||
|
//config:
|
||||||
//config:config FEATURE_FIND_USER
|
//config:config FEATURE_FIND_USER
|
||||||
//config: bool "Enable -user: username/uid matching"
|
//config: bool "Enable -user: username/uid matching"
|
||||||
//config: default y
|
//config: default y
|
||||||
@ -319,6 +329,9 @@
|
|||||||
//usage: "\n -exec CMD ARG ; Run CMD with all instances of {} replaced by"
|
//usage: "\n -exec CMD ARG ; Run CMD with all instances of {} replaced by"
|
||||||
//usage: "\n file name. Fails if CMD exits with nonzero"
|
//usage: "\n file name. Fails if CMD exits with nonzero"
|
||||||
//usage: )
|
//usage: )
|
||||||
|
//usage: IF_FEATURE_FIND_EXEC_PLUS(
|
||||||
|
//usage: "\n -exec CMD ARG + Run CMD with {} replaced by list of file names"
|
||||||
|
//usage: )
|
||||||
//usage: IF_FEATURE_FIND_DELETE(
|
//usage: IF_FEATURE_FIND_DELETE(
|
||||||
//usage: "\n -delete Delete current file/directory. Turns on -depth option"
|
//usage: "\n -delete Delete current file/directory. Turns on -depth option"
|
||||||
//usage: )
|
//usage: )
|
||||||
@ -337,8 +350,12 @@
|
|||||||
# define FNM_CASEFOLD 0
|
# define FNM_CASEFOLD 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
# define dbg(...) ((void)0)
|
# define dbg(...) ((void)0)
|
||||||
/* #define dbg(...) bb_error_msg(__VA_ARGS__) */
|
#else
|
||||||
|
# define dbg(...) bb_error_msg(__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* This is a NOEXEC applet. Be very careful! */
|
/* This is a NOEXEC applet. Be very careful! */
|
||||||
|
|
||||||
@ -375,7 +392,20 @@ IF_FEATURE_FIND_CONTEXT(ACTS(context, security_context_t context;))
|
|||||||
IF_FEATURE_FIND_PAREN( ACTS(paren, action ***subexpr;))
|
IF_FEATURE_FIND_PAREN( ACTS(paren, action ***subexpr;))
|
||||||
IF_FEATURE_FIND_PRUNE( ACTS(prune))
|
IF_FEATURE_FIND_PRUNE( ACTS(prune))
|
||||||
IF_FEATURE_FIND_DELETE( ACTS(delete))
|
IF_FEATURE_FIND_DELETE( ACTS(delete))
|
||||||
IF_FEATURE_FIND_EXEC( ACTS(exec, char **exec_argv; unsigned *subst_count; int exec_argc;))
|
IF_FEATURE_FIND_EXEC( ACTS(exec,
|
||||||
|
char **exec_argv; /* -exec ARGS */
|
||||||
|
unsigned *subst_count;
|
||||||
|
int exec_argc; /* count of ARGS */
|
||||||
|
IF_FEATURE_FIND_EXEC_PLUS(
|
||||||
|
/*
|
||||||
|
* filelist is NULL if "exec ;"
|
||||||
|
* non-NULL if "exec +"
|
||||||
|
*/
|
||||||
|
char **filelist;
|
||||||
|
int filelist_idx;
|
||||||
|
int file_len;
|
||||||
|
)
|
||||||
|
))
|
||||||
IF_FEATURE_FIND_GROUP( ACTS(group, gid_t gid;))
|
IF_FEATURE_FIND_GROUP( ACTS(group, gid_t gid;))
|
||||||
IF_FEATURE_FIND_LINKS( ACTS(links, char links_char; int links_count;))
|
IF_FEATURE_FIND_LINKS( ACTS(links, char links_char; int links_count;))
|
||||||
|
|
||||||
@ -452,7 +482,6 @@ static int exec_actions(action ***appp, const char *fileName, const struct stat
|
|||||||
return rc ^ TRUE; /* restore TRUE bit */
|
return rc ^ TRUE; /* restore TRUE bit */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if !FNM_CASEFOLD
|
#if !FNM_CASEFOLD
|
||||||
static char *strcpy_upcase(char *dst, const char *src)
|
static char *strcpy_upcase(char *dst, const char *src)
|
||||||
{
|
{
|
||||||
@ -576,17 +605,56 @@ ACTF(inum)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if ENABLE_FEATURE_FIND_EXEC
|
#if ENABLE_FEATURE_FIND_EXEC
|
||||||
ACTF(exec)
|
static int do_exec(action_exec *ap, const char *fileName)
|
||||||
{
|
{
|
||||||
int i, rc;
|
int i, rc;
|
||||||
#if ENABLE_USE_PORTABLE_CODE
|
# if ENABLE_FEATURE_FIND_EXEC_PLUS
|
||||||
char **argv = alloca(sizeof(char*) * (ap->exec_argc + 1));
|
int size = ap->exec_argc + ap->filelist_idx + 1;
|
||||||
#else /* gcc 4.3.1 generates smaller code: */
|
# else
|
||||||
char *argv[ap->exec_argc + 1];
|
int size = ap->exec_argc + 1;
|
||||||
|
# endif
|
||||||
|
# if ENABLE_USE_PORTABLE_CODE
|
||||||
|
char **argv = alloca(sizeof(char*) * size);
|
||||||
|
# else /* gcc 4.3.1 generates smaller code: */
|
||||||
|
char *argv[size];
|
||||||
|
# endif
|
||||||
|
char **pp = argv;
|
||||||
|
|
||||||
|
for (i = 0; i < ap->exec_argc; i++) {
|
||||||
|
const char *arg = ap->exec_argv[i];
|
||||||
|
|
||||||
|
# if ENABLE_FEATURE_FIND_EXEC_PLUS
|
||||||
|
if (ap->filelist) {
|
||||||
|
/* Handling "-exec +"
|
||||||
|
* Only one exec_argv[i] has substitution in it.
|
||||||
|
* Expand that one exec_argv[i] into file list.
|
||||||
|
*/
|
||||||
|
if (ap->subst_count[i] == 0) {
|
||||||
|
*pp++ = xstrdup(arg);
|
||||||
|
} else {
|
||||||
|
int j = 0;
|
||||||
|
while (ap->filelist[j]) {
|
||||||
|
*pp++ = xmalloc_substitute_string(arg, 1, "{}", ap->filelist[j]);
|
||||||
|
free(ap->filelist[j]);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
# endif
|
||||||
|
{
|
||||||
|
/* Handling "-exec ;" */
|
||||||
|
*pp++ = xmalloc_substitute_string(arg, ap->subst_count[i], "{}", fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*pp = NULL; /* terminate the list */
|
||||||
|
|
||||||
|
# if ENABLE_FEATURE_FIND_EXEC_PLUS
|
||||||
|
if (ap->filelist) {
|
||||||
|
ap->filelist[0] = NULL;
|
||||||
|
ap->filelist_idx = 0;
|
||||||
|
ap->file_len = 0;
|
||||||
|
}
|
||||||
# endif
|
# endif
|
||||||
for (i = 0; i < ap->exec_argc; i++)
|
|
||||||
argv[i] = xmalloc_substitute_string(ap->exec_argv[i], ap->subst_count[i], "{}", fileName);
|
|
||||||
argv[i] = NULL; /* terminate the list */
|
|
||||||
|
|
||||||
rc = spawn_and_wait(argv);
|
rc = spawn_and_wait(argv);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
@ -597,6 +665,48 @@ ACTF(exec)
|
|||||||
free(argv[i++]);
|
free(argv[i++]);
|
||||||
return rc == 0; /* return 1 if exitcode 0 */
|
return rc == 0; /* return 1 if exitcode 0 */
|
||||||
}
|
}
|
||||||
|
ACTF(exec)
|
||||||
|
{
|
||||||
|
# if ENABLE_FEATURE_FIND_EXEC_PLUS
|
||||||
|
if (ap->filelist) {
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
/* If we have lots of files already, exec the command */
|
||||||
|
if (ap->file_len >= 32*1024)
|
||||||
|
rc = do_exec(ap, NULL);
|
||||||
|
|
||||||
|
ap->file_len += strlen(fileName) + sizeof(char*) + 1;
|
||||||
|
ap->filelist = xrealloc_vector(ap->filelist, 8, ap->filelist_idx);
|
||||||
|
ap->filelist[ap->filelist_idx++] = xstrdup(fileName);
|
||||||
|
return rc == 0; /* return 1 if exitcode 0 */
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
return do_exec(ap, fileName);
|
||||||
|
}
|
||||||
|
# if ENABLE_FEATURE_FIND_EXEC_PLUS
|
||||||
|
static int flush_exec_plus(void)
|
||||||
|
{
|
||||||
|
action *ap;
|
||||||
|
action **app;
|
||||||
|
action ***appp = G.actions;
|
||||||
|
while ((app = *appp++) != NULL) {
|
||||||
|
while ((ap = *app++) != NULL) {
|
||||||
|
if (ap->f == (action_fp)func_exec) {
|
||||||
|
action_exec *ae = (void*)ap;
|
||||||
|
if (ae->filelist_idx != 0) {
|
||||||
|
int rc = do_exec(ae, NULL);
|
||||||
|
# if ENABLE_FEATURE_FIND_NOT
|
||||||
|
if (ap->invert) rc = !rc;
|
||||||
|
# endif
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
#if ENABLE_FEATURE_FIND_USER
|
#if ENABLE_FEATURE_FIND_USER
|
||||||
ACTF(user)
|
ACTF(user)
|
||||||
@ -1037,6 +1147,7 @@ static action*** parse_params(char **argv)
|
|||||||
else if (parm == PARM_exec) {
|
else if (parm == PARM_exec) {
|
||||||
int i;
|
int i;
|
||||||
action_exec *ap;
|
action_exec *ap;
|
||||||
|
IF_FEATURE_FIND_EXEC_PLUS(int all_subst = 0;)
|
||||||
dbg("%d", __LINE__);
|
dbg("%d", __LINE__);
|
||||||
G.need_print = 0;
|
G.need_print = 0;
|
||||||
ap = ALLOC_ACTION(exec);
|
ap = ALLOC_ACTION(exec);
|
||||||
@ -1049,10 +1160,13 @@ static action*** parse_params(char **argv)
|
|||||||
// executes "echo Foo >FILENAME<",
|
// executes "echo Foo >FILENAME<",
|
||||||
// find -exec echo Foo ">{}<" "+"
|
// find -exec echo Foo ">{}<" "+"
|
||||||
// executes "echo Foo FILENAME1 FILENAME2 FILENAME3...".
|
// executes "echo Foo FILENAME1 FILENAME2 FILENAME3...".
|
||||||
// TODO (so far we treat "+" just like ";")
|
|
||||||
if ((argv[0][0] == ';' || argv[0][0] == '+')
|
if ((argv[0][0] == ';' || argv[0][0] == '+')
|
||||||
&& argv[0][1] == '\0'
|
&& argv[0][1] == '\0'
|
||||||
) {
|
) {
|
||||||
|
# if ENABLE_FEATURE_FIND_EXEC_PLUS
|
||||||
|
if (argv[0][0] == '+')
|
||||||
|
ap->filelist = xzalloc(sizeof(ap->filelist[0]));
|
||||||
|
# endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
argv++;
|
argv++;
|
||||||
@ -1062,8 +1176,17 @@ static action*** parse_params(char **argv)
|
|||||||
bb_error_msg_and_die(bb_msg_requires_arg, arg);
|
bb_error_msg_and_die(bb_msg_requires_arg, arg);
|
||||||
ap->subst_count = xmalloc(ap->exec_argc * sizeof(int));
|
ap->subst_count = xmalloc(ap->exec_argc * sizeof(int));
|
||||||
i = ap->exec_argc;
|
i = ap->exec_argc;
|
||||||
while (i--)
|
while (i--) {
|
||||||
ap->subst_count[i] = count_strstr(ap->exec_argv[i], "{}");
|
ap->subst_count[i] = count_strstr(ap->exec_argv[i], "{}");
|
||||||
|
IF_FEATURE_FIND_EXEC_PLUS(all_subst += ap->subst_count[i];)
|
||||||
|
}
|
||||||
|
# if ENABLE_FEATURE_FIND_EXEC_PLUS
|
||||||
|
/*
|
||||||
|
* coreutils expects {} to appear only once in "-exec +"
|
||||||
|
*/
|
||||||
|
if (all_subst != 1 && ap->filelist)
|
||||||
|
bb_error_msg_and_die("only one '{}' allowed for -exec +");
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if ENABLE_FEATURE_FIND_PAREN
|
#if ENABLE_FEATURE_FIND_PAREN
|
||||||
@ -1335,8 +1458,11 @@ int find_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
0) /* depth */
|
0) /* depth */
|
||||||
) {
|
) {
|
||||||
status = EXIT_FAILURE;
|
status = EXIT_FAILURE;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IF_FEATURE_FIND_EXEC_PLUS(status = flush_exec_plus();)
|
||||||
|
out:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user