Page MenuHomeFreeBSD

D49842.diff
No OneTemporary

D49842.diff

diff --git a/bin/ln/ln.c b/bin/ln/ln.c
--- a/bin/ln/ln.c
+++ b/bin/ln/ln.c
@@ -212,6 +212,13 @@
return sb1.st_dev == sb2.st_dev && sb1.st_ino == sb2.st_ino;
}
+/*
+ * Create a link to source. If target is a directory (and some additional
+ * conditions apply, see comments within) the link will be created within
+ * target and have the basename of source. Otherwise, the link will be
+ * named target. If isdir is true, target has already been determined to
+ * be a directory; otherwise, we will check, if needed.
+ */
static int
linkit(const char *source, const char *target, bool isdir)
{
@@ -221,7 +228,7 @@
struct stat sb;
const char *p;
int ch, first;
- bool exists;
+ bool append, exists;
if (!sflag) {
/* If source doesn't exist, quit now. */
@@ -238,14 +245,27 @@
}
/*
- * If the target is a directory (and not a symlink if hflag),
- * append the source's name, unless Fflag is set.
+ * Append a slash and the source's basename if:
+ * - the target is "." or ends in "/" or "/.", or
+ * - the target is a directory (and not a symlink if hflag) and
+ * Fflag is not set
*/
- if (!Fflag && (isdir ||
- (lstat(target, &sb) == 0 && S_ISDIR(sb.st_mode)) ||
- (!hflag && stat(target, &sb) == 0 && S_ISDIR(sb.st_mode)))) {
+ if ((p = strrchr(target, '/')) == NULL)
+ p = target;
+ else
+ p++;
+ append = false;
+ if (p[0] == '\0' || (p[0] == '.' && p[1] == '\0')) {
+ append = true;
+ } else if (!Fflag) {
+ if (isdir || (lstat(target, &sb) == 0 && S_ISDIR(sb.st_mode)) ||
+ (!hflag && stat(target, &sb) == 0 && S_ISDIR(sb.st_mode))) {
+ append = true;
+ }
+ }
+ if (append) {
if (strlcpy(bbuf, source, sizeof(bbuf)) >= sizeof(bbuf) ||
- (p = basename(bbuf)) == NULL ||
+ (p = basename(bbuf)) == NULL /* can't happen */ ||
snprintf(path, sizeof(path), "%s/%s", target, p) >=
(ssize_t)sizeof(path)) {
errno = ENAMETOOLONG;
diff --git a/bin/ln/tests/ln_test.sh b/bin/ln/tests/ln_test.sh
--- a/bin/ln/tests/ln_test.sh
+++ b/bin/ln/tests/ln_test.sh
@@ -170,11 +170,15 @@
}
sfF_flag_body()
{
- atf_check mkdir A B C
+ atf_check mkdir A B C D D/A
atf_check ln -sF A C
atf_check_symlink_to A C
atf_check ln -sfF B C
atf_check_symlink_to B C
+ atf_check ln -sfF A D/
+ atf_check_symlink_to A D/A
+ atf_check ln -sfF ../A .
+ atf_check_symlink_to ../A A
}
atf_test_case s_flag

File Metadata

Mime Type
text/plain
Expires
Mon, Apr 6, 11:01 AM (1 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30962200
Default Alt Text
D49842.diff (2 KB)

Event Timeline