Coverage Report

Created: 2025-07-18 07:08

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