Coverage Report

Created: 2025-07-01 06:58

/src/sleuthkit/tsk/fs/fatfs.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
** The Sleuth Kit
3
**
4
** Copyright (c) 2013 Basis Technology Corp.  All rights reserved
5
** Contact: Brian Carrier [carrier <at> sleuthkit [dot] org]
6
**
7
** This software is distributed under the Common Public License 1.0
8
**
9
*/
10
11
/**
12
 * \file fatfs.c
13
 * Contains the internal TSK FAT file system code to handle basic file system
14
 * processing for opening file system, processing sectors, and directory entries.
15
 */
16
17
#include "tsk_fs_i.h"
18
#include "tsk_fatfs.h"
19
#include "tsk_fatxxfs.h"
20
#include "tsk_exfatfs.h"
21
22
#include "encryptionHelper.h"
23
24
/**
25
 * \internal
26
 * Open part of a disk image as a FAT file system.
27
 *
28
 * @param a_img_info Disk image to analyze
29
 * @param a_offset Byte offset where FAT file system starts
30
 * @param a_ftype Specific type of FAT file system
31
 * @param a_pass (Optional) bitlocker password
32
 * @param a_test NOT USED
33
 * @returns NULL on error or if data is not a FAT file system
34
 */
35
TSK_FS_INFO *
36
fatfs_open(
37
  TSK_IMG_INFO *a_img_info,
38
  TSK_OFF_T a_offset,
39
  TSK_FS_TYPE_ENUM a_ftype,
40
  const char* a_pass,
41
  [[maybe_unused]] uint8_t a_test)
42
0
{
43
0
    const char *func_name = "fatfs_open";
44
0
    FATFS_INFO *fatfs = NULL;
45
0
    TSK_FS_INFO *fs = NULL;
46
0
  int find_boot_sector_attempt = 0;
47
48
0
    tsk_error_reset();
49
50
0
    if (TSK_FS_TYPE_ISFAT(a_ftype) == 0) {
51
0
        tsk_error_reset();
52
0
        tsk_error_set_errno(TSK_ERR_FS_ARG);
53
0
        tsk_error_set_errstr("%s: Invalid FS Type", func_name);
54
0
        return NULL;
55
0
    }
56
57
0
    if (a_img_info->sector_size == 0) {
58
0
        tsk_error_reset();
59
0
        tsk_error_set_errno(TSK_ERR_FS_ARG);
60
0
        tsk_error_set_errstr("fatfs_open: sector size is 0");
61
0
        return NULL;
62
0
    }
63
64
  // Allocate an FATFS_INFO and initialize its generic TSK_FS_INFO members.
65
0
    if ((fatfs = (FATFS_INFO*)tsk_fs_malloc(sizeof(FATFS_INFO))) == NULL) {
66
0
        return NULL;
67
0
  }
68
0
    fs = &(fatfs->fs_info);
69
0
    fs->ftype = a_ftype;
70
0
    fs->img_info = a_img_info;
71
0
    fs->offset = a_offset;
72
0
    fs->dev_bsize = a_img_info->sector_size;
73
0
    fs->journ_inum = 0;
74
0
    fs->tag = TSK_FS_INFO_TAG;
75
76
    // Check for any volume encryption and initialize if found.
77
    // A non-zero value will only be returned if we are very confident encryption was found
78
    // but encountered an error and should not continue trying to open the volume.
79
    // In this case we should also have a specific error to get back to the user, such as reporting an incorrect password.
80
0
    if (0 != handleVolumeEncryption(fs, a_pass)) {
81
0
        tsk_fs_free((TSK_FS_INFO*)fatfs);
82
0
        return NULL;
83
0
    }
84
85
  // Look for a FAT boot sector. Try up to three times because FAT32 and exFAT file systems have backup boot sectors.
86
0
    for (find_boot_sector_attempt = 0; find_boot_sector_attempt < 3; ++find_boot_sector_attempt) {
87
0
        TSK_OFF_T boot_sector_offset;
88
0
        FATFS_MASTER_BOOT_RECORD *bootSector;
89
0
        ssize_t bytes_read = 0;
90
91
0
        switch (find_boot_sector_attempt) {
92
0
            case 0:
93
0
                boot_sector_offset = 0;
94
0
                break;
95
0
            case 1:
96
          // The FATXX backup boot sector is located in sector 6, look there.
97
0
                boot_sector_offset = 6 * fs->img_info->sector_size;
98
0
                break;
99
0
            case 2:
100
                // The exFAT backup boot sector is located in sector 12, look there.
101
0
                boot_sector_offset = 12 * fs->img_info->sector_size;
102
0
                break;
103
0
    }
104
105
        // Read in the prospective boot sector.
106
0
        bytes_read = tsk_fs_read(fs, boot_sector_offset, fatfs->boot_sector_buffer, FATFS_MASTER_BOOT_RECORD_SIZE);
107
0
        if (bytes_read != FATFS_MASTER_BOOT_RECORD_SIZE) {
108
0
            if (bytes_read >= 0) {
109
0
                tsk_error_reset();
110
0
                tsk_error_set_errno(TSK_ERR_FS_READ);
111
0
            }
112
0
            tsk_error_set_errstr2("%s: boot sector", func_name);
113
0
      tsk_fs_free((TSK_FS_INFO *)fatfs);
114
0
      return NULL;
115
0
        }
116
117
        // Check it out...
118
0
        bootSector = (FATFS_MASTER_BOOT_RECORD*)fatfs->boot_sector_buffer;
119
0
        if (tsk_fs_guessu16(fs, bootSector->magic, FATFS_FS_MAGIC) != 0) {
120
            // No magic, look for a backup boot sector.
121
0
            if ((tsk_getu16(TSK_LIT_ENDIAN, bootSector->magic) == 0) && (find_boot_sector_attempt < 3)) {
122
0
                continue;
123
0
            }
124
0
            else {
125
0
                tsk_error_reset();
126
0
                tsk_error_set_errno(TSK_ERR_FS_MAGIC);
127
0
                tsk_error_set_errstr("Not a FATFS file system (magic)");
128
0
                if (tsk_verbose) {
129
0
                    fprintf(stderr, "%s: Incorrect FATFS magic\n", func_name);
130
0
        }
131
0
        tsk_fs_free((TSK_FS_INFO *)fatfs);
132
0
        return NULL;
133
0
            }
134
0
        }
135
0
        else {
136
            // Found the magic.
137
0
            fatfs->using_backup_boot_sector = boot_sector_offset > 0;
138
0
            if (fatfs->using_backup_boot_sector && tsk_verbose) {
139
0
        fprintf(stderr, "%s: Using backup boot sector\n", func_name);
140
0
            }
141
0
            break;
142
0
        }
143
0
    }
144
145
  // Attempt to open the file system as one of the FAT types.
146
0
    if ((a_ftype == TSK_FS_TYPE_FAT_DETECT && (fatxxfs_open(fatfs) == 0 || exfatfs_open(fatfs) == 0)) ||
147
0
    (a_ftype == TSK_FS_TYPE_EXFAT && exfatfs_open(fatfs) == 0) ||
148
0
    (fatxxfs_open(fatfs) == 0)) {
149
0
      return (TSK_FS_INFO*)fatfs;
150
0
  }
151
0
    else {
152
0
        tsk_fs_free((TSK_FS_INFO *)fatfs);
153
0
    return NULL;
154
0
    }
155
0
}
156
157
/* TTL is 0 if the entry has not been used.  TTL of 1 means it was the
158
 * most recently used, and TTL of FATFS_FAT_CACHE_N means it was the least
159
 * recently used.  This function has a LRU replacement algo
160
 *
161
 * Note: This routine assumes &fatfs->cache_lock is locked by the caller.
162
 */
