mirror of
https://github.com/freebsd/freebsd-src
synced 2024-11-05 18:22:52 +00:00
install: Simplify path construction.
There's no need to copy the path twice to split it into base and dir. We simply call `basename()` first, then handle the two trivial cases in which it isn't safe to call `dirname()`. While here, add an early check that the destination is not an empty string. This would always fail eventually, so it may as well fail right away. Also add a test case for this shortcut. MFC after: 1 week Sponsored by: Klara, Inc. Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D44743
This commit is contained in:
parent
e5035d0857
commit
17dc7017d7
2 changed files with 29 additions and 13 deletions
|
@ -25,6 +25,13 @@
|
|||
#
|
||||
#
|
||||
|
||||
atf_test_case copy_to_empty
|
||||
copy_to_empty_body() {
|
||||
printf 'test\n123\r456\r\n789\0z' >testf
|
||||
atf_check -s not-exit:0 -e match:"empty string" \
|
||||
install testf ""
|
||||
}
|
||||
|
||||
copy_to_nonexistent_with_opts() {
|
||||
printf 'test\n123\r456\r\n789\0z' >testf
|
||||
atf_check install "$@" testf copyf
|
||||
|
@ -497,6 +504,7 @@ set_optional_exec_body()
|
|||
}
|
||||
|
||||
atf_init_test_cases() {
|
||||
atf_add_test_case copy_to_empty
|
||||
atf_add_test_case copy_to_nonexistent
|
||||
atf_add_test_case copy_to_nonexistent_safe
|
||||
atf_add_test_case copy_to_nonexistent_comparing
|
||||
|
|
|
@ -657,8 +657,10 @@ static void
|
|||
makelink(const char *from_name, const char *to_name,
|
||||
const struct stat *target_sb)
|
||||
{
|
||||
char src[MAXPATHLEN], dst[MAXPATHLEN], lnk[MAXPATHLEN];
|
||||
struct stat to_sb;
|
||||
char src[MAXPATHLEN], dst[MAXPATHLEN], lnk[MAXPATHLEN];
|
||||
char *to_name_copy, *d, *ld, *ls, *s;
|
||||
const char *base, *dir;
|
||||
struct stat to_sb;
|
||||
|
||||
/* Try hard links first. */
|
||||
if (dolink & (LN_HARD|LN_MIXED)) {
|
||||
|
@ -719,8 +721,6 @@ makelink(const char *from_name, const char *to_name,
|
|||
}
|
||||
|
||||
if (dolink & LN_RELATIVE) {
|
||||
char *to_name_copy, *cp, *d, *ld, *ls, *s;
|
||||
|
||||
if (*from_name != '/') {
|
||||
/* this is already a relative link */
|
||||
do_symlink(from_name, to_name, target_sb);
|
||||
|
@ -740,17 +740,23 @@ makelink(const char *from_name, const char *to_name,
|
|||
to_name_copy = strdup(to_name);
|
||||
if (to_name_copy == NULL)
|
||||
err(EX_OSERR, "%s: strdup", to_name);
|
||||
cp = dirname(to_name_copy);
|
||||
if (realpath(cp, dst) == NULL)
|
||||
err(EX_OSERR, "%s: realpath", cp);
|
||||
/* .. and add the last component. */
|
||||
if (strcmp(dst, "/") != 0) {
|
||||
if (strlcat(dst, "/", sizeof(dst)) > sizeof(dst))
|
||||
base = basename(to_name_copy);
|
||||
if (base == to_name_copy) {
|
||||
/* destination is a file in cwd */
|
||||
(void)strlcpy(dst, "./", sizeof(dst));
|
||||
} else if (base == to_name_copy + 1) {
|
||||
/* destination is a file in the root */
|
||||
(void)strlcpy(dst, "/", sizeof(dst));
|
||||
} else {
|
||||
/* all other cases: safe to call dirname() */
|
||||
dir = dirname(to_name_copy);
|
||||
if (realpath(dir, dst) == NULL)
|
||||
err(EX_OSERR, "%s: realpath", dir);
|
||||
if (strcmp(dst, "/") != 0 &&
|
||||
strlcat(dst, "/", sizeof(dst)) > sizeof(dst))
|
||||
errx(1, "resolved pathname too long");
|
||||
}
|
||||
strcpy(to_name_copy, to_name);
|
||||
cp = basename(to_name_copy);
|
||||
if (strlcat(dst, cp, sizeof(dst)) > sizeof(dst))
|
||||
if (strlcat(dst, base, sizeof(dst)) > sizeof(dst))
|
||||
errx(1, "resolved pathname too long");
|
||||
free(to_name_copy);
|
||||
|
||||
|
@ -834,6 +840,8 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags)
|
|||
} else {
|
||||
devnull = 1;
|
||||
}
|
||||
if (*to_name == '\0')
|
||||
errx(EX_USAGE, "destination cannot be an empty string");
|
||||
|
||||
target = (lstat(to_name, &to_sb) == 0);
|
||||
|
||||
|
|
Loading…
Reference in a new issue