bruce.dubbs at gmail.com
Sun May 17 22:00:12 PDT 2009
Bryan Kadzban wrote:
> Bruce Dubbs wrote:
>> The problem code looks like:
>> exec 4>&1
>> (gzip -cdfq -- "$1" 4>&-; echo $? >&4) 3>&- |
>> ( (gzip -cdfq -- "$2" 4>&-; echo $? >&4) 3>&- 5<&- </dev/null |
>> eval "$cmp" /dev/fd/5 -) 5<&0
> Sheesh, that's complicated!
Yes, it's bad. Earlier they have:
test "X$file" = X- || <"$file" || exit 2
but file is never defined, so this always fails. It might be for another shell
or architecture, but it isn't commented and look screwy.
Let's see if I can decipher...
> Duplicate FD 1 into FD 4. Then start a subshell with FD 3 closed
> (...but where was 3 opened? before this?);
Yes, earlier it does
Why we need to use 3 at all is a mystery to me.
in that subshell, gunzip $1
> to FD 1, closing FD 4 before doing so, and echo the exit status into FD
> 4. Pipe FD 1 (the decompressed file) into another subshell, and
> duplicate that input stream into FD 5 (hmm; FDs 0 and 5 are both this
> In that second subshell, start yet another subshell with FDs 5 and 3
> (...again, with 3) closed, and with stdin coming from /dev/null (not the
> pipe); in that subshell, gunzip $2 to stdout with FD 4 closed, and echo
> the exit status of this gzip into FD 4 as well. Pipe the decompressed
> file into "eval $cmp /dev/fd/5 -" (whatever $cmp is; presumably - means
> Both exit statuses are put into gzip_status, along with whatever "$cmp"
> outputs. This last bit might be the bug, depending on where FD 3 is
> going. If FD 3 is a duplicate of the output stream of zdiff (e.g. they
> did an "exec 3>&1" earlier), then your fix is correct: the output of
> $cmp needs to be shown to the user, not dumped into the gzip_status
> Looks like it's attempting to run "$cmp" (whatever it is) on the two
> streams of gunzip output.
Yes and keep it all in memory. They don't want to do any disk IO here.
(/dev/fd/X is the current process's file
> descriptor X; useful for programs like diff and cmp that require file
> names, when you want to compare a stream.)
> It's a giant Y; the two arms of the Y are the gunzip streams, and the
> point in the middle is the $cmp invocation. The rest is just
> scaffolding to be able to capture the exit status of each gzip, and to
> make sure programs can't get at FDs they shouldn't be able to get at.
> (Does that actually help? :-) )
Yes. I hadn't run into a script that closed file streams with things like 3>&-
>> When I look at /dev/fd, I only have 0 through 3 (and on RH and Ubuntu other
>> systems too, but none use gzip-1.3.12).
> That's because the ls process only has stdin, stdout, and stderr open;
> FD 3 is a handle to the /proc/self/fd directory itself in this case
> (because you're looking at its contents; opendir() returned 3).
That's a new one for me.
> (Oh: /dev/fd is a symlink to /proc/self/fd; see /lib/udev/devices.)
That part I knew. In any case, its fixed up in the book and I did test it,
so it does work.
Thanks for the feedback.
More information about the lfs-dev