Coverage Report

Created: 2025-11-16 06:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/sleuthkit/tsk/vs/dos.c
Line
Count
Source
1
/*
2
 * The Sleuth Kit
3
 *
4
 * Brian Carrier [carrier <at> sleuthkit [dot] org]
5
 * Copyright (c) 2006-2011 Brian Carrier, Basis Technology.  All rights reserved
6
 * Copyright (c) 2003-2005 Brian Carrier.  All rights reserved
7
 *
8
 * This software is distributed under the Common Public License 1.0
9
 */
10
11
/** \file dos.c
12
 * Contains the internal functions to process DOS Partition tables
13
 */
14
15
#include "tsk_vs_i.h"
16
#include "tsk_dos.h"
17
18
19
/* Check the extended partition flags */
20
#define dos_is_ext(x) \
21
15.9k
  ((((x) == 0x05) || ((x) == 0x0F) || ((x) == 0x85)) ? 1 : 0)
22
23
/*
24
 * dos_get_desc
25
 *
26
 * Return a buffer with a string description of the partition type
27
 *
28
 * From: http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
29
 */
30
static char *
31
dos_get_desc(uint8_t ptype)
32
15.5k
{
33
31.1k
#define DESC_LEN 64
34
15.5k
    char *str = tsk_malloc(DESC_LEN);
35
15.5k
    if (str == NULL)
36
0
        return "";
37
38
15.5k
    switch (ptype) {
39
557
    case 0x00:
40
557
        snprintf(str, DESC_LEN, "Empty (0x00)");
41
557
        break;
42
86
    case 0x01:
43
86
        snprintf(str, DESC_LEN, "DOS FAT12 (0x01)");
44
86
        break;
45
69
    case 0x02:
46
69
        snprintf(str, DESC_LEN, "XENIX root (0x02)");
47
69
        break;
48
47
    case 0x03:
49
47
        snprintf(str, DESC_LEN, "XENIX /usr (0x03)");
50
47
        break;
51
90
    case 0x04:
52
151
    case 0x06:
53
151
        snprintf(str, DESC_LEN, "DOS FAT16 (0x%.2x)", ptype);
54
151
        break;
55
3.82k
    case 0x05:
56
3.82k
        snprintf(str, DESC_LEN, "DOS Extended (0x05)");
57
3.82k
        break;
58
58
    case 0x07:
59
58
        snprintf(str, DESC_LEN, "NTFS / exFAT (0x07)");
60
58
        break;
61
57
    case 0x08:
62
57
        snprintf(str, DESC_LEN, "AIX Boot (0x08)");
63
57
        break;
64
64
    case 0x09:
65
64
        snprintf(str, DESC_LEN, "AIX Data (0x09)");
66
64
        break;
67
64
    case 0x0a:
68
64
        snprintf(str, DESC_LEN, "OS/2 Boot Manager (0x0a)");
69
64
        break;
70
        /*
71
           case 0x0a:
72
           snprintf(str, DESC_LEN, "Coherent swap (0x0a)");
73
           break;
74
           case 0x0a:
75
           snprintf(str, DESC_LEN, "OPUS (0x0a)");
76
           break;
77
         */
78
50
    case 0x0b:
79
108
    case 0x0c:
80
108
        snprintf(str, DESC_LEN, "Win95 FAT32 (0x%.2x)", ptype);
81
108
        break;
82
58
    case 0x0e:
83
58
        snprintf(str, DESC_LEN, "Win95 FAT16 (0x0e)");
84
58
        break;
85
757
    case 0x0f:
86
757
        snprintf(str, DESC_LEN, "Win95 Extended (0x0f)");
87
757
        break;
88
75
    case 0x10:
89
75
        snprintf(str, DESC_LEN, "OPUS (0x10)");
90
75
        break;
91
56
    case 0x11:
92
56
        snprintf(str, DESC_LEN, "DOS FAT12 Hidden (0x11)");
93
56
        break;
94
47
    case 0x12:
95
47
        snprintf(str, DESC_LEN, "Hibernation (0x12)");
96
47
        break;
97
73
    case 0x14:
98
121
    case 0x16:
99
121
        snprintf(str, DESC_LEN, "DOS FAT16 Hidden (0x%.2x)", ptype);
100
121
        break;
101
40
    case 0x17:
102
40
        snprintf(str, DESC_LEN, "Hidden IFS/HPFS (0x17)");
103
40
        break;
104
63
    case 0x18:
105
63
        snprintf(str, DESC_LEN, "AST SmartSleep (0x18)");
106
63
        break;
107
62
    case 0x19:
108
115
    case 0x1b:
109
161
    case 0x1c:
110
161
        snprintf(str, DESC_LEN, "Win95 FAT32 Hidden (0x%.2x)", ptype);
111
161
        break;
112
44
    case 0x1e:
113
44
        snprintf(str, DESC_LEN, "Win95 FAT16 Hidden (0x1e)");
114
44
        break;
115
46
    case 0x20:
116
89
    case 0x22:
117
145
    case 0x7e:
118
191
    case 0x7f:
119
240
    case 0xed:
120
284
    case 0xf7:
121
284
        snprintf(str, DESC_LEN, "Unused (0x%.2x)", ptype);
122
284
        break;
123
51
    case 0x21:
124
95
    case 0x23:
125
169
    case 0x26:
126
232
    case 0x31:
127
281
    case 0x33:
128
319
    case 0x34:
129
370
    case 0x36:
130
426
    case 0x71:
131
481
    case 0x73:
132
522
    case 0x76:
133
566
    case 0xf3:
134
566
        snprintf(str, DESC_LEN, "Reserved (0x%.2x)", ptype);
135
566
        break;
136
40
    case 0x24:
137
40
        snprintf(str, DESC_LEN, "NEC DOS 3.x (0x24)");
138
40
        break;
139
47
    case 0x32:
140
47
        snprintf(str, DESC_LEN, "NOS (0x32)");
141
47
        break;
142
55
    case 0x35:
143
55
        snprintf(str, DESC_LEN, "JFS on OS/2 or eCS  (0x35)");
144
55
        break;
145
41
    case 0x38:
146
41
        snprintf(str, DESC_LEN, "THEOS v3.2 2gb (0x38)");
147
41
        break;
148
50
    case 0x39:
149
50
        snprintf(str, DESC_LEN, "THEOS v4 Spanned (0x39)");
150
50
        break;
151
        /*
152
           case 0x39:
153
           snprintf(str, DESC_LEN, "Plan 9 (0x39)");
154
           break;
155
         */
156
52
    case 0x3a:
157
52
        snprintf(str, DESC_LEN, "THEOS v4 4gb (0x3a)");
158
52
        break;
159
46
    case 0x3b:
160
46
        snprintf(str, DESC_LEN, "THEOS v4 Extended (0x3b)");
161
46
        break;
162
39
    case 0x3c:
163
39
        snprintf(str, DESC_LEN, "PartitionMagic Recovery (0x3c)");
164
39
        break;
165
45
    case 0x3d:
166
45
        snprintf(str, DESC_LEN, "Hidden NetWare (0x3d)");
167
45
        break;
168
63
    case 0x40:
169
63
        snprintf(str, DESC_LEN, "Venix 80286 (0x40)");
170
63
        break;
171
57
    case 0x41:
172
57
        snprintf(str, DESC_LEN,
173
57
            "Linux/MINIX (Sharing Disk with DR-DOS) (0x41)");
174
57
        break;
175
        /*
176
           case 0x41:
177
           snprintf(str, DESC_LEN, "Personal RISC Boot (0x41)");
178
           break;
179
           case 0x41:
180
           snprintf(str, DESC_LEN, "PPC PReP Boot (0x41)");
181
           break;
182
         */
183
45
    case 0x42:
184
45
        snprintf(str, DESC_LEN, "Win LVM / Secure FS (0x42)");
185
45
        break;
186
38
    case 0x43:
187
38
        snprintf(str, DESC_LEN,
188
38
            "Linux Native (Sharing Disk with DR-DOS) (0x43)");
189
38
        break;
190
44
    case 0x44:
191
44
        snprintf(str, DESC_LEN, "GoBack (0x44)");
192
44
        break;
193
43
    case 0x45:
194
43
        snprintf(str, DESC_LEN, "Boot-US Boot Manager (0x45)");
195
43
        break;
196
        /*
197
           case 0x45:
198
           snprintf(str, DESC_LEN, "Priam (0x45)");
199
           break;
200
           case 0x45:
201
           snprintf(str, DESC_LEN, "EUMEL/Elan  (0x45)");
202
           break;
203
         */
204
113
    case 0x46:
205
113
        snprintf(str, DESC_LEN, "EUMEL/Elan  (0x46)");
206
113
        break;
207
56
    case 0x47:
208
56
        snprintf(str, DESC_LEN, "EUMEL/Elan  (0x47)");
209
56
        break;
210
42
    case 0x48:
211
42
        snprintf(str, DESC_LEN, "EUMEL/Elan  (0x48)");
212
42
        break;
213
52
    case 0x4a:
214
52
        snprintf(str, DESC_LEN,
215
52
            "Mark Aitchison's ALFS/THIN Lightweight Filesystem (0x4a)");
216
52
        break;
217
        /*case 0x4a:
218
           snprintf(str, DESC_LEN, "AdaOS Aquila (0x4a)");
219
           break; */
220
44
    case 0x4c:
221
44
        snprintf(str, DESC_LEN, "Oberon (0x4c)");
222
44
        break;
223
56
    case 0x4d:
224
95
    case 0x4e:
225
146
    case 0x4f:
226
146
        snprintf(str, DESC_LEN, "QNX 4.x (0x%.2x)", ptype);
227
146
        break;
228
        /*case 0x4f:
229
           snprintf(str, DESC_LEN, "Oberon (0x4f)");
230
           break; */
231
        /*case 0x52:
232
           snprintf(str, DESC_LEN, "CP/M (0x52)");
233
           break; */
234
40
    case 0x50:
235
94
    case 0x51:
236
144
    case 0x53:
237
190
    case 0x54:
238
190
        snprintf(str, DESC_LEN, "OnTrack Disk Manager (0x%.2x)", ptype);
239
190
        break;
240
37
    case 0x52:
241
37
        snprintf(str, DESC_LEN, "Microport SysV/AT (0x52)");
242
37
        break;
243
60
    case 0x55:
244
60
        snprintf(str, DESC_LEN, "EZ-Drive (0x55)");
245
60
        break;
246
38
    case 0x56:
247
38
        snprintf(str, DESC_LEN,
248
38
            "AT&T MS-DOS 3.x Logically Sectored FAT (0x56)");
249
38
        break;
250
        /*case 0x56:
251
           snprintf(str, DESC_LEN, "Golden Bow VFeature Partitioned Volume (0x56)");
252
           break; */
253
        /*case 0x56:
254
           snprintf(str, DESC_LEN, "DM Converted to EZ-BIOS (0x56)");
255
           break; */
256
45
    case 0x57:
257
45
        snprintf(str, DESC_LEN, "DrivePro (0x57)");
258
45
        break;
259
45
    case 0x5c:
260
45
        snprintf(str, DESC_LEN, "Priam EDisk (0x5c)");
261
45
        break;
262
56
    case 0x61:
263
56
        snprintf(str, DESC_LEN, "SpeedStor (0x61)");
264
56
        break;
265
37
    case 0x63:
266
37
        snprintf(str, DESC_LEN, "UNIX System V (0x63)");
267
37
        break;
268
49
    case 0x64:
269
101
    case 0x65:
270
142
    case 0x66:
271
295
    case 0x67:
272
337
    case 0x68:
273
376
    case 0x69:
274
376
        snprintf(str, DESC_LEN, "Novell Netware (0x%.2x)", ptype);
275
376
        break;
276
38
    case 0x70:
277
38
        snprintf(str, DESC_LEN, "DiskSecure Multi-Boot (0x70)");
278
38
        break;
279
44
    case 0x74:
280
44
        snprintf(str, DESC_LEN, "Scramdisk (0x74)");
281
44
        break;
282
203
    case 0x75:
283
203
        snprintf(str, DESC_LEN, "IBM PC/IX (0x75)");
284
203
        break;
285
44
    case 0x77:
286
44
        snprintf(str, DESC_LEN, "VNDI (0x77)");
287
44
        break;
288
        /*case 0x77:
289
           snprintf(str, DESC_LEN, "M2FS/M2CS (0x77)");
290
           break; */
291
46
    case 0x78:
292
46
        snprintf(str, DESC_LEN, "XOSL FS (0x78)");
293
46
        break;
294
55
    case 0x80:
295
55
        snprintf(str, DESC_LEN, "MINIX <=v1.4a (0x80)");
296
55
        break;
297
45
    case 0x81:
298
45
        snprintf(str, DESC_LEN, "MINIX >=v1.4b, Early Linux (0x81)");
299
45
        break;
300
        /*case 0x81:
301
           snprintf(str, DESC_LEN, "Mitac Disk Manager (0x81)");
302
           break; */
303
45
    case 0x82:
304
45
        snprintf(str, DESC_LEN, "Linux Swap / Solaris x86 (0x82)");
305
45
        break;
306
54
    case 0x83:
307
54
        snprintf(str, DESC_LEN, "Linux (0x83)");
308
54
        break;
309
44
    case 0x84:
310
44
        snprintf(str, DESC_LEN, "Hibernation (0x84)");
311
44
        break;
312
651
    case 0x85:
313
651
        snprintf(str, DESC_LEN, "Linux Extended (0x85)");
314
651
        break;
315
52
    case 0x86:
316
52
        snprintf(str, DESC_LEN, "NTFS Volume Set (0x86)");
317
52
        break;
318
40
    case 0x87:
319
40
        snprintf(str, DESC_LEN, "NTFS Volume Set (0x87)");
320
40
        break;
321
68
    case 0x8a:
322
68
        snprintf(str, DESC_LEN, "Linux Kernel (0x8a)");
323
68
        break;
324
45
    case 0x8b:
325
45
        snprintf(str, DESC_LEN, "Legacy Fault Tolerant FAT32 (0x8b)");
326
45
        break;
327
64
    case 0x8c:
328
64
        snprintf(str, DESC_LEN,
329
64
            "Legacy Fault Tolerant FAT32 using BIOS extd INT 13h (0x8c)");
330
64
        break;
331
43
    case 0x8d:
332
43
        snprintf(str, DESC_LEN,
333
43
            "Free FDISK Hidden Primary DOS FAT12 (0x8d)");
334
43
        break;
335
94
    case 0x8e:
336
94
        snprintf(str, DESC_LEN, "Linux Logical Volume Manager (0x8e)");
337
94
        break;
338
54
    case 0x90:
339
54
        snprintf(str, DESC_LEN,
340
54
            "Free FDISK Hidden Primary DOS FAT16 (0x90)");
341
54
        break;
342
40
    case 0x91:
343
40
        snprintf(str, DESC_LEN, "Free FDISK Hidden DOS Extended (0x91)");
344
40
        break;
345
51
    case 0x92:
346
51
        snprintf(str, DESC_LEN,
347
51
            "Free FDISK Hidden Primary DOS Large FAT16 (0x92)");
348
51
        break;
349
42
    case 0x93:
350
42
        snprintf(str, DESC_LEN, "Linux Hidden (0x93)");
351
42
        break;
352
49
    case 0x94:
353
49
        snprintf(str, DESC_LEN, "Amoeba Bad Block Table (0x94)");
354
49
        break;
355
38
    case 0x95:
356
38
        snprintf(str, DESC_LEN, "MIT EXOPC (0x95)");
357
38
        break;
358
43
    case 0x97:
359
43
        snprintf(str, DESC_LEN,
360
43
            "Free FDISK Hidden Primary DOS FAT32 (0x97)");
361
43
        break;
362
62
    case 0x98:
363
62
        snprintf(str, DESC_LEN,
364
62
            "Free FDISK Hidden Primary DOS FAT32 LBA (0x98)");
365
62
        break;
366
        /*case 0x98:
367
           snprintf(str, DESC_LEN, "Datalight ROM-DOS Super-Boot (0x98)");
368
           break; */
369
39
    case 0x99:
370
39
        snprintf(str, DESC_LEN, "DCE376 Logical Drive (0x99)");
371
39
        break;
372
43
    case 0x9a:
373
43
        snprintf(str, DESC_LEN,
374
43
            "Free FDISK Hidden Primary DOS FAT16 LBA (0x9a)");
375
43
        break;
376
41
    case 0x9b:
377
41
        snprintf(str, DESC_LEN,
378
41
            "Free FDISK Hidden DOS Extended LBA (0x9b)");
379
41
        break;
380
50
    case 0x9f:
381
50
        snprintf(str, DESC_LEN, "BSD/OS (0x9f)");
382
50
        break;
383
46
    case 0xa0:
384
99
    case 0xa1:
385
99
        snprintf(str, DESC_LEN, "Hibernation (0x%.2x)", ptype);
386
99
        break;
387
61
    case 0xa3:
388
61
        snprintf(str, DESC_LEN,
389
61
            "HP Volume Expansion (SpeedStor Variant) (0xa3)");
390
61
        break;
391
40
    case 0xa4:
392
40
        snprintf(str, DESC_LEN,
393
40
            "HP Volume Expansion (SpeedStor Variant) (0xa4)");
394
40
        break;
395
40
    case 0xa5:
396
40
        snprintf(str, DESC_LEN, "BSD/386, 386BSD, NetBSD, FreeBSD (0xa5)");
397
40
        break;
398
43
    case 0xa6:
399
43
        snprintf(str, DESC_LEN, "OpenBSD (0xa6)");
400
43
        break;
401
49
    case 0xa7:
402
49
        snprintf(str, DESC_LEN, "NeXTSTEP (0xa7)");
403
49
        break;
404
48
    case 0xa8:
405
48
        snprintf(str, DESC_LEN, "Mac OS X (0xa8)");
406
48
        break;
407
46
    case 0xa9:
408
46
        snprintf(str, DESC_LEN, "NetBSD (0xa9)");
409
46
        break;
410
91
    case 0xaa:
411
91
        snprintf(str, DESC_LEN, "Olivetti Fat 12 1.44MB Service (0xaa)");
412
91
        break;
413
51
    case 0xab:
414
51
        snprintf(str, DESC_LEN, "Mac OS X Boot Partition (0xab)");
415
51
        break;
416
47
    case 0xae:
417
47
        snprintf(str, DESC_LEN, "ShagOS Filesystem (0xae)");
418
47
        break;
419
52
    case 0xaf:
420
52
        snprintf(str, DESC_LEN, "Mac OS X HFS (0xaf)");
421
52
        break;
422
52
    case 0xb0:
423
52
        snprintf(str, DESC_LEN, "BootStar Dummy (0xb0)");
424
52
        break;
425
38
    case 0xb1:
426
38
        snprintf(str, DESC_LEN,
427
38
            "HP Volume Expansion (SpeedStor Variant) (0xb1)");
428
38
        break;
429
53
    case 0xb3:
430
53
        snprintf(str, DESC_LEN,
431
53
            "HP Volume Expansion (SpeedStor Variant) (0xb3)");
432
53
        break;
433
40
    case 0xb4:
434
40
        snprintf(str, DESC_LEN,
435
40
            "HP Volume Expansion (SpeedStor Variant) (0xb4)");
436
40
        break;
437
47
    case 0xb6:
438
47
        snprintf(str, DESC_LEN,
439
47
            "Corrupted Windows NT Mirror Set Master FAT16 (0xb6)");
440
47
        break;
441
        /*case 0xb6:
442
           snprintf(str, DESC_LEN, "HP Volume Expansion (SpeedStor Variant) (0xb6)");
443
           break; */
444
37
    case 0xb7:
445
37
        snprintf(str, DESC_LEN, "BSDI (0xb7)");
446
37
        break;
447
42
    case 0xb8:
448
42
        snprintf(str, DESC_LEN, "BSDI Swap (0xb8)");
449
42
        break;
450
41
    case 0xbb:
451
41
        snprintf(str, DESC_LEN, "Boot Wizard Hidden (0xbb)");
452
41
        break;
453
62
    case 0xbe:
454
62
        snprintf(str, DESC_LEN, "Solaris 8 Boot (0xbe)");
455
62
        break;
456
47
    case 0xc0:
457
47
        snprintf(str, DESC_LEN, "DR-DOS Secured (0xc0)");
458
47
        break;
459
        /*case 0xc0:
460
           snprintf(str, DESC_LEN, "CTOS (0xc0)");
461
           break; */
462
        /*case 0xc0:
463
           snprintf(str, DESC_LEN, "REAL/32 Secure Small (0xc0)");
464
           break; */
465
        /*case 0xc0:
466
           snprintf(str, DESC_LEN, "NTFT (0xc0)");
467
           break; */
468
49
    case 0xc1:
469
49
        snprintf(str, DESC_LEN, "DR-DOS Secured FAT12 (0xc1)");
470
49
        break;
471
43
    case 0xc2:
472
43
        snprintf(str, DESC_LEN, "Hidden Linux (0xc2)");
473
43
        break;
474
44
    case 0xc3:
475
44
        snprintf(str, DESC_LEN, "Hidden Linux Swap (0xc3)");
476
44
        break;
477
41
    case 0xc4:
478
41
        snprintf(str, DESC_LEN, "DR-DOS Secured FAT16 <32M (0xc4)");
479
41
        break;
480
64
    case 0xc5:
481
64
        snprintf(str, DESC_LEN, "DR-DOS Secured Extended (0xc5)");
482
64
        break;
483
43
    case 0xc6:
484
99
    case 0xc7:
485
99
        snprintf(str, DESC_LEN,
486
99
            "Corrupted Windows NT Volume / Stripe Set (0x%.2x)", ptype);
487
99
        break;
488
39
    case 0xc8:
489
39
        snprintf(str, DESC_LEN, "Reserved for DR-DOS 8.0+ (0xc8)");
490
39
        break;
491
48
    case 0xc9:
492
48
        snprintf(str, DESC_LEN, "Reserved for DR-DOS 8.0+ (0xc9)");
493
48
        break;
494
59
    case 0xca:
495
59
        snprintf(str, DESC_LEN, "Reserved for DR-DOS 8.0+ (0xca)");
496
59
        break;
497
44
    case 0xcb:
498
44
        snprintf(str, DESC_LEN, "DR-DOS 7.04+ Secured FAT32 CHS (0xcb)");
499
44
        break;
500
68
    case 0xcc:
501
68
        snprintf(str, DESC_LEN, "DR-DOS 7.04+ Secured FAT32 LBA (0xcc)");
502
68
        break;
503
45
    case 0xcd:
504
45
        snprintf(str, DESC_LEN, "CTOS Memdump? (0xcd)");
505
45
        break;
506
55
    case 0xce:
507
55
        snprintf(str, DESC_LEN, "DR-DOS 7.04+ FAT16X LBA (0xce)");
508
55
        break;
509
51
    case 0xcf:
510
51
        snprintf(str, DESC_LEN, "DR-DOS 7.04+ Secured EXT DOS LBA (0xcf)");
511
51
        break;
512
43
    case 0xd0:
513
43
        snprintf(str, DESC_LEN, "Multiuser DOS Secured (0xd0)");
514
43
        break;
515
        /*case 0xd0:
516
           snprintf(str, DESC_LEN, "REAL/32 Secure Big (0xd0)");
517
           break; */
518
52
    case 0xd1:
519
52
        snprintf(str, DESC_LEN, "Old Multiuser DOS Secured FAT12 (0xd1)");
520
52
        break;
521
48
    case 0xd4:
522
48
        snprintf(str, DESC_LEN,
523
48
            "Old Multiuser DOS Secured FAT16 <32M (0xd4)");
524
48
        break;
525
48
    case 0xd5:
526
48
        snprintf(str, DESC_LEN,
527
48
            "Old Multiuser DOS Secured extended (0xd5)");
528
48
        break;
529
48
    case 0xd6:
530
48
        snprintf(str, DESC_LEN,
531
48
            "Old Multiuser DOS Secured FAT16 >=32M (0xd6)");
532
48
        break;
533
36
    case 0xd8:
534
36
        snprintf(str, DESC_LEN, "CP/M-86 (0xd8)");
535
36
        break;
536
47
    case 0xda:
537
47
        snprintf(str, DESC_LEN, "Non-FS Data (0xda)");
538
47
        break;
539
42
    case 0xdb:
540
42
        snprintf(str, DESC_LEN,
541
42
            "Digital Research CP/M, Concurrent CP/M, Concurrent DOS (0xdb)");
542
42
        break;
543
        /*case 0xdb:
544
           snprintf(str, DESC_LEN, "Unisys CTOS (0xdb)");
545
           break; */
546
        /*case 0xdb:
547
           snprintf(str, DESC_LEN, "KDG Telemetry SCPU boot (0xdb)");
548
           break; */
549
54
    case 0xdd:
550
54
        snprintf(str, DESC_LEN, "Hidden CTOS Memdump?  (0xdd)");
551
54
        break;
552
73
    case 0xde:
553
73
        snprintf(str, DESC_LEN, "Dell Utilities FAT (0xde)");
554
73
        break;
555
        /*case 0xdf:
556
           snprintf(str, DESC_LEN, "DG/UX Virtual Disk Manager (0xdf)");
557
           break; */
558
        /*case 0xdf:
559
           snprintf(str, DESC_LEN, "BootIt EMBRM (0xdf)");
560
           break; */
561
38
    case 0xe0:
562
38
        snprintf(str, DESC_LEN,
563
38
            "Reserved by STMicroelectronics for ST AVFS. (0xe0)");
564
38
        break;
565
45
    case 0xe1:
566
45
        snprintf(str, DESC_LEN,
567
45
            "DOS Access or SpeedStor 12-bit FAT Extended (0xe1)");
568
45
        break;
569
69
    case 0xe3:
570
69
        snprintf(str, DESC_LEN, "DOS R/O or SpeedStor (0xe3)");
571
69
        break;
572
45
    case 0xe4:
573
45
        snprintf(str, DESC_LEN,
574
45
            "SpeedStor 16-bit FAT Extended <1024 cyl. (0xe4)");
575
45
        break;
576
40
    case 0xe5:
577
40
        snprintf(str, DESC_LEN,
578
40
            "Tandy MS-DOS with Logically Sectored FAT (0xe5)");
579
40
        break;
580
52
    case 0xe6:
581
52
        snprintf(str, DESC_LEN, "Storage Dimensions SpeedStor (0xe6)");
582
52
        break;
583
67
    case 0xeb:
584
67
        snprintf(str, DESC_LEN, "BeOS BFS (0xeb)");
585
67
        break;
586
43
    case 0xee:
587
43
        snprintf(str, DESC_LEN, "GPT Safety Partition (0xee)");
588
43
        break;
589
65
    case 0xef:
590
65
        snprintf(str, DESC_LEN, "EFI File System (0xef)");
591
65
        break;
592
44
    case 0xf0:
593
44
        snprintf(str, DESC_LEN, "Linux/PA-RISC Boot Loader (0xf0)");
594
44
        break;
595
44
    case 0xf1:
596
44
        snprintf(str, DESC_LEN, "Storage Dimensions SpeedStor (0xf1)");
597
44
        break;
598
42
    case 0xf2:
599
42
        snprintf(str, DESC_LEN, "DOS 3.3+ Secondary (0xf2)");
600
42
        break;
601
47
    case 0xf4:
602
47
        snprintf(str, DESC_LEN, "SpeedStor Large (0xf4)");
603
47
        break;
604
        /*case 0xf4:
605
           snprintf(str, DESC_LEN, "Prologue Single-Volume (0xf4)");
606
           break; */
607
38
    case 0xf5:
608
38
        snprintf(str, DESC_LEN, "Prologue Multi-Volume (0xf5)");
609
38
        break;
610
49
    case 0xf6:
611
49
        snprintf(str, DESC_LEN, "Storage Dimensions SpeedStor (0xf6)");
612
49
        break;
613
55
    case 0xf9:
614
55
        snprintf(str, DESC_LEN, "pCache (0xf9)");
615
55
        break;
616
62
    case 0xfa:
617
62
        snprintf(str, DESC_LEN, "Bochs (0xfa)");
618
62
        break;
619
66
    case 0xfb:
620
66
        snprintf(str, DESC_LEN, "VMWare File System (0xfb)");
621
66
        break;
622
47
    case 0xfc:
623
47
        snprintf(str, DESC_LEN, "VMWare Swap (0xfc)");
624
47
        break;
625
55
    case 0xfd:
626
55
        snprintf(str, DESC_LEN, "Linux RAID (0xfd)");
627
55
        break;
628
49
    case 0xfe:
629
49
        snprintf(str, DESC_LEN,
630
49
            "Windows NT Disk Administrator Hidden (0xfe)");
631
49
        break;
632
        /*case 0xfe:
633
           snprintf(str, DESC_LEN, "SpeedStor >1024 cyl. (0xfe)");
634
           break; */
635
        /*case 0xfe:
636
           snprintf(str, DESC_LEN, "LANstep (0xfe)");
637
           break; */
638
        /*case 0xfe:
639
           snprintf(str, DESC_LEN, "IBM PS/2 IML (0xfe)");
640
           break; */
641
        /*case 0xfe:
642
           snprintf(str, DESC_LEN, "Old Linux Logical Volume Manager (0xfe)");
643
           break; */
644
168
    case 0xff:
645
168
        snprintf(str, DESC_LEN, "Xenix Bad Block Table (0xff)");
646
168
        break;
647
327
    default:
648
327
        snprintf(str, DESC_LEN, "Unknown Type (0x%.2x)", ptype);
649
327
        break;
650
15.5k
    }
651
652
15.5k
    return str;
653
15.5k
}
654
655
/*
656
 * Load an extended partition table into the structure in TSK_VS_INFO.
657
 *
658
 * sect_cur: The sector where the extended table is located
659
 * sect_ext_base: The sector of the primary extended table (this does
660
 *   not change for recursive calls)
661
 * table: a counter that identifies the table depth
662
 *   (increases by 1 for each recursive call)
663
 *
664
 * For the primary extended table, sect_cur == sect_ext_base
665
 *
666
 * Return 1 on error and 0 on success
667
 *
668
 */
