Coverage Report

Created: 2025-07-23 06:45

/src/sleuthkit/tsk/fs/fatxxfs_meta.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
** fatxxfs
3
** The Sleuth Kit
4
**
5
** Content and meta data layer support for the FATXX 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 fatxxfs.c
23
 * Contains the internal TSK FATXX (FAT12, FAT16, FAT32) file system code to
24
 * handle basic file system processing for opening file system, processing
25
 * sectors, and directory entries.
26
 */
27
28
#include "tsk_fatxxfs.h"
29
#include <assert.h>
30
31
/*
32
 * Identify if the dentry is a valid 8.3 name
33
 *
34
 * returns 1 if it is, 0 if it does not
35
 */
36
static uint8_t
37
is_83_name(FATXXFS_DENTRY * de)
38
35.4k
{
39
35.4k
    if (!de)
40
0
        return 0;
41
42
    /* The IS_NAME macro will fail if the value is 0x05, which is only
43
     * valid in name[0], similarly with '.' */
44
35.4k
    if ((de->name[0] != FATXXFS_SLOT_E5) && (de->name[0] != '.') &&
45
35.4k
        (FATXXFS_IS_83_NAME(de->name[0]) == 0)) {
46
27.1k
        if (tsk_verbose)
47
0
            fprintf(stderr, "fatfs_is_83_name: name[0] is invalid\n");
48
27.1k
        return 0;
49
27.1k
    }
50
51
    // the name cannot start with 0x20
52
8.31k
    else if (de->name[0] == 0x20) {
53
1
        if (tsk_verbose)
54
0
            fprintf(stderr, "fatfs_is_83_name: name[0] has 0x20\n");
55
1
        return 0;
56
1
    }
57
58
    /* the second name field can only be . if the first one is a . */
59
8.31k
    if (de->name[1] == '.') {
60
2
        if (de->name[0] != '.') {
61
2
            if (tsk_verbose)
62
0
                fprintf(stderr, "fatfs_is_83_name: name[1] is .\n");
63
2
            return 0;
64
2
        }
65
2
    }
66
8.31k
    else if (FATXXFS_IS_83_NAME(de->name[1]) == 0) {
67
957
        if (tsk_verbose)
68
0
            fprintf(stderr, "fatfs_is_83_name: name[1] is invalid\n");
69
957
        return 0;
70
957
    }
71
72
7.35k
    if (FATXXFS_IS_83_NAME(de->name[2]) == 0) {
73
2.29k
        if (tsk_verbose)
74
0
            fprintf(stderr, "fatfs_is_83_name: name[2] is invalid\n");
75
2.29k
        return 0;
76
2.29k
    }
77
5.06k
    else if (FATXXFS_IS_83_NAME(de->name[3]) == 0) {
78
2.46k
        if (tsk_verbose)
79
0
            fprintf(stderr, "fatfs_is_83_name: name[3] is invalid\n");
80
2.46k
        return 0;
81
2.46k
    }
82
2.59k
    else if (FATXXFS_IS_83_NAME(de->name[4]) == 0) {
83
2.46k
        if (tsk_verbose)
84
0
            fprintf(stderr, "fatfs_is_83_name: name[4] is invalid\n");
85
2.46k
        return 0;
86
2.46k
    }
87
129
    else if (FATXXFS_IS_83_NAME(de->name[5]) == 0) {
88
31
        if (tsk_verbose)
89
0
            fprintf(stderr, "fatfs_is_83_name: name[5] is invalid\n");
90
31
        return 0;
91
31
    }
92
98
    else if (FATXXFS_IS_83_NAME(de->name[6]) == 0) {
93
25
        if (tsk_verbose)
94
0
            fprintf(stderr, "fatfs_is_83_name: name[6] is invalid\n");
95
25
        return 0;
96
25
    }
97
73
    else if (FATXXFS_IS_83_NAME(de->name[7]) == 0) {
98
17
        if (tsk_verbose)
99
0
            fprintf(stderr, "fatfs_is_83_name: name[7] is invalid\n");
100
17
        return 0;
101
17
    }
102
56
    else if (FATXXFS_IS_83_NAME(de->ext[0]) == 0) {
103
15
        if (tsk_verbose)
104
0
            fprintf(stderr, "fatfs_is_83_name: ext[0] is invalid\n");
105
15
        return 0;
106
15
    }
107
41
    else if (FATXXFS_IS_83_NAME(de->ext[1]) == 0) {
108
18
        if (tsk_verbose)
109
0
            fprintf(stderr, "fatfs_is_83_name: ext[1] is invalid\n");
110
18
        return 0;
111
18
    }
112
23
    else if (FATXXFS_IS_83_NAME(de->ext[2]) == 0) {
113
19
        if (tsk_verbose)
114
0
            fprintf(stderr, "fatfs_is_83_name: ext[2] is invalid\n");
115
19
        return 0;
116
19
    }
117
118
    /* Ensure that if we get a "space", that the rest of the
119
     * name is spaces.  This is not in the spec, but is how
120
     * windows operates and serves as a good check to remove
121
     * false positives.  We do not do this check for the
122
     * volume label though. */
123
4
    if ((de->attrib & FATFS_ATTR_VOLUME) != FATFS_ATTR_VOLUME) {
124
3
        if (((de->name[1] == 0x20) && (de->name[2] != 0x20)) ||
125
3
            ((de->name[2] == 0x20) && (de->name[3] != 0x20)) ||
126
3
            ((de->name[3] == 0x20) && (de->name[4] != 0x20)) ||
127
3
            ((de->name[4] == 0x20) && (de->name[5] != 0x20)) ||
128
3
            ((de->name[5] == 0x20) && (de->name[6] != 0x20)) ||
129
3
            ((de->name[6] == 0x20) && (de->name[7] != 0x20)) ||
130
3
            ((de->ext[1] == 0x20) && (de->ext[2] != 0x20))) {
131
0
            if (tsk_verbose)
132
0
                fprintf(stderr,
133
0
                    "fatfs_is_83_name: space before non-space\n");
134
0
            return 0;
135
0
        }
136
3
    }
137
138
4
    return 1;
139
4
}
140
141
/**
142
 * \internal
143
 * Determine whether a buffer likely contains a directory entry.
144
 * For the most reliable results, request the in-depth test.
145
 *
146
 * @param [in] a_fatfs Source file system for the directory entry.
147
 * @param [in] a_dentry Buffer that may contain a directory entry.
148
 * @param [in] a_cluster_is_alloc The allocation status, possibly unknown, of the
149
 * cluster from which the buffer was filled.
150
 * @param [in] a_do_basic_tests_only Whether to do basic or in-depth testing.
151
 * @return 1 if the buffer likely contains a directory entry, 0 otherwise
152
 */
