|Keep It Simple, Stupid|
Never forget to RTFM properly - a storyby robartes (Priest)
|on Mar 19, 2003 at 16:25 UTC||Need Help??|
This is a story just for amusement. There should be very little hard new information in this, but I thought I'd just post it to give people a laugh or two. I know I needed them :).
Tripped up by Unix semantics
Or: how our hero does not RTFM properly
Our hero, a confused Perl coder with a strong Unix background, is putting the finishing touches to a script that installs a fix to the production environment that needs to be installed now. Part of the script calls for the creation of a directory structure involving multiple symbolically linked directories (ugly as that is). It is in the creation of these links that our hero went off into the wild blue yonder. Read on for an account of the adventure.
The wild blue yonder
"Right," goes our hero, "Unix has ln and ln -s to create hard links and soft links, respectively..
This is wrong - or at least incomplete: Unix does indeed have the ln command that does both forms of link, but the underlying system calls are different: link(2) vs. symlink(2). However, our hero did not make the connection to the underlying system calls, and went looking for a Perl function to do the same. Lessee:
Sweet! Sounds like just the ticket!
Ticket to the wild blue yonder, that is.
Deep into the wild blue yonder
Right, off goes our hero to test his script on a harmless server somewhere. As root of course (bad sysadmin!). You see what's coming. The script works flawlessly (why did our hero not mistype just once? He usually does. Several times.), doing what it was intended to do. Unfortunately, what it was intended to do was also wrong.
It appears of course, that link creates hard links (as in, both filesystem entries have the same inode). symlink creates soft links (or symlinks, amazingly). Anyway, hard linking directories is not a good idea (it can easily create cyclic filesystem structures), so most Unixen make this very difficult, although not impossible. Perl of course, being the social language it is, persuades the OS to create hard links to directories, if the user really, really wants to. Unfortunately, removing a hard linked directory is not possible using rm or Perl's unlink. Not even using the magically dangerous rm -rf incantation.
Return from the wild blue yonder
This was discovered when our hero tried to clean up after himself and tried to erase the directory structury his script had created:
Eh? ... of course it exists ... that's why I want to remove it ... Hang on it's a hard link. Let's google: oh fun, we need to use unlink(2) to unlink it. So our hero dusts off his C compiler and whips up a quick program to remove the hardlink. No damage done. Phew. That was fun. Can I go again? Please?
Our hero got caught by confusing Unix command semantics (where soft links and hard links are made by the same command with different options) and actual underlying system calls (which is what Perl usually uses). Combine this with the fact that general lack of sleep caused our hero to not consider the fact that link does not have any options to specify the type of link somewhat suspicious, and you get the result described above.
Next time, RTFM! Looking through perlfunc would have shown our hero that there was something like symlink. Even if you think you are familiar with the issues, RTFM anyway, you never know what might come up :).
Update: Added readmore tags.