Coverage Report

Created: 2025-12-14 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/sleuthkit/tsk/fs/fatfs_meta.cpp
Line
Count
Source
1
/*
2
** fatfs
3
** The Sleuth Kit
4
**
5
** Meta data layer support for the FAT file system.
6
**
7
** Brian Carrier [carrier <at> sleuthkit [dot] org]
8
** Copyright (c) 2006-2013 Brian Carrier, Basis Technology.  All Rights reserved
9
** Copyright (c) 2003-2005 Brian Carrier.  All rights reserved
10
**
11
** TASK
12
** Copyright (c) 2002 Brian Carrier, @stake Inc.  All rights reserved
13
**
14
**
15
** This software is distributed under the Common Public License 1.0
16
**
17
** Unicode added with support from I.D.E.A.L. Technology Corp (Aug '05)
18
**
19
*/
20
21
/**
22
 * \file fatfs_meta.c
23
 * Meta data layer support for FAT file systems.
24
 */
25
26
#include "tsk_fatfs.h"
27
#include "tsk_fatxxfs.h"
28
#include "tsk_exfatfs.h"
29
30
#include <memory>
31
32
TSK_FS_ATTR_TYPE_ENUM
33
fatfs_get_default_attr_type([[maybe_unused]] const TSK_FS_FILE * a_file)
34
12.0k
{
35
12.0k
    return TSK_FS_ATTR_TYPE_DEFAULT;
36
12.0k
}
37
38
/**
39
 * \internal
40
 * Create an TSK_FS_META structure for the root directory.  FAT does
41
 * not have a directory entry for the root directory, but this
42
 * function collects the data needed to make one.
43
 *
44
 * @param fatfs File system to analyze.
45
 * @param fs_meta Inode structure to copy root directory information into.
46
 * @return 1 on error and 0 on success
47
 */
48
static uint8_t
49
fatfs_make_root(FATFS_INFO *a_fatfs, TSK_FS_META *a_fs_meta)
50
438
{
51
438
    const char *func_name = "fatfs_make_root";
52
438
    TSK_DADDR_T *first_clust_addr_ptr = NULL;
53
54
438
    tsk_error_reset();
55
438
    if (fatfs_ptr_arg_is_null(a_fatfs, "a_fatfs", func_name) ||
56
438
        fatfs_ptr_arg_is_null(a_fs_meta, "a_fs_meta", func_name)) {
57
0
        return 1;
58
0
    }
59
60
    /* Manufacture some metadata. */
61
438
    a_fs_meta->type = TSK_FS_META_TYPE_DIR;
62
438
    a_fs_meta->mode = TSK_FS_META_MODE_UNSPECIFIED;
63
438
    a_fs_meta->nlink = 1;
64
438
    a_fs_meta->addr = FATFS_ROOTINO;
65
438
    a_fs_meta->flags = (TSK_FS_META_FLAG_ENUM)(TSK_FS_META_FLAG_USED | TSK_FS_META_FLAG_ALLOC);
66
438
    a_fs_meta->uid = a_fs_meta->gid = 0;
67
438
    a_fs_meta->mtime = a_fs_meta->atime = a_fs_meta->ctime = a_fs_meta->crtime = 0;
68
438
    a_fs_meta->mtime_nano = a_fs_meta->atime_nano = a_fs_meta->ctime_nano =
69
438
        a_fs_meta->crtime_nano = 0;
70
71
    /* Give the root directory an empty name. */
72
438
    if (a_fs_meta->name2 == NULL) {
73
438
        if ((a_fs_meta->name2 = (TSK_FS_META_NAME_LIST *)
74
438
                tsk_malloc(sizeof(TSK_FS_META_NAME_LIST))) == NULL) {
75
0
            return 1;
76
0
        }
77
438
        a_fs_meta->name2->next = NULL;
78
438
    }
79
438
    a_fs_meta->name2->name[0] = '\0';
80
81
    /* Mark the generic attribute list as not in use (in the generic file model
82
     * attributes are containers for data or metadata). Population of this
83
     * list is done by lazy look up. */
84
438
    a_fs_meta->attr_state = TSK_FS_META_ATTR_EMPTY;
85
438
    if (a_fs_meta->attr) {
86
0
        tsk_fs_attrlist_markunused(a_fs_meta->attr);
87
0
    }
88
89
    /* Determine the size of the root directory and the address of its
90
     * first cluster. */
91
438
    first_clust_addr_ptr = (TSK_DADDR_T*)a_fs_meta->content_ptr;
92
438
    if (a_fatfs->fs_info.ftype == TSK_FS_TYPE_FAT32 ||
93
309
        a_fatfs->fs_info.ftype == TSK_FS_TYPE_EXFAT) {
94
309
        TSK_DADDR_T cnum = 0;
95
309
        TSK_DADDR_T clust = 0;
96
309
        TSK_LIST *list_seen = NULL;
97
98
        /* Convert the address of the first sector of the root directory into
99
         * the address of its first cluster. */
100
309
        clust = FATFS_SECT_2_CLUST(a_fatfs, a_fatfs->rootsect);
101
309
        first_clust_addr_ptr[0] = clust;
102
103
        /* Walk the FAT and count the clusters allocated to the root directory. */
104
309
        cnum = 0;
105
878
        while ((clust) && (0 == FATFS_ISEOF(clust, FATFS_32_MASK))) {
106
569
            TSK_DADDR_T nxt = 0;
107
108
            /* Make sure we do not get into an infinite loop */
109
569
            if (tsk_list_find(list_seen, clust)) {
110
0
                if (tsk_verbose) {
111
0
                    tsk_fprintf(stderr,
112
0
                        "Loop found while determining root directory size\n");
113
0
                }
114
0
                break;
115
0
            }
116
569
            if (tsk_list_add(&list_seen, clust)) {
117
0
                tsk_list_free(list_seen);
118
0
                list_seen = NULL;
119
0
                return 1;
120
0
            }
121
122
569
            cnum++;
123
569
            if (fatfs_getFAT(a_fatfs, clust, &nxt)) {
124
0
                break;
125
0
            }
126
569
            else {
127
569
                clust = nxt;
128
569
            }
129
569
        }
130
309
        tsk_list_free(list_seen);
131
309
        list_seen = NULL;
132
133
        /* Calculate the size of the root directory. */
134
309
        a_fs_meta->size = (cnum * a_fatfs->csize) << a_fatfs->ssize_sh;
135
309
    }
136
129
    else {
137
        /* FAT12 and FAT16 don't use the FAT for the root directory, so set
138
         * the first cluster address to a distinguished value that other code
139
         * will have to check as a special condition. */
140
129
        first_clust_addr_ptr[0] = 1;
141
142
        /* Set the size equal to the number of bytes between the end of the
143
         * FATs and the start of the clusters. */
144
129
        a_fs_meta->size = (a_fatfs->firstclustsect - a_fatfs->firstdatasect) << a_fatfs->ssize_sh;
145
129
    }
146
147
438
    return 0;
148
438
}
149
150
/**
151
* \internal
152
 * Create an TSK_FS_META structure for the master boot record.
153
 *
154
 * @param fatfs File system to analyze
155
 * @param fs_meta Inode structure to copy file information into.
156
 * @return 1 on error and 0 on success
157
 */
158
static uint8_t
159
fatfs_make_mbr(FATFS_INFO *fatfs, TSK_FS_META *fs_meta)
160
341
{
161
341
    TSK_DADDR_T *addr_ptr;
162
163
341
    fs_meta->type = TSK_FS_META_TYPE_VIRT;
164
341
    fs_meta->mode = TSK_FS_META_MODE_UNSPECIFIED;
165
341
    fs_meta->nlink = 1;
166
341
    fs_meta->addr = fatfs->mbr_virt_inum;
167
341
    fs_meta->flags = (TSK_FS_META_FLAG_ENUM)
168
341
        (TSK_FS_META_FLAG_USED | TSK_FS_META_FLAG_ALLOC);
169
341
    fs_meta->uid = fs_meta->gid = 0;
170
341
    fs_meta->mtime = fs_meta->atime = fs_meta->ctime = fs_meta->crtime = 0;
171
341
    fs_meta->mtime_nano = fs_meta->atime_nano = fs_meta->ctime_nano =
172
341
        fs_meta->crtime_nano = 0;
173
174
341
    if (fs_meta->name2 == NULL) {
175
341
        if ((fs_meta->name2 = (TSK_FS_META_NAME_LIST *)
176
341
                tsk_malloc(sizeof(TSK_FS_META_NAME_LIST))) == NULL) {
177
0
            return 1;
178
0
        }
179
341
        fs_meta->name2->next = NULL;
180
341
    }
181
341
    strncpy(fs_meta->name2->name, FATFS_MBRNAME,
182
341
        TSK_FS_META_NAME_LIST_NSIZE);
183
184
341
    fs_meta->attr_state = TSK_FS_META_ATTR_EMPTY;
185
341
    if (fs_meta->attr) {
186
0
        tsk_fs_attrlist_markunused(fs_meta->attr);
187
0
    }
188
189
341
    addr_ptr = (TSK_DADDR_T*)fs_meta->content_ptr;
190
341
    addr_ptr[0] = 0;
191
341
    fs_meta->size = 512;
192
193
341
    return 0;
194
341
}
195
196
/**
197
* \internal
198
 * Create an TSK_FS_META structure for the FAT tables.
199
 *
200
 * @param fatfs File system to analyze
201
 * @param a_which 1 or 2 to choose between defining FAT1 or FAT2
202
 * @param fs_meta Inode structure to copy file information into.
203
 * @return 1 on error and 0 on success
204
 */
