fs-util: introduce open_parent() helper

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.
This commit is contained in:
Lennart Poettering 2018-07-20 11:57:24 +02:00
parent 09942654d3
commit ef8becfac5
3 changed files with 34 additions and 20 deletions

View 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;

View 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;
}

View 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);