http://qs1969.pair.com?node_id=359700

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 need them :).

Tripped up by Unix semantics

Or: how our hero does not RTFM properly

The situation

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 has indeed the ln command, 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:

perldoc -f link link OLDFILE,NEWFILE Creates a new filename linked to the old filename. Returns true for success, false otherwise.

Sweet! Sounds just like 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:

# rm -rf directory Could not remove directory: File exists.

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?

The lesson

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 now what might come up :).

#!/usr/local/bin/perl -w $_="DO30QO00o*40DO30QO00o*40D*20QO20oDOO00DO*00DO40oD10QO10QO*10QO*00D +*20Q O10Q20D*20Q*30Q*00QO*10QO*10Q*30Q10D*20Q00QO40QO10QO20Q*30Q10QO*10QO*0 +0D*2 0Q20oD OO20Q*30Q*30Q*00QO00Q30D*20QO10QO00D*20oDOO20D*20XQO20oDOO +20Q* 00QO4 0D*20QO10Q20D*20Q*30Q10oDO O20QO00Q*00QO0 0Q30D* +20QO *10QO 10QO10QO*10Q40QO20Q*00oDO O40Q*20QO*00 DOO10DO +O10D OO10D O40DOO10D*40oDO*20QO00D*4 0DO*10o*40D *20DO30Q +O*40 o*40DO 30QO00o*40DO30QO00o*40D*20 XQ*10o*30Q 20QO10QO4 +0DO* 00DO10Q*00oO10DOO30o*40DO10Q*00oO00o20D OO40o*40DO 10Q*00DO*3 +0DO* 30DO*10QOO30D*20QO2 0oDOO00DO*00D*40oDO*20DOO30o2 0DOO30D*40Q +OO00 DO10Q*00DOO10D*40Q O10D*40DO*10o*40DO30QO*40o* 40DO00DO00XQ +D00Q 20QO10QO40DO*00DO1 0Q*00oO10o40DOO30o*40DO10Q *00oO20DOO00D +OO40 o*40DO10Q*00DOO00D OO00DO*10QOO30D*20QO20oDO O00DO*00D*40oD +O*20 DOO30o20DOO30D*40QO O00DO10Q*0 0DOO10D*4 0QO10D*40DO*10o +*40D O30QO*40o*40DO00DO00XQD00D*20QO20Q O40Q*00 QO00QO*10D*20D*4 +0oDO *20QO00D*40o*40D*20DO10QO*00oO10o* 20o*40 QO*40Q40Q*00Q*30Q +10DO *00D*20DO10QO*00DO*10QOO30D*20QO20 oDOO0 0DO*00D*20DO*00QO4 +0oDO O20QO00Q00DO*00DOO40DOO30DOO30DO*10 oO00o 30XoO30DO40QO10DO40 +o*30 D*20DO40D*20DO40DO*10DO*10D*20Q20QO10QO40D*20 DO*00DOO30DOO10DOO10 +o00o *20DO*10o*40D*20QO20oDOO00DO*00D*40D*20D*40Q OO00D*20DO10QO*00DOO1 +0D*4 0DOO20D*40DO O10D*40D*20D*40QOO00DO*00 o00DO*20XDO*00o*20DOO0 +0DO1 0QO*00DO*10 DO*10DOO10D*40D*20oDO*2 0oDO*20D*40DO*10o*40DO1 +0QO* 00DOO00DOO0 0o*40D*20QO20DO*00DO*0 0QO40oDOO20QO00Q00DO*00D +OO40 DOO30DOO30D O*10oO00o30oO30DO40QO 10DO40o*30DO40D*20DO40DO* +10D* 20DO*10DO00X Q20QO10QO40D*20DO*00D OO30DOO10DOO10o00o*20DO*10 +o*40 D*20DO30QO00o*40D*20QD00DO30QO00o*40QO 20DO*00D*40oOO00oDOO20Q*30Q +*30Q *00QO00Q30D*20QO10QO00 D*20QO*10 Q40Q10D*20Q*30Q10Q20QO*10o*3 +0D*4 0DO00DO00XDOO10D*40D* 20D*40Q OO00DOO40o*10D*20DOO10D*40oOO +30DO O20oD40D*40DOO10D*40D *20D*4 0QOO00DOO40o20D*20DOO10D*40oOO +00oD OO20Q*30Q*30Q*00QO00Q 30D*2 0QO10QO00D*20QO*10Q40Q10D*20QO4 +0Q*0 0Q30Q40QO*10o*30D*40DO *10Xo *40DO30QO00o*40QO20DO*00D*40D*20 +D*20 oOO30QO00QO20QO*20QO*10o*30D*20o DO*20DO10DOO20D*40D*20DOO10D*40D* +20D* 40QOO00o20o20D*20DOO10D*40D*20D *20oD40QO*20QO*10QO20QO*20QO*10o*3 +0D*2 0oDO*20DO10oDO*20oDO*20D*40DO* 10Xo*40DO30QO00o*40DO30QO00o*40QO*0 +0QO* 20oD +OO30 D*20 The falling droplets: a tale of daring, toothpics and some I/O +QO*4 0QOO +30DO 10Q30oO10DOO30o*40Q40o*30D*20DO10Q30oO20o40DOO30DOO30DOO30oO30Q30QO10Q +O*10 QO10D*20Q20o*30DO*00DO10Q30DO*30DO*30DO*40Q30QO10QO*10QO10XQ40DO*10o*4 +0D*2 0Q20o*30QD00D*20QO*00QO*20oDOO30D*20QO20D*20QOO30QO20QO40Q*00QO00QO*10 +D*20 QO*00Q40Q*00Q20QO*10QD00D*20QO*00QO*20oDOO30D*20QO00QOO30QO20DO*00D*40 +oDO* 20QO00D*40DO*10QD00D*20QO*00QO*20oDOO30XD*20D*20D*20D*20D*20D*20D*20D* +20D* 20D*20D*20D*20D*20D*20D*20D*20QO20oDOO00QOO30QO20D*20QO*00Q40Q*00Q20QO +*10Q D00";s{\s|T.*/O}()g;s(X){\n}g;while (s/(?=[QDOo*])(Q*)(o*)(D*)(O*)(\** +)(\d )0/chr(l($1)*100+l($2)*50+l($3)*25+l($4)*10+l($5)*5+$6)."XxX"/ex){};s{ +XxX} {}g;eval;sub l{return length shift}