-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfilesystem.h
192 lines (164 loc) · 5.7 KB
/
filesystem.h
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
//===-- filesystem.h - FileSystem class definition ------------------------===//
//
// The Toy FAT FileSystem
//
//===----------------------------------------------------------------------===//
///
/// \file
/// File description
///
//===----------------------------------------------------------------------===//
#ifndef TOYFS_FILESYSTEM_H_
#define TOYFS_FILESYSTEM_H_
#include "disk.h"
#include <list>
#include <memory>
#include <mutex>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <vector>
class Entry;
class FileSystem
{
public:
static const int kBlockSize = 64; // 块大小,本程序为了简便等于磁盘扇区大小
static const int kEntrySize = 8; // 目录项大小
static const int kMaxChildEntries = 8; // 一个目录最大的目录项数
static const int kMaxOpenedFiles = 5;
static const int kRawFileNameLength = 5;
static const int END_OF_FILE = '#';
static_assert(kEntrySize * kMaxChildEntries == kBlockSize, "Mismatch constants.");
enum Attribute
{
ReadOnly = 1,
System = 2,
File = 4,
Directory = 8
};
using Attributes = int;
enum OpenMode
{
Read = 1,
Write = 2
};
using OpenModes = int;
// constructors & destructor
explicit FileSystem(Disk& disk);
~FileSystem();
// keep from copying
FileSystem(const FileSystem&) = delete;
FileSystem& operator=(const FileSystem&) = delete;
bool initFileSystem();
std::shared_ptr<Entry> rootEntry();
std::shared_ptr<Entry> getEntry(const std::string& fullPath);
bool exist(const std::string& fullPath);
bool createDir(const std::string& fullPath);
bool createDir(std::shared_ptr<Entry> parent, const std::string& dirName);
bool createFile(const std::string& fullPath, Attributes attributes);
bool createFile(std::shared_ptr<Entry> parent, const std::string& fileName, Attributes attributes);
bool openFile(const std::string& fullPath, OpenModes openModes);
bool closeFile(const std::string& fullPath);
bool isOpened(const std::string& fullPath);
std::vector<std::string> getOpenedFiles();
std::unique_ptr<std::string> readFile(const std::string& fullPath, int length);
int readFile(const std::string& fullPath, char* buf_out, int length);
bool writeFile(const std::string& fullPath, const char* buf_in, int length);
bool setFileAttributes(const std::string& fullPath, Attributes attributes);
bool deleteEntry(const std::string& fullPath);
bool deleteEntry(std::shared_ptr<Entry> entry);
bool sync();
private:
// 文件描述符
struct OpenedFile
{
std::string fullPath;
Attributes attributes;
int blockNumber;
int numOfBlocks;
OpenModes modes;
int g; // get pointer
int p; // put pointer
};
static const int kEntryAttributesIndex = 5;
static const int kEntryBlockStartIndex = 6;
static const int kEntryNumOfBlocksIndex = 7;
const int kFatSize; // FAT 大小
const int kNumOfFatBlocks; // FAT 占用的块数
const int kRootBlockNumber; // 根目录起始块地址
Disk& m_disk;
char* m_fat;
char* m_buffer;
std::shared_ptr<Entry> m_rootEntry;
std::unordered_map<std::string, std::shared_ptr<OpenedFile>> m_openedFiles;
// 互斥锁
// 注意:如需占用多个锁,请按顺序加锁
std::mutex m_mutex1Fat;
std::mutex m_mutex2Buffer;
// FAT 相关函数
bool loadFat();
bool saveFat();
/**
* @brief nextAvailableBlock
* @return 如果有可用块则为可用块号,否则为 -1。
*/
int nextAvailableBlock();
/**
* @brief findNextNBlock
* @param firstBlock
* @param n
* @return firstBlock 之后 n 块的块号,如果结果不存在,返回 -1。
*/
int findNextNBlock(int firstBlock, int n);
// 实用函数
static std::string getNameFromEntryPointer(char* p);
static char* findChildEntryPointer(char* parentEntryPointer, const std::string& childName);
static bool checkName(const std::string& name);
static std::list<std::string> splitPath(const std::string& fullpath);
friend class Entry;
};
class Entry : public std::enable_shared_from_this<Entry>
{
public:
Entry(Disk& disk) : m_disk(disk) {}
// bool isPathValid();
bool isDir() { return m_attributes & FileSystem::Directory; }
bool isReadOnly() { return m_attributes & FileSystem::ReadOnly; }
bool isSystem() { return m_attributes & FileSystem::System; }
FileSystem::Attributes attributes() { return m_attributes; }
std::string name() { return m_name; }
std::string fullpath();
std::shared_ptr<Entry> self() { return shared_from_this(); }
std::shared_ptr<Entry> parent() { return m_parent; }
int size() { return m_numBlock * FileSystem::kBlockSize; }
/**
* @brief getChildren
* @return 如果是目录则为子项目列表,否刚返回空列表。
*/
std::vector<std::shared_ptr<Entry>> getChildren();
/**
* @brief findChild
* @param name 子项名。
* @return 如果子项存在,返回子项,否则返回 null。
*/
std::shared_ptr<Entry> findChild(const std::string& name);
// std::weak_ptr<Entry> addChild(const std::string& name);
private:
Disk& m_disk;
std::string m_name;
FileSystem::Attributes m_attributes;
int m_blockStart;
int m_numBlock;
std::shared_ptr<Entry> m_parent;
friend class FileSystem;
};
inline std::string Entry::fullpath()
{
if (parent() == self())
{
return name();
}
auto fullPath = parent()->fullpath() + "/" + name();
return fullPath.substr(fullPath.find_first_not_of('/') - 1);
}
#endif // TOYFS_FILESYSTEM_H_