Bump to 0.9.7
[platform/upstream/multipath-tools.git] / kpartx / sun.c
1 /*
2  * Lifted from util-linux' partx sun.c
3  *
4  * Copyrights of the original file apply
5  * Copyright (c) 2007 Hannes Reinecke
6  */
7 #include "kpartx.h"
8 #include "byteorder.h"
9 #include <stdio.h>
10 #include <sys/types.h>
11 #include <time.h>               /* time_t */
12
13 #define SUN_DISK_MAGIC          0xDABE  /* Disk magic number */
14 #define SUN_DISK_MAXPARTITIONS  8
15
16 struct __attribute__ ((packed)) sun_raw_part {
17         u_int32_t       start_cylinder; /* where the part starts... */
18         u_int32_t       num_sectors;    /* ...and it's length */
19 };
20
21 struct __attribute__ ((packed)) sun_part_info {
22         u_int8_t        spare1;
23         u_int8_t        id;             /* Partition type */
24         u_int8_t        spare2;
25         u_int8_t        flags;          /* Partition flags */
26 };
27
28 struct __attribute__ ((packed)) sun_disk_label {
29         char            info[128];      /* Informative text string */
30         u_int8_t        spare0[14];
31         struct sun_part_info infos[SUN_DISK_MAXPARTITIONS];
32         u_int8_t        spare1[246];    /* Boot information etc. */
33         u_int16_t       rspeed;         /* Disk rotational speed */
34         u_int16_t       pcylcount;      /* Physical cylinder count */
35         u_int16_t       sparecyl;       /* extra sects per cylinder */
36         u_int8_t        spare2[4];      /* More magic... */
37         u_int16_t       ilfact;         /* Interleave factor */
38         u_int16_t       ncyl;           /* Data cylinder count */
39         u_int16_t       nacyl;          /* Alt. cylinder count */
40         u_int16_t       ntrks;          /* Tracks per cylinder */
41         u_int16_t       nsect;          /* Sectors per track */
42         u_int8_t        spare3[4];      /* Even more magic... */
43         struct sun_raw_part partitions[SUN_DISK_MAXPARTITIONS];
44         u_int16_t       magic;          /* Magic number */
45         u_int16_t       csum;           /* Label xor'd checksum */
46 };
47
48 /* Checksum Verification */
49 static int
50 sun_verify_checksum (struct sun_disk_label *label)
51 {
52         u_int16_t *ush = ((u_int16_t *)(label + 1)) - 1;
53         u_int16_t csum = 0;
54
55         while (ush >= (u_int16_t *)label)
56                 csum ^= *ush--;
57
58         return !csum;
59 }
60
61 int
62 read_sun_pt(int fd, struct slice all, struct slice *sp, unsigned int ns) {
63         struct sun_disk_label *l;
64         struct sun_raw_part *s;
65         unsigned int offset = all.start, end;
66         unsigned int i, j, n;
67         char *bp;
68
69         bp = getblock(fd, offset);
70         if (bp == NULL)
71                 return -1;
72
73         l = (struct sun_disk_label *) bp;
74         if(be16_to_cpu(l->magic) != SUN_DISK_MAGIC)
75                 return -1;
76
77         if (!sun_verify_checksum(l)) {
78                 fprintf(stderr, "Corrupted Sun disk label\n");
79                 return -1;
80         }
81
82         for(i=0, n=0; i<SUN_DISK_MAXPARTITIONS; i++) {
83                 s = &l->partitions[i];
84
85                 if (n < ns) {
86                         sp[n].start = offset +
87                                 be32_to_cpu(s->start_cylinder) * be16_to_cpu(l->nsect) * be16_to_cpu(l->ntrks);
88                         sp[n].size = be32_to_cpu(s->num_sectors);
89                         n++;
90                 } else {
91                         fprintf(stderr,
92                                 "sun_disklabel: too many slices\n");
93                         break;
94                 }
95         }
96         /*
97          * Convention has it that the SUN disklabel will always have
98          * the 'c' partition spanning the entire disk.
99          * So we have to check for contained slices.
100          */
101         for(i = 0; i < SUN_DISK_MAXPARTITIONS; i++) {
102                 if (sp[i].size == 0)
103                         continue;
104
105                 end = sp[i].start + sp[i].size;
106                 for(j = 0; j < SUN_DISK_MAXPARTITIONS; j ++) {
107                         if ( i == j )
108                                 continue;
109                         if (sp[j].size == 0)
110                                 continue;
111
112                         if (sp[i].start < sp[j].start) {
113                                 if (end > sp[j].start &&
114                                     end < sp[j].start + sp[j].size) {
115                                         /* Invalid slice */
116                                         fprintf(stderr,
117                                                 "sun_disklabel: slice %d overlaps with %d\n", i , j);
118                                         sp[i].size = 0;
119                                 }
120                         } else {
121                                 if (end <= sp[j].start + sp[j].size) {
122                                         sp[i].container = j + 1;
123                                 }
124                         }
125                 }
126         }
127         return n;
128 }