Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 22 Jan 2006 20:43:09 +0700 (KRAT)
From:      Eugene Grosbein <eugen@grosbein.pp.ru>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   bin/92149: [patch] ln -f -s does not remove existing directory
Message-ID:  <200601221343.k0MDh9xq048442@ws092.svzserv.kemerovo.su>
Resent-Message-ID: <200601221350.k0MDo32Y004126@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         92149
>Category:       bin
>Synopsis:       [patch] ln -f -s does not remove existing directory
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Jan 22 13:50:02 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Eugene Grosbein
>Release:        FreeBSD 6.0-STABLE i386
>Organization:
Svyaz-Service JSC
>Environment:
System: FreeBSD ws092.svzserv.kemerovo.su 6.0-STABLE FreeBSD 6.0-STABLE #6: Tue Dec 27 22:06:20 KRAT 2005 eugen@ws092.svzserv.kemerovo.su:/usr/obj/usr/src/sys/TEST i386

>Description:

	"ln -f -s" may be used to create a symlink to the file and
	the target file will be unlinked if it exists.

	However, ln will fail with 'Operation not permitted' message
	when target is a directory because unlink(2) does not remove
	empty directories.

>How-To-Repeat:

	mkdir -p dir/etc
	ln -f -s /etc dir

>Fix:

	The following patch allows ln(1) to remove existing target
	if the -s option is supplied and the target is the (empty) directory.

	The patch is for src/bin/ln:

--- ln.c.orig	Sun Jan 22 20:05:44 2006
+++ ln.c	Sun Jan 22 20:28:10 2006
@@ -198,8 +198,16 @@
 	/*
 	 * If the file exists, then unlink it forcibly if -f was specified
 	 * and interactively if -i was specified.
+	 *
+	 * For the directory, remove it when dealing with symbolic link only.
 	 */
 	if (fflag && exists) {
+		if (sflag && rmdir(source)) {
+			if (errno != ENOTDIR) {
+			    warn("%s", source);
+			    return (1);
+			}
+		}
 		if (unlink(source)) {
 			warn("%s", source);
 			return (1);
@@ -216,6 +224,12 @@
 			return (1);
 		}
 
+		if (sflag && rmdir(source)) {
+			if (errno != ENOTDIR) {
+			    warn("%s", source);
+			    return (1);
+			}
+		}
 		if (unlink(source)) {
 			warn("%s", source);
 			return (1);
--- ln.1.orig	Sun Jan 22 20:18:12 2006
+++ ln.1	Sun Jan 22 20:36:06 2006
@@ -69,8 +69,12 @@
 The options are as follows:
 .Bl -tag -width flag
 .It Fl f
-If the target file already exists,
-then unlink it so that the link may occur.
+If the target file or directory already exists,
+then remove it so that the link may occur.
+Note that no attempt to remove the directory is performed
+when running without the
+.Fl s
+option.
 (The
 .Fl f
 option overrides any previous
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200601221343.k0MDh9xq048442>