Upload Tizen:Base source
[framework/base/util-linux-ng.git] / lib / pttype.c
1 /*
2  * Based on libdisk from xfsprogs and Linux fdisk.
3  *
4  * Copyright (c) 2000-2001 Silicon Graphics, Inc.
5  * Copyright (C) 2009 Karel Zak <kzak@redhat.com>
6  */
7 #include <stdio.h>
8 #include <fcntl.h>
9 #include <unistd.h>
10 #include <sys/types.h>
11 #include <netinet/in.h>
12 #include <stdlib.h>
13
14 #include "blkdev.h"
15
16 /* we need to read two sectors, beacuse BSD label offset is 512 */
17 #define PTTYPE_BUFSIZ   (2 * DEFAULT_SECTOR_SIZE)       /* 1024 */
18
19 /*
20  * SGI
21  */
22 struct sgi_device_parameter { /* 48 bytes */
23         unsigned char  skew;
24         unsigned char  gap1;
25         unsigned char  gap2;
26         unsigned char  sparecyl;
27         unsigned short pcylcount;
28         unsigned short head_vol0;
29         unsigned short ntrks;   /* tracks in cyl 0 or vol 0 */
30         unsigned char  cmd_tag_queue_depth;
31         unsigned char  unused0;
32         unsigned short unused1;
33         unsigned short nsect;   /* sectors/tracks in cyl 0 or vol 0 */
34         unsigned short bytes;
35         unsigned short ilfact;
36         unsigned int   flags;           /* controller flags */
37         unsigned int   datarate;
38         unsigned int   retries_on_error;
39         unsigned int   ms_per_word;
40         unsigned short xylogics_gap1;
41         unsigned short xylogics_syncdelay;
42         unsigned short xylogics_readdelay;
43         unsigned short xylogics_gap2;
44         unsigned short xylogics_readgate;
45         unsigned short xylogics_writecont;
46 };
47
48 #define SGI_VOLHDR      0x00
49 /* 1 and 2 were used for drive types no longer supported by SGI */
50 #define SGI_SWAP        0x03
51 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
52 #define SGI_VOLUME      0x06
53 #define SGI_EFS         0x07
54 #define SGI_LVOL        0x08
55 #define SGI_RLVOL       0x09
56 #define SGI_XFS         0x0a
57 #define SGI_XFSLOG      0x0b
58 #define SGI_XLV         0x0c
59 #define SGI_XVM         0x0d
60 #define ENTIRE_DISK     SGI_VOLUME
61 /*
62  * controller flags
63  */
64 #define SECTOR_SLIP     0x01
65 #define SECTOR_FWD      0x02
66 #define TRACK_FWD       0x04
67 #define TRACK_MULTIVOL  0x08
68 #define IGNORE_ERRORS   0x10
69 #define RESEEK          0x20
70 #define CMDTAGQ_ENABLE  0x40
71
72 struct sgi_volume_header {
73         unsigned int   magic;            /* expect SGI_LABEL_MAGIC */
74         unsigned short boot_part;        /* active boot partition */
75         unsigned short swap_part;        /* active swap partition */
76         unsigned char  boot_file[16];    /* name of the bootfile */
77         struct sgi_device_parameter devparam;   /*  1 * 48 bytes */
78         struct volume_directory {               /* 15 * 16 bytes */
79                 unsigned char vol_file_name[8]; /* a character array */
80                 unsigned int  vol_file_start;   /* number of logical block */
81                 unsigned int  vol_file_size;    /* number of bytes */
82         } directory[15];
83         struct sgi_partition {                  /* 16 * 12 bytes */
84                 unsigned int num_sectors;       /* number of blocks */
85                 unsigned int start_sector;      /* must be cylinder aligned */
86                 unsigned int id;
87         } partitions[16];
88         unsigned int   csum;
89         unsigned int   fillbytes;
90 };
91
92 #define SGI_LABEL_MAGIC         0x0be5a941
93
94 static uint32_t
95 twos_complement_32bit_sum(u_int32_t *base, int size)
96 {
97         int i;
98         u_int32_t sum = 0;
99
100         size = size / sizeof(u_int32_t);
101         for (i = 0; i < size; i++)
102                 sum = sum - ntohl(base[i]);
103         return sum;
104 }
105
106 static int
107 sgi_parttable(unsigned char *base)
108 {
109         u_int32_t csum;
110         struct sgi_volume_header *vh = (struct sgi_volume_header *) base;
111
112         if (ntohl(vh->magic) != SGI_LABEL_MAGIC)
113                 return 0;
114         csum = twos_complement_32bit_sum((uint32_t *)vh,
115                                 sizeof(struct sgi_volume_header));
116         return !csum;
117 }
118
119 /*
120  * DOS
121  */
122 static int
123 dos_parttable(unsigned char *base)
124 {
125         return (base[510] == 0x55 && base[511] == 0xaa);
126 }
127
128 /*
129  * AIX
130  */
131 typedef struct {
132         unsigned int   magic;        /* expect AIX_LABEL_MAGIC */
133         /* ... */
134 } aix_partition;
135
136 #define AIX_LABEL_MAGIC         0xc9c2d4c1
137 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
138 #define aixlabel(x) ((aix_partition *)x)
139
140 static int
141 aix_parttable(unsigned char *base)
142 {
143         return (aixlabel(base)->magic == AIX_LABEL_MAGIC ||
144                 aixlabel(base)->magic == AIX_LABEL_MAGIC_SWAPPED);
145 }
146
147 /*
148  * SUN
149  */
150 typedef struct {
151         unsigned char info[128];   /* Informative text string */
152         unsigned char spare0[14];
153         struct sun_info {
154                 unsigned char spare1;
155                 unsigned char id;
156                 unsigned char spare2;
157                 unsigned char flags;
158         } infos[8];
159         unsigned char spare1[246]; /* Boot information etc. */
160         unsigned short rspeed;     /* Disk rotational speed */
161         unsigned short pcylcount;  /* Physical cylinder count */
162         unsigned short sparecyl;   /* extra sects per cylinder */
163         unsigned char spare2[4];   /* More magic... */
164         unsigned short ilfact;     /* Interleave factor */
165         unsigned short ncyl;       /* Data cylinder count */
166         unsigned short nacyl;      /* Alt. cylinder count */
167         unsigned short ntrks;      /* Tracks per cylinder */
168         unsigned short nsect;      /* Sectors per track */
169         unsigned char spare3[4];   /* Even more magic... */
170         struct sun_partition {
171                 u_int32_t start_cylinder;
172                 u_int32_t num_sectors;
173         } partitions[8];
174         unsigned short magic;      /* Magic number */
175         unsigned short csum;       /* Label xor'd checksum */
176 } sun_partition;
177
178 #define SUN_LABEL_MAGIC          0xDABE
179 #define SUN_LABEL_MAGIC_SWAPPED  0xBEDA
180 #define sunlabel(x) ((sun_partition *)x)
181
182 static int
183 sun_parttable(unsigned char *base)
184 {
185         unsigned short *ush;
186         int csum = 0;
187
188         if (sunlabel(base)->magic != SUN_LABEL_MAGIC &&
189             sunlabel(base)->magic != SUN_LABEL_MAGIC_SWAPPED)
190                 return csum;
191         ush = ((unsigned short *) (sunlabel(base) + 1)) - 1;
192         while (ush >= (unsigned short *)sunlabel(base))
193                 csum ^= *ush--;
194         return !csum;
195 }
196
197 /*
198  * MAC
199  */
200 typedef struct {
201         unsigned short magic;
202         /* ... */
203 } mac_partition;
204
205 #define MAC_LABEL_MAGIC         0x4552
206 #define MAC_PARTITION_MAGIC     0x504d
207 #define MAC_OLD_PARTITION_MAGIC 0x5453
208 #define maclabel(x) ((mac_partition *)x)
209
210 static int
211 mac_parttable(unsigned char *base)
212 {
213         return (ntohs(maclabel(base)->magic) == MAC_LABEL_MAGIC ||
214                 ntohs(maclabel(base)->magic) == MAC_PARTITION_MAGIC ||
215                 ntohs(maclabel(base)->magic) == MAC_OLD_PARTITION_MAGIC);
216 }
217
218 /*
219  * BSD subpartitions listed in a disklabel, under a dos-like partition.
220  */
221 #define BSD_DISKMAGIC           0x82564557UL            /* The disk magic number */
222 #define BSD_DISKMAGIC_SWAPED    0x57455682UL
223 struct bsd_disklabel {
224         uint32_t        magic;          /* the magic number */
225         /* ... */
226 };
227
228 static int
229 bsd_parttable(unsigned char *base)
230 {
231         struct bsd_disklabel *l = (struct bsd_disklabel *)
232                                         (base + (DEFAULT_SECTOR_SIZE * 1));
233
234         return (l->magic == BSD_DISKMAGIC || l->magic == BSD_DISKMAGIC_SWAPED);
235 }
236
237 const char *
238 get_pt_type_fd(int fd)
239 {
240         char    *type = NULL;
241         unsigned char   buf[PTTYPE_BUFSIZ];
242
243         if (read(fd, buf, PTTYPE_BUFSIZ) != PTTYPE_BUFSIZ)
244                 ;
245         else {
246                 if (sgi_parttable(buf))
247                         type = "SGI";
248                 else if (sun_parttable(buf))
249                         type = "Sun";
250                 else if (aix_parttable(buf))
251                         type = "AIX";
252                 else if (dos_parttable(buf))
253                         type = "DOS";
254                 else if (mac_parttable(buf))
255                         type = "Mac";
256                 else if (bsd_parttable(buf))
257                         type = "BSD";
258         }
259         return type;
260 }
261
262 const char *
263 get_pt_type(const char *device)
264 {
265         int fd;
266         const char *type;
267
268         fd = open(device, O_RDONLY);
269         if (fd == -1)
270                 return NULL;
271         type = get_pt_type_fd(fd);
272         close(fd);
273         return type;
274 }
275
276 #ifdef TEST_PROGRAM
277 int
278 main(int argc, char **argv)
279 {
280         const char *type;
281
282         if (argc < 2) {
283                 fprintf(stderr, "usage: %s <device>\n", argv[0]);
284                 exit(EXIT_FAILURE);
285         }
286
287         type = get_pt_type(argv[1]);
288         if (type)
289                 printf("Partition type: %s\n", type);
290         exit(EXIT_SUCCESS);
291 }
292 #endif