Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 20 Apr 2001 17:38:52 +0300
From:      Maxim Sobolev <sobomax@FreeBSD.org>
To:        audit@FreeBSD.org
Cc:        hackers@FreeBSD.org
Subject:   Merging ln(1) ``-h'' option from NetBSD [patch]
Message-ID:  <3AE049FC.60613D17@FreeBSD.org>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------9D96218EA2955EAD73F8C911
Content-Type: text/plain; charset=koi8-r
Content-Transfer-Encoding: 7bit

Please somebody take a look at attached patch that adds ``-h'' option
to the ln(1) command (obtained from NetBSD, which has it since 1997).
In addition, I've tried to minimise diffs between our code and
NetBSD's one, so  there are several changes that at a first glance
look superfluous.

-Maxim

--------------9D96218EA2955EAD73F8C911
Content-Type: text/plain; charset=koi8-r;
 name="ln.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="ln.diff"

Index: ln.1
===================================================================
RCS file: /home/ncvs/src/bin/ln/ln.1,v
retrieving revision 1.14
diff -d -u -r1.14 ln.1
--- ln.1	2000/11/20 11:39:37	1.14
+++ ln.1	2001/04/20 14:36:37
@@ -44,11 +44,11 @@
 .Nd make links
 .Sh SYNOPSIS
 .Nm
-.Op Fl fisv
+.Op Fl fhinsv
 .Ar source_file
 .Op target_file
 .Nm
-.Op Fl fisv
+.Op Fl fhinsv
 .Ar source_file ...
 .Op target_dir
 .Nm link
@@ -79,6 +79,14 @@
 option overrides any previous
 .Fl i
 options.)
+.It Fl h
+If the
+.Ar target_file
+or
+.Ar target_dir
+is a symbolic link, do not follow it.  This is most useful with the
+.Fl f
+option, to replace a symlink which may point to a directory.
 .It Fl i
 Cause
 .Nm
@@ -94,6 +102,12 @@
 option overrides any previous
 .Fl f
 options.)
+.It Fl n
+Same as
+.Fl h ,
+for compatibility with other
+.Nm
+implementations.
 .It Fl s
 Create a symbolic link.
 .It Fl v
@@ -168,12 +182,18 @@
 and
 .Fl v
 options are non-standard and their use in scripts is not recommended.
-.Sh HISTORY
-An
+.Sh STANDARDS
+The
 .Nm
-command appeared in
-.At v1 .
+utility conforms to
+.St -p1003.2-92 .
+.Pp
 The simplified
 .Nm link
 command conforms to
 .St -susv2 .
+.Sh HISTORY
+An
+.Nm
+command appeared in
+.At v1 .
Index: ln.c
===================================================================
RCS file: /home/ncvs/src/bin/ln/ln.c,v
retrieving revision 1.18
diff -d -u -r1.18 ln.c
--- ln.c	2000/08/17 16:08:06	1.18
+++ ln.c	2001/04/20 14:36:37
@@ -57,6 +57,7 @@
 
 int	fflag;				/* Unlink existing files. */
 int	iflag;				/* Interactive mode. */
+int	hflag;				/* Check new name for symlink first. */
 int	sflag;				/* Symbolic, not hard, link. */
 int	vflag;				/* Verbose output. */
 					/* System link call. */
@@ -65,6 +66,7 @@
 
 int	linkit __P((char *, char *, int));
 void	usage __P((void));
+int	main __P((int, char *[]));
 
 int
 main(argc, argv)
@@ -73,7 +75,8 @@
 {
 	struct stat sb;
 	int ch, exitval;
-	char *p, *sourcedir;
+	char *p;
+	char *sourcedir;
 
 	/*
 	 * Test for the special case where the utility is called as
@@ -92,12 +95,16 @@
 			usage();
 	}
 
-	while ((ch = getopt(argc, argv, "fisv")) != -1)
+	while ((ch = getopt(argc, argv, "fhinsv")) != -1)
 		switch (ch) {
 		case 'f':
 			fflag = 1;
 			iflag = 0;
 			break;
+		case 'h':
+		case 'n':
+			hflag = 1;
+			break;
 		case 'i':
 			iflag = 1;
 			fflag = 0;
@@ -122,13 +129,22 @@
 	switch(argc) {
 	case 0:
 		usage();
+		/* NOTREACHED */
 	case 1:				/* ln target */
 		exit(linkit(argv[0], ".", 1));
+		/* NOTREACHED */
 	case 2:				/* ln target source */
 		exit(linkit(argv[0], argv[1], 0));
+		/* NOTREACHED */
 	}
 					/* ln target1 target2 directory */
 	sourcedir = argv[argc - 1];
+	if (hflag && lstat(sourcedir, &sb) == 0 && S_ISLNK(sb.st_mode)) {
+		/* we were asked not to follow symlinks, but found one at
+		   the target--simulate "not a directory" error */
+		errno = ENOTDIR;
+		err(1, "%s", sourcedir);
+	}
 	if (stat(sourcedir, &sb))
 		err(1, "%s", sourcedir);
 	if (!S_ISDIR(sb.st_mode))
@@ -136,6 +152,7 @@
 	for (exitval = 0; *argv != sourcedir; ++argv)
 		exitval |= linkit(*argv, sourcedir, 1);
 	exit(exitval);
+	/* NOTREACHED */
 }
 
 int
@@ -161,18 +178,20 @@
 		}
 	}
 
-	/* If the source is a directory, append the target's name. */
-	if (isdir || ((exists = !stat(source, &sb)) && S_ISDIR(sb.st_mode))) {
+	/* If the source is a directory (and not a symlink if hflag),
+	   append the target's name. */
+	if (isdir ||
+	    (!lstat(source, &sb) && S_ISDIR(sb.st_mode)) ||
+	    (!hflag && !stat(source, &sb) && S_ISDIR(sb.st_mode))) {
 		if ((p = strrchr(target, '/')) == NULL)
 			p = target;
 		else
 			++p;
 		(void)snprintf(path, sizeof(path), "%s/%s", source, p);
 		source = path;
-		exists = !lstat(source, &sb);
-	} else
-		exists = !lstat(source, &sb);
+	}
 
+	exists = !lstat(source, &sb);
 	/*
 	 * If the file exists, then unlink it forcibly if -f was specified
 	 * and interactively if -i was specified.
@@ -214,8 +233,9 @@
 usage()
 {
 	(void)fprintf(stderr, "%s\n%s\n%s\n",
-	    "usage: ln [-fisv] file1 file2",
-	    "       ln [-fisv] file ... directory",
+	    "usage: ln [-fhinsv] file1 file2",
+	    "       ln [-fhinsv] file ... directory",
 	    "       link file1 file2");
 	exit(1);
+	/* NOTREACHED */
 }

--------------9D96218EA2955EAD73F8C911--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-audit" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3AE049FC.60613D17>