669
static uint8_t
670
dos_load_ext_table(TSK_VS_INFO * vs, TSK_DADDR_T sect_cur,
671
    TSK_DADDR_T sect_ext_base, int table)
672
4.67k
{
673
4.67k
    dos_sect *sect;
674
4.67k
    char *sect_buf;
675
4.67k
    int i;
676
4.67k
    char *table_str;
677
4.67k
    ssize_t cnt;
678
4.67k
    TSK_DADDR_T max_addr = (vs->img_info->size - vs->offset) / vs->block_size;  // max sector
679
680
4.67k
    if (tsk_verbose)
681
0
        tsk_fprintf(stderr,
682
0
            "dos_load_ext: Table Sector: %" PRIuDADDR
683
0
            ", Primary Base Sector: %" PRIuDADDR "\n", sect_cur,
684
0
            sect_ext_base);
685
686
4.67k
    if ((sect_buf = tsk_malloc(vs->block_size)) == NULL)
687
0
        return 1;
688
4.67k
    sect = (dos_sect *) sect_buf;
689
690
    /* Read the partition table sector */
691
4.67k
    cnt = tsk_vs_read_block(vs, sect_cur, sect_buf, vs->block_size);
692
4.67k
    if (cnt != vs->block_size) {
693
436
        if (cnt >= 0) {
694
160
            tsk_error_reset();
695
160
            tsk_error_set_errno(TSK_ERR_VS_READ);
696
160
        }
697
436
        tsk_error_set_errstr2("Extended DOS table sector %" PRIuDADDR,
698
436
            sect_cur);
699
436
        free(sect_buf);
700
436
        return 1;
701
436
    }
702
703
    /* Sanity Check */
704
4.23k
    if (tsk_getu16(vs->endian, sect->magic) != DOS_MAGIC) {
705
305
        tsk_error_reset();
706
305
        tsk_error_set_errno(TSK_ERR_VS_MAGIC);
707
305
        tsk_error_set_errstr("Extended DOS partition table in sector %"
708
305
            PRIuDADDR, sect_cur);
709
305
        free(sect_buf);
710
305
        return 1;
711
305
    }
712
713
    /* Add an entry of 1 length for the table  to the internal structure */
714
3.93k
    if ((table_str = tsk_malloc(32)) == NULL) {
715
0
        free(sect_buf);
716
0
        return 1;
717
0
    }
718
719
3.93k
    snprintf(table_str, 32, "Extended Table (#%d)", table);
720
3.93k
    if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) sect_cur,