163
// return -1 on error, or cache index on success (0 to FATFS_FAT_CACHE_N)
164
165
static int
166
getFATCacheIdx(FATFS_INFO * fatfs, TSK_DADDR_T sect)
167
0
{
168
0
    int i, cidx;
169
0
    ssize_t cnt;
170
0
    TSK_FS_INFO *fs = (TSK_FS_INFO *) & fatfs->fs_info;
171
172
    // see if we already have it in the cache
173
0
    for (i = 0; i < FATFS_FAT_CACHE_N; i++) {
174
0
        if ((fatfs->fatc_ttl[i] > 0) &&
175
0
            (sect >= fatfs->fatc_addr[i]) &&
176
0
            (sect < (fatfs->fatc_addr[i] + (FATFS_FAT_CACHE_B >> fatfs->ssize_sh)))) {
177
0
            int a;
178
179
            // update the TTLs to push i to the front
180
0
            for (a = 0; a < FATFS_FAT_CACHE_N; a++) {
181
0
                if (fatfs->fatc_ttl[a] == 0)
182
0
                    continue;
183
184
0
                if (fatfs->fatc_ttl[a] < fatfs->fatc_ttl[i])
185
0
                    fatfs->fatc_ttl[a]++;
186
0
            }
187
0
            fatfs->fatc_ttl[i] = 1;
188
//          fprintf(stdout, "FAT Hit: %d\n", sect);
189
//          fflush(stdout);
190
0
            return i;
191
0
        }
192
0
    }
193
194
//    fprintf(stdout, "FAT Miss: %d\n", (int)sect);
195
//    fflush(stdout);
196
197
    // Look for an unused entry or an entry with a TTL of FATFS_FAT_CACHE_N
198
0
    cidx = 0;
199
0
    for (i = 0; i < FATFS_FAT_CACHE_N; i++) {
200
0
        if ((fatfs->fatc_ttl[i] == 0) ||
201
0
            (fatfs->fatc_ttl[i] >= FATFS_FAT_CACHE_N)) {
202
0
            cidx = i;
203
0
        }
204
0
    }
205
//    fprintf(stdout, "FAT Removing: %d\n", (int)fatfs->fatc_addr[cidx]);
206
    //   fflush(stdout);
207
208
    // read the data
209
0
    cnt =
210
0
        tsk_fs_read(fs, sect * fs->block_size, fatfs->fatc_buf[cidx],
211
0
        FATFS_FAT_CACHE_B);
212
0
    if (cnt != FATFS_FAT_CACHE_B) {
213
0
        if (cnt >= 0) {
214
0
            tsk_error_reset();
215
0
            tsk_error_set_errno(TSK_ERR_FS_READ);
216
0
        }
217
0
        tsk_error_set_errstr2("getFATCacheIdx: FAT: %" PRIuDADDR, sect);
218
0
        return -1;
219
0
    }
220
221
    // update the TTLs
222
0
    if (fatfs->fatc_ttl[cidx] == 0)     // special case for unused entry
223
0
        fatfs->fatc_ttl[cidx] = FATFS_FAT_CACHE_N + 1;
224
225
0
    for (i = 0; i < FATFS_FAT_CACHE_N; i++) {
226
0
        if (fatfs->fatc_ttl[i] == 0)
227
0
            continue;
228
229
0
        if (fatfs->fatc_ttl[i] < fatfs->fatc_ttl[cidx])
230
0
            fatfs->fatc_ttl[i]++;
231
0
    }
232
233
0
    fatfs->fatc_ttl[cidx] = 1;
234
0
    fatfs->fatc_addr[cidx] = sect;
235
236
0
    return cidx;
237
0
}
238
239
/*
240
 * Set *value to the entry in the File Allocation Table (FAT)
241
 * for the given cluster
242
 *
243
 * *value is in clusters and may need to be converted to
244
 * sectors by the calling function
245
 *
246
 * Invalid values in the FAT (i.e. greater than the largest
247
 * cluster have a value of 0 returned and a 0 return value.
248
 *
249
 * Return 1 on error and 0 on success
250
 */
