Add a -w warning flag to ln(1). When the -w option is enabled,
ln(1) checks to see if the source of a symlink, i.e. the file it should point to actually exists. The default is the old ln behavior, that does not check, to avoid surprising people who may be using ln(1) in scripts or other non-interactive places. PR: bin/7265 Submitted by: Joel Ray Holveck, detlev!joelh at mail.camalott.com MFC after: 2 weeks
This commit is contained in:
parent
02ca51529e
commit
3595f21aae
15
bin/ln/ln.1
15
bin/ln/ln.1
@ -32,7 +32,7 @@
|
||||
.\" @(#)ln.1 8.2 (Berkeley) 12/30/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd February 14, 2006
|
||||
.Dd June 6, 2008
|
||||
.Dt LN 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -42,13 +42,13 @@
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl s Op Fl F
|
||||
.Op Fl f | i
|
||||
.Op Fl f | iw
|
||||
.Op Fl hnv
|
||||
.Ar source_file
|
||||
.Op Ar target_file
|
||||
.Nm
|
||||
.Op Fl s Op Fl F
|
||||
.Op Fl f | i
|
||||
.Op Fl f | iw
|
||||
.Op Fl hnv
|
||||
.Ar source_file ...
|
||||
.Ar target_dir
|
||||
@ -79,6 +79,8 @@ then unlink it so that the link may occur.
|
||||
.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
|
||||
@ -134,6 +136,8 @@ Create a symbolic link.
|
||||
Cause
|
||||
.Nm
|
||||
to be verbose, showing files as they are processed.
|
||||
.It Fl w
|
||||
Warn if the source of a symbolic link does not currently exist.
|
||||
.El
|
||||
.Pp
|
||||
By default,
|
||||
@ -194,9 +198,10 @@ operation using the two passed arguments.
|
||||
The
|
||||
.Fl h ,
|
||||
.Fl i ,
|
||||
.Fl n
|
||||
and
|
||||
.Fl n ,
|
||||
.Fl v
|
||||
and
|
||||
.Fl w
|
||||
options are non-standard and their use in scripts is not recommended.
|
||||
They are provided solely for compatibility with other
|
||||
.Nm
|
||||
|
39
bin/ln/ln.c
39
bin/ln/ln.c
@ -58,6 +58,8 @@ int hflag; /* Check new name for symlink first. */
|
||||
int iflag; /* Interactive mode. */
|
||||
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;
|
||||
@ -92,7 +94,7 @@ main(int argc, char *argv[])
|
||||
exit(linkit(argv[0], argv[1], 0));
|
||||
}
|
||||
|
||||
while ((ch = getopt(argc, argv, "Ffhinsv")) != -1)
|
||||
while ((ch = getopt(argc, argv, "Ffhinsvw")) != -1)
|
||||
switch (ch) {
|
||||
case 'F':
|
||||
Fflag = 1;
|
||||
@ -100,6 +102,7 @@ main(int argc, char *argv[])
|
||||
case 'f':
|
||||
fflag = 1;
|
||||
iflag = 0;
|
||||
wflag = 0;
|
||||
break;
|
||||
case 'h':
|
||||
case 'n':
|
||||
@ -115,6 +118,9 @@ main(int argc, char *argv[])
|
||||
case 'v':
|
||||
vflag = 1;
|
||||
break;
|
||||
case 'w':
|
||||
wflag = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
@ -127,8 +133,10 @@ main(int argc, char *argv[])
|
||||
linkch = sflag ? '-' : '=';
|
||||
if (sflag == 0)
|
||||
Fflag = 0;
|
||||
if (Fflag == 1 && iflag == 0)
|
||||
if (Fflag == 1 && iflag == 0) {
|
||||
fflag = 1;
|
||||
wflag = 0; /* Implied when fflag != 0 */
|
||||
}
|
||||
|
||||
switch(argc) {
|
||||
case 0:
|
||||
@ -167,6 +175,7 @@ linkit(const char *source, const char *target, int isdir)
|
||||
const char *p;
|
||||
int ch, exists, first;
|
||||
char path[PATH_MAX];
|
||||
char wbuf[PATH_MAX];
|
||||
|
||||
if (!sflag) {
|
||||
/* If source doesn't exist, quit now. */
|
||||
@ -203,6 +212,32 @@ linkit(const char *source, const char *target, int isdir)
|
||||
}
|
||||
|
||||
exists = !lstat(target, &sb);
|
||||
/*
|
||||
* If the link source doesn't exist, and a symbolic link was
|
||||
* requested, and -w was specified, give a warning.
|
||||
*/
|
||||
if (sflag && wflag) {
|
||||
if (*source == '/') {
|
||||
/* Absolute link source. */
|
||||
if (stat(source, &sb) != 0)
|
||||
warn("warning: %s inaccessible", source);
|
||||
} else {
|
||||
/*
|
||||
* Relative symlink source. Try to construct the
|
||||
* absolute path of the source, by appending `source'
|
||||
* to the parent directory of the target.
|
||||
*/
|
||||
p = strrchr(target, '/');
|
||||
if (p != NULL)
|
||||
p++;
|
||||
else
|
||||
p = target;
|
||||
(void)snprintf(wbuf, sizeof(wbuf), "%.*s%s",
|
||||
(p - target), target, source);
|
||||
if (stat(wbuf, &sb) != 0)
|
||||
warn("warning: %s", source);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If the file exists, then unlink it forcibly if -f was specified
|
||||
* and interactively if -i was specified.
|
||||
|
Loading…
Reference in New Issue
Block a user