Coverage Report

Created: 2025-07-01 06:59

/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
}