251
uint8_t
252
fatfs_getFAT(FATFS_INFO * fatfs, TSK_DADDR_T clust, TSK_DADDR_T * value)
253
0
{
254
0
    uint8_t *a_ptr;
255
0
    uint16_t tmp16;
256
0
    TSK_FS_INFO *fs = (TSK_FS_INFO *) & fatfs->fs_info;
257
0
    TSK_DADDR_T sect, offs;
258
0
    int cidx;
259
260
    /* Sanity Check */
261
0
    if (clust > fatfs->lastclust) {
262
        /* silently ignore requests for the unclustered sectors... */
263
0
        if ((clust == fatfs->lastclust + 1) &&
264
0
            ((fatfs->firstclustsect + fatfs->csize * fatfs->clustcnt -
265
0
                    1) != fs->last_block)) {
266
0
            if (tsk_verbose)
267
0
                tsk_fprintf(stderr,
268
0
                    "fatfs_getFAT: Ignoring request for non-clustered sector\n");
269
0
            return 0;
270
0
        }
271
272
0
        tsk_error_reset();
273
0
        tsk_error_set_errno(TSK_ERR_FS_ARG);
274
0
        tsk_error_set_errstr("fatfs_getFAT: invalid cluster address: %"
275
0
            PRIuDADDR, clust);
276
0
        return 1;
277
0
    }
278
279
0
    switch (fatfs->fs_info.ftype) {
280
0
    case TSK_FS_TYPE_FAT12:
281
0
        if (clust & 0xf000) {
282
0
            tsk_error_reset();
283
0
            tsk_error_set_errno(TSK_ERR_FS_ARG);
284
0
            tsk_error_set_errstr
285
0
                ("fatfs_getFAT: TSK_FS_TYPE_FAT12 Cluster %" PRIuDADDR
286
0
                " too large", clust);
287
0
            return 1;
288
0
        }
289
290
        /* id the sector in the FAT */
291
0
        sect = fatfs->firstfatsect +
292
0
            ((clust + (clust >> 1)) >> fatfs->ssize_sh);
293
294
0
        tsk_take_lock(&fatfs->cache_lock);
295
296
        /* Load the FAT if we don't have it */
297
        // see if it is in the cache
298
0
        if (-1 == (cidx = getFATCacheIdx(fatfs, sect))) {
299
0
            tsk_release_lock(&fatfs->cache_lock);
300
0
            return 1;
301
0
        }
302
303
        /* get the offset into the cache */
304
0
        offs = ((sect - fatfs->fatc_addr[cidx]) << fatfs->ssize_sh) +
305
0
            (clust + (clust >> 1)) % fatfs->ssize;
306
307
        /* special case when the 12-bit value goes across the cache
308
         * we load the cache to start at this sect.  The cache
309
         * size must therefore be at least 2 sectors large
310
         */
311
0
        if (offs == (FATFS_FAT_CACHE_B - 1)) {
312
0
            ssize_t cnt;
313
314
            // read the data -- TTLs will already have been updated
315
0
            cnt =
316
0
                tsk_fs_read(fs, sect * fs->block_size,
317
0
                fatfs->fatc_buf[cidx], FATFS_FAT_CACHE_B);
318
0
            if (cnt != FATFS_FAT_CACHE_B) {
319
0
                tsk_release_lock(&fatfs->cache_lock);
320
0
                if (cnt >= 0) {
321
0
                    tsk_error_reset();
322
0
                    tsk_error_set_errno(TSK_ERR_FS_READ);
323
0
                }
324
0
                tsk_error_set_errstr2
325
0
                    ("fatfs_getFAT: TSK_FS_TYPE_FAT12 FAT overlap: %"
326
0
                    PRIuDADDR, sect);
327
0
                return 1;
328
0
            }
329
0
            fatfs->fatc_addr[cidx] = sect;
330
331
0
            offs = (clust + (clust >> 1)) % fatfs->ssize;
332
0
        }
333
334
        /* get pointer to entry in current buffer */
335
0
        a_ptr = (uint8_t *) fatfs->fatc_buf[cidx] + offs;
336
337
0
        tmp16 = tsk_getu16(fs->endian, a_ptr);
338
339
0
        tsk_release_lock(&fatfs->cache_lock);
340
341
        /* slide it over if it is one of the odd clusters */
342
0
        if (clust & 1)
343
0
            tmp16 >>= 4;
344
345
0
        *value = tmp16 & FATFS_12_MASK;
346
347
        /* sanity check */
348
0
        if ((*value > (fatfs->lastclust)) &&
349
0
            (*value < (0x0ffffff7 & FATFS_12_MASK))) {
350
0
            if (tsk_verbose)
351
0
                tsk_fprintf(stderr,
352
0
                    "fatfs_getFAT: TSK_FS_TYPE_FAT12 cluster (%" PRIuDADDR
353
0
                    ") too large (%" PRIuDADDR ") - resetting\n", clust,
354
0
                    *value);
355
0
            *value = 0;
356
0
        }
357
0
        return 0;
358
359
0
    case TSK_FS_TYPE_FAT16:
360
        /* Get sector in FAT for cluster and load it if needed */
361
0
        sect = fatfs->firstfatsect + ((clust << 1) >> fatfs->ssize_sh);
362
363
0
        tsk_take_lock(&fatfs->cache_lock);
364
365
0
        if (-1 == (cidx = getFATCacheIdx(fatfs, sect))) {
366
0
            tsk_release_lock(&fatfs->cache_lock);
367
0
            return 1;
368
0
        }
369
370
371
        /* get pointer to entry in the cache buffer */
372
0
        a_ptr = (uint8_t *) fatfs->fatc_buf[cidx] +
373
0
            ((sect - fatfs->fatc_addr[cidx]) << fatfs->ssize_sh) +
374
0
            ((clust << 1) % fatfs->ssize);
375
376
0
        *value = tsk_getu16(fs->endian, a_ptr) & FATFS_16_MASK;
377
378
0
        tsk_release_lock(&fatfs->cache_lock);
379
380
        /* sanity check */
381
0
        if ((*value > (fatfs->lastclust)) &&
382
0
            (*value < (0x0ffffff7 & FATFS_16_MASK))) {
383
0
            if (tsk_verbose)
384
0
                tsk_fprintf(stderr,
385
0
                    "fatfs_getFAT: contents of TSK_FS_TYPE_FAT16 entry %"
386
0
                    PRIuDADDR " too large - resetting\n", clust);
387
0
            *value = 0;
388
0
        }
389
0
        return 0;
390
391
0
    case TSK_FS_TYPE_FAT32:
392
0
    case TSK_FS_TYPE_EXFAT:
393
        /* Get sector in FAT for cluster and load if needed */
394
0
        sect = fatfs->firstfatsect + ((clust << 2) >> fatfs->ssize_sh);
395
396
0
        tsk_take_lock(&fatfs->cache_lock);
397
398
0
        if (-1 == (cidx = getFATCacheIdx(fatfs, sect))) {
399
0
            tsk_release_lock(&fatfs->cache_lock);
400
0
            return 1;
401
0
        }
402
403
        /* get pointer to entry in current buffer */
404
0
        a_ptr = (uint8_t *) fatfs->fatc_buf[cidx] +
405
0
            ((sect - fatfs->fatc_addr[cidx]) << fatfs->ssize_sh) +
406
0
            (clust << 2) % fatfs->ssize;
407
408
0
        *value = tsk_getu32(fs->endian, a_ptr) & FATFS_32_MASK;
409
410
0
        tsk_release_lock(&fatfs->cache_lock);
411
412
        /* sanity check */
413
0
        if ((*value > fatfs->lastclust) &&
414
0
            (*value < (0x0ffffff7 & FATFS_32_MASK))) {
415
0
            if (tsk_verbose)
416
0
                tsk_fprintf(stderr,
417
0
                    "fatfs_getFAT: contents of entry %" PRIuDADDR
418
0
                    " too large - resetting\n", clust);
419
420
0
            *value = 0;
421
0
        }
422
0
        return 0;
423
424
0
    default:
425
0
        tsk_error_reset();
426
0
        tsk_error_set_errno(TSK_ERR_FS_ARG);
427
0
        tsk_error_set_errstr("fatfs_getFAT: Unknown FAT type: %d",
428
0
            fatfs->fs_info.ftype);
429
0
        return 1;
430
0
    }
431
0
}
432
433
/**************************************************************************
434
 *
435
 * BLOCK WALKING
436
 *
437
 *************************************************************************/
