summaryrefslogtreecommitdiffstats
path: root/libfdisk
diff options
context:
space:
mode:
authorKarel Zak2017-01-13 11:23:23 +0100
committerKarel Zak2017-01-13 11:23:23 +0100
commit7526c305b459f1387dad72d1543308246fc12877 (patch)
tree2947ea35cf9f0f5b688d991bb3ec1d05a2b5c9d4 /libfdisk
parentIf mtab support is disabled, disable ro/rw mtab checks (diff)
downloadkernel-qcow2-util-linux-7526c305b459f1387dad72d1543308246fc12877.tar.gz
kernel-qcow2-util-linux-7526c305b459f1387dad72d1543308246fc12877.tar.xz
kernel-qcow2-util-linux-7526c305b459f1387dad72d1543308246fc12877.zip
libfdisk: don't use blkdev ioctls for regular files
$ 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>
Diffstat (limited to 'libfdisk')
-rw-r--r--libfdisk/docs/libfdisk-sections.txt1
-rw-r--r--libfdisk/src/alignment.c27
-rw-r--r--libfdisk/src/context.c18
-rw-r--r--libfdisk/src/fdiskP.h4
-rw-r--r--libfdisk/src/libfdisk.h.in1
-rw-r--r--libfdisk/src/libfdisk.sym1
6 files changed, 43 insertions, 9 deletions
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, &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;
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);
@@ -693,6 +697,18 @@ int fdisk_is_readonly(struct fdisk_context *cxt)
}
/**
+ * 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;