721
3.93k
            (TSK_DADDR_T) 1, TSK_VS_PART_FLAG_META, table_str, table,
722
3.93k
            -1)) {
723
0
        free(sect_buf);
724
0
        return 1;
725
0
    }
726
727
    /* Cycle through the four partitions in the table
728
     *
729
     * When another extended partition is found, it is processed
730
     * inside of the loop
731
     */
732
17.6k
    for (i = 0; i < 4; i++) {
733
14.6k
        dos_part *part = &sect->ptable[i];
734
735
        /* Get the starting sector and size, we currently
736
         * ignore CHS */
737
14.6k
        uint32_t part_start = tsk_getu32(vs->endian, part->start_sec);
738
14.6k
        uint32_t part_size = tsk_getu32(vs->endian, part->size_sec);
739
740
14.6k
        if (tsk_verbose)
741
0
            tsk_fprintf(stderr,
742
0
                "load_ext: %d:%d    Start: %" PRIu32 "   Size: %"
743
0
                PRIu32 "  Type: %d\n", table, i, part_start, part_size,
744
0
                part->ptype);
745
746
        /* part_start == 0 would cause infinite recursion */
747
14.6k
        if (part_size == 0 || part_start == 0)
748
3.37k
            continue;
749
750
        /* partitions are addressed differently
751
         * in extended partitions */
752
11.2k
        if (dos_is_ext(part->ptype)) {
753
754
2.21k
            TSK_VS_PART_INFO *part_info;
755
756
            /* Sanity check to prevent infinite recursion in dos_load_ext_table.
757
             * If we already have a partition with this starting address then
758
             * return an error. This will prevent any more partitions from being
759
             * added but will leave any existing partitions alone. */
760
2.21k
            part_info = vs->part_list;
761
44.9k
            while (part_info != NULL) {
762
43.2k
                if (part_info->start == (TSK_DADDR_T)(sect_ext_base + part_start)) {
763
427
                    if (tsk_verbose)
764
0
                        tsk_fprintf(stderr,
765
0
                            "Starting sector %" PRIuDADDR
766
0
                            " of extended partition has already been used\n",
767
0
                            (TSK_DADDR_T)(sect_ext_base + part_start));
768
427
                    tsk_error_reset();
769
427
                    tsk_error_set_errno(TSK_ERR_VS_BLK_NUM);
770
427
                    tsk_error_set_errstr
771
427
                        ("dos_load_ext_table: Loop in partition table detected");
772
427
                    free(sect_buf);
773
427
                    return 1;
774
427
                }
775
42.7k
                part_info = part_info->next;
776
42.7k
            }
777
778
            /* part start is added to the start of the
779
             * first extended partition (the primary
780
             * extended partition) */
781
782
1.78k
            if (NULL == tsk_vs_part_add(vs,
783
1.78k
                    (TSK_DADDR_T) (sect_ext_base + part_start),
784
1.78k
                    (TSK_DADDR_T) part_size, TSK_VS_PART_FLAG_META,
785
1.78k
                    dos_get_desc(part->ptype), table, i)) {
786
0
                free(sect_buf);
787
0
                return 1;
788
0
            }
789
790
1.78k
            if (sect_ext_base + part_start > max_addr) {
791
558
                if (tsk_verbose)
792
0
                    tsk_fprintf(stderr,
793
0
                        "Starting sector %" PRIuDADDR
794
0
                        " of extended partition too large for image\n",
795
0
                        sect_ext_base + part_start);
796
558
            }
797
            /* Process the extended partition */
798
1.22k
            else if (dos_load_ext_table(vs, sect_ext_base + part_start,
799
1.22k
                    sect_ext_base, table + 1)) {
800
477
                free(sect_buf);
801
477
                return 1;
802
477
            }
803
1.78k
        }
804
805
9.07k
        else {
806
            /* part_start is added to the start of the
807
             * current partition for the actual
808
             * starting location */
809
810
            // we ignore the max_addr checks on extended partitions...
811
812
9.07k
            if (NULL == tsk_vs_part_add(vs,
813
9.07k
                    (TSK_DADDR_T) (sect_cur + part_start),
814
9.07k
                    (TSK_DADDR_T) part_size, TSK_VS_PART_FLAG_ALLOC,
815
9.07k
                    dos_get_desc(part->ptype), table, i)) {
816
0
                free(sect_buf);
817
0
                return 1;
818
0
            }
819
9.07k
        }
820
11.2k
    }
