summaryrefslogtreecommitdiffstats
path: root/partx
diff options
context:
space:
mode:
authorKarel Zak2006-12-07 00:25:43 +0100
committerKarel Zak2006-12-07 00:25:43 +0100
commit22853e4a82c6ef7b336527529acb94b14a0b0fd8 (patch)
treeee28e4598c8c449d7e811711d8ce8eb17caecfb6 /partx
parentImported from util-linux-2.10f tarball. (diff)
downloadkernel-qcow2-util-linux-22853e4a82c6ef7b336527529acb94b14a0b0fd8.tar.gz
kernel-qcow2-util-linux-22853e4a82c6ef7b336527529acb94b14a0b0fd8.tar.xz
kernel-qcow2-util-linux-22853e4a82c6ef7b336527529acb94b14a0b0fd8.zip
Imported from util-linux-2.10m tarball.
Diffstat (limited to 'partx')
-rw-r--r--partx/Makefile14
-rw-r--r--partx/addpart.c40
-rw-r--r--partx/bsd.c83
-rw-r--r--partx/delpart.c40
-rw-r--r--partx/dos.c106
-rw-r--r--partx/partx.c395
-rw-r--r--partx/partx.h26
-rw-r--r--partx/solaris.c70
-rw-r--r--partx/unixware.c83
9 files changed, 857 insertions, 0 deletions
diff --git a/partx/Makefile b/partx/Makefile
new file mode 100644
index 000000000..39237e019
--- /dev/null
+++ b/partx/Makefile
@@ -0,0 +1,14 @@
+OBJ = bsd.o dos.o partx.o solaris.o unixware.o
+
+all: addpart delpart partx
+
+partx: $(OBJ)
+
+addpart: addpart.o
+
+delpart: delpart.o
+
+clean:
+ rm -f $(OBJ) addpart.o delpart.o addpart delpart partx *~
+
+$(OBJ): partx.h
diff --git a/partx/addpart.c b/partx/addpart.c
new file mode 100644
index 000000000..11d4305b9
--- /dev/null
+++ b/partx/addpart.c
@@ -0,0 +1,40 @@
+/* very primitive wrapper around the `add partition' ioctl */
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <linux/blkpg.h>
+
+int
+main(int argc, char **argv){
+ int fd;
+ struct blkpg_ioctl_arg a;
+ struct blkpg_partition p;
+
+ if (argc != 5) {
+ fprintf(stderr,
+ "usage: %s diskdevice partitionnr start length\n",
+ argv[0]);
+ exit(1);
+ }
+ if ((fd = open(argv[1], O_RDONLY)) < 0) {
+ perror(argv[1]);
+ exit(1);
+ }
+ p.pno = atoi(argv[2]);
+ p.start = 512 * ((long long) atol(argv[3]));
+ p.length = 512 * ((long long) atol(argv[4]));
+ p.devname[0] = 0;
+ p.volname[0] = 0;
+ a.op = BLKPG_ADD_PARTITION;
+ a.flags = 0;
+ a.datalen = sizeof(p);
+ a.data = &p;
+
+ if (ioctl(fd, BLKPG, &a) == -1) {
+ perror("BLKPG");
+ exit(1);
+ }
+
+ return 0;
+}
diff --git a/partx/bsd.c b/partx/bsd.c
new file mode 100644
index 000000000..531c36c23
--- /dev/null
+++ b/partx/bsd.c
@@ -0,0 +1,83 @@
+#include <stdio.h>
+#include "partx.h"
+
+#define BSD_DISKMAGIC (0x82564557UL) /* The disk magic number */
+#define XBSD_MAXPARTITIONS 16
+#define BSD_FS_UNUSED 0
+
+struct bsd_disklabel {
+ unsigned int d_magic; /* the magic number */
+ short int d_type; /* drive type */
+ short int d_subtype; /* controller/d_type specific */
+ char d_typename[16]; /* type name, e.g. "eagle" */
+ char d_packname[16]; /* pack identifier */
+ unsigned int d_secsize; /* # of bytes per sector */
+ unsigned int d_nsectors; /* # of data sectors per track */
+ unsigned int d_ntracks; /* # of tracks per cylinder */
+ unsigned int d_ncylinders; /* # of data cylinders per unit */
+ unsigned int d_secpercyl; /* # of data sectors per cylinder */
+ unsigned int d_secperunit; /* # of data sectors per unit */
+ unsigned short d_sparespertrack;/* # of spare sectors per track */
+ unsigned short d_sparespercyl; /* # of spare sectors per cylinder */
+ unsigned int d_acylinders; /* # of alt. cylinders per unit */
+ unsigned short d_rpm; /* rotational speed */
+ unsigned short d_interleave; /* hardware sector interleave */
+ unsigned short d_trackskew; /* sector 0 skew, per track */
+ unsigned short d_cylskew; /* sector 0 skew, per cylinder */
+ unsigned int d_headswitch; /* head switch time, usec */
+ unsigned int d_trkseek; /* track-to-track seek, usec */
+ unsigned int d_flags; /* generic flags */
+ unsigned int d_drivedata[5]; /* drive-type specific information */
+ unsigned int d_spare[5]; /* reserved for future use */
+ unsigned int d_magic2; /* the magic number (again) */
+ unsigned short d_checksum; /* xor of data incl. partitions */
+
+ /* filesystem and partition information: */
+ unsigned short d_npartitions; /* number of partitions in following */
+ unsigned int d_bbsize; /* size of boot area at sn0, bytes */
+ unsigned int d_sbsize; /* max size of fs superblock, bytes */
+ struct bsd_partition { /* the partition table */
+ unsigned int p_size; /* number of sectors in partition */
+ unsigned int p_offset; /* starting sector */
+ unsigned int p_fsize; /* filesystem basic fragment size */
+ unsigned char p_fstype; /* filesystem type, see below */
+ unsigned char p_frag; /* filesystem fragments per block */
+ unsigned short p_cpg; /* filesystem cylinders per group */
+ } d_partitions[XBSD_MAXPARTITIONS];/* actually may be more */
+};
+
+int
+read_bsd_pt(int fd, struct slice all, struct slice *sp, int ns) {
+ struct bsd_disklabel *l;
+ struct bsd_partition *p;
+ unsigned int offset = all.start;
+ int max_partitions;
+ char *bp;
+ int n = 0;
+
+ bp = getblock(fd, offset+1); /* 1 sector suffices */
+ if (bp == NULL)
+ return -1;
+
+ l = (struct bsd_disklabel *) bp;
+ if (l->d_magic != BSD_DISKMAGIC)
+ return -1;
+
+ max_partitions = 16;
+ if (l->d_npartitions < max_partitions)
+ max_partitions = l->d_npartitions;
+ for (p = l->d_partitions; p - l->d_partitions < max_partitions; p++) {
+ if (p->p_fstype == BSD_FS_UNUSED)
+ /* nothing */;
+ else if (n < ns) {
+ sp[n].start = p->p_offset;
+ sp[n].size = p->p_size;
+ n++;
+ } else {
+ fprintf(stderr,
+ "bsd_partition: too many slices\n");
+ break;
+ }
+ }
+ return n;
+}
diff --git a/partx/delpart.c b/partx/delpart.c
new file mode 100644
index 000000000..8504c0223
--- /dev/null
+++ b/partx/delpart.c
@@ -0,0 +1,40 @@
+/* very primitive wrapper around the `delete partition' ioctl */
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <linux/blkpg.h>
+
+int
+main(int argc, char **argv){
+ int fd;
+ struct blkpg_ioctl_arg a;
+ struct blkpg_partition p;
+
+ if (argc != 3) {
+ fprintf(stderr,
+ "usage: %s diskdevice partitionnr\n",
+ argv[0]);
+ exit(1);
+ }
+ if ((fd = open(argv[1], O_RDONLY)) < 0) {
+ perror(argv[1]);
+ exit(1);
+ }
+ p.pno = atoi(argv[2]);
+ p.start = 0;
+ p.length = 0;
+ p.devname[0] = 0;
+ p.volname[0] = 0;
+ a.op = BLKPG_DEL_PARTITION;
+ a.flags = 0;
+ a.datalen = sizeof(p);
+ a.data = &p;
+
+ if (ioctl(fd, BLKPG, &a) == -1) {
+ perror("BLKPG");
+ exit(1);
+ }
+
+ return 0;
+}
diff --git a/partx/dos.c b/partx/dos.c
new file mode 100644
index 000000000..b32801e0b
--- /dev/null
+++ b/partx/dos.c
@@ -0,0 +1,106 @@
+#include <stdio.h>
+#include "partx.h"
+
+struct partition {
+ unsigned char boot_ind; /* 0x80 - active */
+ unsigned char bh, bs, bc;
+ unsigned char sys_type;
+ unsigned char eh, es, ec;
+ unsigned int start_sect;
+ unsigned int nr_sects;
+};
+
+static int
+is_extended(int type) {
+ return (type == 5 || type == 0xf || type == 0x85);
+}
+
+static int
+read_extended_partition(int fd, struct partition *ep,
+ struct slice *sp, int ns) {
+ struct partition *p;
+ unsigned long start, here, next;
+ unsigned char *bp;
+ int loopct = 0;
+ int moretodo = 1;
+ int i, n=0;
+
+ here = start = ep->start_sect;
+
+ while (moretodo) {
+ moretodo = 0;
+ if (++loopct > 100)
+ return n;
+
+ bp = getblock(fd, here);
+ if (bp == NULL)
+ return n;
+
+ if (bp[510] != 0x55 || bp[511] != 0xaa)
+ return n;
+
+ p = (struct partition *) (bp + 0x1be);
+
+ for (i=0; i<2; i++, p++) {
+ if (p->nr_sects == 0 || is_extended(p->sys_type))
+ continue;
+ if (n < ns) {
+ sp[n].start = here + p->start_sect;
+ sp[n].size = p->nr_sects;
+ n++;
+ } else {
+ fprintf(stderr,
+ "dos_extd_partition: too many slices\n");
+ return n;
+ }
+ loopct = 0;
+ }
+
+ p -= 2;
+ for (i=0; i<2; i++, p++) {
+ if(p->nr_sects != 0 && is_extended(p->sys_type)) {
+ here = start + p->start_sect;
+ moretodo = 1;
+ break;
+ }
+ }
+ }
+ return n;
+}
+
+int
+read_dos_pt(int fd, struct slice all, struct slice *sp, int ns) {
+ struct partition *p;
+ unsigned long offset = all.start;
+ int i, n=0;
+ unsigned char *bp;
+
+ bp = getblock(fd, offset);
+ if (bp == NULL)
+ return -1;
+
+ if (bp[510] != 0x55 || bp[511] != 0xaa)
+ return -1;
+
+ p = (struct partition *) (bp + 0x1be);
+ for (i=0; i<4; i++) {
+ /* always add, even if zero length */
+ if (n < ns) {
+ sp[n].start = p->start_sect;
+ sp[n].size = p->nr_sects;
+ n++;
+ } else {
+ fprintf(stderr,
+ "dos_partition: too many slices\n");
+ break;
+ }
+ p++;
+ }
+ p = (struct partition *) (bp + 0x1be);
+ for (i=0; i<4; i++) {
+ if (is_extended(p->sys_type))
+ n += read_extended_partition(fd, p, sp+n, ns-n);
+ p++;
+ }
+ return n;
+}
diff --git a/partx/partx.c b/partx/partx.c
new file mode 100644
index 000000000..212f651b6
--- /dev/null
+++ b/partx/partx.c
@@ -0,0 +1,395 @@
+/*
+ * Given a block device and a partition table type,
+ * try to parse the partition table, and list the
+ * contents. Optionally add or remove partitions.
+ *
+ * [This is not an fdisk - adding and removing partitions
+ * is not a change of the disk, but just telling the kernel
+ * about presence and numbering of on-disk partitions.]
+ *
+ * Call:
+ * partx [-{l|a|d}] [--type TYPE] [--nr M-N] [partition] wholedisk
+ * where TYPE is {dos|bsd|solaris|unixware}.
+ *
+ * Read wholedisk and add all partitions:
+ * partx -a wholedisk
+ *
+ * Subdivide a partition into slices (and delete or shrink the partition):
+ * [Not easy: one needs the partition number of partition -
+ * that is the last 4 or 6 bits of the minor; it can also be found
+ * in /proc/partitions; but there is no good direct way.]
+ * partx -a partition wholedisk
+ *
+ * Delete all partitions from wholedisk:
+ * partx -d wholedisk
+ *
+ * Delete partitions M-N from wholedisk:
+ * partx -d --nr M-N wholedisk
+ *
+ * aeb, 2000-03-21 -- sah is 42 now
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/ioctl.h>
+#include <linux/hdreg.h> /* HDIO_GETGEO */
+#include <linux/blkpg.h>
+#define BLKGETSIZE _IO(0x12,96) /* return device size */
+
+#include "partx.h"
+static void errmerge(int err, int m, char *msg1, char *msg2);
+
+#define SIZE(a) (sizeof(a)/sizeof((a)[0]))
+
+#define MAXTYPES 64
+#define MAXSLICES 256
+
+struct slice slices[MAXSLICES];
+
+enum action { LIST, ADD, DELETE };
+
+struct pt {
+ char *type;
+ ptreader *fn;
+} pts[MAXTYPES];
+int ptct;
+
+addpts(char *t, ptreader f) {
+ if (ptct >= MAXTYPES) {
+ fprintf(stderr, "addpts: too many types\n");
+ exit(1);
+ }
+ pts[ptct].type = t;
+ pts[ptct].fn = f;
+ ptct++;
+}
+
+initpts(){
+ addpts("dos", read_dos_pt);
+ addpts("bsd", read_bsd_pt);
+ addpts("solaris", read_solaris_pt);
+ addpts("unixware", read_unixware_pt);
+}
+
+static char short_opts[] = "ladvn:t:";
+static const struct option long_opts[] = {
+ { "type", required_argument, NULL, 't' },
+ { "nr", required_argument, NULL, 'n' },
+ { NULL, 0, NULL, 0 }
+};
+
+int
+main(int argc, char **argv){
+ int fd, fd2, c, i, j, k, n;
+ long size;
+ struct hd_geometry g;
+ struct slice all;
+ struct blkpg_ioctl_arg a;
+ struct blkpg_partition pt;
+ struct pt *ptp;
+ enum action what = LIST;
+ char *p, *type, *diskdevice, *device;
+ int lower, upper;
+ int verbose = 0;
+ int ret = 0;
+
+ initpts();
+
+ lower = upper = 0;
+ type = device = diskdevice = NULL;
+
+ while ((c = getopt_long (argc, argv, short_opts, long_opts, NULL))
+ != -1) switch(c) {
+ case 'l':
+ what = LIST; break;
+ case 'a':
+ what = ADD; break;
+ case 'd':
+ what = DELETE; break;
+ case 'n':
+ p = optarg;
+ lower = atoi(p);
+ p = index(p, '-');
+ if (p)
+ upper = atoi(p+1);
+ else
+ upper = lower;
+ break;
+ case 't':
+ type = optarg;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "unknown option\n");
+ exit(1);
+ }
+
+ if (optind == argc-2) {
+ device = argv[optind];
+ diskdevice = argv[optind+1];
+ } else if (optind == argc-1) {
+ diskdevice = device = argv[optind];
+ } else {
+ fprintf(stderr, "call: partx -opts [device] wholedisk\n");
+ exit(1);
+ }
+
+ fd = open(diskdevice, O_RDONLY);
+ if (fd == -1) {
+ perror(diskdevice);
+ exit(1);
+ }
+
+ /* remove the indicated partitions from the kernel partition tables */
+ if (what == DELETE) {
+ if (device != diskdevice) {
+ fprintf(stderr,
+ "call: partx -d [--nr M-N] wholedisk\n");
+ exit(1);
+ }
+
+ if (!lower)
+ lower = 1;
+
+ while (upper == 0 || lower <= upper) {
+ int err;
+
+ pt.pno = lower;
+ pt.start = 0;
+ pt.length = 0;
+ pt.devname[0] = 0;
+ pt.volname[0] = 0;
+ a.op = BLKPG_DEL_PARTITION;
+ a.flags = 0;
+ a.datalen = sizeof(pt);
+ a.data = &pt;
+ if (ioctl(fd, BLKPG, &a) == -1)
+ err = errno;
+ else
+ err = 0;
+ errmerge(err, lower,
+ "error deleting partition %d: ",
+ "error deleting partitions %d-%d: ");
+ /* expected errors:
+ EBUSY: mounted or in use as swap
+ ENXIO: no such nonempty partition
+ EINVAL: not wholedisk, or bad pno
+ EACCES/EPERM: permission denied
+ */
+ if (err && err != EBUSY && err != ENXIO) {
+ ret = 1;
+ break;
+ }
+ if (err == 0 && verbose)
+ printf("deleted partition %d\n", lower);
+ lower++;
+ }
+ errmerge(0, 0,
+ "error deleting partition %d: ",
+ "error deleting partitions %d-%d: ");
+ return ret;
+ }
+
+ if (device != diskdevice) {
+ fd2 = open(device, O_RDONLY);
+ if (fd2 == -1) {
+ perror(device);
+ exit(1);
+ }
+ } else {
+ fd2 = fd;
+ }
+
+ if (ioctl(fd, HDIO_GETGEO, &g)) {
+ perror("HDIO_GETGEO");
+ exit(1);
+ }
+ if (g.start != 0) {
+ fprintf(stderr, "last arg is not the whole disk\n");
+ fprintf(stderr, "call: partx -opts device wholedisk\n");
+ exit(1);
+ }
+
+ if (ioctl(fd2, HDIO_GETGEO, &g)) {
+ perror("HDIO_GETGEO");
+ exit(1);
+ }
+ all.start = g.start;
+
+ if(ioctl(fd2, BLKGETSIZE, &size)) {
+ perror("BLKGETSIZE");
+ exit(1);
+ }
+ all.size = size;
+
+ if (verbose)
+ printf("device %s: start %d size %d\n",
+ device, all.start, all.size);
+
+ if (all.size == 0) {
+ fprintf(stderr, "That disk slice has size 0\n");
+ exit(0);
+ }
+ if (all.size == 2)
+ all.size = 0; /* probably extended partition */
+
+ /* add the indicated partitions to the kernel partition tables */
+ if (!lower)
+ lower = 1;
+ for (i = 0; i < ptct; i++) {
+ ptp = &pts[i];
+ if (!type || !strcmp(type, ptp->type)) {
+ n = ptp->fn(fd, all, slices, SIZE(slices));
+ if (n >= 0 && verbose)
+ printf("%s: %d slices\n", ptp->type, n);
+ if (n > 0 && (verbose || what == LIST)) {
+ for (j=0; j<n; j++)
+ printf("#%2d: %9d-%9d (%9d sectors, %6d MB)\n",
+ lower+j,
+ slices[j].start,
+ slices[j].start+slices[j].size-1,
+ slices[j].size,
+ ((512 * (long long) slices[j].size)
+ / 1000000));
+ }
+ if (n > 0 && what == ADD) {
+ /* test for overlap, as in the case of an
+ extended partition, and reduce size */
+ for (j=0; j<n; j++) {
+ for (k=j+1; k<n; k++) {
+ if (slices[k].start > slices[j].start &&
+ slices[k].start < slices[j].start +
+ slices[j].size) {
+ slices[j].size = slices[k].start -
+ slices[j].start;
+ if (verbose)
+ printf("reduced size of "
+ "partition #%d to %d\n",
+ lower+j,
+ slices[j].size);
+ }
+ }
+ }
+ for (j=0; j<n; j++) {
+ pt.pno = lower+j;
+ pt.start = 512 * (long long) slices[j].start;
+ pt.length = 512 * (long long) slices[j].size;
+ pt.devname[0] = 0;
+ pt.volname[0] = 0;
+ a.op = BLKPG_ADD_PARTITION;
+ a.flags = 0;
+ a.datalen = sizeof(pt);
+ a.data = &pt;
+ if (ioctl(fd, BLKPG, &a) == -1) {
+ perror("BLKPG");
+ fprintf(stderr,
+ "error adding partition %d\n",
+ lower+j);
+ } else if (verbose)
+ printf("added partition %d\n", lower+j);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+void *
+xmalloc (size_t size) {
+ void *t;
+
+ if (size == 0)
+ return NULL;
+ t = malloc (size);
+ if (t == NULL) {
+ fprintf(stderr, "Out of memory\n");
+ exit(1);
+ }
+ return t;
+}
+
+/*
+ * sseek: seek to specified sector
+ */
+#if !defined (__alpha__) && !defined (__ia64__)
+#include <linux/unistd.h> /* _syscall */
+static
+_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
+ long long *, res, uint, wh);
+#endif
+
+static int
+sseek(int fd, unsigned int secnr) {
+ long long in, out;
+ in = ((long long) secnr << 9);
+ out = 1;
+
+#if !defined (__alpha__) && !defined (__ia64__)
+ if (_llseek (fd, in>>32, in & 0xffffffff, &out, SEEK_SET) != 0
+ || out != in)
+#else
+ if ((out = lseek(fd, in, SEEK_SET)) != in)
+#endif
+ {
+ fprintf(stderr, "llseek error\n");
+ return -1;
+ }
+ return 0;
+}
+
+static
+struct block {
+ unsigned int secnr;
+ char *block;
+ struct block *next;
+} *blockhead;
+
+char *
+getblock(int fd, unsigned int secnr) {
+ struct block *bp;
+
+ for (bp = blockhead; bp; bp = bp->next)
+ if (bp->secnr == secnr)
+ return bp->block;
+ if (sseek(fd, secnr))
+ return NULL;
+ bp = xmalloc(sizeof(struct block));
+ bp->secnr = secnr;
+ bp->next = blockhead;
+ blockhead = bp;
+ bp->block = (char *) xmalloc(1024);
+ if (read(fd, bp->block, 1024) != 1024) {
+ fprintf(stderr, "read error, sector %d\n", secnr);
+ bp->block = NULL;
+ }
+ return bp->block;
+}
+
+/* call with errno and integer m and error message */
+/* merge to interval m-n */
+static void
+errmerge(int err, int m, char *msg1, char *msg2) {
+ static int preverr, firstm, prevm;
+
+ if (err != preverr) {
+ if (preverr) {
+ if (firstm == prevm)
+ fprintf(stderr, msg1, firstm);
+ else
+ fprintf(stderr, msg2, firstm, prevm);
+ errno = preverr;
+ perror("BLKPG");
+ }
+ preverr = err;
+ firstm = prevm = m;
+ } else
+ prevm = m;
+}
diff --git a/partx/partx.h b/partx/partx.h
new file mode 100644
index 000000000..b96588a59
--- /dev/null
+++ b/partx/partx.h
@@ -0,0 +1,26 @@
+/*
+ * For each partition type there is a routine that takes
+ * a block device and a range, and returns the list of
+ * slices found there in the supplied array SP that can
+ * hold NS entries. The return value is the number of
+ * entries stored, or -1 if the appropriate type is not
+ * present.
+ */
+
+
+/* units: 512 byte sectors */
+struct slice {
+ unsigned int start;
+ unsigned int size;
+};
+
+typedef int (ptreader)(int fd, struct slice all, struct slice *sp, int ns);
+
+extern ptreader read_dos_pt, read_bsd_pt, read_solaris_pt, read_unixware_pt;
+
+char *getblock(int fd, unsigned int secnr);
+
+static inline int
+four2int(unsigned char *p) {
+ return p[0] + (p[1]<<8) + (p[2]<<16) + (p[3]<<24);
+}
diff --git a/partx/solaris.c b/partx/solaris.c
new file mode 100644
index 000000000..64c39664b
--- /dev/null
+++ b/partx/solaris.c
@@ -0,0 +1,70 @@
+#include <stdio.h>
+#include <time.h> /* time_t */
+#include "partx.h"
+
+#define SOLARIS_X86_NUMSLICE 8
+#define SOLARIS_X86_VTOC_SANE (0x600DDEEEUL)
+
+typedef int daddr_t; /* or long - check */
+
+struct solaris_x86_slice {
+ unsigned short s_tag; /* ID tag of partition */
+ unsigned short s_flag; /* permision flags */
+ daddr_t s_start; /* start sector no of partition */
+ long s_size; /* # of blocks in partition */
+};
+
+struct solaris_x86_vtoc {
+ unsigned long v_bootinfo[3]; /* info for mboot */
+ unsigned long v_sanity; /* to verify vtoc sanity */
+ unsigned long v_version; /* layout version */
+ char v_volume[8]; /* volume name */
+ unsigned short v_sectorsz; /* sector size in bytes */
+ unsigned short v_nparts; /* number of partitions */
+ unsigned long v_reserved[10]; /* free space */
+ struct solaris_x86_slice
+ v_slice[SOLARIS_X86_NUMSLICE]; /* slice headers */
+ time_t timestamp[SOLARIS_X86_NUMSLICE]; /* timestamp */
+ char v_asciilabel[128]; /* for compatibility */
+};
+
+int
+read_solaris_pt(int fd, struct slice all, struct slice *sp, int ns) {
+ struct solaris_x86_vtoc *v;
+ struct solaris_x86_slice *s;
+ unsigned int offset = all.start;
+ int i, n;
+ char *bp;
+
+ bp = getblock(fd, offset+1); /* 1 sector suffices */
+ if (bp == NULL)
+ return -1;
+
+ v = (struct solaris_x86_vtoc *) bp;
+ if(v->v_sanity != SOLARIS_X86_VTOC_SANE)
+ return -1;
+
+ if(v->v_version != 1) {
+ fprintf(stderr, "Cannot handle solaris version %ld vtoc\n",
+ v->v_version);
+ return 0;
+ }
+
+ for(i=0, n=0; i<SOLARIS_X86_NUMSLICE; i++) {
+ s = &v->v_slice[i];
+
+ if (s->s_size == 0)
+ continue;
+ if (n < ns) {
+ sp[n].start = offset + s->s_start;
+ sp[n].size = s->s_size;
+ n++;
+ } else {
+ fprintf(stderr,
+ "solaris_x86_partition: too many slices\n");
+ break;
+ }
+ }
+ return n;
+}
+
diff --git a/partx/unixware.c b/partx/unixware.c
new file mode 100644
index 000000000..3b3f21e16
--- /dev/null
+++ b/partx/unixware.c
@@ -0,0 +1,83 @@
+#include <stdio.h>
+#include "partx.h"
+
+#define UNIXWARE_FS_UNUSED 0
+#define UNIXWARE_NUMSLICE 16
+#define UNIXWARE_DISKMAGIC (0xCA5E600DUL)
+#define UNIXWARE_DISKMAGIC2 (0x600DDEEEUL)
+
+struct unixware_slice {
+ unsigned short s_label; /* label */
+ unsigned short s_flags; /* permission flags */
+ unsigned int start_sect; /* starting sector */
+ unsigned int nr_sects; /* number of sectors in slice */
+};
+
+struct unixware_disklabel {
+ unsigned int d_type; /* drive type */
+ unsigned char d_magic[4]; /* the magic number */
+ unsigned int d_version; /* version number */
+ char d_serial[12]; /* serial number of the device */
+ unsigned int d_ncylinders; /* # of data cylinders per device */
+ unsigned int d_ntracks; /* # of tracks per cylinder */
+ unsigned int d_nsectors; /* # of data sectors per track */
+ unsigned int d_secsize; /* # of bytes per sector */
+ unsigned int d_part_start; /* # of first sector of this partition */
+ unsigned int d_unknown1[12]; /* ? */
+ unsigned int d_alt_tbl; /* byte offset of alternate table */
+ unsigned int d_alt_len; /* byte length of alternate table */
+ unsigned int d_phys_cyl; /* # of physical cylinders per device */
+ unsigned int d_phys_trk; /* # of physical tracks per cylinder */
+ unsigned int d_phys_sec; /* # of physical sectors per track */
+ unsigned int d_phys_bytes; /* # of physical bytes per sector */
+ unsigned int d_unknown2; /* ? */
+ unsigned int d_unknown3; /* ? */
+ unsigned int d_pad[8]; /* pad */
+
+ struct unixware_vtoc {
+ unsigned char v_magic[4]; /* the magic number */
+ unsigned int v_version; /* version number */
+ char v_name[8]; /* volume name */
+ unsigned short v_nslices; /* # of slices */
+ unsigned short v_unknown1; /* ? */
+ unsigned int v_reserved[10]; /* reserved */
+ struct unixware_slice
+ v_slice[UNIXWARE_NUMSLICE]; /* slice headers */
+ } vtoc;
+
+}; /* 408 */
+
+int
+read_unixware_pt(int fd, struct slice all, struct slice *sp, int ns) {
+ struct unixware_disklabel *l;
+ struct unixware_slice *p;
+ unsigned int offset = all.start;
+ char *bp;
+ int n = 0;
+
+ bp = getblock(fd, offset+29); /* 1 sector suffices */
+ if (bp == NULL)
+ return -1;
+
+ l = (struct unixware_disklabel *) bp;
+ if (four2int(l->d_magic) != UNIXWARE_DISKMAGIC ||
+ four2int(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2)
+ return -1;
+
+ p = &l->vtoc.v_slice[1]; /* slice 0 is the whole disk. */
+ while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
+ if (p->s_label == UNIXWARE_FS_UNUSED)
+ /* nothing */;
+ else if (n < ns) {
+ sp[n].start = p->start_sect;
+ sp[n].size = p->nr_sects;
+ n++;
+ } else {
+ fprintf(stderr,
+ "unixware_partition: too many slices\n");
+ break;
+ }
+ p++;
+ }
+ return n;
+}