Path: utzoo!utgpu!jarvis.csri.toronto.edu!clyde.concordia.ca!uunet!samsung!uakari.primate.wisc.edu!caesar.cs.montana.edu!ogicse!plains!overby From: overby@plains.UUCP (Glen Overby) Newsgroups: comp.os.minix Subject: questionable operation of unlink(2) Summary: unlink(2) will not unlink a file unless you have write permission on it. Message-ID: <3052@plains.UUCP> Date: 28 Dec 89 04:13:59 GMT Reply-To: overby@plains.UUCP (Glen Overby) Organization: North Dakota State University, Fargo Lines: 65 This query is primarily directed at Andy and Bruce, but others on the net might have some insight into my question (and why make a fool of yourself to just a few, when you can do it on the net to thousands? :-). Background: unlink(2) will not remove a file to which you do not have write permission. For example, say I own the current directory, and have write premission in it (say, mode 777 -- I know that's poor security, but I'm trying to simplify things here). If I own a file, "Charlie", in the current directory, but cannot write to it (say, mode 444), I cannot unlink it. I tried this in a simple program that does an unlink("Charlie"); and a perror. I get permission denied. Since it does not work with this trivial test program, it is not a problem in rm. I find this "feature" to be different than in any Unix derivative I've used and quite irritating. Upon descending into the FS sources, I found these routines of interest: link:do_unlink path:search_dir protec:forbidden search_dir appears to do most of the dirty work. Here's what I found: File: 1.5.0/fs/path.c PUBLIC int search_dir(ldir_ptr, string, numb, flag) { [...] /* If 'ldir_ptr' is not a pointer to a searchable dir inode, error. */ if ( (ldir_ptr->i_mode & I_TYPE) != I_DIRECTORY) return(ENOTDIR); Check permissions: we need x if searching, w and x if modifying. bits = (flag == LOOK_UP ? X_BIT : W_BIT|X_BIT); if ( (r = forbidden(ldir_ptr, bits, 0)) != OK) return(r); so far, so good. We need this. But ... [...] # rip points to an inode for the file to remove. # dp points to the directory entry in the directory block. rip = get_inode(ldir_ptr->i_dev, dp->d_inum); if ((r = forbidden(rip, W_BIT, 0)) == OK) { Wait a second! Why do we have to check for having write permission here? /* Save d_inum for recovery. */ t = NAME_MAX - sizeof(ino_t); *((ino_t *) &dp->d_name[t])=dp->d_inum; Hmm! a hook for undeleting files! I cannot find anything in the POSIX standard regarding what permissions are required for unlinking a file. What, if anything, will break if the if ... forbidden conditional is removed? -- Glen Overby uunet!plains!overby (UUCP) ncoverby@ndsuvax, overby@plains (Bitnet)