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