diff options
author | Karel Zak | 2006-12-07 00:25:43 +0100 |
---|---|---|
committer | Karel Zak | 2006-12-07 00:25:43 +0100 |
commit | 22853e4a82c6ef7b336527529acb94b14a0b0fd8 (patch) | |
tree | ee28e4598c8c449d7e811711d8ce8eb17caecfb6 /partx | |
parent | Imported from util-linux-2.10f tarball. (diff) | |
download | kernel-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/Makefile | 14 | ||||
-rw-r--r-- | partx/addpart.c | 40 | ||||
-rw-r--r-- | partx/bsd.c | 83 | ||||
-rw-r--r-- | partx/delpart.c | 40 | ||||
-rw-r--r-- | partx/dos.c | 106 | ||||
-rw-r--r-- | partx/partx.c | 395 | ||||
-rw-r--r-- | partx/partx.h | 26 | ||||
-rw-r--r-- | partx/solaris.c | 70 | ||||
-rw-r--r-- | partx/unixware.c | 83 |
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; +} |