1 /*
2  * Copyright (c) 2022 Travis Geiselbrecht
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 #pragma once
9 
10 #include <lib/bio.h>
11 #include <lk/cpp.h>
12 #include <lk/debug.h>
13 #include <stdint.h>
14 #include <sys/types.h>
15 
16 #include "fat_fs.h"
17 
18 // Local object used to track the state of walking through a file or directory
19 // one sector at a time using the block cache. Holds a reference to the open
20 // block cache block and intelligently returns and gets the next one when necessary.
21 class file_block_iterator {
22 public:
23     // initialize with the starting cluster of the file or directory.
24     // special case of starting_cluster == 0 will cause it to track
25     // the root directory of a fat 12 or 16 volume, which handle
26     // root directories differently.
27     file_block_iterator(fat_fs *_fat, uint32_t starting_cluster);
28     ~file_block_iterator();
29 
30     DISALLOW_COPY_ASSIGN_AND_MOVE(file_block_iterator);
31 
get_bcache_ptr(size_t offset)32     const uint8_t *get_bcache_ptr(size_t offset) {
33         DEBUG_ASSERT(offset < fat->info().bytes_per_sector);
34         DEBUG_ASSERT(bcache_buf);
35         return (const uint8_t *)bcache_buf + offset;
36     }
37 
38     // move N sectors ahead in the file, walking the FAT cluster chain as necessary.
39     // sectors == 0 will ensure the current block is loaded.
40     status_t next_sectors(uint32_t sectors);
41 
42     // move one sector
next_sector()43     status_t next_sector() { return next_sectors(1); }
44 
45     // return the number of sectors this has moved forward during its lifetime
get_sector_inc_count()46     uint32_t get_sector_inc_count() const { return sector_inc_count; }
reset_sector_inc_count()47     void reset_sector_inc_count() { sector_inc_count = 0; }
48 
49 private:
50     void put_bcache_block();
51     status_t load_current_bcache_block();
52     status_t load_bcache_block(bnum_t bnum);
53 
54     fat_fs *fat;
55     uint32_t cluster;           // current cluster we're on
56     uint32_t sector_offset;     // sector number within cluster
57     uint32_t sector_inc_count = 0; // number of sectors we have moved forward in the lifetime of this
58 
59     void *bcache_buf = nullptr; // current pointer to the bcache, if held
60     bnum_t bcache_bnum;         // current block number of the bcache_buf, if valid
61 };
62 
63