Coverage Report

Created: 2024-04-23 06:05

/src/sleuthkit/tsk/fs/hfs_dent.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
** The Sleuth Kit
3
**
4
** This software is subject to the IBM Public License ver. 1.0,
5
** which was displayed prior to download and is included in the readme.txt
6
** file accompanying the Sleuth Kit files.  It may also be requested from:
7
** Crucial Security Inc.
8
** 14900 Conference Center Drive
9
** Chantilly, VA 20151
10
**
11
** Copyright (c) 2009-2011 Brian Carrier.  All rights reserved.
12
**
13
** Judson Powers [jpowers@atc-nycorp.com]
14
** Matt Stillerman [matt@atc-nycorp.com]
15
** Copyright (c) 2008, 2012 ATC-NY.  All rights reserved.
16
** This file contains data developed with support from the National
17
** Institute of Justice, Office of Justice Programs, U.S. Department of Justice.
18
**
19
** Wyatt Banks [wbanks@crucialsecurity.com]
20
** Copyright (c) 2005 Crucial Security Inc.  All rights reserved.
21
**
22
** Brian Carrier [carrier@sleuthkit.org]
23
** Copyright (c) 2003-2005 Brian Carrier.  All rights reserved
24
**
25
** Copyright (c) 1997,1998,1999, International Business Machines
26
** Corporation and others. All Rights Reserved.
27
*/
28
29
/* TCT
30
 * LICENSE
31
 *      This software is distributed under the IBM Public License.
32
 * AUTHOR(S)
33
 *      Wietse Venema
34
 *      IBM T.J. Watson Research
35
 *      P.O. Box 704
36
 *      Yorktown Heights, NY 10598, USA
37
 --*/
38
39
/*
40
** You may distribute the Sleuth Kit, or other software that incorporates
41
** part of all of the Sleuth Kit, in object code form under a license agreement,
42
** provided that:
43
** a) you comply with the terms and conditions of the IBM Public License
44
**    ver 1.0; and
45
** b) the license agreement
46
**     i) effectively disclaims on behalf of all Contributors all warranties
47
**        and conditions, express and implied, including warranties or
48
**        conditions of title and non-infringement, and implied warranties
49
**        or conditions of merchantability and fitness for a particular
50
**        purpose.
51
**    ii) effectively excludes on behalf of all Contributors liability for
52
**        damages, including direct, indirect, special, incidental and
53
**        consequential damages such as lost profits.
54
**   iii) states that any provisions which differ from IBM Public License
55
**        ver. 1.0 are offered by that Contributor alone and not by any
56
**        other party; and
57
**    iv) states that the source code for the program is available from you,
58
**        and informs licensees how to obtain it in a reasonable manner on or
59
**        through a medium customarily used for software exchange.
60
**
61
** When the Sleuth Kit or other software that incorporates part or all of
62
** the Sleuth Kit is made available in source code form:
63
**     a) it must be made available under IBM Public License ver. 1.0; and
64
**     b) a copy of the IBM Public License ver. 1.0 must be included with
65
**        each copy of the program.
66
*/
67
68
/** \file hfs_dent.c
69
 * Contains the file name layer code for HFS+ file systems -- not included in
70
 * code by default.
71
 */
72
73
#include "tsk_fs_i.h"
74
#include "tsk_hfs.h"
75
76
/* convert HFS+'s UTF16 to UTF8
77
 * replaces null characters with another character (0xfffd)
78
 * replaces slashes (permitted by HFS+ but causes problems with TSK)
79
 *   with colons (generally not allowed by Mac OS X)
80
 * note that at least one directory on HFS+ volumes begins with
81
 *   four nulls, so we do need to handle nulls; also, Apple chooses
82
 *   to encode nulls as UTF8 \xC0\x80, which is not a valid UTF8 sequence
83
 *
84
 *   @param fs  the file system
85
 *   @param uni  the UTF16 string as a sequence of bytes
86
 *   @param ulen  then length of the UTF16 string in characters
87
 *   @param asc   a buffer to hold the UTF8 result
88
 *   @param alen  the length of that buffer
89
 *   @param flags  control some aspects of the conversion
90
 *   @return 0 on success, 1 on failure; sets up to error string 1
91
 *
92
 *   HFS_U16U8_FLAG_REPLACE_SLASH  if this flag is set, then slashes will be replaced
93
 *   by colons.  Otherwise, they will not be replaced.
94
 *
95
 *   HFS_U16U8_FLAG_REPLACE_CONTROL if this flag is set, then all control characters
96
 *   will be replaced by the UTF16_NULL_REPLACE character. N.B., always replaces
97
 *   null characters regardless of this flag.
98
 */
