GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/fdisk/part.c Lines: 0 140 0.0 %
Date: 2016-12-06 Branches: 0 66 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: part.c,v 1.75 2015/11/26 08:15:07 tim Exp $	*/
2
3
/*
4
 * Copyright (c) 1997 Tobias Weingartner
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/disklabel.h>
21
22
#include <err.h>
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <string.h>
26
#include <uuid.h>
27
28
#include "disk.h"
29
#include "misc.h"
30
#include "part.h"
31
32
int	PRT_check_chs(struct prt *partn);
33
34
static const struct part_type {
35
	int	type;
36
	char	sname[14];
37
	char	guid[37];
38
} part_types[] = {
39
	{ 0x00, "unused      ", "00000000-0000-0000-0000-000000000000" },
40
	{ 0x01, "DOS FAT-12  ", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" },
41
	{ 0x02, "XENIX /     "},   /* XENIX / filesystem */
42
	{ 0x03, "XENIX /usr  "},   /* XENIX /usr filesystem */
43
	{ 0x04, "DOS FAT-16  ", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" },
44
	{ 0x05, "Extended DOS"},   /* Extended DOS */
45
	{ 0x06, "DOS > 32MB  ", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" },
46
	{ 0x07, "NTFS        ", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" },
47
	{ 0x08, "AIX fs      "},   /* AIX filesystem */
48
	{ 0x09, "AIX/Coherent"},   /* AIX boot partition or Coherent */
49
	{ 0x0A, "OS/2 Bootmgr"},   /* OS/2 Boot Manager or OPUS */
50
	{ 0x0B, "Win95 FAT-32", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" },
51
	{ 0x0C, "Win95 FAT32L", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" },
52
	{ 0x0E, "DOS FAT-16  ", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" },
53
	{ 0x0F, "Extended LBA"},   /* Extended DOS LBA-mapped */
54
	{ 0x10, "OPUS        "},   /* OPUS */
55
	{ 0x11, "OS/2 hidden ", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" },
56
	{ 0x12, "Compaq Diag."},   /* Compaq Diagnostics */
57
	{ 0x14, "OS/2 hidden ", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" },
58
	{ 0x16, "OS/2 hidden ", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" },
59
	{ 0x17, "OS/2 hidden ", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" },
60
	{ 0x18, "AST swap    "},   /* AST Windows swapfile */
61
	{ 0x19, "Willowtech  "},   /* Willowtech Photon coS */
62
	{ 0x1C, "ThinkPad Rec", "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" },
63
	{ 0x24, "NEC DOS     "},   /* NEC DOS */
64
	{ 0x27, "Win Recovery", "de94bba4-06d1-4d40-a16a-bfd50179d6ac" },
65
	{ 0x20, "Willowsoft  "},   /* Willowsoft OFS1 */
66
	{ 0x38, "Theos       "},   /* Theos */
67
	{ 0x39, "Plan 9      "},   /* Plan 9 */
68
	{ 0x40, "VENIX 286   "},   /* VENIX 286 or LynxOS */
69
	{ 0x41, "Lin/Minux DR"},   /* Linux/MINIX (sharing disk with DRDOS) or Personal RISC boot */
70
	{ 0x42, "LinuxSwap DR", "af9b60a0-1431-4f62-bc68-3311714a69ad" },
71
	{ 0x43, "Linux DR    "},   /* Linux native (sharing disk with DRDOS) */
72
	{ 0x4D, "QNX 4.2 Pri "},   /* QNX 4.2 Primary */
73
	{ 0x4E, "QNX 4.2 Sec "},   /* QNX 4.2 Secondary */
74
	{ 0x4F, "QNX 4.2 Ter "},   /* QNX 4.2 Tertiary */
75
	{ 0x50, "DM          "},   /* DM (disk manager) */
76
	{ 0x51, "DM          "},   /* DM6 Aux1 (or Novell) */
77
	{ 0x52, "CP/M or SysV"},   /* CP/M or Microport SysV/AT */
78
	{ 0x53, "DM          "},   /* DM6 Aux3 */
79
	{ 0x54, "Ontrack     "},   /* Ontrack */
80
	{ 0x55, "EZ-Drive    "},   /* EZ-Drive (disk manager) */
81
	{ 0x56, "Golden Bow  "},   /* Golden Bow (disk manager) */
82
	{ 0x5C, "Priam       "},   /* Priam Edisk (disk manager) */
83
	{ 0x61, "SpeedStor   "},   /* SpeedStor */
84
	{ 0x63, "ISC, HURD, *"},   /* ISC, System V/386, GNU HURD or Mach */
85
	{ 0x64, "NetWare 2.xx"},   /* Novell NetWare 2.xx */
86
	{ 0x65, "NetWare 3.xx"},   /* Novell NetWare 3.xx */
87
	{ 0x66, "NetWare 386 "},   /* Novell 386 NetWare */
88
	{ 0x67, "Novell      "},   /* Novell */
89
	{ 0x68, "Novell      "},   /* Novell */
90
	{ 0x69, "Novell      "},   /* Novell */
91
	{ 0x70, "DiskSecure  "},   /* DiskSecure Multi-Boot */
92
	{ 0x75, "PCIX        "},   /* PCIX */
93
	{ 0x7f, "ChromeKernel", "fe3a2a5d-4f32-41a7-b725-accc3285a309" },
94
	{ 0x80, "Minix (old) "},   /* Minix 1.1 ... 1.4a */
95
	{ 0x81, "Minix (new) "},   /* Minix 1.4b ... 1.5.10 */
96
	{ 0x82, "Linux swap  ", "0657fd6d-a4ab-43c4-84e5-0933c84b4f4f" },
97
	{ 0x83, "Linux files*", "0fc63daf-8483-4772-8e79-3d69d8477de4" },
98
	{ 0x84, "OS/2 hidden "},   /* OS/2 hidden C: drive */
99
	{ 0x85, "Linux ext.  "},   /* Linux extended */
100
	{ 0x86, "NT FAT VS   "},   /* NT FAT volume set */
101
	{ 0x87, "NTFS VS     "},   /* NTFS volume set or HPFS mirrored */
102
	{ 0x8E, "Linux LVM   ", "e6d6d379-f507-44c2-a23c-238f2a3df928" },
103
	{ 0x93, "Amoeba FS   "},   /* Amoeba filesystem */
104
	{ 0x94, "Amoeba BBT  "},   /* Amoeba bad block table */
105
	{ 0x99, "Mylex       "},   /* Mylex EISA SCSI */
106
	{ 0x9F, "BSDI        "},   /* BSDI BSD/OS */
107
	{ 0xA0, "NotebookSave"},   /* Phoenix NoteBIOS save-to-disk */
108
	{ 0xA5, "FreeBSD     ", "516e7cb4-6ecf-11d6-8ff8-00022d09712b" },
109
	{ 0xA6, "OpenBSD     ", "824cc7a0-36a8-11e3-890a-952519ad3f61" },
110
	{ 0xA7, "NEXTSTEP    "},   /* NEXTSTEP */
111
	{ 0xA8, "MacOS X     ", "55465300-0000-11aa-aa11-00306543ecac" },
112
	{ 0xA9, "NetBSD      ", "516e7cb4-6ecf-11d6-8ff8-00022d09712b" },
113
	{ 0xAB, "MacOS X boot", "426f6f74-0000-11aa-aa11-00306543ecac" },
114
	{ 0xAF, "MacOS X HFS+", "48465300-0000-11aa-aa11-00306543ecac" },
115
	{ 0xB7, "BSDI filesy*"},   /* BSDI BSD/386 filesystem */
116
	{ 0xB8, "BSDI swap   "},   /* BSDI BSD/386 swap */
117
	{ 0xBF, "Solaris     ", "6a85cf4d-1dd2-11b2-99a6-080020736631" },
118
	{ 0xC0, "CTOS        "},   /* CTOS */
119
	{ 0xC1, "DRDOSs FAT12"},   /* DRDOS/sec (FAT-12) */
120
	{ 0xC4, "DRDOSs < 32M"},   /* DRDOS/sec (FAT-16, < 32M) */
121
	{ 0xC6, "DRDOSs >=32M"},   /* DRDOS/sec (FAT-16, >= 32M) */
122
	{ 0xC7, "HPFS Disbled"},   /* Syrinx (Cyrnix?) or HPFS disabled */
123
	{ 0xDB, "CPM/C.DOS/C*"},   /* Concurrent CPM or C.DOS or CTOS */
124
	{ 0xDE, "Dell Maint  "},   /* Dell maintenance partition */
125
	{ 0xE1, "SpeedStor   "},   /* DOS access or SpeedStor 12-bit FAT extended partition */
126
	{ 0xE3, "SpeedStor   "},   /* DOS R/O or SpeedStor or Storage Dimensions */
127
	{ 0xE4, "SpeedStor   "},   /* SpeedStor 16-bit FAT extended partition < 1024 cyl. */
128
	{ 0xEB, "BeOS/i386   ", "42465331-3ba3-10f1-802a-4861696b7521" },
129
	{ 0xEE, "EFI GPT     "},   /* EFI Protective Partition */
130
	{ 0xEF, "EFI Sys     ", "c12a7328-f81f-11d2-ba4b-00a0c93ec93b" },
131
	{ 0xF1, "SpeedStor   "},   /* SpeedStor or Storage Dimensions */
132
	{ 0xF2, "DOS 3.3+ Sec"},   /* DOS 3.3+ Secondary */
133
	{ 0xF4, "SpeedStor   "},   /* SpeedStor >1024 cyl. or LANstep or IBM PS/2 IML */
134
	{ 0xFF, "Xenix BBT   "},   /* Xenix Bad Block Table */
135
};
136
137
void
138
PRT_printall(void)
139
{
140
	int i, idrows;
141
142
	idrows = ((sizeof(part_types)/sizeof(struct part_type))+3)/4;
143
144
	printf("Choose from the following Partition id values:\n");
145
	for (i = 0; i < idrows; i++) {
146
		printf("%02X %s   %02X %s   %02X %s",
147
		    part_types[i].type, part_types[i].sname,
148
		    part_types[i+idrows].type, part_types[i+idrows].sname,
149
		    part_types[i+idrows*2].type, part_types[i+idrows*2].sname);
150
		if ((i+idrows*3) < (sizeof(part_types)/sizeof(struct part_type))) {
151
			printf("   %02X %s\n",
152
			    part_types[i+idrows*3].type,
153
			    part_types[i+idrows*3].sname);
154
		} else
155
			printf( "\n" );
156
	}
157
}
158
159
const char *
160
PRT_ascii_id(int id)
161
{
162
	static char unknown[] = "<Unknown ID>";
163
	int i;
164
165
	for (i = 0; i < sizeof(part_types)/sizeof(struct part_type); i++) {
166
		if (part_types[i].type == id)
167
			return (part_types[i].sname);
168
	}
169
170
	return (unknown);
171
}
172
173
void
174
PRT_parse(struct dos_partition *prt, off_t offset, off_t reloff,
175
    struct prt *partn)
176
{
177
	off_t off;
178
	u_int32_t t;
179
180
	partn->flag = prt->dp_flag;
181
	partn->shead = prt->dp_shd;
182
183
	partn->ssect = (prt->dp_ssect) & 0x3F;
184
	partn->scyl = ((prt->dp_ssect << 2) & 0xFF00) | prt->dp_scyl;
185
186
	partn->id = prt->dp_typ;
187
	partn->ehead = prt->dp_ehd;
188
	partn->esect = (prt->dp_esect) & 0x3F;
189
	partn->ecyl = ((prt->dp_esect << 2) & 0xFF00) | prt->dp_ecyl;
190
191
	if ((partn->id == DOSPTYP_EXTEND) || (partn->id == DOSPTYP_EXTENDL))
192
		off = reloff;
193
	else
194
		off = offset;
195
196
#if 0 /* XXX */
197
	partn->bs = letoh32(prt->dp_start) + off;
198
	partn->ns = letoh32(prt->dp_size);
199
#else
200
	memcpy(&t, &prt->dp_start, sizeof(u_int32_t));
201
	partn->bs = letoh32(t) + off;
202
	memcpy(&t, &prt->dp_size, sizeof(u_int32_t));
203
	partn->ns = letoh32(t);
204
#endif
205
206
	PRT_fix_CHS(partn);
207
}
208
209
int
210
PRT_check_chs(struct prt *partn)
211
{
212
	if ( (partn->shead > 255) ||
213
		(partn->ssect >63) ||
214
		(partn->scyl > 1023) ||
215
		(partn->ehead >255) ||
216
		(partn->esect >63) ||
217
		(partn->ecyl > 1023) )
218
	{
219
		return (0);
220
	}
221
	return (1);
222
}
223
224
void
225
PRT_make(struct prt *partn, off_t offset, off_t reloff,
226
    struct dos_partition *prt)
227
{
228
	off_t off;
229
	u_int32_t ecsave, scsave;
230
	u_int64_t t;
231
232
	/* Save (and restore below) cylinder info we may fiddle with. */
233
	scsave = partn->scyl;
234
	ecsave = partn->ecyl;
235
236
	if ((partn->scyl > 1023) || (partn->ecyl > 1023)) {
237
		partn->scyl = (partn->scyl > 1023)? 1023: partn->scyl;
238
		partn->ecyl = (partn->ecyl > 1023)? 1023: partn->ecyl;
239
	}
240
	if ((partn->id == DOSPTYP_EXTEND) || (partn->id == DOSPTYP_EXTENDL))
241
		off = reloff;
242
	else
243
		off = offset;
244
245
	if (PRT_check_chs(partn)) {
246
		prt->dp_shd = partn->shead & 0xFF;
247
		prt->dp_ssect = (partn->ssect & 0x3F) |
248
		    ((partn->scyl & 0x300) >> 2);
249
		prt->dp_scyl = partn->scyl & 0xFF;
250
		prt->dp_ehd = partn->ehead & 0xFF;
251
		prt->dp_esect = (partn->esect & 0x3F) |
252
		    ((partn->ecyl & 0x300) >> 2);
253
		prt->dp_ecyl = partn->ecyl & 0xFF;
254
	} else {
255
		/* should this really keep flag, id and set others to 0xff? */
256
		memset(prt, 0xFF, sizeof(*prt));
257
		printf("Warning CHS values out of bounds only saving "
258
		    "LBA values\n");
259
	}
260
261
	prt->dp_flag = partn->flag & 0xFF;
262
	prt->dp_typ = partn->id & 0xFF;
263
264
	t = htole64(partn->bs - off);
265
	memcpy(&prt->dp_start, &t, sizeof(u_int32_t));
266
	t = htole64(partn->ns);
267
	memcpy(&prt->dp_size, &t, sizeof(u_int32_t));
268
269
	partn->scyl = scsave;
270
	partn->ecyl = ecsave;
271
}
272
273
void
274
PRT_print(int num, struct prt *partn, char *units)
275
{
276
	const int secsize = unit_types[SECTORS].conversion;
277
	double size;
278
	int i;
279
280
	i = unit_lookup(units);
281
282
	if (partn == NULL) {
283
		printf("            Starting         Ending    "
284
		    "     LBA Info:\n");
285
		printf(" #: id      C   H   S -      C   H   S "
286
		    "[       start:        size ]\n");
287
		printf("---------------------------------------"
288
		    "----------------------------------------\n");
289
	} else {
290
		size = ((double)partn->ns * secsize) / unit_types[i].conversion;
291
		printf("%c%1d: %.2X %6u %3u %3u - %6u %3u %3u "
292
		    "[%12llu:%12.0f%s] %s\n",
293
		    (partn->flag == DOSACTIVE)?'*':' ',
294
		    num, partn->id,
295
		    partn->scyl, partn->shead, partn->ssect,
296
		    partn->ecyl, partn->ehead, partn->esect,
297
		    partn->bs, size,
298
		    unit_types[i].abbr,
299
		    PRT_ascii_id(partn->id));
300
	}
301
}
302
303
void
304
PRT_fix_BN(struct prt *part, int pn)
305
{
306
	u_int32_t spt, tpc, spc;
307
	u_int32_t start = 0;
308
	u_int32_t end = 0;
309
310
	/* Zero out entry if not used */
311
	if (part->id == DOSPTYP_UNUSED) {
312
		memset(part, 0, sizeof(*part));
313
		return;
314
	}
315
316
	/* Disk geometry. */
317
	spt = disk.sectors;
318
	tpc = disk.heads;
319
	spc = spt * tpc;
320
321
	start += part->scyl * spc;
322
	start += part->shead * spt;
323
	start += part->ssect - 1;
324
325
	end += part->ecyl * spc;
326
	end += part->ehead * spt;
327
	end += part->esect - 1;
328
329
	/* XXX - Should handle this... */
330
	if (start > end)
331
		warnx("Start of partition #%d after end!", pn);
332
333
	part->bs = start;
334
	part->ns = (end - start) + 1;
335
}
336
337
void
338
PRT_fix_CHS(struct prt *part)
339
{
340
	u_int32_t spt, tpc, spc;
341
	u_int32_t start, end, size;
342
	u_int32_t cyl, head, sect;
343
344
	/* Zero out entry if not used */
345
	if (part->id == DOSPTYP_UNUSED || part->ns == 0) {
346
		memset(part, 0, sizeof(*part));
347
		return;
348
	}
349
350
	/* Disk geometry. */
351
	spt = disk.sectors;
352
	tpc = disk.heads;
353
	spc = spt * tpc;
354
355
	start = part->bs;
356
	size = part->ns;
357
	end = (start + size) - 1;
358
359
	/* Figure out starting CHS values */
360
	cyl = (start / spc); start -= (cyl * spc);
361
	head = (start / spt); start -= (head * spt);
362
	sect = (start + 1);
363
364
	part->scyl = cyl;
365
	part->shead = head;
366
	part->ssect = sect;
367
368
	/* Figure out ending CHS values */
369
	cyl = (end / spc); end -= (cyl * spc);
370
	head = (end / spt); end -= (head * spt);
371
	sect = (end + 1);
372
373
	part->ecyl = cyl;
374
	part->ehead = head;
375
	part->esect = sect;
376
}
377
378
char *
379
PRT_uuid_to_typename(struct uuid *uuid)
380
{
381
	static char partition_type[37];	/* Room for a GUID if needed. */
382
	char *uuidstr = NULL;
383
	int i, entries, status;
384
385
	memset(partition_type, 0, sizeof(partition_type));
386
387
	uuid_to_string(uuid, &uuidstr, &status);
388
	if (status != uuid_s_ok)
389
		goto done;
390
391
	entries = sizeof(part_types) / sizeof(struct part_type);
392
393
	for (i = 0; i < entries; i++) {
394
		if (memcmp(part_types[i].guid, uuidstr,
395
		    sizeof(part_types[i].guid)) == 0)
396
			break;
397
	}
398
399
	if (i < entries)
400
		strlcpy(partition_type, part_types[i].sname,
401
		    sizeof(partition_type));
402
	else
403
		strlcpy(partition_type, uuidstr, sizeof(partition_type));
404
405
done:
406
	free(uuidstr);
407
408
	return (partition_type);
409
}
410
411
int
412
PRT_uuid_to_type(struct uuid *uuid)
413
{
414
	char *uuidstr;
415
	int entries, i, status, type;
416
417
	type = 0;
418
419
	uuid_to_string(uuid, &uuidstr, &status);
420
	if (status != uuid_s_ok)
421
		goto done;
422
423
	entries = sizeof(part_types) / sizeof(struct part_type);
424
	for (i = 0; i < entries; i++) {
425
		if (memcmp(part_types[i].guid, uuidstr,
426
		    sizeof(part_types[i].guid)) == 0) {
427
			type = part_types[i].type;
428
			break;
429
		}
430
	}
431
432
done:
433
	free(uuidstr);
434
	return (type);
435
}
436
437
struct uuid *
438
PRT_type_to_uuid(int type)
439
{
440
	static struct uuid guid;
441
	int i, entries, status = uuid_s_ok;
442
443
	memset(&guid, 0, sizeof(guid));
444
445
	entries = sizeof(part_types) / sizeof(struct part_type);
446
447
	for (i = 0; i < entries; i++) {
448
		if (part_types[i].type == type)
449
			break;
450
	}
451
	if (i < entries)
452
		uuid_from_string(part_types[i].guid, &guid, &status);
453
	if (i == entries || status != uuid_s_ok)
454
		uuid_from_string(part_types[0].guid, &guid, &status);
455
456
	return (&guid);
457
}