bin/64430: Bug in mv(1)

Samuel Tardieu sam at rfc1149.net
Thu Mar 18 11:00:36 PST 2004


>Number:         64430
>Category:       bin
>Synopsis:       Bug in mv(1)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Mar 18 11:00:28 PST 2004
>Closed-Date:
>Last-Modified:
>Originator:     Samuel Tardieu
>Release:        FreeBSD 4.9-STABLE i386
>Organization:
Avian Carrier & Friends
>Environment:
System: FreeBSD beeblebrox 4.9-STABLE FreeBSD 4.9-STABLE #6: Mon Mar 15 21:54:41 CET 2004 root at willow:/usr/obj/usr/src/sys/BEEBLEBROX i386


>Description:
	In some cases, mv is unable to move files. Four conditions must
	be met to have it fail as far as I can see:
	  1) The source must be a symlink
	  2) The target must be a symlink
	  3) The target must point onto a mounting point
	  4) The source and target must not be on the same filesystem

	In this case, mv will issue an inappropriate "cannot rename a
	mounting point" error.

>How-To-Repeat:
	If /tmp is a mounting point and you are not in the /tmp filesystem,
	the following sequence reproduces the bug:
	  % ln -s /tmp bbb1
	  % ln -s /tmp bbb2
	  % mv bbb1 bbb2
	  mv: cannot rename a mount point

	The expected behaviour would be to move the bbb1 symlink into /tmp,
	target of the bbb2 symlink, as is done for any other kind of source
	or destination.

>Fix:
The following patch fixes that.

--- mv-old/mv.c	2004-03-18 19:44:53.000000000 +0100
+++ mv-new/mv.c	2004-03-18 19:44:53.000000000 +0100
@@ -212,6 +212,30 @@
 		struct statfs sfs;
 		char path[PATH_MAX];
 
+		/* If the source is a symbolic link and is on another
+		 * filesystem, it can be recreated at the destination.
+		 */
+		if (lstat(from, &sb) == -1) {
+		  warn("%s",from);
+		  return (1);
+		}
+		if (S_ISLNK(sb.st_mode)) {
+		  bzero(path, PATH_MAX);
+		  if (readlink(from, path, PATH_MAX) == -1) {
+		    warn("%s", from);
+		    return (1);
+		  }
+		  if (symlink(path,to)==-1) {
+		    warn("%s", to);
+		    return (1);
+		  }
+		  if (unlink(from) == -1) {
+		    warn("%s", from);
+		    return (1);
+		  }
+		  return (0);
+		}
+
 		/* Can't mv(1) a mount point. */
 		if (realpath(from, path) == NULL) {
 			warnx("cannot resolve %s: %s", from, path);
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list