205
static uint8_t
206
fatfs_make_fat(FATFS_INFO *fatfs, uint8_t a_which, TSK_FS_META *fs_meta)
207
351
{
208
351
    TSK_FS_INFO *fs = (TSK_FS_INFO*)fatfs;
209
351
    TSK_DADDR_T *addr_ptr = (TSK_DADDR_T *)fs_meta->content_ptr;
210
211
351
    if ((a_which != 1) && (a_which != 2)) {
212
0
        return 1;
213
0
    }
214
215
351
    if (a_which > fatfs->numfat) {
216
0
        return 1;
217
0
    }
218
219
351
    fs_meta->type = TSK_FS_META_TYPE_VIRT;
220
351
    fs_meta->mode = TSK_FS_META_MODE_UNSPECIFIED;
221
351
    fs_meta->nlink = 1;
222
223
351
    fs_meta->flags = (TSK_FS_META_FLAG_ENUM)
224
351
        (TSK_FS_META_FLAG_USED | TSK_FS_META_FLAG_ALLOC);
225
351
    fs_meta->uid = fs_meta->gid = 0;
226
351
    fs_meta->mtime = fs_meta->atime = fs_meta->ctime = fs_meta->crtime = 0;
227
351
    fs_meta->mtime_nano = fs_meta->atime_nano = fs_meta->ctime_nano =
228
351
        fs_meta->crtime_nano = 0;
229
230
351
    if (fs_meta->name2 == NULL) {
231
351
        if ((fs_meta->name2 = (TSK_FS_META_NAME_LIST *)
232
351
                tsk_malloc(sizeof(TSK_FS_META_NAME_LIST))) == NULL)
233
0
            return 1;
234
351
        fs_meta->name2->next = NULL;
235
351
    }
236
237
351
    if (a_which == 1) {
238
341
        fs_meta->addr = fatfs->fat1_virt_inum;
239
341
        strncpy(fs_meta->name2->name, FATFS_FAT1NAME,
240
341
            TSK_FS_META_NAME_LIST_NSIZE);
241
341
        addr_ptr[0] = fatfs->firstfatsect;
242
341
    }
243
10
    else {
244
10
        fs_meta->addr = fatfs->fat2_virt_inum;
245
10
        strncpy(fs_meta->name2->name, FATFS_FAT2NAME,
246
10
            TSK_FS_META_NAME_LIST_NSIZE);
247
10
        addr_ptr[0] = fatfs->firstfatsect + fatfs->sectperfat;
248
10
    }
249
250
351
    fs_meta->attr_state = TSK_FS_META_ATTR_EMPTY;
251
351
    if (fs_meta->attr) {
252
0
        tsk_fs_attrlist_markunused(fs_meta->attr);
253
0
    }
254
255
351
    fs_meta->size = fatfs->sectperfat * fs->block_size;
256
257
351
    return 0;
258
351
}
259
260
/**
261
 * \internal
262
 * Load a FATFS_DENTRY structure with the bytes at a given inode address.
263
 *
264
 * @param [in] a_fs The file system from which to read the bytes.
265
 * @param [out] a_de The FATFS_DENTRY.
266
 * @param [in] a_inum An inode address.
267
 * @return 0 on success, 1 on failure.
268
 */
269
uint8_t
270
fatfs_dentry_load(FATFS_INFO *a_fatfs, FATFS_DENTRY *a_dentry, TSK_INUM_T a_inum)
271
669k
{
272
669k
    const char *func_name = "fatfs_dentry_load";
273
669k
    TSK_FS_INFO *fs = (TSK_FS_INFO*)a_fatfs;
274
669k
    TSK_DADDR_T sect = 0;
275
669k
    size_t off = 0;
276
669k
    ssize_t cnt = 0;
277
278
669k
    tsk_error_reset();
279
669k
    if (fatfs_ptr_arg_is_null(a_fatfs, "a_fatfs", func_name) ||
280
669k
        fatfs_ptr_arg_is_null(a_dentry, "a_dentry", func_name) ||
281
669k
        !fatfs_inum_arg_is_in_range(a_fatfs, a_inum, func_name)) {
282
0
        return 1;
283
0
    }
284
285
    /* Map the inode address to a sector. */
286
669k
    sect = FATFS_INODE_2_SECT(a_fatfs, a_inum);
287
669k
    if (sect > fs->last_block) {
288
0
        tsk_error_reset();
289
0
        tsk_error_set_errno(TSK_ERR_FS_INODE_NUM);
290
0
        tsk_error_set_errstr("%s: Inode %" PRIuINUM
291
0
            " in sector too big for image: %" PRIuDADDR, func_name, a_inum, sect);
292
0
        return 1;
293
0
    }
294
295
    /* Get the byte offset of the inode address within the sector. */
296
669k
    off = FATFS_INODE_2_OFF(a_fatfs, a_inum);
297
298
    /* Read in the bytes. */
299
669k
    cnt = tsk_fs_read(fs, sect * fs->block_size + off, (char*)a_dentry, sizeof(FATFS_DENTRY));
300
669k
    if (cnt != sizeof(FATFS_DENTRY)) {
301
0
        if (cnt >= 0) {
302
0
            tsk_error_reset();
303
0
            tsk_error_set_errno(TSK_ERR_FS_READ);
304
0
        }
305
0
        tsk_error_set_errstr2("%s: block: %" PRIuDADDR,
306
0
            func_name, sect);
307
0
        return 1;
308
0
    }
309
310
669k
    return 0;
311
669k
}
312
313
/**
314
 * \internal
315
 * Populate the TSK_FS_META structure of a TSK_FS_FILE structure for a
316
 * given inode address.
317
 *
318
 * @param [in] a_fs File system that contains the inode.
319
 * @param [out] a_fs_file The file corresponding to the inode.
320
 * @param [in] a_inum The inode address.
321
 * @returns 1 if an error occurs or if the inode address is not
322
 * for a valid inode, 0 otherwise.
323
 */
324
uint8_t
325
fatfs_inode_lookup(TSK_FS_INFO *a_fs, TSK_FS_FILE *a_fs_file,
326
    TSK_INUM_T a_inum)
327
640k
{
328
640k
    const char *func_name = "fatfs_inode_lookup";
329
640k
    FATFS_INFO *fatfs = (FATFS_INFO*)a_fs;
330
331
640k
    tsk_error_reset();
332
640k
    if (fatfs_ptr_arg_is_null(a_fs, "a_fs", func_name) ||
333
640k
        fatfs_ptr_arg_is_null(a_fs_file, "a_fs_file", func_name) ||
334
640k
        !fatfs_inum_arg_is_in_range(fatfs, a_inum, func_name)) {
335
0
        return 1;
336
0
    }
337
338
    /* Allocate or reset the TSK_FS_META struct. */
339
640k
    if (a_fs_file->meta == NULL) {
340
640k
        if ((a_fs_file->meta =
341
640k
                tsk_fs_meta_alloc(FATFS_FILE_CONTENT_LEN)) == NULL) {
342
0
            return 1;
343
0
        }
344
640k
    }
345
0
    else {
346
0
        tsk_fs_meta_reset(a_fs_file->meta);
347
0
    }
348
349
    /* Manufacture an inode for the root directory or a FAT virtual file,
350
     * or do a look up. */
351
640k
    if (a_inum == a_fs->root_inum) {
352
406
        if (fatfs_make_root(fatfs, a_fs_file->meta))
353
0
            return 1;
354
406
        else
355
406
            return 0;
356
406
    }
357
639k
    else if (a_inum == fatfs->mbr_virt_inum) {
358
341
        if (fatfs_make_mbr(fatfs, a_fs_file->meta))
359
0
            return 1;
360
341
        else
361
341
            return 0;
362
341
    }
363
639k
    else if (a_inum == fatfs->fat1_virt_inum) {
364
341
        if (fatfs_make_fat(fatfs, 1, a_fs_file->meta))
365
0
            return 1;
366
341
        else
367
341
            return 0;
368
341
    }
369
639k
    else if (a_inum == fatfs->fat2_virt_inum && fatfs->numfat == 2) {
370
10
        if (fatfs_make_fat(fatfs, 2, a_fs_file->meta))
371
0
            return 1;
372
10
        else
373
10
            return 0;
374
10
    }
375
639k
    else if (a_inum == TSK_FS_ORPHANDIR_INUM(a_fs)) {
376
699
        if (tsk_fs_dir_make_orphan_dir_meta(a_fs, a_fs_file->meta))
377
0
            return 1;
378
699
        else
379
699
            return 0;
380
699
    }
381
638k
    else {
382
638k
        return fatfs->inode_lookup(fatfs, a_fs_file, a_inum);
383
638k
    }
384
640k
}
385
386
/** \internal
387
 * Make data runs out of the clusters allocated to a file represented by a
388
 * TSK_FS_FILE structure. Each data run will have a starting sector and a
389
 * length in sectors. The runs will be stored as a non-resident attribute in
390
 * the TSK_FS_ATTRLIST of the TSK_FS_META structure of the TSK_FS_FILE.
391
 *
392
 * @param a_fs_file A representation of a file.
393
 * @return 1 on error and 0 on success
394
 */
