upstream: refactor tilde_expand_filename() and make it handle ~user
paths with no trailing slash; feedback/ok markus and jsg OpenBSD-Commit-ID: a2ab365598a902f0f14ba6a4f8fb2d07a9b5d51d
This commit is contained in:
parent
dc38236ab6
commit
9614113377
78
misc.c
78
misc.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: misc.c,v 1.171 2021/11/13 21:14:13 deraadt Exp $ */
|
||||
/* $OpenBSD: misc.c,v 1.172 2022/01/08 07:32:45 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2005-2020 Damien Miller. All rights reserved.
|
||||
|
@ -1119,53 +1119,69 @@ freeargs(arglist *args)
|
|||
int
|
||||
tilde_expand(const char *filename, uid_t uid, char **retp)
|
||||
{
|
||||
const char *path, *sep;
|
||||
char user[128], *ret;
|
||||
char *ocopy = NULL, *copy, *s = NULL;
|
||||
const char *path = NULL, *user = NULL;
|
||||
struct passwd *pw;
|
||||
u_int len, slash;
|
||||
size_t len;
|
||||
int ret = -1, r, slash;
|
||||
|
||||
*retp = NULL;
|
||||
if (*filename != '~') {
|
||||
*retp = xstrdup(filename);
|
||||
return 0;
|
||||
}
|
||||
filename++;
|
||||
ocopy = copy = xstrdup(filename + 1);
|
||||
|
||||
path = strchr(filename, '/');
|
||||
if (path != NULL && path > filename) { /* ~user/path */
|
||||
slash = path - filename;
|
||||
if (slash > sizeof(user) - 1) {
|
||||
error_f("~username too long");
|
||||
return -1;
|
||||
if (*copy == '\0') /* ~ */
|
||||
path = NULL;
|
||||
else if (*copy == '/') {
|
||||
copy += strspn(copy, "/");
|
||||
if (*copy == '\0')
|
||||
path = NULL; /* ~/ */
|
||||
else
|
||||
path = copy; /* ~/path */
|
||||
} else {
|
||||
user = copy;
|
||||
if ((path = strchr(copy, '/')) != NULL) {
|
||||
copy[path - copy] = '\0';
|
||||
path++;
|
||||
path += strspn(path, "/");
|
||||
if (*path == '\0') /* ~user/ */
|
||||
path = NULL;
|
||||
/* else ~user/path */
|
||||
}
|
||||
memcpy(user, filename, slash);
|
||||
user[slash] = '\0';
|
||||
/* else ~user */
|
||||
}
|
||||
if (user != NULL) {
|
||||
if ((pw = getpwnam(user)) == NULL) {
|
||||
error_f("No such user %s", user);
|
||||
return -1;
|
||||
goto out;
|
||||
}
|
||||
} else if ((pw = getpwuid(uid)) == NULL) { /* ~/path */
|
||||
} else if ((pw = getpwuid(uid)) == NULL) {
|
||||
error_f("No such uid %ld", (long)uid);
|
||||
return -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Make sure directory has a trailing '/' */
|
||||
len = strlen(pw->pw_dir);
|
||||
if (len == 0 || pw->pw_dir[len - 1] != '/')
|
||||
sep = "/";
|
||||
else
|
||||
sep = "";
|
||||
slash = (len = strlen(pw->pw_dir)) == 0 || pw->pw_dir[len - 1] != '/';
|
||||
|
||||
/* Skip leading '/' from specified path */
|
||||
if (path != NULL)
|
||||
filename = path + 1;
|
||||
|
||||
if (xasprintf(&ret, "%s%s%s", pw->pw_dir, sep, filename) >= PATH_MAX) {
|
||||
error_f("Path too long");
|
||||
return -1;
|
||||
if ((r = xasprintf(&s, "%s%s%s", pw->pw_dir,
|
||||
slash ? "/" : "", path != NULL ? path : "")) <= 0) {
|
||||
error_f("xasprintf failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
*retp = ret;
|
||||
return 0;
|
||||
if (r >= PATH_MAX) {
|
||||
error_f("Path too long");
|
||||
goto out;
|
||||
}
|
||||
/* success */
|
||||
ret = 0;
|
||||
*retp = s;
|
||||
s = NULL;
|
||||
out:
|
||||
free(s);
|
||||
free(ocopy);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *
|
||||
|
|
Loading…
Reference in New Issue