summaryrefslogtreecommitdiff
path: root/sbin/fdisk/disk.c
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2014-03-14 15:41:34 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2014-03-14 15:41:34 +0000
commit6ad247cd626ea34f6cb942bf33053b788613b984 (patch)
tree9fd8e36e7e6e3e00fbf03ab623dd5c686e01ebcc /sbin/fdisk/disk.c
parent55cfab68ddb4c47c09c290067034b18712ec4b46 (diff)
Revert last -- broke building snaps.
Diffstat (limited to 'sbin/fdisk/disk.c')
-rw-r--r--sbin/fdisk/disk.c83
1 files changed, 66 insertions, 17 deletions
diff --git a/sbin/fdisk/disk.c b/sbin/fdisk/disk.c
index dc01f59ecc9..d79e4104612 100644
--- a/sbin/fdisk/disk.c
+++ b/sbin/fdisk/disk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: disk.c,v 1.37 2014/03/13 12:02:28 krw Exp $ */
+/* $OpenBSD: disk.c,v 1.38 2014/03/14 15:41:33 krw Exp $ */
/*
* Copyright (c) 1997, 2001 Tobias Weingartner
@@ -41,6 +41,8 @@
struct disklabel dl;
+struct DISK_metrics *DISK_getlabelmetrics(char *name);
+
int
DISK_open(char *disk, int mode)
{
@@ -57,34 +59,80 @@ DISK_open(char *disk, int mode)
return (fd);
}
-void
-DISK_getlabelgeometry(struct disk *disk)
+/* Routine to go after the disklabel for geometry
+ * information. This should work everywhere, but
+ * in the land of PC, things are not always what
+ * they seem.
+ */
+struct DISK_metrics *
+DISK_getlabelmetrics(char *name)
{
+ struct DISK_metrics *lm = NULL;
u_int64_t sz, spc;
int fd;
- /* Get label geometry. */
- if ((fd = DISK_open(disk->name, O_RDONLY)) != -1) {
+ /* Get label metrics */
+ if ((fd = DISK_open(name, O_RDONLY)) != -1) {
+ lm = malloc(sizeof(struct DISK_metrics));
+ if (lm == NULL)
+ err(1, NULL);
+
if (ioctl(fd, DIOCGPDINFO, &dl) == -1) {
warn("DIOCGPDINFO");
+ free(lm);
+ lm = NULL;
} else {
- disk->cylinders = dl.d_ncylinders;
- disk->heads = dl.d_ntracks;
- disk->sectors = dl.d_nsectors;
+ lm->cylinders = dl.d_ncylinders;
+ lm->heads = dl.d_ntracks;
+ lm->sectors = dl.d_nsectors;
/* MBR handles only first UINT32_MAX sectors. */
- spc = (u_int64_t)disk->heads * disk->sectors;
+ spc = (u_int64_t)lm->heads * lm->sectors;
sz = DL_GETDSIZE(&dl);
if (sz > UINT32_MAX) {
- disk->cylinders = UINT32_MAX / spc;
- disk->size = disk->cylinders * spc;
+ lm->cylinders = UINT32_MAX / spc;
+ lm->size = lm->cylinders * spc;
warnx("disk too large (%llu sectors)."
" size truncated.", sz);
} else
- disk->size = sz;
+ lm->size = sz;
unit_types[SECTORS].conversion = dl.d_secsize;
}
close(fd);
}
+
+ return (lm);
+}
+
+/* This is ugly, and convoluted. All the magic
+ * for disk geo/size happens here. Basically,
+ * the real size is the one we will use in the
+ * rest of the program, the label size is what we
+ * got from the disklabel. If the disklabel fails,
+ * we assume we are working with a normal file,
+ * and should request the user to specify the
+ * geometry he/she wishes to use.
+ */
+int
+DISK_getmetrics(struct disk *disk, struct DISK_metrics *user)
+{
+
+ disk->label = DISK_getlabelmetrics(disk->name);
+
+ /* If user supplied, use that */
+ if (user) {
+ disk->real = user;
+ return (0);
+ }
+
+ /* If we have a label, use that */
+ if (disk->label) {
+ disk->real = disk->label;
+ return (0);
+ }
+
+ /* Can not get geometry, punt */
+ disk->real = NULL;
+ return (1);
}
/*
@@ -92,18 +140,19 @@ DISK_getlabelgeometry(struct disk *disk)
* to indicate the units that should be used for display.
*/
int
-DISK_printgeometry(struct disk *disk, char *units)
+DISK_printmetrics(struct disk *disk, char *units)
{
const int secsize = unit_types[SECTORS].conversion;
double size;
int i;
i = unit_lookup(units);
- size = ((double)disk->size * secsize) / unit_types[i].conversion;
+ size = ((double)disk->real->size * secsize) / unit_types[i].conversion;
printf("Disk: %s\t", disk->name);
- if (disk->size) {
- printf("geometry: %d/%d/%d [%.0f ", disk->cylinders,
- disk->heads, disk->sectors, size);
+ if (disk->real) {
+ printf("geometry: %d/%d/%d [%.0f ",
+ disk->real->cylinders, disk->real->heads,
+ disk->real->sectors, size);
if (i == SECTORS && secsize != sizeof(struct dos_mbr))
printf("%d-byte ", secsize);
printf("%s]\n", unit_types[i].lname);