From cd65bd626a0928569f4027ae55d3b82007d2fde3 Mon Sep 17 00:00:00 2001 From: w-mj Date: Wed, 19 Jun 2019 21:03:17 +0800 Subject: [PATCH] surfing the directory; --- fs/ext2/ext2_fs.cpp | 48 ++++++++++++++++++++-------- fs/ext2/ext2_fs.h | 13 +++++--- fs/test_fs.cpp | 76 +++++++++++++++++++++++++++++++++++++++------ 3 files changed, 111 insertions(+), 26 deletions(-) diff --git a/fs/ext2/ext2_fs.cpp b/fs/ext2/ext2_fs.cpp index aedc2be..2a2a564 100644 --- a/fs/ext2/ext2_fs.cpp +++ b/fs/ext2/ext2_fs.cpp @@ -47,9 +47,10 @@ void EXT2_FS::printFS() { } } -void EXT2_FS::printInode(Inode* i) { +void EXT2_Inode::print() { + using namespace std; - cout << "\nInode:" << endl; + cout << "\nInode: " << inode_n << endl; cout << "文件类型和访问权限 " << i->mode << mode_to_str(i->mode) << endl; cout << "拥有者 " << i->uid << endl; cout << "文件长度 " << i->size << endl; @@ -76,6 +77,19 @@ int EXT2_FS::block_to_pos(int block) { return (block - 1) * block_size + 1024; } +int EXT2_FS::inode_to_pos(int 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)->inode_table) + inode_n * sizeof(Inode); +} + void EXT2_FS::mount() { sb = new SuperBlock(); dev->seek(1024); // 跳过引导块 @@ -113,15 +127,15 @@ 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 = block_to_pos(gdt_list.front()->inode_table) + sizeof(Inode); + _u32 root_inode_pos = gdt_list.front()->inode_table; EXT2_DEntry* ext2_entry; - ext2_entry = new EXT2_DEntry(this, nullptr, root_inode_pos, VFS::Directory, "/"); + ext2_entry = new EXT2_DEntry(this, nullptr, 1, VFS::Directory, "/"); root = ext2_entry; // ext2_entry->inflate(); // ext2_entry->load_children(); // _sa(sb_buf.data, 1024); - //printFS(); + printFS(); //printInode(ext2_entry->ext2_inode->i); status = VFS::FS_mounted; } @@ -133,7 +147,7 @@ EXT2_FS::~EXT2_FS() { delete sb; } -EXT2_Inode::EXT2_Inode(EXT2_FS *fs, EXT2::Inode *i): VFS::Inode(fs) { +EXT2_Inode::EXT2_Inode(EXT2_FS *fs, _u32 n, EXT2::Inode *i): VFS::Inode(fs) { this->i = i; ino = 0; counter = 0; @@ -151,6 +165,7 @@ EXT2_Inode::EXT2_Inode(EXT2_FS *fs, EXT2::Inode *i): VFS::Inode(fs) { blocks = i->blocks; bytes = 0; sock = 1; + inode_n = n; } EXT2_DEntry::EXT2_DEntry(EXT2_FS* fs1, VFS::DEntry* parent1, @@ -166,9 +181,9 @@ EXT2_DEntry::EXT2_DEntry(EXT2_FS* fs1, VFS::DEntry* parent1, } void EXT2_DEntry::load_children() { - if (ext2_inode == nullptr || sync == 1) { - inflate(); - } + if (ext2_inode != nullptr && sync == 0) + return ; + inflate(); _log_info("load children"); _error(ext2_inode == nullptr); @@ -185,6 +200,8 @@ void EXT2_DEntry::load_children() { _u32 s_pos = 0; _u32 next_length = 12; DirEntry *temp_str = new DirEntry(); + for (auto x: children) + delete x; children.clear(); while (true) { // _sa(buf.data + s_pos, 20); @@ -192,7 +209,7 @@ void EXT2_DEntry::load_children() { if (temp_str->rec_len == 0) break; EXT2_DEntry *sub = new EXT2_DEntry(ext2_fs, this, - temp_str->inode, temp_str->file_type, + temp_str->inode - 1, temp_str->file_type, std::string((char*)temp_str->name, temp_str->name_len)); children.push_back(sub); // std::cout << sub->name << " " << sub->inode_n << std::endl; @@ -206,12 +223,13 @@ void EXT2_DEntry::inflate() { _log_info("inflate"); EXT2::Inode* disk_inode = new Inode(); MM::Buf buf(sizeof(Inode)); - _u32 inode_pos = inode_n; - // _si(inode_pos); + _u32 inode_pos = ext2_fs->inode_to_pos(inode_n); + _si(inode_pos); fs->dev->seek(inode_pos); fs->dev->read(buf, sizeof(Inode)); memcpy(disk_inode, buf.data, sizeof(Inode)); - ext2_inode = new EXT2_Inode(ext2_fs, disk_inode); + ext2_inode = new EXT2_Inode(ext2_fs, inode_n, disk_inode); + ext2_inode->print(); inode = ext2_inode; sync = 0; } @@ -219,4 +237,8 @@ void EXT2_DEntry::inflate() { EXT2_DEntry::~EXT2_DEntry() { delete inode; +} + +EXT2_Inode::~EXT2_Inode() { + delete i; } \ No newline at end of file diff --git a/fs/ext2/ext2_fs.h b/fs/ext2/ext2_fs.h index 9484794..7b024ae 100644 --- a/fs/ext2/ext2_fs.h +++ b/fs/ext2/ext2_fs.h @@ -8,13 +8,15 @@ namespace EXT2 { class EXT2_FS: public VFS::FS { - std::list gdt_list; - SuperBlock* sb; void printFS(); void printInode(Inode*); public: int block_to_pos(int block); + int inode_to_pos(int inode_n); + + SuperBlock* sb; + std::list gdt_list; _u32 block_size; EXT2_FS(Dev::BlockDevice* dev); @@ -24,9 +26,12 @@ public: class EXT2_Inode: public VFS::Inode { public: - EXT2_Inode(EXT2_FS*, EXT2::Inode*); + EXT2_Inode(EXT2_FS*, _u32 n, EXT2::Inode*); + _u32 inode_n; EXT2::Inode* i; - void print_Inode(); + void print(); + + ~EXT2_Inode(); }; diff --git a/fs/test_fs.cpp b/fs/test_fs.cpp index 7befbbf..85d4598 100644 --- a/fs/test_fs.cpp +++ b/fs/test_fs.cpp @@ -1,17 +1,70 @@ #include -#include +#include +#include #include "ext2/ext2_fs.h" #include "dev/block_dev.h" #include "dev/mock_disk.h" -void ls(VFS::DEntry *cwd) { +std::vector split(const std::string& s, char sp) { + int i = 0, l = 0; + std::vector 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; +} + +void ls(VFS::DEntry *cwd, std::vector cmdd) { using namespace std; + cwd->load_children(); for (auto& x: cwd->children) { - cout << x->name << " "; + if (cmdd.size() == 2 && cmdd[1] == "l") + cout << x->name << " " << x->inode_n << endl; + else + cout << x->name << " "; } cout << endl; } +VFS::DEntry *cd(VFS::DEntry *cwd, const std::vector& cmdd) { + using namespace std; + cwd->load_children(); + list::iterator it = cwd->children.begin(); + VFS::DEntry *ans = cwd; + if (cmdd[1] == ".") + ; + else if (cmdd[1] == "..") { + + if (cwd->parent != nullptr) + ans = cwd->parent; + } else { + while(it != cwd->children.end()) { + if (cmdd[1] == (*it)->name) { + break; + } + it++; + } + if (it == cwd->children.end()) { + cout << "No such directory " << cmdd[1] << endl; + } else { + if ((*it)->type != VFS::Directory) { + cout << cmdd[1] << " is not a directory." << endl; + } + ans = *it; + } + } + // if (cwd != ans) + // delete cwd; + return ans; +} + int main(void) { using namespace std; @@ -23,19 +76,24 @@ int main(void) { string cmd; VFS::DEntry *cwd = nullptr; - cout << "$ "; + cout << "[umount]$ "; while (getline(cin, cmd)) { + vector cmdd = split(cmd, ' '); if (cmd == "mount") { fs->mount(); cwd = fs->root; cout << "mount disk at /" << endl; } else if (fs->status == VFS::FS_unmounted) { cout << "Please mount fs first." << endl; - } else if (cmd == "ls") { - cwd->load_children(); - ls(cwd); + } else if (cmdd[0] == "ls") { + ls(cwd, cmdd); + } else if (cmdd[0] == "cd") { + cwd = cd(cwd, cmdd); } - - cout << "$ "; + + if (cwd != nullptr) + cout << cwd->name << "$ "; + else + cout << "[umount]$ "; } } \ No newline at end of file