diff options
author | Philip Guenther <guenther@cvs.openbsd.org> | 2013-03-12 06:00:06 +0000 |
---|---|---|
committer | Philip Guenther <guenther@cvs.openbsd.org> | 2013-03-12 06:00:06 +0000 |
commit | 22d6176c7a5b0d9982db2ad3b4a2e6befb249d3b (patch) | |
tree | a21b7f3ff4ae40407fc29238268b11a7ae5ffdfc /bin/ln | |
parent | 7832dd65734e7616e36f99c1a4281e4d293cfe03 (diff) |
Add support for the -L and -P options.
Based on a patch from Kent R. Spillner (kspillner (at) acm.org)
ok jmc@ millert@
Diffstat (limited to 'bin/ln')
-rw-r--r-- | bin/ln/ln.1 | 23 | ||||
-rw-r--r-- | bin/ln/ln.c | 28 |
2 files changed, 35 insertions, 16 deletions
diff --git a/bin/ln/ln.1 b/bin/ln/ln.1 index 89a2be0f00a..8e72ac88dff 100644 --- a/bin/ln/ln.1 +++ b/bin/ln/ln.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ln.1,v 1.29 2011/03/02 07:47:21 jmc Exp $ +.\" $OpenBSD: ln.1,v 1.30 2013/03/12 06:00:05 guenther Exp $ .\" $NetBSD: ln.1,v 1.10 1995/07/25 19:37:04 jtc Exp $ .\" .\" Copyright (c) 1980, 1990, 1993 @@ -33,7 +33,7 @@ .\" .\" @(#)ln.1 8.2 (Berkeley) 12/30/93 .\" -.Dd $Mdocdate: March 2 2011 $ +.Dd $Mdocdate: March 12 2013 $ .Dt LN 1 .Os .Sh NAME @@ -41,11 +41,11 @@ .Nd make hard and symbolic links to files .Sh SYNOPSIS .Nm ln -.Op Fl fhns +.Op Fl fhLnPs .Ar source .Op Ar target .Nm ln -.Op Fl fs +.Op Fl fLPs .Ar source ...\& .Op Ar directory .Sh DESCRIPTION @@ -68,10 +68,23 @@ The options are as follows: Unlink any already existing file, permitting the link to occur. .It Fl h If the target is a symlink to a directory, do not descend into it. +.It Fl L +When creating a hard link and the source is a symbolic link, +link to the fully resolved target of the symbolic link. +This is the default. +This option cancels the +.Fl P +option. .It Fl n An alias for .Fl h for compatibility with other operating systems. +.It Fl P +When creating a hard link and the source is a symbolic link, +link to the symbolic link itself. +This option cancels the +.Fl L +option. .It Fl s Create a symbolic link. .El @@ -183,7 +196,7 @@ create a new symlink pointing to itself. This results from directory-walking. .Sh SEE ALSO -.Xr link 2 , +.Xr linkat 2 , .Xr lstat 2 , .Xr readlink 2 , .Xr stat 2 , diff --git a/bin/ln/ln.c b/bin/ln/ln.c index 0b0be08f7a4..c5c40e7c409 100644 --- a/bin/ln/ln.c +++ b/bin/ln/ln.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ln.c,v 1.18 2009/10/27 23:59:21 deraadt Exp $ */ +/* $OpenBSD: ln.c,v 1.19 2013/03/12 06:00:05 guenther Exp $ */ /* $NetBSD: ln.c,v 1.10 1995/03/21 09:06:10 cgd Exp $ */ /* @@ -35,6 +35,7 @@ #include <err.h> #include <errno.h> +#include <fcntl.h> #include <libgen.h> #include <stdio.h> #include <stdlib.h> @@ -44,9 +45,8 @@ int dirflag; /* Undocumented directory flag. */ int fflag; /* Unlink existing files. */ int hflag; /* Check new name for symlink first. */ +int Pflag; /* Hard link to symlink. */ int sflag; /* Symbolic, not hard, link. */ - /* System link call. */ -int (*linkf)(const char *, const char *); int linkit(char *, char *, int); void usage(void) __dead; @@ -58,7 +58,7 @@ main(int argc, char *argv[]) int ch, exitval; char *sourcedir; - while ((ch = getopt(argc, argv, "Ffhns")) != -1) + while ((ch = getopt(argc, argv, "FfhLnPs")) != -1) switch (ch) { case 'F': dirflag = 1; /* XXX: deliberately undocumented. */ @@ -70,6 +70,12 @@ main(int argc, char *argv[]) case 'n': hflag = 1; break; + case 'L': + Pflag = 0; + break; + case 'P': + Pflag = 1; + break; case 's': sflag = 1; break; @@ -80,8 +86,6 @@ main(int argc, char *argv[]) argv += optind; argc -= optind; - linkf = sflag ? symlink : link; - switch(argc) { case 0: usage(); @@ -118,7 +122,7 @@ linkit(char *target, char *source, int isdir) if (!sflag) { /* If target doesn't exist, quit now. */ - if (stat(target, &sb)) { + if ((Pflag ? lstat : stat)(target, &sb)) { warn("%s", target); return (1); } @@ -157,7 +161,7 @@ linkit(char *target, char *source, int isdir) if (exists && !sflag) { struct stat tsb; - if (stat(target, &tsb) != 0) { + if ((Pflag ? lstat : stat)(target, &tsb)) { warn("%s: disappeared", target); return (1); } @@ -177,7 +181,9 @@ linkit(char *target, char *source, int isdir) * Attempt the link. */ if ((fflag && unlink(source) < 0 && errno != ENOENT) || - (*linkf)(target, source)) { + sflag ? symlink(target, source) : + linkat(AT_FDCWD, target, AT_FDCWD, source, + Pflag ? 0 : AT_SYMLINK_FOLLOW)) { warn("%s", source); return (1); } @@ -191,8 +197,8 @@ usage(void) extern char *__progname; (void)fprintf(stderr, - "usage: %s [-fhns] source [target]\n" - " %s [-fs] source ... [directory]\n", + "usage: %s [-fhLnPs] source [target]\n" + " %s [-fLPs] source ... [directory]\n", __progname, __progname); exit(1); } |