395
uint8_t
396
fatfs_make_data_runs(TSK_FS_FILE * a_fs_file)
397
13.2k
{
398
13.2k
    const char *func_name = "fatfs_make_data_runs";
399
13.2k
    TSK_FS_INFO *fs = NULL;
400
13.2k
    TSK_FS_META *fs_meta = NULL;
401
13.2k
    FATFS_INFO *fatfs = NULL;
402
13.2k
    TSK_DADDR_T clust = 0;
403
13.2k
    TSK_OFF_T size_remain = 0;
404
13.2k
    TSK_FS_ATTR *fs_attr = NULL;
405
406
13.2k
    if ((fatfs_ptr_arg_is_null(a_fs_file, "a_fs_file", func_name)) ||
407
13.2k
        (fatfs_ptr_arg_is_null(a_fs_file->meta, "a_fs_file->meta", func_name)) ||
408
13.2k
        (fatfs_ptr_arg_is_null(a_fs_file->fs_info, "a_fs_file->fs_info", func_name))) {
409
0
        return TSK_ERR;
410
0
    }
411
412
13.2k
    fs_meta = a_fs_file->meta;
413
13.2k
    fs = a_fs_file->fs_info;
414
13.2k
    fatfs = (FATFS_INFO*)fs;
415
416
    /* Check for an already populated attribute list, since a lazy strategy
417
     * is used to fill in attributes. If the attribute list is not yet
418
     * allocated, do so now. */
419
13.2k
    if ((fs_meta->attr != NULL)
420
0
        && (fs_meta->attr_state == TSK_FS_META_ATTR_STUDIED)) {
421
0
        return 0;
422
0
    }
423
13.2k
    else if (fs_meta->attr_state == TSK_FS_META_ATTR_ERROR) {
424
0
        return 1;
425
0
    }
426
427
13.2k
    if (fs_meta->attr != NULL) {
428
0
        tsk_fs_attrlist_markunused(fs_meta->attr);
429
0
    }
430
13.2k
    else  {
431
13.2k
        fs_meta->attr = tsk_fs_attrlist_alloc();
432
13.2k
    }
433
434
    /* Get the stashed first cluster address of the file. */
435
13.2k
    clust = ((TSK_DADDR_T*)fs_meta->content_ptr)[0];
436
13.2k
    if ((clust > (fatfs->lastclust)) &&
437
1.20k
        (FATFS_ISEOF(clust, fatfs->mask) == 0)) {
438
1.17k
        fs_meta->attr_state = TSK_FS_META_ATTR_ERROR;
439
1.17k
        tsk_error_reset();
440
1.17k
        if (a_fs_file->meta->flags & TSK_FS_META_FLAG_UNALLOC) {
441
184
            tsk_error_set_errno(TSK_ERR_FS_RECOVER);
442
184
        }
443
994
        else {
444
994
            tsk_error_set_errno(TSK_ERR_FS_INODE_COR);
445
994
        }
446
1.17k
        tsk_error_set_errstr
447
1.17k
            ("%s: Starting cluster address too large: %"
448
1.17k
            PRIuDADDR, func_name, clust);
449
1.17k
        return 1;
450
1.17k
    }
451
452
    /* Figure out the allocated length of the file in bytes. Because the
453
     * allocation unit for FAT file systems is the cluster, round the
454
     * size up to a multiple of cluster size. */
455
12.0k
    size_remain = roundup(fs_meta->size, fatfs->csize * fs->block_size);
456
457
12.0k
    if ((a_fs_file->meta->addr == fs->root_inum) &&
458
422
        (fs->ftype != TSK_FS_TYPE_FAT32) &&
459
157
        (fs->ftype != TSK_FS_TYPE_EXFAT) &&
460
113
        (clust == 1)) {
461
        /* Make a single contiguous data run for a FAT12 or FAT16 root
462
         * directory. The root directory for these file systems is not
463
         * tracked in the FAT. */
464
113
        TSK_FS_ATTR_RUN *data_run;
465
466
113
        if (tsk_verbose) {
467
0
            tsk_fprintf(stderr,
468
0
                "%s: Loading root directory\n", func_name);
469
0
        }
470
471
        /* Allocate the run. */
472
113
        data_run = tsk_fs_attr_run_alloc();
473
113
        if (data_run == NULL) {
474
0
            return 1;
475
0
        }
476
477
        /* Set the starting sector address and run length. The run begins with
478
         * the first sector of the data area. */
479
113
        data_run->addr = fatfs->rootsect;
480
113
        data_run->len = fatfs->firstclustsect - fatfs->firstdatasect;
481
482
        /* Allocate a non-resident attribute to hold the run and add it
483
         to the attribute list. */
484
113
        if ((fs_attr =
485
113
                tsk_fs_attrlist_getnew(fs_meta->attr,
486
113
                    TSK_FS_ATTR_NONRES)) == NULL) {
487
0
            return 1;
488
0
        }
489
490
        /* Tie everything together. */
491
113
        if (tsk_fs_attr_set_run(a_fs_file, fs_attr, data_run, NULL,
492
113
                TSK_FS_ATTR_TYPE_DEFAULT, TSK_FS_ATTR_ID_DEFAULT,
493
113
                data_run->len * fs->block_size,
494
113
                data_run->len * fs->block_size,
495
113
                data_run->len * fs->block_size, TSK_FS_ATTR_FLAG_NONE, 0)) {
496
0
            return 1;
497
0
        }
498
499
113
        fs_meta->attr_state = TSK_FS_META_ATTR_STUDIED;
500
501
113
        return 0;
502
113
    }
503
11.9k
    else if ((a_fs_file->meta->addr >= fatfs->mbr_virt_inum) &&
504
32
             (a_fs_file->meta->addr <= fatfs->mbr_virt_inum + fatfs->numfat)) {
505
        /* Make a single contiguous data run for a virtual file (MBR, FAT). */
506
0
        TSK_FS_ATTR_RUN *data_run;
507
508
0
        if (tsk_verbose) {
509
0
            tsk_fprintf(stderr,
510
0
                "%s: Loading virtual file: %" PRIuINUM
511
0
                "\n", func_name, a_fs_file->meta->addr);
512
0
        }
513
514
        /* Allocate the run. */
515
0
        data_run = tsk_fs_attr_run_alloc();
516
0
        if (data_run == NULL) {
517
0
            return 1;
518
0
        }
519
520
        /* Set the starting sector address and run length. */
521
0
        data_run->addr = clust;
522
0
        data_run->len = a_fs_file->meta->size / fs->block_size;
523
524
        /* Allocate a non-resident attribute to hold the run and add it
525
         to the attribute list. */
526
0
        if ((fs_attr =
527
0
                tsk_fs_attrlist_getnew(fs_meta->attr,
528
0
                    TSK_FS_ATTR_NONRES)) == NULL) {
529
0
            return 1;
530
0
        }
531
532
        /* Tie everything together. */
533
0
        if (tsk_fs_attr_set_run(a_fs_file, fs_attr, data_run, NULL,
534
0
                TSK_FS_ATTR_TYPE_DEFAULT, TSK_FS_ATTR_ID_DEFAULT,
535
0
                data_run->len * fs->block_size,
536
0
                data_run->len * fs->block_size,
537
0
                data_run->len * fs->block_size, TSK_FS_ATTR_FLAG_NONE, 0)) {
538
0
            return 1;
539
0
        }
540
541
0
        fs_meta->attr_state = TSK_FS_META_ATTR_STUDIED;
542
0
        return 0;
543
0
    }
544
11.9k
    else if (fs_meta->flags & TSK_FS_META_FLAG_UNALLOC) {
545
        /* Make data runs for a deleted file that we want to recover.
546
         * In this case, we could get a lot of errors because of inconsistent
547
         * data.  To make it clear that these are from a recovery, we set most
548
         * error codes to _RECOVER so that they can be more easily suppressed.
549
         */
550
2.68k
        TSK_DADDR_T sbase;
551
2.68k
        TSK_DADDR_T startclust = clust;
552
2.68k
        TSK_OFF_T recoversize = fs_meta->size;
553
2.68k
        TSK_FS_ATTR_RUN *data_run = NULL;
554
2.68k
        TSK_FS_ATTR_RUN *data_run_tmp = NULL;
555
2.68k
        TSK_FS_ATTR_RUN *data_run_head = NULL;
556
        // TSK_OFF_T full_len_s = 0;         // set but not used
557
2.68k
        uint8_t canRecover = 1; // set to 0 if recovery is not possible
558
559
2.68k
        if (tsk_verbose)
560
0
            tsk_fprintf(stderr,
561
0
                "%s: Processing deleted file %" PRIuINUM
562
0
                " in recovery mode\n", func_name, fs_meta->addr);
563
564
        /* We know the size and the starting cluster
565
         *
566
         * We are going to take the clusters from the starting cluster
567
         * onwards and skip the clusters that are current allocated
568
         */
569
570
    /* Quick check for exFAT only
571
     * Empty deleted files have a starting cluster of zero, which
572
     * causes problems in the exFAT functions since the first data
573
     * cluster should be 2. Since a starting cluster of zero indicates
574
     * no data, make an empty data run and skip any further processing
575
     */
576
2.68k
    if((fs->ftype == TSK_FS_TYPE_EXFAT) && (startclust == 0)){
577
            // initialize the data run
578
0
      fs_attr = tsk_fs_attrlist_getnew(a_fs_file->meta->attr, TSK_FS_ATTR_NONRES);
579
0
      if (fs_attr == NULL) {
580
0
        a_fs_file->meta->attr_state = TSK_FS_META_ATTR_ERROR;
581
0
        return 1;
582
0
      }
583
584
      // Add the empty data run
585
0
            if (tsk_fs_attr_set_run(a_fs_file, fs_attr, NULL, NULL,
586
0
                    TSK_FS_ATTR_TYPE_DEFAULT, TSK_FS_ATTR_ID_DEFAULT,
587
0
                    0, 0, 0, (TSK_FS_ATTR_FLAG_ENUM)0, 0)) {
588
0
                fs_meta->attr_state = TSK_FS_META_ATTR_ERROR;
589
0
                return 1;
590
0
            }
591
0
      fs_meta->attr_state = TSK_FS_META_ATTR_STUDIED;
592
0
      return 0;
593
0
    }
594
595
        /* Sanity checks on the starting cluster */
596
        /* Convert the cluster addr to a sector addr */
597
2.68k
        sbase = FATFS_CLUST_2_SECT(fatfs, startclust);
598
599
2.68k
        if (sbase > fs->last_block) {
600
9
            tsk_error_reset();
601
9
            tsk_error_set_errno(TSK_ERR_FS_RECOVER);
602
9
            tsk_error_set_errstr
603
9
                ("%s: Starting cluster address too large (recovery): %"
604
9
                PRIuDADDR, func_name, sbase);
605
9
            fs_meta->attr_state = TSK_FS_META_ATTR_ERROR;
606
9
            return 1;
607
9
        }
608
2.67k
        else {
609
2.67k
            int retval;
610
611
            /* If the starting cluster is already allocated then we can't
612
             * recover it */
613
2.67k
            retval = fatfs->is_cluster_alloc(fatfs, startclust);
614
2.67k
            if (retval != 0) {
615
1.04k
                canRecover = 0;
616
1.04k
            }
617
2.67k
        }
618
619
        /* Part 1 is to make sure there are enough unallocated clusters
620
         * for the size of the file
621
         */
622
2.67k
        clust = startclust;
623
2.67k
        size_remain = recoversize;
624
625
        // we could make this negative so sign it for the comparison
626
1.57M
        while (((int64_t) size_remain > 0) && (canRecover)) {
627
1.57M
            int retval;
628
1.57M
            sbase = FATFS_CLUST_2_SECT(fatfs, clust);
629
630
            /* Are we past the end of the FS?
631
             * that means we could not find enough unallocated clusters
632
             * for the file size */
633
1.57M
            if (sbase + fatfs->csize - 1 > fs->last_block) {
634
0
                canRecover = 0;
635
636
0
                if (tsk_verbose)
637
0
                    tsk_fprintf(stderr,
638
0
                        "%s: Could not find enough unallocated sectors to recover with - aborting\n", func_name);
639
0
                break;
640
0
            }
641
642
            /* Skip allocated clusters */
643
1.57M
            retval = fatfs->is_cluster_alloc(fatfs, clust);
644
1.57M
            if (retval == -1) {
645
0
                canRecover = 0;
646
0
                break;
647
0
            }
648
1.57M
            else if (retval == 1) {
649
440k
                clust++;
650
440k
                continue;
651
440k
            }
652
653
            /* We can use this sector */
654
            // see if we need a new run
655
1.13M
            if ((data_run == NULL)
656
1.13M
                || (data_run->addr + data_run->len != sbase)) {
657
658
207k
                TSK_FS_ATTR_RUN *data_run_tmp = tsk_fs_attr_run_alloc();
659
207k
                if (data_run_tmp == NULL) {
660
0
                    fs_meta->attr_state = TSK_FS_META_ATTR_ERROR;
661
0
                    tsk_fs_attr_run_free(data_run_head);
662
0
                    return 1;
663
0
                }
664
665
207k
                if (data_run_head == NULL) {
666
1.62k
                    data_run_head = data_run_tmp;
667
1.62k
                    data_run_tmp->offset = 0;
668
1.62k
                }
669
205k
                else if (data_run != NULL) {
670
205k
                    data_run->next = data_run_tmp;
671
205k
                    data_run_tmp->offset =
672
205k
                        data_run->offset + data_run->len;
673
205k
                }
674
207k
                data_run = data_run_tmp;
675
207k
                data_run->len = 0;
676
207k
                data_run->addr = sbase;
677
207k
            }
678
1.13M
            data_run->len += fatfs->csize;
679
            // full_len_s += fatfs->csize;    // set but not used
680
681
1.13M
            size_remain -= (fatfs->csize << fatfs->ssize_sh);
682
1.13M
            clust++;
683
1.13M
        }
684
685
        // Get a FS_DATA structure and add the runlist to it
686
2.67k
        if ((fs_attr =
687
2.67k
                tsk_fs_attrlist_getnew(fs_meta->attr,
688
2.67k
                    TSK_FS_ATTR_NONRES)) == NULL) {
689
0
            fs_meta->attr_state = TSK_FS_META_ATTR_ERROR;
690
0
            tsk_fs_attr_run_free(data_run_head);
691
0
            return 1;
692
0
        }
693
694
2.67k
        if (canRecover) {
695
            /* We can recover the file */
696
697
            // initialize the data run
698
1.62k
            if (tsk_fs_attr_set_run(a_fs_file, fs_attr, data_run_head,
699
1.62k
                    NULL, TSK_FS_ATTR_TYPE_DEFAULT, TSK_FS_ATTR_ID_DEFAULT,
700
1.62k
                    fs_meta->size, fs_meta->size, roundup(fs_meta->size,
701
1.62k
                        fatfs->csize * fs->block_size), TSK_FS_ATTR_FLAG_NONE, 0)) {
702
0
                fs_meta->attr_state = TSK_FS_META_ATTR_ERROR;
703
0
                return 1;
704
0
            }
705
706
1.62k
            fs_meta->attr_state = TSK_FS_META_ATTR_STUDIED;
707
1.62k
        }
708
        // create a one cluster run
709
1.04k
        else {
710
1.04k
            tsk_fs_attr_run_free(data_run_head);
711
712
1.04k
            data_run_tmp = tsk_fs_attr_run_alloc();
713
1.04k
            if (data_run_tmp == NULL) {
714
0
                fs_meta->attr_state = TSK_FS_META_ATTR_ERROR;
715
0
                return 1;
716
0
            }
717
1.04k
            data_run_tmp->addr = sbase;
718
1.04k
            data_run_tmp->len = fatfs->csize;
719
720
            // initialize the data run
721
1.04k
            if (tsk_fs_attr_set_run(a_fs_file, fs_attr, data_run_tmp, NULL,
722
1.04k
                    TSK_FS_ATTR_TYPE_DEFAULT, TSK_FS_ATTR_ID_DEFAULT,
723
1.04k
                    fs_meta->size, fs_meta->size, roundup(fs_meta->size,
724
1.04k
                        fatfs->csize * fs->block_size), TSK_FS_ATTR_FLAG_NONE, 0)) {
725
0
                fs_meta->attr_state = TSK_FS_META_ATTR_ERROR;
726
0
                return 1;
727
0
            }
728
729
1.04k
            fs_meta->attr_state = TSK_FS_META_ATTR_STUDIED;
730
1.04k
        }
731
732
2.67k
        return 0;
733
2.67k
    }
734
9.25k
    else {
735
9.25k
        TSK_LIST *list_seen = NULL;
736
9.25k
        TSK_FS_ATTR_RUN *data_run = NULL;
737
9.25k
        TSK_FS_ATTR_RUN *data_run_head = NULL;
738
        // TSK_OFF_T full_len_s = 0;   // set but not used
739
9.25k
        TSK_DADDR_T sbase;
740
        /* Do normal cluster chain walking for a file or directory, including
741
         * FAT32 and exFAT root directories. */
742
743
9.25k
        if (tsk_verbose) {
744
0
            tsk_fprintf(stderr,
745
0
                "%s: Processing file %" PRIuINUM
746
0
                " in normal mode\n", func_name, fs_meta->addr);
747
0
        }
748
749
        /* Cycle through the cluster chain */
750
11.3k
        while ((clust & fatfs->mask) > 0 && (int64_t) size_remain > 0 &&
751
2.06k
            (0 == FATFS_ISEOF(clust, fatfs->mask))) {
752
753
            /* Convert the cluster addr to a sector addr */
754
2.06k
            sbase = FATFS_CLUST_2_SECT(fatfs, clust);
755
756
2.06k
            if (sbase + fatfs->csize - 1 > fs->last_block) {
757
0
                fs_meta->attr_state = TSK_FS_META_ATTR_ERROR;
758
0
                tsk_error_reset();
759
760
0
                tsk_error_set_errno(TSK_ERR_FS_INODE_COR);
761
0
                tsk_error_set_errstr
762
0
                    ("%s: Invalid sector address in FAT (too large): %"
763
0
                    PRIuDADDR " (plus %d sectors)", func_name, sbase, fatfs->csize);
764
0
                tsk_fs_attr_run_free(data_run_head);
765
0
                if (list_seen != NULL) {
766
0
                    tsk_list_free(list_seen);
767
0
                    list_seen = NULL;
768
0
                }
769
0
                return 1;
770
0
            }
771
772
            // see if we need a new run
773
2.06k
            if ((data_run == NULL)
774
2.06k
                || (data_run->addr + data_run->len != sbase)) {
775
776
2.06k
                TSK_FS_ATTR_RUN *data_run_tmp = tsk_fs_attr_run_alloc();
777
2.06k
                if (data_run_tmp == NULL) {
778
0
                    tsk_fs_attr_run_free(data_run_head);
779
0
                    fs_meta->attr_state = TSK_FS_META_ATTR_ERROR;
780
0
                    if (list_seen != NULL) {
781
0
                        tsk_list_free(list_seen);
782
0
                        list_seen = NULL;
783
0
                    }
784
0
                    return 1;
785
0
                }
786
787
2.06k
                if (data_run_head == NULL) {
788
1.29k
                    data_run_head = data_run_tmp;
789
1.29k
                    data_run_tmp->offset = 0;
790
1.29k
                }
791
767
                else if (data_run != NULL) {
792
767
                    data_run->next = data_run_tmp;
793
767
                    data_run_tmp->offset =
794
767
                        data_run->offset + data_run->len;
795
767
                }
796
2.06k
                data_run = data_run_tmp;
797
2.06k
                data_run->len = 0;
798
2.06k
                data_run->addr = sbase;
799
2.06k
            }
800
801
2.06k
            data_run->len += fatfs->csize;
802
            // full_len_s += fatfs->csize;  // set but not used
803
2.06k
            size_remain -= (fatfs->csize * fs->block_size);
804
805
2.06k
            if ((int64_t) size_remain > 0) {
806
767
                TSK_DADDR_T nxt;
807
767
                if (fatfs_getFAT(fatfs, clust, &nxt)) {
808
0
                    tsk_error_set_errstr2("%s: Inode: %" PRIuINUM
809
0
                        "  cluster: %" PRIuDADDR, func_name, fs_meta->addr, clust);
810
0
                    fs_meta->attr_state = TSK_FS_META_ATTR_ERROR;
811
0
                    tsk_fs_attr_run_free(data_run_head);
812
0
                    if (list_seen != NULL) {
813
0
                        tsk_list_free(list_seen);
814
0
                        list_seen = NULL;
815
0
                    }
816
0
                    return 1;
817
0
                }
818
767
                clust = nxt;
819
820
                /* Make sure we do not get into an infinite loop */
821
767
                if (tsk_list_find(list_seen, clust)) {
822
0
                    if (tsk_verbose)
823
0
                        tsk_fprintf(stderr,
824
0
                            "Loop found while processing file\n");
825
0
                    if (data_run_head != NULL ) {
826
0
                      tsk_fs_attr_run_free(data_run_head);
827
                      // Make sure to set data_run_head to NULL to prevent a use-after-free
828
0
                      data_run_head = NULL;
829
0
                    }
830
0
                    if (list_seen != NULL) {
831
0
                        tsk_list_free(list_seen);
832
0
                        list_seen = NULL;
833
0
                    }
834
0
                    break;
835
0
                }
836
837
767
                if (tsk_list_add(&list_seen, clust)) {
838
0
                    fs_meta->attr_state = TSK_FS_META_ATTR_ERROR;
839
0
                    tsk_fs_attr_run_free(data_run_head);
840
0
                    if (list_seen != NULL) {
841
0
                        tsk_list_free(list_seen);
842
0
                        list_seen = NULL;
843
0
                    }
844
0
                    return 1;
845
0
                }
846
767
            }
847
2.06k
        }
848
849
        // add the run list to the inode structure
850
9.25k
        if ((fs_attr =
851
9.25k
                tsk_fs_attrlist_getnew(fs_meta->attr,
852
9.25k
                    TSK_FS_ATTR_NONRES)) == NULL) {
853
0
            fs_meta->attr_state = TSK_FS_META_ATTR_ERROR;
854
0
            if (list_seen != NULL) {
855
0
                tsk_list_free(list_seen);
856
0
                list_seen = NULL;
857
0
            }
858
0
            return 1;
859
0
        }
860
861
        // initialize the data run
862
9.25k
        if (tsk_fs_attr_set_run(a_fs_file, fs_attr, data_run_head, NULL,
863
9.25k
                TSK_FS_ATTR_TYPE_DEFAULT, TSK_FS_ATTR_ID_DEFAULT,
864
9.25k
                fs_meta->size, fs_meta->size, roundup(fs_meta->size,
865
9.25k
                    fatfs->csize * fs->block_size), TSK_FS_ATTR_FLAG_NONE, 0)) {
866
0
            fs_meta->attr_state = TSK_FS_META_ATTR_ERROR;
867
0
            tsk_fs_attr_run_free(data_run_head);
868
0
            if (list_seen != NULL) {
869
0
                tsk_list_free(list_seen);
870
0
                list_seen = NULL;
871
0
            }
872
0
            return 1;
873
0
        }
874
875
9.25k
        tsk_list_free(list_seen);
876
9.25k
        list_seen = NULL;
877
878
9.25k
        fs_meta->attr_state = TSK_FS_META_ATTR_STUDIED;
879
880
9.25k
        return 0;
881
9.25k
    }
882
12.0k
}
883
884
/* Used for istat callback */
885
typedef struct {
886
    FILE *hFile;
887
    int idx;
888
    int istat_seen;
889
} FATFS_PRINT_ADDR;
890
891
/* Callback a_action for file_walk to print the sector addresses
892
 * of a file, used for istat
893
 */
