• Posts
  • RSS
  • ◂◂RSS
  • Contact

  • Self Redirection

    January 28th, 2012
    tech  [html]
    Trying to append a file to another, I was surprised when the terminal just sat there, taking seconds for something that should have been instant. When I canceled the operation I found that the file I was trying to append to hadn't changed and the original file had ballooned to several megabytes. Looking back, I had redirected a file to itself:
      $ cat file1 >> file1 # should have been file2
    
    You can try this yourself, but be prepared to hit Ctrl+C if it isn't instant:
       $ echo "abc" > tmp.txt
       $ cat tmp.txt >> tmp.txt
    
    With 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 file
    
    It's even smart enough to detect hardlinks:
       $ echo "abc" > tmp.txt
       $ ln tmp.txt tmp2.txt
       $ cat tmp.txt &gt> tmp2.txt
       cat: tmp.txt: input file is output file
    
    The 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

    Recent posts on blogs I like:

    Streaming the Biden Infrastructure Plan

    I streamed my thoughts about the Biden infrastructure plan, and unlike previous streams, I uploaded this to YouTube. I go into more details (and more tangents) on video, but, some key points: Out of the nearly $600 billion in the current proposal that is …

    via Pedestrian Observations April 11, 2021

    Collections: Clothing, How Did They Make it? Part IVb: Cloth Money

    This is the second half of the fourth part of our four part (I, II, III, IVa) look at the production of textiles, particularly wool and linen, in the pre-modern world. Last time, we looked at commercial textile workers and the finishing processes for text…

    via A Collection of Unmitigated Pedantry April 9, 2021

    Notes from “Don’t Shoot the Dog”

    I just finished Karen Pryor’s “Don’t Shoot the Dog: the New Art of Teaching and Training.” Partly because a friend points out that it’s not on Audible and therefore she can’t possibly read it, here are the notes I took and some thoughts. It’s a quick, eas…

    via The whole sky April 2, 2021

    more     (via openring)


  • Posts
  • RSS
  • ◂◂RSS
  • Contact