Coverage Report

Created: 2025-11-11 07:01

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.8k
  ((((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.4k
{
33
30.9k
#define DESC_LEN 64
34
15.4k
    char *str = tsk_malloc(DESC_LEN);
35
15.4k
    if (str == NULL)
36
0
        return "";
37
38
15.4k
    switch (ptype) {
39
645
    case 0x00:
40
645
        snprintf(str, DESC_LEN, "Empty (0x00)");
41
645
        break;
42
123
    case 0x01:
43
123
        snprintf(str, DESC_LEN, "DOS FAT12 (0x01)");
44
123
        break;
45
77
    case 0x02:
46
77
        snprintf(str, DESC_LEN, "XENIX root (0x02)");
47
77
        break;
48
56
    case 0x03:
49
56
        snprintf(str, DESC_LEN, "XENIX /usr (0x03)");
50
56
        break;
51
80
    case 0x04:
52
128
    case 0x06:
53
128
        snprintf(str, DESC_LEN, "DOS FAT16 (0x%.2x)", ptype);
54
128
        break;
55
3.82k
    case 0x05:
56
3.82k
        snprintf(str, DESC_LEN, "DOS Extended (0x05)");
57
3.82k
        break;
58
59
    case 0x07:
59
59
        snprintf(str, DESC_LEN, "NTFS / exFAT (0x07)");
60
59
        break;
61
79
    case 0x08:
62
79
        snprintf(str, DESC_LEN, "AIX Boot (0x08)");
63
79
        break;
64
50
    case 0x09:
65
50
        snprintf(str, DESC_LEN, "AIX Data (0x09)");
66
50
        break;
67
63
    case 0x0a:
68
63
        snprintf(str, DESC_LEN, "OS/2 Boot Manager (0x0a)");
69
63
        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
48
    case 0x0b:
79
98
    case 0x0c:
80
98
        snprintf(str, DESC_LEN, "Win95 FAT32 (0x%.2x)", ptype);
81
98
        break;
82
49
    case 0x0e:
83
49
        snprintf(str, DESC_LEN, "Win95 FAT16 (0x0e)");
84
49
        break;
85
735
    case 0x0f:
86
735
        snprintf(str, DESC_LEN, "Win95 Extended (0x0f)");
87
735
        break;
88
75
    case 0x10:
89
75
        snprintf(str, DESC_LEN, "OPUS (0x10)");
90
75
        break;
91
59
    case 0x11:
92
59
        snprintf(str, DESC_LEN, "DOS FAT12 Hidden (0x11)");
93
59
        break;
94
43
    case 0x12:
95
43
        snprintf(str, DESC_LEN, "Hibernation (0x12)");
96
43
        break;
97
76
    case 0x14:
98
130
    case 0x16:
99
130
        snprintf(str, DESC_LEN, "DOS FAT16 Hidden (0x%.2x)", ptype);
100
130
        break;
101
41
    case 0x17:
102
41
        snprintf(str, DESC_LEN, "Hidden IFS/HPFS (0x17)");
103
41
        break;
104
53
    case 0x18:
105
53
        snprintf(str, DESC_LEN, "AST SmartSleep (0x18)");
106
53
        break;
107
51
    case 0x19:
108
97
    case 0x1b:
109
148
    case 0x1c:
110
148
        snprintf(str, DESC_LEN, "Win95 FAT32 Hidden (0x%.2x)", ptype);
111
148
        break;
112
50
    case 0x1e:
113
50
        snprintf(str, DESC_LEN, "Win95 FAT16 Hidden (0x1e)");
114
50
        break;
115
39
    case 0x20:
116
81
    case 0x22:
117
122
    case 0x7e:
118
177
    case 0x7f:
119
216
    case 0xed:
120
261
    case 0xf7:
121
261
        snprintf(str, DESC_LEN, "Unused (0x%.2x)", ptype);
122
261
        break;
123
60
    case 0x21:
124
114
    case 0x23:
125
185
    case 0x26:
126
237
    case 0x31:
127
288
    case 0x33:
128
346
    case 0x34:
129
388
    case 0x36:
130
440
    case 0x71:
131
489
    case 0x73:
132
530
    case 0x76:
133
586
    case 0xf3:
134
586
        snprintf(str, DESC_LEN, "Reserved (0x%.2x)", ptype);
135
586
        break;
136
45
    case 0x24:
137
45
        snprintf(str, DESC_LEN, "NEC DOS 3.x (0x24)");
138
45
        break;
139
69
    case 0x32:
140
69
        snprintf(str, DESC_LEN, "NOS (0x32)");
141
69
        break;
142
54
    case 0x35:
143
54
        snprintf(str, DESC_LEN, "JFS on OS/2 or eCS  (0x35)");
144
54
        break;
145
49
    case 0x38:
146
49
        snprintf(str, DESC_LEN, "THEOS v3.2 2gb (0x38)");
147
49
        break;
148
38
    case 0x39:
149
38
        snprintf(str, DESC_LEN, "THEOS v4 Spanned (0x39)");
150
38
        break;
151
        /*
152
           case 0x39:
153
           snprintf(str, DESC_LEN, "Plan 9 (0x39)");
154
           break;
155
         */
156
56
    case 0x3a:
157
56
        snprintf(str, DESC_LEN, "THEOS v4 4gb (0x3a)");
158
56
        break;
159
43
    case 0x3b:
160
43
        snprintf(str, DESC_LEN, "THEOS v4 Extended (0x3b)");
161
43
        break;
162
49
    case 0x3c:
163
49
        snprintf(str, DESC_LEN, "PartitionMagic Recovery (0x3c)");
164
49
        break;
165
44
    case 0x3d:
166
44
        snprintf(str, DESC_LEN, "Hidden NetWare (0x3d)");
167
44
        break;
168
52
    case 0x40:
169
52
        snprintf(str, DESC_LEN, "Venix 80286 (0x40)");
170
52
        break;
171
68
    case 0x41:
172
68
        snprintf(str, DESC_LEN,
173
68
            "Linux/MINIX (Sharing Disk with DR-DOS) (0x41)");
174
68
        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
43
    case 0x42:
184
43
        snprintf(str, DESC_LEN, "Win LVM / Secure FS (0x42)");
185
43
        break;
186
34
    case 0x43:
187
34
        snprintf(str, DESC_LEN,
188
34
            "Linux Native (Sharing Disk with DR-DOS) (0x43)");
189
34
        break;
190
49
    case 0x44:
191
49
        snprintf(str, DESC_LEN, "GoBack (0x44)");
192
49
        break;
193
42
    case 0x45:
194
42
        snprintf(str, DESC_LEN, "Boot-US Boot Manager (0x45)");
195
42
        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
90
    case 0x46:
205
90
        snprintf(str, DESC_LEN, "EUMEL/Elan  (0x46)");
206
90
        break;
207
60
    case 0x47:
208
60
        snprintf(str, DESC_LEN, "EUMEL/Elan  (0x47)");
209
60
        break;
210
41
    case 0x48:
211
41
        snprintf(str, DESC_LEN, "EUMEL/Elan  (0x48)");
212
41
        break;
213
40
    case 0x4a:
214
40
        snprintf(str, DESC_LEN,
215
40
            "Mark Aitchison's ALFS/THIN Lightweight Filesystem (0x4a)");
216
40
        break;
217
        /*case 0x4a:
218
           snprintf(str, DESC_LEN, "AdaOS Aquila (0x4a)");
219
           break; */
220
38
    case 0x4c:
221
38
        snprintf(str, DESC_LEN, "Oberon (0x4c)");
222
38
        break;
223
51
    case 0x4d:
224
92
    case 0x4e:
225
143
    case 0x4f:
226
143
        snprintf(str, DESC_LEN, "QNX 4.x (0x%.2x)", ptype);
227
143
        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
44
    case 0x50:
235
99
    case 0x51:
236
149
    case 0x53:
237
193
    case 0x54:
238
193
        snprintf(str, DESC_LEN, "OnTrack Disk Manager (0x%.2x)", ptype);
239
193
        break;
240
36
    case 0x52:
241
36
        snprintf(str, DESC_LEN, "Microport SysV/AT (0x52)");
242
36
        break;
243
57
    case 0x55:
244
57
        snprintf(str, DESC_LEN, "EZ-Drive (0x55)");
245
57
        break;
246
35
    case 0x56:
247
35
        snprintf(str, DESC_LEN,
248
35
            "AT&T MS-DOS 3.x Logically Sectored FAT (0x56)");
249
35
        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
40
    case 0x57:
257
40
        snprintf(str, DESC_LEN, "DrivePro (0x57)");
258
40
        break;
259
44
    case 0x5c:
260
44
        snprintf(str, DESC_LEN, "Priam EDisk (0x5c)");
261
44
        break;
262
59
    case 0x61:
263
59
        snprintf(str, DESC_LEN, "SpeedStor (0x61)");
264
59
        break;
265
36
    case 0x63:
266
36
        snprintf(str, DESC_LEN, "UNIX System V (0x63)");
267
36
        break;
268
40
    case 0x64:
269
89
    case 0x65:
270
130
    case 0x66:
271
266
    case 0x67:
272
302
    case 0x68:
273
338
    case 0x69:
274
338
        snprintf(str, DESC_LEN, "Novell Netware (0x%.2x)", ptype);
275
338
        break;
276
42
    case 0x70:
277
42
        snprintf(str, DESC_LEN, "DiskSecure Multi-Boot (0x70)");
278
42
        break;
279
57
    case 0x74:
280
57
        snprintf(str, DESC_LEN, "Scramdisk (0x74)");
281
57
        break;
282
177
    case 0x75:
283
177
        snprintf(str, DESC_LEN, "IBM PC/IX (0x75)");
284
177
        break;
285
36
    case 0x77:
286
36
        snprintf(str, DESC_LEN, "VNDI (0x77)");
287
36
        break;
288
        /*case 0x77:
289
           snprintf(str, DESC_LEN, "M2FS/M2CS (0x77)");
290
           break; */
291
43
    case 0x78:
292
43
        snprintf(str, DESC_LEN, "XOSL FS (0x78)");
293
43
        break;
294
46
    case 0x80:
295
46
        snprintf(str, DESC_LEN, "MINIX <=v1.4a (0x80)");
296
46
        break;
297
42
    case 0x81:
298
42
        snprintf(str, DESC_LEN, "MINIX >=v1.4b, Early Linux (0x81)");
299
42
        break;
300
        /*case 0x81:
301
           snprintf(str, DESC_LEN, "Mitac Disk Manager (0x81)");
302
           break; */
303
49
    case 0x82:
304
49
        snprintf(str, DESC_LEN, "Linux Swap / Solaris x86 (0x82)");
305
49
        break;
306
47
    case 0x83:
307
47
        snprintf(str, DESC_LEN, "Linux (0x83)");
308
47
        break;
309
38
    case 0x84:
310
38
        snprintf(str, DESC_LEN, "Hibernation (0x84)");
311
38
        break;
312
601
    case 0x85:
313
601
        snprintf(str, DESC_LEN, "Linux Extended (0x85)");
314
601
        break;
315
43
    case 0x86:
316
43
        snprintf(str, DESC_LEN, "NTFS Volume Set (0x86)");
317
43
        break;
318
45
    case 0x87:
319
45
        snprintf(str, DESC_LEN, "NTFS Volume Set (0x87)");
320
45
        break;
321
62
    case 0x8a:
322
62
        snprintf(str, DESC_LEN, "Linux Kernel (0x8a)");
323
62
        break;
324
41
    case 0x8b:
325
41
        snprintf(str, DESC_LEN, "Legacy Fault Tolerant FAT32 (0x8b)");
326
41
        break;
327
65
    case 0x8c:
328
65
        snprintf(str, DESC_LEN,
329
65
            "Legacy Fault Tolerant FAT32 using BIOS extd INT 13h (0x8c)");
330
65
        break;
331
46
    case 0x8d:
332
46
        snprintf(str, DESC_LEN,
333
46
            "Free FDISK Hidden Primary DOS FAT12 (0x8d)");
334
46
        break;
335
102
    case 0x8e:
336
102
        snprintf(str, DESC_LEN, "Linux Logical Volume Manager (0x8e)");
337
102
        break;
338
55
    case 0x90:
339
55
        snprintf(str, DESC_LEN,
340
55
            "Free FDISK Hidden Primary DOS FAT16 (0x90)");
341
55
        break;
342
39
    case 0x91:
343
39
        snprintf(str, DESC_LEN, "Free FDISK Hidden DOS Extended (0x91)");
344
39
        break;
345
37
    case 0x92:
346
37
        snprintf(str, DESC_LEN,
347
37
            "Free FDISK Hidden Primary DOS Large FAT16 (0x92)");
348
37
        break;
349
66
    case 0x93:
350
66
        snprintf(str, DESC_LEN, "Linux Hidden (0x93)");
351
66
        break;
352
61
    case 0x94:
353
61
        snprintf(str, DESC_LEN, "Amoeba Bad Block Table (0x94)");
354
61
        break;
355
37
    case 0x95:
356
37
        snprintf(str, DESC_LEN, "MIT EXOPC (0x95)");
357
37
        break;
358
38
    case 0x97:
359
38
        snprintf(str, DESC_LEN,
360
38
            "Free FDISK Hidden Primary DOS FAT32 (0x97)");
361
38
        break;
362
64
    case 0x98:
363
64
        snprintf(str, DESC_LEN,
364
64
            "Free FDISK Hidden Primary DOS FAT32 LBA (0x98)");
365
64
        break;
366
        /*case 0x98:
367
           snprintf(str, DESC_LEN, "Datalight ROM-DOS Super-Boot (0x98)");
368
           break; */
369
50
    case 0x99:
370
50
        snprintf(str, DESC_LEN, "DCE376 Logical Drive (0x99)");
371
50
        break;
372
46
    case 0x9a:
373
46
        snprintf(str, DESC_LEN,
374
46
            "Free FDISK Hidden Primary DOS FAT16 LBA (0x9a)");
375
46
        break;
376
42
    case 0x9b:
377
42
        snprintf(str, DESC_LEN,
378
42
            "Free FDISK Hidden DOS Extended LBA (0x9b)");
379
42
        break;
380
47
    case 0x9f:
381
47
        snprintf(str, DESC_LEN, "BSD/OS (0x9f)");
382
47
        break;
383
49
    case 0xa0:
384
92
    case 0xa1:
385
92
        snprintf(str, DESC_LEN, "Hibernation (0x%.2x)", ptype);
386
92
        break;
387
62
    case 0xa3:
388
62
        snprintf(str, DESC_LEN,
389
62
            "HP Volume Expansion (SpeedStor Variant) (0xa3)");
390
62
        break;
391
43
    case 0xa4:
392
43
        snprintf(str, DESC_LEN,
393
43
            "HP Volume Expansion (SpeedStor Variant) (0xa4)");
394
43
        break;
395
47
    case 0xa5:
396
47
        snprintf(str, DESC_LEN, "BSD/386, 386BSD, NetBSD, FreeBSD (0xa5)");
397
47
        break;
398
37
    case 0xa6:
399
37
        snprintf(str, DESC_LEN, "OpenBSD (0xa6)");
400
37
        break;
401
47
    case 0xa7:
402
47
        snprintf(str, DESC_LEN, "NeXTSTEP (0xa7)");
403
47
        break;
404
39
    case 0xa8:
405
39
        snprintf(str, DESC_LEN, "Mac OS X (0xa8)");
406
39
        break;
407
42
    case 0xa9:
408
42
        snprintf(str, DESC_LEN, "NetBSD (0xa9)");
409
42
        break;
410
90
    case 0xaa:
411
90
        snprintf(str, DESC_LEN, "Olivetti Fat 12 1.44MB Service (0xaa)");
412
90
        break;
413
48
    case 0xab:
414
48
        snprintf(str, DESC_LEN, "Mac OS X Boot Partition (0xab)");
415
48
        break;
416
50
    case 0xae:
417
50
        snprintf(str, DESC_LEN, "ShagOS Filesystem (0xae)");
418
50
        break;
419
40
    case 0xaf:
420
40
        snprintf(str, DESC_LEN, "Mac OS X HFS (0xaf)");
421
40
        break;
422
53
    case 0xb0:
423
53
        snprintf(str, DESC_LEN, "BootStar Dummy (0xb0)");
424
53
        break;
425
42
    case 0xb1:
426
42
        snprintf(str, DESC_LEN,
427
42
            "HP Volume Expansion (SpeedStor Variant) (0xb1)");
428
42
        break;
429
56
    case 0xb3:
430
56
        snprintf(str, DESC_LEN,
431
56
            "HP Volume Expansion (SpeedStor Variant) (0xb3)");
432
56
        break;
433
38
    case 0xb4:
434
38
        snprintf(str, DESC_LEN,
435
38
            "HP Volume Expansion (SpeedStor Variant) (0xb4)");
436
38
        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
41
    case 0xb7:
445
41
        snprintf(str, DESC_LEN, "BSDI (0xb7)");
446
41
        break;
447
40
    case 0xb8:
448
40
        snprintf(str, DESC_LEN, "BSDI Swap (0xb8)");
449
40
        break;
450
37
    case 0xbb:
451
37
        snprintf(str, DESC_LEN, "Boot Wizard Hidden (0xbb)");
452
37
        break;
453
56
    case 0xbe:
454
56
        snprintf(str, DESC_LEN, "Solaris 8 Boot (0xbe)");
455
56
        break;
456
42
    case 0xc0:
457
42
        snprintf(str, DESC_LEN, "DR-DOS Secured (0xc0)");
458
42
        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
42
    case 0xc1:
469
42
        snprintf(str, DESC_LEN, "DR-DOS Secured FAT12 (0xc1)");
470
42
        break;
471
40
    case 0xc2:
472
40
        snprintf(str, DESC_LEN, "Hidden Linux (0xc2)");
473
40
        break;
474
42
    case 0xc3:
475
42
        snprintf(str, DESC_LEN, "Hidden Linux Swap (0xc3)");
476
42
        break;
477
49
    case 0xc4:
478
49
        snprintf(str, DESC_LEN, "DR-DOS Secured FAT16 <32M (0xc4)");
479
49
        break;
480
61
    case 0xc5:
481
61
        snprintf(str, DESC_LEN, "DR-DOS Secured Extended (0xc5)");
482
61
        break;
483
46
    case 0xc6:
484
93
    case 0xc7:
485
93
        snprintf(str, DESC_LEN,
486
93
            "Corrupted Windows NT Volume / Stripe Set (0x%.2x)", ptype);
487
93
        break;
488
41
    case 0xc8:
489
41
        snprintf(str, DESC_LEN, "Reserved for DR-DOS 8.0+ (0xc8)");
490
41
        break;
491
41
    case 0xc9:
492
41
        snprintf(str, DESC_LEN, "Reserved for DR-DOS 8.0+ (0xc9)");
493
41
        break;
494
54
    case 0xca:
495
54
        snprintf(str, DESC_LEN, "Reserved for DR-DOS 8.0+ (0xca)");
496
54
        break;
497
55
    case 0xcb:
498
55
        snprintf(str, DESC_LEN, "DR-DOS 7.04+ Secured FAT32 CHS (0xcb)");
499
55
        break;
500
58
    case 0xcc:
501
58
        snprintf(str, DESC_LEN, "DR-DOS 7.04+ Secured FAT32 LBA (0xcc)");
502
58
        break;
503
38
    case 0xcd:
504
38
        snprintf(str, DESC_LEN, "CTOS Memdump? (0xcd)");
505
38
        break;
506
56
    case 0xce:
507
56
        snprintf(str, DESC_LEN, "DR-DOS 7.04+ FAT16X LBA (0xce)");
508
56
        break;
509
54
    case 0xcf:
510
54
        snprintf(str, DESC_LEN, "DR-DOS 7.04+ Secured EXT DOS LBA (0xcf)");
511
54
        break;
512
50
    case 0xd0:
513
50
        snprintf(str, DESC_LEN, "Multiuser DOS Secured (0xd0)");
514
50
        break;
515
        /*case 0xd0:
516
           snprintf(str, DESC_LEN, "REAL/32 Secure Big (0xd0)");
517
           break; */
518
47
    case 0xd1:
519
47
        snprintf(str, DESC_LEN, "Old Multiuser DOS Secured FAT12 (0xd1)");
520
47
        break;
521
34
    case 0xd4:
522
34
        snprintf(str, DESC_LEN,
523
34
            "Old Multiuser DOS Secured FAT16 <32M (0xd4)");
524
34
        break;
525
40
    case 0xd5:
526
40
        snprintf(str, DESC_LEN,
527
40
            "Old Multiuser DOS Secured extended (0xd5)");
528
40
        break;
529
36
    case 0xd6:
530
36
        snprintf(str, DESC_LEN,
531
36
            "Old Multiuser DOS Secured FAT16 >=32M (0xd6)");
532
36
        break;
533
39
    case 0xd8:
534
39
        snprintf(str, DESC_LEN, "CP/M-86 (0xd8)");
535
39
        break;
536
52
    case 0xda:
537
52
        snprintf(str, DESC_LEN, "Non-FS Data (0xda)");
538
52
        break;
539
52
    case 0xdb:
540
52
        snprintf(str, DESC_LEN,
541
52
            "Digital Research CP/M, Concurrent CP/M, Concurrent DOS (0xdb)");
542
52
        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
40
    case 0xdd:
550
40
        snprintf(str, DESC_LEN, "Hidden CTOS Memdump?  (0xdd)");
551
40
        break;
552
59
    case 0xde:
553
59
        snprintf(str, DESC_LEN, "Dell Utilities FAT (0xde)");
554
59
        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
44
    case 0xe0:
562
44
        snprintf(str, DESC_LEN,
563
44
            "Reserved by STMicroelectronics for ST AVFS. (0xe0)");
564
44
        break;
565
42
    case 0xe1:
566
42
        snprintf(str, DESC_LEN,
567
42
            "DOS Access or SpeedStor 12-bit FAT Extended (0xe1)");
568
42
        break;
569
52
    case 0xe3:
570
52
        snprintf(str, DESC_LEN, "DOS R/O or SpeedStor (0xe3)");
571
52
        break;
572
34
    case 0xe4:
573
34
        snprintf(str, DESC_LEN,
574
34
            "SpeedStor 16-bit FAT Extended <1024 cyl. (0xe4)");
575
34
        break;
576
41
    case 0xe5:
577
41
        snprintf(str, DESC_LEN,
578
41
            "Tandy MS-DOS with Logically Sectored FAT (0xe5)");
579
41
        break;
580
56
    case 0xe6:
581
56
        snprintf(str, DESC_LEN, "Storage Dimensions SpeedStor (0xe6)");
582
56
        break;
583
74
    case 0xeb:
584
74
        snprintf(str, DESC_LEN, "BeOS BFS (0xeb)");
585
74
        break;
586
52
    case 0xee:
587
52
        snprintf(str, DESC_LEN, "GPT Safety Partition (0xee)");
588
52
        break;
589
59
    case 0xef:
590
59
        snprintf(str, DESC_LEN, "EFI File System (0xef)");
591
59
        break;
592
37
    case 0xf0:
593
37
        snprintf(str, DESC_LEN, "Linux/PA-RISC Boot Loader (0xf0)");
594
37
        break;
595
39
    case 0xf1:
596
39
        snprintf(str, DESC_LEN, "Storage Dimensions SpeedStor (0xf1)");
597
39
        break;
598
38
    case 0xf2:
599
38
        snprintf(str, DESC_LEN, "DOS 3.3+ Secondary (0xf2)");
600
38
        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
41
    case 0xf5:
608
41
        snprintf(str, DESC_LEN, "Prologue Multi-Volume (0xf5)");
609
41
        break;
610
41
    case 0xf6:
611
41
        snprintf(str, DESC_LEN, "Storage Dimensions SpeedStor (0xf6)");
612
41
        break;
613
47
    case 0xf9:
614
47
        snprintf(str, DESC_LEN, "pCache (0xf9)");
615
47
        break;
616
61
    case 0xfa:
617
61
        snprintf(str, DESC_LEN, "Bochs (0xfa)");
618
61
        break;
619
78
    case 0xfb:
620
78
        snprintf(str, DESC_LEN, "VMWare File System (0xfb)");
621
78
        break;
622
49
    case 0xfc:
623
49
        snprintf(str, DESC_LEN, "VMWare Swap (0xfc)");
624
49
        break;
625
55
    case 0xfd:
626
55
        snprintf(str, DESC_LEN, "Linux RAID (0xfd)");
627
55
        break;
628
61
    case 0xfe:
629
61
        snprintf(str, DESC_LEN,
630
61
            "Windows NT Disk Administrator Hidden (0xfe)");
631
61
        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
218
    case 0xff:
645
218
        snprintf(str, DESC_LEN, "Xenix Bad Block Table (0xff)");
646
218
        break;
647
344
    default:
648
344
        snprintf(str, DESC_LEN, "Unknown Type (0x%.2x)", ptype);
649
344
        break;
650
15.4k
    }
651
652
15.4k
    return str;
653
15.4k
}
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.63k
{
673
4.63k
    dos_sect *sect;
674
4.63k
    char *sect_buf;
675
4.63k
    int i;
676
4.63k
    char *table_str;
677
4.63k
    ssize_t cnt;
678
4.63k
    TSK_DADDR_T max_addr = (vs->img_info->size - vs->offset) / vs->block_size;  // max sector
679
680
4.63k
    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.63k
    if ((sect_buf = tsk_malloc(vs->block_size)) == NULL)
687
0
        return 1;
688
4.63k
    sect = (dos_sect *) sect_buf;
689
690
    /* Read the partition table sector */
691
4.63k
    cnt = tsk_vs_read_block(vs, sect_cur, sect_buf, vs->block_size);
692
4.63k
    if (cnt != vs->block_size) {
693
438
        if (cnt >= 0) {
694
167
            tsk_error_reset();
695
167
            tsk_error_set_errno(TSK_ERR_VS_READ);
696
167
        }
697
438
        tsk_error_set_errstr2("Extended DOS table sector %" PRIuDADDR,
698
438
            sect_cur);
699
438
        free(sect_buf);
700
438
        return 1;
701
438
    }
702
703
    /* Sanity Check */
704
4.20k
    if (tsk_getu16(vs->endian, sect->magic) != DOS_MAGIC) {
705
313
        tsk_error_reset();
706
313
        tsk_error_set_errno(TSK_ERR_VS_MAGIC);
707
313
        tsk_error_set_errstr("Extended DOS partition table in sector %"
708
313
            PRIuDADDR, sect_cur);
709
313
        free(sect_buf);
710
313
        return 1;
711
313
    }
712
713
    /* Add an entry of 1 length for the table  to the internal structure */
714
3.88k
    if ((table_str = tsk_malloc(32)) == NULL) {
715
0
        free(sect_buf);
716
0
        return 1;
717
0
    }
718
719
3.88k
    snprintf(table_str, 32, "Extended Table (#%d)", table);
720
3.88k
    if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) sect_cur,
721
3.88k
            (TSK_DADDR_T) 1, TSK_VS_PART_FLAG_META, table_str, table,
722
3.88k
            -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.5k
    for (i = 0; i < 4; i++) {
733
14.5k
        dos_part *part = &sect->ptable[i];
734
735
        /* Get the starting sector and size, we currently
736
         * ignore CHS */
737
14.5k
        uint32_t part_start = tsk_getu32(vs->endian, part->start_sec);
738
14.5k
        uint32_t part_size = tsk_getu32(vs->endian, part->size_sec);
739
740
14.5k
        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.5k
        if (part_size == 0 || part_start == 0)
748
3.34k
            continue;
749
750
        /* partitions are addressed differently
751
         * in extended partitions */
752
11.1k
        if (dos_is_ext(part->ptype)) {
753
754
2.09k
            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.09k
            part_info = vs->part_list;
761
40.4k
            while (part_info != NULL) {
762
38.7k
                if (part_info->start == (TSK_DADDR_T)(sect_ext_base + part_start)) {
763
408
                    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
408
                    tsk_error_reset();
769
408
                    tsk_error_set_errno(TSK_ERR_VS_BLK_NUM);
770
408
                    tsk_error_set_errstr
771
408
                        ("dos_load_ext_table: Loop in partition table detected");
772
408
                    free(sect_buf);
773
408
                    return 1;
774
408
                }
775
38.3k
                part_info = part_info->next;
776
38.3k
            }
777
778
            /* part start is added to the start of the
779
             * first extended partition (the primary
780
             * extended partition) */
781
782
1.69k
            if (NULL == tsk_vs_part_add(vs,
783
1.69k
                    (TSK_DADDR_T) (sect_ext_base + part_start),
784
1.69k
                    (TSK_DADDR_T) part_size, TSK_VS_PART_FLAG_META,
785
1.69k
                    dos_get_desc(part->ptype), table, i)) {
786
0
                free(sect_buf);
787
0
                return 1;
788
0
            }
789
790
1.69k
            if (sect_ext_base + part_start > max_addr) {
791
520
                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
520
            }
797
            /* Process the extended partition */
798
1.17k
            else if (dos_load_ext_table(vs, sect_ext_base + part_start,
799
1.17k
                    sect_ext_base, table + 1)) {
800
460
                free(sect_buf);
801
460
                return 1;
802
460
            }
803
1.69k
        }
804
805
9.06k
        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.06k
            if (NULL == tsk_vs_part_add(vs,
813
9.06k
                    (TSK_DADDR_T) (sect_cur + part_start),
814
9.06k
                    (TSK_DADDR_T) part_size, TSK_VS_PART_FLAG_ALLOC,
815
9.06k
                    dos_get_desc(part->ptype), table, i)) {
816
0
                free(sect_buf);
817
0
                return 1;
818
0
            }
819
9.06k
        }
820
11.1k
    }
821
822
3.01k
    free(sect_buf);
823
3.01k
    return 0;
824
3.88k
}
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.32k
{
841
1.32k
    dos_sect *sect;
842
1.32k
    char *sect_buf;
843
1.32k
    int i, added = 0;
844
1.32k
    char *table_str;
845
1.32k
    ssize_t cnt;
846
1.32k
    TSK_DADDR_T taddr = vs->offset / vs->block_size + DOS_PART_SOFFSET;
847
1.32k
    TSK_DADDR_T max_addr = (vs->img_info->size - vs->offset) / vs->block_size;  // max sector
848
849
1.32k
    if (tsk_verbose)
850
0
        tsk_fprintf(stderr,
851
0
            "dos_load_prim: Table Sector: %" PRIuDADDR "\n", taddr);
852
853
1.32k
    if ((sect_buf = tsk_malloc(vs->block_size)) == NULL)
854
0
        return 1;
855
1.32k
    sect = (dos_sect *) sect_buf;
856
857
    /* Read the table */
858
1.32k
    cnt = tsk_vs_read_block
859
1.32k
        (vs, DOS_PART_SOFFSET, sect_buf, vs->block_size);
860
861
1.32k
    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.31k
    if (tsk_vs_guessu16(vs, sect->magic, DOS_MAGIC)) {
875
39
        tsk_error_reset();
876
39
        tsk_error_set_errno(TSK_ERR_VS_MAGIC);
877
39
        tsk_error_set_errstr
878
39
            ("File is not a DOS partition (invalid primary magic) (Sector: %"
879
39
            PRIuDADDR ")", taddr);
880
39
        if (tsk_verbose)
881
0
            fprintf(stderr,
882
0
                "File is not a DOS partition (invalid primary magic) (Sector: %"
883
0
                PRIuDADDR ")", taddr);
884
39
        free(sect_buf);
885
39
        return 1;
886
39
    }
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.27k
    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.27k
    if ((table_str = tsk_malloc(32)) == NULL) {
945
0
        free(sect_buf);
946
0
        return 1;
947
0
    }
948
949
1.27k
    snprintf(table_str, 32, "Primary Table (#0)");
950
1.27k
    if (NULL == tsk_vs_part_add(vs, DOS_PART_SOFFSET, (TSK_DADDR_T) 1,
951
1.27k
            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
115
            continue;
971
972
        // make sure the first couple are in the image bounds
973
4.78k
        if ((i < 2) && (part_start > max_addr)) {
974
88
            tsk_error_reset();
975
88
            tsk_error_set_errno(TSK_ERR_VS_BLK_NUM);
976
88
            tsk_error_set_errstr
977
88
                ("dos_load_prim_table: Starting sector too large for image");
978
88
            if (tsk_verbose)
979
0
                tsk_fprintf(stderr,
980
0
                    "Starting sector %" PRIu32 " too large for image\n",
981
0
                    part_start);
982
88
            free(sect_buf);
983
88
            return 1;
984
88
        }
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.70k
        added = 1;
997
998
        /* Add the partition to the internal structure
999
         * If it is an extended partition, process it now */
1000
4.70k
        if (dos_is_ext(part->ptype)) {
1001
3.46k
            if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) part_start,
1002
3.46k
                    (TSK_DADDR_T) part_size, TSK_VS_PART_FLAG_META,
1003
3.46k
                    dos_get_desc(part->ptype), 0, i)) {
1004
0
                free(sect_buf);
1005
0
                return 1;
1006
0
            }
1007
1008
3.46k
            if (dos_load_ext_table(vs, part_start, part_start, 1)) {
1009
1.15k
                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.15k
                tsk_error_reset();
1015
1.15k
            }
1016
3.46k
        }
1017
1.23k
        else {
1018
1.23k
            if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) part_start,
1019
1.23k
                    (TSK_DADDR_T) part_size, TSK_VS_PART_FLAG_ALLOC,
1020
1.23k
                    dos_get_desc(part->ptype), 0, i)) {
1021
0
                free(sect_buf);
1022
0
                return 1;
1023
0
            }