438
/*
439
** Walk the sectors of the partition.
440
**
441
** NOTE: This is by SECTORS and not CLUSTERS
442
** _flags: TSK_FS_BLOCK_FLAG_ALLOC, TSK_FS_BLOCK_FLAG_UNALLOC, TSK_FS_BLOCK_FLAG_META
443
**  TSK_FS_BLOCK_FLAG_CONT
444
**
445
*/
446
uint8_t
447
fatfs_block_walk(TSK_FS_INFO * fs, TSK_DADDR_T a_start_blk,
448
    TSK_DADDR_T a_end_blk, TSK_FS_BLOCK_WALK_FLAG_ENUM a_flags,
449
    TSK_FS_BLOCK_WALK_CB a_action, void *a_ptr)
450
0
{
451
0
    const char *myname = "fatfs_block_walk";
452
0
    FATFS_INFO *fatfs = (FATFS_INFO *) fs;
453
0
    char *data_buf = NULL;
454
0
    ssize_t cnt;
455
0
    TSK_FS_BLOCK *fs_block;
456
457
0
    TSK_DADDR_T addr;
458
0
    int myflags;
459
0
    unsigned int i;
460
461
    // clean up any error messages that are lying around
462
0
    tsk_error_reset();
463
464
    /*
465
     * Sanity checks.
466
     */
467
0
    if (a_start_blk < fs->first_block || a_start_blk > fs->last_block) {
468
0
        tsk_error_reset();
469
0
        tsk_error_set_errno(TSK_ERR_FS_WALK_RNG);
470
0
        tsk_error_set_errstr("%s: Start block: %" PRIuDADDR "", myname,
471
0
            a_start_blk);
472
0
        return 1;
473
0
    }
474
0
    if (a_end_blk < fs->first_block || a_end_blk > fs->last_block) {
475
0
        tsk_error_reset();
476
0
        tsk_error_set_errno(TSK_ERR_FS_WALK_RNG);
477
0
        tsk_error_set_errstr("%s: End block: %" PRIuDADDR "", myname,
478
0
            a_end_blk);
479
0
        return 1;
480
0
    }
481
482
0
    if (tsk_verbose)
483
0
        tsk_fprintf(stderr,
484
0
            "fatfs_block_walk: Block Walking %" PRIuDADDR " to %"
485
0
            PRIuDADDR "\n", a_start_blk, a_end_blk);
486
487
488
    /* Sanity check on a_flags -- make sure at least one ALLOC is set */
489
0
    if (((a_flags & TSK_FS_BLOCK_WALK_FLAG_ALLOC) == 0) &&
490
0
        ((a_flags & TSK_FS_BLOCK_WALK_FLAG_UNALLOC) == 0)) {
491
0
        a_flags = (TSK_FS_BLOCK_WALK_FLAG_ENUM)
492
0
            (a_flags | TSK_FS_BLOCK_WALK_FLAG_ALLOC |
493
0
            TSK_FS_BLOCK_WALK_FLAG_UNALLOC);
494
0
    }
495
0
    if (((a_flags & TSK_FS_BLOCK_WALK_FLAG_META) == 0) &&
496
0
        ((a_flags & TSK_FS_BLOCK_WALK_FLAG_CONT) == 0)) {
497
0
        a_flags = (TSK_FS_BLOCK_WALK_FLAG_ENUM)
498
0
            (a_flags | TSK_FS_BLOCK_WALK_FLAG_CONT | TSK_FS_BLOCK_WALK_FLAG_META);
499
0
    }
500
501
0
    if ((fs_block = tsk_fs_block_alloc(fs)) == NULL) {
502
0
        return 1;
503
0
    }
504
505
    /* cycle through the sectors.  We do the sectors before the first
506
     * cluster separate from the data area */
507
0
    addr = a_start_blk;
508
509
    /* Before the data area beings (FAT, root directory etc.) */
510
0
    if ((a_start_blk < fatfs->firstclustsect)
511
0
        && (a_flags & TSK_FS_BLOCK_WALK_FLAG_ALLOC)) {
512
513
0
        if (tsk_verbose)
514
0
            tsk_fprintf(stderr,
515
0
                "fatfs_block_walk: Walking non-data area (pre %"
516
0
                PRIuDADDR "\n)", fatfs->firstclustsect);
517
518
0
        if ((data_buf = (char *) tsk_malloc(fs->block_size * 8)) == NULL) {
519
0
            tsk_fs_block_free(fs_block);
520
0
            return 1;
521
0
        }
522
523
        /* Read 8 sectors at a time to be faster */
524
0
        for (; addr < fatfs->firstclustsect && addr <= a_end_blk;) {
525
526
0
            if ((a_flags & TSK_FS_BLOCK_WALK_FLAG_AONLY) == 0) {
527
0
                cnt =
528
0
                    tsk_fs_read_block(fs, addr, data_buf,
529
0
                    fs->block_size * 8);
530
0
                if (cnt != fs->block_size * 8) {
531
0
                    if (cnt >= 0) {
532
0
                        tsk_error_reset();
533
0
                        tsk_error_set_errno(TSK_ERR_FS_READ);
534
0
                    }
535
0
                    tsk_error_set_errstr2
536
0
                        ("fatfs_block_walk: pre-data area block: %"
537
0
                        PRIuDADDR, addr);
538
0
                    free(data_buf);
539
0
                    tsk_fs_block_free(fs_block);
540
0
                    return 1;
541
0
                }
542
0
            }
543
544
            /* Process the sectors until we get to the clusters,
545
             * end of target, or end of buffer */
546
0
            for (i = 0;
547
0
                i < 8 && (addr) <= a_end_blk
548
0
                && (addr) < fatfs->firstclustsect; i++, addr++) {
549
0
                int retval;
550
551
0
                myflags = TSK_FS_BLOCK_FLAG_ALLOC;
552
553
                /* stuff before the first data sector is the
554
                 * FAT and boot sector */
555
0
                if (addr < fatfs->firstdatasect)
556
0
                    myflags |= TSK_FS_BLOCK_FLAG_META;
557
                /* This must be the root directory for FAT12/16 */
558
0
                else
559
0
                    myflags |= TSK_FS_BLOCK_FLAG_CONT;
560
561
                // test this sector (we already tested ALLOC)
562
0
                if ((myflags & TSK_FS_BLOCK_FLAG_META)
563
0
                    && (!(a_flags & TSK_FS_BLOCK_WALK_FLAG_META)))
564
0
                    continue;
565
0
                else if ((myflags & TSK_FS_BLOCK_FLAG_CONT)
566
0
                    && (!(a_flags & TSK_FS_BLOCK_WALK_FLAG_CONT)))
567
0
                    continue;
568
569
0
                if (a_flags & TSK_FS_BLOCK_WALK_FLAG_AONLY)
570
0
                    myflags |= TSK_FS_BLOCK_FLAG_AONLY;
571
572
0
                tsk_fs_block_set(fs, fs_block, addr,
573
0
                    (TSK_FS_BLOCK_FLAG_ENUM) (myflags | TSK_FS_BLOCK_FLAG_RAW),
574
0
                    &data_buf[i * fs->block_size]);
575
576
0
                retval = a_action(fs_block, a_ptr);
577
0
                if (retval == TSK_WALK_STOP) {
578
0
                    free(data_buf);
579
0
                    tsk_fs_block_free(fs_block);
580
0
                    return 0;
581
0
                }
582
0
                else if (retval == TSK_WALK_ERROR) {
583
0
                    free(data_buf);
584
0
                    tsk_fs_block_free(fs_block);
585
0
                    return 1;
586
0
                }
587
0
            }
588
0
        }
589
590
0
        free(data_buf);
591
592
        /* Was that it? */
593
0
        if (addr >= a_end_blk) {
594
0
            tsk_fs_block_free(fs_block);
595
0
            return 0;
596
0
        }
597
0
    }
598
    /* Reset the first sector to the start of the data area if we did
599
     * not examine it - the next calculation will screw up otherwise */
600
0
    else if (addr < fatfs->firstclustsect) {
601
0
        addr = fatfs->firstclustsect;
602
0
    }
603
604
605
    /* Now we read in the clusters in cluster-sized chunks,
606
     * sectors are too small
607
     */
608
609
    /* Determine the base sector of the cluster where the first
610
     * sector is located */
611
0
    addr = FATFS_CLUST_2_SECT(fatfs, (FATFS_SECT_2_CLUST(fatfs, addr)));
612
613
0
    if ((data_buf = (char*) tsk_malloc(fs->block_size * fatfs->csize)) == NULL) {
614
0
        tsk_fs_block_free(fs_block);
615
0
        return 1;
616
0
    }
617
618
0
    if (tsk_verbose)
619
0
        tsk_fprintf(stderr,
620
0
            "fatfs_block_walk: Walking data area blocks (%" PRIuDADDR
621
0
            " to %" PRIuDADDR ")\n", addr, a_end_blk);
622
623
0
    for (; addr <= a_end_blk; addr += fatfs->csize) {
624
0
        int retval;
625
0
        size_t read_size;
626
627
        /* Identify its allocation status */
628
0
        retval = fatfs_is_sectalloc(fatfs, addr);
629
0
        if (retval == -1) {
630
0
            free(data_buf);
631
0
            tsk_fs_block_free(fs_block);
632
0
            return 1;
633
0
        }
634
0
        else if (retval == 1) {
635
0
            myflags = TSK_FS_BLOCK_FLAG_ALLOC;
636
0
        }
637
0
        else {
638
0
            myflags = TSK_FS_BLOCK_FLAG_UNALLOC;
639
0
        }
640
641
        /* At this point, there should be no more meta - just content */
642
0
        myflags |= TSK_FS_BLOCK_FLAG_CONT;
643
644
        // test if we should call the callback with this one
645
0
        if ((myflags & TSK_FS_BLOCK_FLAG_CONT)
646
0
            && (!(a_flags & TSK_FS_BLOCK_WALK_FLAG_CONT)))
647
0
            continue;
648
0
        else if ((myflags & TSK_FS_BLOCK_FLAG_ALLOC)
649
0
            && (!(a_flags & TSK_FS_BLOCK_WALK_FLAG_ALLOC)))
650
0
            continue;
651
0
        else if ((myflags & TSK_FS_BLOCK_FLAG_UNALLOC)
652
0
            && (!(a_flags & TSK_FS_BLOCK_WALK_FLAG_UNALLOC)))
653
0
            continue;
654
655
0
        if (a_flags & TSK_FS_BLOCK_WALK_FLAG_AONLY)
656
0
            myflags |= TSK_FS_BLOCK_FLAG_AONLY;
657
658
659
        /* The final cluster may not be full */
660
0
        if (a_end_blk - addr + 1 < fatfs->csize)
661
0
            read_size = (size_t) (a_end_blk - addr + 1);
662
0
        else
663
0
            read_size = fatfs->csize;
664
665
0
        if ((a_flags & TSK_FS_BLOCK_WALK_FLAG_AONLY) == 0) {
666
0
            cnt = tsk_fs_read_block
667
0
                (fs, addr, data_buf, fs->block_size * read_size);
668
0
            if (cnt != (ssize_t)(fs->block_size * read_size)) {
669
0
                if (cnt >= 0) {
670
0
                    tsk_error_reset();
671
0
                    tsk_error_set_errno(TSK_ERR_FS_READ);
672
0
                }
673
0
                tsk_error_set_errstr2("fatfs_block_walk: block: %"
674
0
                    PRIuDADDR, addr);
675
0
                free(data_buf);
676
0
                tsk_fs_block_free(fs_block);
677
0
                return 1;
678
0
            }
679
0
        }
680
681
        /* go through each sector in the cluster */
682
0
        for (i = 0; i < read_size; i++) {
683
0
            int retval;
684
685
0
            if (addr + i < a_start_blk)
686
0
                continue;
687
0
            else if (addr + i > a_end_blk)
688
0
                break;
689
690
0
            tsk_fs_block_set(fs, fs_block, addr + i,
691
0
                (TSK_FS_BLOCK_FLAG_ENUM) (myflags | TSK_FS_BLOCK_FLAG_RAW),
692
0
                &data_buf[i * fs->block_size]);
693
694
0
            retval = a_action(fs_block, a_ptr);
695
0
            if (retval == TSK_WALK_STOP) {
696
0
                free(data_buf);
697
0
                tsk_fs_block_free(fs_block);
698
0
                return 0;
699
0
            }
700
0
            else if (retval == TSK_WALK_ERROR) {
701
0
                free(data_buf);
702
0
                tsk_fs_block_free(fs_block);
703
0
                return 1;
704
0
            }
705
0
        }
706
0
    }
707
708
0
    free(data_buf);
709
0
    tsk_fs_block_free(fs_block);
710
0
    return 0;
711
0
}
712
713
TSK_FS_BLOCK_FLAG_ENUM
714
fatfs_block_getflags(TSK_FS_INFO * a_fs, TSK_DADDR_T a_addr)
715
0
{
716
0
    FATFS_INFO *fatfs = (FATFS_INFO *) a_fs;
717
0
    int flags = 0;
718
719
    // FATs and boot sector
720
0
    if (a_addr < fatfs->firstdatasect) {
721
0
        flags = TSK_FS_BLOCK_FLAG_META | TSK_FS_BLOCK_FLAG_ALLOC;
722
0
    }
723
    // root directory for FAT12/16
724
0
    else if (a_addr < fatfs->firstclustsect) {
725
0
        flags = TSK_FS_BLOCK_FLAG_CONT | TSK_FS_BLOCK_FLAG_ALLOC;
726
0
    }
727
0
    else {
728
0
        int retval;
729
0
        flags = TSK_FS_BLOCK_FLAG_CONT;
730
731
        /* Identify its allocation status */
732
0
        retval = fatfs_is_sectalloc(fatfs, a_addr);
733
0
        if (retval != -1) {
734
0
            if (retval == 1)
735
0
                flags |= TSK_FS_BLOCK_FLAG_ALLOC;
736
0
            else
737
0
                flags |= TSK_FS_BLOCK_FLAG_UNALLOC;
738
0
        }
739
0
    }
740
0
    return (TSK_FS_BLOCK_FLAG_ENUM)flags;
741
0
}
742
743
/*
744
 * Identifies if a sector is allocated
745
 *
746
 * If it is less than the data area, then it is allocated
747
 * else the FAT table is consulted
748
 *
749
 * Return 1 if allocated, 0 if unallocated, and -1 if error
750
 */
