[comp.unix.questions] unlink

sjg@sun0.melb.bull.oz.au (Simon J. Gerraty) (10/18/90)

We have an interesting situation here.  While investigating the
practicalities of using an Appletalk-NFS gateway (Gatorbox I
think but please don't quote me), one of our users created a
file on one of our Sun's with a '/' in the name.
Unfortunately he forgot to remove the file before returning the
gateway.

Having exhausted all the normal solutions for removing files
with "funny" chars in their names, I was asked to have a look.
Again after quickly trying the above solutions myself, I went
and had a look in the manuals.

It only took five minutes to write a short C programme to print
inode/name pairs from a directory. ls(1) etc weren't any use at
all, though echo '*' would at least show the name.

Ok, I know the inode, all I have to do is get rid of it.  How?
While there are system/library calls to read directory entries,
there appears no way of _writing_ them, not even for root?  So a
simple directory sanitiser is out of the question.

It gets worse though as there appear to be no system/library
calls available to unlink or otherwise operate on an inode.  All
the commands, and system/library calls appear to deal with
pathnames only and naturally vomit when asked to deal with a
fictitious path (since the filename has a '/' in it :-)

So, have I missed something, or do I have to resort to editing
the raw disk file?  

I would also be interested to here how NFS created the stupid
file in the first place.  Perhaps I can write an programme to
ask NFS to remove it?

By the way all of the above applies to SunOS 4.0.3
--
Simon J. Gerraty			<sjg@sun0.melb.bull.oz.au>

#include <disclaimer>             /* imagine something *very* witty here */

chris@mimsy.umd.edu (Chris Torek) (10/19/90)

In article <1990Oct18.030832.10894@melb.bull.oz.au>
sjg@sun0.melb.bull.oz.au (Simon J. Gerraty) writes:
>...using an Appletalk-NFS gateway ... one of our users created a
>file on one of our Sun's with a '/' in the name.  Unfortunately he
>forgot to remove the file before returning the gateway. ...
>So, have I missed something, or do I have to resort to editing
>the raw disk file?  

Step 0 (apply iff necessary): fix fsck (and/or install the 4.3BSD-reno
fsck).  This requires sources, unfortunately.  Fortunately, the vendor
has sources.  Unfortunately, the vendor tends to be uncooperative in
this sort of situation.

Step 1: move all the good files out of the directory (this is to make step 2
simpler).

Step 2: run fsck.  It will say

	... DIRECTORY CORRUPTED.  FIX?

Answer yes.  It will then eventually want to reconnect or clear the file
it lost when it `fixed' the directory.

Alternatively, you can clri the inode of the directory, and all files
within that directory that have no other links will be recovered into
lost+found (again, moving all the other files helps here).

>I would also be interested to here how NFS created the stupid
>file in the first place.  Perhaps I can write an programme to
>ask NFS to remove it?

Yes, you can, though it is nontrivial.  The trick is that NFS does
not have `path names'; it just has `names'.  To look up /foo/bar/baz
you get a `file handle' on / and look up foo.  This gives a new file
handle, and you look up bar; this gives yet another file handle you
can use to look up baz.  For whatever silly reason, the Sun NFS
server code does not check for `impossible' characters in each file
lookup or create operation.  So it is possible to get an NFS handle
for the parent directory and hand the kernel a `remove' request with
the `file name', even though it does have an embedded slash.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris

cpcahil@virtech.uucp (Conor P. Cahill) (10/19/90)

In article <1990Oct18.030832.10894@melb.bull.oz.au> sjg@sun0.melb.bull.oz.au (Simon J. Gerraty) writes:
>It only took five minutes to write a short C programme to print
>inode/name pairs from a directory. ls(1) etc weren't any use at
>all, though echo '*' would at least show the name.

You could have used od(1) to get this info.

>Ok, I know the inode, all I have to do is get rid of it.  How?

If you just want to get rid of it, try clri followed by fsck.

If you want to save the file and just change the name so that it
no longer has a / in it, use fsdb.


-- 
Conor P. Cahill            (703)430-9247        Virtual Technologies, Inc.,
uunet!virtech!cpcahil                           46030 Manekin Plaza, Suite 160
                                                Sterling, VA 22170 

cbrandau@isis.cs.du.edu (carl brandauer) (10/21/90)

First, why write a C program when 'ls -i' will return the inumber (NOT inode)
of the file.  Once you have the inumber (say nnn),

	find . -inum nnn -exec rm {} \;

will do what you need.

cpcahil@virtech.uucp (Conor P. Cahill) (10/21/90)

In article <1990Oct20.182146.27039@isis.cs.du.edu> cbrandau@isis.UUCP (carl brandauer) writes:
>First, why write a C program when 'ls -i' will return the inumber (NOT inode)
>of the file.  Once you have the inumber (say nnn),
>
>	find . -inum nnn -exec rm {} \;
>
>will do what you need.

No it won't.  The problem with a filename that has a '/' in it is that
there is no way to access that file because the low level kernel 
routines interpret the '/' as a directory separator.


-- 
Conor P. Cahill            (703)430-9247        Virtual Technologies, Inc.,
uunet!virtech!cpcahil                           46030 Manekin Plaza, Suite 160
                                                Sterling, VA 22170 

chris@mimsy.umd.edu (Chris Torek) (10/21/90)

>In article <1990Oct20.182146.27039@isis.cs.du.edu> cbrandau@isis.UUCP
>(carl brandauer) writes:
>>First, why write a C program when 'ls -i' will return the inumber (NOT inode)
>>of the file.

(This depends on your `ls'.  The inode number is available in the directory
entry, but the last person to hack on `ls' may not not have been clever enough
to avoid an extra stat() call.)

>>	find . -inum nnn -exec rm {} \;
>>will do what you need.

In article <1990Oct21.002523.27266@virtech.uucp> cpcahil@virtech.uucp
(Conor P. Cahill) writes:
>No it won't.

Right.

>The problem with a filename that has a '/' in it is that
>there is no way to access that file because the low level kernel 
>routines interpret the '/' as a directory separator.

Confusing.

It is the *high level* KERNEL routines that interpret slashes.  The
problem is that NFS sits below this level.  Pictorially:

		[user space]
 -------|-------------------------------------------
 	|	[kernel space]
	|
  +-----v-----+
  | look for  | system calls
  | '/' and 0 | (open, link, unlink, stat, rename, ...)
  +-----v-----+
	|
	|
  +-----v-----+
  | r/w file  |
  | names in  <------------- NFS
  | directory |
  +-----v-----+
  	|
   (disk I/O)

Since NFS bypasses the code that makes sure each directory component
is valid, it is entirely capable of creating (and removing) invalid
component names.  (The same is true of disk I/O errors and bugs, which
is why fsck should check for such names.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris

avg@hq.demos.su (Vadim G. Antonov) (10/21/90)

Hm. What are you talkin' about? The fastest and simpliest way to
get rid of this weird file is to open your FM at the page describing
file systems structure and enter:

	adb -w /dev/dskNNN

Find the directory entry on the disk, write something valid instead of /,
mount disk and remove it with vanilla rm. Of course it is not a task for
Pascal programmers. ;-)

Vadim Antonov
DEMOS, Moscow, USSR

guy@auspex.auspex.com (Guy Harris) (10/31/90)

>For whatever silly reason, the Sun NFS server code does not check for
>`impossible' characters in each file lookup or create operation.

The reason is "nobody thought of putting such a check in".  I think
SunOS 4.1 does do the check.  (Auspex servers do the check as well, and
I suspect some but not all other vendors do.)

bernie@DIALix.oz.au (Bernd Felsche) (11/17/90)

In <1990Oct21.112102.1478@hq.demos.su>
	avg@hq.demos.su (Vadim G. Antonov) writes:

>Hm. What are you talkin' about? The fastest and simpliest way to
>get rid of this weird file is to open your FM at the page describing
>file systems structure and enter:

>	adb -w /dev/dskNNN
	^^^^^^^
Who's still got adb?  I used fsdb for much the same thing.

>Find the directory entry on the disk, write something valid instead of /,
>mount disk and remove it with vanilla rm. Of course it is not a task for
>Pascal programmers. ;-)

Heck, I could write a setuid program to do it!

(Very sleazy indeed, as it would fetch the inode and filesystem 
info for the directory to fsdb via a pipe: because I'm too lazy 
to write a subset of fsdb myself.)

You _don't_ even have to umount the filesystem, because the only 
change you are making is to the filename, which can't be de-referenced 
anyway (almost said "unlinked" :-)), until you rewrite the 
directory block.

On second thought, Pascal programmers should stick to paper... :-)
-- 
 ________Bernd_Felsche__________bernie@DIALix.oz.au_____________
[ Phone: +61 9 419 2297		19 Coleman Road			]
[ TZ:	 UTC-8			Calista, Western Australia 6167	]