821
822
3.03k
    free(sect_buf);
823
3.03k
    return 0;
824
3.93k
}
825
826
827
/*
828
 * Load the primary partition table (MBR) into the internal
829
 * data structures in TSK_VS_INFO
830
 *
831
 * This will automatically call load_ext_table for extended
832
 * partitions
833
 *
834
 * sect_cur is the address of the table to load
835
 *
836
 * 0 is returned if the load is successful and 1 if error
837
 */
838
static uint8_t
839
dos_load_prim_table(TSK_VS_INFO * vs, uint8_t test)
840
1.34k
{
841
1.34k
    dos_sect *sect;
842
1.34k
    char *sect_buf;
843
1.34k
    int i, added = 0;
844
1.34k
    char *table_str;
845
1.34k
    ssize_t cnt;
846
1.34k
    TSK_DADDR_T taddr = vs->offset / vs->block_size + DOS_PART_SOFFSET;
847
1.34k
    TSK_DADDR_T max_addr = (vs->img_info->size - vs->offset) / vs->block_size;  // max sector
848
849
1.34k
    if (tsk_verbose)
850
0
        tsk_fprintf(stderr,
851
0
            "dos_load_prim: Table Sector: %" PRIuDADDR "\n", taddr);
852
853
1.34k
    if ((sect_buf = tsk_malloc(vs->block_size)) == NULL)
854
0
        return 1;
855
1.34k
    sect = (dos_sect *) sect_buf;
856
857
    /* Read the table */
858
1.34k
    cnt = tsk_vs_read_block
859
1.34k
        (vs, DOS_PART_SOFFSET, sect_buf, vs->block_size);
860
861
1.34k
    if (cnt != vs->block_size) {
862
17
        if (cnt >= 0) {
863
17
            tsk_error_reset();
864
17
            tsk_error_set_errno(TSK_ERR_VS_READ);
865
17
        }
866
17
        tsk_error_set_errstr2("Primary DOS table sector %" PRIuDADDR,
867
17
            taddr);
868
17
        free(sect_buf);
869
17
        return 1;
870
17
    }
871
872
873
    /* Sanity Check */
874
1.32k
    if (tsk_vs_guessu16(vs, sect->magic, DOS_MAGIC)) {
875
45
        tsk_error_reset();
876
45
        tsk_error_set_errno(TSK_ERR_VS_MAGIC);
877
45
        tsk_error_set_errstr
878
45
            ("File is not a DOS partition (invalid primary magic) (Sector: %"
879
45
            PRIuDADDR ")", taddr);
880
45
        if (tsk_verbose)
881
0
            fprintf(stderr,
882
0
                "File is not a DOS partition (invalid primary magic) (Sector: %"
883
0
                PRIuDADDR ")", taddr);
884
45
        free(sect_buf);
885
45
        return 1;
886
45
    }
887
888
    /* Because FAT and NTFS use the same magic - check for a
889
     * standard MS OEM name and sizes.  Not a great check, but we can't
890
     * really test the table entries.
891
     */
892
1.28k
    if (test) {
893
0
        if (tsk_verbose)
894
0
            tsk_fprintf(stderr,
895
0
                "dos_load_prim_table: Testing FAT/NTFS conditions\n");
896
897
0
        if (strncmp("MSDOS", sect->oemname, 5) == 0) {
898
0
            tsk_error_reset();
899
0
            tsk_error_set_errno(TSK_ERR_VS_MAGIC);
900
0
            tsk_error_set_errstr
901
0
                ("dos_load_prim_table: MSDOS OEM name exists");
902
0
            if (tsk_verbose)
903
0
                tsk_fprintf(stderr,
904
0
                    "dos_load_prim_table: MSDOS OEM name exists\n");
905
0
            free(sect_buf);
906
0
            return 1;
907
0
        }
908
0
        else if (strncmp("MSWIN", sect->oemname, 5) == 0) {
909
0
            tsk_error_reset();
910
0
            tsk_error_set_errno(TSK_ERR_VS_MAGIC);
911
0
            tsk_error_set_errstr
912
0
                ("dos_load_prim_table: MSWIN OEM name exists");
913
0
            if (tsk_verbose)
914
0
                tsk_fprintf(stderr,
915
0
                    "dos_load_prim_table: MSWIN OEM name exists\n");
916
0
            free(sect_buf);
917
0
            return 1;
918
0
        }
919
0
        else if (strncmp("NTFS", sect->oemname, 4) == 0) {
920
0
            tsk_error_reset();
921
0
            tsk_error_set_errno(TSK_ERR_VS_MAGIC);
922
0
            tsk_error_set_errstr
923
0
                ("dos_load_prim_table: NTFS OEM name exists");
924
0
            if (tsk_verbose)
925
0
                tsk_fprintf(stderr,
926
0
                    "dos_load_prim_table: NTFS OEM name exists\n");
927
0
            free(sect_buf);
928
0
            return 1;
929
0
        }
930
0
        else if (strncmp("FAT", sect->oemname, 4) == 0) {
931
0
            tsk_error_reset();
932
0
            tsk_error_set_errno(TSK_ERR_VS_MAGIC);
933
0
            tsk_error_set_errstr
934
0
                ("dos_load_prim_table: FAT OEM name exists");
935
0
            if (tsk_verbose)
936
0
                tsk_fprintf(stderr,
937
0
                    "dos_load_prim_table: FAT OEM name exists\n");
938
0
            free(sect_buf);
939
0
            return 1;
940
0
        }
941
0
    }
942
943
    /* Add an entry of 1 sector for the table  to the internal structure */
944
1.28k
    if ((table_str = tsk_malloc(32)) == NULL) {
945
0
        free(sect_buf);
946
0
        return 1;
947
0
    }
948
949
1.28k
    snprintf(table_str, 32, "Primary Table (#0)");
950
1.28k
    if (NULL == tsk_vs_part_add(vs, DOS_PART_SOFFSET, (TSK_DADDR_T) 1,
951
1.28k
            TSK_VS_PART_FLAG_META, table_str, -1, -1)) {
952
0
        free(sect_buf);
953
0
        return 1;
954
0
    }
955
956
    /* Cycle through the partition table */
957
6.08k
    for (i = 0; i < 4; i++) {
958
4.90k
        dos_part *part = &sect->ptable[i];
959
960
        /* We currently ignore CHS */
961
4.90k
        uint32_t part_start = tsk_getu32(vs->endian, part->start_sec);
962
4.90k
        uint32_t part_size = tsk_getu32(vs->endian, part->size_sec);
963
964
4.90k
        if (tsk_verbose)
965
0
            tsk_fprintf(stderr,
966
0
                "load_pri:0:%d    Start: %" PRIu32 "   Size: %" PRIu32
967
0
                "  Type: %d\n", i, part_start, part_size, part->ptype);
968
969
4.90k
        if (part_size == 0)
970
108
            continue;
971
972
        // make sure the first couple are in the image bounds
973
4.80k
        if ((i < 2) && (part_start > max_addr)) {
974
105
            tsk_error_reset();
975
105
            tsk_error_set_errno(TSK_ERR_VS_BLK_NUM);
976
105
            tsk_error_set_errstr
977
105
                ("dos_load_prim_table: Starting sector too large for image");
978
105
            if (tsk_verbose)
979
0
                tsk_fprintf(stderr,
980
0
                    "Starting sector %" PRIu32 " too large for image\n",
981
0
                    part_start);
982
105
            free(sect_buf);
983
105
            return 1;
984
105
        }
985
#if 0
986
// I'm not sure if this is too strict ...
987
        else if ((part_start + part_size) > max_addr) {
988
            tsk_error_reset();
989
            tsk_error_set_errno(TSK_ERR_VS_BLK_NUM);
990
            tsk_error_set_errstr
991
                ("dos_load_prim_table: Partition ends after image");
992
            return 1;
993
        }
994
#endif
995
996
4.69k
        added = 1;
997
998
        /* Add the partition to the internal structure
999
         * If it is an extended partition, process it now */
1000
4.69k
        if (dos_is_ext(part->ptype)) {
1001
3.44k
            if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) part_start,
1002
3.44k
                    (TSK_DADDR_T) part_size, TSK_VS_PART_FLAG_META,
1003
3.44k
                    dos_get_desc(part->ptype), 0, i)) {
1004
0
                free(sect_buf);
1005
0
                return 1;
1006
0
            }