894
static TSK_WALK_RET_ENUM
895
print_addr_act(
896
  [[maybe_unused]] TSK_FS_FILE * fs_file,
897
  [[maybe_unused]] TSK_OFF_T a_off,
898
  TSK_DADDR_T addr,
899
  [[maybe_unused]] char *buf,
900
  [[maybe_unused]] size_t size,
901
  [[maybe_unused]] TSK_FS_BLOCK_FLAG_ENUM a_flags,
902
  void *a_ptr)
903
0
{
904
0
    FATFS_PRINT_ADDR *print = (FATFS_PRINT_ADDR *) a_ptr;
905
906
0
    tsk_fprintf(print->hFile, "%" PRIuDADDR " ", addr);
907
908
0
    if (++(print->idx) == 8) {
909
0
        tsk_fprintf(print->hFile, "\n");
910
0
        print->idx = 0;
911
0
    }
912
0
    print->istat_seen = 1;
913
914
0
    return TSK_WALK_CONT;
915
0
}
916
917
/**
918
 * Print details on a specific file to a file handle.
919
 *
920
 * @param a_fs File system file is located in.
921
 * @param a_hFile File handle to print text to.
922
 * @param a_inum Address of file in file system.
923
 * @param a_numblock The number of blocks in file to force print (can go beyond file size).
924
 * @param a_sec_skew Clock skew in seconds to also print times in.
925
 *
926
 * @returns 1 on error and 0 on success.
927
 */
