diff --git a/include/fs.hpp b/include/fs.hpp index 3a420aa..61b9f45 100644 --- a/include/fs.hpp +++ b/include/fs.hpp @@ -18,7 +18,7 @@ public: ssize_t read(INode_Data *inode_data, char buf[], size_t count, size_t offset); ssize_t write(INode_Data *inode_data, const char buf[], size_t count, size_t offset); - int truncate(INode_Data *inode_data, size_t length); + int truncate(INode_Data *inode_data, off_t length); ssize_t lseek_next_data(INode_Data *inode_data, size_t offset); ssize_t lseek_next_hole(INode_Data *inode_data, size_t offset); diff --git a/include/fs/fs_data_types.hpp b/include/fs/fs_data_types.hpp index 9242c0c..ee99b41 100644 --- a/include/fs/fs_data_types.hpp +++ b/include/fs/fs_data_types.hpp @@ -41,6 +41,10 @@ public: #define NUMBER_OF_DIRECT_BLOCKS \ (((INODE_SIZE - NUMBER_OF_METADATA_BYTES) / sizeof(u_int64_t)) - 3) +#define FILE_SIZE_MAX \ + (IO_BLOCK_SIZE * (NUMBER_OF_DIRECT_BLOCKS + INDIRECT_BLOCKS + \ + (INDIRECT_BLOCKS * INDIRECT_BLOCKS) + \ + (INDIRECT_BLOCKS * INDIRECT_BLOCKS * INDIRECT_BLOCKS))) u_int64_t single_indirect_block, double_indirect_block, triple_indirect_block; u_int64_t direct_blocks[NUMBER_OF_DIRECT_BLOCKS]; diff --git a/include/fs_constants.hpp b/include/fs_constants.hpp index 38c9c9c..f66c649 100644 --- a/include/fs_constants.hpp +++ b/include/fs_constants.hpp @@ -2,6 +2,7 @@ #define FS_CONSTANTS_HPP #include +#include #include #include #include @@ -11,6 +12,7 @@ #include #include + #define IO_BLOCK_SIZE 4096 #define INDIRECT_BLOCKS 512 diff --git a/lib/files.cpp b/lib/files.cpp index 6bee7f4..275d4e0 100644 --- a/lib/files.cpp +++ b/lib/files.cpp @@ -6,8 +6,8 @@ #include #include -FileNode* FilesOperation::fischl_load_entry(TreeNode *root, const char *path){ - return fischl_find_entry(fs, root, path); +FileNode *FilesOperation::fischl_load_entry(TreeNode *root, const char *path) { + return fischl_find_entry(fs, root, path); } void FilesOperation::printbuffer(const char *buff, int len) { @@ -37,28 +37,27 @@ void FilesOperation::create_dot_dotdot(INode_Data *inode, } void FilesOperation::initialize_rootinode() { - // this method must be called explicitly right after initializion - INode_Data *root_inode = new INode_Data(); - fs->inode_manager->new_inode(getuid(), getgid(), S_IFDIR|0755, root_inode); - u_int64_t root_inode_number = root_inode->inode_num; - create_dot_dotdot(root_inode, root_inode_number); - root_node = fischl_init_entry(root_inode_number, "/", root_inode); - assert(root_node->self_info!=NULL); - fs->inode_manager->save_inode(root_inode); + // this method must be called explicitly right after initializion + INode_Data *root_inode = new INode_Data(); + fs->inode_manager->new_inode(getuid(), getgid(), S_IFDIR | 0755, root_inode); + u_int64_t root_inode_number = root_inode->inode_num; + create_dot_dotdot(root_inode, root_inode_number); + root_node = fischl_init_entry(root_inode_number, "/", root_inode); + assert(root_node->self_info != NULL); + fs->inode_manager->save_inode(root_inode); } void FilesOperation::initialize(bool load) { - if (load){ - INode_Data *root_inode = new INode_Data(); - root_inode->inode_num = 1; - fs->inode_manager->load_inode(root_inode); - root_node = fischl_init_entry(1, "/", root_inode); - assert(root_node->self_info!=NULL); - fs->load_superblock(); - } - else{ - initialize_rootinode(); - } + if (load) { + INode_Data *root_inode = new INode_Data(); + root_inode->inode_num = 1; + fs->inode_manager->load_inode(root_inode); + root_node = fischl_init_entry(1, "/", root_inode); + assert(root_node->self_info != NULL); + fs->load_superblock(); + } else { + initialize_rootinode(); + } } void FilesOperation::printDirectory(u_int64_t inode_number) { @@ -114,14 +113,16 @@ INode_Data *FilesOperation::create_new_inode(u_int64_t parent_inode_number, } } - bool allocated = false; - INode_Data *new_inode = new INode_Data(); - fs->inode_manager->new_inode(getuid(), getgid(), mode, new_inode); - printf("NEW INODE %llu %llu %llu %o\n",new_inode->inode_num, new_inode->metadata.uid, new_inode->metadata.gid, (mode_t)new_inode->metadata.permissions); - if ((mode & S_IFMT) == S_IFDIR) { - create_dot_dotdot(new_inode, parent_inode_number); - fs->inode_manager->save_inode(new_inode); - } + bool allocated = false; + INode_Data *new_inode = new INode_Data(); + fs->inode_manager->new_inode(getuid(), getgid(), mode, new_inode); + printf("NEW INODE %llu %llu %llu %o\n", new_inode->inode_num, + new_inode->metadata.uid, new_inode->metadata.gid, + (mode_t)new_inode->metadata.permissions); + if ((mode & S_IFMT) == S_IFDIR) { + create_dot_dotdot(new_inode, parent_inode_number); + fs->inode_manager->save_inode(new_inode); + } char rw_buffer[IO_BLOCK_SIZE] = {0}; for (u_int64_t idx = 0; idx < inode.metadata.size / IO_BLOCK_SIZE; idx++) { @@ -210,86 +211,87 @@ u_int64_t FilesOperation::disk_namei(const char *path) { // should raise error } -u_int64_t FilesOperation::namei(const char* path) { - FileNode* filenode = fischl_load_entry(root_node, path); - if (filenode) return filenode->inode_number; - else return -1; +u_int64_t FilesOperation::namei(const char *path) { + FileNode *filenode = fischl_load_entry(root_node, path); + if (filenode) + return filenode->inode_number; + else + return -1; } bool FilesOperation::permission_check(int mask, INode_Data *inode) { - mode_t per = (mode_t)inode->metadata.permissions; - uid_t uid = (uid_t)inode->metadata.uid; - gid_t gid = (gid_t)inode->metadata.gid; - //printf("PERMISSION CHECK %d %llu %llu %o\n", mask, uid, gid, per); - if(getuid() == uid){ - if ((mask & R_OK) && !(per & S_IRUSR)) { - return false; // Permission denied for reading - } - - if ((mask & W_OK) && !(per & S_IWUSR)) { - return false; // Permission denied for writing - } - - if ((mask & X_OK) && !(per & S_IXUSR)) { - return false; // Permission denied for executing - } - return true; + mode_t per = (mode_t)inode->metadata.permissions; + uid_t uid = (uid_t)inode->metadata.uid; + gid_t gid = (gid_t)inode->metadata.gid; + // printf("PERMISSION CHECK %d %llu %llu %o\n", mask, uid, gid, per); + if (getuid() == uid) { + if ((mask & R_OK) && !(per & S_IRUSR)) { + return false; // Permission denied for reading } - else if(getgid() == gid){ - if ((mask & R_OK) && !(per & S_IRGRP)) { - return false; // Permission denied for reading - } - if ((mask & W_OK) && !(per & S_IWGRP)) { - return false; // Permission denied for writing - } - - if ((mask & X_OK) && !(per & S_IXGRP)) { - return false; // Permission denied for executing - } - return true; + if ((mask & W_OK) && !(per & S_IWUSR)) { + return false; // Permission denied for writing } - else{ - if ((mask & R_OK) && !(per & S_IROTH)) { - return false; // Permission denied for reading - } - if ((mask & W_OK) && !(per & S_IWOTH)) { - return false; // Permission denied for writing - } - - if ((mask & X_OK) && !(per & S_IXOTH)) { - return false; // Permission denied for executing - } - return true; - } -} - -bool FilesOperation::permission_check_by_inode_num(int mask, u_int64_t inode_num) { - INode_Data inode; - inode.inode_num = inode_num; - - fs->inode_manager->load_inode(&inode); - if(!permission_check(mask, &inode)){ - return false; + if ((mask & X_OK) && !(per & S_IXUSR)) { + return false; // Permission denied for executing } return true; + } else if (getgid() == gid) { + if ((mask & R_OK) && !(per & S_IRGRP)) { + return false; // Permission denied for reading + } + + if ((mask & W_OK) && !(per & S_IWGRP)) { + return false; // Permission denied for writing + } + + if ((mask & X_OK) && !(per & S_IXGRP)) { + return false; // Permission denied for executing + } + return true; + } else { + if ((mask & R_OK) && !(per & S_IROTH)) { + return false; // Permission denied for reading + } + + if ((mask & W_OK) && !(per & S_IWOTH)) { + return false; // Permission denied for writing + } + + if ((mask & X_OK) && !(per & S_IXOTH)) { + return false; // Permission denied for executing + } + return true; + } } -int FilesOperation::fischl_access(const char* path, int mask) { +bool FilesOperation::permission_check_by_inode_num(int mask, + u_int64_t inode_num) { + INode_Data inode; + inode.inode_num = inode_num; - u_int64_t fh = namei(path); + fs->inode_manager->load_inode(&inode); + if (!permission_check(mask, &inode)) { + return false; + } + return true; +} - if (fh == -1){ - return -ENOENT; - } +int FilesOperation::fischl_access(const char *path, int mask) { - if(!permission_check_by_inode_num(mask, fh)){ - return -EACCES; - } - // return 0 when access is allowed - return 0; -} + u_int64_t fh = namei(path); + + if (fh == -1) { + return -ENOENT; + } + + if (!permission_check_by_inode_num(mask, fh)) { + return -EACCES; + } + // return 0 when access is allowed + return 0; +} int FilesOperation::fischl_mkdir(const char *path, mode_t mode) { // check path @@ -302,84 +304,111 @@ int FilesOperation::fischl_mkdir(const char *path, mode_t mode) { char *ParentPath = pathdup; // pathdup are separated by pathdup, so it take // only - FileNode *parent_filenode = strlen(ParentPath)? fischl_load_entry(root_node, ParentPath): root_node->self_info; - if (parent_filenode == NULL) { - fprintf(stderr,"[%s ,%d] ParentPath:{%s} not found\n",__func__,__LINE__, ParentPath); - free(pathdup); - return -ENOENT;//parentpath directory does not exist - } - u_int64_t parent_inode_number = parent_filenode->inode_number; - if(!permission_check_by_inode_num(W_OK, parent_inode_number)){ - return -EACCES; - } - - //printf("%s, %llu, %s\n", parent_filenode->name, parent_inode_number, newDirname); - //make new inode - INode_Data* ret = create_new_inode(parent_inode_number, newDirname, mode|S_IFDIR);//specify S_IFDIR as directory - if (ret == NULL) return -1;//ENOSPC but create_new_inode handle ENAMETOOLONG EEXIST - fischl_add_entry(parent_filenode->subdirectory, ret->inode_num, newDirname, ret); + FileNode *parent_filenode = strlen(ParentPath) + ? fischl_load_entry(root_node, ParentPath) + : root_node->self_info; + if (parent_filenode == NULL) { + fprintf(stderr, "[%s ,%d] ParentPath:{%s} not found\n", __func__, __LINE__, + ParentPath); free(pathdup); - return 0;//SUCCESS + return -ENOENT; // parentpath directory does not exist + } + u_int64_t parent_inode_number = parent_filenode->inode_number; + if (!permission_check_by_inode_num(W_OK, parent_inode_number)) { + return -EACCES; + } + + // printf("%s, %llu, %s\n", parent_filenode->name, parent_inode_number, + // newDirname); make new inode + INode_Data *ret = + create_new_inode(parent_inode_number, newDirname, + mode | S_IFDIR); // specify S_IFDIR as directory + if (ret == NULL) + return -1; // ENOSPC but create_new_inode handle ENAMETOOLONG EEXIST + fischl_add_entry(parent_filenode->subdirectory, ret->inode_num, newDirname, + ret); + free(pathdup); + return 0; // SUCCESS } /* special file */ -int FilesOperation::fischl_mknod(const char* path, mode_t mode, dev_t dev) { - //check path - char *pathdup = strdup(path); - char *lastSlash = strrchr(pathdup, '/'); - *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 - // fprintf(stderr,"[%s ,%d] ParentPath:%s, strlen=%d\n",__func__,__LINE__, ParentPath, strlen(ParentPath)); - FileNode *parent_filenode = strlen(ParentPath)? fischl_load_entry(root_node, ParentPath): root_node->self_info; - if (parent_filenode == NULL) { - fprintf(stderr,"[%s ,%d] ParentPath:{%s} not found\n",__func__,__LINE__, ParentPath); - free(pathdup); - return -1; - } - u_int64_t parent_inode_number = parent_filenode->inode_number; - if(!permission_check_by_inode_num(W_OK, parent_inode_number)){ - return -EACCES; - } - //make new inode - INode_Data* ret = create_new_inode(parent_inode_number, newFilename, mode); - if (ret == NULL) return -1;//ENOSPC but create_new_inode handle ENAMETOOLONG EEXIST - //make new node - fischl_add_entry(parent_filenode->subdirectory, ret->inode_num, newFilename, ret); +int FilesOperation::fischl_mknod(const char *path, mode_t mode, dev_t dev) { + // check path + char *pathdup = strdup(path); + char *lastSlash = strrchr(pathdup, '/'); + *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 + // fprintf(stderr,"[%s ,%d] ParentPath:%s, strlen=%d\n",__func__,__LINE__, + // ParentPath, strlen(ParentPath)); + FileNode *parent_filenode = strlen(ParentPath) + ? fischl_load_entry(root_node, ParentPath) + : root_node->self_info; + if (parent_filenode == NULL) { + fprintf(stderr, "[%s ,%d] ParentPath:{%s} not found\n", __func__, __LINE__, + ParentPath); free(pathdup); - return 0;//SUCESS + return -1; + } + u_int64_t parent_inode_number = parent_filenode->inode_number; + if (!permission_check_by_inode_num(W_OK, parent_inode_number)) { + return -EACCES; + } + // make new inode + INode_Data *ret = create_new_inode(parent_inode_number, newFilename, mode); + if (ret == NULL) + return -1; // ENOSPC but create_new_inode handle ENAMETOOLONG EEXIST + // make new node + fischl_add_entry(parent_filenode->subdirectory, ret->inode_num, newFilename, + ret); + free(pathdup); + return 0; // SUCESS } /* regular file */ -int FilesOperation::fischl_create(const char* path, mode_t mode, struct fuse_file_info* fi) { - //check path - char *pathdup = strdup(path); - char *lastSlash = strrchr(pathdup, '/'); - *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 - // fprintf(stderr,"[%s ,%d] ParentPath:%s, strlen=%d\n",__func__,__LINE__, ParentPath, strlen(ParentPath)); - FileNode *parent_filenode = strlen(ParentPath)? fischl_load_entry(root_node, ParentPath): root_node->self_info; - if (parent_filenode == NULL) { - fprintf(stderr,"[%s ,%d] ParentPath:{%s} not found\n",__func__,__LINE__, ParentPath); - free(pathdup); - return -1; - } - u_int64_t parent_inode_number = parent_filenode->inode_number; - if(!permission_check_by_inode_num(W_OK, parent_inode_number)){ - return -EACCES; - } - //make new inode - INode_Data* ret = create_new_inode(parent_inode_number, newFilename, mode); - if (ret == NULL) return -1;//ENOSPC but create_new_inode handle ENAMETOOLONG EEXIST - //make new node in RAM - fischl_add_entry(parent_filenode->subdirectory, ret->inode_num, newFilename, ret); - //directly give inode number rather than create file descriptor table - fi->fh = ret->inode_num;//assign file descriptor as inode number to fuse system +int FilesOperation::fischl_create(const char *path, mode_t mode, + struct fuse_file_info *fi) { + // check path + char *pathdup = strdup(path); + char *lastSlash = strrchr(pathdup, '/'); + *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 + // fprintf(stderr,"[%s ,%d] ParentPath:%s, strlen=%d\n",__func__,__LINE__, + // ParentPath, strlen(ParentPath)); + FileNode *parent_filenode = strlen(ParentPath) + ? fischl_load_entry(root_node, ParentPath) + : root_node->self_info; + if (parent_filenode == NULL) { + fprintf(stderr, "[%s ,%d] ParentPath:{%s} not found\n", __func__, __LINE__, + ParentPath); free(pathdup); - return 0;//SUCESS + return -1; + } + u_int64_t parent_inode_number = parent_filenode->inode_number; + if (!permission_check_by_inode_num(W_OK, parent_inode_number)) { + return -EACCES; + } + // make new inode + INode_Data *ret = create_new_inode(parent_inode_number, newFilename, mode); + if (ret == NULL) + return -1; // ENOSPC but create_new_inode handle ENAMETOOLONG EEXIST + // make new node in RAM + fischl_add_entry(parent_filenode->subdirectory, ret->inode_num, newFilename, + ret); + // directly give inode number rather than create file descriptor table + fi->fh = + ret->inode_num; // assign file descriptor as inode number to fuse system + free(pathdup); + return 0; // SUCESS } int FilesOperation::fischl_getattr(const char *path, struct stat *stbuf, @@ -397,40 +426,45 @@ int FilesOperation::fischl_getattr(const char *path, struct stat *stbuf, inode.inode_num = fh; fs->inode_manager->load_inode(&inode); - //printf("GETATTR PERM %o\n", (mode_t)inode.metadata.permissions); + // printf("GETATTR PERM %o\n", (mode_t)inode.metadata.permissions); - //memset(stbuf, 0, sizeof(struct stat)); - if ((inode.metadata.permissions & S_IFMT) == S_IFDIR) { - stbuf->st_mode = (mode_t)inode.metadata.permissions;//S_IFDIR | 0755; - stbuf->st_nlink = 2;//inode.metadata.reference_count; - stbuf->st_uid = inode.metadata.uid; - stbuf->st_gid = inode.metadata.gid; - stbuf->st_atime = (time_t)(inode.metadata.access_time / 1000000000ULL); - stbuf->st_mtime = (time_t)(inode.metadata.modification_time / 1000000000ULL); - stbuf->st_size = IO_BLOCK_SIZE; - stbuf->st_ino = inode.inode_num; - } else if(S_ISLNK(inode.metadata.permissions)){ - stbuf->st_mode = (mode_t)inode.metadata.permissions; - stbuf->st_nlink = 1;//inode.metadata.reference_count; - stbuf->st_uid = inode.metadata.uid; - stbuf->st_gid = inode.metadata.gid; - stbuf->st_atime = (time_t)(inode.metadata.access_time / 1000000000ULL); - stbuf->st_mtime = (time_t)(inode.metadata.modification_time / 1000000000ULL); - stbuf->st_size = inode.metadata.size; - stbuf->st_ino = inode.inode_num; - } else { - stbuf->st_mode = (mode_t)inode.metadata.permissions; - stbuf->st_nlink = inode.metadata.reference_count; - stbuf->st_uid = inode.metadata.uid; - stbuf->st_gid = inode.metadata.gid; - //printf("GETATTR %llu %llu %llu %o\n", inode.inode_num, inode.metadata.uid, inode.metadata.gid, (mode_t)inode.metadata.permissions); - stbuf->st_atime = (time_t)(inode.metadata.access_time / 1000000000ULL); - stbuf->st_mtime = (time_t)(inode.metadata.modification_time / 1000000000ULL); - stbuf->st_size = inode.metadata.size; - stbuf->st_ino = inode.inode_num; - } - //perror(std::to_string(inode.inode_num).c_str()); - return res; + // memset(stbuf, 0, sizeof(struct stat)); + if ((inode.metadata.permissions & S_IFMT) == S_IFDIR) { + stbuf->st_mode = (mode_t)inode.metadata.permissions; // S_IFDIR | 0755; + stbuf->st_nlink = 2; // inode.metadata.reference_count; + stbuf->st_uid = inode.metadata.uid; + stbuf->st_gid = inode.metadata.gid; + stbuf->st_atime = (time_t)(inode.metadata.access_time / 1000000000ULL); + stbuf->st_mtime = + (time_t)(inode.metadata.modification_time / 1000000000ULL); + stbuf->st_size = IO_BLOCK_SIZE; + stbuf->st_ino = inode.inode_num; + } else if (S_ISLNK(inode.metadata.permissions)) { + stbuf->st_mode = (mode_t)inode.metadata.permissions; + stbuf->st_nlink = 1; // inode.metadata.reference_count; + stbuf->st_uid = inode.metadata.uid; + stbuf->st_gid = inode.metadata.gid; + stbuf->st_atime = (time_t)(inode.metadata.access_time / 1000000000ULL); + stbuf->st_mtime = + (time_t)(inode.metadata.modification_time / 1000000000ULL); + stbuf->st_size = inode.metadata.size; + stbuf->st_ino = inode.inode_num; + } else { + stbuf->st_mode = (mode_t)inode.metadata.permissions; + stbuf->st_nlink = inode.metadata.reference_count; + stbuf->st_uid = inode.metadata.uid; + stbuf->st_gid = inode.metadata.gid; + // printf("GETATTR %llu %llu %llu %o\n", inode.inode_num, + // inode.metadata.uid, inode.metadata.gid, + // (mode_t)inode.metadata.permissions); + stbuf->st_atime = (time_t)(inode.metadata.access_time / 1000000000ULL); + stbuf->st_mtime = + (time_t)(inode.metadata.modification_time / 1000000000ULL); + stbuf->st_size = inode.metadata.size; + stbuf->st_ino = inode.inode_num; + } + // perror(std::to_string(inode.inode_num).c_str()); + return res; } int FilesOperation::fischl_readdir(const char *path, void *buf, @@ -444,45 +478,47 @@ int FilesOperation::fischl_readdir(const char *path, void *buf, return -1; } - INode_Data inode; - inode.inode_num = fh; - fs->inode_manager->load_inode(&inode); - if(!permission_check(R_OK, &inode)){ - return -EACCES; - } - char buffer[IO_BLOCK_SIZE] = {0}; - for (u_int64_t idx=0; idxread(&inode, buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE); - DirectoryEntry ent; - for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){ - ent.deserialize(buffer+i); - if (ent.inode_number) { - filler(buf, ent.file_name, NULL, 0, FUSE_FILL_DIR_PLUS); - printf("%s\t%llu;\t\n", ent.file_name, ent.inode_number); - } - } + INode_Data inode; + inode.inode_num = fh; + fs->inode_manager->load_inode(&inode); + if (!permission_check(R_OK, &inode)) { + return -EACCES; + } + char buffer[IO_BLOCK_SIZE] = {0}; + for (u_int64_t idx = 0; idx < inode.metadata.size / IO_BLOCK_SIZE; idx++) { + fs->read(&inode, buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE); + DirectoryEntry ent; + for (int i = 0; i <= IO_BLOCK_SIZE - 264; i += 264) { + ent.deserialize(buffer + i); + if (ent.inode_number) { + filler(buf, ent.file_name, NULL, 0, FUSE_FILL_DIR_PLUS); + printf("%s\t%llu;\t\n", ent.file_name, ent.inode_number); + } } + } return 0; } -int FilesOperation::fischl_releasedir(const char *path, struct fuse_file_info *fi){ - if(fischl_load_entry(root_node, path) == NULL) - return -ENOENT; - //do with file descriptor that cannot be used - fi->fh = -1; - return 0;//SUCESS +int FilesOperation::fischl_releasedir(const char *path, + struct fuse_file_info *fi) { + if (fischl_load_entry(root_node, path) == NULL) + return -ENOENT; + // do with file descriptor that cannot be used + fi->fh = -1; + return 0; // SUCESS } void FilesOperation::unlink_inode(u_int64_t inode_number) { INode_Data inode; inode.inode_num = inode_number; fs->inode_manager->load_inode(&inode); - if (inode.metadata.reference_count > 1 && (inode.metadata.permissions & S_IFMT) != S_IFDIR){ - inode.metadata.reference_count -= 1; - fs->inode_manager->save_inode(&inode); - return; - } + if (inode.metadata.reference_count > 1 && + (inode.metadata.permissions & S_IFMT) != S_IFDIR) { + inode.metadata.reference_count -= 1; + fs->inode_manager->save_inode(&inode); + return; + } if ((inode.metadata.permissions & S_IFMT) == S_IFDIR) { char buffer[IO_BLOCK_SIZE] = {0}; for (u_int64_t idx = 0; idx < inode.metadata.size / IO_BLOCK_SIZE; idx++) { @@ -501,83 +537,85 @@ void FilesOperation::unlink_inode(u_int64_t inode_number) { fs->inode_manager->free_inode(&inode); } -int FilesOperation::fischl_opendir(const char* path, struct fuse_file_info* fi) { +int FilesOperation::fischl_opendir(const char *path, + struct fuse_file_info *fi) { - u_int64_t fh = namei(path); + u_int64_t fh = namei(path); - if (fh == -1){ - return -ENOENT; - } + if (fh == -1) { + return -ENOENT; + } - INode_Data inode; - inode.inode_num = fh; - - fs->inode_manager->load_inode(&inode); - if(!permission_check(X_OK|R_OK, &inode)){ - return -EACCES; - } - fi->fh = fh; - return 0; + INode_Data inode; + inode.inode_num = fh; + + fs->inode_manager->load_inode(&inode); + if (!permission_check(X_OK | R_OK, &inode)) { + return -EACCES; + } + fi->fh = fh; + return 0; } -int FilesOperation::fischl_rmdir(const char* path) { - char *pathdup = strdup(path); - char *lastSlash = strrchr(pathdup, '/'); - *lastSlash = '\0'; - char *dirname = lastSlash+1; - char *ParentPath = pathdup; - if (!strcmp(dirname,".")||!strcmp(dirname,"..")) { - printf("refusing to remove . or ..\n"); - return -1; +int FilesOperation::fischl_rmdir(const char *path) { + char *pathdup = strdup(path); + char *lastSlash = strrchr(pathdup, '/'); + *lastSlash = '\0'; + char *dirname = lastSlash + 1; + char *ParentPath = pathdup; + if (!strcmp(dirname, ".") || !strcmp(dirname, "..")) { + printf("refusing to remove . or ..\n"); + return -1; + } + FileNode *parent_filenode = fischl_load_entry(root_node, ParentPath); + if (parent_filenode == NULL) { + printf("parent %s not found by fischl_load_entry\n", ParentPath); + free(pathdup); + return -1; + } + u_int64_t parent_inode_number = parent_filenode->inode_number; + u_int64_t target_inode = 0; + + // remove its record from parent + INode_Data parent_INode; + parent_INode.inode_num = parent_inode_number; + fs->inode_manager->load_inode(&parent_INode); + if (!permission_check(W_OK, &parent_INode)) { + return -EACCES; + } + char rw_buffer[IO_BLOCK_SIZE] = {0}; + for (u_int64_t idx = 0; idx < parent_INode.metadata.size / IO_BLOCK_SIZE; + idx++) { + fs->read(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE); + DirectoryEntry ent; + for (int i = 0; i <= IO_BLOCK_SIZE - 264; i += 264) { + ent.deserialize(rw_buffer + i); + if (strcmp(ent.file_name, dirname) == 0) { + target_inode = ent.inode_number; + ent.inode_number = 0; + memset(ent.file_name, 0, sizeof(ent.file_name)); + ent.serialize(rw_buffer + i); + break; + } } - FileNode *parent_filenode = fischl_load_entry(root_node, ParentPath); - if (parent_filenode == NULL) { - printf("parent %s not found by fischl_load_entry\n", ParentPath); - free(pathdup); - return -1; - } - u_int64_t parent_inode_number = parent_filenode->inode_number; - u_int64_t target_inode = 0; - - // remove its record from parent - INode_Data parent_INode; - parent_INode.inode_num = parent_inode_number; - fs->inode_manager->load_inode(&parent_INode); - if(!permission_check(W_OK, &parent_INode)){ - return -EACCES; - } - char rw_buffer[IO_BLOCK_SIZE] = {0}; - for (u_int64_t idx=0; idxread(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE); - DirectoryEntry ent; - for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){ - ent.deserialize(rw_buffer+i); - if (strcmp(ent.file_name, dirname)==0) { - target_inode = ent.inode_number; - ent.inode_number = 0; - memset(ent.file_name, 0, sizeof(ent.file_name)); - ent.serialize(rw_buffer+i); - break; - } - } - if (target_inode) { - fs->write(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE); - break; - } - } - - // remove inode itself if (target_inode) { - unlink_inode(target_inode); - // remove node itself and from parent hash - fischl_rm_entry(parent_filenode->subdirectory, dirname); - free(pathdup); - return 0; - } else { - printf("cannot find %s in %s", dirname, ParentPath); - free(pathdup); - return -1; + fs->write(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE); + break; } + } + + // remove inode itself + if (target_inode) { + unlink_inode(target_inode); + // remove node itself and from parent hash + fischl_rm_entry(parent_filenode->subdirectory, dirname); + free(pathdup); + return 0; + } else { + printf("cannot find %s in %s", dirname, ParentPath); + free(pathdup); + return -1; + } } int FilesOperation::fischl_chmod(const char *path, mode_t mode, @@ -611,276 +649,298 @@ int FilesOperation::fischl_chown(const char *path, uid_t uid, gid_t gid, INode_Data inode; inode.inode_num = fh; fs->inode_manager->load_inode(&inode); - if(uid != (uid_t)(-1)){ + if (uid != (uid_t)(-1)) { inode.metadata.uid = uid; } - if(gid != (gid_t)(-1)){ + if (gid != (gid_t)(-1)) { inode.metadata.gid = gid; } fs->inode_manager->save_inode(&inode); return 0; } +int FilesOperation::fischl_unlink(const char *path) { -int FilesOperation::fischl_unlink(const char* path) { - - char *pathdup = strdup(path); - char *lastSlash = strrchr(pathdup, '/'); - *lastSlash = '\0'; - char *filename = lastSlash+1; - char *ParentPath = pathdup; - if (!strcmp(filename,".")||!strcmp(filename,"..")) { - printf("refusing to remove . or ..\n"); - return -1; - } - FileNode *parent_filenode = fischl_load_entry(root_node, ParentPath); - if (parent_filenode == NULL) { - printf("parent %s not found by fischl_load_entry\n", ParentPath); - free(pathdup); - return -1; - } - u_int64_t parent_inode_number = parent_filenode->inode_number; - u_int64_t target_inode = 0; - - // remove its record from parent - INode_Data parent_INode; - parent_INode.inode_num = parent_inode_number; - fs->inode_manager->load_inode(&parent_INode); - if(!permission_check(W_OK, &parent_INode)){ - return -EACCES; - } - char rw_buffer[IO_BLOCK_SIZE] = {0}; - for (u_int64_t idx=0; idxread(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE); - DirectoryEntry ent; - for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){ - ent.deserialize(rw_buffer+i); - if (strcmp(ent.file_name, filename)==0) { - target_inode = ent.inode_number; - if(!permission_check_by_inode_num(W_OK, target_inode)){ - return -EACCES; - } - ent.inode_number = 0; - memset(ent.file_name, 0, sizeof(ent.file_name)); - ent.serialize(rw_buffer+i); - break; - } - } - if (target_inode) { - fs->write(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE); - break; - } - } - - // remove inode itself - if (target_inode) { - unlink_inode(target_inode); - // remove node itself and from parent hash - fischl_rm_entry(parent_filenode->subdirectory, filename); - free(pathdup); - return 0; - } else { - printf("cannot find %s in %s", filename, ParentPath); - free(pathdup); - return -1; - } -} - -int FilesOperation::fischl_open(const char *path, struct fuse_file_info *fi){ - /*Creation (O_CREAT, O_EXCL, O_NOCTTY) flags will be filtered out / handled by the kernel. - if no files will use create function - */ - FileNode *get_file; - if((get_file = fischl_load_entry(root_node, path)) == NULL) - return -ENOENT; - - INode_Data inode; - inode.inode_num = get_file->inode_number; - - fs->inode_manager->load_inode(&inode); - - if (fi->flags & O_WRONLY){ - if (!permission_check(W_OK, &inode)) { - return -EACCES; // Permission denied - } - } - if (fi->flags & O_RDONLY){ - if (!permission_check(R_OK, &inode)) { - return -EACCES; // Permission denied - } - } - if (fi->flags & O_RDWR){ - if (!permission_check(R_OK|W_OK, &inode)) { - return -EACCES; // Permission denied - } - } - - //if need to do with flag fi->flags ((fi->flags & O_ACCMODE)). Initial setting ALL access - //create function will handle file descriptor fi->fh - fi->fh = get_file->inode_number; - return 0;//SUCESS -} - -int FilesOperation::fischl_release(const char *path, struct fuse_file_info *fi){ - /*Creation (O_CREAT, O_EXCL, O_NOCTTY) flags will be filtered out / handled by the kernel. - if no files will use create function - */ - FileNode *get_file; - if((get_file = fischl_load_entry(root_node, path)) == NULL) - return -ENOENT; - //do with file descriptor that cannot be used - fi->fh = -1; - return 0;//SUCESS -} - -int FilesOperation::fischl_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi){ - /** Write data to an open file - * - * Write should return exactly the number of bytes requested - * except on error. An exception to this is when the 'direct_io' - * mount option is specified (see read operation). - * - * Unless FUSE_CAP_HANDLE_KILLPRIV is disabled, this method is - * expected to reset the setuid and setgid bits. - */ - // use path for debug, filedescriptor is enough - // FileNode *get_file; - // if((get_file = fischl_load_entry(root_node, path)) == NULL) - // return -ENOENT; - // Caution! this based on content in file are multiple of IO_BLOCK_SIZE, not the exact write size. - // based on current write_datablock API implement, when write_datablock pass with actual size not index this function should be fixed - - INode_Data inode; - // Assuming inode is correctly initialized here based on 'path' - inode.inode_num = fi->fh; - fs->inode_manager->load_inode(&inode); - //size_t len = (inode.metadata.size/IO_BLOCK_SIZE) * IO_BLOCK_SIZE; // Assuming each block is 4096 bytes - // Determine the length of the buffer - // Allocate memory for the new buffer - char* buffer = (char*)malloc(size); - memcpy(buffer, buf, size); - ssize_t bytes_write = fs->write(&inode, buffer, size, offset); - /*size_t block_index = offset / IO_BLOCK_SIZE; // Starting block index - size_t block_offset = offset % IO_BLOCK_SIZE; // Offset within the first block - while (bytes_write < size) { - char block_buffer[IO_BLOCK_SIZE]; // Temporary buffer for each block - size_t copy_size = std::min(size - bytes_write, IO_BLOCK_SIZE - block_offset); - memcpy(block_buffer + block_offset, buf + bytes_write, copy_size); - fs->write(&inode, block_buffer, IO_BLOCK_SIZE, block_index*IO_BLOCK_SIZE); - // fprintf(stderr,"[%s ,%d] inode.size %d, block_index %d, block_buffer %s\n",__func__,__LINE__, inode.size, block_index, block_buffer); - bytes_write += copy_size; - block_index++; - block_offset = 0; // Only the first block might have a non-zero offset - }*/ - fs->inode_manager->save_inode(&inode); - free(buffer); - return bytes_write; // Return the actual number of bytes read -} - -int FilesOperation::fischl_readlink(const char* path, char* buf, size_t size){ - FileNode *get_file; - if((get_file = fischl_load_entry(root_node, path)) == NULL) - return -ENOENT; - INode_Data symlink_inode; - symlink_inode.inode_num = get_file->inode_number; - fs->inode_manager->load_inode(&symlink_inode); - if(!permission_check(R_OK, &symlink_inode)){ - return -EACCES; - } - //char buffer[symlink_inode.metadata.size]; - //memset(buffer, 0, sizeof(buffer)); - fs->read(&symlink_inode, buf, symlink_inode.metadata.size, 0); - buf[symlink_inode.metadata.size] = 0; - //printf("READLINK %d %s\n", symlink_inode.metadata.size, buf); - /*u_int64_t fh = namei(buffer); - if (fh == -1){ - return -ENOENT; - } - INode_Data inode; - // Assuming inode is correctly initialized here based on 'path' - inode.inode_num = fh; - fs->inode_manager->load_inode(&inode); - size_t bytes_read = fs->read(&inode, buf, size, 0); - printf("READLINK %d %s\n", bytes_read, buf);*/ - return 0; -} - -int FilesOperation::fischl_symlink(const char* to, const char* from){ - //check path - //printf("SYMLINK %s %s\n", from, to); - char *pathdup = strdup(from); - char *lastSlash = strrchr(pathdup, '/'); - *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 - // fprintf(stderr,"[%s ,%d] ParentPath:%s, strlen=%d\n",__func__,__LINE__, ParentPath, strlen(ParentPath)); - FileNode *parent_filenode = strlen(ParentPath)? fischl_load_entry(root_node, ParentPath): root_node->self_info; - if (parent_filenode == NULL) { - fprintf(stderr,"[%s ,%d] ParentPath:{%s} not found\n",__func__,__LINE__, ParentPath); - free(pathdup); - return -ENOENT; - } - u_int64_t parent_inode_number = parent_filenode->inode_number; - if(!permission_check_by_inode_num(W_OK, parent_inode_number)){ - return -EACCES; - } - //make new inode - INode_Data* ret = create_new_inode(parent_inode_number, newFilename, S_IFLNK|0777); - if (ret == NULL) return -1;//ENOSPC but create_new_inode handle ENAMETOOLONG EEXIST - //make new node in RAM - fischl_add_entry(parent_filenode->subdirectory, ret->inode_num, newFilename, ret); - size_t size = strlen(to); - char* buffer = (char*)malloc(size); - memcpy(buffer, to, size); - //printf("%d %s\n", size, buffer); - size_t bytes_write = fs->write(ret, buffer, size, 0); - free(buffer); + char *pathdup = strdup(path); + char *lastSlash = strrchr(pathdup, '/'); + *lastSlash = '\0'; + char *filename = lastSlash + 1; + char *ParentPath = pathdup; + if (!strcmp(filename, ".") || !strcmp(filename, "..")) { + printf("refusing to remove . or ..\n"); + return -1; + } + FileNode *parent_filenode = fischl_load_entry(root_node, ParentPath); + if (parent_filenode == NULL) { + printf("parent %s not found by fischl_load_entry\n", ParentPath); free(pathdup); - fs->inode_manager->save_inode(ret); - //printf("%d %d %llu\n", bytes_write, ret->metadata.size, ret->inode_num); - return 0;//SUCESS + return -1; + } + u_int64_t parent_inode_number = parent_filenode->inode_number; + u_int64_t target_inode = 0; + + // remove its record from parent + INode_Data parent_INode; + parent_INode.inode_num = parent_inode_number; + fs->inode_manager->load_inode(&parent_INode); + if (!permission_check(W_OK, &parent_INode)) { + return -EACCES; + } + char rw_buffer[IO_BLOCK_SIZE] = {0}; + for (u_int64_t idx = 0; idx < parent_INode.metadata.size / IO_BLOCK_SIZE; + idx++) { + fs->read(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE); + DirectoryEntry ent; + for (int i = 0; i <= IO_BLOCK_SIZE - 264; i += 264) { + ent.deserialize(rw_buffer + i); + if (strcmp(ent.file_name, filename) == 0) { + target_inode = ent.inode_number; + if (!permission_check_by_inode_num(W_OK, target_inode)) { + return -EACCES; + } + ent.inode_number = 0; + memset(ent.file_name, 0, sizeof(ent.file_name)); + ent.serialize(rw_buffer + i); + break; + } + } + if (target_inode) { + fs->write(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE); + break; + } + } + + // remove inode itself + if (target_inode) { + unlink_inode(target_inode); + // remove node itself and from parent hash + fischl_rm_entry(parent_filenode->subdirectory, filename); + free(pathdup); + return 0; + } else { + printf("cannot find %s in %s", filename, ParentPath); + free(pathdup); + return -1; + } } -int FilesOperation::insert_inode_to(u_int64_t parent_inode_number, const char* name, INode_Data *new_inode, bool check_replace) { - // trys to create a file under parent directory - if (strlen(name)>=256) { - perror("Name too long, cannot create file or directory"); - return -1; - } - INode_Data inode; - inode.inode_num = parent_inode_number; - fs->inode_manager->load_inode(&inode); - if ((inode.metadata.permissions & S_IFMT) != S_IFDIR) { - fprintf(stderr,"[%s ,%d] please create under directory\n",__func__,__LINE__); - return -1; - } +int FilesOperation::fischl_open(const char *path, struct fuse_file_info *fi) { + /*Creation (O_CREAT, O_EXCL, O_NOCTTY) flags will be filtered out / handled by + the kernel. if no files will use create function + */ + FileNode *get_file; + if ((get_file = fischl_load_entry(root_node, path)) == NULL) + return -ENOENT; - // Check if file or directory already exists - char r_buffer[IO_BLOCK_SIZE] = {0}; - for (u_int64_t idx=0; idxread(&inode, r_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE); - DirectoryEntry ent; - for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){ - ent.deserialize(r_buffer+i); - if (strcmp(ent.file_name, name)==0 && ent.inode_number != 0) { - if(check_replace){ - if((new_inode->metadata.permissions & S_IFMT) == S_IFDIR){ - fprintf(stderr,"[%s ,%d] %s/ already exists\n",__func__,__LINE__, name); - }else{ - fprintf(stderr,"[%s ,%d] %s already exists\n",__func__,__LINE__, name); - } - return -1; - } - else{ - //printf("RENAME HAPPENS %s %s\n", ); - ent.inode_number = new_inode->inode_num; - ent.serialize(r_buffer+i); - fs->write(&inode, r_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE); - return 0; - } - } - } + INode_Data inode; + inode.inode_num = get_file->inode_number; + + fs->inode_manager->load_inode(&inode); + + if (fi->flags & O_WRONLY) { + if (!permission_check(W_OK, &inode)) { + return -EACCES; // Permission denied } + } + if (fi->flags & O_RDONLY) { + if (!permission_check(R_OK, &inode)) { + return -EACCES; // Permission denied + } + } + if (fi->flags & O_RDWR) { + if (!permission_check(R_OK | W_OK, &inode)) { + return -EACCES; // Permission denied + } + } + + // if need to do with flag fi->flags ((fi->flags & O_ACCMODE)). Initial + // setting ALL access create function will handle file descriptor fi->fh + fi->fh = get_file->inode_number; + return 0; // SUCESS +} + +int FilesOperation::fischl_release(const char *path, + struct fuse_file_info *fi) { + /*Creation (O_CREAT, O_EXCL, O_NOCTTY) flags will be filtered out / handled by + the kernel. if no files will use create function + */ + FileNode *get_file; + if ((get_file = fischl_load_entry(root_node, path)) == NULL) + return -ENOENT; + // do with file descriptor that cannot be used + fi->fh = -1; + return 0; // SUCESS +} + +int FilesOperation::fischl_write(const char *path, const char *buf, size_t size, + off_t offset, struct fuse_file_info *fi) { + /** Write data to an open file + * + * Write should return exactly the number of bytes requested + * except on error. An exception to this is when the 'direct_io' + * mount option is specified (see read operation). + * + * Unless FUSE_CAP_HANDLE_KILLPRIV is disabled, this method is + * expected to reset the setuid and setgid bits. + */ + // use path for debug, filedescriptor is enough + // FileNode *get_file; + // if((get_file = fischl_load_entry(root_node, path)) == NULL) + // return -ENOENT; + // Caution! this based on content in file are multiple of IO_BLOCK_SIZE, not + // the exact write size. based on current write_datablock API implement, when + // write_datablock pass with actual size not index this function should be + // fixed + + INode_Data inode; + // Assuming inode is correctly initialized here based on 'path' + inode.inode_num = fi->fh; + fs->inode_manager->load_inode(&inode); + // size_t len = (inode.metadata.size/IO_BLOCK_SIZE) * IO_BLOCK_SIZE; // + // Assuming each block is 4096 bytes + // Determine the length of the buffer + // Allocate memory for the new buffer + char *buffer = (char *)malloc(size); + memcpy(buffer, buf, size); + ssize_t bytes_write = fs->write(&inode, buffer, size, offset); + /*size_t block_index = offset / IO_BLOCK_SIZE; // Starting block index + size_t block_offset = offset % IO_BLOCK_SIZE; // Offset within the first block + while (bytes_write < size) { + char block_buffer[IO_BLOCK_SIZE]; // Temporary buffer for each block + size_t copy_size = std::min(size - bytes_write, IO_BLOCK_SIZE - + block_offset); memcpy(block_buffer + block_offset, buf + bytes_write, + copy_size); fs->write(&inode, block_buffer, IO_BLOCK_SIZE, + block_index*IO_BLOCK_SIZE); + // fprintf(stderr,"[%s ,%d] inode.size %d, block_index %d, block_buffer + %s\n",__func__,__LINE__, inode.size, block_index, block_buffer); bytes_write + += copy_size; block_index++; block_offset = 0; // Only the first block might + have a non-zero offset + }*/ + fs->inode_manager->save_inode(&inode); + free(buffer); + if (bytes_write < 0) + return -errno; + return bytes_write; // Return the actual number of bytes read +} + +int FilesOperation::fischl_readlink(const char *path, char *buf, size_t size) { + FileNode *get_file; + if ((get_file = fischl_load_entry(root_node, path)) == NULL) + return -ENOENT; + INode_Data symlink_inode; + symlink_inode.inode_num = get_file->inode_number; + fs->inode_manager->load_inode(&symlink_inode); + if (!permission_check(R_OK, &symlink_inode)) { + return -EACCES; + } + // char buffer[symlink_inode.metadata.size]; + // memset(buffer, 0, sizeof(buffer)); + fs->read(&symlink_inode, buf, symlink_inode.metadata.size, 0); + buf[symlink_inode.metadata.size] = 0; + // printf("READLINK %d %s\n", symlink_inode.metadata.size, buf); + /*u_int64_t fh = namei(buffer); + if (fh == -1){ + return -ENOENT; + } + INode_Data inode; + // Assuming inode is correctly initialized here based on 'path' + inode.inode_num = fh; + fs->inode_manager->load_inode(&inode); + size_t bytes_read = fs->read(&inode, buf, size, 0); + printf("READLINK %d %s\n", bytes_read, buf);*/ + return 0; +} + +int FilesOperation::fischl_symlink(const char *to, const char *from) { + // check path + // printf("SYMLINK %s %s\n", from, to); + char *pathdup = strdup(from); + char *lastSlash = strrchr(pathdup, '/'); + *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 + // fprintf(stderr,"[%s ,%d] ParentPath:%s, strlen=%d\n",__func__,__LINE__, + // ParentPath, strlen(ParentPath)); + FileNode *parent_filenode = strlen(ParentPath) + ? fischl_load_entry(root_node, ParentPath) + : root_node->self_info; + if (parent_filenode == NULL) { + fprintf(stderr, "[%s ,%d] ParentPath:{%s} not found\n", __func__, __LINE__, + ParentPath); + free(pathdup); + return -ENOENT; + } + u_int64_t parent_inode_number = parent_filenode->inode_number; + if (!permission_check_by_inode_num(W_OK, parent_inode_number)) { + return -EACCES; + } + // make new inode + INode_Data *ret = + create_new_inode(parent_inode_number, newFilename, S_IFLNK | 0777); + if (ret == NULL) + return -1; // ENOSPC but create_new_inode handle ENAMETOOLONG EEXIST + // make new node in RAM + fischl_add_entry(parent_filenode->subdirectory, ret->inode_num, newFilename, + ret); + size_t size = strlen(to); + char *buffer = (char *)malloc(size); + memcpy(buffer, to, size); + // printf("%d %s\n", size, buffer); + size_t bytes_write = fs->write(ret, buffer, size, 0); + free(buffer); + free(pathdup); + fs->inode_manager->save_inode(ret); + // printf("%d %d %llu\n", bytes_write, ret->metadata.size, ret->inode_num); + return 0; // SUCESS +} + +int FilesOperation::insert_inode_to(u_int64_t parent_inode_number, + const char *name, INode_Data *new_inode, + bool check_replace) { + // trys to create a file under parent directory + if (strlen(name) >= 256) { + perror("Name too long, cannot create file or directory"); + return -1; + } + INode_Data inode; + inode.inode_num = parent_inode_number; + fs->inode_manager->load_inode(&inode); + if ((inode.metadata.permissions & S_IFMT) != S_IFDIR) { + fprintf(stderr, "[%s ,%d] please create under directory\n", __func__, + __LINE__); + return -1; + } + + // Check if file or directory already exists + char r_buffer[IO_BLOCK_SIZE] = {0}; + for (u_int64_t idx = 0; idx < inode.metadata.size / IO_BLOCK_SIZE; idx++) { + fs->read(&inode, r_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE); + DirectoryEntry ent; + for (int i = 0; i <= IO_BLOCK_SIZE - 264; i += 264) { + ent.deserialize(r_buffer + i); + if (strcmp(ent.file_name, name) == 0 && ent.inode_number != 0) { + if (check_replace) { + if ((new_inode->metadata.permissions & S_IFMT) == S_IFDIR) { + fprintf(stderr, "[%s ,%d] %s/ already exists\n", __func__, __LINE__, + name); + } else { + fprintf(stderr, "[%s ,%d] %s already exists\n", __func__, __LINE__, + name); + } + return -1; + } else { + // printf("RENAME HAPPENS %s %s\n", ); + ent.inode_number = new_inode->inode_num; + ent.serialize(r_buffer + i); + fs->write(&inode, r_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE); + return 0; + } + } + } + } bool allocated = false; @@ -918,238 +978,270 @@ int FilesOperation::insert_inode_to(u_int64_t parent_inode_number, const char* n return 0; } -int FilesOperation::fischl_link(const char* from, const char* to){ +int FilesOperation::fischl_link(const char *from, const char *to) { - FileNode *get_file; - if((get_file = fischl_load_entry(root_node, from)) == NULL) - return -ENOENT; - INode_Data ret; - ret.inode_num = get_file->inode_number; - fs->inode_manager->load_inode(&ret); - - //check path - char *pathdup = strdup(to); - char *lastSlash = strrchr(pathdup, '/'); - *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 - // fprintf(stderr,"[%s ,%d] ParentPath:%s, strlen=%d\n",__func__,__LINE__, ParentPath, strlen(ParentPath)); - FileNode *parent_filenode = strlen(ParentPath)? fischl_load_entry(root_node, ParentPath): root_node->self_info; - if (parent_filenode == NULL) { - fprintf(stderr,"[%s ,%d] ParentPath:{%s} not found\n",__func__,__LINE__, ParentPath); - free(pathdup); - return -1; - } + FileNode *get_file; + if ((get_file = fischl_load_entry(root_node, from)) == NULL) + return -ENOENT; + INode_Data ret; + ret.inode_num = get_file->inode_number; + fs->inode_manager->load_inode(&ret); - u_int64_t parent_inode_number = parent_filenode->inode_number; - if(!permission_check_by_inode_num(W_OK, parent_inode_number)){ - return -EACCES; - } - if(insert_inode_to(parent_inode_number, newFilename, &ret, true)<0){ - return -1; - } - - ret.metadata.reference_count += 1; - fs->inode_manager->save_inode(&ret); - fischl_add_entry(parent_filenode->subdirectory, ret.inode_num, newFilename, &ret); + // check path + char *pathdup = strdup(to); + char *lastSlash = strrchr(pathdup, '/'); + *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 + // fprintf(stderr,"[%s ,%d] ParentPath:%s, strlen=%d\n",__func__,__LINE__, + // ParentPath, strlen(ParentPath)); + FileNode *parent_filenode = strlen(ParentPath) + ? fischl_load_entry(root_node, ParentPath) + : root_node->self_info; + if (parent_filenode == NULL) { + fprintf(stderr, "[%s ,%d] ParentPath:{%s} not found\n", __func__, __LINE__, + ParentPath); free(pathdup); - return 0; + return -1; + } + + u_int64_t parent_inode_number = parent_filenode->inode_number; + if (!permission_check_by_inode_num(W_OK, parent_inode_number)) { + return -EACCES; + } + if (insert_inode_to(parent_inode_number, newFilename, &ret, true) < 0) { + return -1; + } + + ret.metadata.reference_count += 1; + fs->inode_manager->save_inode(&ret); + fischl_add_entry(parent_filenode->subdirectory, ret.inode_num, newFilename, + &ret); + free(pathdup); + return 0; } - // TODO: rename dir and rename fail -int FilesOperation::fischl_rename(const char *old_path, const char *new_path, unsigned int flags){ - //find old path - char *pathdup = strdup(old_path); - char *lastSlash = strrchr(pathdup, '/'); - *lastSlash = '\0'; - char *filename = lastSlash+1; - char *oldParentPath = pathdup; - if (!strcmp(filename,".")||!strcmp(filename,"..")) { - printf("refuse to remove . or ..\n"); - return -1; - } - //put old path info in rename struct - RenameInfo rename_info; - rename_info.exchangeExist = false; - rename_info.oldParentNode = fischl_load_entry(root_node, oldParentPath); - //if path end with / means to rename directory - rename_info.oldFileNode = strlen(filename)? fischl_load_entry(rename_info.oldParentNode->subdirectory, filename):rename_info.oldParentNode; +int FilesOperation::fischl_rename(const char *old_path, const char *new_path, + unsigned int flags) { + // find old path + char *pathdup = strdup(old_path); + char *lastSlash = strrchr(pathdup, '/'); + *lastSlash = '\0'; + char *filename = lastSlash + 1; + char *oldParentPath = pathdup; + if (!strcmp(filename, ".") || !strcmp(filename, "..")) { + printf("refuse to remove . or ..\n"); + return -1; + } + // put old path info in rename struct + RenameInfo rename_info; + rename_info.exchangeExist = false; + rename_info.oldParentNode = fischl_load_entry(root_node, oldParentPath); + // if path end with / means to rename directory + rename_info.oldFileNode = + strlen(filename) + ? fischl_load_entry(rename_info.oldParentNode->subdirectory, filename) + : rename_info.oldParentNode; - if (rename_info.oldFileNode == NULL) { - fprintf(stderr,"[%s ,%d] path %s not found by fischl_load_entry\n",__func__,__LINE__, old_path); - free(pathdup); - return -ENOENT; - } - - //find new path - char *new_pathdup = strdup(new_path); - lastSlash = strrchr(new_pathdup, '/'); - *lastSlash = '\0'; // Split the string into parent path and new directory name; \0 - char *newParentPath = new_pathdup;//pathdup are separated by pathdup, so it take only - //put new path info in rename struct - rename_info.newName = lastSlash+1; //\0, get from - rename_info.newFileNode = fischl_load_entry(root_node, new_path); - rename_info.newParentNode = strlen(newParentPath)? fischl_load_entry(root_node, newParentPath): root_node->self_info; - - if(!permission_check_by_inode_num(W_OK, rename_info.oldParentNode->inode_number)){ - return -EACCES; - } - if(!permission_check_by_inode_num(W_OK, rename_info.newParentNode->inode_number)){ - return -EACCES; - } - if(!permission_check_by_inode_num(W_OK, rename_info.oldFileNode->inode_number)){ - return -EACCES; - } - if(rename_info.newFileNode != NULL && !permission_check_by_inode_num(W_OK, rename_info.newFileNode->inode_number)){ - return -EACCES; - } + if (rename_info.oldFileNode == NULL) { + fprintf(stderr, "[%s ,%d] path %s not found by fischl_load_entry\n", + __func__, __LINE__, old_path); + free(pathdup); + return -ENOENT; + } - //configure with flag - if (flags & RENAME_NOREPLACE) { - // Check if newpath exists and return error if it does - if(rename_info.newFileNode != NULL){ - fprintf(stderr,"[%s ,%d] newpath has already existed\n",__func__,__LINE__); - free(new_pathdup);//new path - free(pathdup);//old path - return -1; - } - } + // find new path + char *new_pathdup = strdup(new_path); + lastSlash = strrchr(new_pathdup, '/'); + *lastSlash = '\0'; // Split the string into parent path and new directory + // name; \0 + char *newParentPath = new_pathdup; // pathdup are separated by pathdup, so it + // take only + // put new path info in rename struct + rename_info.newName = + lastSlash + 1; //\0, get from + rename_info.newFileNode = fischl_load_entry(root_node, new_path); + rename_info.newParentNode = strlen(newParentPath) + ? fischl_load_entry(root_node, newParentPath) + : root_node->self_info; - if (flags & RENAME_EXCHANGE) { - // Ensure both oldpath and newpath exist and exchange them atomically - if(rename_info.newFileNode == NULL){ - fprintf(stderr,"[%s ,%d] newpath does not exist cannot exchange\n",__func__,__LINE__); - free(new_pathdup); - free(pathdup); - return -1; - } - rename_info.exchangeExist = true; - INode_Data parent_INode; - parent_INode.inode_num = rename_info.newParentNode->inode_number; - fs->inode_manager->load_inode(&parent_INode); - char rw_buffer[IO_BLOCK_SIZE] = {0}; - - bool change_flag = false; - //delete record on old path - for (u_int64_t idx=0; idxread(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE); - DirectoryEntry ent; - for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){ - ent.deserialize(rw_buffer+i); - if (ent.inode_number == rename_info.newFileNode->inode_number) { - change_flag = true;//should be change - strncpy(ent.file_name, filename, sizeof(ent.file_name) - 1); - ent.file_name[sizeof(ent.file_name) - 1] = '\0'; - ent.serialize(rw_buffer+i); - break; - } - } - if (change_flag) { - fs->write(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE); - change_flag = false; - break; - } - } - parent_INode.inode_num = rename_info.oldParentNode->inode_number; - fs->inode_manager->load_inode(&parent_INode); - - change_flag = false; - //delete record on old path - for (u_int64_t idx=0; idxread(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE); - DirectoryEntry ent; - for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){ - ent.deserialize(rw_buffer+i); - if (ent.inode_number == rename_info.oldFileNode->inode_number) { - change_flag = true;//should be change - strncpy(ent.file_name, rename_info.newName, sizeof(ent.file_name) - 1); - ent.file_name[sizeof(ent.file_name) - 1] = '\0'; - ent.serialize(rw_buffer+i); - break; - } - } - if (change_flag) { - fs->write(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE); - change_flag = false; - break; - } - } - fischl_rm_entry(rename_info.oldParentNode->subdirectory, filename); - fischl_rm_entry(rename_info.newParentNode->subdirectory, rename_info.newName); - return 0; - } - - // Normal rename logic if no flags are specified; can overwirte - // Hard Disk rename - if(rename_info.oldFileNode->subdirectory != NULL){//secure its directory - //remove its record from subdirectory; find .. from subdirectory + if (!permission_check_by_inode_num(W_OK, + rename_info.oldParentNode->inode_number)) { + return -EACCES; + } + if (!permission_check_by_inode_num(W_OK, + rename_info.newParentNode->inode_number)) { + return -EACCES; + } + if (!permission_check_by_inode_num(W_OK, + rename_info.oldFileNode->inode_number)) { + return -EACCES; + } + if (rename_info.newFileNode != NULL && + !permission_check_by_inode_num(W_OK, + rename_info.newFileNode->inode_number)) { + return -EACCES; + } + // configure with flag + if (flags & RENAME_NOREPLACE) { + // Check if newpath exists and return error if it does + if (rename_info.newFileNode != NULL) { + fprintf(stderr, "[%s ,%d] newpath has already existed\n", __func__, + __LINE__); + free(new_pathdup); // new path + free(pathdup); // old path + return -1; } - // remove its record from parent + } + + if (flags & RENAME_EXCHANGE) { + // Ensure both oldpath and newpath exist and exchange them atomically + if (rename_info.newFileNode == NULL) { + fprintf(stderr, "[%s ,%d] newpath does not exist cannot exchange\n", + __func__, __LINE__); + free(new_pathdup); + free(pathdup); + return -1; + } + rename_info.exchangeExist = true; INode_Data parent_INode; - parent_INode.inode_num = rename_info.oldParentNode->inode_number; + parent_INode.inode_num = rename_info.newParentNode->inode_number; fs->inode_manager->load_inode(&parent_INode); char rw_buffer[IO_BLOCK_SIZE] = {0}; - - // relocate the old path file to new path - INode_Data ret; - ret.inode_num = rename_info.oldFileNode->inode_number; - fs->inode_manager->load_inode(&ret); - if(insert_inode_to(rename_info.newParentNode->inode_number, rename_info.newName, &ret, false)<0){ - return -1; - } + bool change_flag = false; - //delete record on old path - for (u_int64_t idx=0; idxread(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE); - DirectoryEntry ent; - for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){ - ent.deserialize(rw_buffer+i); - if (strcmp(ent.file_name, filename)==0) { - change_flag = true;//should be change - ent.inode_number = 0; - memset(ent.file_name, 0, sizeof(ent.file_name)); - ent.serialize(rw_buffer+i); - break; - } - } - if (change_flag) { - fs->write(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE); - change_flag = false; - break; + // delete record on old path + for (u_int64_t idx = 0; idx < parent_INode.metadata.size / IO_BLOCK_SIZE; + idx++) { + fs->read(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE); + DirectoryEntry ent; + for (int i = 0; i <= IO_BLOCK_SIZE - 264; i += 264) { + ent.deserialize(rw_buffer + i); + if (ent.inode_number == rename_info.newFileNode->inode_number) { + change_flag = true; // should be change + strncpy(ent.file_name, filename, sizeof(ent.file_name) - 1); + ent.file_name[sizeof(ent.file_name) - 1] = '\0'; + ent.serialize(rw_buffer + i); + break; } + } + if (change_flag) { + fs->write(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE); + change_flag = false; + break; + } } - if(rename_info.newParentNode != NULL){ - fischl_rm_entry(rename_info.newParentNode->subdirectory, rename_info.newName); + parent_INode.inode_num = rename_info.oldParentNode->inode_number; + fs->inode_manager->load_inode(&parent_INode); + + change_flag = false; + // delete record on old path + for (u_int64_t idx = 0; idx < parent_INode.metadata.size / IO_BLOCK_SIZE; + idx++) { + fs->read(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE); + DirectoryEntry ent; + for (int i = 0; i <= IO_BLOCK_SIZE - 264; i += 264) { + ent.deserialize(rw_buffer + i); + if (ent.inode_number == rename_info.oldFileNode->inode_number) { + change_flag = true; // should be change + strncpy(ent.file_name, rename_info.newName, + sizeof(ent.file_name) - 1); + ent.file_name[sizeof(ent.file_name) - 1] = '\0'; + ent.serialize(rw_buffer + i); + break; + } + } + if (change_flag) { + fs->write(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE); + change_flag = false; + break; + } } fischl_rm_entry(rename_info.oldParentNode->subdirectory, filename); - - //free path - free(pathdup); - free(new_pathdup); + fischl_rm_entry(rename_info.newParentNode->subdirectory, + rename_info.newName); return 0; + } + + // Normal rename logic if no flags are specified; can overwirte + // Hard Disk rename + if (rename_info.oldFileNode->subdirectory != NULL) { // secure its directory + // remove its record from subdirectory; find .. from subdirectory + } + // remove its record from parent + INode_Data parent_INode; + parent_INode.inode_num = rename_info.oldParentNode->inode_number; + fs->inode_manager->load_inode(&parent_INode); + char rw_buffer[IO_BLOCK_SIZE] = {0}; + + // relocate the old path file to new path + INode_Data ret; + ret.inode_num = rename_info.oldFileNode->inode_number; + fs->inode_manager->load_inode(&ret); + if (insert_inode_to(rename_info.newParentNode->inode_number, + rename_info.newName, &ret, false) < 0) { + return -1; + } + bool change_flag = false; + // delete record on old path + for (u_int64_t idx = 0; idx < parent_INode.metadata.size / IO_BLOCK_SIZE; + idx++) { + fs->read(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE); + DirectoryEntry ent; + for (int i = 0; i <= IO_BLOCK_SIZE - 264; i += 264) { + ent.deserialize(rw_buffer + i); + if (strcmp(ent.file_name, filename) == 0) { + change_flag = true; // should be change + ent.inode_number = 0; + memset(ent.file_name, 0, sizeof(ent.file_name)); + ent.serialize(rw_buffer + i); + break; + } + } + if (change_flag) { + fs->write(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE); + change_flag = false; + break; + } + } + if (rename_info.newParentNode != NULL) { + fischl_rm_entry(rename_info.newParentNode->subdirectory, + rename_info.newName); + } + fischl_rm_entry(rename_info.oldParentNode->subdirectory, filename); + + // free path + free(pathdup); + free(new_pathdup); + return 0; } int FilesOperation::fischl_truncate(const char *path, off_t offset, struct fuse_file_info *fi) { - (void)fi; - int res = 0; - u_int64_t fh = namei(path); + (void)fi; + int res = 0; + u_int64_t fh = namei(path); - if (fh == -1) { - return -ENOENT; - } + if (fh == -1) { + return -ENOENT; + } - INode_Data inode; - inode.inode_num = fh; - fs->inode_manager->load_inode(&inode); - if(!permission_check(W_OK, &inode)){ - return -EACCES; - } - res = fs->truncate(&inode, offset); - fs->inode_manager->save_inode(&inode); - return res; + INode_Data inode; + inode.inode_num = fh; + fs->inode_manager->load_inode(&inode); + if (!permission_check(W_OK, &inode)) { + return -EACCES; + } + res = fs->truncate(&inode, offset); + fs->inode_manager->save_inode(&inode); + if (res < 0) + return -errno; + return res; } int FilesOperation::fischl_read(const char *path, char *buf, size_t size, @@ -1171,11 +1263,12 @@ int FilesOperation::fischl_read(const char *path, char *buf, size_t size, // Assuming inode is correctly initialized here based on 'path' inode.inode_num = fi->fh; fs->inode_manager->load_inode(&inode); - //printf("OUT READ %llu %llu %llu\n", inode.inode_num, inode.single_indirect_block, inode.double_indirect_block); + // printf("OUT READ %llu %llu %llu\n", inode.inode_num, + // inode.single_indirect_block, inode.double_indirect_block); ssize_t bytes_read = fs->read(&inode, buf, size, offset); - //printf("BYTES_READ %d\n",int(bytes_read)); - //for (int i = 0; i < bytes_read; i++)printf("%x", buf[i]&0xff); - //printf("\n"); + // printf("BYTES_READ %d\n",int(bytes_read)); + // for (int i = 0; i < bytes_read; i++)printf("%x", buf[i]&0xff); + // printf("\n"); /*size_t len = (inode.metadata.size/IO_BLOCK_SIZE) * IO_BLOCK_SIZE; // Assuming each block is 4096 bytes @@ -1199,33 +1292,40 @@ int FilesOperation::fischl_read(const char *path, char *buf, size_t size, buf, block_buffer); bytes_read += copy_size; block_index++; block_offset = 0; // Only the first block might have a non-zero offset }*/ + + if (bytes_read < 0) + return -errno; return bytes_read; // Return the actual number of bytes read } -int FilesOperation::fischl_utimens(const char *path, const struct timespec tv[2], struct fuse_file_info *fi){ - (void) fi; - int res = 0; - u_int64_t fh = namei(path); +int FilesOperation::fischl_utimens(const char *path, + const struct timespec tv[2], + struct fuse_file_info *fi) { + (void)fi; + int res = 0; + u_int64_t fh = namei(path); - if (fh == -1){ - return -ENOENT; - } + if (fh == -1) { + return -ENOENT; + } - INode_Data inode; - inode.inode_num = fh; - fs->inode_manager->load_inode(&inode); - inode.metadata.access_time = (u_int64_t)tv[0].tv_sec * 1000000000ULL + tv[0].tv_nsec; - inode.metadata.modification_time = (u_int64_t)tv[1].tv_sec * 1000000000ULL + tv[1].tv_nsec; - fs->inode_manager->save_inode(&inode); - return 0; + INode_Data inode; + inode.inode_num = fh; + fs->inode_manager->load_inode(&inode); + inode.metadata.access_time = + (u_int64_t)tv[0].tv_sec * 1000000000ULL + tv[0].tv_nsec; + inode.metadata.modification_time = + (u_int64_t)tv[1].tv_sec * 1000000000ULL + tv[1].tv_nsec; + fs->inode_manager->save_inode(&inode); + return 0; } -int FilesOperation::fischl_statfs(const char* path, struct statvfs* stbuf) { - stbuf->f_bsize = 4096; - stbuf->f_blocks = 0; - stbuf->f_bfree = 0; - stbuf->f_files = 0; - stbuf->f_ffree = 0; - stbuf->f_namemax = 256; - return 0; +int FilesOperation::fischl_statfs(const char *path, struct statvfs *stbuf) { + stbuf->f_bsize = 4096; + stbuf->f_blocks = 0; + stbuf->f_bfree = 0; + stbuf->f_files = 0; + stbuf->f_ffree = 0; + stbuf->f_namemax = 256; + return 0; } \ No newline at end of file diff --git a/lib/fs/datablock_manager.cpp b/lib/fs/datablock_manager.cpp index 192f463..2d8ff51 100644 --- a/lib/fs/datablock_manager.cpp +++ b/lib/fs/datablock_manager.cpp @@ -52,8 +52,10 @@ int DataBlock_Manager_Bitmap::new_datablock(u_int64_t *block_num) { char zero_buf[IO_BLOCK_SIZE] = {0}; if (bitmap_block_num < block_segment_start || - bitmap_block_num >= block_segment_end) + bitmap_block_num >= block_segment_end) { + perror("Error with new_datablock freelist head\n"); return -1; + } if ((err = fs->disk->read_block(bitmap_block_num, bitmap.buf)) < 0) return err; @@ -64,8 +66,10 @@ int DataBlock_Manager_Bitmap::new_datablock(u_int64_t *block_num) { u_int64_t relative_block_num = bitmap.claim_relative_block(); - if (relative_block_num == 0) + if (relative_block_num == 0) { + errno = ENOSPC; return -1; + } u_int64_t block_num_ = relative_block_num + bitmap_block_num; diff --git a/lib/fs/fs_file_io.cpp b/lib/fs/fs_file_io.cpp index 4182b52..d2951cd 100644 --- a/lib/fs/fs_file_io.cpp +++ b/lib/fs/fs_file_io.cpp @@ -31,7 +31,8 @@ int Fs::sweep_inode_datablocks(INode_Data *inode_data, DatablockOperation *op) { int result; - //printf("SWEEP %llu %llu %llu\n", inode_data->inode_num, inode_data->single_indirect_block, inode_data->double_indirect_block); + // printf("SWEEP %llu %llu %llu\n", inode_data->inode_num, + // inode_data->single_indirect_block, inode_data->double_indirect_block); u_int64_t start_index = start_block_index; for (size_t i = start_index; i < NUMBER_OF_DIRECT_BLOCKS; ++i) { @@ -96,7 +97,8 @@ int Fs::sweep_datablocks(u_int64_t *block_num, int indirect_num, } } - //if((*block_num)>30000000000000LL)printf("DIES 1 %llu %d %llu\n", *block_num, indirect_num, start_block_index); + // if((*block_num)>30000000000000LL)printf("DIES 1 %llu %d %llu\n", + // *block_num, indirect_num, start_block_index); if (indirect_num == 0) { bool delete_block = false; @@ -113,7 +115,7 @@ int Fs::sweep_datablocks(u_int64_t *block_num, int indirect_num, if ((*block_num) == 0) { memset(buf, 0, sizeof(buf)); } else { - + if ((err = disk->read_block(*block_num, buf)) < 0) return err; } @@ -175,7 +177,8 @@ public: std::min(IO_BLOCK_SIZE - offset, count - bytes_completed); if (block_num != 0) { - if((block_num)>3000000000000LL)printf("DIES 2\n"); + if ((block_num) > 3000000000000LL) + printf("DIES 2\n"); if ((err = fs->disk->read_block(block_num, datablock_buf)) < 0) return err; @@ -204,8 +207,9 @@ public: size_t write_size = std::min(IO_BLOCK_SIZE - offset, count - bytes_completed); - if (write_size < IO_BLOCK_SIZE){ - if((block_num)>3000000000000LL)printf("DIES 3\n"); + if (write_size < IO_BLOCK_SIZE) { + if ((block_num) > 3000000000000LL) + printf("DIES 3\n"); if ((err = fs->disk->read_block(block_num, datablock_buf)) < 0) return err; } @@ -235,7 +239,8 @@ public: (*delete_block) = true; return 1; } - if((block_num)>3000000000000LL)printf("DIES 4\n"); + if ((block_num) > 3000000000000LL) + printf("DIES 4\n"); if ((err = fs->disk->read_block(block_num, datablock_buf)) < 0) return err; @@ -289,9 +294,10 @@ ssize_t Fs::read(INode_Data *inode_data, char buf[], size_t count, op.bytes_completed = 0; op.fs = this; - //printf("IN READ %llu %llu %llu\n", inode_data->inode_num, inode_data->single_indirect_block, inode_data->double_indirect_block); + // printf("IN READ %llu %llu %llu\n", inode_data->inode_num, + // inode_data->single_indirect_block, inode_data->double_indirect_block); if ((err = sweep_inode_datablocks(inode_data, start_block_index, false, - &op)) != 0) + &op)) < 0) return err; return op.bytes_completed; @@ -301,6 +307,11 @@ ssize_t Fs::write(INode_Data *inode_data, const char buf[], size_t count, size_t offset) { int err; + if (count + offset > FILE_SIZE_MAX) { + errno = EFBIG; + return -1; + } + u_int64_t start_block_index = offset / IO_BLOCK_SIZE; size_t internal_offset = offset - (start_block_index * IO_BLOCK_SIZE); @@ -311,8 +322,8 @@ ssize_t Fs::write(INode_Data *inode_data, const char buf[], size_t count, op.bytes_completed = 0; op.fs = this; - if ((err = sweep_inode_datablocks(inode_data, start_block_index, true, - &op)) != 0) + if ((err = sweep_inode_datablocks(inode_data, start_block_index, true, &op)) < + 0) return err; inode_data->metadata.size = @@ -321,9 +332,19 @@ ssize_t Fs::write(INode_Data *inode_data, const char buf[], size_t count, return op.bytes_completed; } -int Fs::truncate(INode_Data *inode_data, size_t length) { +int Fs::truncate(INode_Data *inode_data, off_t length) { int err; + if (length > FILE_SIZE_MAX) { + errno = EFBIG; + return -1; + } + + if (length < 0) { + errno = EINVAL; + return -1; + } + u_int64_t start_block_index = length / IO_BLOCK_SIZE; size_t internal_offset = length - (start_block_index * IO_BLOCK_SIZE); @@ -343,8 +364,10 @@ int Fs::truncate(INode_Data *inode_data, size_t length) { ssize_t Fs::lseek_next_data(INode_Data *inode_data, size_t offset) { int err; - if (offset >= inode_data->metadata.size) + if (offset >= inode_data->metadata.size) { + errno = ENXIO; return -1; + } u_int64_t start_block_index = offset / IO_BLOCK_SIZE; size_t internal_offset = offset - (start_block_index * IO_BLOCK_SIZE); @@ -359,8 +382,10 @@ ssize_t Fs::lseek_next_data(INode_Data *inode_data, size_t offset) { &op)) < 0) return err; - if (op.bytes_completed >= inode_data->metadata.size) + if (op.bytes_completed >= inode_data->metadata.size) { + errno = ENXIO; return -1; + } return op.bytes_completed; } @@ -368,8 +393,10 @@ ssize_t Fs::lseek_next_data(INode_Data *inode_data, size_t offset) { ssize_t Fs::lseek_next_hole(INode_Data *inode_data, size_t offset) { int err; - if (offset >= inode_data->metadata.size) + if (offset >= inode_data->metadata.size) { + errno = ENXIO; return -1; + } u_int64_t start_block_index = offset / IO_BLOCK_SIZE; size_t internal_offset = offset - (start_block_index * IO_BLOCK_SIZE); diff --git a/lib/rawdisk.cpp b/lib/rawdisk.cpp index f6203d0..fb48d18 100644 --- a/lib/rawdisk.cpp +++ b/lib/rawdisk.cpp @@ -43,7 +43,7 @@ RealRawDisk::RealRawDisk(const char *directory) exit(1); } - //diskSize = 27648 * IO_BLOCK_SIZE; + // diskSize = 27648 * IO_BLOCK_SIZE; // Calculate the size in bytes numSectors = diskSize / 512; // Assuming a sector size of 512 bytes @@ -65,16 +65,18 @@ int RealRawDisk::read_block(u_int64_t block_number, char *buffer) { if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) { printf("LSEEK ERROR %llu %llu\n", block_number, offset); perror("Error seeking to offset"); + errno = EIO; return -1; } // TODO: this is incorrect ssize_t bytesRead = read(fd, buffer, IO_BLOCK_SIZE); - //printf("READ BLOCK: %llu\n", block_number); - //for (int i = 0; i < IO_BLOCK_SIZE; i++)printf("%x", buffer[i]&0xff); - //printf("\n"); + // printf("READ BLOCK: %llu\n", block_number); + // for (int i = 0; i < IO_BLOCK_SIZE; i++)printf("%x", buffer[i]&0xff); + // printf("\n"); if (bytesRead < IO_BLOCK_SIZE) { perror("Error reading from device"); + errno = EIO; return -1; } @@ -86,6 +88,7 @@ int RealRawDisk::write_block(u_int64_t block_number, char *buffer) { if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) { perror("Error seeking to offset"); + errno = EIO; return -1; } @@ -93,6 +96,7 @@ int RealRawDisk::write_block(u_int64_t block_number, char *buffer) { ssize_t bytesWritten = write(fd, buffer, IO_BLOCK_SIZE); if (bytesWritten < IO_BLOCK_SIZE) { perror("Error writing to device"); + errno = EIO; return -1; } @@ -118,6 +122,7 @@ int FakeRawDisk::read_block(u_int64_t block_number, char *buffer) { if (offset + IO_BLOCK_SIZE > diskSize) { perror("Error reading past fake disk size"); + errno = EIO; return -1; } @@ -131,6 +136,7 @@ int FakeRawDisk::write_block(u_int64_t block_number, char *buffer) { if (offset + IO_BLOCK_SIZE > diskSize) { perror("Error writing past fake disk size"); + errno = EIO; return -1; }