153
uint8_t
154
fatxxfs_is_dentry(
155
  FATFS_INFO *a_fatfs,
156
  FATFS_DENTRY *a_dentry,
157
  [[maybe_unused]] FATFS_DATA_UNIT_ALLOC_STATUS_ENUM a_cluster_is_alloc,
158
  uint8_t a_do_basic_tests_only)
159
1.88M
{
160
1.88M
    const char *func_name = "fatxxfs_is_dentry";
161
1.88M
    TSK_FS_INFO *fs = (TSK_FS_INFO *) & a_fatfs->fs_info;
162
1.88M
    FATXXFS_DENTRY *dentry = (FATXXFS_DENTRY*)a_dentry;
163
164
1.88M
    if (!a_dentry)
165
0
        return 0;
166
167
    /* LFN have their own checks, which are pretty weak since most
168
     * fields are UTF16 */
169
1.88M
    if ((dentry->attrib & FATFS_ATTR_LFN) == FATFS_ATTR_LFN) {
170
17.8k
        FATXXFS_DENTRY_LFN *de_lfn = (FATXXFS_DENTRY_LFN*) dentry;
171
172
17.8k
        if ((de_lfn->seq > (FATXXFS_LFN_SEQ_FIRST | 0x0f))
173
17.8k
            && (de_lfn->seq != FATXXFS_SLOT_DELETED)) {
174
5.98k
            if (tsk_verbose)
175
0
                fprintf(stderr, "%s: LFN seq\n", func_name);
176
5.98k
            return 0;
177
5.98k
        }
178
179
11.9k
        return 1;
180
17.8k
    }
181
1.86M
    else {
182
        // the basic test is only for the 'essential data'.
183
1.86M
        if (a_do_basic_tests_only == 0) {
184
302k
            if (dentry->ntbyte & ~(FATXXFS_CASE_LOWER_ALL)) {
185
79.4k
                if (tsk_verbose)
186
0
                    fprintf(stderr, "%s: lower case all\n", func_name);
187
79.4k
                return 0;
188
79.4k
            }
189
223k
            else if (dentry->attrib & ~(FATFS_ATTR_ALL)) {
190
1.95k
                if (tsk_verbose)
191
0
                    fprintf(stderr, "%s: attribute all\n", func_name);
192
1.95k
                return 0;
193
1.95k
            }
194
195
            // verify we do not have too many flags set
196
221k
            if (dentry->attrib & FATFS_ATTR_VOLUME) {
197
9.10k
                if ((dentry->attrib & FATFS_ATTR_DIRECTORY) ||
198
9.10k
                    (dentry->attrib & FATFS_ATTR_READONLY) ||
199
9.10k
                    (dentry->attrib & FATFS_ATTR_ARCHIVE)) {
200
8.72k
                    if (tsk_verbose)
201
0
                        fprintf(stderr,
202
0
                            "%s: Vol and Dir/RO/Arch\n", func_name);
203
8.72k
                    return 0;
204
8.72k
                }
205
9.10k
            }
206
207
            /* The ctime, cdate, and adate fields are optional and
208
             * therefore 0 is a valid value
209
             * We have had scenarios where ISDATE and ISTIME return true,
210
             * but the unix2dos fail during the conversion.  This has been
211
             * useful to detect corrupt entries, so we do both.
212
             */
213
212k
            if ((tsk_getu16(fs->endian, dentry->ctime) != 0) &&
214
212k
                (FATFS_ISTIME(tsk_getu16(fs->endian, dentry->ctime)) == 0)) {
215
1.90k
                if (tsk_verbose)
216
0
                    fprintf(stderr, "%s: ctime\n", func_name);
217
1.90k
                return 0;
218
1.90k
            }
219
210k
            else if ((tsk_getu16(fs->endian, dentry->wtime) != 0) &&
220
210k
                (FATFS_ISTIME(tsk_getu16(fs->endian, dentry->wtime)) == 0)) {
221
2.47k
                if (tsk_verbose)
222
0
                    fprintf(stderr, "%s: wtime\n", func_name);
223
2.47k
                return 0;
224
2.47k
            }
225
208k
            else if ((tsk_getu16(fs->endian, dentry->cdate) != 0) &&
226
208k
                ((FATFS_ISDATE(tsk_getu16(fs->endian, dentry->cdate)) == 0) ||
227
61.2k
                    (fatfs_dos_2_unix_time(tsk_getu16(fs->endian, dentry->cdate),
228
34.4k
                            tsk_getu16(fs->endian, dentry->ctime),
229
34.4k
                            dentry->ctimeten) == 0))) {
230
27.3k
                if (tsk_verbose)
231
0
                    fprintf(stderr, "%s: cdate\n", func_name);
232
27.3k
                return 0;
233
27.3k
            }
234
180k
            else if (dentry->ctimeten > 200) {
235
157
                if (tsk_verbose)
236
0
                    fprintf(stderr, "%s: ctimeten\n", func_name);
237
157
                return 0;
238
157
            }
239
180k
            else if ((tsk_getu16(fs->endian, dentry->adate) != 0) &&
240
180k
                ((FATFS_ISDATE(tsk_getu16(fs->endian, dentry->adate)) == 0) ||
241
42.3k
                    (fatfs_dos_2_unix_time(tsk_getu16(fs->endian, dentry->adate),
242
22.4k
                            0, 0) == 0))) {
243
20.0k
                if (tsk_verbose)
244
0
                    fprintf(stderr, "%s: adate\n", func_name);
245
20.0k
                return 0;
246
20.0k
            }
247
160k
            else if ((tsk_getu16(fs->endian, dentry->wdate) != 0) &&
248
160k
                ((FATFS_ISDATE(tsk_getu16(fs->endian, dentry->wdate)) == 0) ||
249
46.7k
                    (fatfs_dos_2_unix_time(tsk_getu16(fs->endian, dentry->wdate),
250
25.6k
                            tsk_getu16(fs->endian, dentry->wtime), 0) == 0))) {
251
25.6k
                if (tsk_verbose)
252
0
                    fprintf(stderr, "%s: wdate\n", func_name);
253
25.6k
                return 0;
254
25.6k
            }
255
212k
        }
256
257
        /* verify the starting cluster is small enough */
258
1.69M
        if ((FATXXFS_DENTRY_CLUST(fs, dentry) > (a_fatfs->lastclust)) &&
259
1.69M
            (FATFS_ISEOF(FATXXFS_DENTRY_CLUST(fs, dentry), a_fatfs->mask) == 0)) {
260
248k
            if (tsk_verbose)
261
0
                fprintf(stderr, "%s: start cluster\n", func_name);
262
248k
            return 0;
263
248k
        }
264
265
        /* Verify the file size is smaller than the data area */
266
1.44M
        else if (tsk_getu32(fs->endian, dentry->size) >
267
1.44M
            ((a_fatfs->clustcnt * a_fatfs->csize) << a_fatfs->ssize_sh)) {
268
260k
            if (tsk_verbose)
269
0
                fprintf(stderr, "%s: size\n", func_name);
270
260k
            return 0;
271
260k
        }
272
273
1.18M
        else if ((tsk_getu32(fs->endian, dentry->size) > 0)
274
1.18M
            && (FATXXFS_DENTRY_CLUST(fs, dentry) == 0)) {
275
131k
            if (tsk_verbose)
276
0
                fprintf(stderr,
277
0
                    "%s: non-zero size and NULL starting cluster\n", func_name);
278
131k
            return 0;
279
131k
        }
280
    
281
1.05M
    else if((a_fatfs->subtype == TSK_FATFS_SUBTYPE_SPEC) && (is_83_name(dentry) == 0))
282
35.4k
      return 0;
283
284
        // basic sanity check on values
285
1.01M
        else if ((tsk_getu16(fs->endian, dentry->ctime) == 0)
286
1.01M
            && (tsk_getu16(fs->endian, dentry->wtime) == 0)
287
1.01M
            && (tsk_getu16(fs->endian, dentry->cdate) == 0)
288
1.01M
            && (tsk_getu16(fs->endian, dentry->adate) == 0)
289
1.01M
            && (tsk_getu16(fs->endian, dentry->wdate) == 0)
290
1.01M
            && (FATXXFS_DENTRY_CLUST(fs, dentry) == 0)
291
1.01M
            && (tsk_getu32(fs->endian, dentry->size) == 0)) {
292
20.0k
            if (tsk_verbose)
293
0
                fprintf(stderr,
294
0
                    "%s: nearly all values zero\n", func_name);
295
20.0k
            return 0;
296
20.0k
        }
297
298
999k
        return 1;
299
1.69M
    }
300
1.88M
}
301
302
/*
303
 * convert the attribute list in FAT to a UNIX mode
304
 */
