diff options
author | Eric Sandeen <sandeen@redhat.com> | 2013-03-11 18:12:59 -0500 |
---|---|---|
committer | David Sterba <dsterba@suse.cz> | 2013-03-12 16:44:40 +0100 |
commit | 10e00b07640438c2412ec360433e38609c727738 (patch) | |
tree | fabc1a5ee78397e975bd3af048d80fd0842570e8 | |
parent | 5bc34c66028fe8c9eea21a682b760713c2e0dc47 (diff) |
btrfs-progs: three new device/path helpers
Add 3 new helpers:
* is_block_device(), to test if a path is a block device.
* get_btrfs_mount(), to get the mountpoint of a device,
if mounted.
* open_path_or_dev_mnt(path), to open either the pathname
or, if it's a mounted btrfs dev, the mountpoint. Useful
for some commands which can take either type of arg.
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
-rw-r--r-- | utils.c | 87 | ||||
-rw-r--r-- | utils.h | 3 |
2 files changed, 90 insertions, 0 deletions
@@ -640,6 +640,93 @@ error: return ret; } +/* + * checks if a path is a block device node + * Returns negative errno on failure, otherwise + * returns 1 for blockdev, 0 for not-blockdev + */ +int is_block_device(const char *path) { + struct stat statbuf; + + if (stat(path, &statbuf) < 0) + return -errno; + + return S_ISBLK(statbuf.st_mode); +} + +/* + * Find the mount point for a mounted device. + * On success, returns 0 with mountpoint in *mp. + * On failure, returns -errno (not mounted yields -EINVAL) + * Is noisy on failures, expects to be given a mounted device. + */ +int get_btrfs_mount(const char *dev, char *mp, size_t mp_size) { + int ret; + int fd = -1; + + ret = is_block_device(dev); + if (ret <= 0) { + if (!ret) { + fprintf(stderr, "%s is not a block device\n", dev); + ret = -EINVAL; + } else { + fprintf(stderr, "Could not check %s: %s\n", + dev, strerror(-ret)); + } + goto out; + } + + fd = open(dev, O_RDONLY); + if (fd < 0) { + ret = -errno; + fprintf(stderr, "Could not open %s: %s\n", dev, strerror(errno)); + goto out; + } + + ret = check_mounted_where(fd, dev, mp, mp_size, NULL); + if (!ret) { + fprintf(stderr, "%s is not a mounted btrfs device\n", dev); + ret = -EINVAL; + } else { /* mounted, all good */ + ret = 0; + } +out: + if (fd != -1) + close(fd); + if (ret) + fprintf(stderr, "Could not get mountpoint for %s\n", dev); + return ret; +} + +/* + * Given a pathname, return a filehandle to: + * the original pathname or, + * if the pathname is a mounted btrfs device, to its mountpoint. + * + * On error, return -1, errno should be set. + */ +int open_path_or_dev_mnt(const char *path) +{ + char mp[BTRFS_PATH_NAME_MAX + 1]; + int fdmnt; + + if (is_block_device(path)) { + int ret; + + ret = get_btrfs_mount(path, mp, sizeof(mp)); + if (ret < 0) { + /* not a mounted btrfs dev */ + errno = EINVAL; + return -1; + } + fdmnt = open(mp, O_RDWR); + } else { + fdmnt = open_file_or_dir(path); + } + + return fdmnt; +} + /* checks if a device is a loop device */ int is_loop_device (const char* device) { struct stat statbuf; @@ -56,6 +56,9 @@ int get_label(const char *btrfs_dev); int set_label(const char *btrfs_dev, const char *label); char *__strncpy__null(char *dest, const char *src, size_t n); +int is_block_device(const char *file); +int get_btrfs_mount(const char *path, char *mp, size_t mp_size); +int open_path_or_dev_mnt(const char *path); int is_swap_device(const char *file); /* Helper to always get proper size of the destination string */ #define strncpy_null(dest, src) __strncpy__null(dest, src, sizeof(dest)) |