1007
1008
3.44k
            if (dos_load_ext_table(vs, part_start, part_start, 1)) {
1009
1.16k
                if (tsk_verbose) {
1010
0
                    fprintf(stderr,
1011
0
                        "Error loading extended table, moving on");
1012
0
                    tsk_error_print(stderr);
1013
0
                }
1014
1.16k
                tsk_error_reset();
1015
1.16k
            }
1016
3.44k
        }
1017
1.24k
        else {
1018
1.24k
            if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) part_start,
1019
1.24k
                    (TSK_DADDR_T) part_size, TSK_VS_PART_FLAG_ALLOC,
1020
1.24k
                    dos_get_desc(part->ptype), 0, i)) {
1021
0
                free(sect_buf);
1022
0
                return 1;
1023
0
            }
1024
1.24k
        }
1025
4.69k
    }
1026
1.17k
    free(sect_buf);
1027
1028
1.17k
    if (added == 0) {
1029
1
        if (tsk_verbose)
1030
0
            tsk_fprintf(stderr, "dos_load_prim: No valid entries\n");
1031
1032
1
        tsk_error_reset();
1033
1
        tsk_error_set_errno(TSK_ERR_VS_MAGIC);
1034
1
        tsk_error_set_errstr
1035
1
            ("dos_load_prim_table: No valid entries in primary table");
1036
1
        return 1;
1037
1
    }
