//handling symlink request void symlink_handler(Msg *msg, int sender_pid) { char oldname[MAXPATHNAMELEN], newname[MAXPATHNAMELEN]; memset(oldname,'\0',MAXPATHNAMELEN); memset(newname,'\0',MAXPATHNAMELEN); CopyFrom(sender_pid,oldname,msg->ptr1,msg->num2+1); CopyFrom(sender_pid,newname,msg->ptr2,msg->num3+1); int dir_len=msg->num3; char *dir_newname=newname+msg->num3; while((*dir_newname)!='/'&&dir_newname!=newname){ dir_len--; dir_newname--; } if((*dir_newname)=='/'){ dir_len++; dir_newname++; } int parent_inum=path_to_inum(newname,dir_len,msg->num1,0); int sym_inum=alloc_inode(INODE_SYMLINK,parent_inum); if(sym_inum<=0){ msg->type=-1; return; } inode_cache *parent_inode=read_inode(parent_inum); inode_cache *sym_inode=read_inode(sym_inum); int sym_bnum=alloc_block(); block_cache *sym_block=read_block(sym_bnum); struct dir_entry *sym_dir_entry=search_dir_entry(parent_inum,dir_newname); if(sym_dir_entry!=NULL){ msg->type=-1; return; } if((sym_dir_entry=empty_dir(msg->num1))==NULL){ msg->type=-1; return; } sym_dir_entry->inum=sym_inum; memcpy(sym_dir_entry->name,dir_newname,msg->num3-dir_len); sym_inode->data.size=msg->num2; sym_inode->data.nlink=1; sym_inode->data.direct[0]=sym_bnum; sym_block->dirty=1; memcpy(sym_block->data,oldname,msg->num2); parent_inode->data.size+=sizeof(struct dir_entry); parent_inode->dirty=1; }
/* 搜索文件pathname,若找到则返回其inode号,否则返回-1 */ static int search_file(const char* pathname, struct path_search_record* searched_record) { /* 如果待查找的是根目录,为避免下面无用的查找,直接返回已知根目录信息 */ if (!strcmp(pathname, "/") || !strcmp(pathname, "/.") || !strcmp(pathname, "/..")) { searched_record->parent_dir = &root_dir; searched_record->file_type = FT_DIRECTORY; searched_record->searched_path[0] = 0; // 搜索路径置空 return 0; } uint32_t path_len = strlen(pathname); /* 保证pathname至少是这样的路径/x且小于最大长度 */ ASSERT(pathname[0] == '/' && path_len > 1 && path_len < MAX_PATH_LEN); char* sub_path = (char*)pathname; struct dir* parent_dir = &root_dir; struct dir_entry dir_e; /* 记录路径解析出来的各级名称,如路径"/a/b/c", * 数组name每次的值分别是"a","b","c" */ char name[MAX_FILE_NAME_LEN] = {0}; searched_record->parent_dir = parent_dir; searched_record->file_type = FT_UNKNOWN; uint32_t parent_inode_no = 0; // 父目录的inode号 sub_path = path_parse(sub_path, name); while (name[0]) { // 若第一个字符就是结束符,结束循环 /* 记录查找过的路径,但不能超过searched_path的长度512字节 */ ASSERT(strlen(searched_record->searched_path) < 512); /* 记录已存在的父目录 */ strcat(searched_record->searched_path, "/"); strcat(searched_record->searched_path, name); /* 在所给的目录中查找文件 */ if (search_dir_entry(cur_part, parent_dir, name, &dir_e)) { memset(name, 0, MAX_FILE_NAME_LEN); /* 若sub_path不等于NULL,也就是未结束时继续拆分路径 */ if (sub_path) { sub_path = path_parse(sub_path, name); } if (FT_DIRECTORY == dir_e.f_type) { // 如果被打开的是目录 parent_inode_no = parent_dir->inode->i_no; dir_close(parent_dir); parent_dir = dir_open(cur_part, dir_e.i_no); // 更新父目录 searched_record->parent_dir = parent_dir; continue; } else if (FT_REGULAR == dir_e.f_type) { // 若是普通文件 searched_record->file_type = FT_REGULAR; return dir_e.i_no; } } else { //若找不到,则返回-1 /* 找不到目录项时,要留着parent_dir不要关闭, * 若是创建新文件的话需要在parent_dir中创建 */ return -1; } } /* 执行到此,必然是遍历了完整路径并且查找的文件或目录只有同名目录存在 */ dir_close(searched_record->parent_dir); /* 保存被查找目录的直接父目录 */ searched_record->parent_dir = dir_open(cur_part, parent_inode_no); searched_record->file_type = FT_DIRECTORY; return dir_e.i_no; }
int fs_remove(fs_t* fs, inodeid_t dir, char *name) { //checks if the arguments are valid if (fs == NULL || dir>=ITAB_SIZE || name == NULL) { dprintf("[fs_remove] malformed arguments. \n"); return -1; } if (strlen(name) == 0 || strlen(name)+1 > FS_MAX_FNAME_SZ) { dprintf("[fs_remove] file name size error\n"); return -1; } if (!BMAP_ISSET(fs->inode_bmap, dir)) { dprintf("[fs_remove] inode is not being used.\n"); return -1; } inodeid_t entryid = 0; if (!fsi_dir_search(fs, dir, name, &entryid) == 0) { dprintf("[fs_remove] file/dir does not exist\n"); return -1; } fs_inode_t* idir = &fs->inode_tab[dir]; if (idir->type != FS_DIR) { dprintf("[fs_remove] inode is not a directory. \n"); return -1; } fs_dentry_t page[DIR_PAGE_ENTRIES]; int num_dir_entry = 0, block_num = 0; search_dir_entry(fs, dir, entryid, &num_dir_entry, &block_num, (char*)page); fs_dentry_t last_page[DIR_PAGE_ENTRIES]; // array de entradas do ultimo bloco int last_entry_index = (idir->size % BLOCK_SIZE / sizeof(fs_dentry_t)) -1; block_read(fs->blocks,idir->blocks[idir->size/BLOCK_SIZE],(char *)last_page); fs_dentry_t* last_entry = &last_page[last_entry_index]; // ponteiro p/ última posição ocupada do dir page[num_dir_entry] = *last_entry; // mete a ultima entrada na posição da que vai ser removida block_write(fs->blocks, idir->blocks[block_num], (char*)page); // escreve o bloco (page) no disco idir->size -= sizeof(fs_dentry_t); // diminui o tamanho do directório em uma entrada int i, j; if (last_entry_index == 0) { //se for a primeira entrada do bloco, elimina esse bloco for(i = 0, j = 1; idir->blocks[j] != 0; i++, j++); BMAP_CLR(fs->blk_bmap, idir->blocks[i]); idir->blocks[i] = 0; } fs_inode_t ientry = fs->inode_tab[entryid]; // vai buscar o inode do ficheiro/directorio à tabela de inodes if(ientry.type == FS_FILE) fs_remove_file(fs, entryid); else fs_remove_dir(fs, entryid); BMAP_CLR(fs->inode_bmap, entryid); return 0; }
//handling unlink request void unlink_handler(Msg *msg, int sender_pid) { char pathname[MAXPATHNAMELEN]; memset(pathname,'\0',MAXPATHNAMELEN); CopyFrom(sender_pid,pathname,msg->ptr1,msg->num2+1); int dir_len=msg->num2; char *dir_pathname=pathname+msg->num2; while((*dir_pathname)!='/'&&dir_pathname!=pathname){ dir_len--; dir_pathname--; } if((*dir_pathname)=='/'){ dir_len++; dir_pathname++; } int parent_inum=path_to_inum(pathname,dir_len,msg->num1,0); int path_inum=check_dir(parent_inum,dir_pathname); if(path_inum<=0||parent_inum<=0){ msg->type=-1; return; } inode_cache *path_inode=read_inode(path_inum); inode_cache *parent_inode=read_inode(parent_inum); if(path_inode->data.type==INODE_DIRECTORY){ msg->type=-1; return; } struct dir_entry *path_dir_entry=search_dir_entry(parent_inum,dir_pathname); if(path_inode->data.nlink>1){ path_dir_entry->inum=0; path_inode->data.nlink--; memset(path_dir_entry->name,'\0',DIRNAMELEN); parent_inode->data.size-=sizeof(struct dir_entry); parent_inode->dirty=1; } else if(path_inode->data.nlink==1){ path_dir_entry->inum=0; path_inode->data.nlink--; memset(path_dir_entry->name,'\0',DIRNAMELEN); free_inode(path_inum);//XXX path_inode->dirty=1; parent_inode->data.size-=sizeof(struct dir_entry); parent_inode->dirty=1; } else{ msg->type=-1; return; } }
//handling link request void link_handler(Msg *msg, int sender_pid) { char oldname[MAXPATHNAMELEN], newname[MAXPATHNAMELEN]; if(path_to_inum(newname,msg->num3,msg->num1,0)>0){ /*newname exists*/ msg->type=-1; return; } memset(oldname,'\0',MAXPATHNAMELEN); memset(newname,'\0',MAXPATHNAMELEN); CopyFrom(sender_pid,oldname,msg->ptr1,msg->num2+1); CopyFrom(sender_pid,newname,msg->ptr2,msg->num3+1); int dir_len=msg->num3; char *dir_newname=newname+msg->num3; while((*dir_newname)!='/'&&dir_newname!=newname){ dir_len--; dir_newname--; } if((*dir_newname)=='/'){ dir_len++; dir_newname++; } int parent_inum=path_to_inum(newname,dir_len,msg->num1,0); int dir_len_old=msg->num2; char *dir_oldname=oldname+msg->num2; while((*dir_oldname)!='/'&&dir_oldname!=oldname){ dir_len_old--; dir_oldname--; } if((*dir_oldname)=='/'){ dir_len_old++; dir_oldname++; } int parent_old_inum=path_to_inum(oldname,dir_len_old,msg->num1,0); int old_inum=check_dir(parent_old_inum,dir_oldname); if(old_inum<=0){ msg->type=-1; return; } inode_cache *old_inode=read_inode(old_inum); if(old_inode->data.type==INODE_DIRECTORY){ msg->type=-1; return; } struct dir_entry *newlink=search_dir_entry(parent_inum,dir_newname); if(newlink!=NULL){ msg->type=-1; return; } if((newlink=empty_dir(parent_inum))==NULL){ msg->type=-1; return; } inode_cache *parent_inode=read_inode(parent_inum); parent_inode->data.size+=sizeof(struct dir_entry); parent_inode->dirty=1; newlink->inum=old_inum; memcpy(newlink->name,dir_newname,msg->num3-dir_len); old_inode->data.nlink++; old_inode->dirty=1; }