305
static TSK_FS_META_TYPE_ENUM
306
attr2type(uint16_t attr)
307
489k
{
308
489k
    if (attr & FATFS_ATTR_DIRECTORY)
309
37.8k
        return TSK_FS_META_TYPE_DIR;
310
451k
    else
311
451k
        return TSK_FS_META_TYPE_REG;
312
489k
}
313
314
static int
315
attr2mode(uint16_t attr)
316
489k
{
317
489k
    int mode;
318
319
    /* every file is executable */
320
489k
    mode =
321
489k
        (TSK_FS_META_MODE_IXUSR | TSK_FS_META_MODE_IXGRP |
322
489k
        TSK_FS_META_MODE_IXOTH);
323
324
489k
    if ((attr & FATFS_ATTR_READONLY) == 0)
325
426k
        mode |=
326
426k
            (TSK_FS_META_MODE_IRUSR | TSK_FS_META_MODE_IRGRP |
327
426k
            TSK_FS_META_MODE_IROTH);
328
329
489k
    if ((attr & FATFS_ATTR_HIDDEN) == 0)
330
438k
        mode |=
331
438k
            (TSK_FS_META_MODE_IWUSR | TSK_FS_META_MODE_IWGRP |
332
438k
            TSK_FS_META_MODE_IWOTH);
333
334
489k
    return mode;
335
489k
}
336
337
TSK_RETVAL_ENUM
338
fatxxfs_dinode_copy(FATFS_INFO *a_fatfs, TSK_INUM_T a_inum,
339
    FATFS_DENTRY *a_dentry, uint8_t a_cluster_is_alloc, TSK_FS_FILE *a_fs_file)