928
uint8_t
929
fatfs_istat(TSK_FS_INFO *a_fs, TSK_FS_ISTAT_FLAG_ENUM istat_flags, FILE *a_hFile, TSK_INUM_T a_inum,
930
    TSK_DADDR_T a_numblock, int32_t a_sec_skew)
931
0
{
932
0
    const char* func_name = "fatfs_istat";
933
0
    FATFS_INFO *fatfs = (FATFS_INFO*)a_fs;
934
0
    TSK_FS_META *fs_meta = NULL;
935
0
    TSK_FS_META_NAME_LIST *fs_name_list = NULL;
936
0
    FATFS_PRINT_ADDR print;
937
0
    char timeBuf[128];
938
939
0
    tsk_error_reset();
940
0
    if (fatfs_ptr_arg_is_null(a_fs, "a_fs", func_name) ||
941
0
        fatfs_ptr_arg_is_null(a_hFile, "a_hFile", func_name) ||
942
0
        !fatfs_inum_arg_is_in_range(fatfs, a_inum, func_name)) {
943
0
        return 1;
944
0
    }
945
946
    /* Create a TSK_FS_FILE corresponding to the specified inode. */
947
0
    std::unique_ptr<TSK_FS_FILE, decltype(&tsk_fs_file_close)> fs_file{
948
0
        tsk_fs_file_open_meta(a_fs, NULL, a_inum),
949
0
        tsk_fs_file_close
950
0
    };
951
952
0
    if (!fs_file) {
953
0
        return 1;
954
0
    }
955
0
    fs_meta = fs_file->meta;
956
957
    /* Print the inode address. */
958
0
    tsk_fprintf(a_hFile, "Directory Entry: %" PRIuINUM "\n", a_inum);
959
960
    /* Print the allocation status. */
961
0
    tsk_fprintf(a_hFile, "%sAllocated\n",
962
0
        (fs_meta->flags & TSK_FS_META_FLAG_UNALLOC) ? "Not " : "");
963
964
    /* Print the attributes. */
965
0
    tsk_fprintf(a_hFile, "File Attributes: ");
966
967
0
    if (a_inum == a_fs->root_inum) {
968
0
        tsk_fprintf(a_hFile, "Root Directory\n");
969
0
    }
970
0
    else if (fs_meta->type == TSK_FS_META_TYPE_VIRT) {
971
0
        tsk_fprintf(a_hFile, "Virtual File\n");
972
0
    }
973
0
    else if (fs_meta->addr == TSK_FS_ORPHANDIR_INUM(a_fs)) {
974
0
        tsk_fprintf(a_hFile, "Virtual Directory\n");
975
0
    }
976
0
    else {
977
0
        if (fatfs->istat_attr_flags(fatfs, a_inum, a_hFile)) {
978
0
            return 1;
979
0
        }
980
0
    }
981
982
    /* Print the file size. */
983
0
    tsk_fprintf(a_hFile, "Size: %" PRIdOFF "\n", fs_meta->size);
984
985
    /* Print the name. */
986
0
    if (fs_meta->name2) {
987
0
        fs_name_list = fs_meta->name2;
988
0
        tsk_fprintf(a_hFile, "Name: %s\n", fs_name_list->name);
989
0
    }
990
991
    /* Print the times. */
992
0
    if (a_sec_skew != 0) {
993
0
        tsk_fprintf(a_hFile, "\nAdjusted Directory Entry Times:\n");
994
995
0
        if (fs_meta->mtime)
996
0
            fs_meta->mtime -= a_sec_skew;
997
0
        if (fs_meta->atime)
998
0
            fs_meta->atime -= a_sec_skew;
999
0
        if (fs_meta->crtime)
1000
0
            fs_meta->crtime -= a_sec_skew;
1001
1002
0
        tsk_fprintf(a_hFile, "Written:\t%s\n",
1003
0
            tsk_fs_time_to_str(fs_meta->mtime, timeBuf));
1004
0
        tsk_fprintf(a_hFile, "Accessed:\t%s\n",
1005
0
            tsk_fs_time_to_str(fs_meta->atime, timeBuf));
1006
0
        tsk_fprintf(a_hFile, "Created:\t%s\n",
1007
0
            tsk_fs_time_to_str(fs_meta->crtime, timeBuf));
1008
1009
0
        if (fs_meta->mtime)
1010
0
            fs_meta->mtime += a_sec_skew;
1011
0
        if (fs_meta->atime)
1012
0
            fs_meta->atime += a_sec_skew;
1013
0
        if (fs_meta->crtime)
1014
0
            fs_meta->crtime += a_sec_skew;
1015
1016
0
        tsk_fprintf(a_hFile, "\nOriginal Directory Entry Times:\n");
1017
0
    }
1018
0
    else {
1019
0
        tsk_fprintf(a_hFile, "\nDirectory Entry Times:\n");
1020
0
    }
1021
1022
0
    tsk_fprintf(a_hFile, "Written:\t%s\n", tsk_fs_time_to_str(fs_meta->mtime,
1023
0
        timeBuf));
1024
0
    tsk_fprintf(a_hFile, "Accessed:\t%s\n",
1025
0
        tsk_fs_time_to_str(fs_meta->atime, timeBuf));
1026
0
    tsk_fprintf(a_hFile, "Created:\t%s\n",
1027
0
        tsk_fs_time_to_str(fs_meta->crtime, timeBuf));
1028
1029
    /* Print the specified number of sector addresses. */
1030
0
    tsk_fprintf(a_hFile, "\nSectors:\n");
1031
0
    if (istat_flags & TSK_FS_ISTAT_RUNLIST) {
1032
0
        const TSK_FS_ATTR *fs_attr_default =
1033
0
            tsk_fs_file_attr_get_type(fs_file.get(),
1034
0
                TSK_FS_ATTR_TYPE_DEFAULT, 0, 0);
1035
0
        if (fs_attr_default && (fs_attr_default->flags & TSK_FS_ATTR_NONRES)) {
1036
0
            if (tsk_fs_attr_print(fs_attr_default, a_hFile)) {
1037
0
                tsk_fprintf(a_hFile, "\nError creating run lists\n");
1038
0
                tsk_error_print(a_hFile);
1039
0
                tsk_error_reset();
1040
0
            }
1041
0
        }
1042
0
    }
1043
0
    else {
1044
1045
0
        if (a_numblock > 0) {
1046
            /* A bad hack to force a specified number of blocks */
1047
0
            fs_meta->size = a_numblock * a_fs->block_size;
1048
0
        }
1049
0
        print.istat_seen = 0;
1050
0
        print.idx = 0;
1051
0
        print.hFile = a_hFile;
1052
0
        if (tsk_fs_file_walk(fs_file.get(),
1053
0
            (TSK_FS_FILE_WALK_FLAG_ENUM)(TSK_FS_FILE_WALK_FLAG_AONLY | TSK_FS_FILE_WALK_FLAG_SLACK),
1054
0
            print_addr_act, (void *)&print)) {
1055
0
            tsk_fprintf(a_hFile, "\nError reading file\n");
1056
0
            tsk_error_print(a_hFile);
1057
0
            tsk_error_reset();
1058
0
        }
1059
0
        else if (print.idx != 0) {
1060
0
            tsk_fprintf(a_hFile, "\n");
1061
0
        }
1062
0
    }
1063
1064
0
    return 0;
1065
0
}
1066
1067
/* Mark the sector used in the bitmap */
1068
static TSK_WALK_RET_ENUM
1069
inode_walk_file_act(
1070
  [[maybe_unused]] TSK_FS_FILE * fs_file,
1071
  [[maybe_unused]] TSK_OFF_T a_off,
1072
  TSK_DADDR_T addr,
1073
  [[maybe_unused]] char *buf,
1074
  [[maybe_unused]] size_t size,
1075
  [[maybe_unused]] TSK_FS_BLOCK_FLAG_ENUM a_flags,
1076
  void *a_ptr)
