Compare commits

19 Commits
Author SHA1 Message Date
Mingjian W 48172dfac5 Update README.md 2019-06-28 16:48:43 +08:00
w-mj 95c1abc4f2 chmod 2019-06-27 11:26:16 +08:00
w-mj 0cfb3ab131 chown 2019-06-27 11:17:29 +08:00
w-mj e4a0f5131b login 2019-06-27 10:47:25 +08:00
w-mj 637e37f2eb echo 2019-06-27 10:01:04 +08:00
w-mj 01b6674bc5 -Wall -Werror && umount 2019-06-26 20:24:27 +08:00
w-mj d9d14d0429 mount another fs 2019-06-26 19:32:33 +08:00
w-mj f874c07d04 bug fix.
inode_to_pos in other group
2019-06-26 18:19:45 +08:00
w-mj 72ddb76b79 unify vfs file and system file 2019-06-25 19:57:43 +08:00
w-mj 3f22946877 more stable iter 2019-06-25 17:06:04 +08:00
w-mj f21101a85c fix bug of reading big file 2019-06-25 16:59:09 +08:00
w-mj 1bc09972c1 cnt groups 2019-06-25 16:14:46 +08:00
w-mj 54b8ae5c3a clean output 2019-06-25 15:02:37 +08:00
w-mj cfc2d7a624 hard link not allowed for directory 2019-06-25 14:52:12 +08:00
w-mj 9748d564f3 dirty inode 2019-06-25 14:44:43 +08:00
w-mj e2fb8ef953 follow 2019-06-23 21:07:05 +08:00
w-mj 0c2a130596 symbol link 2019-06-23 20:05:57 +08:00
w-mj 9323d88ca1 sth 2019-06-23 16:48:35 +08:00
Mingjian W fe3d369a52 Merge pull request #1 from w-mj/add-license-1
Create LICENSE
2019-06-23 15:25:05 +08:00
27 changed files with 800 additions and 271 deletions
+1 -1
View File
@@ -1 +1 @@
# 自制操作系统
# 文件系统课程设计
+18
View File
@@ -0,0 +1,18 @@
#include "common.h"
std::vector<std::string> split(const std::string& s, char sp) {
size_t i = 0, l = 0;
std::vector<std::string> res;
while (i < s.size()) {
if (s[i] == sp) {
if (i != l)
res.push_back(s.substr(l, i - l));
l = i + 1;
}
i++;
}
if (i != l)
res.push_back(s.substr(l, i - l));
return res;
}
+4
View File
@@ -0,0 +1,4 @@
#pragma once
#include <vector>
#include <string>
std::vector<std::string> split(const std::string& s, char sp);
+5 -5
View File
@@ -171,7 +171,7 @@ static void out_info(_I mode) {
}
#endif
#if DELOG_MODE == 0
printf("%s\n", ms_buf);
fprintf(stderr, "%s\n", ms_buf);
#endif
goto _out_info_END;
}
@@ -180,7 +180,7 @@ static void out_info(_I mode) {
fprintf(flog, "%s\n", ms_buf);
}
#if DELOG_MODE == 0
printf("%s\n", ms_buf);
fprintf(stderr, "%s\n", ms_buf);
#endif
goto _out_info_END;
}
@@ -253,7 +253,7 @@ _print_debug_CON:
default:
fprintf(stderr, "Unknown fmt %c\n", fmt[0]);
}
_print_debug_END:
// _print_debug_END:
return ;
}
@@ -323,7 +323,7 @@ _I print_bin(_s s, _I size, _u8 *p, _I len) {
if ((i & _BITS_MASK(LINEBSIZE)) == 0) {
last_i = LINENUM;
if (j > 0 && j < LINENUM + 1) {
for (int t = 0; t < LINENUM - j; t++)
for (_u32 t = 0; t < LINENUM - j; t++)
fmt_dot(s, n);
last_i = j;
}
@@ -348,7 +348,7 @@ _I print_bin(_s s, _I size, _u8 *p, _I len) {
if (len) {
last_i = LINENUM;
if (j > 0 && j < LINENUM + 1) {
for (int t = 0; t < LINENUM - j; t++)
for (_u32 t = 0; t < LINENUM - j; t++)
fmt_dot(s, n);
last_i = j;
}
+2
View File
@@ -49,9 +49,11 @@ enum {
#if DELOG_MODE < 2
#define _debug_info(expstr, m, ...) _pos_delog(_DBG_INFO_DELOG, m, expstr, __VA_ARGS__)
#define _dbg_log(...) _pos_delog(_DBG_INFO_DELOG, "t", "log", __VA_ARGS__)
#define _d_end() _dbg_log("finished.")
#else
#define _debug_info(expstr, m, ...) do{}while(0)
#define _dbg_log(...) do{}while(0)
#define _d_end() do{}while(0)
#endif
#define _log_info(...) _Npos_delog(_LOG_INFO_DELOG, __VA_ARGS__)
#define _reg() _log_info("[%s] run!", __func__)
+1 -1
View File
@@ -11,7 +11,7 @@ public:
virtual _u32 write(MM::Buf& buf, _u32 pos, _u32 size) = 0;
// virtual _u32 tell()=0;
// virtual void seek(_u32 pos)=0;
virtual void open(const std::string& path) = 0;
// virtual void open(const std::string& path) = 0;
virtual void close() = 0;
};
+13 -46
View File
@@ -6,69 +6,36 @@
using namespace Dev;
MockDisk::MockDisk(VFS::File& f): f(f) {}
_u32 MockDisk::read(MM::Buf& buf1, _u32 pos, _u32 size) {
//std::cout << "\n开始读文件"<<ftell(f)<<std::endl;
// this->seek(pos);
// f.read(buf.data, size);
// for (int i = 0; i < size; i++)
// std::cout << (int)buf.data[i];
// return fread(buf.data, size, 1, f);
memcpy(buf1.data, buf + pos, size);
f.seek(pos, SEEK_SET);
f.read((char*)buf1.data, size);
return size;
}
_u32 MockDisk::write(MM::Buf& buf1, _u32 pos, _u32 size) {
// seek(pos);
// f.write(buf.data, size);
// return fwrite(buf.data, size, 1, f);
// _dbg_log("写入文件 old");
// _si(pos);
// _si(size);
//_sa(buf + pos, size);
memcpy(buf + pos, buf1.data, size);
//_dbg_log("写入文件 new");
//_sa(buf + pos, size);
f.seek(pos, SEEK_SET);
f.write((char*)buf1.data, size);
return size;
}
_u32 MockDisk::tell() {
return ftell(f);
return f.tell();
}
void MockDisk::seek(_u32 pos) {
//_si(pos);
fseek(f, pos, SEEK_SET);
// fseek(f, pos, SEEK_SET);
f.seek(pos, SEEK_SET);
}
void MockDisk::open(const std::string& path) {
void MockDisk::open() {
std::cout << "正在打开文件" << std::endl;
name = path;
f = fopen(path.c_str(), "rb");
// f.open(path, std::ios::binary);
if (f == nullptr) {
// std::cout << "文件打开错误"<< std::endl;
perror("文件打开错误");
}
fseek(f, 0, SEEK_END);
length = ftell(f);
fseek(f, 0, SEEK_SET);
buf = new char[length];
fread(buf, length, 1, f);
fclose(f);
length = f.size;
}
void MockDisk::close() {
f = fopen(name.c_str(), "wb");
_dbg_log("保存磁盘");
// f.open(path, std::ios::binary);
if (f == nullptr) {
// std::cout << "文件打开错误"<< std::endl;
perror("文件打开错误");
}
fwrite(buf, length, 1, f);
fclose(f);
delete buf;
f.close();
}
+4 -3
View File
@@ -1,6 +1,7 @@
#pragma once
#include "block_dev.h"
#include "fs/vfs.h"
#include <stdio.h>
#include <string>
namespace Dev
@@ -9,17 +10,17 @@ namespace Dev
class MockDisk: public BlockDevice {
private:
// std::fstream f;
FILE* f;
VFS::File& f;
_u32 tell();
_u32 length;
char *buf;
void seek(_u32 pos);
std::string name;
public:
MockDisk(VFS::File& f);
_u32 read(MM::Buf& buf, _u32 pos, _u32 size);
_u32 write(MM::Buf& buf, _u32 pos, _u32 size);
void open(const std::string& path);
void open();
void close();
};
+36
View File
@@ -16,3 +16,39 @@
2. 对于目录,该目录下的所有文件名和子目录储存在数据块中。
3. 对于符号链接,如果目标路径较短则直接保存在inode中,若目标路径较长则分配一个数据块保存。
4. 设备文件、FIFO和socket等特殊文件没有数据块。
## TODO List
[x] ls
[x] cd
[x] mkdir
[x] touch
[x] cat
[x] rm
[x] link
[x] mv
[x] cp
[x] ln
[ ] namei
[ ] mount
[ ] 重新设计分配数据块的方法
[ ] 优化算法
[ ] 块组测试
[ ] 修正乱用\_u8和\_u32
[ ] 修正.和..的load_children()
+83 -21
View File
@@ -15,6 +15,7 @@ EXT2_DEntry::EXT2_DEntry(EXT2_FS* fs1, VFS::DEntry* parent1,
if (parent == nullptr)
parent = this;
inode = nullptr;
ext2_inode = nullptr;
inode_n = inode_n1;
type=type1;
name = std::string(name1);
@@ -41,15 +42,15 @@ void EXT2_DEntry::load_children() {
children.clear();
// for (_u32 i = 0; i < ext2_inode->i->blocks; i++) {
_sp(*ext2_inode);
// ext2_inode->print();
ext2_inode->print();
_u32 all_length = 0;
for (int i: *ext2_inode) {
_u32 data_block_pos = ext2_fs->block_to_pos(i);
dev->read(buf, data_block_pos, ext2_fs->block_size);
// _sa(buf.data, ext2_fs->block_size);
_u32 s_pos = 0;
_u32 next_length = 12;
while (all_length < ext2_inode->i->size) {
// _u32 next_length = 12;
while (all_length < ext2_inode->size) {
// _sa(buf.data + s_pos, 20);
memmove(temp_str, buf.data + s_pos, sizeof(DirEntry));
if (temp_str->rec_len == 0)
@@ -93,6 +94,7 @@ void EXT2_DEntry::inflate() {
ext2_inode = new EXT2_Inode(ext2_fs, inode_n, disk_inode);
ext2_inode->print();
inode = ext2_inode;
// type = VFS::mode_to_type(inode->mode);
sync = 0;
}
@@ -103,6 +105,7 @@ static inline int cal_name_len(int s) {
}
void EXT2_DEntry::write_children() {
_error(type != VFS::Directory);
DirEntry new_disk_entry[1];
EXT2_File parent_body(this, this->ext2_inode);
_u32 all_length = 0;
@@ -121,14 +124,14 @@ void EXT2_DEntry::write_children() {
}
sub_item_cnt++;
all_length += new_disk_entry->rec_len;
parent_body.write((_u8*)new_disk_entry, new_disk_entry->rec_len);
parent_body.write((char *)new_disk_entry, new_disk_entry->rec_len);
// new_disk_entry->name = de->name.c_str();
}
_d_end();
}
VFS::DEntry* EXT2_DEntry::mkdir(const std::string& new_name) {
if (type != VFS::Directory)
_error(type);
_error(type != VFS::Directory);
EXT2_GD *new_dir_gd = nullptr;
_u32 new_i_n = ext2_fs->alloc_inode(&new_dir_gd);
new_dir_gd->get_gd()->used_dirs_count++;
@@ -165,24 +168,25 @@ VFS::DEntry* EXT2_DEntry::mkdir(const std::string& new_name) {
// EXT2_File parent_body11(this, this->ext2_inode);
// 修改父目录的Inode
ext2_inode->i->links_count++; // 硬链接计数器加1
ext2_inode->nlink++; // 硬链接计数器加1
ext2_inode->write_inode();
DirEntry new_disk_entry[1];
// 在子目录的文件体中写入.和..
new_disk_entry->file_type = VFS::Directory;
EXT2_File child_body(new_entry, new_i);
new_disk_entry->inode = new_i_n;
new_disk_entry->rec_len = 12;
new_disk_entry->name_len = 1;
new_disk_entry->name[0] = '.';
new_disk_entry->name[1] = '\0';
child_body.write((_u8*)new_disk_entry, new_disk_entry->rec_len);
child_body.write((char*)new_disk_entry, new_disk_entry->rec_len);
new_disk_entry->inode = this->inode_n;
new_disk_entry->name_len = 2;
new_disk_entry->rec_len = ext2_fs->block_size - 12;
new_disk_entry->name[1] = '.';
new_disk_entry->name[2] = '\0';
child_body.write((_u8*)new_disk_entry, new_disk_entry->rec_len);
child_body.write((char*)new_disk_entry, new_disk_entry->rec_len);
// EXT2_File child_bod11y(new_entry, new_i);
// ext2_fs->sb->
@@ -192,8 +196,7 @@ VFS::DEntry* EXT2_DEntry::mkdir(const std::string& new_name) {
}
VFS::DEntry *EXT2_DEntry::create(const std::string& name) {
if (type != VFS::Directory)
_error(type);
_error(type != VFS::Directory);
_pos();
inflate();
_u32 new_i_n = ext2_fs->alloc_inode();
@@ -214,6 +217,7 @@ VFS::DEntry *EXT2_DEntry::create(const std::string& name) {
new_i->write_inode(); // 新Inode写入磁盘
EXT2_DEntry *new_entry = new EXT2_DEntry(ext2_fs, this, new_i_n, VFS::RegularFile, name);
new_entry->ext2_inode = new_i;
new_entry->inode = new_i;
load_children();
children.push_back(new_entry);
write_children();
@@ -224,6 +228,8 @@ VFS::DEntry *EXT2_DEntry::create(const std::string& name) {
}
VFS::File *EXT2_DEntry::get_file() {
if (type==VFS::SymbolLink)
return follow()->open();
return new EXT2_File(this);
}
@@ -232,7 +238,7 @@ void EXT2_DEntry::unlink(VFS::DEntry *d) {
_error(type != VFS::Directory);
load_children();
if (d->type == VFS::Directory) {
ext2_inode->i->links_count--; // 降低自己的引用链接
ext2_inode->nlink--; // 降低自己的引用链接
ext2_inode->write_inode();
ext2_fs->gdt_list[d->inode_n / ext2_fs->sb->inodes_per_group]->get_gd()->used_dirs_count--;
ext2_fs->write_gdt();
@@ -247,26 +253,26 @@ void EXT2_DEntry::unlink(VFS::DEntry *d) {
void EXT2_DEntry::unlink() {
inflate();
_dbg_log("ulink %d ref cnt: %d type: %d.", inode_n, ext2_inode->i->links_count, type);
if (ext2_inode->i->links_count == 0)
_dbg_log("ulink %d ref cnt: %d type: %d.", inode_n, ext2_inode->nlink, type);
if (ext2_inode->nlink == 0)
return;
ext2_inode->i->links_count--;
ext2_inode->nlink--;
// 硬引用计数减一,当引用计数为0时彻底删除文件,目录可以等于1
if (ext2_inode->i->links_count == 0 || (type==VFS::Directory && ext2_inode->i->links_count == 1)) {
if (ext2_inode->nlink == 0 || (type==VFS::Directory && ext2_inode->nlink == 1)) {
_pos();
ext2_inode->i->dtime = time(0);
EXT2_File f(this);
f.resize(0);
// if (type==VFS::Directory)
// ext2_inode->i->size = 1024;
ext2_inode->i->links_count = 0;
ext2_inode->nlink = 0;
ext2_fs->release_inode(inode_n);
ext2_fs->write_gdt();
ext2_fs->write_super();
}
ext2_inode->write_inode();
_dbg_log("ulink %d ref cnt: %d type: %d. finish", inode_n, ext2_inode->i->links_count, type);
_dbg_log("ulink %d ref cnt: %d type: %d. finish", inode_n, ext2_inode->nlink, type);
}
void EXT2_DEntry::unlink_children() {
@@ -278,7 +284,7 @@ void EXT2_DEntry::unlink_children() {
if (d->inode_n == inode_n || d->inode_n == parent->inode_n)
continue;
if (d->type == VFS::Directory) {
ext2_inode->i->links_count--; // 降低自己的引用链接
ext2_inode->nlink--; // 降低自己的引用链接
ext2_fs->gdt_list[d->inode_n / ext2_fs->sb->inodes_per_group]->get_gd()->used_dirs_count--;
d->unlink_children();
}
@@ -297,6 +303,10 @@ VFS::DEntry *EXT2_DEntry::link(DEntry *tar, const std::string& s) {
_log_info("[EXT2]: Hard Link must in the same file system.");
return nullptr;
}
if (type == VFS::Directory) {
_log_info("%s: hard link not allowed for directory", name.c_str());
return nullptr;
}
EXT2_DEntry *t = dynamic_cast<EXT2_DEntry*>(tar);
std::string ts;
if (s == "")
@@ -308,7 +318,14 @@ VFS::DEntry *EXT2_DEntry::link(DEntry *tar, const std::string& s) {
t->children.push_back(new_e);
t->write_children();
inflate();
ext2_inode->i->links_count++;
if (type == VFS::Directory) {
// 目录的硬链接比普通文件多一个
ext2_inode->nlink += 2;
// 目录的硬链接,组中目录数目加一
ext2_fs->gdt_list[inode_n / ext2_fs->sb->inodes_per_group]->get_gd()->used_dirs_count++;
ext2_fs->write_gdt();
} else
ext2_inode->nlink += 1;
ext2_inode->write_inode();
return new_e;
}
@@ -328,7 +345,7 @@ VFS::DEntry* EXT2_DEntry::copy(DEntry *dir, const std::string& new_name) {
VFS::DEntry *new_entry = dir->create(new_name==""?this->name:new_name);
VFS::File *old_f = this->open();
VFS::File *new_f = new_entry->open();
_u8 buf[old_f->size];
char buf[old_f->size];
old_f->read(buf, old_f->size);
new_f->write(buf, old_f->size);
// dynamic_cast<EXT2_DEntry*>(new_entry)->ext2_inode->write_inode();
@@ -337,8 +354,53 @@ VFS::DEntry* EXT2_DEntry::copy(DEntry *dir, const std::string& new_name) {
return new_entry;
}
VFS::DEntry *EXT2_DEntry::symlink(DEntry *file, const std::string& new_name) {
EXT2_DEntry *new_entry = static_cast<EXT2_DEntry*>(create(new_name==""?file->name:new_name));
_pos();
new_entry->inode->mode = S_IFLNK | S_IRWXG | S_IRWXO | S_IRWXU;
new_entry->type = VFS::SymbolLink;
_pos();
std::string path = file->printed_path();
if (path.size() <= 60) {
memmove(new_entry->ext2_inode->i->block, path.c_str(), path.size());
} else {
VFS::File *file = new_entry->open();
file->write(path.c_str(), path.size());
file->close();
}
new_entry->ext2_inode->size = path.size();
new_entry->inode->size = path.size();
new_entry->ext2_inode->write_inode();
write_children();
_d_end();
return new_entry;
}
VFS::DEntry *EXT2_DEntry::follow() {
_dbg_log("start");
inflate();
char buf[inode->size];
if (inode->size <= 60) {
memmove(buf, ext2_inode->i->block, inode->size);
} else {
VFS::File *f = open();
f->read(buf, inode->size);
f->close();
}
_ss(buf);
VFS::NameI *path = VFS::NameI::from_str(std::string(buf, inode->size));
VFS::DEntry *ans = parent->get_child(path);
delete path;
_d_end();
return ans;
}
EXT2_DEntry::~EXT2_DEntry() {
delete inode;
for (auto x: children) {
if (x->name != ".." && x->name != ".")
delete x;
}
}
+3 -2
View File
@@ -36,9 +36,10 @@ namespace EXT2
VFS::DEntry *move(DEntry *dir, const std::string& new_name="");
bool empty();
VFS::DEntry* copy(DEntry *dir, const std::string& new_name);
VFS::DEntry *copy(DEntry *dir, const std::string& new_name);
VFS::DEntry *symlink(DEntry *file, const std::string& new_name="");
VFS::DEntry *follow();
~EXT2_DEntry();
};
+23 -16
View File
@@ -10,7 +10,7 @@ EXT2_File::EXT2_File(EXT2_DEntry *d, EXT2_Inode *i) {
ext2_fs = i->ext2_fs;
type = d->type;
pos = 0;
size = i->i->size;
size = i->size;
_dbg_log("打开文件");
_si(size);
}
@@ -23,17 +23,17 @@ EXT2_File::EXT2_File(EXT2_DEntry *d) {
ext2_fs = d->ext2_inode->ext2_fs;
type = d->type;
pos = 0;
size = d->ext2_inode->i->size;
size = d->ext2_inode->size;
_dbg_log("打开文件");
_si(size);
}
_u32 EXT2_File::tell() {
int EXT2_File::tell() {
return pos;
}
_u32 EXT2_File::seek(int pos, int whence) {
int EXT2_File::seek(int pos, int whence) {
switch (whence) {
case VFS::SEEK::CUR:
this->pos += pos;
@@ -47,10 +47,11 @@ _u32 EXT2_File::seek(int pos, int whence) {
default:
_error_s(whence, "Unknow whence");
}
_si(this->pos);
return this->pos;
}
_u32 EXT2_File::read(_u8 *buf, _u32 len) {
int EXT2_File::read(char *buf, int len) {
if (pos + len > size)
return 0;
_u32 read_len = 0, this_read_len;
@@ -64,9 +65,10 @@ _u32 EXT2_File::read(_u8 *buf, _u32 len) {
MM::Buf buff(block_size);
ext2_fs->dev->read(buff, pos_in_fs, block_size); // 从第一个块读入数据,每次都读出一整块
memcpy(buf, buff.data + byte_in_block, std::min(len, block_size - byte_in_block));
read_len = std::min(len, block_size - byte_in_block);
while (read_len < len && pos + read_len < size) {
_sa(buff.data, 1024);
memcpy(buf, buff.data + byte_in_block, std::min((_u32)len, block_size - byte_in_block));
read_len = std::min((_u32)len, block_size - byte_in_block);
while (read_len < (_u32)len && pos + read_len < (_u32)size) {
it++; // 指向下一个块
block_n = *it; // 下一个块号
pos_in_fs = ext2_fs->block_to_pos(block_n); // 下一个块的位置
@@ -78,10 +80,11 @@ _u32 EXT2_File::read(_u8 *buf, _u32 len) {
return read_len;
}
_u32 EXT2_File::write(_u8 *buf, _u32 len) {
if (len + pos > size)
resize(len + pos);
ext2_inode->print();
int EXT2_File::write(const char *buf, int len) {
// _si(pos);
resize(len + pos);
// ext2_inode->print();
_u32 write_len = 0, this_write_len;
_u32 block_size = ext2_fs->block_size; // 块大小
_u32 byte_in_block = pos % block_size; // 第一个字节在块中的位置
@@ -91,13 +94,13 @@ _u32 EXT2_File::write(_u8 *buf, _u32 len) {
_u32 pos_in_fs = ext2_fs->block_to_pos(block_n); // 第一个块在文件系统中的位置
//_si(pos + len);
MM::Buf buff(block_size);
this_write_len = std::min(block_size - byte_in_block, len);
this_write_len = std::min(block_size - byte_in_block, (_u32)len);
memcpy(buff.data, buf, this_write_len);
ext2_fs->dev->write(buff, pos_in_fs + byte_in_block, this_write_len); // 向第一个块写数据
write_len = this_write_len;
while (write_len < len) {
while (write_len < (_u32)len) {
it++; // 指向下一个块
block_n = *it; // 下一个块号
block_n = *it; // 下一个块号,其实这里可以自动分配空间,不用resize
pos_in_fs = ext2_fs->block_to_pos(block_n); // 下一个块的位置
this_write_len = std::min(block_size, len - write_len);
memcpy(buff.data, buf + write_len, this_write_len);
@@ -117,9 +120,13 @@ void EXT2_File::resize(_u32 new_size) {
_u32 target_block = new_size / fs->block_size + (new_size % fs->block_size > 0);
_dbg_log("resize from %d to %d", current_block, target_block);
if (target_block == current_block) {
_dbg_log("do not alloc size form %d to %d", size, new_size);
size = new_size;
ext2_inode->size = new_size;
ext2_inode->write_inode();
return;
}
auto it = ext2_inode->end();
auto it = ext2_inode->alloc_iter();
if (target_block > current_block) {
// 分配空间
while (target_block != current_block) {
+4 -4
View File
@@ -17,10 +17,10 @@ namespace EXT2 {
public:
EXT2_File(EXT2_DEntry *);
EXT2_File(EXT2_DEntry *, EXT2_Inode *);
_u32 tell();
_u32 seek(int pos, int whence);
_u32 read(_u8*, _u32 size);
_u32 write(_u8*, _u32 size);
int tell();
int seek(int pos, int whence);
int read(char*, int size);
int write(const char*, int size);
void resize(_u32 new_size);
};
}
+53 -41
View File
@@ -17,33 +17,34 @@ EXT2_FS::EXT2_FS(Dev::BlockDevice* dev): FS(dev) {
void EXT2_FS::printFS() {
using namespace std;
cout << endl;
cout << "文件系统中Inode数量 " << sb->inodes_count << endl;
cout << "以块为单位的文件系统大小 " << sb->blocks_count << endl;
cout << "文件系统中保留块数目 " << sb->r_blocks_count << endl;
cout << "文件系统中空闲块数目 " << sb->free_blocks_count << endl;
cout << "文件系统中空闲Inode数量 " << sb->free_inodes_count << endl;
cout << "第一个使用的块号 " << sb->first_data_block << endl;
cout << "块大小 " << block_size << endl;
cout << "逻辑片大小 " << sb->log_frag_size << endl;
cout << "每组块数 " << sb->blocks_per_group << endl;
cout << "每组碎片数 " << sb->frags_per_group << endl;
cout << "每组Inode数 " << sb->inodes_per_group << endl;
cout << "上次挂载时间 " << sb->mtime << endl;
cout << "上次写入超级块的时间 " << sb->wtime << endl;
cout << "未进行检查的挂载次数 " << sb->mnt_count << endl;
cout << "必须执行检查前的最大挂载次数 " << sb->max_mnt_count << endl;
cout << "Magic " << sb->magic << endl;
cout << "文件系统的状态 " << sb->state << endl;
cerr << endl;
cerr << "文件系统中Inode数量 " << sb->inodes_count << endl;
cerr << "以块为单位的文件系统大小 " << sb->blocks_count << endl;
cerr << "文件系统中保留块数目 " << sb->r_blocks_count << endl;
cerr << "文件系统中空闲块数目 " << sb->free_blocks_count << endl;
cerr << "文件系统中空闲Inode数量 " << sb->free_inodes_count << endl;
cerr << "第一个使用的块号 " << sb->first_data_block << endl;
cerr << "块大小 " << block_size << endl;
cerr << "逻辑片大小 " << sb->log_frag_size << endl;
cerr << "每组块数 " << sb->blocks_per_group << endl;
cerr << "每组碎片数 " << sb->frags_per_group << endl;
cerr << "每组Inode数 " << sb->inodes_per_group << endl;
cerr << "上次挂载时间 " << sb->mtime << endl;
cerr << "上次写入超级块的时间 " << sb->wtime << endl;
cerr << "未进行检查的挂载次数 " << sb->mnt_count << endl;
cerr << "必须执行检查前的最大挂载次数 " << sb->max_mnt_count << endl;
cerr << "Magic " << sb->magic << endl;
cerr << "文件系统的状态 " << sb->state << endl;
cout << "组描述符表:" << endl;
cerr << endl << "组描述符表:" << endl;
for (EXT2_GD* gdt: gdt_list) {
cout << "块位图块号 " << gdt->get_gd()->block_bitmap << endl;
cout << "索引节点位图的块号 " << gdt->get_gd()->inode_bitmap << endl;
cout << "第一个索引节点表块的块号 " << gdt->get_gd()->inode_table << endl;
cout << "组中空闲块的个数 " << gdt->get_gd()->free_blocks_count << endl;
cout << "组中空闲索引节点的个数 " << gdt->get_gd()->free_inodes_count << endl;
cout << "组中目录的个数 " << gdt->get_gd()->used_dirs_count << endl;
cerr << "块位图块号 " << gdt->get_gd()->block_bitmap << endl;
cerr << "索引节点位图的块号 " << gdt->get_gd()->inode_bitmap << endl;
cerr << "第一个索引节点表块的块号 " << gdt->get_gd()->inode_table << endl;
cerr << "组中空闲块的个数 " << gdt->get_gd()->free_blocks_count << endl;
cerr << "组中空闲索引节点的个数 " << gdt->get_gd()->free_inodes_count << endl;
cerr << "组中目录的个数 " << gdt->get_gd()->used_dirs_count << endl;
cerr << endl;
}
}
@@ -57,16 +58,26 @@ int EXT2_FS::block_to_pos(int block) {
int EXT2_FS::inode_to_pos(int inode_n) {
inode_n--;
int max_inodes_in_group = 8 * block_size;
auto it = gdt_list.begin();
while (it != gdt_list.end() && inode_n > max_inodes_in_group) {
inode_n -= max_inodes_in_group;
it++;
}
_error(it == gdt_list.end());
_error(inode_n > max_inodes_in_group);
_si(inode_n);
_si(sb->inodes_per_group);
int group_n = inode_n / sb->inodes_per_group;
inode_n = inode_n % sb->inodes_per_group;
int ans = block_to_pos(gdt_list[group_n]->get_gd()->inode_table) + inode_n * sizeof(Inode);
_sx(ans);
return ans;
return block_to_pos((*it)->get_gd()->inode_table) + inode_n * sizeof(Inode);
// inode_n--;
// int max_inodes_in_group = 8 * block_size;
// auto it = gdt_list.begin();
// while (it != gdt_list.end() && inode_n > max_inodes_in_group) {
// inode_n -= max_inodes_in_group;
// it++;
// }
// _error(it == gdt_list.end());
// _error(inode_n > max_inodes_in_group);
// return block_to_pos((*it)->get_gd()->inode_table) + inode_n * sizeof(Inode);
}
void EXT2_FS::mount() {
@@ -87,8 +98,8 @@ void EXT2_FS::mount() {
block_size = 1024 * (1 << sb->log_block_size);
// dev->seek(block_size + 1024); // 指向GDT
_u32 read_pos = block_size + 1024;
group_cnt = 8 * sb->blocks_count / sb->blocks_per_group;
for (int i = 0; i < group_cnt; i++) {
group_cnt = sb->inodes_count / sb->inodes_per_group;
for (_u32 i = 0; i < group_cnt; i++) {
GroupDescriptor* gtp = new GroupDescriptor();
dev->read(sb_buf, read_pos, sizeof(GroupDescriptor));
memmove(gtp, sb_buf.data, sizeof(GroupDescriptor));
@@ -107,7 +118,7 @@ void EXT2_FS::mount() {
// dev->read(sb_buf, sizeof(Inode));
// Inode* root_inode = new Inode();
// memmove(root_inode, sb_buf.data, sizeof(Inode));
_u32 root_inode_pos = gdt_list.front()->get_gd()->inode_table;
// _u32 root_inode_pos = gdt_list.front()->get_gd()->inode_table;
EXT2_DEntry* ext2_entry = new EXT2_DEntry(this, nullptr, 2, VFS::Directory, "/");
root = ext2_entry;
// ext2_entry->inflate();
@@ -172,17 +183,17 @@ void EXT2_FS::write_super() {
_u32 super_pos = 1; // super block
MM::Buf buf(sizeof(SuperBlock));
memcpy(buf.data, sb, sizeof(SuperBlock));
for (EXT2_GD *x: gdt_list) {
for (size_t i = 0; i < gdt_list.size(); i++) {
dev->write(buf, block_to_pos(super_pos), sizeof(SuperBlock));
super_pos += sb->blocks_per_group;
}
_d_end();
}
void EXT2_FS::write_gdt() {
_u32 super_pos = 2; // 第一个组描述符表位置
MM::Buf buf(gdt_list.size() * sizeof(GroupDescriptor));
_u32 s_pos = 0;
_pos();
for (EXT2_GD *x: gdt_list) {
memcpy(buf.data + s_pos, x->get_gd(), sizeof(GroupDescriptor));
@@ -190,11 +201,11 @@ void EXT2_FS::write_gdt() {
x->write_inode_bitmap();
x->write_block_bitmap();
}
_pos();
for (EXT2_GD *x: gdt_list) {
for (size_t i = 0; i < gdt_list.size(); i++) {
dev->write(buf, block_to_pos(super_pos), sizeof(GroupDescriptor));
super_pos += sb->blocks_per_group;
}
_d_end();
}
EXT2_GD *EXT2_FS::get_inode_group(_u32 inode_n) {
@@ -211,4 +222,5 @@ EXT2_FS::~EXT2_FS() {
delete x;
}
delete sb;
delete root;
}
+2 -2
View File
@@ -49,7 +49,7 @@ _u32 EXT2_GD::alloc_inode() {
if (gd->free_inodes_count == 0)
return 0;
get_inode_bitmap();
for (int i = 0; i < fs->block_size; i++) {
for (_u32 i = 0; i < fs->block_size; i++) {
if (inode_bitmap[i] != (_u8)0xff) {
int t = lowest_0(inode_bitmap[i]);
_set_bit(inode_bitmap[i], t);
@@ -65,7 +65,7 @@ _u32 EXT2_GD::alloc_block() {
if (gd->free_blocks_count == 0)
return 0;
get_block_bitmap();
for (int i = 0; i < fs->block_size; i++) {
for (_u32 i = 0; i < fs->block_size; i++) {
if (block_bitmap[i] != (_u8)0xff) {
int t = lowest_0(block_bitmap[i]);
_set_bit(block_bitmap[i], t);
+58 -29
View File
@@ -4,30 +4,31 @@
#include "mm/buf.h"
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace EXT2;
void EXT2_Inode::print() {
using namespace std;
cout << "\nInode: " << inode_n << endl;
cout << "文件类型和访问权限 " << i->mode << mode_to_str(i->mode) << endl;
cout << "拥有者 " << i->uid << endl;
cout << "文件长度 " << i->size << endl;
cout << "最后一次访问时间 " << i->atime << endl;
cout << "索引节点最后改变的时间 " << i->ctime << endl;
cout << "文件内容最后改变的时间 " << i->mtime << endl;
cout << "文件删除的时间 " << i->dtime << endl;
cout << "组id " << i->gid << endl;
cout << "硬链接计数器 " << i->links_count << endl;
cout << "文件的数据块数 " << blocks << endl;
cout << "文件标志 " << i->flags << endl;
cout << "文件版本 " << i->generation << endl;
cout << "文件访问控制列表 " << i->file_acl << endl;
cout << "目录访问控制列表 " << i->dir_acl << endl;
cout << "片地址 " << i->faddr << endl;
cout << "数据块指针 ";
for (int j = 0; j < blocks;j++)
cout << i->block[j] << " ";
cout << endl;
cerr << "\nInode: " << inode_n << endl;
cerr << "文件类型和访问权限 " << i->mode << mode_to_str(i->mode) << endl;
cerr << "拥有者 " << i->uid << endl;
cerr << "文件长度 " << i->size << endl;
cerr << "最后一次访问时间 " << i->atime << endl;
cerr << "索引节点最后改变的时间 " << i->ctime << endl;
cerr << "文件内容最后改变的时间 " << i->mtime << endl;
cerr << "文件删除的时间 " << i->dtime << endl;
cerr << "组id " << i->gid << endl;
cerr << "硬链接计数器 " << i->links_count << endl;
cerr << "文件的数据块数 " << blocks << endl;
cerr << "文件标志 " << i->flags << endl;
cerr << "文件版本 " << i->generation << endl;
cerr << "文件访问控制列表 " << i->file_acl << endl;
cerr << "目录访问控制列表 " << i->dir_acl << endl;
cerr << "片地址 " << i->faddr << endl;
cerr << "数据块指针 ";
for (_u32 j = 0; j < min(blocks, (_u32)15); j++)
cerr << i->block[j] << " ";
cerr << endl;
}
EXT2_Inode::EXT2_Inode(EXT2_FS *fs, _u32 n, EXT2::Inode *i): VFS::Inode(fs) {
@@ -50,7 +51,7 @@ EXT2_Inode::EXT2_Inode(EXT2_FS *fs, _u32 n, EXT2::Inode *i): VFS::Inode(fs) {
ext2_fs = fs;
blocks = i->blocks / (ext2_fs->block_size / 512);
bytes = size % ext2_fs->block_size;
for (int t = blocks; t < N_BLOCKS; t++) {
for (int t = blocks; !S_ISLNK(mode) && t < N_BLOCKS; t++) {
i->block[t] = 0;
}
}
@@ -101,6 +102,14 @@ void EXT2_Inode::write_inode() {
MM::Buf buf(sizeof(EXT2::Inode));
i->blocks = blocks * (ext2_fs->block_size / 512);
i->size = size;
_si(size);
i->mode = mode;
i->links_count=nlink;
i->uid = uid;
i->gid = gid;
i->atime = atime;
i->mtime = mtime;
i->ctime = ctime;
memcpy(buf.data, i, sizeof(EXT2::Inode));
// _sa(buf.data, sizeof(EXT2::Inode));
ext2_fs->dev->write(buf, inode_pos, sizeof(EXT2::Inode));
@@ -108,9 +117,12 @@ void EXT2_Inode::write_inode() {
// _sa(buf.data, sizeof(EXT2::Inode));
// ext2_fs->dev->read(buf, inode_pos, sizeof(EXT2::Inode));
// _sa(buf.data, sizeof(EXT2::Inode));
_dbg_log("finish.");
}
void EXT2_Inode::dirty() {
write_inode();
}
EXT2_Inode::iterator EXT2_Inode::begin() {
return iterator::getInstance(this, 0);
@@ -120,6 +132,12 @@ EXT2_Inode::iterator EXT2_Inode::end() {
return iterator::getInstance(this, blocks);
}
EXT2_Inode::iterator EXT2_Inode::alloc_iter() {
auto a = iterator::getInstance(this, blocks);
a.auto_alloc = true;
return a;
}
EXT2_Inode::iterator EXT2_Inode::iter_at(_u32 i) {
return iterator::getInstance(this, i);
}
@@ -151,7 +169,6 @@ EXT2_Inode::iterator::iterator(EXT2_Inode* i) {
EXT2_Inode::iterator EXT2_Inode::iterator::getInstance(EXT2_Inode *i, _u32 blocks) {
EXT2_Inode::iterator it(i);
_dbg_log("get instance %d", blocks);
it.index_cnt = blocks; // 最大值
if (blocks == 0) {
it.level = 0;
@@ -179,6 +196,9 @@ EXT2_Inode::iterator EXT2_Inode::iterator::getInstance(EXT2_Inode *i, _u32 block
} else {
_error(1);
}
_dbg_log("get instance %d, [%d, %d, %d, %d]",
blocks, it.indexs[0], it.indexs[1], it.indexs[2], it.indexs[3]);
return it;
}
@@ -197,6 +217,11 @@ void EXT2_Inode::iterator::load_buf(int t) {
_u32 new_block_pos = block_buf[t][indexs[t]];
if (block_buf[t + 1] == nullptr)
block_buf[t + 1] = new _u32[sub_blocks_in_block[level]];
_si(new_block_pos);
if (new_block_pos == 0 && !auto_alloc) {
_dbg_log("Reach iter end but not set auto alloc.");
return;
}
if (new_block_pos == 0) {
_dbg_log("auto alloc data block");
// 如果没有下一个数据块,则分配一个
@@ -204,19 +229,20 @@ void EXT2_Inode::iterator::load_buf(int t) {
block_buf[t][indexs[t]] = new_block_pos;
dirty[t] = true;
block_pos[t + 1] = new_block_pos;
memset(block_buf[t + 1], 0, sizeof(block_buf[t + 1])); // 新块数据清零
memset(block_buf[t + 1], 0, fs->block_size); // 新块数据清零
} else {
MM::Buf buf(fs->block_size);
fs->dev->read(buf, fs->block_to_pos(new_block_pos), fs->block_size);
memcpy(block_buf[t + 1], buf.data, sizeof(block_buf[t + 1]));
memcpy(block_buf[t + 1], buf.data, fs->block_size);
}
_sa(block_buf[t + 1], 1024);
t++;
}
}
void EXT2_Inode::iterator::write_back() {
_dbg_log("write back");
if (dirty[0]) {
_dbg_log("write back 0");
memcpy(inode->i->block, block_buf[0], sizeof(_u32) * EXT2::N_BLOCKS);
dirty[0] = false;
}
@@ -224,10 +250,11 @@ void EXT2_Inode::iterator::write_back() {
MM::Buf *buf=nullptr;
for (int t = 1; t < 4; t++) {
if (dirty[t]) {
_dbg_log("write back %d", t);
if (buf == nullptr)
buf = new MM::Buf(fs->block_size);
_u32 pos = fs->block_to_pos(block_pos[t]);
memmove(buf->data, block_buf[t], sizeof(block_buf[t]));
memmove(buf->data, block_buf[t], fs->block_size);
fs->dev->write(*buf, pos, fs->block_size);
dirty[t] = false;
}
@@ -244,6 +271,7 @@ EXT2_Inode::iterator& EXT2_Inode::iterator::operator++() {
index_cnt++;
indexs[level]++;
_si(indexs[level]);
_si(level);
if (indexs[level] >= sub_blocks_in_block[level]) {
// 小升级!
int t = level;
@@ -286,10 +314,11 @@ EXT2_Inode::iterator& EXT2_Inode::iterator::operator--() {
bool
EXT2_Inode::iterator::operator==(const iterator& ano) const {
// return index_cnt == ano.index_cnt;
_error(inode != ano.inode);
if (ano.index_cnt != index_cnt || ano.level != level)
return false;
for (_u32 i = 0; i < level; i++) {
for (int i = 0; i < level; i++) {
if (indexs[i] != ano.indexs[i])
return false;
}
@@ -305,7 +334,7 @@ int EXT2_Inode::iterator::operator*() {
if (block_buf[level] == nullptr)
load_buf(0);
int ans = block_buf[level][indexs[level]];
if (ans == 0) {
if (ans == 0 && auto_alloc) {
_dbg_log("auto alloc data block");
ans = inode->ext2_fs->alloc_block();
block_buf[level][indexs[level]] = ans;
+4
View File
@@ -40,6 +40,8 @@ namespace EXT2
void load_buf(int from=0);
void write_back(); // 写回磁盘
bool auto_alloc = false; // 自动分配空间
iterator(EXT2_Inode* i);
public:
@@ -73,9 +75,11 @@ namespace EXT2
_u32 nth_block(_u32 n);
void write_inode();
void dirty();
iterator begin();
iterator end();
iterator alloc_iter();
iterator iter_at(_u32 i);
~EXT2_Inode();
View File
+44
View File
@@ -0,0 +1,44 @@
#pragma once
#include "vfs.h"
#include <list>
#include <string>
#include <iostream>
#include <algorithm>
struct MountedFS {
VFS::FS *fs = nullptr;
std::string point; // 挂载点
MountedFS(VFS::FS *vfs, const std::string& p): fs(vfs), point(p) {}
};
class FSManager {
private:
std::list<MountedFS> fs_list;
VFS::DEntry *root = nullptr;
public:
void mount(VFS::FS *vfs, const std::string& p) {
for (auto &x: fs_list) {
if (x.point == p) {
std::cout << p << " is already mounted by another fs" << std::endl;
}
}
fs_list.emplace_back(vfs, p);
if (p == "/")
root = vfs->root;
}
void umount(const std::string& p) {
if (p == "/") {
std::cout << "Cannot umount root." << std::endl;
return;
}
auto res = std::find_if(fs_list.begin(), fs_list.end(), [&p](const MountedFS& x){x.point == p;});
if (res == fs_list.end()) {
std::cout << "No any filesystem mounted on " << p << std::endl;
return;
}
fs_list.erase(res);
delete res->fs;
}
};
+79
View File
@@ -0,0 +1,79 @@
#include "real_file.h"
#include "delog/delog.h"
#include <cstring>
#include <sys/stat.h>
using namespace RealFile;
RealFile::RealFile::RealFile(const char* name) {
int ss = strlen(name);
fname = new char[ss];
strcpy(fname, name);
struct stat statbuf;
stat(fname, &statbuf);
size=statbuf.st_size;
_si(statbuf.st_nlink);
this->open("rb");
_dbg_log("open file %s size %d", name, size);
buf = new char[size];
fread(buf, size, 1, fp);
fclose(fp);
fp = nullptr;
}
RealFile::RealFile::~RealFile() {
delete fname;
}
int RealFile::RealFile::tell() {
if (fp != nullptr)
return pos;
return -1;
}
int RealFile::RealFile::seek(int pos, int whence) {
switch (whence) {
case SEEK_SET:
return (this->pos = pos);
case SEEK_CUR:
return (this->pos = this->pos + pos);
case SEEK_END:
return (this->pos = size + pos);
}
return -1;
}
int RealFile::RealFile::read(char *p, int size) {
memmove(p, buf + pos, size);
return size;
}
int RealFile::RealFile::write(const char *p, int size) {
memmove(buf + pos, p, size);
return size;
}
void RealFile::RealFile::open(const char* mode) {
_pos();
_ss(fname);
_ss(mode);
fp = fopen(fname, mode);
if (fp == nullptr) {
perror(__func__);
exit(1);
}
pos = 0;
}
void RealFile::RealFile::close() {
_dbg_log("save file");
open("wb");
fwrite(buf, size, 1, fp);
fclose(fp);
fp = nullptr;
// VFS::File::close();
}
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include "fs/vfs.h"
#include "types.h"
#include <cstdio>
namespace RealFile {
class RealFile: public VFS::File {
FILE *fp = nullptr;
char *fname = nullptr;
char *buf;
int pos;
public:
RealFile(const char* name);
~RealFile();
int tell();
int seek(int pos, int whence);
int read(char*, int size);
int write(const char*, int size);
void open(const char* mode);
void close();
};
}
+231 -83
View File
@@ -8,59 +8,37 @@
#include "dev/mock_disk.h"
#include "delog/delog.h"
#include "stat.h"
std::vector<std::string> split(const std::string& s, char sp) {
int i = 0, l = 0;
std::vector<std::string> res;
while (i < s.size()) {
if (s[i] == sp) {
if (i != l)
res.push_back(s.substr(l, i - l));
l = i + 1;
}
i++;
}
if (i != l)
res.push_back(s.substr(l, i - l));
return res;
}
VFS::NameI *parse_path(const std::string path) {
using namespace VFS;
NameI *ans = nullptr, *prev;
if (path[0] == '/')
ans = prev = new NameI("/");
else
ans = prev = new NameI(".");
printf("%x %x\n", ans->prev, ans->next);
std::vector<std::string> sp = split(path, '/');
for (const auto& x: sp) {
// printf("++++++++++++++++++++++++++++++++++++\n");
_ss(x.c_str());
if (x.size() == 0)
continue;
if (x == ".")
continue;
if (ans == nullptr) {
ans = new NameI(x);
prev = ans;
} else {
prev = new NameI(x, prev);
}
}
_pos();
return ans;
error:
delete ans;
return nullptr;
}
#include "delog/common.h"
#include "fs/real_file/real_file.h"
static int uid, gid;
struct OP {
const char *name;
VFS::DEntry* (*op)(VFS::DEntry *, const std::vector<std::string>&);
};
// 2 r 1 w 0 x
bool check(VFS::Inode *i, int pre) {
if (uid == 0)
return true;
if (i->uid == uid) {
return i->mode & (0100 << pre);
}
if (i->gid == gid) {
return i->mode & (0010 << pre);
}
return i->mode & (0001 << pre);
}
#define chk_r(i) check(i, 2)
#define chk_w(i) check(i, 1)
#define chk_x(i) check(i, 0)
#define pre(f, i) do {\
if (!f(i)) {\
std::cout << "Premission denine." << std::endl;\
return cwd;\
}\
} while(0)
static void ls_one(VFS::DEntry *x, bool l) {
using namespace std;
@@ -73,6 +51,9 @@ static void ls_one(VFS::DEntry *x, bool l) {
case VFS::RegularFile:
cout << "-";
break;
case VFS::SymbolLink:
cout << "l";
break;
default:
cout << "?";
break;
@@ -86,19 +67,25 @@ static void ls_one(VFS::DEntry *x, bool l) {
VFS::DEntry *ls(VFS::DEntry *cwd, const std::vector<std::string>& cmdd) {
using namespace std;
VFS::NameI *target = parse_path(cmdd[cmdd.size() - 1]);
VFS::NameI *target = VFS::NameI::from_str(cmdd[cmdd.size() - 1]);
auto t = cwd->get_child(target);
// t = cwd;
if (t == nullptr) {
cout << "No such file or directory. " << cmdd[cmdd.size() - 1] << endl;
return cwd;
}
t->inflate();
if (!chk_r(t->inode)) {
std::cout << "Premission denine." << std::endl;
return cwd;
}
if (t->type == VFS::Directory) {
t->load_children();
for (auto& x: t->children) {
ls_one(x, cmdd.size() == 2 && cmdd[1] == "-l");
ls_one(x, cmdd[1] == "-l");
}
} else {
ls_one(t, cmdd.size() == 2 && cmdd[1] == "-l");
ls_one(t, cmdd[1] == "-l");
}
cout << endl;
delete target;
@@ -111,7 +98,7 @@ VFS::DEntry *cd(VFS::DEntry *cwd,const std::vector<std::string>& cmdd) {
return cwd;
if (cmdd[cmdd.size() - 1] == "..")
return cwd->parent;
VFS::NameI *target = parse_path(cmdd[cmdd.size() - 1]);
VFS::NameI *target = VFS::NameI::from_str(cmdd[cmdd.size() - 1]);
auto ans = cwd->get_child(target);
if (ans == nullptr) {
cout << "No such directory " << cmdd[1] << endl;
@@ -126,7 +113,7 @@ VFS::DEntry *cd(VFS::DEntry *cwd,const std::vector<std::string>& cmdd) {
VFS::DEntry *mkdir(VFS::DEntry *cwd,const std::vector<std::string>& cmdd) {
std::string name;
VFS::NameI *target = parse_path(cmdd[cmdd.size() - 1]);
VFS::NameI *target = VFS::NameI::from_str(cmdd[cmdd.size() - 1]);
VFS::DEntry *d = cwd->get_path(target, &name);
if (d == nullptr) {
@@ -139,7 +126,7 @@ VFS::DEntry *mkdir(VFS::DEntry *cwd,const std::vector<std::string>& cmdd) {
VFS::DEntry *touch(VFS::DEntry *cwd,const std::vector<std::string>& cmdd) {
std::string name;
VFS::NameI *target = parse_path(cmdd[cmdd.size() - 1]);
VFS::NameI *target = VFS::NameI::from_str(cmdd[cmdd.size() - 1]);
VFS::DEntry *d = cwd->get_path(target, &name);
if (d == nullptr) {
@@ -151,8 +138,10 @@ VFS::DEntry *touch(VFS::DEntry *cwd,const std::vector<std::string>& cmdd) {
}
VFS::DEntry *cat(VFS::DEntry *cwd,const std::vector<std::string>& cmdd) {
VFS::NameI *target = parse_path(cmdd[cmdd.size() - 1]);
VFS::NameI *target = VFS::NameI::from_str(cmdd[cmdd.size() - 1]);
auto ans = cwd->get_child(target);
while (ans->type == VFS::SymbolLink)
ans = ans->follow();
VFS::File *fe = ans->open();
if (fe == nullptr)
@@ -163,7 +152,7 @@ VFS::DEntry *cat(VFS::DEntry *cwd,const std::vector<std::string>& cmdd) {
} else {
_si(fe->size);
char *buf = new char[fe->size];
fe->read((_u8*)buf, fe->size);
fe->read(buf, fe->size);
fwrite(buf, fe->size, 1, stdout);
putchar('\n');
fflush(stdout);
@@ -176,7 +165,7 @@ VFS::DEntry *cat(VFS::DEntry *cwd,const std::vector<std::string>& cmdd) {
VFS::DEntry *rm(VFS::DEntry *cwd,const std::vector<std::string>& cmdd) {
VFS::DEntry *d;
VFS::NameI *target = parse_path(cmdd[cmdd.size() - 1]);
VFS::NameI *target = VFS::NameI::from_str(cmdd[cmdd.size() - 1]);
VFS::DEntry *to_del = cwd->get_child(target, &d);
if (to_del == nullptr) {
std::cout << "No such file " << cmdd[cmdd.size() - 1] << std::endl;
@@ -195,7 +184,7 @@ VFS::DEntry *rm(VFS::DEntry *cwd,const std::vector<std::string>& cmdd) {
VFS::DEntry *link(VFS::DEntry *cwd, const std::vector<std::string>& cmdd) {
using namespace VFS;
VFS::NameI *from = parse_path(cmdd[cmdd.size() - 2]);
VFS::NameI *from = VFS::NameI::from_str(cmdd[cmdd.size() - 2]);
DEntry *fe = cwd->get_child(from);
if (fe == nullptr) {
@@ -204,7 +193,7 @@ VFS::DEntry *link(VFS::DEntry *cwd, const std::vector<std::string>& cmdd) {
}
DEntry *te;
std::string s;
NameI *target = parse_path(cmdd[cmdd.size() - 1]);
NameI *target = VFS::NameI::from_str(cmdd[cmdd.size() - 1]);
if ((te = cwd->get_path(target, &s)) == nullptr) {
_log_info("%s is already exists.", cmdd[2].c_str());
return cwd;
@@ -215,7 +204,7 @@ VFS::DEntry *link(VFS::DEntry *cwd, const std::vector<std::string>& cmdd) {
VFS::DEntry *mv(VFS::DEntry *cwd, const std::vector<std::string>& cmdd) {
using namespace VFS;
VFS::NameI *from = parse_path(cmdd[cmdd.size() - 2]);
VFS::NameI *from = VFS::NameI::from_str(cmdd[cmdd.size() - 2]);
DEntry *fe = cwd->get_child(from);
if (fe == nullptr) {
@@ -224,9 +213,9 @@ VFS::DEntry *mv(VFS::DEntry *cwd, const std::vector<std::string>& cmdd) {
}
DEntry *te;
std::string s;
NameI *target = parse_path(cmdd[cmdd.size() - 1]);
NameI *target = VFS::NameI::from_str(cmdd[cmdd.size() - 1]);
if ((te = cwd->get_path(target, &s)) == nullptr) {
_log_info("%s is already exists.", cmdd[2].c_str());
_log_info("%s is not exists.", cmdd[2].c_str());
return cwd;
}
fe->move(te, s);
@@ -235,7 +224,7 @@ VFS::DEntry *mv(VFS::DEntry *cwd, const std::vector<std::string>& cmdd) {
VFS::DEntry *cp(VFS::DEntry *cwd, const std::vector<std::string>& cmdd) {
using namespace VFS;
VFS::NameI *from = parse_path(cmdd[cmdd.size() - 2]);
VFS::NameI *from = VFS::NameI::from_str(cmdd[cmdd.size() - 2]);
DEntry *fe = cwd->get_child(from);
if (fe == nullptr) {
@@ -244,15 +233,133 @@ VFS::DEntry *cp(VFS::DEntry *cwd, const std::vector<std::string>& cmdd) {
}
DEntry *te;
std::string s;
NameI *target = parse_path(cmdd[cmdd.size() - 1]);
NameI *target = VFS::NameI::from_str(cmdd[cmdd.size() - 1]);
if ((te = cwd->get_path(target, &s)) == nullptr) {
_log_info("%s is already exists.", cmdd[2].c_str());
_log_info("%s is not exists.", cmdd[2].c_str());
return cwd;
}
fe->copy(te, s);
return cwd;
}
VFS::DEntry *symlink(VFS::DEntry *cwd, const std::vector<std::string>& cmdd) {
using namespace VFS;
VFS::NameI *from = VFS::NameI::from_str(cmdd[cmdd.size() - 2]);
DEntry *fe = cwd->get_child(from);
if (fe == nullptr) {
_log_info("%s is not exists.", cmdd[1].c_str());
return cwd;
}
DEntry *te;
std::string s;
NameI *target = VFS::NameI::from_str(cmdd[cmdd.size() - 1]);
if ((te = cwd->get_path(target, &s)) == nullptr) {
_log_info("%s is not exists.", cmdd[2].c_str());
return cwd;
}
te->symlink(fe, s);
return cwd;
}
VFS::DEntry *mount(VFS::DEntry *cwd, const std::vector<std::string>& cmdd) {
using namespace VFS;
NameI *fs = VFS::NameI::from_str(cmdd[cmdd.size() - 2]);
NameI *dir = VFS::NameI::from_str(cmdd[cmdd.size() - 1]);
DEntry *fs_e = cwd->get_child(fs);
DEntry *mnt_e = cwd->get_child(dir);
if (fs_e == nullptr) {
std::cout << "no such device " << cmdd[cmdd.size() - 2] << std::endl;
return cwd;
}
if (mnt_e == nullptr) {
std::cout << "no such diectory " << cmdd[cmdd.size() - 1] << std::endl;
return cwd;
}
File *f = fs_e->open();
Dev::BlockDevice *d = new Dev::MockDisk(*f);
FS* new_fs = new EXT2::EXT2_FS(d);
new_fs->mount();
new_fs->root->load_children();
new_fs->root->parent = mnt_e->parent;
// mnt_e->inode = new_fs->root->inode;
// mnt_e->children = new_fs->root->children;
new_fs->root->name = mnt_e->name;
mnt_e->parent->children.push_back(new_fs->root);
mnt_e->parent->children.remove(mnt_e);
return cwd;
}
VFS::DEntry *umount(VFS::DEntry *cwd, const std::vector<std::string>& cmdd) {
using namespace VFS;
NameI *dir = VFS::NameI::from_str(cmdd[cmdd.size() - 1]);
DEntry *mnt_e = cwd->get_child(dir);
if (mnt_e == nullptr) {
std::cout << "no such diectory " << cmdd[cmdd.size() - 1] << std::endl;
return cwd;
}
DEntry *t = mnt_e->parent;
t->children.clear();
t->load_children();
mnt_e->fs->dev->close();
delete mnt_e->fs;
return cwd;
}
VFS::DEntry *echo(VFS::DEntry *cwd, const std::vector<std::string>& cmdd) {
if (cmdd.size() != 4)
return cwd;
const std::string& text = cmdd[1];
VFS::NameI *fi = VFS::NameI::from_str(cmdd[cmdd.size() - 1]);
VFS::DEntry *file = cwd->get_child(fi);
if (file == nullptr) {
std::cout << "no such file " << cmdd[cmdd.size() - 1] << std::endl;
return cwd;
}
if (file->type != VFS::RegularFile) {
std::cout << cmdd[cmdd.size() - 1] << " is not a file." << std::endl;
return cwd;
}
VFS::File *f = file->open();
if (cmdd[2] == ">>") {
f->seek(0, SEEK_END);
} else {
f->seek(0, SEEK_SET);
}
f->write(text.c_str(), text.size());
f->close();
return cwd;
}
VFS::DEntry *chmod(VFS::DEntry *cwd, const std::vector<std::string>& cmdd) {
VFS::NameI *fi = VFS::NameI::from_str(cmdd[cmdd.size() - 1]);
VFS::DEntry *file = cwd->get_child(fi);
file->inflate();
pre(chk_w, file->inode);
int m = 0;
for (char x: cmdd[1]) {
m <<= 3;
m += x - '0';
}
file->inode->mode &= ~(0777);
file->inode->mode |= m;
file->inode->dirty();
return cwd;
}
VFS::DEntry *chown(VFS::DEntry *cwd, const std::vector<std::string>& cmdd) {
if (cmdd.size() != 4)
return cwd;
VFS::NameI *fi = VFS::NameI::from_str(cmdd[cmdd.size() - 1]);
VFS::DEntry *file = cwd->get_child(fi);
file->inflate();
pre(chk_w, file->inode);
file->inode->uid = stoi(cmdd[1]);
file->inode->gid = stoi(cmdd[2]);
file->inode->dirty();
return cwd;
}
OP ops[] = {
{"ls", ls},
{"cd", cd},
@@ -263,15 +370,63 @@ OP ops[] = {
{"link", link},
{"mv", mv},
{"cp", cp},
{"ln", symlink},
{"mount", mount},
{"umount", umount},
{"echo", echo},
{"chown", chown},
{"chmod", chmod},
{"unknown", nullptr}
};
struct User {
std::string uname;
int uid, gid;
std::string passwd;
User(std::vector<std::string> s) {
uname = s[0];
uid = stoi(s[1]);
gid = stoi(s[2]);
passwd = s[3];
// std::cout << uname << " " << uid << " " << gid << " " << passwd << std::endl;
}
};
void login(VFS::DEntry *root) {
auto de = root->get_child("passwd");
auto pass = de->open();
char buf[pass->size];
pass->read(buf, pass->size);
std::string s(buf, pass->size);
auto sp = split(s, '\n');
std::vector<User> uv;
for (auto x: sp) {
uv.emplace_back(split(x, ':'));
}
std::string buf2, buf1;
bool success = false;
do {
std::cout << "user: ";
std::cin >> buf2;
std::cout << "password: ";
std::cin >> buf1;
for (auto x: uv) {
if (x.uname == buf2 && x.passwd == buf1) {
uid = x.uid;
gid = x.gid;
success = true;
}
}
} while (!success);
}
#include <unistd.h>
int main(void) {
using namespace std;
Dev::BlockDevice *dev = new Dev::MockDisk();
dev->open("fs/ext2/fs");
RealFile::RealFile real_disk("fs/ext2/fs");
Dev::BlockDevice *dev = new Dev::MockDisk(real_disk);
EXT2::EXT2_FS *ext2_fs = new EXT2::EXT2_FS(dev);
VFS::FS *fs = ext2_fs;
cout << "System up." << endl;
@@ -281,9 +436,13 @@ int main(void) {
fs->mount();
cwd = fs->root;
login(cwd);
cout << "[umount]$ ";
cout << "/$ ";
while (getline(cin, cmd)) {
if (cmd.size() == 0)
continue;
vector<string> cmdd = split(cmd, ' ');
if (cmd == "mount") {
fs->mount();
@@ -292,7 +451,7 @@ int main(void) {
} else if (fs->status == VFS::FS_unmounted) {
cout << "Please mount fs first." << endl;
} else if (cmdd[0] == "exit") {
break;
break;
} else if (cmdd[0] == "dump") {
MM::Buf buf(1024);
if (cmdd[1] == "i")
@@ -310,10 +469,10 @@ int main(void) {
else {
VFS::NameI *path = nullptr;
if (cmdd.size() > 1) {
path = parse_path(cmdd[cmdd.size() - 1]);
path = VFS::NameI::from_str(cmdd[cmdd.size() - 1]);
} else {
cmdd.push_back(".");
path = parse_path(".");
path = VFS::NameI::from_str(".");
}
if (path == nullptr) {
cout << "Wrong path " << cmdd[cmdd.size() - 1] << endl;
@@ -325,18 +484,7 @@ int main(void) {
}
if (cwd != nullptr) {
std::stack<std::string> st;
VFS::DEntry *t = cwd;
while (t != t->parent) {
st.push(t->name);
t = t->parent;
}
cout << "/";
while (!st.empty()) {
cout << st.top() << "/";
st.pop();
}
cout << "$ ";
cout << cwd->printed_path() << "$ ";
} else
cout << "[umount]$ ";
}
+64
View File
@@ -1,6 +1,11 @@
#include "vfs.h"
#include "delog/delog.h"
#include "delog/common.h"
#include "stat.h"
#include <string>
#include <sstream>
#include <stack>
#include <vector>
using namespace VFS;
@@ -58,6 +63,21 @@ DEntry *DEntry::get_path(const NameI *namei, std::string* fname) {
return ans;
}
std::string DEntry::printed_path() {
std::stack<std::string> st;
std::stringstream ss;
VFS::DEntry *t = this;
while (t != t->parent) {
st.push(t->name);
t = t->parent;
}
while (!st.empty()) {
ss << "/" << st.top();
st.pop();
}
return ss.str();
}
File *DEntry::open(const std::string& name) {
auto a = get_child(name);
if (a == nullptr || a->type != RegularFile)
@@ -85,4 +105,48 @@ NameI::~NameI() {
prev->next = nullptr;
delete next;
delete prev;
}
void VFS::File::close() {
_dbg_log("delete this");
delete this; // 恶魔操作
}
VFS::NameI *VFS::NameI::from_str(const std::string& path) {
using namespace VFS;
NameI *ans = nullptr, *prev;
if (path[0] == '/')
ans = prev = new NameI("/");
else
ans = prev = new NameI(".");
// printf("%x %x\n", ans->prev, ans->next);
std::vector<std::string> sp = split(path, '/');
for (const auto& x: sp) {
// printf("++++++++++++++++++++++++++++++++++++\n");
_ss(x.c_str());
if (x.size() == 0)
continue;
if (x == ".")
continue;
if (ans == nullptr) {
ans = new NameI(x);
prev = ans;
} else {
prev = new NameI(x, prev);
}
}
_pos();
return ans;
}
_u8 VFS::mode_to_type(_u8 mode) {
if(S_ISLNK(mode)) return VFS::SymbolLink;
if(S_ISREG(mode)) return VFS::RegularFile;
if(S_ISDIR(mode)) return VFS::Directory;
if(S_ISCHR(mode)) return VFS::CharacterDevice;
if(S_ISBLK(mode)) return VFS::BlockDevice;
if(S_ISFIFO(mode)) return VFS::NamedPipe;
if(S_ISSOCK(mode)) return VFS::SymbolLink;
return Unknown;
}
+34 -15
View File
@@ -30,6 +30,7 @@ namespace VFS
class Inode;
class FS;
class File;
class DEntry;
/**
* NAMEi
@@ -38,7 +39,10 @@ namespace VFS
public:
std::string name;
NameI *next=nullptr, *prev=nullptr;
NameI(const std::string name, NameI *p=nullptr);
static NameI *from_str(const std::string &);
~NameI();
};
@@ -47,8 +51,8 @@ namespace VFS
*/
class DEntry {
private:
virtual File* get_file()=0;
protected:
virtual File* get_file()=0;
public:
FS* fs;
_u32 inode_n; // inode编号,懒加载
@@ -83,11 +87,20 @@ namespace VFS
File *open();
// 把自己复制到另一个文件夹中,新文件夹中文件的Entry
virtual VFS::DEntry *copy(DEntry *dir, const std::string& new_name="")=0;
// 在当前文件夹下创建另一个文件file的符号链接
virtual VFS::DEntry *symlink(DEntry *file, const std::string& new_name="")=0;
// 找到一个符号链接指向的文件
virtual VFS::DEntry *follow()=0;
File *open(const std::string& name);
DEntry* get_child(const std::string& name);
DEntry* get_child(const NameI *namei, DEntry **path=nullptr);
DEntry *get_path(const NameI *namei, std::string* fname=nullptr);
std::string printed_path();
virtual ~DEntry() {}
};
enum {
@@ -97,7 +110,7 @@ namespace VFS
class FS {
public:
Dev::BlockDevice* dev; // 设备
Dev::BlockDevice* dev=nullptr; // 设备
// _u32 flag; // 安装标志
_u32 magic; // 文件系统标志
@@ -132,12 +145,12 @@ namespace VFS
_u8 sock; // 如果文件是一个socket则为0
int lock; // 自旋锁
FS* fs;
FS* fs=nullptr;
public:
Inode(FS* fs1):fs(fs1), dev(fs1->dev) {}
void create(DEntry*, int mode); // 为与目录项相关联的普通文件创建一个索引节点
Inode(FS* fs1):dev(fs1->dev), fs(fs1) {}
// 将Inode标记为脏,找时机写回设备
virtual void dirty()=0;
virtual ~Inode() {}
};
@@ -146,14 +159,20 @@ namespace VFS
*/
class File {
public:
_u32 pos;
_u32 size;
_u8 type;
_u8 open_mode;
virtual _u32 tell()=0;
virtual _u32 seek(int pos, int whence)=0;
virtual _u32 read(_u8*, _u32 size)=0;
virtual _u32 write(_u8*, _u32 size)=0;
int pos;
int size;
int type;
int open_mode;
virtual int tell()=0;
virtual int seek(int pos, int whence)=0;
virtual int read(char*, int size)=0;
virtual int write(const char*, int size)=0;
virtual void close();
virtual ~File() {}
};
_u8 mode_to_type(_u8 mode);
}; // namespace VFS
+6
View File
@@ -7,6 +7,12 @@
#include <list>
#include <string>
/**
* !!!!!!!!!!!!!!
* !这个文件没有用!
* !!!!!!!!!!!!!!
*/
namespace VFS
{
class Denty {
+1 -1
View File
@@ -12,7 +12,7 @@
#define _lshf(a, n) ((a) >> (n))
#define _Lclr(a, n) ((a) & (~(_BITS_MASK(n))))
#define _Hclr(a, n) _rshf(_lshf(a, n), n)
#define _LNclr(a, n) ((a & (_BITS_MASK(n))))
#define _LNclr(a, n) (((a) & (_BITS_MASK(n))))
#include "types.h"
+3 -1
View File
@@ -14,7 +14,9 @@ INC_FLAG = $(addprefix -I, $(INC_PATH))
DEFINES = DEBUG
DEF_FLAG = $(addprefix -D, $(DEFINES))
CC_FLAG = $(INC_FLAG) $(DEF_FLAG)
OTH_FLAG = -Werror -Wall
CC_FLAG = $(INC_FLAG) $(DEF_FLAG) $(OTH_FLAG)
# MAIN_NAME = config/test_config
# OBJ_FILE= $(addsuffix .o, $(addprefix $(OBJ_PATH)/, $(SRC_NAME)))