mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-02 12:20:51 +00:00
Allow creating hard links to symlinks using ln(1).
This implements the POSIX.1-2008 -L and -P flags. The default remains to create hard links to the target of symlinks. Approved by: re (kib), ed (mentor)
This commit is contained in:
parent
3ca3047aee
commit
80a0e9b5f5
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=195768
39
bin/ln/ln.1
39
bin/ln/ln.1
@ -32,7 +32,7 @@
|
||||
.\" @(#)ln.1 8.2 (Berkeley) 12/30/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 6, 2008
|
||||
.Dd July 17, 2009
|
||||
.Dt LN 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -41,13 +41,13 @@
|
||||
.Nd link files
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl s Op Fl F
|
||||
.Op Fl L | Fl P | Fl s Op Fl F
|
||||
.Op Fl f | iw
|
||||
.Op Fl hnv
|
||||
.Ar source_file
|
||||
.Op Ar target_file
|
||||
.Nm
|
||||
.Op Fl s Op Fl F
|
||||
.Op Fl L | Fl P | Fl s Op Fl F
|
||||
.Op Fl f | iw
|
||||
.Op Fl hnv
|
||||
.Ar source_file ...
|
||||
@ -77,16 +77,6 @@ to a file is one of the differences between a hard and symbolic link.
|
||||
.Pp
|
||||
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.
|
||||
(The
|
||||
.Fl f
|
||||
option overrides any previous
|
||||
.Fl i
|
||||
and
|
||||
.Fl w
|
||||
options.)
|
||||
.It Fl F
|
||||
If the target file already exists and is a directory, then remove it
|
||||
so that the link may occur.
|
||||
@ -105,6 +95,29 @@ The
|
||||
option is a no-op unless
|
||||
.Fl s
|
||||
option is specified.
|
||||
.It Fl L
|
||||
When creating a hard link to a symbolic link,
|
||||
create a hard link to the target of the symbolic link.
|
||||
This is the default.
|
||||
This option cancels the
|
||||
.Fl P
|
||||
option.
|
||||
.It Fl P
|
||||
When creating a hard link to a symbolic link,
|
||||
create a hard link to the symbolic link itself.
|
||||
This option cancels the
|
||||
.Fl L
|
||||
option.
|
||||
.It Fl f
|
||||
If the target file already exists,
|
||||
then unlink it so that the link may occur.
|
||||
(The
|
||||
.Fl f
|
||||
option overrides any previous
|
||||
.Fl i
|
||||
and
|
||||
.Fl w
|
||||
options.)
|
||||
.It Fl h
|
||||
If the
|
||||
.Ar target_file
|
||||
|
24
bin/ln/ln.c
24
bin/ln/ln.c
@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -56,12 +57,11 @@ int fflag; /* Unlink existing files. */
|
||||
int Fflag; /* Remove empty directories also. */
|
||||
int hflag; /* Check new name for symlink first. */
|
||||
int iflag; /* Interactive mode. */
|
||||
int Pflag; /* Create hard links to symlinks. */
|
||||
int sflag; /* Symbolic, not hard, link. */
|
||||
int vflag; /* Verbose output. */
|
||||
int wflag; /* Warn if symlink target does not
|
||||
* exist, and -f is not enabled. */
|
||||
/* System link call. */
|
||||
int (*linkf)(const char *, const char *);
|
||||
char linkch;
|
||||
|
||||
int linkit(const char *, const char *, int);
|
||||
@ -90,15 +90,20 @@ main(int argc, char *argv[])
|
||||
argv += optind;
|
||||
if (argc != 2)
|
||||
usage();
|
||||
linkf = link;
|
||||
exit(linkit(argv[0], argv[1], 0));
|
||||
}
|
||||
|
||||
while ((ch = getopt(argc, argv, "Ffhinsvw")) != -1)
|
||||
while ((ch = getopt(argc, argv, "FLPfhinsvw")) != -1)
|
||||
switch (ch) {
|
||||
case 'F':
|
||||
Fflag = 1;
|
||||
break;
|
||||
case 'L':
|
||||
Pflag = 0;
|
||||
break;
|
||||
case 'P':
|
||||
Pflag = 1;
|
||||
break;
|
||||
case 'f':
|
||||
fflag = 1;
|
||||
iflag = 0;
|
||||
@ -129,7 +134,6 @@ main(int argc, char *argv[])
|
||||
argv += optind;
|
||||
argc -= optind;
|
||||
|
||||
linkf = sflag ? symlink : link;
|
||||
linkch = sflag ? '-' : '=';
|
||||
if (sflag == 0)
|
||||
Fflag = 0;
|
||||
@ -179,7 +183,7 @@ linkit(const char *source, const char *target, int isdir)
|
||||
|
||||
if (!sflag) {
|
||||
/* If source doesn't exist, quit now. */
|
||||
if (stat(source, &sb)) {
|
||||
if ((Pflag ? lstat : stat)(source, &sb)) {
|
||||
warn("%s", source);
|
||||
return (1);
|
||||
}
|
||||
@ -276,7 +280,9 @@ linkit(const char *source, const char *target, int isdir)
|
||||
}
|
||||
|
||||
/* Attempt the link. */
|
||||
if ((*linkf)(source, target)) {
|
||||
if (sflag ? symlink(source, target) :
|
||||
linkat(AT_FDCWD, source, AT_FDCWD, target,
|
||||
Pflag ? 0 : AT_SYMLINK_FOLLOW)) {
|
||||
warn("%s", target);
|
||||
return (1);
|
||||
}
|
||||
@ -289,8 +295,8 @@ void
|
||||
usage(void)
|
||||
{
|
||||
(void)fprintf(stderr, "%s\n%s\n%s\n",
|
||||
"usage: ln [-s [-F]] [-f | -i] [-hnv] source_file [target_file]",
|
||||
" ln [-s [-F]] [-f | -i] [-hnv] source_file ... target_dir",
|
||||
"usage: ln [-s [-F] | -L | -P] [-f | -i] [-hnv] source_file [target_file]",
|
||||
" ln [-s [-F] | -L | -P] [-f | -i] [-hnv] source_file ... target_dir",
|
||||
" link source_file target_file");
|
||||
exit(1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user