diff --git a/fs/ext2/ext2_dentry.cpp b/fs/ext2/ext2_dentry.cpp index 3f89a69..0970631 100644 --- a/fs/ext2/ext2_dentry.cpp +++ b/fs/ext2/ext2_dentry.cpp @@ -126,7 +126,7 @@ void EXT2_DEntry::write_children() { } } -void EXT2_DEntry::mkdir(const std::string& new_name) { +VFS::DEntry* EXT2_DEntry::mkdir(const std::string& new_name) { if (type != VFS::Directory) _error(type); EXT2_GD *new_dir_gd = nullptr; @@ -188,12 +188,14 @@ void EXT2_DEntry::mkdir(const std::string& new_name) { // ext2_fs->sb-> ext2_fs->write_gdt(); ext2_fs->write_super(); + return new_entry; } -void EXT2_DEntry::create(const std::string& name) { +VFS::DEntry *EXT2_DEntry::create(const std::string& name) { if (type != VFS::Directory) _error(type); _pos(); + inflate(); _u32 new_i_n = ext2_fs->alloc_inode(); _error(new_i_n == 0); EXT2::Inode *new_disk_i = new EXT2::Inode(); @@ -212,13 +214,13 @@ void 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; - load_children(); children.push_back(new_entry); write_children(); ext2_fs->write_gdt(); ext2_fs->write_super(); + return new_entry; } VFS::File *EXT2_DEntry::get_file() { @@ -290,10 +292,10 @@ void EXT2_DEntry::unlink_children() { _dbg_log("unlink chlidren current %d. finish", inode_n); } -void EXT2_DEntry::link(DEntry *tar, const std::string& s) { +VFS::DEntry *EXT2_DEntry::link(DEntry *tar, const std::string& s) { if (tar->fs != fs) { _log_info("[EXT2]: Hard Link must in the same file system."); - return; + return nullptr; } EXT2_DEntry *t = dynamic_cast(tar); std::string ts; @@ -308,11 +310,13 @@ void EXT2_DEntry::link(DEntry *tar, const std::string& s) { inflate(); ext2_inode->i->links_count++; ext2_inode->write_inode(); + return new_e; } -void EXT2_DEntry::move(DEntry *dir, const std::string& new_name) { - link(dir, new_name); // 在dir中创建item的硬链接 +VFS::DEntry *EXT2_DEntry::move(DEntry *dir, const std::string& new_name) { + auto ans = link(dir, new_name); // 在dir中创建item的硬链接 parent->unlink(this); // 在父目录中删除自己 + return ans; } bool EXT2_DEntry::empty() { @@ -320,6 +324,19 @@ bool EXT2_DEntry::empty() { return children.size() == 2; } +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]; + old_f->read(buf, old_f->size); + new_f->write(buf, old_f->size); + // dynamic_cast(new_entry)->ext2_inode->write_inode(); + delete old_f; + delete new_f; + return new_entry; +} + EXT2_DEntry::~EXT2_DEntry() { delete inode; diff --git a/fs/ext2/ext2_dentry.h b/fs/ext2/ext2_dentry.h index 0bf1013..8a0e590 100644 --- a/fs/ext2/ext2_dentry.h +++ b/fs/ext2/ext2_dentry.h @@ -25,17 +25,20 @@ namespace EXT2 void inflate(); void load_children(); - void mkdir(const std::string& name); - void create(const std::string& name); + VFS::DEntry* mkdir(const std::string& name); + VFS::DEntry* create(const std::string& name); void unlink(VFS::DEntry *d); // 删除子项目 void unlink(); // 删除自己 void unlink_children(); // 在tar中创建自己的硬链接 - void link(DEntry *tar, const std::string& s=""); + VFS::DEntry *link(DEntry *tar, const std::string& s=""); // 将本目录中的item移动到另一个目录中 - void move(DEntry *dir, const std::string& new_name=""); + VFS::DEntry *move(DEntry *dir, const std::string& new_name=""); bool empty(); + VFS::DEntry* copy(DEntry *dir, const std::string& new_name); + + ~EXT2_DEntry(); }; diff --git a/fs/ext2/ext2_file.cpp b/fs/ext2/ext2_file.cpp index de0b7b1..abc7865 100644 --- a/fs/ext2/ext2_file.cpp +++ b/fs/ext2/ext2_file.cpp @@ -79,8 +79,11 @@ _u32 EXT2_File::read(_u8 *buf, _u32 len) { } _u32 EXT2_File::write(_u8 *buf, _u32 len) { + if (len + pos > size) + resize(len + pos); + ext2_inode->print(); _u32 write_len = 0, this_write_len; - _u32 block_size = ext2_fs->block_size; // 块大小 + _u32 block_size = ext2_fs->block_size; // 块大小 _u32 byte_in_block = pos % block_size; // 第一个字节在块中的位置 _u32 nth_block = pos / block_size; // 第一个字节在第n个块,pos以0开始计数,不需要加1 auto it = ext2_inode->iter_at(nth_block); @@ -134,7 +137,9 @@ void EXT2_File::resize(_u32 new_size) { } } size = new_size; + ext2_inode->size = size; ext2_inode->blocks = target_block; + ext2_inode->write_inode(); ext2_fs->write_gdt(); ext2_fs->write_super(); } \ No newline at end of file diff --git a/fs/ext2/ext2_fs.cpp b/fs/ext2/ext2_fs.cpp index dd4764c..3828aab 100644 --- a/fs/ext2/ext2_fs.cpp +++ b/fs/ext2/ext2_fs.cpp @@ -125,7 +125,7 @@ _u32 EXT2_FS::alloc_inode(EXT2_GD **ret_gd) { for (EXT2_GD* gdd: gdt_list) { _u32 t = gdd->alloc_inode(); if (t != 0) { - // _si(t); + _si(t); sb->free_inodes_count--; if (ret_gd != nullptr) *ret_gd = gdd; diff --git a/fs/ext2/ext2_group_descriptor.cpp b/fs/ext2/ext2_group_descriptor.cpp index 504f4dc..016c8d2 100644 --- a/fs/ext2/ext2_group_descriptor.cpp +++ b/fs/ext2/ext2_group_descriptor.cpp @@ -48,7 +48,6 @@ _u8 *EXT2_GD::get_block_bitmap() { _u32 EXT2_GD::alloc_inode() { if (gd->free_inodes_count == 0) return 0; - _pos(); get_inode_bitmap(); for (int i = 0; i < fs->block_size; i++) { if (inode_bitmap[i] != (_u8)0xff) { diff --git a/fs/ext2/ext2_inode.cpp b/fs/ext2/ext2_inode.cpp index 5ee8942..475e921 100644 --- a/fs/ext2/ext2_inode.cpp +++ b/fs/ext2/ext2_inode.cpp @@ -32,7 +32,7 @@ void EXT2_Inode::print() { EXT2_Inode::EXT2_Inode(EXT2_FS *fs, _u32 n, EXT2::Inode *i): VFS::Inode(fs) { this->i = i; - ino = 0; + ino = n; counter = 0; mode = i->mode; nlink = i->links_count; @@ -49,9 +49,10 @@ EXT2_Inode::EXT2_Inode(EXT2_FS *fs, _u32 n, EXT2::Inode *i): VFS::Inode(fs) { inode_n = n; ext2_fs = fs; blocks = i->blocks / (ext2_fs->block_size / 512); - bytes = size % blocks; - for (int t = blocks; t < N_BLOCKS; t++) + bytes = size % ext2_fs->block_size; + for (int t = blocks; t < N_BLOCKS; t++) { i->block[t] = 0; + } } _u32 EXT2_Inode::byte_in_block(_u32 b) { @@ -99,6 +100,7 @@ void EXT2_Inode::write_inode() { _u32 inode_pos = ext2_fs->inode_to_pos(inode_n); MM::Buf buf(sizeof(EXT2::Inode)); i->blocks = blocks * (ext2_fs->block_size / 512); + i->size = size; memcpy(buf.data, i, sizeof(EXT2::Inode)); // _sa(buf.data, sizeof(EXT2::Inode)); ext2_fs->dev->write(buf, inode_pos, sizeof(EXT2::Inode)); @@ -213,6 +215,7 @@ void EXT2_Inode::iterator::load_buf(int t) { } void EXT2_Inode::iterator::write_back() { + _dbg_log("write back"); if (dirty[0]) { memcpy(inode->i->block, block_buf[0], sizeof(_u32) * EXT2::N_BLOCKS); dirty[0] = false; diff --git a/fs/test_fs.cpp b/fs/test_fs.cpp index 1aeaa2f..5ba7d1a 100644 --- a/fs/test_fs.cpp +++ b/fs/test_fs.cpp @@ -233,6 +233,26 @@ VFS::DEntry *mv(VFS::DEntry *cwd, const std::vector& cmdd) { return cwd; } +VFS::DEntry *cp(VFS::DEntry *cwd, const std::vector& cmdd) { + using namespace VFS; + VFS::NameI *from = parse_path(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 = parse_path(cmdd[cmdd.size() - 1]); + if ((te = cwd->get_path(target, &s)) == nullptr) { + _log_info("%s is already exists.", cmdd[2].c_str()); + return cwd; + } + fe->copy(te, s); + return cwd; +} + OP ops[] = { {"ls", ls}, {"cd", cd}, @@ -242,6 +262,7 @@ OP ops[] = { {"rm", rm}, {"link", link}, {"mv", mv}, + {"cp", cp}, {"unknown", nullptr} }; diff --git a/fs/vfs.h b/fs/vfs.h index 6a44ba3..977cb91 100644 --- a/fs/vfs.h +++ b/fs/vfs.h @@ -64,9 +64,9 @@ namespace VFS virtual void load_children()=0; // 在当前目录项创建文件夹 - virtual void mkdir(const std::string& new_name)=0; + virtual VFS::DEntry* mkdir(const std::string& new_name)=0; // 在当前目录下创建空文件 - virtual void create(const std::string& new_name)=0; + virtual VFS::DEntry* create(const std::string& new_name)=0; // 在当前目录下删除子项目,修改自己与子文件夹的引用关系 virtual void unlink(DEntry*)=0; // 删除自己,释放空间,会由ulink(DEntry*)调用 @@ -76,11 +76,13 @@ namespace VFS // 判断一个目录是否为空 virtual bool empty()=0; // 在另一个目录项中创建自己的硬链接 - virtual void link(DEntry *dir, const std::string& s="")=0; + virtual VFS::DEntry *link(DEntry *dir, const std::string& s="")=0; // 把自己移动到另一个目录中 - virtual void move(DEntry *dir, const std::string& new_name="")=0; + virtual VFS::DEntry *move(DEntry *dir, const std::string& new_name="")=0; // 打开文件 File *open(); + // 把自己复制到另一个文件夹中,新文件夹中文件的Entry + virtual VFS::DEntry *copy(DEntry *dir, const std::string& new_name="")=0; File *open(const std::string& name); DEntry* get_child(const std::string& name);