1038
1.17k
    return 0;
1039
1.17k
}
1040
1041
1042
static void
1043
dos_close(TSK_VS_INFO * vs)
1044
1.34k
{
1045
1.34k
    vs->tag = 0;
1046
1.34k
    tsk_vs_part_free(vs);
1047
1.34k
    free(vs);
1048
1.34k
}
1049
1050
1051
/*
1052
 * Given the path to the file, open it and load the internal
1053
 * partition table structure
1054
 *
1055
 * offset is the byte offset to the start of the volume system
1056
 *
1057
 * If test is 1 then additional tests are performed to make sure
1058
 * it isn't a FAT or NTFS file system. This is used when autodetection
1059
 * is being used to detect the volume system type.
1060
 */
1061
TSK_VS_INFO *
1062
tsk_vs_dos_open(TSK_IMG_INFO * img_info, TSK_DADDR_T offset, uint8_t test)
1063
1.34k
{
1064
1.34k
    TSK_VS_INFO *vs;
1065
1066
    // clean up any errors that are lying around
1067
1.34k
    tsk_error_reset();
1068
1069
1.34k
    if (img_info->sector_size == 0) {
1070
0
        tsk_error_reset();
1071
0
        tsk_error_set_errno(TSK_ERR_VS_ARG);
1072
0
        tsk_error_set_errstr("tsk_vs_dos_open: sector size is 0");
1073
0
        return NULL;
1074
0
    }
1075
1076
1.34k
    vs = (TSK_VS_INFO *) tsk_malloc(sizeof(*vs));
1077
1.34k
    if (vs == NULL)
1078
0
        return NULL;
1079
1080
1.34k
    vs->vstype = TSK_VS_TYPE_DOS;
1081
1.34k
    vs->tag = TSK_VS_INFO_TAG;
1082
1.34k
    vs->img_info = img_info;
1083
1084
1.34k
    vs->offset = offset;
1085
1086
    /* initialize settings */
1087
1.34k
    vs->part_list = NULL;
1088
1.34k
    vs->part_count = 0;
1089
1.34k
    vs->endian = 0;
1090
1.34k
    vs->block_size = img_info->sector_size;
1091
1092
1093
    /* Assign functions */
1094
1.34k
    vs->close = dos_close;
1095
1096
    /* Load the partitions into the sorted list */
1097
1.34k
    if (dos_load_prim_table(vs, test)) {
1098
168
        dos_close(vs);
1099
168
        return NULL;
1100
168
    }
1101
1102
    /* fill in the sorted list with the 'unknown' values */
1103
1.17k
    if (tsk_vs_part_unused(vs)) {
1104
0
        dos_close(vs);
1105
0
        return NULL;
1106
0
    }
1107
1108
1.17k
    return vs;
1109
1.17k
}