Skip to content
Permalink
Browse files

tree-wide: stop using canonicalize_file_name(), use chase_symlinks() …

…instead

Let's use chase_symlinks() everywhere, and stop using GNU
canonicalize_file_name() everywhere. For most cases this should not change
behaviour, however increase exposure of our function to get better tested. Most
importantly in a few cases (most notably nspawn) it can take the correct root
directory into account when chasing symlinks.
  • Loading branch information...
poettering committed Nov 18, 2016
1 parent c9d5c9c commit e187369587b1c6a5f65a12e7ec0bf7844905d014
@@ -224,25 +224,25 @@ int readlink_and_make_absolute(const char *p, char **r) {
return 0;
}

int readlink_and_canonicalize(const char *p, char **r) {
int readlink_and_canonicalize(const char *p, const char *root, char **ret) {
char *t, *s;
int j;
int r;

assert(p);
assert(r);
assert(ret);

j = readlink_and_make_absolute(p, &t);
if (j < 0)
return j;
r = readlink_and_make_absolute(p, &t);
if (r < 0)
return r;

s = canonicalize_file_name(t);
if (s) {
r = chase_symlinks(t, root, &s);
if (r < 0)
/* If we can't follow up, then let's return the original string, slightly cleaned up. */
*ret = path_kill_slashes(t);
else {
*ret = s;
free(t);
*r = s;
} else
*r = t;

path_kill_slashes(*r);
}

return 0;
}
@@ -39,7 +39,7 @@ int readlinkat_malloc(int fd, const char *p, char **ret);
int readlink_malloc(const char *p, char **r);
int readlink_value(const char *p, char **ret);
int readlink_and_make_absolute(const char *p, char **r);
int readlink_and_canonicalize(const char *p, char **r);
int readlink_and_canonicalize(const char *p, const char *root, char **r);
int readlink_and_make_absolute_root(const char *root, const char *path, char **ret);

int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
@@ -29,6 +29,7 @@
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "hashmap.h"
#include "mount-util.h"
#include "parse-util.h"
@@ -205,9 +206,10 @@ int fd_is_mount_point(int fd, const char *filename, int flags) {
}

/* flags can be AT_SYMLINK_FOLLOW or 0 */
int path_is_mount_point(const char *t, int flags) {
_cleanup_close_ int fd = -1;
int path_is_mount_point(const char *t, const char *root, int flags) {
_cleanup_free_ char *canonical = NULL, *parent = NULL;
_cleanup_close_ int fd = -1;
int r;

assert(t);

@@ -219,9 +221,9 @@ int path_is_mount_point(const char *t, int flags) {
* /bin -> /usr/bin/ and /usr is a mount point, then the parent that we
* look at needs to be /usr, not /. */
if (flags & AT_SYMLINK_FOLLOW) {
canonical = canonicalize_file_name(t);
if (!canonical)
return -errno;
r = chase_symlinks(t, root, &canonical);
if (r < 0)
return r;

t = canonical;
}
@@ -473,7 +475,7 @@ int bind_remount_recursive(const char *prefix, bool ro, char **blacklist) {
return r;

/* Deal with mount points that are obstructed by a later mount */
r = path_is_mount_point(x, 0);
r = path_is_mount_point(x, NULL, 0);
if (r == -ENOENT || r == 0)
continue;
if (r < 0)
@@ -30,7 +30,7 @@
#include "missing.h"

int fd_is_mount_point(int fd, const char *filename, int flags);
int path_is_mount_point(const char *path, int flags);
int path_is_mount_point(const char *path, const char *root, int flags);

int repeat_unmount(const char *path, int flags);

@@ -220,10 +220,11 @@ int path_strv_make_absolute_cwd(char **l) {
return 0;
}

char **path_strv_resolve(char **l, const char *prefix) {
char **path_strv_resolve(char **l, const char *root) {
char **s;
unsigned k = 0;
bool enomem = false;
int r;

if (strv_isempty(l))
return l;
@@ -233,46 +234,44 @@ char **path_strv_resolve(char **l, const char *prefix) {
* changes on failure. */

STRV_FOREACH(s, l) {
char *t, *u;
_cleanup_free_ char *orig = NULL;
char *t, *u;

if (!path_is_absolute(*s)) {
free(*s);
continue;
}

if (prefix) {
if (root) {
orig = *s;
t = strappend(prefix, orig);
t = prefix_root(root, orig);
if (!t) {
enomem = true;
continue;
}
} else
t = *s;

errno = 0;
u = canonicalize_file_name(t);
if (!u) {
if (errno == ENOENT) {
if (prefix) {
u = orig;
orig = NULL;
free(t);
} else
u = t;
} else {
r = chase_symlinks(t, root, &u);
if (r == -ENOENT) {
if (root) {
u = orig;
orig = NULL;
free(t);
if (errno == ENOMEM || errno == 0)
enomem = true;
} else
u = t;
} else if (r < 0) {
free(t);

continue;
}
} else if (prefix) {
if (r == -ENOMEM)
enomem = true;

continue;
} else if (root) {
char *x;

free(t);
x = path_startswith(u, prefix);
x = path_startswith(u, root);
if (x) {
/* restore the slash if it was lost */
if (!startswith(x, "/"))
@@ -304,12 +303,12 @@ char **path_strv_resolve(char **l, const char *prefix) {
return l;
}

char **path_strv_resolve_uniq(char **l, const char *prefix) {
char **path_strv_resolve_uniq(char **l, const char *root) {

if (strv_isempty(l))
return l;

if (!path_strv_resolve(l, prefix))
if (!path_strv_resolve(l, root))
return NULL;

return strv_uniq(l);
@@ -66,8 +66,8 @@ static inline bool path_equal_ptr(const char *a, const char *b) {
})

int path_strv_make_absolute_cwd(char **l);
char** path_strv_resolve(char **l, const char *prefix);
char** path_strv_resolve_uniq(char **l, const char *prefix);
char** path_strv_resolve(char **l, const char *root);
char** path_strv_resolve_uniq(char **l, const char *root);

int find_binary(const char *name, char **filename);

@@ -783,7 +783,7 @@ static int automount_start(Unit *u) {
assert(a);
assert(a->state == AUTOMOUNT_DEAD || a->state == AUTOMOUNT_FAILED);

if (path_is_mount_point(a->where, 0) > 0) {
if (path_is_mount_point(a->where, NULL, 0) > 0) {
log_unit_error(u, "Path %s is already a mount point, refusing start.", a->where);
return -EEXIST;
}
@@ -199,7 +199,7 @@ int machine_id_commit(const char *root) {

etc_machine_id = prefix_roota(root, "/etc/machine-id");

r = path_is_mount_point(etc_machine_id, 0);
r = path_is_mount_point(etc_machine_id, NULL, 0);
if (r < 0)
return log_error_errno(r, "Failed to determine whether %s is a mount point: %m", etc_machine_id);
if (r == 0) {
@@ -159,7 +159,7 @@ static int mount_one(const MountPoint *p, bool relabel) {
if (relabel)
(void) label_fix(p->where, true, true);

r = path_is_mount_point(p->where, AT_SYMLINK_FOLLOW);
r = path_is_mount_point(p->where, NULL, AT_SYMLINK_FOLLOW);
if (r < 0 && r != -ENOENT) {
log_full_errno((p->mode & MNT_FATAL) ? LOG_ERR : LOG_DEBUG, r, "Failed to determine whether %s is a mount point: %m", p->where);
return (p->mode & MNT_FATAL) ? r : 0;
@@ -596,7 +596,7 @@ static int apply_mount(
case READONLY:
case READWRITE:

r = path_is_mount_point(bind_mount_path(m), 0);
r = path_is_mount_point(bind_mount_path(m), NULL, 0);
if (r < 0)
return log_debug_errno(r, "Failed to determine whether %s is already a mount point: %m", bind_mount_path(m));
if (r > 0) /* Nothing to do here, it is already a mount. We just later toggle the MS_RDONLY bit for the mount point if needed. */
@@ -860,7 +860,7 @@ int setup_namespace(

if (root_directory) {
/* Turn directory into bind mount, if it isn't one yet */
r = path_is_mount_point(root_directory, AT_SYMLINK_FOLLOW);
r = path_is_mount_point(root_directory, NULL, AT_SYMLINK_FOLLOW);
if (r < 0)
goto finish;
if (r == 0) {
@@ -87,14 +87,15 @@ static enum {

static int equivalent(const char *a, const char *b) {
_cleanup_free_ char *x = NULL, *y = NULL;
int r;

x = canonicalize_file_name(a);
if (!x)
return -errno;
r = chase_symlinks(a, NULL, &x);
if (r < 0)
return r;

y = canonicalize_file_name(b);
if (!y)
return -errno;
r = chase_symlinks(b, NULL, &y);
if (r < 0)
return r;

return path_equal(x, y);
}
@@ -252,7 +252,7 @@ static bool path_is_busy(const char *where) {
int r;

/* already a mountpoint; generators run during reload */
r = path_is_mount_point(where, AT_SYMLINK_FOLLOW);
r = path_is_mount_point(where, NULL, AT_SYMLINK_FOLLOW);
if (r > 0)
return false;

@@ -938,21 +938,21 @@ static int add_matches(sd_journal *j, char **args) {
have_term = false;

} else if (path_is_absolute(*i)) {
_cleanup_free_ char *p, *t = NULL, *t2 = NULL, *interpreter = NULL;
const char *path;
_cleanup_free_ char *p = NULL, *t = NULL, *t2 = NULL, *interpreter = NULL;
struct stat st;

p = canonicalize_file_name(*i);
path = p ?: *i;
r = chase_symlinks(*i, NULL, &p);
if (r < 0)
return log_error_errno(r, "Couldn't canonicalize path: %m");

if (lstat(path, &st) < 0)
if (lstat(p, &st) < 0)
return log_error_errno(errno, "Couldn't stat file: %m");

if (S_ISREG(st.st_mode) && (0111 & st.st_mode)) {
if (executable_is_script(path, &interpreter) > 0) {
if (executable_is_script(p, &interpreter) > 0) {
_cleanup_free_ char *comm;

comm = strndup(basename(path), 15);
comm = strndup(basename(p), 15);
if (!comm)
return log_oom();

@@ -968,7 +968,7 @@ static int add_matches(sd_journal *j, char **args) {
return log_oom();
}
} else {
t = strappend("_EXE=", path);
t = strappend("_EXE=", p);
if (!t)
return log_oom();
}
@@ -979,7 +979,7 @@ static int add_matches(sd_journal *j, char **args) {
r = sd_journal_add_match(j, t2, 0);

} else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
r = add_matches_for_device(j, path);
r = add_matches_for_device(j, p);
if (r < 0)
return r;
} else {
@@ -164,7 +164,7 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
}

if (verify) {
r = readlink_and_canonicalize(_syspath, &syspath);
r = readlink_and_canonicalize(_syspath, NULL, &syspath);
if (r == -ENOENT)
/* the device does not exist (any more?) */
return -ENODEV;
@@ -338,7 +338,7 @@ static int user_mkdir_runtime_path(User *u) {
if (r < 0)
return log_error_errno(r, "Failed to create /run/user: %m");

if (path_is_mount_point(u->runtime_path, 0) <= 0) {
if (path_is_mount_point(u->runtime_path, NULL, 0) <= 0) {
_cleanup_free_ char *t = NULL;

(void) mkdir_label(u->runtime_path, 0700);

0 comments on commit e187369

Please sign in to comment.
You can’t perform that action at this time.