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