bug-findutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: find -L -execdir (Was: "find" ends with exit code "0" although exec


From: James Youngman
Subject: Re: find -L -execdir (Was: "find" ends with exit code "0" although exec command returned an error)
Date: Tue, 22 Dec 2015 15:58:33 +0000

On Sun, Dec 20, 2015 at 7:54 PM, Stephane Chazelas
<address@hidden> wrote:
> 2015-12-20 18:30:36 +0000, James Youngman:
>> On Fri, Dec 18, 2015 at 11:43 PM, Stephane Chazelas
>> <address@hidden> wrote:
>>
>> > At that Q&A, we also discuss the behaviour of GNU find when both
>> > -L and -execdir are used for which I think at least the
>> > documentation could benefit from some clarification.

For those just joining us, that Q&A is
http://unix.stackexchange.com/questions/250191/why-gnu-find-execdir-command-behave-differently-than-bsd-find/250194

>> Could you be more specific?
> [...]
>
> Hi James
>
> Well what I wrote at the link was quite explicit. But to expand
> a bit:
>
> -execdir cmd {} is a feature introduced by BSDs and there, is
> explicitely documented to run cmd from  within dirname(file) and
> where {} is expanded basename(file).
>
> In the GNU find documentation, it's less clearly stated, but it
> mostly says the same thing.
>
> What -execdir does is more described in the -exec section:
>
>  -- Action: -exec command ;
>      This insecure variant of the '-execdir' action is specified by
>      POSIX. The main difference is that the command is executed in the
>      directory from which 'find' was invoked, meaning that '{}' is
>      expanded to a relative path starting with the name of one of the
>      starting directories, rather than just the basename of the matched
>      file.
>
>
> It says with -execdir, {} is the basename of the file which
> (without -L) is not completely true as it's "./" concatenated
> with the basename of the file.
>
> With -L (and it's not documented except in a comment in the
> code, again see http://unix.stackexchange.com/a/250194), cmd is
> not run from dirname(file), and {} is not "./" basename(file),

Right; that comment is
http://git.savannah.gnu.org/cgit/findutils.git/tree/find/exec.c?id=v4.5.14#n86
:-

      /* 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.
      */

Not stated there is the fact that -L is implemented in ftsfind by
turning on the FTS_LOGICAL flag of fts.   The gnulib fts
implementation forces FTS_CWDFD off for this case:

        /* Logical walks turn on NOCHDIR; symbolic links are too hard. */
        if (ISSET(FTS_LOGICAL)) {
                SET(FTS_NOCHDIR);
                CLR(FTS_CWDFD);
        }

The {} in -execdir always expands to the relative path to the file
we're considering.   I don't want to document that this is dependent
on the setting of -L since that's a bug (see below).


> it's mostly the same as -exec.
>
> /tmp/test$ mkdir -p 1/2/3
> /tmp/test$ find . -exec pwd \; -exec echo {} \;
> /tmp/test
> .
> /tmp/test
> ./1
> /tmp/test
> ./1/2
> /tmp/test
> ./1/2/3
> /tmp/test$ find . -execdir pwd \; -execdir echo {} \;
> /tmp/test
> ./.
> /tmp/test
> ./1
> /tmp/test/1
> ./2
> /tmp/test/1/2
> ./3
> /tmp/test$ find -L . -execdir pwd \; -execdir echo {} \;
> /tmp/test
> ./.
> /tmp/test
> ././1
> /tmp/test
> ././1/2
> /tmp/test
> ././1/2/3
>
>
>
> Ideally, I'd say it would be better if GNU find behaviour was
> the same as BSD's (where above you'd get the same output with
> and without -L.

I agree.

>
> If not (as I agree it won't make much difference from a security
> point of view as we're following links anyway), IMO the behaviour
> should be documented (along with the fact that it diverges from
> the original BSD implementation).

Trying your example with recent find code ($PWD here is the root of a
freshly built findutils tree), though, I don't get the same result.
It looks to me as if the the behaviour you're describing is a
previously reported and fixed bug
(https://savannah.gnu.org/bugs/?27563).   That bug was fixed in
version 4.5.9 (and apparently affects the current stable release):

$  for binary in `pwd`/installed-64/bin/find-* ; do ( mkdir -p
tmp/1/2/3 && cd tmp   && printf "%-8s %s\n" "$(echo ${binary}  | sed
-e 's_^.*/find-__')" "$(${binary} -L . -mindepth 3 \( -execdir pwd \;
, -execdir ls -d {} \; \) | tr '\n' ' ')" && rm -rf tmp); done | sort
-V
4.2.21   /home/james/source/GNU/findutils/tmp/1/2 ./3
4.2.22   /home/james/source/GNU/findutils/tmp/1/2 ./3
4.2.23   /home/james/source/GNU/findutils/tmp/1/2 ./3
4.2.24   /home/james/source/GNU/findutils/tmp/1/2 ./3
4.2.25   /home/james/source/GNU/findutils/tmp/1/2 ./3
4.2.26   /home/james/source/GNU/findutils/tmp/1/2 ./3
4.2.27   /home/james/source/GNU/findutils/tmp/1/2 ./3
4.2.28   /home/james/source/GNU/findutils/tmp/1/2 ./3
4.2.29   /home/james/source/GNU/findutils/tmp/1/2 ./3
4.2.30   /home/james/source/GNU/findutils/tmp/1/2 ./3
4.2.31   /home/james/source/GNU/findutils/tmp/1/2 ./3
4.2.32   /home/james/source/GNU/findutils/tmp/1/2 ./3
4.2.33   /home/james/source/GNU/findutils/tmp/1/2 ./3
4.3.0    /home/james/source/GNU/findutils/tmp ././1/2/3
4.3.1    /home/james/source/GNU/findutils/tmp ././1/2/3
4.3.2    /home/james/source/GNU/findutils/tmp ././1/2/3
4.3.3    /home/james/source/GNU/findutils/tmp ././1/2/3
4.3.4    /home/james/source/GNU/findutils/tmp ././1/2/3
4.3.5    /home/james/source/GNU/findutils/tmp ././1/2/3
4.3.6    /home/james/source/GNU/findutils/tmp ././1/2/3
4.3.7    /home/james/source/GNU/findutils/tmp ././1/2/3
4.3.9    /home/james/source/GNU/findutils/tmp ././1/2/3
4.3.10   /home/james/source/GNU/findutils/tmp ././1/2/3
4.3.11   /home/james/source/GNU/findutils/tmp ././1/2/3
4.3.12   /home/james/source/GNU/findutils/tmp ././1/2/3
4.3.13   /home/james/source/GNU/findutils/tmp ././1/2/3
4.4.0    /home/james/source/GNU/findutils/tmp ././1/2/3
4.4.1    /home/james/source/GNU/findutils/tmp ././1/2/3
4.4.2    /home/james/source/GNU/findutils/tmp ././1/2/3
4.5.0    /home/james/source/GNU/findutils/tmp ././1/2/3
4.5.1    /home/james/source/GNU/findutils/tmp ././1/2/3
4.5.2    /home/james/source/GNU/findutils/tmp ././1/2/3
4.5.3    /home/james/source/GNU/findutils/tmp ././1/2/3
4.5.4    /home/james/source/GNU/findutils/tmp ././1/2/3
4.5.5    /home/james/source/GNU/findutils/tmp ././1/2/3
4.5.6b   /home/james/source/GNU/findutils/tmp ././1/2/3
4.5.6    /home/james/source/GNU/findutils/tmp ././1/2/3
4.5.7    /home/james/source/GNU/findutils/tmp ././1/2/3
4.5.8    /home/james/source/GNU/findutils/tmp ././1/2/3
4.5.9    /home/james/source/GNU/findutils/tmp/1/2 ./3
4.5.10   /home/james/source/GNU/findutils/tmp/1/2 ./3
4.5.11   /home/james/source/GNU/findutils/tmp/1/2 ./3
4.5.12   /home/james/source/GNU/findutils/tmp/1/2 ./3
4.5.13   /home/james/source/GNU/findutils/tmp/1/2 ./3
4.5.14   /home/james/source/GNU/findutils/tmp/1/2 ./3
4.5.15   /home/james/source/GNU/findutils/tmp/1/2 ./3

Relevant bugfix:
http://git.savannah.gnu.org/cgit/findutils.git/commit/?id=e1d0a991e96ee164d74579efc027b09336e50c79
Tests: 
http://git.savannah.gnu.org/cgit/findutils.git/commit/?id=a1f54022d1913a92ccb728211127d5c238397eb6

Thanks,
James.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]