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