Date: Sun, 11 Feb 2001 23:09:44 +0100 (CET) From: mkamm@gmx.net To: FreeBSD-gnats-submit@freebsd.org Subject: bin/25013: mv(1) cannot move unresolvable symlinks across devices Message-ID: <200102112209.f1BM9iB02125@homebox.kammerhofer.org>
next in thread | raw e-mail | index | archive | help
>Number: 25013 >Category: bin >Synopsis: mv(1) cannot move unresolvable symlinks across devices >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Sun Feb 11 14:50:01 PST 2001 >Closed-Date: >Last-Modified: >Originator: Martin Kammerhofer >Release: FreeBSD 4.2-STABLE i386 >Organization: Universität Graz >Environment: >Description: Unresolvable symlinks cannot be moved across devices with mv(1). >How-To-Repeat: I assume that /tmp and $HOME are on different devices: $ ln -sf /GENERIC /tmp/generic $ mv /tmp/generic ~ # this does work Now I try to move a broken symlink $ ln -sf /NOSUCH /tmp/nosuch $ mv /tmp/nosuch ~ # this does work too Finally I trigger the bug: $ ln -sf /NODIR/NOFILE /tmp/nofile $ mv /tmp/nofile ~ mv: cannot resolve /tmp/nofile: /NODIR Even option -f doesn't help here. >Fix: The problem was introduced with a code snippet that protects against moving mountpoints. Moving mountpoints is bad, because that would trigger "cp -pRP /mountpoint newname". My patch invokes this code snippet only if a directory is to be moved and bypasses it otherwise. (My patch also tries to avoid redundant lstat(2) calls.) Index: mv.c =================================================================== RCS file: /home/ncvs/src/bin/mv/mv.c,v retrieving revision 1.27 diff -u -r1.27 mv.c --- mv.c 2000/07/20 18:30:00 1.27 +++ mv.c 2001/02/10 03:51:23 @@ -152,10 +152,11 @@ do_move(from, to) char *from, *to; { - struct stat sb; - int ask, ch, first; + struct stat sb_from, sb; + int ask, ch, first, got_from; char modep[15]; + got_from = 0; /* lstat of "from" not done yet */ /* * Check access. If interactive and file exists, ask user if it * should be replaced. Otherwise if file exists but isn't writable @@ -164,10 +165,11 @@ if (!fflg && !access(to, F_OK)) { /* prompt only if source exist */ - if (lstat(from, &sb) == -1) { + if (lstat(from, &sb_from) == -1) { warn("%s", from); return (1); } + got_from = 1; #define YESNO "(y/n [n]) " ask = 0; @@ -202,6 +204,14 @@ struct statfs sfs; char path[MAXPATHLEN]; + /* if from isn't a directory it can't be a mount point */ + if (!got_from && lstat(from, &sb_from) == -1) { + warn("%s", from); + return (1); + } + if (!S_ISDIR(sb_from.st_mode)) + goto copy_it; + /* Can't mv(1) a mount point. */ if (realpath(from, path) == NULL) { warnx("cannot resolve %s: %s", from, path); @@ -221,12 +231,13 @@ * it's a regular file, do the copy internally; otherwise, use * cp and rm. */ - if (lstat(from, &sb)) { + if (!got_from && lstat(from, &sb_from)) { warn("%s", from); return (1); } - return (S_ISREG(sb.st_mode) ? - fastcopy(from, to, &sb) : copy(from, to)); + copy_it: + return (S_ISREG(sb_from.st_mode) ? + fastcopy(from, to, &sb_from) : copy(from, to)); } int >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200102112209.f1BM9iB02125>