support unlinking files and directories

This commit is contained in:
Ziao 2023-11-18 20:20:32 -08:00
parent 1e735ea7d0
commit 5dbac3d9e3
3 changed files with 90 additions and 3 deletions

View File

@ -14,11 +14,11 @@ class FilesOperation {
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);
// int unlink_inode(u_int64_t inode_number);
void unlink_inode(u_int64_t inode_number);
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);
//int fischl_readdir(const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *, enum fuse_readdir_flags);
//int fischl_unlink (const char *);
int fischl_unlink (const char *);
//int fischl_open (const char *, struct fuse_file_info *);
};

View File

@ -295,3 +295,76 @@ u_int64_t FilesOperation::fischl_mknod(const char* path, mode_t mode) {
delete pathdup;
return ret;
}
void FilesOperation::unlink_inode(u_int64_t inode_number) {
INode inode;
inode.inode_construct(inode_number, disk);
if ((inode.permissions & S_IFMT) == S_IFDIR) {
char buffer[IO_BLOCK_SIZE] = {0};
for(u_int64_t idx=0; idx<inode.size; idx++) {
read_datablock(inode, idx, buffer);
DirectoryEntry ent;
for(int i=0;i<=IO_BLOCK_SIZE-64;i+=64){
if(ent.inode_number && strcmp(ent.file_name,".") && strcmp(ent.file_name,"..")){
unlink_inode(ent.inode_number);
}
}
}
}
while(inode.size != 0) {
inode.datablock_deallocate(disk);
inode.size--;
}
inop.inode_free(disk, inode_number);
}
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;
}
u_int64_t parent_inode = namei(ParentPath);
if (parent_inode == (u_int64_t)(-1)) {
delete pathdup;
return -1;
}
u_int64_t target_inode = 0;
// remove its record from parent
INode parent_INode;
parent_INode.inode_construct(parent_inode, disk);
char rw_buffer[IO_BLOCK_SIZE] = {0};
for (u_int64_t idx=0; idx<parent_INode.size; idx++) {
read_datablock(parent_INode, idx, rw_buffer);
DirectoryEntry ent;
for(int i=0;i<=IO_BLOCK_SIZE-64;i+=64){
ent.deserialize(rw_buffer+i);
if (strcmp(ent.file_name, filename)==0) {
target_inode = ent.inode_number;
ent.inode_number = 0;
ent.serialize(rw_buffer+i);
break;
}
}
if (target_inode) {
write_datablock(parent_INode, idx, rw_buffer);
break;
}
}
// remove inode itself
if (target_inode) {
unlink_inode(target_inode);
delete pathdup;
return 0;
} else {
printf("cannot find %s in %s", filename, ParentPath);
delete pathdup;
return -1;
}
}

View File

@ -80,7 +80,7 @@ int main(int argc, char *argv[]) {
printf("=== Part 5: pressure test create files ===\n");
u_int64_t file_pressure = fsop.fischl_mkdir("/pressure", 0);
u_int64_t inode_numbers[700];
std::string prefix = "/pressure/";
std::string prefix = "/pressure/No_";
for(int i=0;i<700;i++){
inode_numbers[i] = fsop.fischl_mkdir((prefix+std::to_string(i)).c_str(), 0);
}
@ -88,4 +88,18 @@ int main(int argc, char *argv[]) {
u_int64_t inode_number = fsop.namei((prefix+std::to_string(i)).c_str());
assert(inode_number == inode_numbers[i]);
}
printf("=== Part 6: unlink test ===\n");
fsop.printDirectory(file_pressure);
for(int i=0;i<700;i+=2){
assert(!fsop.fischl_unlink((prefix+std::to_string(i)).c_str()));
}
for(int i=0;i<4;i+=2){
assert(fsop.namei((prefix+std::to_string(i)).c_str())==(u_int64_t)(-1));
}
for(int i=1;i<700;i+=2){
u_int64_t inode_number = fsop.namei((prefix+std::to_string(i)).c_str());
assert(inode_number == inode_numbers[i]);
}
fsop.printDirectory(file_pressure);
}