340
489k
{
341
489k
    const char *func_name = "fatxxfs_dinode_copy";
342
489k
    int i;
343
489k
    TSK_FS_INFO *fs = (TSK_FS_INFO *) & a_fatfs->fs_info;
344
489k
    TSK_FS_META *fs_meta = a_fs_file->meta;
345
489k
    FATXXFS_DENTRY *dentry = (FATXXFS_DENTRY*)a_dentry;
346
489k
    TSK_DADDR_T *addr_ptr;
347
489k
    uint32_t flags = 0;
348
349
489k
    if (fs_meta->content_len < FATFS_FILE_CONTENT_LEN) {
350
0
        if ((fs_meta =
351
0
                tsk_fs_meta_realloc(fs_meta,
352
0
                    FATFS_FILE_CONTENT_LEN)) == NULL) {
353
0
            return TSK_ERR;
354
0
        }
355
0
    }
356
357
489k
    fs_meta->attr_state = TSK_FS_META_ATTR_EMPTY;
358
489k
    if (fs_meta->attr) {
359
40.6k
        tsk_fs_attrlist_markunused(fs_meta->attr);
360
40.6k
    }
361
362
489k
    fs_meta->mode = (TSK_FS_META_MODE_ENUM)attr2mode(dentry->attrib);
363
489k
    fs_meta->type = attr2type(dentry->attrib);
364
365
489k
    fs_meta->addr = a_inum;
366
367
489k
    if (a_cluster_is_alloc) {
368
462k
    if(FATXXFS_IS_DELETED(dentry->name, a_fatfs)){
369
292k
      flags = TSK_FS_META_FLAG_UNALLOC;
370
292k
    }
371
169k
    else{
372
169k
      flags = TSK_FS_META_FLAG_ALLOC;
373
169k
    }
374
462k
    }
375
27.3k
    else {
376
27.3k
        flags = TSK_FS_META_FLAG_UNALLOC;
377
27.3k
    }
378
379
489k
    flags |= (dentry->name[0] == FATXXFS_SLOT_EMPTY ?
380
355k
              TSK_FS_META_FLAG_UNUSED : TSK_FS_META_FLAG_USED);
381
382
489k
    fs_meta->flags = (TSK_FS_META_FLAG_ENUM)flags;
383
384
489k
    if ((dentry->attrib & FATFS_ATTR_LFN) == FATFS_ATTR_LFN) {
385
        /* LFN entries don't have these values */
386
0
        fs_meta->nlink = 0;
387
0
        fs_meta->size = 0;
388
0
        fs_meta->mtime = 0;
389
0
        fs_meta->atime = 0;
390
0
        fs_meta->ctime = 0;
391
0
        fs_meta->crtime = 0;
392
0
        fs_meta->mtime_nano = fs_meta->atime_nano = fs_meta->ctime_nano =
393
0
            fs_meta->crtime_nano = 0;
394
0
    }
395
489k
    else {
396
        /* There is no notion of link in FAT, just deleted or not */
397
489k
    if(FATXXFS_IS_DELETED(dentry->name, a_fatfs)){
398
311k
      fs_meta->nlink = 0;
399
311k
    }
400
177k
    else{
401
177k
      fs_meta->nlink = 1;
402
177k
    }
403
489k
        fs_meta->size = (TSK_OFF_T) tsk_getu32(fs->endian, dentry->size);
404
405
        /* If these are valid dates, then convert to a unix date format */
406
489k
        if (FATFS_ISDATE(tsk_getu16(fs->endian, dentry->wdate)))
407
58.3k
            fs_meta->mtime =
408
58.3k
                fatfs_dos_2_unix_time(tsk_getu16(fs->endian, dentry->wdate),
409
58.3k
                tsk_getu16(fs->endian, dentry->wtime), 0);
410
431k
        else
411
431k
            fs_meta->mtime = 0;
412
489k
        fs_meta->mtime_nano = 0;
413
414
489k
        if (FATFS_ISDATE(tsk_getu16(fs->endian, dentry->adate)))
415
105k
            fs_meta->atime =
416
105k
                fatfs_dos_2_unix_time(tsk_getu16(fs->endian, dentry->adate), 0, 0);
417
384k
        else
418
384k
            fs_meta->atime = 0;
419
489k
        fs_meta->atime_nano = 0;
420
421
422
        /* cdate is the creation date in FAT and there is no change,
423
         * so we just put in into change and set create to 0.  The other
424
         * front-end code knows how to handle it and display it
425
         */
426
489k
        if (FATFS_ISDATE(tsk_getu16(fs->endian, dentry->cdate))) {
427
94.9k
            fs_meta->crtime =
428
94.9k
                fatfs_dos_2_unix_time(tsk_getu16(fs->endian, dentry->cdate),
429
94.9k
                tsk_getu16(fs->endian, dentry->ctime), dentry->ctimeten);
430
94.9k
            fs_meta->crtime_nano = fatfs_dos_2_nanosec(dentry->ctimeten);
431
94.9k
        }
432
394k
        else {
433
394k
            fs_meta->crtime = 0;
434
394k
            fs_meta->crtime_nano = 0;
435
394k
        }
436
437
        // FAT does not have a changed time
438
489k
        fs_meta->ctime = 0;
439
489k
        fs_meta->ctime_nano = 0;
440
489k
    }
441
442
    /* Values that do not exist in FAT */
443
489k
    fs_meta->uid = 0;
444
489k
    fs_meta->gid = 0;
445
489k
    fs_meta->seq = 0;
446
447
448
    /* We will be copying a name, so allocate a structure */
449
489k
    if (fs_meta->name2 == NULL) {
450
448k
        if ((fs_meta->name2 = (TSK_FS_META_NAME_LIST *)
451
448k
                tsk_malloc(sizeof(TSK_FS_META_NAME_LIST))) == NULL)
452
0
            return TSK_ERR;
453
448k
        fs_meta->name2->next = NULL;
454
448k
    }
455
456
    /* If we have a LFN entry, then we need to convert the three
457
     * parts of the name to UTF-8 and copy it into the name structure .
458
     */
459
489k
    if ((dentry->attrib & FATFS_ATTR_LFN) == FATFS_ATTR_LFN) {
460
0
        FATXXFS_DENTRY_LFN *lfn = (FATXXFS_DENTRY_LFN *) dentry;
461
462
        /* Convert the first part of the name */
463
0
        UTF8 *name8 = (UTF8 *) fs_meta->name2->name;
464
0
        UTF16 *name16 = (UTF16 *) lfn->part1;
465
466
0
        int retVal = tsk_UTF16toUTF8(fs->endian, (const UTF16 **) &name16,
467
0
            (UTF16 *) & lfn->part1[10],
468
0
            &name8,
469
0
            (UTF8 *) ((uintptr_t) fs_meta->name2->name +
470
0
                sizeof(fs_meta->name2->name)),
471
0
            TSKlenientConversion);
472
473
0
        if (retVal != TSKconversionOK) {
474
0
            tsk_error_reset();
475
0
            tsk_error_set_errno(TSK_ERR_FS_UNICODE);
476
0
            tsk_error_set_errstr
477
0
                ("%s: Error converting FAT LFN (1) to UTF8: %d",
478
0
                func_name, retVal);
479
0
            *name8 = '\0';
480
481
0
            return TSK_COR;
482
0
        }
483
484
        /* Convert the second part of the name */
485
0
        name16 = (UTF16 *) lfn->part2;
486
0
        retVal = tsk_UTF16toUTF8(fs->endian, (const UTF16 **) &name16,
487
0
            (UTF16 *) & lfn->part2[12],
488
0
            &name8,
489
0
            (UTF8 *) ((uintptr_t) fs_meta->name2->name +
490
0
                sizeof(fs_meta->name2->name)), TSKlenientConversion);
491
492
0
        if (retVal != TSKconversionOK) {
493
0
            tsk_error_reset();
494
0
            tsk_error_set_errno(TSK_ERR_FS_UNICODE);
495
0
            tsk_error_set_errstr
496
0
                ("%s: Error converting FAT LFN (2) to UTF8: %d",
497
0
                func_name, retVal);
498
0
            *name8 = '\0';
499
500
0
            return TSK_COR;
501
0
        }
502
503
        /* Convert the third part of the name */
504
0
        name16 = (UTF16 *) lfn->part3;
505
0
        retVal = tsk_UTF16toUTF8(fs->endian, (const UTF16 **) &name16,
506
0
            (UTF16 *) & lfn->part3[4],
507
0
            &name8,
508
0
            (UTF8 *) ((uintptr_t) fs_meta->name2->name +
509
0
                sizeof(fs_meta->name2->name)), TSKlenientConversion);
510
511
0
        if (retVal != TSKconversionOK) {
512
0
            tsk_error_reset();
513
0
            tsk_error_set_errno(TSK_ERR_FS_UNICODE);
514
0
            tsk_error_set_errstr
515
0
                ("%s: Error converting FAT LFN (3) to UTF8: %d",
516
0
                func_name, retVal);
517
0
            *name8 = '\0';
518
519
0
            return TSK_COR;
520
0
        }
521
522
        /* Make sure it is NULL Terminated */
523
0
        if ((uintptr_t) name8 >
524
0
            (uintptr_t) fs_meta->name2->name +
525
0
            sizeof(fs_meta->name2->name))
526
0
            fs_meta->name2->name[sizeof(fs_meta->name2->name) - 1] = '\0';
527
0
        else
528
0
            *name8 = '\0';
529
0
    }
530
    /* If the entry is for a volume label, then copy the label.
531
     */
532
489k
    else if ((dentry->attrib & FATFS_ATTR_VOLUME) == FATFS_ATTR_VOLUME) {
533
50.4k
        int a;
534
535
50.4k
        i = 0;
536
454k
        for (a = 0; a < 8; a++) {
537
403k
            if ((dentry->name[a] != 0x00) && (dentry->name[a] != 0xff))
538
96.7k
                fs_meta->name2->name[i++] = dentry->name[a];
539
403k
        }
540
201k
        for (a = 0; a < 3; a++) {
541
151k
            if ((dentry->ext[a] != 0x00) && (dentry->ext[a] != 0xff))
542
40.1k
                fs_meta->name2->name[i++] = dentry->ext[a];
543
151k
        }
544
50.4k
        fs_meta->name2->name[i] = '\0';
545
546
        /* clean up non-ASCII because we are
547
         * copying it into a buffer that is supposed to be UTF-8 and
548
         * we don't know what encoding it is actually in or if it is
549
         * simply junk. */
550
50.4k
        fatfs_cleanup_ascii(fs_meta->name2->name);
551
50.4k
    }
552
    /* If the entry is a normal short entry, then copy the name
553
     * and add the '.' for the extension
554
     */
555
439k
    else {
556
755k
        for (i = 0; (i < 8) && (dentry->name[i] != 0) && (dentry->name[i] != ' ');
557
439k
            i++) {
558
315k
            if ((i == 0) && (dentry->name[0] == FATXXFS_SLOT_DELETED))
559
81
                fs_meta->name2->name[0] = '_';
560
315k
            else if ((dentry->ntbyte & FATXXFS_CASE_LOWER_BASE) &&
561
315k
                (dentry->name[i] >= 'A') && (dentry->name[i] <= 'Z'))
562
365
                fs_meta->name2->name[i] = dentry->name[i] + 32;
563
315k
            else
564
315k
                fs_meta->name2->name[i] = dentry->name[i];
565
315k
        }
566
567
439k
        if ((dentry->ext[0]) && (dentry->ext[0] != ' ')) {
568
84.3k
            int a;
569
84.3k
            fs_meta->name2->name[i++] = '.';
570
84.3k
            for (a = 0;
571
222k
                (a < 3) && (dentry->ext[a] != 0) && (dentry->ext[a] != ' ');
572
138k
                a++, i++) {
573
138k
                if ((dentry->ntbyte & FATXXFS_CASE_LOWER_EXT)
574
138k
                    && (dentry->ext[a] >= 'A') && (dentry->ext[a] <= 'Z'))
575
277
                    fs_meta->name2->name[i] = dentry->ext[a] + 32;
576
137k
                else
577
137k
                    fs_meta->name2->name[i] = dentry->ext[a];
578
138k
            }
579
84.3k
        }
580
439k
        fs_meta->name2->name[i] = '\0';
581
582
        /* clean up non-ASCII because we are
583
         * copying it into a buffer that is supposed to be UTF-8 and
584
         * we don't know what encoding it is actually in or if it is
585
         * simply junk. */
586
439k
        fatfs_cleanup_ascii(fs_meta->name2->name);
587
439k
    }
588
589
    /* Clean up name to remove control characters */
590
489k
    i = 0;
591
1.16M
    while (fs_meta->name2->name[i] != '\0') {
592
675k
        if (TSK_IS_CNTRL(fs_meta->name2->name[i]))
593
286k
            fs_meta->name2->name[i] = '^';
594
675k
        i++;
595
675k
    }
596
597
    /* get the starting cluster */
598
489k
    addr_ptr = (TSK_DADDR_T *) fs_meta->content_ptr;
599
489k
    if ((dentry->attrib & FATFS_ATTR_LFN) == FATFS_ATTR_LFN) {
600
0
        addr_ptr[0] = 0;
601
0
    }
602
489k
    else {
603
489k
        addr_ptr[0] = FATXXFS_DENTRY_CLUST(fs, dentry) & a_fatfs->mask;
604
489k
    }
605
606
    /* FAT does not store a size for its directories so make one based
607
     * on the number of allocated sectors
608
     */
609
489k
    if ((dentry->attrib & FATFS_ATTR_DIRECTORY) &&
610
489k
        ((dentry->attrib & FATFS_ATTR_LFN) != FATFS_ATTR_LFN)) {
611
37.8k
        if (fs_meta->flags & TSK_FS_META_FLAG_ALLOC) {
612
29.7k
            TSK_LIST *list_seen = NULL;
613
614
            /* count the total number of clusters in this file */
615
29.7k
            TSK_DADDR_T clust = FATXXFS_DENTRY_CLUST(fs, dentry);
616
29.7k
            int cnum = 0;
617
618
32.7k
            while ((clust) && (0 == FATFS_ISEOF(clust, a_fatfs->mask))) {
619
3.01k
                TSK_DADDR_T nxt;
620
621
                /* Make sure we do not get into an infinite loop */
622
3.01k
                if (tsk_list_find(list_seen, clust)) {
623
10
                    if (tsk_verbose)
624
0
                        tsk_fprintf(stderr,
625
0
                            "Loop found while determining directory size\n");
626
10
                    break;
627
10
                }
628
3.00k
                if (tsk_list_add(&list_seen, clust)) {
629
0
                    tsk_list_free(list_seen);
630
0
                    list_seen = NULL;
631
0
                    return TSK_ERR;
632
0
                }
633
634
3.00k
                cnum++;
635
636
3.00k
                if (fatfs_getFAT(a_fatfs, clust, &nxt))
637
60
                    break;
638
2.94k
                else
639
2.94k
                    clust = nxt;
640
3.00k
            }
641
642
29.7k
            tsk_list_free(list_seen);
643
29.7k
            list_seen = NULL;
644
645
29.7k
            fs_meta->size =
646
29.7k
                (TSK_OFF_T) ((cnum * a_fatfs->csize) << a_fatfs->ssize_sh);
647
29.7k
        }
648
        /* if the dir is unallocated, then assume 0 or cluster size
649
         * Ideally, we would have a smart algo here to do recovery
650
         * and look for dentries.  However, we do not have that right
651
         * now and if we do not add this special check then it can
652
         * assume that an allocated file cluster chain belongs to the
653
         * directory */
654
8.13k
        else {
655
            // if the first cluster is allocated, then set size to be 0
656
8.13k
            if (fatxxfs_is_cluster_alloc(a_fatfs, FATXXFS_DENTRY_CLUST(fs,
657
8.13k
                        dentry)) == 1)
658
4.06k
                fs_meta->size = 0;
659
4.06k
            else
660
4.06k
                fs_meta->size = a_fatfs->csize << a_fatfs->ssize_sh;
661
8.13k
        }
662
37.8k
    }
663
664
489k
    return TSK_OK;
665
489k
}
666
667
/**
668
 * \internal
669
 * Populate the TSK_FS_META object of a TSK_FS_FILE object for a
670
 * given inode address.
671
 *
672
 * @param [in] a_fs File system that contains the inode.
673
 * @param [out] a_fs_file The file corresponding to the inode.
674
 * @param [in] a_inum The inode address.
675
 * @returns 1 if an error occurs or if the inode address is not
676
 * for a valid inode, 0 otherwise.
677
 */
