I'm going through a bash script, trying to figure out how it works and potentially patching it. The script in question is this cryptroot
script from debian responsible for decrypting block devices at boot. Not being completely at home in bash definitely makes it a challenge.
I found this piece of code and I'm not sure what it does.
if [ -r /conf/conf.d/cryptroot ]; then
while read mapping <&3; do
setup_mapping "$mapping" 3<&-
done 3< /conf/conf.d/cryptroot
fi
My guess is that it reads each line in /conf/conf.d/cryptroot
and passes it to setup_mapping
. But I don't quite understand how, what the significance of <&3
, 3&-
and 3</conf/conf.d/cryptroot
is, and what they do?
When I read lines from a file I usually do something like this:
while read LINE
do COMMAND
done < FILE
Where the output of FILE
is directed to read
in the while loop and doing COMMAND
until the last line.
I also know a little bit about redirection, as in, I sometimes use it to redirect STDOUT
and STDERR
to stuff like /dev/null
for example. But I'm not sure what the redirection to 3
means.
After reading a little bit more about I/O redirection I've something close to an answer, according to tldp.org.
The file descriptors for stdin, stdout, and stderr are 0, 1, and 2, respectively. For opening additional files, there remain descriptors 3 to 9.
So the 3 is "just" a reference to an open file or:
...simply a number that the operating system assigns to an open file to keep track of it. Consider it a simplified type of file pointer.
So from what I understand:
- The
3< /conf/conf.d/cryptroot
opens/conf/conf.d/cryptroot
for reading and assigns it to file descriptor 3. - The
read mapping <&3
seems to be reading the first line from file descriptor 3, which points to the open file/conf/conf.d/cryptroot
. - The
setup_mapping "$mapping" 3<&-
seems to be closing file descriptor 3, does this mean that it is opened again for every turn in the loop and pointing to the next line?
If the above is correct my question is why do this rather than the "normal" way? e.g.
while read mapping; do
setup_mapping "$mapping"
done < /conf/conf.d/cryptroot
What advantage (if any) does the first version provide?