Add '-F' option which allows to delete existing empty directories, when

creating symbolic links.

PR:		bin/92149
Submitted by:	Eugene Grosbein <eugen grosbein.pp.ru>
This commit is contained in:
Gleb Smirnoff 2006-02-14 11:08:05 +00:00
parent 991d33c312
commit 5e09de40c3
2 changed files with 50 additions and 8 deletions

View File

@ -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 ,

View File

@ -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);
}