Sun 21 Nov 2004 03:22:08 PM UTC, comment #1:
I've figured out how this happens. The relevant system calls are the following:-
27681 lstat64("b", {st_dev=makedev(3, 2), st_ino=16677, st_mode=S_IFDIR|0755, s\t_nlink=2, st_uid=1001, st_gid=100, st_blksize=4096, st_blocks=2, st_size=1024,\ st_atime=2004/11/21-14:53:04, st_mtime=2004/11/21-14:53:04, st_ctime=2004/11/2\1-14:53:04}) = 0
27681 rt_sigaction(SIGCHLD, {SIG_DFL}, {SIG_DFL}, 8) = 0
27681 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHL\D, child_tidptr=0x401682e8) = 27683
27681 waitpid(27683, <unfinished ...>
27683 fchdir(3) = 0
27683 execve("/bin/touch", ["/bin/touch", "/tmp/racebug/user/b/gotcha"], ["HZ=1\00", "TERM=xterm", "SHELL=/bin/bash", "USER=root", "PATH=/usr/local/sbin:/usr/l\ocal/"..., "MAIL=/var/mail/root", "PWD=/tmp/racebug", "HOME=/root", "SHLVL=2", \"LOGNAME=root", "_=/usr/bin/strace"]) = 0
(Under other versions of Unix, the clone system call would be "fork").
The problem is that to implement -exec, "find" changes directory back to the directory from which it started (by using fchdir). The 'touch' command then uses the path name /tmp/racebug/user/b/gotcha, but by the time it does that, "b" points to /tmp/racebug/root. Hence the file "/tmp/racebug/root/gotcha" gets created, even though find never looked inside /tmp/racebug/root, but only in /tmp/racebug/user.
It is this problem that the FreeBSD version of find addresses with "-execdir". I have had that on my list of things to do for some time now. However, I now understand more fully why the feature is really necessary. We can't change the behaviour of -exec because the POSIX standard
states that the working directory of the invoked command must be the same as the directory which was the working directory when find was invoked.
An analohous problem of course exists with "find ... -print0 | xargs -0 blah ..."
|