summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-11-18 21:35:21 +0100
committerSven Eden <yamakuzure@gmx.net>2017-07-17 17:58:35 +0200
commit2f30582bd3d00ce582d190ddb379e46e0a67f813 (patch)
tree0207414de754246408c3b947ca9ae3f0690571ac /src
parent084937b3d7c4da3e3c48d05779f8cfbdc39a2ce6 (diff)
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.
Diffstat (limited to 'src')
-rw-r--r--src/basic/fs-util.c26
-rw-r--r--src/basic/fs-util.h2
-rw-r--r--src/basic/mount-util.c16
-rw-r--r--src/basic/mount-util.h2
-rw-r--r--src/basic/path-util.c55
-rw-r--r--src/basic/path-util.h4
-rw-r--r--src/core/mount-setup.c2
-rw-r--r--src/login/logind-user.c2
8 files changed, 60 insertions, 49 deletions
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c
index f288848c9..0d96302be 100644
--- a/src/basic/fs-util.c
+++ b/src/basic/fs-util.c
@@ -225,25 +225,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;
}
diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h
index 871f7209f..de4bb861e 100644
--- a/src/basic/fs-util.h
+++ b/src/basic/fs-util.h
@@ -42,7 +42,7 @@ int readlink_malloc(const char *p, char **r);
#if 0 /// UNNEEDED by elogind
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);
#endif // 0
diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c
index 051b14b17..477342e71 100644
--- a/src/basic/mount-util.c
+++ b/src/basic/mount-util.c
@@ -161,7 +161,7 @@ int fd_is_mount_point(int fd, const char *filename, int flags) {
fallback_fdinfo:
r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id);
- if (r == -EOPNOTSUPP)
+ if (IN_SET(r, -EOPNOTSUPP, -EACCES))
goto fallback_fstat;
if (r < 0)
return r;
@@ -204,9 +204,10 @@ fallback_fstat:
}
/* 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);
@@ -218,9 +219,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 +474,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)
@@ -525,6 +526,7 @@ bool fstype_is_network(const char *fstype) {
"glusterfs\0"
"pvfs2\0" /* OrangeFS */
"ocfs2\0"
+ "lustre\0"
;
const char *x;
diff --git a/src/basic/mount-util.h b/src/basic/mount-util.h
index d538ea953..ea887e162 100644
--- a/src/basic/mount-util.h
+++ b/src/basic/mount-util.h
@@ -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);
#if 0 /// UNNEEDED by elogind
int repeat_unmount(const char *path, int flags);
diff --git a/src/basic/path-util.c b/src/basic/path-util.c
index 25a956e97..9dd073338 100644
--- a/src/basic/path-util.c
+++ b/src/basic/path-util.c
@@ -222,10 +222,11 @@ int path_strv_make_absolute_cwd(char **l) {
}
#endif // 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;
@@ -235,17 +236,17 @@ 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;
@@ -253,28 +254,26 @@ char **path_strv_resolve(char **l, const char *prefix) {
} 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, "/"))
@@ -306,12 +305,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);
@@ -356,6 +355,16 @@ char* path_startswith(const char *path, const char *prefix) {
assert(path);
assert(prefix);
+ /* Returns a pointer to the start of the first component after the parts matched by
+ * the prefix, iff
+ * - both paths are absolute or both paths are relative,
+ * and
+ * - each component in prefix in turn matches a component in path at the same position.
+ * An empty string will be returned when the prefix and path are equivalent.
+ *
+ * Returns NULL otherwise.
+ */
+
if ((path[0] == '/') != (prefix[0] == '/'))
return NULL;
diff --git a/src/basic/path-util.h b/src/basic/path-util.h
index 605485665..4d284d23c 100644
--- a/src/basic/path-util.h
+++ b/src/basic/path-util.h
@@ -76,8 +76,8 @@ static inline bool path_equal_ptr(const char *a, const char *b) {
#if 0 /// UNNEEDED by elogind
int path_strv_make_absolute_cwd(char **l);
#endif // 0
-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);
#if 0 /// UNNEEDED by elogind
int find_binary(const char *name, char **filename);
diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c
index c551fa62b..7dfaf27df 100644
--- a/src/core/mount-setup.c
+++ b/src/core/mount-setup.c
@@ -174,7 +174,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;
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index c1fd75a82..b8abc6af0 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -347,7 +347,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);