Bump to 0.9.7
[platform/upstream/multipath-tools.git] / kpartx / bsd.c
1 #include "kpartx.h"
2 #include <stdio.h>
3
4 #define BSD_LABEL_OFFSET        64
5 #define BSD_DISKMAGIC   (0x82564557UL)  /* The disk magic number */
6 #define XBSD_MAXPARTITIONS      16
7 #define BSD_FS_UNUSED           0
8
9 struct bsd_disklabel {
10         unsigned int    d_magic;        /* the magic number */
11         short int       d_type;         /* drive type */
12         short int       d_subtype;      /* controller/d_type specific */
13         char    d_typename[16];         /* type name, e.g. "eagle" */
14         char    d_packname[16];         /* pack identifier */
15         unsigned int    d_secsize;      /* # of bytes per sector */
16         unsigned int    d_nsectors;     /* # of data sectors per track */
17         unsigned int    d_ntracks;      /* # of tracks per cylinder */
18         unsigned int    d_ncylinders;   /* # of data cylinders per unit */
19         unsigned int    d_secpercyl;    /* # of data sectors per cylinder */
20         unsigned int    d_secperunit;   /* # of data sectors per unit */
21         unsigned short  d_sparespertrack;/* # of spare sectors per track */
22         unsigned short  d_sparespercyl; /* # of spare sectors per cylinder */
23         unsigned int    d_acylinders;   /* # of alt. cylinders per unit */
24         unsigned short  d_rpm;          /* rotational speed */
25         unsigned short  d_interleave;   /* hardware sector interleave */
26         unsigned short  d_trackskew;    /* sector 0 skew, per track */
27         unsigned short  d_cylskew;      /* sector 0 skew, per cylinder */
28         unsigned int    d_headswitch;   /* head switch time, usec */
29         unsigned int    d_trkseek;      /* track-to-track seek, usec */
30         unsigned int    d_flags;        /* generic flags */
31         unsigned int    d_drivedata[5]; /* drive-type specific information */
32         unsigned int    d_spare[5];     /* reserved for future use */
33         unsigned int    d_magic2;       /* the magic number (again) */
34         unsigned short  d_checksum;     /* xor of data incl. partitions */
35
36                         /* filesystem and partition information: */
37         unsigned short  d_npartitions;  /* number of partitions in following */
38         unsigned int    d_bbsize;       /* size of boot area at sn0, bytes */
39         unsigned int    d_sbsize;       /* max size of fs superblock, bytes */
40         struct  bsd_partition {         /* the partition table */
41                 unsigned int    p_size;   /* number of sectors in partition */
42                 unsigned int    p_offset; /* starting sector */
43                 unsigned int    p_fsize;  /* filesystem basic fragment size */
44                 unsigned char   p_fstype; /* filesystem type, see below */
45                 unsigned char   p_frag;   /* filesystem fragments per block */
46                 unsigned short  p_cpg;    /* filesystem cylinders per group */
47         } d_partitions[XBSD_MAXPARTITIONS];/* actually may be more */
48 };
49
50 int
51 read_bsd_pt(int fd, struct slice all, struct slice *sp, unsigned int ns) {
52         struct bsd_disklabel *l;
53         struct bsd_partition *p;
54         unsigned int offset = all.start, end;
55         int max_partitions;
56         char *bp;
57         unsigned int n = 0, i, j;
58
59         bp = getblock(fd, offset+1);    /* 1 sector suffices */
60         if (bp == NULL)
61                 return -1;
62
63         l = (struct bsd_disklabel *) bp;
64         if (l->d_magic != BSD_DISKMAGIC) {
65                 /*
66                  * BSD disklabels can also start 64 bytes offset from the
67                  * start of the first sector
68                  */
69                 bp = getblock(fd, offset);
70                 if (bp == NULL)
71                         return -1;
72
73                 l = (struct bsd_disklabel *)(bp + 64);
74                 if (l->d_magic != BSD_DISKMAGIC)
75                         return -1;
76         }
77
78         max_partitions = 16;
79         if (l->d_npartitions < max_partitions)
80                 max_partitions = l->d_npartitions;
81         for (p = l->d_partitions; p - l->d_partitions <  max_partitions; p++) {
82                 if (p->p_fstype == BSD_FS_UNUSED)
83                         /* nothing */;
84                 else if (n < ns) {
85                         sp[n].start = p->p_offset;
86                         sp[n].size = p->p_size;
87                         n++;
88                 } else {
89                         fprintf(stderr,
90                                 "bsd_partition: too many slices\n");
91                         break;
92                 }
93         }
94         /*
95          * Convention has it that the bsd disklabel will always have
96          * the 'c' partition spanning the entire disk.
97          * So we have to check for contained slices.
98          */
99         for(i = 0; i < n; i++) {
100                 if (sp[i].size == 0)
101                         continue;
102
103                 end = sp[i].start + sp[i].size;
104                 for(j = 0; j < n; j ++) {
105                         if ( i == j )
106                                 continue;
107                         if (sp[j].size == 0)
108                                 continue;
109
110                         if (sp[i].start < sp[j].start) {
111                                 if (end > sp[j].start &&
112                                     end < sp[j].start + sp[j].size) {
113                                         /* Invalid slice */
114                                         fprintf(stderr,
115                                                 "bsd_disklabel: slice %d overlaps with %d\n", i , j);
116                                         sp[i].size = 0;
117                                 }
118                         } else {
119                                 if (end <= sp[j].start + sp[j].size) {
120                                         sp[i].container = j + 1;
121                                 }
122                         }
123                 }
124         }
125         return n;
126 }