99
uint8_t
100
hfs_UTF16toUTF8(TSK_FS_INFO * fs, uint8_t * uni, int ulen, char *asc,
101
    int alen, uint32_t flags)
102
0
{
103
0
    UTF8 *ptr8;
104
0
    uint8_t *uniclean;
105
0
    UTF16 *ptr16;
106
0
    int i;
107
0
    TSKConversionResult r;
108
109
    // remove nulls from the Unicode string
110
    // convert / to :
111
0
    uniclean = (uint8_t *) tsk_malloc(ulen * 2);
112
0
    if (!uniclean)
113
0
        return 1;
114
115
0
    memcpy(uniclean, uni, ulen * 2);
116
117
0
    for (i = 0; i < ulen; ++i) {
118
0
        uint16_t uc = tsk_getu16(fs->endian, uniclean + i * 2);
119
120
121
0
        int changed = 0;
122
0
        if (uc == UTF16_NULL) {
123
0
            uc = UTF16_NULL_REPLACE;
124
0
            changed = 1;
125
0
        }
126
0
        else if ((flags & HFS_U16U8_FLAG_REPLACE_SLASH)
127
0
            && uc == UTF16_SLASH) {
128
0
            uc = UTF16_COLON;
129
0
            changed = 1;
130
0
        }
131
132
0
        else if ((flags & HFS_U16U8_FLAG_REPLACE_CONTROL)
133
0
            && uc < UTF16_LEAST_PRINTABLE) {
134
0
            uc = (uint16_t) UTF16_NULL_REPLACE;
135
0
            changed = 1;
136
0
        }
137
138
0
        if (changed)
139
0
            *((uint16_t *) (uniclean + i * 2)) =
140
0
                tsk_getu16(fs->endian, (uint8_t *) & uc);
141
0
    }
142
143
    // convert to UTF-8
144
0
    memset(asc, 0, alen);
145
146
0
    ptr8 = (UTF8 *) asc;
147
0
    ptr16 = (UTF16 *) uniclean;
148
0
    r = tsk_UTF16toUTF8(fs->endian, (const UTF16 **) &ptr16,
149
0
        (const UTF16 *) (&uniclean[ulen * 2]), &ptr8,
150
0
        (UTF8 *) & asc[alen], TSKstrictConversion);
151
152
0
    free(uniclean);
153
0
    if (r != TSKconversionOK) {
154
0
        tsk_error_set_errno(TSK_ERR_FS_UNICODE);
155
0
        tsk_error_set_errstr
156
0
            ("hfs_UTF16toUTF8: unicode conversion failed (%d)", (int) r);
157
0
        return 1;
158
0
    }
159
160
0
    return 0;
161
0
}
162
163
static TSK_FS_NAME_TYPE_ENUM
164
hfsmode2tsknametype(uint16_t a_mode)
165
0
{
166
0
    switch (a_mode & HFS_IN_IFMT) {
167
0
    case HFS_IN_IFIFO:
168
0
        return TSK_FS_NAME_TYPE_FIFO;
169
0
    case HFS_IN_IFCHR:
170
0
        return TSK_FS_NAME_TYPE_CHR;
171
0
    case HFS_IN_IFDIR:
172
0
        return TSK_FS_NAME_TYPE_DIR;
173
0
    case HFS_IN_IFBLK:
174
0
        return TSK_FS_NAME_TYPE_BLK;
175
0
    case HFS_IN_IFREG:
176
0
        return TSK_FS_NAME_TYPE_REG;
177
0
    case HFS_IN_IFLNK:
178
0
        return TSK_FS_NAME_TYPE_LNK;
179
0
    case HFS_IN_IFSOCK:
180
0
        return TSK_FS_NAME_TYPE_SOCK;
181
0
    case HFS_IFWHT:
182
0
        return TSK_FS_NAME_TYPE_WHT;
183
0
    case HFS_IFXATTR:
184
0
        return TSK_FS_NAME_TYPE_UNDEF;
185
0
    default:
186
        /* error */
187
0
        return TSK_FS_NAME_TYPE_UNDEF;
188
0
    }
189
0
}
190
191
192
// used to pass data to the callback
193
typedef struct {
194
    TSK_FS_DIR *fs_dir;
195
    TSK_FS_NAME *fs_name;
196
    uint32_t cnid;
197
} HFS_DIR_OPEN_META_INFO;
198
199
static uint8_t
200
hfs_dir_open_meta_cb(HFS_INFO * hfs, int8_t level_type,
201
    const hfs_btree_key_cat * cur_key, int cur_keylen, size_t nodesize,
202
    TSK_OFF_T key_off, void *ptr)
