Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!cs.utexas.edu!usc!bloom-beacon!spdcc!ima!minya!jc From: jc@minya.UUCP (John Chambers) Newsgroups: comp.unix.wizards Subject: Two identical filenames in one directory! Message-ID: <22@minya.UUCP> Date: 27 Sep 89 21:26:09 GMT Organization: home Lines: 88 Hi, folks. Here I am again with another puzzle. You might recognize the following output: | foo: ls -ltr |tail -6 | 1956 -rw-rw-rw- 1 news news 797 Sep 27 13:13 errlog | 2241 -rw-rw-rw- 1 news news 14751 Sep 27 14:10 oactive | 256 drwxrwxrwx 2 news news 224 Sep 27 16:08 history.od | 128 drwxrwxrwx 2 news news 224 Sep 27 16:08 history.d | 1777 -rw-rw-rw- 1 news news 14751 Sep 27 16:40 active | 1898 -rw-rw-rw- 1 news news 14751 Sep 27 16:40 active Those two "active" files are a bit curious. Perhaps one of them has a nonprinting character in its name? Next I tried: | foo: mv active active.save | foo: ls -ltr |tail -6 | ./active not found | 1922 -rw-rw-rw- 1 news news 3 Sep 26 17:03 seq | 1956 -rw-rw-rw- 1 news news 797 Sep 27 13:13 errlog | 2241 -rw-rw-rw- 1 news news 14751 Sep 27 14:10 oactive | 256 drwxrwxrwx 2 news news 224 Sep 27 16:08 history.od | 128 drwxrwxrwx 2 news news 224 Sep 27 16:08 history.d | 1777 -rw-rw-rw- 1 news news 14751 Sep 27 16:40 active.save Curiouser and curiouser. The "active" file didn't just disappear; ls told me that it wasn't there. If it had a funny nonprinting character in its name, we'd expect to see it still. I undid the change, and fed the listing to a hexdump program. I won't bore you with the results of this; suffice it to say that there was no funny character at the end of the last two lines. (No remarks about the funny character sitting at the keyboard, please!) My next try was to feed the directory itself to the hexdumper, and edit out most of the lines so you don't have to wade thru them like I did. The two active files nicely turned out to be neighbors: | foo: hd . | ... | 192:_qactive_________jactive_________$errlog__________active--______ | C0:0F6676760000000106667676000000000A677666000000000066767622000000 | 611349650000000F7A1349650000000074522CF70000000000134965DD000000 | ... This is the "vertical" hexdump format, where each character in a vertical 3-byte slice. Thus byte 195 is 'c' which is 0x63. You all realized that this was Sys/V without needing to be told, of course, as soon as you saw this dump. If we chop it into 16-byte chunks, we have the entries: | _qactive________ | 0F66767600000001 | 611349650000000F and: | _jactive________ | 0666767600000000 | 7A13496500000000 Now we see what happened. Some gremlin (I almost said daemon ;-) has changed the last byte of one entry from 0x00 to 0x1F. When ls scans the directory, it sees a file called "active", properly null-terminated. It then tries to stat("active",&status), and this fails, because the kernel's namei() routine fills it with 8 null bytes, compares all 14 bytes, and they don't match. This also explains why the duplicate active files have all the data but the inode numbers the same; they are both listings for the second file. On earlier versions of Unix, I'd know instantly what to do. It's easy enough to write a program that runs thru a directory and extends each null byte to the end of the entry. But on Sys/V, this doesn't work, because nobody, not even root, can write a directory. I might observe that this is a clear violation of the principle that sofware should be conservative in what it produces and liberal in what it accepts. Sys/V allows the creation of such a directory entry; the proof is above; it should properly handle references to them. I might also make nasty remarks about the folks who decided that this sort of thing couldn't happen, so they didn't have to allow root to open directories for writing. I might even make comments about people who add code to kernels that does nothing productive; it just wastes cycles preventing me from doing something I want to do. But I won't. I'll just ask: Does anyone know a solution to this problem, short of zeroing the directory, running fsck, and reinstalling from backup? The best way would be to say "Yes, root can write a directory; here's how..." Alternatively, I guess I could try to find a pirate copy of the source to fsck, and add this to its repertoire. It'd probably only take an hour or two. Ain't binary-only systems nice? -- #echo 'Opinions Copyright 1989 by John Chambers; for licensing information contact:' echo ' John Chambers <{adelie,ima,mit-eddie}!minya!{jc,root}> (617/484-6393)' echo '' saying