751
int8_t
752
fatfs_is_sectalloc(FATFS_INFO * fatfs, TSK_DADDR_T sect)
753
0
{
754
0
    TSK_FS_INFO *fs = (TSK_FS_INFO *) fatfs;
755
    /* If less than the first cluster sector, then it is allocated
756
     * otherwise check the FAT
757
     */
758
0
    if (sect < fatfs->firstclustsect)
759
0
        return 1;
760
761
    /* If we are in the unused area, then we are "unalloc" */
762
0
    if ((sect <= fs->last_block) &&
763
0
        (sect >= (fatfs->firstclustsect + fatfs->csize * fatfs->clustcnt)))
764
0
        return 0;
765
766
0
    return fatfs->is_cluster_alloc(fatfs, FATFS_SECT_2_CLUST(fatfs, sect));
767
0
}
768
769
/* return 1 on error and 0 on success */
770
uint8_t
771
fatfs_jopen(
772
  [[maybe_unused]] TSK_FS_INFO * fs,
773
  [[maybe_unused]] TSK_INUM_T inum)
774
0
{
775
0
    tsk_error_reset();
776
0
    tsk_error_set_errno(TSK_ERR_FS_UNSUPFUNC);
777
0
    tsk_error_set_errstr("FAT does not have a journal\n");
778
0
    return 1;
779
0
}
780
781
/* return 1 on error and 0 on success */
782
uint8_t
783
fatfs_fscheck(
784
  [[maybe_unused]] TSK_FS_INFO * fs,
785
  [[maybe_unused]] FILE * hFile)