678
uint8_t
679
fatxxfs_inode_lookup(FATFS_INFO *a_fatfs, TSK_FS_FILE *a_fs_file,
680
    TSK_INUM_T a_inum)
681
448k
{
682
448k
    const char *func_name = "fatxxfs_inode_lookup";
683
448k
    TSK_DADDR_T sector = 0;
684
448k
    int8_t ret_val = 0;
685
448k
    FATFS_DATA_UNIT_ALLOC_STATUS_ENUM sector_alloc_status = FATFS_DATA_UNIT_ALLOC_STATUS_UNKNOWN;
686
448k
    FATFS_DENTRY dentry;
687
448k
    TSK_RETVAL_ENUM copy_result = TSK_OK;
688
689
448k
    tsk_error_reset();
690
448k
    if (fatfs_ptr_arg_is_null(a_fatfs, "a_fatfs", func_name) ||
691
448k
        fatfs_ptr_arg_is_null(a_fs_file, "a_fs_file", func_name) ||
692
448k
        !fatfs_inum_arg_is_in_range(a_fatfs, a_inum, func_name)) {
693
0
        return 1;
694
0
    }
695
696
448k
    sector = FATFS_INODE_2_SECT(a_fatfs, a_inum);
697
448k
    if (sector > a_fatfs->fs_info.last_block) {
698
0
        tsk_error_reset();
699
0
        tsk_error_set_errno(TSK_ERR_FS_INODE_NUM);
700
0
        tsk_error_set_errstr("%s: Inode %" PRIuINUM
701
0
            " in sector too big for image: %" PRIuDADDR, func_name, a_inum, sector);
702
0
        return 1;
703
0
    }
704
705
448k
    if (fatfs_dentry_load(a_fatfs, &dentry, a_inum) != 0) {
706
0
        return 1;
707
0
    }
708
709
448k
    ret_val = fatfs_is_sectalloc(a_fatfs, sector);
710
448k
    if (ret_val == -1) {
711
0
        return 1;
712
0
    }
713
448k
    else {
714
448k
        sector_alloc_status = (FATFS_DATA_UNIT_ALLOC_STATUS_ENUM)ret_val;
715
448k
    }
716
717
    /* Note that only the sector allocation status is used to choose
718
     * between the basic or in-depth version of the inode validity
719
     * test. In other places in the code information about whether or not
720
     * the sector that contains the inode is part of a folder is used to
721
     * make this decision. Here, that information is not available. Thus,
722
     * the test here is less reliable and may result in some false
723
     * positives. */
724
448k
    if (!fatxxfs_is_dentry(a_fatfs, &dentry, sector_alloc_status, sector_alloc_status)) {
725
0
        tsk_error_reset();
726
0
        tsk_error_set_errno(TSK_ERR_FS_INODE_NUM);
727
0
        tsk_error_set_errstr("%s: %" PRIuINUM
728
0
            " is not an inode", func_name, a_inum);
729
0
        return 1;
730
0
    }
731
732
448k
    copy_result = fatxxfs_dinode_copy(a_fatfs, a_inum, &dentry, (uint8_t)sector_alloc_status, a_fs_file);
733
448k
    if (copy_result == TSK_OK) {
734
448k
        return 0;
735
448k
    }
736
0
    else if (copy_result == TSK_COR) {
737
        /* If there was a Unicode conversion error,
738
         * then still return the inode. */
739
0
        if (tsk_verbose) {
740
0
            tsk_error_print(stderr);
741
0
        }
742
0
        tsk_error_reset();
743
0
        return 0;
744
0
    }
745
0
    else {
746
0
        return 1;
747
0
    }
748
448k
}
749
750
/**
751
 * Output the file attributes of an exFAT file directory entry in
752
 * human-readable form.
753
 *
754
 * @param a_fatfs Source file system for the directory entry.
755
 * @param a_inum Inode address associated with the directory entry.
756
 * @param a_hFile Handle of the file to which to write.
757
 * @return 0 on success, 1 on failure, per TSK convention
758
 */
