Self Redirection |
January 28th, 2012 |
tech |
$ cat file1 >> file1 # should have been file2You can try this yourself, but be prepared to hit Ctrl+C if it isn't instant:
$ echo "abc" > tmp.txt $ cat tmp.txt >> tmp.txtWith BSD
cat
, as I have on my mac, this just sits there,
filling up the disk at around 2MB/s. With GNU cat
, on the
server where I read email, I get:
cat: tmp.txt: input file is output fileIt's even smart enough to detect hardlinks:
$ echo "abc" > tmp.txt $ ln tmp.txt tmp2.txt $ cat tmp.txt >> tmp2.txt cat: tmp.txt: input file is output fileThe code for this in GNU cat, unchanged except for whitespace since at least 1992-11-08 when it was first put under source control, is:
/* Input file can be output file for non-regular files. fstat on pipes returns S_IFSOCK on some systems, S_IFIFO on others, so the checking should not be done for those types, and to allow things like cat < /dev/tty > /dev/tty, checking is not done for device files either. */ if (S_ISREG (stat_buf.st_mode)) { out_dev = stat_buf.st_dev; out_ino = stat_buf.st_ino; } else check_redirection = 0; ... /* Compare the device and i-node numbers of this input file with the corresponding values of the (output file associated with) stdout, and skip this input file if they coincide. Input files cannot be redirected to themselves. */ if (check_redirection && stat_buf.st_dev == out_dev && stat_buf.st_ino == out_ino) { error (0, 0, "%s: input file is output file", infile); exit_stat = 1; goto contin; }The reason hardlinks don't fool
cat
is that it checks the device and inode
values, which all hardlinks to a file will have the same:
$ echo "abc" > tmp.txt $ ln tmp.txt tmp2.txt $ stat tmp.txt | grep Inode Device: 803h/2051dInode: 18645001 Links: 2 $ $ stat tmp2.txt | grep Inode Device: 803h/2051dInode: 18645001 Links: 2
Comment via: google plus, facebook