chiark / gitweb /
when determining unit file list, include invalid unit names in an "invalid" state
[elogind.git] / src / shared / path-util.c
index ccd766760802ab3e6e5230975440ed6e8bee782e..b51a68d6d2ff7c47d1949cdbc3f2497f064dc9f1 100644 (file)
@@ -35,6 +35,7 @@
 #include "log.h"
 #include "strv.h"
 #include "path-util.h"
+#include "missing.h"
 
 bool path_is_absolute(const char *p) {
         return p[0] == '/';
@@ -120,7 +121,7 @@ char *path_make_absolute(const char *p, const char *prefix) {
         if (path_is_absolute(p) || !prefix)
                 return strdup(p);
 
-        return join(prefix, "/", p, NULL);
+        return strjoin(prefix, "/", p, NULL);
 }
 
 char *path_make_absolute_cwd(const char *p) {
@@ -330,10 +331,57 @@ bool path_equal(const char *a, const char *b) {
 }
 
 int path_is_mount_point(const char *t, bool allow_symlink) {
-        struct stat a, b;
         char *parent;
         int r;
+        struct file_handle *h;
+        int mount_id, mount_id_parent;
+        struct stat a, b;
+
+        /* We are not actually interested in the file handles, but
+         * name_to_handle_at() also passes us the mount ID, hence use
+         * it but throw the handle away */
+
+        if (path_equal(t, "/"))
+                return 1;
+
+        h = alloca(MAX_HANDLE_SZ);
+        h->handle_bytes = MAX_HANDLE_SZ;
+
+        r = name_to_handle_at(AT_FDCWD, t, h, &mount_id, allow_symlink ? AT_SYMLINK_FOLLOW : 0);
+        if (r < 0) {
+                if (errno == ENOSYS || errno == ENOTSUP)
+                        /* This kernel or file system does not support
+                         * name_to_handle_at(), hence fallback to the
+                         * traditional stat() logic */
+                        goto fallback;
+
+                if (errno == ENOENT)
+                        return 0;
+
+                return -errno;
+        }
+
+        r = path_get_parent(t, &parent);
+        if (r < 0)
+                return r;
+
+        h->handle_bytes = MAX_HANDLE_SZ;
+        r = name_to_handle_at(AT_FDCWD, parent, h, &mount_id_parent, 0);
+        free(parent);
+
+        if (r < 0) {
+                /* The parent can't do name_to_handle_at() but the
+                 * directory we are interested in can? If so, it must
+                 * be a mount point */
+                if (errno == ENOTSUP)
+                        return 1;
+
+                return -errno;
+        }
+
+        return mount_id != mount_id_parent;
 
+fallback:
         if (allow_symlink)
                 r = stat(t, &a);
         else