203
0
{
204
0
    HFS_DIR_OPEN_META_INFO *info = (HFS_DIR_OPEN_META_INFO *) ptr;
205
0
    TSK_FS_INFO *fs = &hfs->fs_info;
206
207
0
    if (tsk_verbose)
208
0
        fprintf(stderr,
209
0
            "hfs_dir_open_meta_cb: want %" PRIu32 " vs got %" PRIu32
210
0
            " (%s node)\n", info->cnid, tsk_getu32(hfs->fs_info.endian,
211
0
                cur_key->parent_cnid),
212
0
            (level_type == HFS_BT_NODE_TYPE_IDX) ? "Index" : "Leaf");
213
214
0
    if (level_type == HFS_BT_NODE_TYPE_IDX) {
215
0
        if (tsk_getu32(hfs->fs_info.endian,
216
0
                cur_key->parent_cnid) < info->cnid) {
217
0
            return HFS_BTREE_CB_IDX_LT;
218
0
        }
219
0
        else {
220
0
            return HFS_BTREE_CB_IDX_EQGT;
221
0
        }
222
0
    }
223
0
    else {
224
0
        uint8_t *rec_buf = (uint8_t *) cur_key;
225
0
        uint16_t rec_type;
226
0
        size_t rec_off2;
227
228
0
        if (tsk_getu32(hfs->fs_info.endian,
229
0
                cur_key->parent_cnid) < info->cnid) {
230
0
            return HFS_BTREE_CB_LEAF_GO;
231
0
        }
232
0
        else if (tsk_getu32(hfs->fs_info.endian,
233
0
                cur_key->parent_cnid) > info->cnid) {
234
0
            return HFS_BTREE_CB_LEAF_STOP;
235
0
        }
236
  // Need at least 2 bytes for key_len
237
0
        if (cur_keylen < 2) {
238
0
            tsk_error_set_errno(TSK_ERR_FS_GENFS);
239
0
            tsk_error_set_errstr("hfs_dir_open_meta: cur_keylen value out of bounds");
240
0
            return HFS_BTREE_CB_ERR;
241
0
        }
242
0
        rec_off2 = 2 + tsk_getu16(hfs->fs_info.endian, cur_key->key_len);
243
244
0
        if ((nodesize < 2) || (rec_off2 >= nodesize - 2)) {
245
0
            tsk_error_set_errno(TSK_ERR_FS_GENFS);
246
0
            tsk_error_set_errstr("hfs_dir_open_meta: nodesize value out of bounds");
247
0
            return HFS_BTREE_CB_ERR;
248
0
        }
249
0
        rec_type = tsk_getu16(hfs->fs_info.endian, &rec_buf[rec_off2]);
250
251
        // Catalog entry is for a file
252
0
        if (rec_type == HFS_FILE_THREAD) {
253
0
            tsk_error_set_errno(TSK_ERR_FS_GENFS);
254
0
            tsk_error_set_errstr("hfs_dir_open_meta: Entry"
255
0
                " is a file, not a folder");
256
0
            return HFS_BTREE_CB_ERR;
257
0
        }
258
259
        /* This will link the folder to its parent, which is the ".." entry */
260
0
        else if (rec_type == HFS_FOLDER_THREAD) {
261
0
            if ((nodesize < sizeof(hfs_thread)) || (rec_off2 > nodesize - sizeof(hfs_thread))) {
262
0
                tsk_error_set_errno(TSK_ERR_FS_GENFS);
263
0
                tsk_error_set_errstr("hfs_dir_open_meta: nodesize value out of bounds");
264
0
                return HFS_BTREE_CB_ERR;
265
0
            }
266
0
            hfs_thread *thread = (hfs_thread *) & rec_buf[rec_off2];
267
0
            strcpy(info->fs_name->name, "..");
268
0
            info->fs_name->meta_addr =
269
0
                tsk_getu32(hfs->fs_info.endian, thread->parent_cnid);
270
0
            info->fs_name->type = TSK_FS_NAME_TYPE_DIR;
271
0
            info->fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;
272
0
        }
273
274
        /* This is a folder in the folder */
275
0
        else if (rec_type == HFS_FOLDER_RECORD) {
276
0
            if ((nodesize < sizeof(hfs_folder)) || (rec_off2 > nodesize - sizeof(hfs_folder))) {
277
0
                tsk_error_set_errno(TSK_ERR_FS_GENFS);
278
0
                tsk_error_set_errstr("hfs_dir_open_meta: nodesize value out of bounds");
279
0
                return HFS_BTREE_CB_ERR;
280
0
            }
281
0
            hfs_folder *folder = (hfs_folder *) & rec_buf[rec_off2];
282
283
0
            info->fs_name->meta_addr =
284
0
                tsk_getu32(hfs->fs_info.endian, folder->std.cnid);
285
0
            info->fs_name->type = TSK_FS_NAME_TYPE_DIR;
286
0
            info->fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;
287
288
            // Make sure there is enough space in cur_key for the name 
289
            // (name is unicode so each characters is two bytes; 6 bytes
290
            // of non-name characters)
291
0
            const int32_t nameLength =
292
0
                tsk_getu16(hfs->fs_info.endian, cur_key->name.length);
293
294
0
            if (2*nameLength > tsk_getu16(hfs->fs_info.endian, cur_key->key_len) - 6) {
295
0
                error_returned
296
0
                ("hfs_dir_open_meta_cb: name length is too long");
297
0
                return HFS_BTREE_CB_ERR;
298
0
            }
299
0
            if (hfs_UTF16toUTF8(fs, (uint8_t *) cur_key->name.unicode,
300
0
                    nameLength, info->fs_name->name, HFS_MAXNAMLEN + 1,
301
0
                    HFS_U16U8_FLAG_REPLACE_SLASH)) {
302
0
                return HFS_BTREE_CB_ERR;
303
0
            }
304
0
        }
305
306
        /* This is a normal file in the folder */
307
0
        else if (rec_type == HFS_FILE_RECORD) {
308
0
            if ((nodesize < sizeof(hfs_file)) || (rec_off2 > nodesize - sizeof(hfs_file))) {
309
0
                tsk_error_set_errno(TSK_ERR_FS_GENFS);
310
0
                tsk_error_set_errstr("hfs_dir_open_meta: nodesize value out of bounds");
311
0
                return HFS_BTREE_CB_ERR;
312
0
            }
313
0
            hfs_file *file = (hfs_file *) & rec_buf[rec_off2];
314
            // This could be a hard link.  We need to test this CNID, and follow it if necessary.
315
0
            unsigned char is_err;
316
0
            TSK_INUM_T file_cnid =
317
0
                tsk_getu32(hfs->fs_info.endian, file->std.cnid);
318
0
            TSK_INUM_T target_cnid =
319
0
                hfs_follow_hard_link(hfs, file, &is_err);
320
0
            if (is_err > 1) {
321
0
                error_returned
322
0
                    ("hfs_dir_open_meta_cb: trying to follow a possible hard link in the directory");
323
0
                return HFS_BTREE_CB_ERR;
324
0
            }
325
0
            if (target_cnid != file_cnid) {
326
0
                HFS_ENTRY entry;
327
0
                uint8_t lkup;   // lookup result
328
329
                // This is a hard link.  We need to fill in the name->type and name->meta_addr from the target
330
0
                info->fs_name->meta_addr = target_cnid;
331
                // get the Catalog entry for the target CNID
332
333
0
                lkup = hfs_cat_file_lookup(hfs, target_cnid, &entry,
334
0
                    FALSE);
335
0
                if (lkup != 0) {
336
0
                    error_returned
337
0
                        ("hfs_dir_open_meta_cb: retrieving the catalog entry for the target of a hard link");
338
0
                    return HFS_BTREE_CB_ERR;
339
0
                }
340
0
                info->fs_name->type =
341
0
                    hfsmode2tsknametype(tsk_getu16(hfs->fs_info.endian,
342
0
                        entry.cat.std.perm.mode));
343
0
            }
344
0
            else {
345
                // This is NOT a hard link.
346
0
                info->fs_name->meta_addr =
347
0
                    tsk_getu32(hfs->fs_info.endian, file->std.cnid);
348
0
                info->fs_name->type =
349
0
                    hfsmode2tsknametype(tsk_getu16(hfs->fs_info.endian,
350
0
                        file->std.perm.mode));
351
0
            }
352
0
            info->fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;
353
354
            // Make sure there is enough space in cur_key for the name 
355
            // (name is unicode so each characters is two bytes; 6 bytes
356
            // of non-name characters)
357
0
            const int32_t nameLength =
358
0
                tsk_getu16(hfs->fs_info.endian, cur_key->name.length);
359
0
            if (2*nameLength > tsk_getu16(hfs->fs_info.endian, cur_key->key_len) - 6) {
360
0
                error_returned
361
0
                ("hfs_dir_open_meta_cb: name length is too long");
362
0
                return HFS_BTREE_CB_ERR;
363
0
            }
364
0
            if (hfs_UTF16toUTF8(fs, (uint8_t *) cur_key->name.unicode,
365
0
                    nameLength, info->fs_name->name, HFS_MAXNAMLEN + 1,
366
0
                    HFS_U16U8_FLAG_REPLACE_SLASH)) {
367
0
                return HFS_BTREE_CB_ERR;
368
0
            }
369
0
        }
370
0
        else {
371
0
            tsk_error_set_errno(TSK_ERR_FS_GENFS);
372
            // @@@ MAY NEED TO IMPROVE BELOW MESSAGE
373
0
            tsk_error_set_errstr
374
0
                ("hfs_dir_open_meta: Unknown record type %d in leaf node",
375
0
                rec_type);
376
0
            return HFS_BTREE_CB_ERR;
377
0
        }
378
379
0
        if (tsk_fs_dir_add(info->fs_dir, info->fs_name)) {
380
0
            return HFS_BTREE_CB_ERR;
381
0
        }
382
0
        return HFS_BTREE_CB_LEAF_GO;
383
0
    }
384
0
}
385
386
/** \internal
387
* Process a directory and load up FS_DIR with the entries. If a pointer to
388
* an already allocated FS_DIR structure is given, it will be cleared.  If no existing
389
* FS_DIR structure is passed (i.e. NULL), then a new one will be created. If the return
390
* value is error or corruption, then the FS_DIR structure could
391
* have entries (depending on when the error occurred).
392
*
393
* @param a_fs File system to analyze
394
* @param a_fs_dir Pointer to FS_DIR pointer. Can contain an already allocated
395
* structure or a new structure.
396
* @param a_addr Address of directory to process.
397
* @param recursion_depth Recursion depth to limit the number of self-calls
398
* @returns error, corruption, ok etc.
399
*/
400
TSK_RETVAL_ENUM
401
hfs_dir_open_meta(TSK_FS_INFO * fs, TSK_FS_DIR ** a_fs_dir,
402
    TSK_INUM_T a_addr, int recursion_depth)