759
uint8_t
760
fatxxfs_istat_attr_flags(FATFS_INFO *a_fatfs, TSK_INUM_T a_inum, FILE *a_hFile)
761
0
{
762
0
    const char *func_name = "fatxxfs_istat_attr_flags";
763
0
    FATXXFS_DENTRY dentry;
764
765
0
    tsk_error_reset();
766
0
    if (fatfs_ptr_arg_is_null(a_fatfs, "a_fatfs", func_name) ||
767
0
        fatfs_ptr_arg_is_null(a_hFile, "a_hFile", func_name) ||
768
0
        !fatfs_inum_arg_is_in_range(a_fatfs, a_inum, func_name)) {
769
0
        return 1;
770
0
    }
771
772
0
    if (fatfs_dentry_load(a_fatfs, (FATFS_DENTRY*)(&dentry), a_inum)) {
773
0
        return 1;
774
0
    }
775
776
0
    if ((dentry.attrib & FATFS_ATTR_LFN) == FATFS_ATTR_LFN) {
777
0
        tsk_fprintf(a_hFile, "Long File Name\n");
778
0
    }
779
0
    else {
780
0
        if (dentry.attrib & FATFS_ATTR_DIRECTORY)
781
0
            tsk_fprintf(a_hFile, "Directory");
782
0
        else if (dentry.attrib & FATFS_ATTR_VOLUME)
783
0
            tsk_fprintf(a_hFile, "Volume Label");
784
0
        else
785
0
            tsk_fprintf(a_hFile, "File");
786
787
0
        if (dentry.attrib & FATFS_ATTR_READONLY)
788
0
            tsk_fprintf(a_hFile, ", Read Only");
789
0
        if (dentry.attrib & FATFS_ATTR_HIDDEN)
790
0
            tsk_fprintf(a_hFile, ", Hidden");
791
0
        if (dentry.attrib & FATFS_ATTR_SYSTEM)
792
0
            tsk_fprintf(a_hFile, ", System");
793
0
        if (dentry.attrib & FATFS_ATTR_ARCHIVE)
794
0
            tsk_fprintf(a_hFile, ", Archive");
795
0
        if (dentry.ntbyte & FATXXFS_ENCRYPTED_DATA) {
796
0
            tsk_fprintf(a_hFile, ", Encrypted");
797
798
0
            if (dentry.ntbyte & FATXXFS_LARGE_EFS_HEADER)
799
0
                tsk_fprintf(a_hFile, ", Large EFS Header");
800
0
        }
801
802
0
        tsk_fprintf(a_hFile, "\n");
803
0
    }
804
805
0
    return 0;
806
0
}
807
808
uint8_t
809
fatxxfs_inode_walk_should_skip_dentry(FATFS_INFO *a_fatfs, TSK_INUM_T a_inum,
810
    FATFS_DENTRY *a_dentry, unsigned int a_selection_flags,
811
    int a_cluster_is_alloc)
