[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.