path-util: rework file_in_same_dir() on top of path_extract_directory()

Let's port one more over.

Note that this changes behaviour of file_in_same_dir() in some regards.
Specifically, a trailing slash of the input path will be treated
differently: previously we'd operate below that dir then, instead of the
parent. I think that makes little sense however, and I think the code
using this function doesn't expect that either.

Moroever, addresses some corner cases if the path is specified as "/" or
".", i.e. where e cannot extract a parent. These will now be treated as
error, which I think is much cleaner.
This commit is contained in:
Lennart Poettering
2023-01-24 18:13:27 +01:00
parent 5b532e14e3
commit 162f6477c6
6 changed files with 93 additions and 86 deletions
+7 -13
View File
@@ -174,24 +174,18 @@ int readlink_value(const char *p, char **ret) {
return 0;
}
int readlink_and_make_absolute(const char *p, char **r) {
int readlink_and_make_absolute(const char *p, char **ret) {
_cleanup_free_ char *target = NULL;
char *k;
int j;
int r;
assert(p);
assert(r);
assert(ret);
j = readlink_malloc(p, &target);
if (j < 0)
return j;
r = readlink_malloc(p, &target);
if (r < 0)
return r;
k = file_in_same_dir(p, target);
if (!k)
return -ENOMEM;
*r = k;
return 0;
return file_in_same_dir(p, target, ret);
}
int chmod_and_chown_at(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid) {
+21 -17
View File
@@ -1164,31 +1164,35 @@ bool path_is_normalized(const char *p) {
return true;
}
char *file_in_same_dir(const char *path, const char *filename) {
char *e, *ret;
size_t k;
int file_in_same_dir(const char *path, const char *filename, char **ret) {
_cleanup_free_ char *b = NULL;
int r;
assert(path);
assert(filename);
assert(ret);
/* This removes the last component of path and appends
* filename, unless the latter is absolute anyway or the
* former isn't */
/* This removes the last component of path and appends filename, unless the latter is absolute anyway
* or the former isn't */
if (path_is_absolute(filename))
return strdup(filename);
b = strdup(filename);
else {
_cleanup_free_ char *dn = NULL;
e = strrchr(path, '/');
if (!e)
return strdup(filename);
r = path_extract_directory(path, &dn);
if (r == -EDESTADDRREQ) /* no path prefix */
b = strdup(filename);
else if (r < 0)
return r;
else
b = path_join(dn, filename);
}
if (!b)
return -ENOMEM;
k = strlen(filename);
ret = new(char, (e + 1 - path) + k + 1);
if (!ret)
return NULL;
memcpy(mempcpy(ret, path, e + 1 - path), filename, k + 1);
return ret;
*ret = TAKE_PTR(b);
return 0;
}
bool hidden_or_backup_file(const char *filename) {
+1 -1
View File
@@ -170,7 +170,7 @@ static inline bool path_is_safe(const char *p) {
}
bool path_is_normalized(const char *p) _pure_;
char *file_in_same_dir(const char *path, const char *filename);
int file_in_same_dir(const char *path, const char *filename, char **ret);
bool hidden_or_backup_file(const char *filename) _pure_;