/src/sleuthkit/tsk/vs/mac.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 mac.c |
12 | | * Contains the internal functions to process and load a Mac partition table. |
13 | | */ |
14 | | #include "tsk_vs_i.h" |
15 | | #include "tsk_mac.h" |
16 | | |
17 | | |
18 | | /* |
19 | | * Process the partition table at the sector address |
20 | | * |
21 | | * It is loaded into the internal sorted list |
22 | | * |
23 | | * Return 1 on error and 0 on success |
24 | | */ |
25 | | static uint8_t |
26 | | mac_load_table(TSK_VS_INFO * vs) |
27 | 1.16k | { |
28 | 1.16k | char *part_buf; |
29 | 1.16k | mac_part *part; |
30 | 1.16k | char *table_str; |
31 | 1.16k | uint32_t idx, max_part; |
32 | 1.16k | TSK_DADDR_T taddr = vs->offset / vs->block_size + MAC_PART_SOFFSET; |
33 | 1.16k | TSK_DADDR_T max_addr = (vs->img_info->size - vs->offset) / vs->block_size; // max sector |
34 | | |
35 | 1.16k | if (tsk_verbose) |
36 | 0 | tsk_fprintf(stderr, "mac_load_table: Sector: %" PRIuDADDR "\n", |
37 | 0 | taddr); |
38 | | |
39 | | /* The table can be variable length, so we loop on it |
40 | | * The idx variable shows which round it is |
41 | | * Each structure is a block size |
42 | | */ |
43 | 1.16k | if ((part_buf = tsk_malloc(vs->block_size)) == NULL) |
44 | 0 | return 1; |
45 | 1.16k | part = (mac_part *) part_buf; |
46 | | |
47 | 1.16k | max_part = 1; /* set it to 1 and it will be set in the first loop */ |
48 | 87.2k | for (idx = 0; idx < max_part; idx++) { |
49 | 86.9k | uint32_t part_start; |
50 | 86.9k | uint32_t part_size; |
51 | 86.9k | uint32_t part_status; |
52 | 86.9k | char *str; |
53 | 86.9k | ssize_t cnt; |
54 | 86.9k | int flag = 0; |
55 | | |
56 | | |
57 | | /* Read the entry */ |
58 | 86.9k | cnt = tsk_vs_read_block |
59 | 86.9k | (vs, MAC_PART_SOFFSET + idx, part_buf, vs->block_size); |
60 | | |
61 | | /* If -1, then tsk_errno is already set */ |
62 | 86.9k | if (cnt != vs->block_size) { |
63 | 586 | if (cnt >= 0) { |
64 | 184 | tsk_error_reset(); |
65 | 184 | tsk_error_set_errno(TSK_ERR_VS_READ); |
66 | 184 | } |
67 | 586 | tsk_error_set_errstr2("MAC Partition entry %" PRIuDADDR, |
68 | 586 | taddr + idx); |
69 | 586 | free(part_buf); |
70 | 586 | return 1; |
71 | 586 | } |
72 | | |
73 | | |
74 | | /* Sanity Check */ |
75 | 86.3k | if (idx == 0) { |
76 | | /* Set the endian ordering the first time around */ |
77 | 872 | if (tsk_vs_guessu16(vs, part->magic, MAC_MAGIC)) { |
78 | 125 | tsk_error_reset(); |
79 | 125 | tsk_error_set_errno(TSK_ERR_VS_MAGIC); |
80 | 125 | tsk_error_set_errstr("Mac partition table entry (Sector: %" |
81 | 125 | PRIuDADDR ") %" PRIx16, |
82 | 125 | (taddr + idx), tsk_getu16(vs->endian, part->magic)); |
83 | 125 | if (tsk_verbose) |
84 | 0 | tsk_fprintf(stderr, |
85 | 0 | "mac_load: Missing initial magic value\n"); |
86 | 125 | free(part_buf); |
87 | 125 | return 1; |
88 | 125 | } |
89 | | |
90 | | /* Get the number of partitions */ |
91 | 747 | max_part = tsk_getu32(vs->endian, part->pmap_size); |
92 | 747 | } |
93 | 85.5k | else if (tsk_getu16(vs->endian, part->magic) != MAC_MAGIC) { |
94 | 106 | tsk_error_reset(); |
95 | 106 | tsk_error_set_errno(TSK_ERR_VS_MAGIC); |
96 | 106 | tsk_error_set_errstr("Mac partition table entry (Sector: %" |
97 | 106 | PRIuDADDR ") %" PRIx16, (taddr + idx), |
98 | 106 | tsk_getu16(vs->endian, part->magic)); |
99 | 106 | if (tsk_verbose) |
100 | 0 | tsk_fprintf(stderr, |
101 | 0 | "mac_load: Missing magic value in entry %" PRIu32 "\n", |
102 | 0 | idx); |
103 | 106 | free(part_buf); |
104 | 106 | return 1; |
105 | 106 | } |
106 | | |
107 | | |
108 | 86.1k | part_start = tsk_getu32(vs->endian, part->start_sec); |
109 | 86.1k | part_size = tsk_getu32(vs->endian, part->size_sec); |
110 | 86.1k | part_status = tsk_getu32(vs->endian, part->status); |
111 | | |
112 | 86.1k | if (tsk_verbose) |
113 | 0 | tsk_fprintf(stderr, |
114 | 0 | "mac_load: %" PRIu32 " Starting Sector: %" PRIu32 |
115 | 0 | " Size: %" PRIu32 " Type: %s Status: %"PRIu32"\n", idx, part_start, |
116 | 0 | part_size, part->type, part_status); |
117 | | |
118 | 86.1k | if (part_size == 0) |
119 | 7.66k | continue; |
120 | | |
121 | 78.4k | if (part_status == 0) |
122 | 1.33k | flag = TSK_VS_PART_FLAG_UNALLOC; |
123 | 77.1k | else |
124 | 77.1k | flag = TSK_VS_PART_FLAG_ALLOC; |
125 | | |
126 | | // make sure the first couple are within the bounds of the image. |
127 | 78.4k | if ((idx < 2) && (part_start > max_addr)) { |
128 | 98 | tsk_error_reset(); |
129 | 98 | tsk_error_set_errno(TSK_ERR_VS_BLK_NUM); |
130 | 98 | tsk_error_set_errstr |
131 | 98 | ("mac_load_table: Starting sector too large for image"); |
132 | 98 | if (tsk_verbose) |
133 | 0 | tsk_fprintf(stderr, |
134 | 0 | "mac_load: Starting sector too large for image (%" |
135 | 0 | PRIu32 " vs %" PRIu32 ")\n", part_start, max_addr); |
136 | 98 | free(part_buf); |
137 | 98 | return 1; |
138 | 98 | } |
139 | | |
140 | | |
141 | 78.3k | if ((str = tsk_malloc(sizeof(part->name))) == NULL) { |
142 | 0 | free(part_buf); |
143 | 0 | return 1; |
144 | 0 | } |
145 | | |
146 | 78.3k | strncpy(str, (char *) part->type, sizeof(part->name)); |
147 | 78.3k | str[sizeof(part->name) - 1] = 0; |
148 | | |
149 | 78.3k | if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) part_start, |
150 | 78.3k | (TSK_DADDR_T) part_size, (TSK_VS_PART_FLAG_ENUM)flag, str, -1, |
151 | 78.3k | idx)) { |
152 | 0 | free(part_buf); |
153 | 0 | return 1; |
154 | 0 | } |
155 | 78.3k | } |
156 | 251 | free(part_buf); |
157 | 251 | part_buf = NULL; |
158 | | |
159 | | // Bail if we didn't find any valid entries |
160 | 251 | if (vs->part_count == 0) { |
161 | 3 | return 1; |
162 | 3 | } |
163 | | |
164 | | /* Add an entry for the table length */ |
165 | 248 | if ((table_str = tsk_malloc(16)) == NULL) { |
166 | 0 | return 1; |
167 | 0 | } |
168 | | |
169 | 248 | snprintf(table_str, 16, "Table"); |
170 | 248 | if (NULL == tsk_vs_part_add(vs, taddr, max_part, TSK_VS_PART_FLAG_META, |
171 | 248 | table_str, -1, -1)) { |
172 | 0 | return 1; |
173 | 0 | } |
174 | | |
175 | 248 | return 0; |
176 | 248 | } |
177 | | |
178 | | |
179 | | static void |
180 | | mac_close(TSK_VS_INFO * vs) |
181 | 675 | { |
182 | 675 | vs->tag = 0; |
183 | 675 | tsk_vs_part_free(vs); |
184 | 675 | free(vs); |
185 | 675 | } |
186 | | |
187 | | /* |
188 | | * Process img_info as a Mac disk. Initialize TSK_VS_INFO or return |
189 | | * NULL on error |
190 | | * */ |
191 | | TSK_VS_INFO * |
192 | | tsk_vs_mac_open(TSK_IMG_INFO * img_info, TSK_DADDR_T offset) |
193 | 675 | { |
194 | 675 | TSK_VS_INFO *vs; |
195 | | |
196 | | // clean up any errors that are lying around |
197 | 675 | tsk_error_reset(); |
198 | | |
199 | 675 | if (img_info->sector_size == 0) { |
200 | 0 | tsk_error_reset(); |
201 | 0 | tsk_error_set_errno(TSK_ERR_VS_ARG); |
202 | 0 | tsk_error_set_errstr("tsk_vs_mac_open: sector size is 0"); |
203 | 0 | return NULL; |
204 | 0 | } |
205 | | |
206 | 675 | vs = (TSK_VS_INFO *) tsk_malloc(sizeof(*vs)); |
207 | 675 | if (vs == NULL) |
208 | 0 | return NULL; |
209 | | |
210 | 675 | vs->img_info = img_info; |
211 | 675 | vs->vstype = TSK_VS_TYPE_MAC; |
212 | 675 | vs->tag = TSK_VS_INFO_TAG; |
213 | | |
214 | | /* If an offset was given, then use that too */ |
215 | 675 | vs->offset = offset; |
216 | | |
217 | | //vs->sect_offset = offset + MAC_PART_OFFSET; |
218 | | |
219 | | /* initialize settings */ |
220 | 675 | vs->part_list = NULL; |
221 | 675 | vs->part_count = 0; |
222 | 675 | vs->endian = 0; |
223 | 675 | vs->block_size = img_info->sector_size; |
224 | | |
225 | | /* Assign functions */ |
226 | 675 | vs->close = mac_close; |
227 | | |
228 | | /* Load the partitions into the sorted list */ |
229 | 675 | if (mac_load_table(vs)) { |
230 | | |
231 | | // try some other sector sizes |
232 | 491 | uint8_t returnNull = 1; |
233 | 491 | if (vs->block_size == 512) { |
234 | 491 | if (tsk_verbose) |
235 | 0 | tsk_fprintf(stderr, |
236 | 0 | "mac_open: Trying 4096-byte sector size instead of 512-byte\n"); |
237 | 491 | vs->block_size = 4096; |
238 | 491 | returnNull = mac_load_table(vs); |
239 | 491 | } |
240 | 0 | else if (vs->block_size == 4096) { |
241 | 0 | if (tsk_verbose) |
242 | 0 | tsk_fprintf(stderr, |
243 | 0 | "mac_open: Trying 512-byte sector size instead of 4096-byte\n"); |
244 | 0 | vs->block_size = 512; |
245 | 0 | returnNull = mac_load_table(vs); |
246 | 0 | } |
247 | | |
248 | 491 | if (returnNull) { |
249 | 427 | mac_close(vs); |
250 | 427 | return NULL; |
251 | 427 | } |
252 | 491 | } |
253 | | |
254 | | /* fill in the sorted list with the 'unknown' values */ |
255 | 248 | if (tsk_vs_part_unused(vs)) { |
256 | 0 | mac_close(vs); |
257 | 0 | return NULL; |
258 | 0 | } |
259 | | |
260 | 248 | return vs; |
261 | 248 | } |