403
0
{
404
0
    HFS_INFO *hfs = (HFS_INFO *) fs;
405
0
    uint32_t cnid;              /* catalog node ID of the entry (= inum) */
406
0
    TSK_FS_DIR *fs_dir;
407
0
    TSK_FS_NAME *fs_name;
408
0
    HFS_DIR_OPEN_META_INFO info;
409
410
411
0
    tsk_error_reset();
412
413
0
    cnid = (uint32_t) a_addr;
414
415
0
    if (tsk_verbose)
416
0
        fprintf(stderr,
417
0
            "hfs_dir_open_meta: called for directory %" PRIu32 "\n", cnid);
418
419
0
    if (a_addr < fs->first_inum || a_addr > fs->last_inum) {
420
0
        tsk_error_reset();
421
0
        tsk_error_set_errno(TSK_ERR_FS_WALK_RNG);
422
0
        tsk_error_set_errstr("hfs_dir_open_meta: Invalid inode value: %"
423
0
            PRIuINUM, a_addr);
424
0
        return TSK_ERR;
425
0
    }
426
0
    else if (a_fs_dir == NULL) {
427
0
        tsk_error_reset();
428
0
        tsk_error_set_errno(TSK_ERR_FS_ARG);
429
0
        tsk_error_set_errstr
430
0
            ("hfs_dir_open_meta: NULL fs_dir argument given");
431
0
        return TSK_ERR;
432
0
    }
433
434
0
    if (tsk_verbose)
435
0
        tsk_fprintf(stderr,
436
0
            "hfs_dir_open_meta: Processing directory %" PRIuINUM "\n",
437
0
            a_addr);
438
439
0
    fs_dir = *a_fs_dir;
440
0
    if (fs_dir) {
441
0
        tsk_fs_dir_reset(fs_dir);
442
0
        fs_dir->addr = a_addr;
443
0
    }
444
0
    else if ((*a_fs_dir = fs_dir =
445
0
            tsk_fs_dir_alloc(fs, a_addr, 128)) == NULL) {
446
0
        return TSK_ERR;
447
0
    }
448
449
0
    if ((fs_name = tsk_fs_name_alloc(HFS_MAXNAMLEN + 1, 0)) == NULL) {
450
0
        return TSK_ERR;
451
0
    }
452
0
    info.fs_dir = fs_dir;
453
0
    info.fs_name = fs_name;
454
455
0
    if ((fs_dir->fs_file =
456
0
            tsk_fs_file_open_meta(fs, NULL, a_addr)) == NULL) {
457
0
        tsk_error_errstr2_concat(" - hfs_dir_open_meta");
458
0
        tsk_fs_name_free(fs_name);
459
0
        return TSK_ERR;
460
0
    }
461
462
    // if we are listing the root directory, add the Orphan directory and special HFS file entries
463
0
    if (a_addr == fs->root_inum) {
464
0
        int i;
465
0
        for (i = 0; i < 6; i++) {
466
0
            switch (i) {
467
0
            case 0:
468
0
                if (!hfs->has_extents_file)
469
0
                    continue;
470
0
                strncpy(fs_name->name, HFS_EXTENTS_FILE_NAME,
471
0
                    fs_name->name_size);
472
0
                fs_name->meta_addr = HFS_EXTENTS_FILE_ID;
473
0
                break;
474
0
            case 1:
475
0
                strncpy(fs_name->name, HFS_CATALOG_FILE_NAME,
476
0
                    fs_name->name_size);
477
0
                fs_name->meta_addr = HFS_CATALOG_FILE_ID;
478
0
                break;
479
0
            case 2:
480
                // Note: the Extents file and the BadBlocks file are really the same.
481
0
                if (!hfs->has_extents_file)
482
0
                    continue;
483
0
                strncpy(fs_name->name, HFS_BAD_BLOCK_FILE_NAME,
484
0
                    fs_name->name_size);
485
0
                fs_name->meta_addr = HFS_BAD_BLOCK_FILE_ID;
486
0
                break;
487
0
            case 3:
488
0
                strncpy(fs_name->name, HFS_ALLOCATION_FILE_NAME,
489
0
                    fs_name->name_size);
490
0
                fs_name->meta_addr = HFS_ALLOCATION_FILE_ID;
491
0
                break;
492
0
            case 4:
493
0
                if (!hfs->has_startup_file)
494
0
                    continue;
495
0
                strncpy(fs_name->name, HFS_STARTUP_FILE_NAME,
496
0
                    fs_name->name_size);
497
0
                fs_name->meta_addr = HFS_STARTUP_FILE_ID;
498
0
                break;
499
0
            case 5:
500
0
                if (!hfs->has_attributes_file)
501
0
                    continue;
502
0
                strncpy(fs_name->name, HFS_ATTRIBUTES_FILE_NAME,
503
0
                    fs_name->name_size);
504
0
                fs_name->meta_addr = HFS_ATTRIBUTES_FILE_ID;
505
0
                break;
506
                /*
507
                   case 6:
508
                   strncpy(fs_name->name, HFS_REPAIR_CATALOG_FILE_NAME, fs_name->name_size);
509
                   fs_name->meta_addr = HFS_REPAIR_CATALOG_FILE_ID;
510
                   break;
511
                   case 7:
512
                   strncpy(fs_name->name, HFS_BOGUS_EXTENT_FILE_NAME, fs_name->name_size);
513
                   fs_name->meta_addr = HFS_BOGUS_EXTENT_FILE_ID;
514
                   break;
515
                 */
516
0
            }
517
0
            fs_name->type = TSK_FS_NAME_TYPE_REG;
518
0
            fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;
519
0
            if (tsk_fs_dir_add(fs_dir, fs_name)) {
520
0
                tsk_fs_name_free(fs_name);
521
0
                return TSK_ERR;
522
0
            }
523
0
        }
524
0
    }
525
526
0
    info.cnid = cnid;
527
0
    if (hfs_cat_traverse(hfs, hfs_dir_open_meta_cb, &info)) {
528
0
        tsk_fs_name_free(fs_name);
529
0
        return TSK_ERR;
530
0
    }
531
532
0
    tsk_fs_name_free(fs_name);
533
0
    return TSK_OK;
534
0
}
535
536
int
537
hfs_name_cmp(TSK_FS_INFO * a_fs_info, const char *s1, const char *s2)
538
0
{
539
0
    HFS_INFO *hfs = (HFS_INFO *) a_fs_info;
540
0
    if (hfs->is_case_sensitive)
541
0
        return strcmp(s1, s2);
542
0
    else
543
0
        return strcasecmp(s1, s2);
544
0
}