summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bin/ln/ln.130
-rw-r--r--bin/ln/ln.c28
2 files changed, 50 insertions, 8 deletions
diff --git a/bin/ln/ln.1 b/bin/ln/ln.1
index e494d14..4c17dc1 100644
--- a/bin/ln/ln.1
+++ b/bin/ln/ln.1
@@ -32,7 +32,7 @@
.\" @(#)ln.1 8.2 (Berkeley) 12/30/93
.\" $FreeBSD$
.\"
-.Dd December 30, 1993
+.Dd February 14, 2006
.Dt LN 1
.Os
.Sh NAME
@@ -41,11 +41,11 @@
.Nd make links
.Sh SYNOPSIS
.Nm
-.Op Fl fhinsv
+.Op Fl Ffhinsv
.Ar source_file
.Op Ar target_file
.Nm
-.Op Fl fhinsv
+.Op Fl Ffhinsv
.Ar source_file ...
.Ar target_dir
.Nm link
@@ -76,6 +76,24 @@ then unlink it so that the link may occur.
option overrides any previous
.Fl i
options.)
+.It Fl F
+If the target file already exists and is a directory, then remove it
+so that the link may occur.
+The
+.Fl F
+option should be used with either
+.Fl f
+or
+.Fl i
+options.
+If none is specified,
+.Fl f
+is implied.
+The
+.Fl F
+option is a no-op unless
+.Fl s
+option is specified.
.It Fl h
If the
.Ar target_file
@@ -179,6 +197,12 @@ options are non-standard and their use in scripts is not recommended.
They are provided solely for compatibility with other
.Nm
implementations.
+.Pp
+The
+.Fl F
+option is
+.Fx
+extention and should not be used in portable scripts.
.Sh SEE ALSO
.Xr link 2 ,
.Xr lstat 2 ,
diff --git a/bin/ln/ln.c b/bin/ln/ln.c
index 5609449..76c743e 100644
--- a/bin/ln/ln.c
+++ b/bin/ln/ln.c
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
int fflag; /* Unlink existing files. */
+int Fflag; /* Remove empty directories also. */
int hflag; /* Check new name for symlink first. */
int iflag; /* Interactive mode. */
int sflag; /* Symbolic, not hard, link. */
@@ -91,8 +92,11 @@ main(int argc, char *argv[])
exit(linkit(argv[0], argv[1], 0));
}
- while ((ch = getopt(argc, argv, "fhinsv")) != -1)
+ while ((ch = getopt(argc, argv, "Ffhinsv")) != -1)
switch (ch) {
+ case 'F':
+ Fflag = 1;
+ break;
case 'f':
fflag = 1;
iflag = 0;
@@ -121,6 +125,10 @@ main(int argc, char *argv[])
linkf = sflag ? symlink : link;
linkch = sflag ? '-' : '=';
+ if (sflag == 0)
+ Fflag = 0;
+ if (Fflag == 1 && iflag == 0)
+ fflag = 1;
switch(argc) {
case 0:
@@ -200,7 +208,12 @@ linkit(const char *target, const char *source, int isdir)
* and interactively if -i was specified.
*/
if (fflag && exists) {
- if (unlink(source)) {
+ if (Fflag && S_ISDIR(sb.st_mode)) {
+ if (rmdir(source)) {
+ warn("%s", source);
+ return (1);
+ }
+ } else if (unlink(source)) {
warn("%s", source);
return (1);
}
@@ -216,7 +229,12 @@ linkit(const char *target, const char *source, int isdir)
return (1);
}
- if (unlink(source)) {
+ if (Fflag && S_ISDIR(sb.st_mode)) {
+ if (rmdir(source)) {
+ warn("%s", source);
+ return (1);
+ }
+ } else if (unlink(source)) {
warn("%s", source);
return (1);
}
@@ -236,8 +254,8 @@ void
usage(void)
{
(void)fprintf(stderr, "%s\n%s\n%s\n",
- "usage: ln [-fhinsv] source_file [target_file]",
- " ln [-fhinsv] source_file ... target_dir",
+ "usage: ln [-Ffhinsv] source_file [target_file]",
+ " ln [-Ffhinsv] source_file ... target_dir",
" link source_file target_file");
exit(1);
}
OpenPOWER on IntegriCloud