Compare commits
19
Commits
add-license-1
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48172dfac5 | ||
|
|
95c1abc4f2 | ||
|
|
0cfb3ab131 | ||
|
|
e4a0f5131b | ||
|
|
637e37f2eb | ||
|
|
01b6674bc5 | ||
|
|
d9d14d0429 | ||
|
|
f874c07d04 | ||
|
|
72ddb76b79 | ||
|
|
3f22946877 | ||
|
|
f21101a85c | ||
|
|
1bc09972c1 | ||
|
|
54b8ae5c3a | ||
|
|
cfc2d7a624 | ||
|
|
9748d564f3 | ||
|
|
e2fb8ef953 | ||
|
|
0c2a130596 | ||
|
|
9323d88ca1 | ||
|
|
fe3d369a52 |
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <string>
|
||||
std::vector<std::string> split(const std::string& s, char sp);
|
||||
+5
-5
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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();
|
||||
};
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* !!!!!!!!!!!!!!
|
||||
* !这个文件没有用!
|
||||
* !!!!!!!!!!!!!!
|
||||
*/
|
||||
|
||||
namespace VFS
|
||||
{
|
||||
class Denty {
|
||||
|
||||
+1
-1
@@ -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"
|
||||
|
||||
|
||||
@@ -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)))
|
||||
|
||||
Reference in New Issue
Block a user