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