diff --git a/CMakeLists.txt b/CMakeLists.txt index 81bcbfb..4a134ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ add_executable(fischl lib/fischl.cpp lib/main.cpp lib/files.cpp + lib/direntry.cpp ) diff --git a/include/files.h b/include/files.h index 713bc03..a2ab95c 100644 --- a/include/files.h +++ b/include/files.h @@ -1,10 +1,11 @@ #include #include +#include "direntry.h" class FilesOperation { RawDisk& disk; INodeOperation inop; - u_int64_t root_inode; + TreeNode *root_node; INode* new_inode(u_int64_t inode_number, u_int64_t permissions); void create_dot_dotdot(INode*, u_int64_t); public: @@ -13,8 +14,9 @@ class FilesOperation { int write_datablock(INode& inode, u_int64_t index, const char* buffer); void initialize_rootinode(); void printDirectory(u_int64_t); - u_int64_t create_new_inode(u_int64_t parent_inode_number, const char* name, mode_t mode); + INode* create_new_inode(u_int64_t parent_inode_number, const char* name, mode_t mode); void unlink_inode(u_int64_t inode_number); + u_int64_t disk_namei(const char* path); u_int64_t namei(const char* path); u_int64_t fischl_mkdir(const char*, mode_t); u_int64_t fischl_mknod(const char*, mode_t); diff --git a/lib/files.cpp b/lib/files.cpp index 9304fcb..2b78405 100644 --- a/lib/files.cpp +++ b/lib/files.cpp @@ -2,8 +2,26 @@ #include "files.h" #include #include -#include "direntry.h" +#include +struct DirectoryEntry { + u_int64_t inode_number; + char file_name[256]; + void serialize(char* buffer) { + u_int64_t t = inode_number; + for (int j = 0; j < 8; j++){ + buffer[j] = t & (((u_int64_t)1<<(8))-1); + t >>= 8; + } + strcpy(buffer+8, file_name); + } + void deserialize(char* buffer) { + inode_number = 0; + for (int j = 0; j < 8; j++) + inode_number = inode_number | (((u_int64_t)(unsigned char)buffer[j])<<(8*j)); + strcpy(file_name, buffer+8); + } +}; FilesOperation::FilesOperation(RawDisk& disk_): disk(disk_) { inop.initialize(disk); @@ -85,18 +103,20 @@ void FilesOperation::create_dot_dotdot(INode* inode, u_int64_t parent_inode_numb DirectoryEntry dotdot; dotdot.inode_number = parent_inode_number; strcpy(dotdot.file_name, ".."); - dotdot.serialize(buffer+64); + dotdot.serialize(buffer+264); int ret = write_datablock(*inode, 0, buffer); inode->inode_save(disk); } void FilesOperation::initialize_rootinode() { // this method must be called explicitly right after initializion - root_inode = inop.inode_allocate(disk); - printf("Info: root inode number: %llu\n", root_inode); - INode *get_inode = new_inode(root_inode, S_IFDIR); - create_dot_dotdot(get_inode, root_inode); - delete get_inode; + u_int64_t root_inode_number = inop.inode_allocate(disk); + printf("Info: root inode number: %llu\n", root_inode_number); + INode *root_inode = new_inode(root_inode_number, S_IFDIR); + create_dot_dotdot(root_inode, root_inode_number); + root_node = fischl_init_entry(root_inode_number, "/", root_inode); + assert(root_node->self_info!=NULL); + delete root_inode; } void FilesOperation::printDirectory(u_int64_t inode_number) { @@ -106,24 +126,24 @@ void FilesOperation::printDirectory(u_int64_t inode_number) { char buffer[IO_BLOCK_SIZE] = {0}; read_datablock(inode, 0, buffer); DirectoryEntry ent; - for(int i=0;i<=IO_BLOCK_SIZE-64;i+=64){ + for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){ ent.deserialize(buffer+i); if (ent.inode_number) printf("%s\t%llu;\t", ent.file_name, ent.inode_number); } printf("\n"); } -u_int64_t FilesOperation::create_new_inode(u_int64_t parent_inode_number, const char* name, mode_t mode) { +INode* FilesOperation::create_new_inode(u_int64_t parent_inode_number, const char* name, mode_t mode) { // trys to create a file under parent directory - if (strlen(name)>=56) { + if (strlen(name)>=256) { perror("Name too long, cannot create file or directory"); - return -1; + return NULL; } INode inode; inode.inode_construct(parent_inode_number, disk); if ((inode.permissions & S_IFMT) != S_IFDIR) { printf("Parent Inode is not a directory\n"); - return -1; + return NULL; } // Check if file or directory already exists @@ -131,11 +151,11 @@ u_int64_t FilesOperation::create_new_inode(u_int64_t parent_inode_number, const for (u_int64_t idx=0; idxpermissions & S_IFMT) == S_IFDIR) { create_dot_dotdot(get_inode, parent_inode_number); } - delete get_inode; - return new_inode_number; + return get_inode; } -u_int64_t FilesOperation::namei(const char* path) { +u_int64_t FilesOperation::disk_namei(const char* path) { // returns the inode number corresponding to path - u_int64_t current_inode = root_inode; + u_int64_t current_inode = root_node->self_info->inode_number; std::string current_dirname; std::istringstream pathStream(path); std::string new_name; std::getline(pathStream, new_name, '/'); if(!new_name.empty()){ - printf("namei: path should start with /\n"); + printf("disk_namei: path should start with /\n"); return -1; } while (std::getline(pathStream, new_name, '/')) { INode inode; inode.inode_construct(current_inode, disk); if ((inode.permissions & S_IFMT) != S_IFDIR || inode.size == 0) { - printf("namei: %s is not a non-empty directory\n", current_dirname.c_str()); + printf("disk_namei: %s is not a non-empty directory\n", current_dirname.c_str()); return -1; } u_int64_t new_inode_number = 0; @@ -206,7 +225,7 @@ u_int64_t FilesOperation::namei(const char* path) { for(u_int64_t idx=0; idxself_info->inode_number) // path = "/foo.txt" should return inode for foo.txt // path = "/mydir" should return inode for mydir // path = "/nonemptydir/foo" should return inode for foo // path = "/notnonemptydir/foo" should raise error } +u_int64_t FilesOperation::namei(const char* path) { + FileNode* filenode = fischl_find_entry(root_node, path); + if (filenode) return filenode->inode_number; + else return -1; +} + u_int64_t FilesOperation::fischl_mkdir(const char* path, mode_t mode) { //check path char *pathdup = strdup(path); @@ -238,16 +263,19 @@ u_int64_t FilesOperation::fischl_mkdir(const char* path, mode_t mode) { char *newDirname = lastSlash+1; //\0, get from char *ParentPath = pathdup;//pathdup are separated by pathdup, so it take only - u_int64_t parent_inode_number = namei(ParentPath); - if (parent_inode_number == (u_int64_t)-1) { - printf("fischl_mkdir failed because namei failed to find inode for %s\n", ParentPath); + FileNode *parent_filenode = strlen(ParentPath)? fischl_find_entry(root_node, ParentPath): root_node->self_info; + if (parent_filenode == NULL) { + printf("parent %s not found by fischl_find_entry\n", ParentPath); delete pathdup; return -1; } + u_int64_t parent_inode_number = parent_filenode->inode_number; //make new inode - u_int64_t ret = create_new_inode(parent_inode_number, newDirname, mode|S_IFDIR);//specify S_IFDIR as directory + INode* ret = create_new_inode(parent_inode_number, newDirname, mode|S_IFDIR);//specify S_IFDIR as directory + if (ret == NULL) return -1; + fischl_add_entry(parent_filenode->subdirectory, ret->block_number, newDirname, ret); delete pathdup; - return ret; + return ret->block_number; //after new_inode(mkfile), go to fischl_add_entry record @@ -260,17 +288,21 @@ u_int64_t FilesOperation::fischl_mknod(const char* path, mode_t mode) { *lastSlash = '\0'; // Split the string into parent path and new directory name; \0 char *newFilename = lastSlash+1; //\0, get from char *ParentPath = pathdup;//pathdup are separated by pathdup, so it take only - - u_int64_t parent_inode_number = namei(ParentPath); - if (parent_inode_number == (u_int64_t)-1) { - printf("fischl_mkdir failed because namei failed to find inode for %s\n", ParentPath); + printf("mknod ParentPath:%s, strlen=%d\n", ParentPath, strlen(ParentPath)); + FileNode *parent_filenode = strlen(ParentPath)? fischl_find_entry(root_node, ParentPath): root_node->self_info; + if (parent_filenode == NULL) { + printf("parent %s not found by fischl_find_entry\n", ParentPath); delete pathdup; return -1; } + u_int64_t parent_inode_number = parent_filenode->inode_number; //make new inode - u_int64_t ret = create_new_inode(parent_inode_number, newFilename, mode); + INode* ret = create_new_inode(parent_inode_number, newFilename, mode); + if (ret == NULL) return -1; + //make new node + fischl_add_entry(parent_filenode->subdirectory, ret->block_number, newFilename, ret); delete pathdup; - return ret; + return ret->block_number; } void FilesOperation::unlink_inode(u_int64_t inode_number) { @@ -281,7 +313,7 @@ void FilesOperation::unlink_inode(u_int64_t inode_number) { for(u_int64_t idx=0; idxinode_number; u_int64_t target_inode = 0; - + // remove its record from parent INode parent_INode; - parent_INode.inode_construct(parent_inode, disk); + parent_INode.inode_construct(parent_inode_number, disk); char rw_buffer[IO_BLOCK_SIZE] = {0}; for (u_int64_t idx=0; idxsubdirectory, filename); delete pathdup; return 0; } else { diff --git a/test/layer2_API.cpp b/test/layer2_API.cpp index 70eff32..0630e16 100644 --- a/test/layer2_API.cpp +++ b/test/layer2_API.cpp @@ -13,7 +13,6 @@ int main(int argc, char *argv[]) { fsop.initialize_rootinode(); // create multiple files using mkdir or mknod - // directories that contain more than 64 files use more than one datablocks, it is not supported yet printf("=== Part 1: create files by path ===\n"); u_int64_t file1 = fsop.fischl_mknod("/test",0); // mode here is not used yet printf("/test is inode %llu, it is a file\n", file1); @@ -113,4 +112,9 @@ int main(int argc, char *argv[]) { assert(inode_number == inode_numbers[i]); } fsop.printDirectory(file_pressure); + + // long filename test + std::string longfilename = std::string(255,'A'); + u_int64_t filelong = fsop.fischl_mknod((std::string("/")+longfilename).c_str(),0); + printf("/AAA...AAA is inode %llu, it is a file\n", filelong); } \ No newline at end of file