summaryrefslogtreecommitdiffstats
path: root/partx/dos.c
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/dos.c
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/dos.c')
-rw-r--r--partx/dos.c106
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;
+}