From efbe4ab8e24ba859a0a4e3919a7e52165dae39d2 Mon Sep 17 00:00:00 2001 From: Goffredo Baroncelli Date: Thu, 8 Feb 2024 21:19:19 +0100 Subject: [PATCH] btrfs-progs: add path opening helpers without dirstream For historical reasons the helpers [btrfs_]open_dir... return also the 'DIR *dirstream' value when a directory is opened. However this is never used. So avoid calling diropen() and return only the fd. This is a preparatory patch. Signed-off-by: Goffredo Baroncelli Signed-off-by: David Sterba --- common/open-utils.c | 75 +++++++++++++++++++++++++++++++++++++++++++++ common/open-utils.h | 5 +++ 2 files changed, 80 insertions(+) diff --git a/common/open-utils.c b/common/open-utils.c index 111a51d9..f4ff1bfc 100644 --- a/common/open-utils.c +++ b/common/open-utils.c @@ -317,4 +317,79 @@ void close_file_or_dir(int fd, DIR *dirstream) errno = old_errno; } +/* + * Open the given path and check if it's a btrfs filesystem. + */ +int btrfs_open_fd2(const char *path, bool verbose, bool read_write, bool dir_only) +{ + struct statfs stfs; + struct stat st; + int ret; + if (stat(path, &st) != 0) { + error_on(verbose, "cannot access '%s': %m", path); + return -1; + } + + if (dir_only && !S_ISDIR(st.st_mode)) { + error_on(verbose, "not a directory: %s", path); + return -3; + } + + if (statfs(path, &stfs) != 0) { + error_on(verbose, "cannot access '%s': %m", path); + return -1; + } + + if (stfs.f_type != BTRFS_SUPER_MAGIC) { + error_on(verbose, "not a btrfs filesystem: %s", path); + return -2; + } + + if (S_ISDIR(st.st_mode) || !read_write) + ret = open(path, O_RDONLY); + else + ret = open(path, O_RDWR); + + if (ret < 0) { + error_on(verbose, "cannot access '%s': %m", path); + } + + return ret; +} + +int btrfs_open_file_or_dir_fd(const char *path) +{ + return btrfs_open_fd2(path, true, true, false); +} + +int btrfs_open_dir_fd(const char *path) +{ + return btrfs_open_fd2(path, true, true, true); +} + +/* + * Given a path, return a file descriptor to the original path name or, if the + * pathname is a mounted btrfs device, to its mountpoint. + * + * On error, return -1, errno should be set. + */ +int btrfs_open_mnt_fd(const char *path, bool verbose) +{ + char mp[PATH_MAX]; + int ret; + + if (path_is_block_device(path)) { + ret = get_btrfs_mount(path, mp, sizeof(mp)); + if (ret < 0) { + error_on(verbose, "'%s' is not a mounted btrfs device", path); + errno = EINVAL; + return -1; + } + ret = btrfs_open_fd2(mp, verbose, true, true); + } else { + ret = btrfs_open_dir_fd(path); + } + + return ret; +} diff --git a/common/open-utils.h b/common/open-utils.h index 3f8c004e..96d99f5d 100644 --- a/common/open-utils.h +++ b/common/open-utils.h @@ -39,4 +39,9 @@ int btrfs_open_file_or_dir(const char *path, DIR **dirstream, int verbose); void close_file_or_dir(int fd, DIR *dirstream); +int btrfs_open_fd2(const char *path, bool verbose, bool read_write, bool dir_only); +int btrfs_open_file_or_dir_fd(const char *path); +int btrfs_open_dir_fd(const char *path); +int btrfs_open_mnt_fd(const char *path, bool verbose); + #endif