summaryrefslogtreecommitdiff
path: root/Kernel/Ext2FileSystem.h
blob: 9509531d484f54d3e3c4aa4796272157c3f503fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#pragma once

#include "ext2fs.h"
#include "OwnPtr.h"
#include "DataBuffer.h"
#include "FileSystem.h"

static const size_t bytesPerSector = 512;

class Ext2VirtualNode;

class Ext2FileSystem {
public:
    Ext2FileSystem() { }
    ~Ext2FileSystem();

    void initialize();
    RefPtr<DataBuffer> loadFile(ext2_dir_entry*);

    ext2_inode* findInode(DWORD index);
    ext2_inode* findPath(const String& path, DWORD& inodeIndex);

private:
    friend class Ext2VirtualNode;

    void readSuperBlock();
    void readBlockGroup(DWORD);
    void readInodeTable(DWORD);
    void dumpDirectory(ext2_inode&);
    void dumpFile(ext2_inode&);

    template<typename F> void forEachBlockIn(ext2_inode&, F func);
    template<typename F> void traverseDirectory(ext2_dir_entry&, DWORD blockCount, F);
    template<typename F> void traverseDirectory(ext2_inode&, F);
    RefPtr<DataBuffer> readFile(ext2_inode&);

    RefPtr<DataBuffer> readBlocks(DWORD blockIndex, BYTE count);
    void readDiskSector(DWORD sectorIndex, BYTE* buffer);

    size_t blockSize() const { return 1024 << m_superBlock->s_log_frag_size; }
    size_t sectorsPerBlock() const { return blockSize() / bytesPerSector; }
    DWORD blockGroupForInode(DWORD inode) const;
    DWORD toInodeTableIndex(DWORD inode) const;

    ext2_super_block& superBlock() { ASSERT(m_superBlock); return *m_superBlock; }

    OwnPtr<ext2_super_block> m_superBlock;
    ext2_inode* m_root { nullptr }; // raw pointer into one of the m_inodeTables

    size_t m_blockGroupCount { 0 };
    ext2_group_descriptor* m_groupTable { nullptr };
    ext2_inode** m_inodeTables { nullptr };
};

class Ext2VirtualNode final : public FileSystem::VirtualNode {
public:
    static RefPtr<Ext2VirtualNode> create(DWORD index, String&& path, Ext2FileSystem&, DWORD inodeNumber);

    virtual ~Ext2VirtualNode();

    virtual size_t size() const override { return m_inode.i_size; }
    virtual uid_t uid() const override { return m_inode.i_uid; }
    virtual gid_t gid() const override { return m_inode.i_gid; }
    virtual size_t mode() const override { return m_inode.i_mode; }

    virtual size_t read(BYTE* outbuf, size_t start, size_t maxLength) override;

private:
    Ext2VirtualNode(DWORD index, String&& path, Ext2FileSystem&, ext2_inode&, DWORD inodeNumber);

    Ext2FileSystem& m_fileSystem;
    ext2_inode& m_inode;
    DWORD m_inodeNumber { 0 };
};