[kpartx] bug fixes for dos extended partition [3/4]
[platform/upstream/multipath-tools.git] / kpartx / dos.c
1 /*
2  * Source: copy of util-linux' partx dos.c
3  *
4  * Copyrights of the original file apply 
5  * Copyright (c) 2005 Bastian Blank
6  */
7 #include "kpartx.h"
8 #include "byteorder.h"
9 #include <stdio.h>
10 #include <string.h>
11 #include "dos.h"
12
13 static int
14 is_extended(int type) {
15         return (type == 5 || type == 0xf || type == 0x85);
16 }
17
18 static int
19 read_extended_partition(int fd, struct partition *ep,
20                         struct slice *sp, int ns)
21 {
22         struct partition p;
23         unsigned long start, here, next;
24         unsigned char *bp;
25         int loopct = 0;
26         int moretodo = 1;
27         int i, n=0;
28
29         next = start = le32_to_cpu(ep->start_sect);
30
31         while (moretodo) {
32                 here = next;
33                 moretodo = 0;
34                 if (++loopct > 100)
35                         return n;
36
37                 bp = (unsigned char *)getblock(fd, here);
38                 if (bp == NULL)
39                         return n;
40
41                 if (bp[510] != 0x55 || bp[511] != 0xaa)
42                         return n;
43
44                 for (i=0; i<2; i++) {
45                         memcpy(&p, bp + 0x1be + i * sizeof (p), sizeof (p));
46                         if (is_extended(p.sys_type)) {
47                                 if (p.nr_sects && !moretodo) {
48                                         next = start + le32_to_cpu(p.start_sect);
49                                         moretodo = 1;
50                                 }
51                                 continue;
52                         }
53                         if (n < ns) {
54                                 sp[n].start = here + le32_to_cpu(p.start_sect);
55                                 sp[n].size = le32_to_cpu(p.nr_sects);
56                                 n++;
57                         } else {
58                                 fprintf(stderr,
59                                     "dos_extd_partition: too many slices\n");
60                                 return n;
61                         }
62                         loopct = 0;
63                 }
64         }
65         return n;
66 }
67
68 static int
69 is_gpt(int type) {
70         return (type == 0xEE);
71 }
72
73 int
74 read_dos_pt(int fd, struct slice all, struct slice *sp, int ns) {
75         struct partition p;
76         unsigned long offset = all.start;
77         int i, n=4;
78         unsigned char *bp;
79
80         bp = (unsigned char *)getblock(fd, offset);
81         if (bp == NULL)
82                 return -1;
83
84         if (bp[510] != 0x55 || bp[511] != 0xaa)
85                 return -1;
86
87         for (i=0; i<4; i++) {
88                 memcpy(&p, bp + 0x1be + i * sizeof (p), sizeof (p));
89         }
90         for (i=0; i<4; i++) {
91                 memcpy(&p, bp + 0x1be + i * sizeof (p), sizeof (p));
92                 if (is_gpt(p.sys_type))
93                         return 0;
94                 if (i < ns) {
95                         sp[i].start =  le32_to_cpu(p.start_sect);
96                         sp[i].size = le32_to_cpu(p.nr_sects);
97                 } else {
98                         fprintf(stderr,
99                                 "dos_partition: too many slices\n");
100                         break;
101                 }
102                 if (is_extended(p.sys_type)) {
103                         n += read_extended_partition(fd, &p, sp+n, ns-n);
104                         /* hide the extended partition itself */
105                         sp[i].size = 0;
106                 }
107         }
108         return n;
109 }