1077
20.4k
{
1078
20.4k
    setbit((uint8_t *) a_ptr, addr);
1079
20.4k
    return TSK_WALK_CONT;
1080
20.4k
}
1081
1082
/* The inode_walk call back for each file.  we want only the directories */
1083
static TSK_WALK_RET_ENUM
1084
inode_walk_dent_act(
1085
  TSK_FS_FILE * fs_file,
1086
  [[maybe_unused]] const char *a_path,
1087
  void *a_ptr)
1088
89.0k
{
1089
89.0k
    unsigned int flags = TSK_FS_FILE_WALK_FLAG_SLACK | TSK_FS_FILE_WALK_FLAG_AONLY;
1090
1091
89.0k
    if ((fs_file->meta == NULL)
1092
89.0k
        || ( ! TSK_FS_IS_DIR_META(fs_file->meta->type)))
1093
79.9k
        return TSK_WALK_CONT;
1094
1095
    /* Get the sector addresses & ignore any errors */
1096
9.13k
    if (tsk_fs_file_walk(fs_file,
1097
9.13k
            (TSK_FS_FILE_WALK_FLAG_ENUM)flags,
1098
9.13k
            inode_walk_file_act, a_ptr)) {
1099
995
        tsk_error_reset();
1100
995
    }
1101
1102
9.13k
    return TSK_WALK_CONT;
1103
89.0k
}
1104
1105
/**
1106
 * Walk the inodes in a specified range and do a TSK_FS_META_WALK_CB callback
1107
 * for each inode that satisfies criteria specified by a set of
1108
 * TSK_FS_META_FLAG_ENUM flags. The following flags are supported:
1109
 * TSK_FS_META_FLAG_ALLOC, TSK_FS_META_FLAG_UNALLOC, TSK_FS_META_FLAG_ORPHAN,
1110
 * TSK_FS_META_FLAG_USED (FATXX only), and TSK_FS_META_FLAG_UNUSED
1111
 * (FATXX only).
1112
 *
1113
 * @param [in] a_fs File system that contains the inodes.
1114
 * @param [in] a_start_inum Inclusive lower bound of inode range.
1115
 * @param [in] a_end_inum Inclusive upper bound of inode range.
1116
 * @param [in] a_selection_flags Inode selection criteria.
1117
 * @param [in] a_action Callback function for selected inodes.
1118
 * @param [in] a_ptr Private data pointer passed through to callback function.
1119
 * @return 0 on success, 1 on failure, per TSK convention
1120
 */
1121
uint8_t
1122
fatfs_inode_walk(TSK_FS_INFO *a_fs, TSK_INUM_T a_start_inum,
1123
    TSK_INUM_T a_end_inum, TSK_FS_META_FLAG_ENUM a_selection_flags,
1124
    TSK_FS_META_WALK_CB a_action, void *a_ptr)
