[comp.os.minix] fs/path.c and fs/link.c

cechew@bruce.cs.monash.OZ.AU (Earl Chew) (07/31/90)

While browsing through path.c and link.c whilst repairing the recently posted
symbolic link patches I noticed the following code in fs/path.c last_dir:

-------------------------------------------------------------------------------
  dup_inode(rip);		/* inode will be returned with put_inode */

  /* Remove trailing "/." from paths (e.g., "/usr/ast/." becomes "/usr/ast") */
  if (fs_call == UNLINK || fs_call == RMDIR) {
	while (1) {
		p = path + strlen(path) - 2;	/* pts to next-to-last char */
		if (p > path && *p == '/' && *(p + 1) == '.') 
			*p = '\0';
		else
			break;
	}
  }

  /* Scan the path component by component. */
  while (TRUE) {
-------------------------------------------------------------------------------

Furthermore, looking in fs/link.c:

-------------------------------------------------------------------------------
  /* Now test if the call is allowed, separately for unlink() and rmdir(). */
  if (fs_call == UNLINK) {
	/* Only the su may unlink directories, but the su can unlink any dir.*/
	if ( (rip->i_mode & I_TYPE) == I_DIRECTORY && !super_user) r = EPERM;

	/* Actually try to unlink the file; fails if parent is mode 0 etc. */
	if (r == OK) r = search_dir(rldirp, string, (ino_t *) 0, DELETE);
  } else {
	/* The call is rmdir().  Five conditions have to met for this call:
	 * 	- The file must be a directory
	 *	- The directory must be empty (except for . and ..)
	 *	- It must not be /
 	 *	- The path must not end in . or ..
	 *	- The directory must not be anybody's working directory
	 */
	if ( (rip->i_mode & I_TYPE) != I_DIRECTORY) r = ENOTDIR;
	if (search_dir(rip, "", &numb, LOOK_UP) == OK) r = ENOTEMPTY;
	if (strcmp(user_path, "/") == 0) r = EPERM;	/* can't remove root */
	if (strcmp(string, ".") == 0 || strcmp(string, "..") == 0) r = EPERM;
	for (rfp = &fproc[INIT_PROC_NR + 1]; rfp < &fproc[NR_PROCS]; rfp++) {
		if (rfp->fp_workdir == rip || rfp->fp_rootdir == rip) {
			r = EBUSY;	/* can't remove anybody's working dir*/
			break;
		}
	}
-------------------------------------------------------------------------------

My questions primarily concern the code in fs/path.c.

o Why is the extra code in last_dir.c? Why is it necessary to protect against
  unlink("/ast/.") or rmdir("/ast/.")?

o Since "." is stripped, the code for RMDIR testing for trailing "." is
  superfluous, isn't it?

o Furthermore, if RMDIR attempts to remove "..", ".." won't be empty so the
  procedure should fail with ENOTEMPTY and won't even get down to the line that
  fails the operation with EPERM. Correct?

Earl
-- 
Earl Chew, Dept of Computer Science, Monash University, Australia 3168
ARPA: cechew%bruce.cs.monash.oz.au@uunet.uu.net  ACS : cechew@bruce.oz
----------------------------------------------------------------------