fs-util: introduce open_parent() helper
authorLennart Poettering <lennart@poettering.net>
Fri, 20 Jul 2018 09:57:24 +0000 (11:57 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 23 Jul 2018 11:38:18 +0000 (13:38 +0200)
We often open the parent directory of a path. Let's add a common helper
for that, that shortens our code a bit and adds some extra safety
checks, for example it will fail if used on the root directory (which
doesn't really have a parent).

The helper is actually generalized from a function in btrfs-util.[ch]
which already existed for this purpose.

src/basic/btrfs-util.c
src/basic/fs-util.c
src/basic/fs-util.h

index 6d2490f..efac0b9 100644 (file)
@@ -28,6 +28,7 @@
 #include "device-nodes.h"
 #include "fd-util.h"
 #include "fileio.h"
+#include "fs-util.h"
 #include "io-util.h"
 #include "macro.h"
 #include "missing.h"
@@ -59,23 +60,6 @@ static int validate_subvolume_name(const char *name) {
         return 0;
 }
 
-static int open_parent(const char *path, int flags) {
-        _cleanup_free_ char *parent = NULL;
-        int fd;
-
-        assert(path);
-
-        parent = dirname_malloc(path);
-        if (!parent)
-                return -ENOMEM;
-
-        fd = open(parent, flags);
-        if (fd < 0)
-                return -errno;
-
-        return fd;
-}
-
 static int extract_subvolume_name(const char *path, const char **subvolume) {
         const char *fn;
         int r;
@@ -144,7 +128,7 @@ int btrfs_subvol_make(const char *path) {
         if (r < 0)
                 return r;
 
-        fd = open_parent(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
+        fd = open_parent(path, O_CLOEXEC, 0);
         if (fd < 0)
                 return fd;
 
@@ -1283,7 +1267,7 @@ int btrfs_subvol_remove(const char *path, BtrfsRemoveFlags flags) {
         if (r < 0)
                 return r;
 
-        fd = open_parent(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
+        fd = open_parent(path, O_CLOEXEC, 0);
         if (fd < 0)
                 return fd;
 
@@ -1723,7 +1707,7 @@ int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, BtrfsSnapshotFlag
         if (r < 0)
                 return r;
 
-        new_fd = open_parent(new_path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
+        new_fd = open_parent(new_path, O_CLOEXEC, 0);
         if (new_fd < 0)
                 return new_fd;
 
index 3a8b32d..567f4af 100644 (file)
@@ -1195,3 +1195,31 @@ int fsync_directory_of_file(int fd) {
 
         return 0;
 }
+
+int open_parent(const char *path, int flags, mode_t mode) {
+        _cleanup_free_ char *parent = NULL;
+        int fd;
+
+        if (isempty(path))
+                return -EINVAL;
+        if (path_equal(path, "/")) /* requesting the parent of the root dir is fishy, let's prohibit that */
+                return -EINVAL;
+
+        parent = dirname_malloc(path);
+        if (!parent)
+                return -ENOMEM;
+
+        /* Let's insist on O_DIRECTORY since the parent of a file or directory is a directory. Except if we open an
+         * O_TMPFILE file, because in that case we are actually create a regular file below the parent directory. */
+
+        if ((flags & O_PATH) == O_PATH)
+                flags |= O_DIRECTORY;
+        else if ((flags & O_TMPFILE) != O_TMPFILE)
+                flags |= O_DIRECTORY|O_RDONLY;
+
+        fd = open(parent, flags, mode);
+        if (fd < 0)
+                return -errno;
+
+        return fd;
+}
index 2856677..754163d 100644 (file)
@@ -103,3 +103,5 @@ void unlink_tempfilep(char (*p)[]);
 int unlinkat_deallocate(int fd, const char *name, int flags);
 
 int fsync_directory_of_file(int fd);
+
+int open_parent(const char *path, int flags, mode_t mode);