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/dos.c | |
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/dos.c')
-rw-r--r-- | partx/dos.c | 106 |
1 files changed, 106 insertions, 0 deletions
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; +} |