From 7526c305b459f1387dad72d1543308246fc12877 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Fri, 13 Jan 2017 11:23:23 +0100 Subject: libfdisk: don't use blkdev ioctls for regular files $ fdisk open("sdc.img", O_RDONLY|O_CLOEXEC) = 3 ioctl(3, BLKSSZGET, 0x7ffcf51357c4) = -1 ENOTTY (Inappropriate ioctl for device) ioctl(3, BLKGETSIZE64, 0x7ffcf51357b0) = -1 ENOTTY (Inappropriate ioctl for device) ioctl(3, BLKGETSIZE, 0x7ffcf51356c8) = -1 ENOTTY (Inappropriate ioctl for device) ioctl(3, FDGETPRM, 0x7ffcf51356d0) = -1 ENOTTY (Inappropriate ioctl for device) ioctl(3, HDIO_GETGEO, 0x7ffcf5135790) = -1 ENOTTY (Inappropriate ioctl for device) Signed-off-by: Karel Zak --- libfdisk/docs/libfdisk-sections.txt | 1 + libfdisk/src/alignment.c | 27 +++++++++++++++++++-------- libfdisk/src/context.c | 18 +++++++++++++++++- libfdisk/src/fdiskP.h | 4 ++++ libfdisk/src/libfdisk.h.in | 1 + libfdisk/src/libfdisk.sym | 1 + 6 files changed, 43 insertions(+), 9 deletions(-) (limited to 'libfdisk') diff --git a/libfdisk/docs/libfdisk-sections.txt b/libfdisk/docs/libfdisk-sections.txt index 72a7dca34..11b25b108 100644 --- a/libfdisk/docs/libfdisk-sections.txt +++ b/libfdisk/docs/libfdisk-sections.txt @@ -315,6 +315,7 @@ fdisk_is_details fdisk_is_labeltype fdisk_is_listonly fdisk_is_readonly +fdisk_is_regfile fdisk_new_context fdisk_new_nested_context FDISK_PLURAL diff --git a/libfdisk/src/alignment.c b/libfdisk/src/alignment.c index 58acefb89..b874a48f8 100644 --- a/libfdisk/src/alignment.c +++ b/libfdisk/src/alignment.c @@ -183,12 +183,14 @@ int fdisk_lba_is_phy_aligned(struct fdisk_context *cxt, fdisk_sector_t lba) return lba_is_phy_aligned(cxt, lba); } -static unsigned long get_sector_size(int fd) +static unsigned long get_sector_size(struct fdisk_context *cxt) { int sect_sz; - if (!blkdev_get_sector_size(fd, §_sz)) + if (!fdisk_is_regfile(cxt) && + !blkdev_get_sector_size(cxt->dev_fd, §_sz)) return (unsigned long) sect_sz; + return DEFAULT_SECTOR_SIZE; } @@ -423,22 +425,31 @@ int fdisk_reset_device_properties(struct fdisk_context *cxt) int fdisk_discover_geometry(struct fdisk_context *cxt) { fdisk_sector_t nsects; + unsigned int h = 0, s = 0; assert(cxt); assert(cxt->geom.heads == 0); DBG(CXT, ul_debugobj(cxt, "%s: discovering geometry...", cxt->dev_path)); - /* get number of 512-byte sectors, and convert it the real sectors */ - if (!blkdev_get_sectors(cxt->dev_fd, (unsigned long long *) &nsects)) - cxt->total_sectors = (nsects / (cxt->sector_size >> 9)); + if (fdisk_is_regfile(cxt)) + cxt->total_sectors = cxt->dev_st.st_size / cxt->sector_size; + else { + /* get number of 512-byte sectors, and convert it the real sectors */ + if (!blkdev_get_sectors(cxt->dev_fd, (unsigned long long *) &nsects)) + cxt->total_sectors = (nsects / (cxt->sector_size >> 9)); + + /* what the kernel/bios thinks the geometry is */ + blkdev_get_geometry(cxt->dev_fd, &h, &s); + } DBG(CXT, ul_debugobj(cxt, "total sectors: %ju (ioctl=%ju)", (uintmax_t) cxt->total_sectors, (uintmax_t) nsects)); - /* what the kernel/bios thinks the geometry is */ - blkdev_get_geometry(cxt->dev_fd, &cxt->geom.heads, (unsigned int *) &cxt->geom.sectors); + cxt->geom.cylinders = 0; + cxt->geom.heads = h; + cxt->geom.sectors = s; /* obtained heads and sectors */ recount_geometry(cxt); @@ -491,7 +502,7 @@ int fdisk_discover_topology(struct fdisk_context *cxt) blkid_free_probe(pr); #endif - cxt->sector_size = get_sector_size(cxt->dev_fd); + cxt->sector_size = get_sector_size(cxt); if (!cxt->phy_sector_size) /* could not discover physical size */ cxt->phy_sector_size = cxt->sector_size; diff --git a/libfdisk/src/context.c b/libfdisk/src/context.c index 90f97a565..947f104fa 100644 --- a/libfdisk/src/context.c +++ b/libfdisk/src/context.c @@ -488,6 +488,8 @@ static void reset_context(struct fdisk_context *cxt) free(cxt->collision); cxt->collision = NULL; + memset(&cxt->dev_st, 0, sizeof(cxt->dev_st)); + cxt->dev_fd = -1; cxt->firstsector = NULL; cxt->firstsector_bufsz = 0; @@ -581,7 +583,7 @@ int fdisk_assign_device(struct fdisk_context *cxt, int rc, org = fdisk_is_listonly(cxt->parent); /* assign_device() is sensitive to "listonly" mode, so let's - * follow the current context setting for the parent to avoid + * follow the current context setting for the parent to avoid * unwanted extra warnings. */ fdisk_enable_listonly(cxt->parent, fdisk_is_listonly(cxt)); @@ -601,6 +603,8 @@ int fdisk_assign_device(struct fdisk_context *cxt, if (fd < 0) return -errno; + fstat(fd, &cxt->dev_st); + cxt->readonly = readonly; cxt->dev_fd = fd; cxt->dev_path = strdup(fname); @@ -692,6 +696,18 @@ int fdisk_is_readonly(struct fdisk_context *cxt) return cxt->readonly; } +/** + * fdisk_is_regfile: + * @cxt: context + * + * Returns: 1 if open file descriptor is regular file rather than a block device. + */ +int fdisk_is_regfile(struct fdisk_context *cxt) +{ + assert(cxt); + return S_ISREG(cxt->dev_st.st_mode); +} + /** * fdisk_unref_context: * @cxt: fdisk context diff --git a/libfdisk/src/fdiskP.h b/libfdisk/src/fdiskP.h index c624773db..b068638ab 100644 --- a/libfdisk/src/fdiskP.h +++ b/libfdisk/src/fdiskP.h @@ -346,11 +346,14 @@ struct fdisk_ask { struct fdisk_context { int dev_fd; /* device descriptor */ char *dev_path; /* device path */ + struct stat dev_st; /* stat(2) result */ + int refcount; unsigned char *firstsector; /* buffer with master boot record */ unsigned long firstsector_bufsz; + /* topology */ unsigned long io_size; /* I/O size used by fdisk */ unsigned long optimal_io_size; /* optional I/O returned by device */ @@ -397,6 +400,7 @@ struct fdisk_context { struct fdisk_script *script; /* what we want to follow */ }; + /* context.c */ extern int __fdisk_switch_label(struct fdisk_context *cxt, struct fdisk_label *lb); diff --git a/libfdisk/src/libfdisk.h.in b/libfdisk/src/libfdisk.h.in index 59cce190d..141109ec9 100644 --- a/libfdisk/src/libfdisk.h.in +++ b/libfdisk/src/libfdisk.h.in @@ -182,6 +182,7 @@ int fdisk_assign_device(struct fdisk_context *cxt, const char *fname, int readonly); int fdisk_deassign_device(struct fdisk_context *cxt, int nosync); int fdisk_is_readonly(struct fdisk_context *cxt); +int fdisk_is_regfile(struct fdisk_context *cxt); int fdisk_enable_details(struct fdisk_context *cxt, int enable); int fdisk_is_details(struct fdisk_context *cxt); diff --git a/libfdisk/src/libfdisk.sym b/libfdisk/src/libfdisk.sym index d6d4ac557..9b769d8e5 100644 --- a/libfdisk/src/libfdisk.sym +++ b/libfdisk/src/libfdisk.sym @@ -278,4 +278,5 @@ FDISK_2.29 { FDISK_2.30 { fdisk_script_has_force_label; + fdisk_is_regfile; } FDISK_2.29; -- cgit v1.2.3-55-g7522