/src/sleuthkit/tsk/vs/bsd.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 bsd.c |
12 | | * Contains the internal functions required to process BSD disk labels. |
13 | | */ |
14 | | #include "tsk_vs_i.h" |
15 | | #include "tsk_bsd.h" |
16 | | |
17 | | |
18 | | /* |
19 | | * Return a buffer with a description of the partition type. The buffer |
20 | | * must be freed by the caller. |
21 | | */ |
22 | | static char * |
23 | | bsd_get_desc(uint8_t fstype) |
24 | 0 | { |
25 | 0 | char *str = tsk_malloc(64); |
26 | 0 | if (str == NULL) |
27 | 0 | return ""; |
28 | | |
29 | 0 | switch (fstype) { |
30 | | |
31 | 0 | case 0: |
32 | 0 | strncpy(str, "Unused (0x00)", 64); |
33 | 0 | break; |
34 | 0 | case 1: |
35 | 0 | strncpy(str, "Swap (0x01)", 64); |
36 | 0 | break; |
37 | 0 | case 2: |
38 | 0 | strncpy(str, "Version 6 (0x02)", 64); |
39 | 0 | break; |
40 | 0 | case 3: |
41 | 0 | strncpy(str, "Version 7 (0x03)", 64); |
42 | 0 | break; |
43 | 0 | case 4: |
44 | 0 | strncpy(str, "System V (0x04)", 64); |
45 | 0 | break; |
46 | 0 | case 5: |
47 | 0 | strncpy(str, "4.1BSD (0x05)", 64); |
48 | 0 | break; |
49 | 0 | case 6: |
50 | 0 | strncpy(str, "Eighth Edition (0x06)", 64); |
51 | 0 | break; |
52 | 0 | case 7: |
53 | 0 | strncpy(str, "4.2BSD (0x07)", 64); |
54 | 0 | break; |
55 | 0 | case 8: |
56 | 0 | strncpy(str, "MSDOS (0x08)", 64); |
57 | 0 | break; |
58 | 0 | case 9: |
59 | 0 | strncpy(str, "4.4LFS (0x09)", 64); |
60 | 0 | break; |
61 | 0 | case 10: |
62 | 0 | strncpy(str, "Unknown (0x0A)", 64); |
63 | 0 | break; |
64 | 0 | case 11: |
65 | 0 | strncpy(str, "HPFS (0x0B)", 64); |
66 | 0 | break; |
67 | 0 | case 12: |
68 | 0 | strncpy(str, "ISO9660 (0x0C)", 64); |
69 | 0 | break; |
70 | 0 | case 13: |
71 | 0 | strncpy(str, "Boot (0x0D)", 64); |
72 | 0 | break; |
73 | 0 | case 14: |
74 | 0 | strncpy(str, "Vinum (0x0E)", 64); |
75 | 0 | break; |
76 | 0 | default: |
77 | 0 | snprintf(str, 64, "Unknown Type (0x%.2x)", fstype); |
78 | 0 | break; |
79 | 0 | } |
80 | | |
81 | 0 | return str; |
82 | 0 | } |
83 | | |
84 | | /* |
85 | | * Process the partition table at the sector address |
86 | | * |
87 | | * Return 1 on error and 0 if no error |
88 | | */ |
89 | | static uint8_t |
90 | | bsd_load_table(TSK_VS_INFO * a_vs) |
91 | 0 | { |
92 | 0 | char *sect_buf; |
93 | 0 | bsd_disklabel *dlabel; |
94 | 0 | uint32_t idx = 0; |
95 | 0 | ssize_t cnt; |
96 | 0 | char *table_str; |
97 | 0 | TSK_DADDR_T laddr = a_vs->offset / a_vs->block_size + BSD_PART_SOFFSET; // used for printing only |
98 | 0 | TSK_DADDR_T max_addr = (a_vs->img_info->size - a_vs->offset) / a_vs->block_size; // max sector |
99 | |
|
100 | 0 | if (tsk_verbose) |
101 | 0 | tsk_fprintf(stderr, |
102 | 0 | "bsd_load_table: Table Sector: %" PRIuDADDR "\n", laddr); |
103 | |
|
104 | 0 | if ((sect_buf = tsk_malloc(a_vs->block_size)) == NULL) |
105 | 0 | return 1; |
106 | 0 | dlabel = (bsd_disklabel *) sect_buf; |
107 | | |
108 | | /* read the block */ |
109 | 0 | cnt = tsk_vs_read_block |
110 | 0 | (a_vs, BSD_PART_SOFFSET, sect_buf, a_vs->block_size); |
111 | 0 | if (cnt != a_vs->block_size) { |
112 | 0 | if (cnt >= 0) { |
113 | 0 | tsk_error_reset(); |
114 | 0 | tsk_error_set_errno(TSK_ERR_VS_READ); |
115 | 0 | } |
116 | 0 | tsk_error_set_errstr2("BSD Disk Label in Sector: %" PRIuDADDR, |
117 | 0 | laddr); |
118 | 0 | free(sect_buf); |
119 | 0 | return 1; |
120 | 0 | } |
121 | | |
122 | | /* Check the magic */ |
123 | 0 | if (tsk_vs_guessu32(a_vs, dlabel->magic, BSD_MAGIC)) { |
124 | 0 | tsk_error_reset(); |
125 | 0 | tsk_error_set_errno(TSK_ERR_VS_MAGIC); |
126 | 0 | tsk_error_set_errstr("BSD partition table (magic #1) (Sector: %" |
127 | 0 | PRIuDADDR ") %" PRIx32, laddr, tsk_getu32(a_vs->endian, |
128 | 0 | dlabel->magic)); |
129 | 0 | free(sect_buf); |
130 | 0 | return 1; |
131 | 0 | } |
132 | | |
133 | | /* Check the second magic value */ |
134 | 0 | if (tsk_getu32(a_vs->endian, dlabel->magic2) != BSD_MAGIC) { |
135 | 0 | tsk_error_reset(); |
136 | 0 | tsk_error_set_errno(TSK_ERR_VS_MAGIC); |
137 | 0 | tsk_error_set_errstr("BSD disk label (magic #2) (Sector: %" |
138 | 0 | PRIuDADDR ") %" PRIx32, laddr, tsk_getu32(a_vs->endian, |
139 | 0 | dlabel->magic2)); |
140 | 0 | free(sect_buf); |
141 | 0 | return 1; |
142 | 0 | } |
143 | | |
144 | | /* Add an entry of 1 length for the table to the internal structure */ |
145 | 0 | if ((table_str = tsk_malloc(32)) == NULL) { |
146 | 0 | free(sect_buf); |
147 | 0 | return 1; |
148 | 0 | } |
149 | | |
150 | 0 | snprintf(table_str, 32, "Partition Table"); |
151 | 0 | if (NULL == tsk_vs_part_add(a_vs, BSD_PART_SOFFSET, |
152 | 0 | (TSK_DADDR_T) 1, TSK_VS_PART_FLAG_META, table_str, -1, -1)) { |
153 | 0 | free(sect_buf); |
154 | 0 | return 1; |
155 | 0 | } |
156 | | |
157 | | /* Cycle through the partitions, there are either 8 or 16 */ |
158 | 0 | for (idx = 0; idx < tsk_getu16(a_vs->endian, dlabel->num_parts); idx++) { |
159 | |
|
160 | 0 | uint32_t part_start; |
161 | 0 | uint32_t part_size; |
162 | |
|
163 | 0 | part_start = tsk_getu32(a_vs->endian, dlabel->part[idx].start_sec); |
164 | 0 | part_size = tsk_getu32(a_vs->endian, dlabel->part[idx].size_sec); |
165 | |
|
166 | 0 | if (tsk_verbose) |
167 | 0 | tsk_fprintf(stderr, |
168 | 0 | "load_table: %" PRIu32 " Starting Sector: %" PRIu32 |
169 | 0 | " Size: %" PRIu32 " Type: %d\n", idx, part_start, |
170 | 0 | part_size, dlabel->part[idx].fstype); |
171 | |
|
172 | 0 | if (part_size == 0) |
173 | 0 | continue; |
174 | | |
175 | | // make sure the first couple are in the image bounds |
176 | 0 | if ((idx < 2) && (part_start > max_addr)) { |
177 | 0 | tsk_error_reset(); |
178 | 0 | tsk_error_set_errno(TSK_ERR_VS_BLK_NUM); |
179 | 0 | tsk_error_set_errstr |
180 | 0 | ("bsd_load_table: Starting sector too large for image"); |
181 | 0 | free(sect_buf); |
182 | 0 | return 1; |
183 | 0 | } |
184 | | |
185 | | |
186 | | /* Add the partition to the internal sorted list */ |
187 | 0 | if (NULL == tsk_vs_part_add(a_vs, (TSK_DADDR_T) part_start, |
188 | 0 | (TSK_DADDR_T) part_size, TSK_VS_PART_FLAG_ALLOC, |
189 | 0 | bsd_get_desc(dlabel->part[idx].fstype), -1, idx)) { |
190 | 0 | free(sect_buf); |
191 | 0 | return 1; |
192 | 0 | } |
193 | 0 | } |
194 | | |
195 | 0 | free(sect_buf); |
196 | 0 | return 0; |
197 | 0 | } |
198 | | |
199 | | |
200 | | static void |
201 | | bsd_close(TSK_VS_INFO * a_vs) |
202 | 0 | { |
203 | 0 | a_vs->tag = 0; |
204 | 0 | tsk_vs_part_free(a_vs); |
205 | 0 | free(a_vs); |
206 | 0 | } |
207 | | |
208 | | /* |
209 | | * analyze the image in img_info and process it as BSD |
210 | | * Initialize the TSK_VS_INFO structure |
211 | | * |
212 | | * Return TSK_VS_INFO or NULL if not BSD or an error |
213 | | */ |
214 | | TSK_VS_INFO * |
215 | | tsk_vs_bsd_open(TSK_IMG_INFO * img_info, TSK_DADDR_T offset) |
216 | 0 | { |
217 | 0 | TSK_VS_INFO *vs; |
218 | | |
219 | | // clean up any errors that are lying around |
220 | 0 | tsk_error_reset(); |
221 | |
|
222 | 0 | if (img_info->sector_size == 0) { |
223 | 0 | tsk_error_reset(); |
224 | 0 | tsk_error_set_errno(TSK_ERR_VS_ARG); |
225 | 0 | tsk_error_set_errstr("tsk_vs_bsd_open: sector size is 0"); |
226 | 0 | return NULL; |
227 | 0 | } |
228 | | |
229 | 0 | vs = (TSK_VS_INFO *) tsk_malloc(sizeof(*vs)); |
230 | 0 | if (vs == NULL) |
231 | 0 | return NULL; |
232 | | |
233 | 0 | vs->img_info = img_info; |
234 | 0 | vs->vstype = TSK_VS_TYPE_BSD; |
235 | 0 | vs->tag = TSK_VS_INFO_TAG; |
236 | | |
237 | | /* use the offset provided */ |
238 | 0 | vs->offset = offset; |
239 | | |
240 | | /* initialize settings */ |
241 | 0 | vs->part_list = NULL; |
242 | 0 | vs->part_count = 0; |
243 | 0 | vs->endian = 0; |
244 | 0 | vs->block_size = img_info->sector_size; |
245 | | |
246 | | /* Assign functions */ |
247 | 0 | vs->close = bsd_close; |
248 | | |
249 | | /* Load the partitions into the sorted list */ |
250 | 0 | if (bsd_load_table(vs)) { |
251 | 0 | bsd_close(vs); |
252 | 0 | return NULL; |
253 | 0 | } |
254 | | |
255 | | /* fill in the sorted list with the 'unknown' values */ |
256 | 0 | if (tsk_vs_part_unused(vs)) { |
257 | 0 | bsd_close(vs); |
258 | 0 | return NULL; |
259 | 0 | } |
260 | | |
261 | 0 | return vs; |
262 | 0 | } |