Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F151010855
D49842.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
2 KB
Referenced Files
None
Subscribers
None
D49842.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D49842: ln: Tweak append logic.
Attached
Detach File
Event Timeline
Log In to Comment