[busybox] BUG with find -exec

Denis Vlasenko vda.linux at googlemail.com
Sat Dec 23 00:47:00 UTC 2006


On Friday 22 December 2006 10:41, Bernhard Fischer wrote:
> Hi,
> 
> Just noticed this little glitch:
> 
> $ (/tmp/busybox/busybox find /usr/lib/ -name '*.pyc' -o -name '*.pyo'
> -exec ls {} \; ;echo ret=$?)2>&1 >&1 | tail  -n 7

-name '*.pyc' -o -name '*.pyo' -exec ls

means:

-name '*.pyc' -o ( -name '*.pyo' -a -exec ls )

You probably wanted something different. But I digress.

> /usr/lib/python2.3/site-packages/twisted/manhole/explorer.pyo
> find: ls: No such file or directory
> /usr/lib/python2.3/site-packages/twisted/manhole/_inspectro.pyo
> find: ls: No such file or directory
> /usr/lib/python2.3/site-packages/antlr.pyo
> find: ls: No such file or directory
> ret=0
> 
> Didn't look, but giving the absolute path to the command to be run
> via -exec makes the error output go away..

Bug is here:

--- findutils/find.c    (revision 17059)
+++ findutils/find.c    (working copy)
@@ -197,9 +197,9 @@
        for (i = 0; i < ap->exec_argc; i++)
                argv[i] = subst(ap->exec_argv[i], ap->subst_count[i], fileName);
        argv[i] = NULL; /* terminate the list */
-       errno = 0;
        rc = wait4pid(spawn(argv));
-       if (errno)
+       if (rc)
                bb_perror_msg("%s", argv[0]);
        for (i = 0; i < ap->exec_argc; i++)
                free(argv[i]);

I needed to modify spawn a bit so that errno is retrieved from the vfork'ed child.
BTW, do you know why we use "_static_ int failed" here?
I tested and without it, errno isn't returned properly. Why?

pid_t spawn(char **argv)
{
        /* Why static? */
        static int failed;
        pid_t pid;
        void *app = ENABLE_FEATURE_SH_STANDALONE_SHELL ? find_applet_by_name(argv[0]) : 0;

        // Be nice to nommu machines.
        failed = 0;
        pid = vfork();
        if (pid < 0) return pid;
        if (!pid) {
                execvp(app ? CONFIG_BUSYBOX_EXEC_PATH : *argv, argv);

                // We're sharing a stack with blocked parent, let parent know we failed
                // and then exit to unblock parent (but don't run atexit() stuff, which
                // would screw up parent.)

                failed = errno;
                _exit(0);
        }
        if (failed) {
                errno = failed;
                return -1;
        }
        return pid;
}
--
vda



More information about the busybox mailing list