1125
293
{
1126
293
    const char *func_name = "fatfs_inode_walk";
1127
293
    FATFS_INFO *fatfs = (FATFS_INFO*)a_fs;
1128
293
    unsigned int flags = a_selection_flags;
1129
293
    TSK_INUM_T end_inum_tmp = 0;
1130
293
    TSK_DADDR_T ssect = 0;
1131
293
    TSK_DADDR_T lsect = 0;
1132
293
    TSK_DADDR_T sect = 0;
1133
293
    char *dino_buf = NULL;
1134
293
    FATFS_DENTRY *dep = NULL;
1135
293
    unsigned int dentry_idx = 0;
1136
293
    uint8_t *dir_sectors_bitmap = NULL;
1137
293
    ssize_t cnt = 0;
1138
293
    uint8_t done = 0;
1139
1140
293
    tsk_error_reset();
1141
293
    if (fatfs_ptr_arg_is_null(a_fs, "a_fs", func_name) ||
1142
293
        fatfs_ptr_arg_is_null(*(void **) &a_action, "a_action", func_name)) {
1143
0
        return 1;
1144
0
    }
1145
1146
293
    if (a_start_inum < a_fs->first_inum || a_start_inum > a_fs->last_inum) {
1147
0
        tsk_error_set_errno(TSK_ERR_FS_WALK_RNG);
1148
0
        tsk_error_set_errstr("%s: Begin inode out of range:  %" PRIuINUM "",
1149
0
            func_name, a_start_inum);
1150
0
        return 1;
1151
0
    }
1152
293
    else if (a_end_inum < a_fs->first_inum ||
1153
293
             a_end_inum > a_fs->last_inum ||
1154
293
             a_end_inum < a_start_inum) {
1155
0
        tsk_error_set_errno(TSK_ERR_FS_WALK_RNG);
1156
0
        tsk_error_set_errstr("%s: End inode out of range: %" PRIuINUM "",
1157
0
            func_name, a_end_inum);
1158
0
        return 1;
1159
0
    }
1160
1161
    /* FAT file systems do not really have the concept of unused inodes. */
1162
293
    if ((flags & TSK_FS_META_FLAG_UNUSED) && !(flags & TSK_FS_META_FLAG_USED)) {
1163
0
        return 0;
1164
0
    }
1165
293
    flags |= TSK_FS_META_FLAG_USED;
1166
293
    flags &= ~TSK_FS_META_FLAG_UNUSED;
1167
1168
    /* Make sure the inode selection flags are set correctly. */
1169
293
    if (flags & TSK_FS_META_FLAG_ORPHAN) {
1170
        /* If ORPHAN file inodes are wanted, make sure that the UNALLOC
1171
         * selection flag is set. */
1172
0
        flags |= TSK_FS_META_FLAG_UNALLOC;
1173
0
        flags &= ~TSK_FS_META_FLAG_ALLOC;
1174
0
    }
1175
293
    else {
1176
        /* If neither of the ALLOC or UNALLOC inode selection flags are set,
1177
        *  then set them both. */
1178
293
        if (((flags & TSK_FS_META_FLAG_ALLOC) == 0) &&
1179
293
            ((flags & TSK_FS_META_FLAG_UNALLOC) == 0)) {
1180
0
            flags |= (TSK_FS_META_FLAG_ALLOC | TSK_FS_META_FLAG_UNALLOC);
1181
0
        }
1182
293
    }
1183
1184
293
    if (tsk_verbose) {
1185
0
        tsk_fprintf(stderr,
1186
0
            "%s: Inode walking %" PRIuINUM " to %"
1187
0
            PRIuINUM "\n", func_name, a_start_inum, a_end_inum);
1188
0
    }
1189
1190
    /* If we are looking for orphan files and have not yet populated
1191
     * the list of files reachable by name for this file system, do so now.
1192
     */
1193
293
    if ((flags & TSK_FS_META_FLAG_ORPHAN)) {
1194
0
        if (tsk_fs_dir_load_inum_named(a_fs) != TSK_OK) {
1195
0
            tsk_error_errstr2_concat(
1196
0
                "%s: Identifying orphan inodes", func_name);
1197
0
            return 1;
1198
0
        }
1199
0
    }
1200
1201
    /* Allocate a TSK_FS_FILE object with a TSK_FS_META object to populate and
1202
     * pass to the callback function when an inode that fits the inode
1203
     * selection criteria is found. */
1204
293
    std::unique_ptr<TSK_FS_FILE, decltype(&tsk_fs_file_close)> fs_file{
1205
293
        tsk_fs_file_alloc(a_fs),
1206
293
        tsk_fs_file_close
1207
293
    };
1208
293
    if (!fs_file) {
1209
0
        return 1;
1210
0
    }
1211
1212
293
    if ((fs_file->meta =
1213
293
            tsk_fs_meta_alloc(FATFS_FILE_CONTENT_LEN)) == NULL) {
1214
0
        return 1;
1215
0
    }
1216
1217
    /* Process the root directory inode, if it's included in the walk. */
1218
293
    if (a_start_inum == a_fs->root_inum) {
1219
293
        if (((TSK_FS_META_FLAG_ALLOC & flags) == TSK_FS_META_FLAG_ALLOC)
1220
0
            && ((TSK_FS_META_FLAG_ORPHAN & flags) == 0)) {
1221
0
            TSK_WALK_RET_ENUM retval = TSK_WALK_CONT;
1222
1223
0
            if (fatfs_make_root(fatfs, fs_file->meta)) {
1224
0
                return 1;
1225
0
            }
1226
1227
0
            retval = a_action(fs_file.get(), a_ptr);
1228
0
            if (retval == TSK_WALK_STOP) {
1229
0
                return 0;
1230
0
            }
1231
0
            else if (retval == TSK_WALK_ERROR) {
1232
0
                return 1;
1233
0
            }
1234
0
        }
1235
1236
293
        a_start_inum++;
1237
293
        if (a_start_inum == a_end_inum) {
1238
0
            return 0;
1239
0
        }
1240
293
    }
1241
293
    size_t bitmap_len = (a_fs->block_count + 7) / 8;
1242
1243
    // Taking 128 MiB as an arbitrary upper bound
1244
293
    if ((bitmap_len == 0) || (bitmap_len > (128 * 1024 * 1024))) {
1245
261
        return 1;
1246
261
    }
1247
1248
    /* Allocate a bitmap to keep track of which sectors are allocated to
1249
     * directories. */
1250
32
    if ((dir_sectors_bitmap = (uint8_t*)tsk_malloc(bitmap_len)) == NULL) {
1251
0
        return 1;
1252
0
    }
1253
1254
    /* If not doing an orphan files search, populate the directory sectors
1255
     * bitmap. The bitmap will be used to make sure that no sector marked as
1256
     * allocated to a directory is skipped when searching for directory
1257
     * entries to map to inodes. */
1258
32
    if ((flags & TSK_FS_META_FLAG_ORPHAN) == 0) {
1259
32
        if (tsk_verbose) {
1260
0
            tsk_fprintf(stderr,
1261
0
                "fatfs_inode_walk: Walking directories to collect sector info\n");
1262
0
        }
1263
1264
        /* Manufacture an inode for the root directory. */
1265
32
        if (fatfs_make_root(fatfs, fs_file->meta)) {
1266
0
            free(dir_sectors_bitmap);
1267
0
            return 1;
1268
0
        }
1269
1270
        /* Do a file_walk on the root directory to set the bits in the
1271
         * directory sectors bitmap for each sector allocated to the root
1272
         * directory. */
1273
32
        if (tsk_fs_file_walk(fs_file.get(),
1274
32
                (TSK_FS_FILE_WALK_FLAG_ENUM)(TSK_FS_FILE_WALK_FLAG_SLACK | TSK_FS_FILE_WALK_FLAG_AONLY),
1275
32
                inode_walk_file_act, (void*)dir_sectors_bitmap)) {
1276
0
            free(dir_sectors_bitmap);
1277
0
            return 1;
1278
0
        }
1279
1280
        /* Now walk recursively through the entire directory tree to set the
1281
         * bits in the directory sectors bitmap for each sector allocated to
1282
         * the children of the root directory. */
1283
32
        if (tsk_fs_dir_walk(a_fs, a_fs->root_inum,
1284
32
                (TSK_FS_DIR_WALK_FLAG_ENUM)(TSK_FS_DIR_WALK_FLAG_ALLOC | TSK_FS_DIR_WALK_FLAG_RECURSE |
1285
32
                TSK_FS_DIR_WALK_FLAG_NOORPHAN), inode_walk_dent_act,
1286
32
                (void *) dir_sectors_bitmap)) {
1287
0
            tsk_error_errstr2_concat
1288
0
                ("- fatfs_inode_walk: mapping directories");
1289
0
            free(dir_sectors_bitmap);
1290
0
            return 1;
1291
0
        }
1292
32
    }
1293
1294
    /* If the end inode is the one of the virtual virtual FAT files or the
1295
     * virtual orphan files directory, adjust the end inum and handle the
1296
     * virtual inodes after the main inode walking loop below completes. */
1297
32
    if (a_end_inum > a_fs->last_inum - FATFS_NUM_VIRT_FILES(fatfs)) {
1298
32
        end_inum_tmp = a_fs->last_inum - FATFS_NUM_VIRT_FILES(fatfs);
1299
32
    }
1300
0
    else {
1301
0
        end_inum_tmp = a_end_inum;
1302
0
    }
1303
1304
    /* Map the begin and end inodes to the sectors that contain them.
1305
     * This sets the image level boundaries for the inode walking loop. */
1306
32
    ssect = FATFS_INODE_2_SECT(fatfs, a_start_inum);
1307
32
    if (ssect > a_fs->last_block) {
1308
0
        tsk_error_reset();
1309
0
        tsk_error_set_errno(TSK_ERR_FS_WALK_RNG);
1310
0
        tsk_error_set_errstr
1311
0
            ("%s: Begin inode in sector too big for image: %"
1312
0
            PRIuDADDR, func_name, ssect);
1313
0
        free(dir_sectors_bitmap);
1314
0
        return 1;
1315
0
    }
1316
1317
32
    lsect = FATFS_INODE_2_SECT(fatfs, end_inum_tmp);
1318
32
    if (lsect > a_fs->last_block) {
1319
0
        tsk_error_reset();
1320
0
        tsk_error_set_errno(TSK_ERR_FS_WALK_RNG);
1321
0
        tsk_error_set_errstr
1322
0
            ("%s: End inode in sector too big for image: %"
1323
0
            PRIuDADDR, func_name, lsect);
1324
0
        free(dir_sectors_bitmap);
1325
0
        return 1;
1326
0
    }
1327
1328
    /* Allocate a buffer big enough to read in a cluster at a time. */
1329
32
    if ((dino_buf = (char*)tsk_malloc(fatfs->csize << fatfs->ssize_sh)) ==
1330
32
        NULL) {
1331
0
        free(dir_sectors_bitmap);
1332
0
        return 1;
1333
0
    }
1334
1335
    /* Walk the inodes. */
1336
32
    sect = ssect;
1337
23.2k
    while (sect <= lsect) {
1338
23.1k
        int cluster_is_alloc = 0;
1339
23.1k
        size_t num_sectors_to_process = 0;
1340
23.1k
        size_t sector_idx = 0;
1341
23.1k
        uint8_t do_basic_dentry_test = 0;
1342
1343
        /* Read in a chunk of the image to process on this iteration of the inode
1344
         * walk. The actual size of the read will depend on whether or not it is
1345
         * coming from the root directory of a FAT12 or FAT16 file system. As
1346
         * indicated by the size of the buffer, the data area (exFAT cluster
1347
         * heap) will for the most part be read in a cluster at a time.
1348
         * However, the root directory for a FAT12/FAT16 file system precedes
1349
         * the data area and the read size for it should be a sector, not a
1350
         * cluster. */
1351
23.1k
        if (sect < fatfs->firstclustsect) {
1352
1353
6.38k
            if ((flags & TSK_FS_META_FLAG_ORPHAN) != 0) {
1354
                /* If orphan file hunting, there are no orphans in the root
1355
                 * directory, so skip ahead to the data area. */
1356
0
                sect = fatfs->firstclustsect;
1357
0
                continue;
1358
0
            }
1359
1360
            /* Read in a FAT12/FAT16 root directory sector. */
1361
6.38k
            cnt = tsk_fs_read_block(a_fs, sect, dino_buf, fatfs->ssize);
1362
6.38k
            if (cnt != fatfs->ssize) {
1363
0
                if (cnt >= 0) {
1364
0
                    tsk_error_reset();
1365
0
                    tsk_error_set_errno(TSK_ERR_FS_READ);
1366
0
                }
1367
0
                tsk_error_set_errstr2
1368
0
                    ("%s (root dir): sector: %" PRIuDADDR,
1369
0
                    func_name, sect);
1370
0
                free(dir_sectors_bitmap);
1371
0
                free(dino_buf);
1372
0
                return 1;
1373
0
            }
1374
1375
6.38k
            cluster_is_alloc = 1;
1376
6.38k
            num_sectors_to_process = 1;
1377
6.38k
        }
1378
16.8k
        else {
1379
            /* The walk has proceeded into the data area (exFAT cluster heap).
1380
             * It's time to read in a cluster at a time. Get the base sector
1381
             * for the cluster that contains the current sector. */
1382
16.8k
            sect =
1383
16.8k
                FATFS_CLUST_2_SECT(fatfs, (FATFS_SECT_2_CLUST(fatfs,
1384
16.8k
                        sect)));
1385
1386
            /* Determine whether the cluster is allocated. Skip it if it is
1387
             * not allocated and the UNALLOCATED inode selection flag is not
1388
             * set. */
1389
16.8k
            cluster_is_alloc = fatfs_is_sectalloc(fatfs, sect);
1390
16.8k
            if ((cluster_is_alloc == 0)
1391
12.4k
                && ((flags & TSK_FS_META_FLAG_UNALLOC) == 0)) {
1392
0
                sect += fatfs->csize;
1393
0
                continue;
1394
0
            }
1395
16.8k
            else if (cluster_is_alloc == -1) {
1396
0
                free(dir_sectors_bitmap);
1397
0
                free(dino_buf);
1398
0
                return 1;
1399
0
            }
1400
1401
            /* If the cluster is allocated but is not allocated to a
1402
             * directory, then skip it.  NOTE: This will miss orphan file
1403
             * entries in the slack space of files.
1404
             */
1405
16.8k
            if ((cluster_is_alloc == 1) && (isset(dir_sectors_bitmap, sect) == 0)) {
1406
4.30k
                sect += fatfs->csize;
1407
4.30k
                continue;
1408
4.30k
            }
1409
1410
            /* The final cluster may not be full. */
1411
12.5k
            if (lsect - sect + 1 < fatfs->csize) {
1412
14
                num_sectors_to_process = (size_t) (lsect - sect + 1);
1413
14
            }
1414
12.4k
            else {
1415
12.4k
                num_sectors_to_process = fatfs->csize;
1416
12.4k
            }
1417
1418
            /* Read in a cluster. */
1419
12.5k
            cnt = tsk_fs_read_block
1420
12.5k
                (a_fs, sect, dino_buf, num_sectors_to_process << fatfs->ssize_sh);
1421
12.5k
            if (cnt != (ssize_t)(num_sectors_to_process << fatfs->ssize_sh)) {
1422
0
                if (cnt >= 0) {
1423
0
                    tsk_error_reset();
1424
0
                    tsk_error_set_errno(TSK_ERR_FS_READ);
1425
0
                }
1426
0
                tsk_error_set_errstr2("%s: sector: %"
1427
0
                    PRIuDADDR, func_name, sect);
1428
0
                free(dir_sectors_bitmap);
1429
0
                free(dino_buf);
1430
0
                return 1;
1431
0
            }
1432
12.5k
        }
1433
1434
        /* Now that the sectors are read in, prepare to step through them in
1435
         * directory entry size chunks. Only do a basic test to confirm the
1436
         * contents of each chunk is a directory entry unless the sector that
1437
         * contains it is not allocated to a directory or is unallocated.*/
1438
18.8k
        do_basic_dentry_test = 1;
1439
18.8k
        if ((isset(dir_sectors_bitmap, sect) == 0) || (cluster_is_alloc == 0)) {
1440
12.4k
            do_basic_dentry_test = 0;
1441
12.4k
        }
1442
1443
        /* Walk through the sectors read in. */
1444
57.9k
        for (sector_idx = 0; sector_idx < num_sectors_to_process; sector_idx++) {
1445
39.0k
            TSK_INUM_T inum = 0;
1446
1447
            /* If the last inode in this sector is before the start
1448
             * inode, skip the sector. */
1449
39.0k
            if (FATFS_SECT_2_INODE(fatfs, sect + 1) < a_start_inum) {
1450
0
                sect++;
1451
0
                continue;
1452
0
            }
1453
1454
            /* Advance the directory entry pointer to the start of the
1455
             * sector. */
1456
39.0k
            dep = (FATFS_DENTRY*)(&dino_buf[sector_idx << fatfs->ssize_sh]);
1457
1458
            /* If the sector is not allocated to a directory and the first
1459
             * chunk is not a directory entry, skip the sector. */
1460
39.0k
            if (!isset(dir_sectors_bitmap, sect) &&
1461
31.8k
                !fatfs->is_dentry(fatfs, dep, (FATFS_DATA_UNIT_ALLOC_STATUS_ENUM)cluster_is_alloc, do_basic_dentry_test)) {
1462
22.4k
                sect++;
1463
22.4k
                continue;
1464
22.4k
            }
1465
1466
            /* Get the base inode address of this sector. */
1467
16.5k
            inum = FATFS_SECT_2_INODE(fatfs, sect);
1468
16.5k
            if (tsk_verbose) {
1469
0
                tsk_fprintf(stderr,
1470
0
                    "%s: Processing sector %" PRIuDADDR
1471
0
                    " starting at inode %" PRIuINUM "\n", func_name, sect, inum);
1472
0
            }
1473
1474
            /* Walk through the potential directory entries in the sector. */
1475
372k
            for (dentry_idx = 0; dentry_idx < fatfs->dentry_cnt_se;
1476
356k
                dentry_idx++, inum++, dep++) {
1477
356k
                int retval;
1478
356k
                TSK_RETVAL_ENUM retval2 = TSK_OK;
1479
1480
                /* If the inode address of the potential entry is less than
1481
                 * the beginning inode address for the inode walk, skip it. */
1482
356k
                if (inum < a_start_inum) {
1483
0
                    continue;
1484
0
                }
1485
1486
                /* If inode address of the potential entry is greater than the
1487
                 * ending inode address for the walk, terminate the inode walk. */
1488
356k
                if (inum > end_inum_tmp) {
1489
0
                    done = 1;
1490
0
                    break;
1491
0
                }
1492
1493
                /* If the potential entry is likely not an entry, or it is an
1494
                 * entry that is not reported in an inode walk, or it does not
1495
                 * satisfy the inode selection flags, then skip it. */
1496
356k
                if (!fatfs->is_dentry(fatfs, dep, (FATFS_DATA_UNIT_ALLOC_STATUS_ENUM)cluster_is_alloc, do_basic_dentry_test) ||
1497
220k
                    fatfs->inode_walk_should_skip_dentry(fatfs, inum, dep, flags, cluster_is_alloc)) {
1498
175k
                    continue;
1499
175k
                }
1500
1501
180k
                retval2 = fatfs->dinode_copy(fatfs, inum, dep, cluster_is_alloc, fs_file.get());
1502
1503
180k
                if (retval2 != TSK_OK) {
1504
0
                    if (retval2 == TSK_COR) {
1505
                        /* Corrupted, move on to the next chunk. */
1506
0
                        if (tsk_verbose) {
1507
0
                            tsk_error_print(stderr);
1508
0
                        }
1509
0
                        tsk_error_reset();
1510
0
                        continue;
1511
0
                    }
1512
0
                    else {
1513
0
                        free(dir_sectors_bitmap);
1514
0
                        free(dino_buf);
1515
0
                        return 1;
1516
0
                    }
1517
0
                }
1518
1519
180k
                if (tsk_verbose) {
1520
0
                    tsk_fprintf(stderr,
1521
0
                        "%s: Directory Entry %" PRIuINUM
1522
0
                        " (%u) at sector %" PRIuDADDR "\n", func_name, inum, dentry_idx,
1523
0
                        sect);
1524
0
                }
1525
1526
                /* Do the callback. */
1527
180k
                retval = a_action(fs_file.get(), a_ptr);
1528
180k
                if (retval == TSK_WALK_STOP) {
1529
0
                    free(dir_sectors_bitmap);
1530
0
                    free(dino_buf);
1531
0
                    return 0;
1532
0
                }
1533
180k
                else if (retval == TSK_WALK_ERROR) {
1534
1
                    free(dir_sectors_bitmap);
1535
1
                    free(dino_buf);
1536
1
                    return 1;
1537
1
                }
1538
180k
            }
1539
16.5k
            sect++;
1540
16.5k
            if (done) {
1541
0
                break;
1542
0
            }
1543
16.5k
        }
1544
18.8k
        if (done) {
1545
0
            break;
1546
0
        }
1547
18.8k
    }
1548
1549
31
    free(dir_sectors_bitmap);
1550
31
    free(dino_buf);
1551
1552
    // handle the virtual orphans folder and FAT files if they asked for them
1553
31
    if ((a_end_inum > a_fs->last_inum - FATFS_NUM_VIRT_FILES(fatfs))
1554
31
        && (flags & TSK_FS_META_FLAG_ALLOC)
1555
0
        && ((flags & TSK_FS_META_FLAG_ORPHAN) == 0)) {
1556
0
        TSK_INUM_T inum;
1557
1558
        // cycle through the special files
1559
0
        for (inum = a_fs->last_inum - FATFS_NUM_VIRT_FILES(fatfs) + 1;
1560
0
            inum <= a_end_inum; inum++) {
1561
0
            int retval;
1562
1563
0
            tsk_fs_meta_reset(fs_file->meta);
1564
1565
0
            if (inum == fatfs->mbr_virt_inum) {
1566
0
                if (fatfs_make_mbr(fatfs, fs_file->meta)) {
1567
0
                    return 1;
1568
0
                }
1569
0
            }
1570
0
            else if (inum == fatfs->fat1_virt_inum) {
1571
0
                if (fatfs_make_fat(fatfs, 1, fs_file->meta)) {
1572
0
                    return 1;
1573
0
                }
1574
0
            }
1575
0
            else if (inum == fatfs->fat2_virt_inum && fatfs->numfat == 2) {
1576
0
                if (fatfs_make_fat(fatfs, 2, fs_file->meta)) {
1577
0
                    return 1;
1578
0
                }
1579
0
            }
1580
0
            else if (inum == TSK_FS_ORPHANDIR_INUM(a_fs)) {
1581
0
                if (tsk_fs_dir_make_orphan_dir_meta(a_fs, fs_file->meta)) {
1582
0
                    return 1;
1583
0
                }
1584
0
            }
1585
1586
0
            retval = a_action(fs_file.get(), a_ptr);
1587
0
            if (retval == TSK_WALK_STOP) {
1588
0
                return 0;
1589
0
            }
1590
0
            else if (retval == TSK_WALK_ERROR) {
1591
0
                return 1;
1592
0
            }
1593
0
        }
1594
0
    }
1595
1596
31
    return 0;
1597
31
}