aboutsummaryrefslogtreecommitdiffstats
path: root/extlinux
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2012-06-20 16:01:43 -0700
committerH. Peter Anvin <hpa@zytor.com>2012-06-20 16:01:43 -0700
commit6be9e52dcb80c910373cc8eaade2de13b0afed00 (patch)
treeee619b15ca3bf75980be1e4b1b100fbe4d8db1e2 /extlinux
parent0b49326e70074030a9d416d36264fe859cc16328 (diff)
downloadsyslinux-6be9e52dcb80c910373cc8eaade2de13b0afed00.tar.gz
syslinux-6be9e52dcb80c910373cc8eaade2de13b0afed00.tar.xz
syslinux-6be9e52dcb80c910373cc8eaade2de13b0afed00.zip
extlinux: centralize and reuse btrfs validation
We can re-use btrfs device validation now. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'extlinux')
-rw-r--r--extlinux/main.c111
1 files changed, 77 insertions, 34 deletions
diff --git a/extlinux/main.c b/extlinux/main.c
index 15ea0379..63751669 100644
--- a/extlinux/main.c
+++ b/extlinux/main.c
@@ -766,17 +766,33 @@ static void device_cleanup(void)
/* Verify that a device fd and a pathname agree.
Return 0 on valid, -1 on error. */
+static int validate_device_btrfs(int pathfd, int devfd);
static int validate_device(const char *path, int devfd)
{
struct stat pst, dst;
struct statfs sfs;
+ int pfd;
+ int rv = -1;
+
+ pfd = open(path, O_RDONLY|O_DIRECTORY);
+ if (pfd < 0)
+ goto err;
+
+ if (fstat(pfd, &pst) || fstat(devfd, &dst) || statfs(path, &sfs))
+ goto err;
- if (stat(path, &pst) || fstat(devfd, &dst) || statfs(path, &sfs))
- return -1;
/* btrfs st_dev is not matched with mnt st_rdev, it is a known issue */
- if (fs_type == BTRFS && sfs.f_type == BTRFS_SUPER_MAGIC)
- return 0;
- return (pst.st_dev == dst.st_rdev) ? 0 : -1;
+ if (fs_type == BTRFS) {
+ if (sfs.f_type == BTRFS_SUPER_MAGIC)
+ rv = validate_device_btrfs(pfd, devfd);
+ } else {
+ rv = (pst.st_dev == dst.st_rdev) ? 0 : -1;
+ }
+
+err:
+ if (pfd >= 0)
+ close(pfd);
+ return rv;
}
#ifndef __KLIBC__
@@ -907,66 +923,93 @@ static const char *find_device_mountinfo(const char *path, dev_t dev)
return NULL;
}
-static const char *find_device_btrfs(const char *path)
+static int validate_device_btrfs(int pfd, int dfd)
{
- int fd;
struct btrfs_ioctl_fs_info_args fsinfo;
static struct btrfs_ioctl_dev_info_args devinfo;
struct btrfs_super_block sb2;
- const char *rv = NULL;
-
- fd = open(path, O_RDONLY);
- if (fd < 0)
- goto err;
- if (ioctl(fd, BTRFS_IOC_FS_INFO, &fsinfo))
- goto err;
+ if (ioctl(pfd, BTRFS_IOC_FS_INFO, &fsinfo))
+ return -1;
/* We do not support multi-device btrfs yet */
if (fsinfo.num_devices != 1)
- goto err;
+ return -1;
/* The one device will have the max devid */
memset(&devinfo, 0, sizeof devinfo);
devinfo.devid = fsinfo.max_id;
- if (ioctl(fd, BTRFS_IOC_DEV_INFO, &devinfo))
- goto err;
- close(fd);
- fd = -1;
+ if (ioctl(pfd, BTRFS_IOC_DEV_INFO, &devinfo))
+ return -1;
if (devinfo.path[0] != '/')
- goto err;
-
- fd = open((const char *)devinfo.path, O_RDONLY);
- if (fd < 0)
- goto err;
+ return -1;
- if (xpread(fd, &sb2, sizeof sb2, BTRFS_SUPER_INFO_OFFSET) != sizeof sb2)
- goto err;
+ if (xpread(dfd, &sb2, sizeof sb2, BTRFS_SUPER_INFO_OFFSET) != sizeof sb2)
+ return -1;
if (memcmp(sb2.magic, BTRFS_MAGIC, BTRFS_MAGIC_L))
- goto err;
+ return -1;
if (memcmp(sb2.fsid, fsinfo.fsid, sizeof fsinfo.fsid))
- goto err;
+ return -1;
if (sb2.num_devices != 1)
- goto err;
+ return -1;
if (sb2.dev_item.devid != devinfo.devid)
- goto err;
+ return -1;
if (memcmp(sb2.dev_item.uuid, devinfo.uuid, sizeof devinfo.uuid))
- goto err;
+ return -1;
if (memcmp(sb2.dev_item.fsid, fsinfo.fsid, sizeof fsinfo.fsid))
+ return -1;
+
+ return 0; /* It's good! */
+}
+
+static const char *find_device_btrfs(const char *path)
+{
+ int pfd, dfd;
+ struct btrfs_ioctl_fs_info_args fsinfo;
+ static struct btrfs_ioctl_dev_info_args devinfo;
+ const char *rv = NULL;
+
+ pfd = dfd = -1;
+
+ pfd = open(path, O_RDONLY);
+ if (pfd < 0)
goto err;
- rv = (const char *)devinfo.path; /* It's good! */
+ if (ioctl(pfd, BTRFS_IOC_FS_INFO, &fsinfo))
+ goto err;
+
+ /* We do not support multi-device btrfs yet */
+ if (fsinfo.num_devices != 1)
+ goto err;
+
+ /* The one device will have the max devid */
+ memset(&devinfo, 0, sizeof devinfo);
+ devinfo.devid = fsinfo.max_id;
+ if (ioctl(pfd, BTRFS_IOC_DEV_INFO, &devinfo))
+ goto err;
+
+ if (devinfo.path[0] != '/')
+ goto err;
+
+ dfd = open((const char *)devinfo.path, O_RDONLY);
+ if (dfd < 0)
+ goto err;
+
+ if (!validate_device_btrfs(pfd, dfd))
+ rv = (const char *)devinfo.path; /* It's good! */
err:
- if (fd >= 0)
- close(fd);
+ if (pfd >= 0)
+ close(pfd);
+ if (dfd >= 0)
+ close(dfd);
return rv;
}