ln: Allow a trailing slash when creating a link to a directory.
In the 'ln source... directory' synopsis, the basename of each source determines the name of the created link. Determine this using basename(3) instead of strrchr(..., '/') which is incorrect if the pathname ends in a slash. The patch is somewhat changed to allow for basename(3) implementations that change the passed pathname, and to fix the -w option's checking also. The code to compare directory entries only applies to hard links, which cannot be created to directories using ln. Example: ln -s /etc/defaults/ /tmp This should create a symlink named defaults. PR: 121568 Submitted by: Ighighi MFC after: 1 week
This commit is contained in:
parent
3acd904d85
commit
dc00aa5dd6
27
bin/ln/ln.c
27
bin/ln/ln.c
@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -226,6 +227,7 @@ linkit(const char *source, const char *target, int isdir)
|
||||
int ch, exists, first;
|
||||
char path[PATH_MAX];
|
||||
char wbuf[PATH_MAX];
|
||||
char bbuf[PATH_MAX];
|
||||
|
||||
if (!sflag) {
|
||||
/* If source doesn't exist, quit now. */
|
||||
@ -248,11 +250,9 @@ linkit(const char *source, const char *target, int isdir)
|
||||
if (isdir ||
|
||||
(lstat(target, &sb) == 0 && S_ISDIR(sb.st_mode)) ||
|
||||
(!hflag && stat(target, &sb) == 0 && S_ISDIR(sb.st_mode))) {
|
||||
if ((p = strrchr(source, '/')) == NULL)
|
||||
p = source;
|
||||
else
|
||||
++p;
|
||||
if (snprintf(path, sizeof(path), "%s/%s", target, p) >=
|
||||
if (strlcpy(bbuf, source, sizeof(bbuf)) >= sizeof(bbuf) ||
|
||||
(p = basename(bbuf)) == NULL ||
|
||||
snprintf(path, sizeof(path), "%s/%s", target, p) >=
|
||||
(ssize_t)sizeof(path)) {
|
||||
errno = ENAMETOOLONG;
|
||||
warn("%s", source);
|
||||
@ -276,15 +276,14 @@ linkit(const char *source, const char *target, int isdir)
|
||||
* absolute path of the source, by appending `source'
|
||||
* to the parent directory of the target.
|
||||
*/
|
||||
p = strrchr(target, '/');
|
||||
if (p != NULL)
|
||||
p++;
|
||||
else
|
||||
p = target;
|
||||
(void)snprintf(wbuf, sizeof(wbuf), "%.*s%s",
|
||||
(int)(p - target), target, source);
|
||||
if (stat(wbuf, &sb) != 0)
|
||||
warn("warning: %s", source);
|
||||
strlcpy(bbuf, target, sizeof(bbuf));
|
||||
p = dirname(bbuf);
|
||||
if (p != NULL) {
|
||||
(void)snprintf(wbuf, sizeof(wbuf), "%s/%s",
|
||||
p, source);
|
||||
if (stat(wbuf, &sb) != 0)
|
||||
warn("warning: %s", source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user