812
61.1k
{
813
61.1k
    const char *func_name = "fatxxfs_inode_walk_should_skip_dentry";
814
61.1k
    FATXXFS_DENTRY *dentry = (FATXXFS_DENTRY*)a_dentry;
815
61.1k
    unsigned int dentry_flags = 0;
816
817
61.1k
    assert(a_fatfs != NULL);
818
61.1k
    assert(fatfs_inum_is_in_range(a_fatfs, a_inum));
819
61.1k
    assert(a_dentry != NULL);
820
821
61.1k
    tsk_error_reset();
822
61.1k
    if (fatfs_ptr_arg_is_null(a_fatfs, "a_fatfs", func_name) ||
823
61.1k
        !fatfs_inum_arg_is_in_range(a_fatfs, a_inum, func_name) ||
824
61.1k
        fatfs_ptr_arg_is_null(a_dentry, "a_dentry", func_name)) {
825
0
        return 1;
826
0
    }
827
828
    /* If this is a long file name entry, then skip it and
829
     * wait for the short name. */
830
61.1k
    if ((dentry->attrib & FATFS_ATTR_LFN) == FATFS_ATTR_LFN) {
831
2.48k
        return 1;
832
2.48k
    }
833
834
    /* Skip the "." and ".." entries because they are redundant. */
835
58.6k
    if (((dentry->attrib & FATFS_ATTR_DIRECTORY) == FATFS_ATTR_DIRECTORY) &&
836
58.6k
         (dentry->name[0] == '.')) {
837
2
        return 1;
838
2
    }
839
840
    /* Compare directory entry allocation status with the inode selection
841
     * flags. Allocation status is determined first by the allocation status
842
     * of the sector that contains the entry, then by the deleted status of
843
     * the file. This is necessary because when a directory is deleted, its
844
     * contents are not always marked as unallocated. */
845
58.6k
    if (a_cluster_is_alloc == 1) {
846
45.1k
    if(FATXXFS_IS_DELETED(dentry->name, a_fatfs)){
847
27.0k
      dentry_flags = TSK_FS_META_FLAG_UNALLOC;
848
27.0k
    }
849
18.0k
    else{
850
18.0k
      dentry_flags = TSK_FS_META_FLAG_ALLOC;
851
18.0k
    }
852
45.1k
    }
853
13.5k
    else {
854
13.5k
        dentry_flags = TSK_FS_META_FLAG_UNALLOC;
855
13.5k
    }
856
857
58.6k
    if ((a_selection_flags & dentry_flags) != dentry_flags) {
858
18.0k
        return 1;
859
18.0k
    }
860
861
    /* If the processing flags call for only processing orphan files, check
862
     * whether or not this inode is in list of non-orphan files found via name
863
     * walk. */
864
40.6k
    if ((dentry_flags & TSK_FS_META_FLAG_UNALLOC) &&
865
40.6k
        (a_selection_flags & TSK_FS_META_FLAG_ORPHAN) &&
866
40.6k
        (tsk_fs_dir_find_inum_named(&(a_fatfs->fs_info), a_inum))) {
867
0
        return 1;
868
0
    }
869
870
40.6k
    return 0;
871
40.6k
}