]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libfdisk: don't use blkdev ioctls for regular files
authorKarel Zak <kzak@redhat.com>
Fri, 13 Jan 2017 10:23:23 +0000 (11:23 +0100)
committerKarel Zak <kzak@redhat.com>
Fri, 13 Jan 2017 10:23:23 +0000 (11:23 +0100)
$ fdisk <diskimage>

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 <kzak@redhat.com>
libfdisk/docs/libfdisk-sections.txt
libfdisk/src/alignment.c
libfdisk/src/context.c
libfdisk/src/fdiskP.h
libfdisk/src/libfdisk.h.in
libfdisk/src/libfdisk.sym

index 72a7dca34ff70d88e16fe007904122157ad4d956..11b25b108a6fb34a588fd152aae052d0a2687791 100644 (file)
@@ -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
index 58acefb890b8cebb595d5eb50db5acb070a0cc08..b874a48f897c479bfea8a300ab0de3f7f0e62094 100644 (file)
@@ -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, &sect_sz))
+       if (!fdisk_is_regfile(cxt) &&
+           !blkdev_get_sector_size(cxt->dev_fd, &sect_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;
 
index 90f97a565f0822b5dc91ab9af73573663c090e8f..947f104fabf8ad8f31184036c4144c4cca1791cb 100644 (file)
@@ -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
index c624773db5ba7cbeb295d77171f175f981fbde2e..b068638ab1de847480d63118aa80d093d90635b8 100644 (file)
@@ -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);
index 59cce190d7805897f73565b71421cfe88daaef63..141109ec94be6c56a7101824d45426fe9649fbdd 100644 (file)
@@ -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);
index d6d4ac55778f0712a46e732be096b8a263e2365f..9b769d8e5ffb23c0644c6a8f7e0f442f23b2b3b9 100644 (file)
@@ -278,4 +278,5 @@ FDISK_2.29 {
 
 FDISK_2.30 {
        fdisk_script_has_force_label;
+       fdisk_is_regfile;
 } FDISK_2.29;