[comp.os.minix] Fixes to 'mv'

paradis@encore.UUCP (Jim Paradis) (04/18/87)

Well, I finally got around to fixing the 'mv' utility.  As distributed,
it exhibited the following nasties:

	- If you moved a directory to some other part of the
	  tree, it would not update its ".." entry to reflect
	  its new place in the hierarchy

	- It would gladly let you clobber your "." and ".." 
	  entries (e.g. "mv .. foo" did not complain)

	- It would not let you specify a directory as the
	  destination of a directory move
	  (e.g. "mv /a/b/c/dirname ." would fail).

The fixes are as follows:

(1) Change the following code in main()

Was:

	if ((st.st_mode & S_IFMT) == S_IFDIR) {
	  if (!stat(argv[2], &st) && (st.st_mode & S_IFMT) == S_IFDIR) {
	    std_err("mv: target ");
	    std_err(argv[2]);
	    std_err(" exists\n");
	    exit(1);
	  }
	}
	else {
	  setgid (getgid());
	  setuid (getuid());
	}

Should be:

	setgid (getgid());
	setuid (getuid());


(2) Add the following right at the beginning of move():

	/* It's too dangerous to fool with "." or ".." ! */
	if ((strcmp(old, ".") == 0) || (strcmp(old, "..") == 0)) {
		cant(old);
	}

(3) Add the following just before the call to utime() in move():

	/* If this was a directory that we moved, then we ahve
	** to update its ".." entry (in case it was moved some-
	** where else in the tree)
	*/
	if ((st.st_mode & S_IFMT) == S_IFDIR) {
	    int i;
	    char parent[64], dotdot[64];

	    strcpy(parent, new);

	    /* Determine the name for the parent of
	    ** the new name by counting back until we
	    ** hit a '/' or the beginning of the string
	    */
	    for(i = (strlen(parent) - 1); i > 0; i--) {
		if(parent[i] == '/') break;
	    }

	    /* If there are no slashes, then the name is
	    ** in the current directory, so its parent
	    ** is ".".  Otherwise, the parent is the
	    ** name up to the last slash.
	    */
	    if (i == 0) {
		strcpy(parent, ".");
	    }
	    else {
		/* null-terminate name at last slash */
		parent[i] = '\0';
	    }

	    /* Unlink the ".." entry */
	    strcpy(dotdot, new);
	    strcat(dotdot, "/..");
	    unlink(dotdot);

	    /* Now link it to its parent */
	    link(parent, dotdot);
	}

Enjoy!

   +----------------+  Jim Paradis                  linus--+
+--+-------------+  |  Encore Computer Corp.       necntc--|
|  | E N C O R E |  |  257 Cedar Hill St.           ihnp4--+-encore!paradis
|  +-------------+--+  Marlboro MA 01752           decvax--|
+----------------+     (617) 460-0500             talcott--+
You don't honestly think ENCORE is responsible for this??!!