1024
1.23k
        }
1025
4.70k
    }
1026
1.18k
    free(sect_buf);
1027
1028
1.18k
    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.18k
    return 0;
1039
1.18k
}
1040
1041
1042
static void
1043
dos_close(TSK_VS_INFO * vs)
1044
1.32k
{
1045
1.32k
    vs->tag = 0;
1046
1.32k
    tsk_vs_part_free(vs);
1047
1.32k
    free(vs);
1048
1.32k
}
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.32k
{
1064
1.32k
    TSK_VS_INFO *vs;
1065
1066
    // clean up any errors that are lying around
1067
1.32k
    tsk_error_reset();
1068
1069
1.32k
    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.32k
    vs = (TSK_VS_INFO *) tsk_malloc(sizeof(*vs));
1077
1.32k
    if (vs == NULL)
1078
0
        return NULL;
1079
1080
1.32k
    vs->vstype = TSK_VS_TYPE_DOS;
1081
1.32k
    vs->tag = TSK_VS_INFO_TAG;
1082
1.32k
    vs->img_info = img_info;
1083
1084
1.32k
    vs->offset = offset;
1085
1086
    /* initialize settings */
1087
1.32k
    vs->part_list = NULL;
1088
1.32k
    vs->part_count = 0;
1089
1.32k
    vs->endian = 0;
1090
1.32k
    vs->block_size = img_info->sector_size;
1091
1092
1093
    /* Assign functions */
1094
1.32k
    vs->close = dos_close;
1095
1096
    /* Load the partitions into the sorted list */
1097
1.32k
    if (dos_load_prim_table(vs, test)) {
1098
145
        dos_close(vs);
1099
145
        return NULL;
1100
145
    }
1101
1102
    /* fill in the sorted list with the 'unknown' values */
1103
1.18k
    if (tsk_vs_part_unused(vs)) {
1104
0
        dos_close(vs);
1105
0
        return NULL;
1106
0
    }
1107
1108
1.18k
    return vs;
1109
1.18k
}