diff options
Diffstat (limited to 'kpartx/dos.c')
-rw-r--r-- | kpartx/dos.c | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/kpartx/dos.c b/kpartx/dos.c new file mode 100644 index 0000000..2f4e8a9 --- /dev/null +++ b/kpartx/dos.c @@ -0,0 +1,112 @@ +#include "kpartx.h" +#include "byteorder.h" +#include <stdio.h> +#include "dos.h" + +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; + unsigned char *bp; + int loopct = 0; + int moretodo = 1; + int i, n=0; + + here = start = le32_to_cpu(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 + le32_to_cpu(p->start_sect); + sp[n].size = le32_to_cpu(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 + le32_to_cpu(p->start_sect); + moretodo = 1; + break; + } + } + } + return n; +} + +static int +is_gpt(int type) { + return (type == 0xEE); +} + +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++) { + if (is_gpt(p->sys_type)) { + return 0; + } + p++; + } + p = (struct partition *) (bp + 0x1be); + for (i=0; i<4; i++) { + /* always add, even if zero length */ + if (n < ns) { + sp[n].start = le32_to_cpu(p->start_sect); + sp[n].size = le32_to_cpu(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; +} |