From 5e09de40c3bce6d5fab191fd4364f2f6bbc29b60 Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Tue, 14 Feb 2006 11:08:05 +0000 Subject: [PATCH] Add '-F' option which allows to delete existing empty directories, when creating symbolic links. PR: bin/92149 Submitted by: Eugene Grosbein --- bin/ln/ln.1 | 30 +++++++++++++++++++++++++++--- bin/ln/ln.c | 28 +++++++++++++++++++++++----- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/bin/ln/ln.1 b/bin/ln/ln.1 index e494d1465f7f..4c17dc153e20 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 5609449a4d69..76c743ee4a81 100644 --- a/bin/ln/ln.c +++ b/bin/ln/ln.c @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include 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); }