786
0
{
787
0
    tsk_error_reset();
788
0
    tsk_error_set_errno(TSK_ERR_FS_UNSUPFUNC);
789
0
    tsk_error_set_errstr("fscheck not implemented for FAT yet");
790
0
    return 1;
791
792
    /* Check that allocated dentries point to start of allocated cluster chain */
793
794
795
    /* Size of file is consistent with cluster chain length */
796
797
798
    /* Allocated cluster chains have a corresponding alloc dentry */
799
800
801
    /* Non file dentries have no clusters */
802
803
804
    /* Only one volume label */
805
806
807
    /* Dump Bad Sector Addresses */
808
809
810
    /* Dump unused sector addresses
811
     * Reserved area, end of FAT, end of Data Area */
812
0
}
813
814
/* return 1 on error and 0 on success */
815
uint8_t
816
fatfs_jentry_walk(
817
  [[maybe_unused]] TSK_FS_INFO * fs,
818
  [[maybe_unused]] int a_flags,
819
  [[maybe_unused]] TSK_FS_JENTRY_WALK_CB a_action,
820
  [[maybe_unused]] void *a_ptr)
821
0
{
822
0
    tsk_error_reset();
823
0
    tsk_error_set_errno(TSK_ERR_FS_UNSUPFUNC);
824
0
    tsk_error_set_errstr("FAT does not have a journal\n");
825
0
    return 1;
826
0
}
827
828
/* return 1 on error and 0 on success */
829
uint8_t
830
fatfs_jblk_walk(
831
  [[maybe_unused]] TSK_FS_INFO * fs,
832
  [[maybe_unused]] TSK_DADDR_T start,
833
  [[maybe_unused]] TSK_DADDR_T end,
834
  [[maybe_unused]] int a_flags,
835
  [[maybe_unused]] TSK_FS_JBLK_WALK_CB a_action,
836
  [[maybe_unused]] void *a_ptr)
837
0
{
838
0
    tsk_error_reset();
839
0
    tsk_error_set_errno(TSK_ERR_FS_UNSUPFUNC);
840
0
    tsk_error_set_errstr("FAT does not have a journal\n");
841
0
    return 1;
842
0
}
843
844
/* fatfs_close - close an fatfs file system */
845
void
846
fatfs_close(TSK_FS_INFO *fs)
847
0
{
848
0
    FATFS_INFO *fatfs = (FATFS_INFO *) fs;
849
850
0
    fatfs_dir_buf_free(fatfs);
851
852
0
    fs->tag = 0;
853
0
  memset(fatfs->boot_sector_buffer, 0, FATFS_MASTER_BOOT_RECORD_SIZE);
854
0
    tsk_deinit_lock(&fatfs->cache_lock);
855
0
    tsk_deinit_lock(&fatfs->dir_lock);
856
  
857
0
    tsk_fs_free(fs);
858
0
}
859