static int get_dir_inode_by_index(int dir_inode_index,INODE *p_dir_inode){ assert(dir_inode_index==super_block.root_dir_inode_index,"only one directory(root dir:/)"); if(get_inode_by_index(dir_inode_index,p_dir_inode)>=0){ if(p_dir_inode->i_mode==I_DIRECTORY) return dir_inode_index; } return -1; }
int sfs_GetFileSize(const char* path) { int inode_num, size; inode_struct* inode; inode_num = get_inode_num_by_name(path); if(inode_num == -1) return -1; inode = get_inode_by_index(inode_num); size = inode->size; free(inode); return size; }
int mksfs(int fresh) { super_block spr_block; char buff[BLKSIZ]; int i; // Initialize fd_table for(i = 0; i < MAXOPENFILES; i++) fd_table[i].status = FREE; if(fresh) { // Initialize and write super block to disk init_fresh_disk(DISKIMG, BLKSIZ, BLOCKNUM); spr_block.magic_number = MAGICNUM; spr_block.block_size = BLKSIZ; spr_block.fs_size = BLOCKNUM; spr_block.inode_tbl_length = INODETBLSIZ; spr_block.root_inode = ROOTINODENUM; write_blocks(SUPERBLOCKADD, 1, (void*) &spr_block); // Setup datablock bitmap memset(buff, FREE, BLKSIZ); write_blocks(DBBITMAPADD, 1, buff); // Setup INODE Bitmap and allocate first i-node entry to root directory buff[ROOTINODENUM] = USED; write_blocks(INBITMAPADD, 1, buff); // Allocate fd to root directory fd_table[ROOTFD].status = USED; fd_table[ROOTFD].inode_num = ROOTINODENUM; fd_table[ROOTFD].rw_pointer = 0; fd_table[ROOTFD].inode = (inode_struct*) calloc(1, sizeof(inode_struct)); fd_table[ROOTFD].inode->size = 0; write_inode_by_index(fd_table[ROOTFD].inode_num, fd_table[ROOTFD].inode); } else { init_disk(DISKIMG, BLKSIZ, BLOCKNUM); fd_table[ROOTFD].status = USED; fd_table[ROOTFD].inode_num = ROOTINODENUM; fd_table[ROOTFD].inode = get_inode_by_index(ROOTINODENUM); fd_table[ROOTFD].rw_pointer = fd_table[ROOTFD].inode->size; } return 0; }
//有问题:调用的rw_sector中读取数据长度必须为SECTOR_SIZE的整数倍 //该函数还发现一个问题:如果fsbuf为全局静态变量,由于开始读目录内容填充了fsbuf,然后在比较的时候又读取了硬盘,再次填充了fsbuf,导致之前的数据被覆盖。所以fsbuf还是设定成局部变量。 //切忌:尽量减少全局变量的使用。 static int get_inode_by_name(const char *dir_name,const char *file_name,int file_type,INODE *p_inode){ INODE dir_inode; DIR_ENTRY *dir_entry; int dir_entry_index; int dir_entry_count; u8 fsbuf[SECTOR_SIZE*2]; if(get_dir_inode_by_name(dir_name,&dir_inode)<0){ set_error_index(DIR_NOT_EXIST); return -1; } dir_entry_count=dir_inode.i_size/DIR_ENTRY_SIZE; rw_sector(INFO_FS_READ, ROOT_DEVICE, (dir_inode.i_start_sector_index)*SECTOR_SIZE, dir_inode.i_size, TASK_FS, fsbuf); for(dir_entry_index=0;dir_entry_index<dir_entry_count;dir_entry_index++){ dir_entry=(DIR_ENTRY *)(fsbuf+dir_entry_index*DIR_ENTRY_SIZE); /* #ifdef DEBUG_FS */ /* printl("dir_index=%d dir_name=%s filename=%s cmp=%d\n", */ /* dir_entry->inode_index, */ /* dir_entry->name, */ /* file_name, */ /* strcmp(dir_entry->name,file_name)==0); */ /* #endif */ //此处的dir_entry->inode_index=0:表示该文件建立后删除了 if(dir_entry->inode_index>0 && strcmp(dir_entry->name,file_name)==0){ if(get_inode_by_index(dir_entry->inode_index,p_inode)){ if((p_inode->i_mode & file_type) !=0){ /* printl("get inode by name data_sector_index=%d\n",p_inode->i_start_sector_index); */ return dir_entry->inode_index; } } } } set_error_index(FILE_NOT_EXIST); return -1; }
static BOOL do_unlink(MESSAGE *message){ int inode_index,flags,sector_index,sector_length; const char *path; char dir_name[MAX_FILENAME_LENGTH]={0}; char file_name[MAX_FILENAME_LENGTH]={0}; INODE inode; flags=message->flags; path=message->arg_pointer; //分离父目录路径和文件名 if(!strip_path(path,dir_name,file_name)){ return FALSE; } //1.get inode_index,and remove the dir_entry inode_index=search_file(dir_name,file_name,GET_FILE_TYPE(flags)); #ifdef DEBUG_FS printl("inode_index=%d(in do_unlink)\n",inode_index); #endif if(inode_index<0){ set_error_index(FILE_NOT_EXIST); return FALSE; } if(!remove_dir_entry(dir_name,inode_index)){ set_error_index(FILE_NOT_EXIST); return FALSE; } //2.get file inode by inode_index get_inode_by_index(inode_index,&inode); //3.clear imap by inode_index free_imap_bit(inode_index); //4.clear smap inode sector_index=inode.i_start_sector_index-get_data_block_first_index(super_block); sector_length=inode.i_sectors_length; /* printl("sector_index=%d sector_length=%d data_first_index=%d\n",inode.i_start_sector_index,sector_length,get_data_block_first_index(super_block)); */ free_smap_bit(sector_index,sector_length); return TRUE; }
/* * Construct all files in a PID directory. */ static void make_all_pid_entries(struct inode * parent, int slot) { struct inode *node; struct inode_stat stat; int i; for (i = 0; pid_files[i].name != NULL; i++) { node = get_inode_by_index(parent, i); if (node != NULL) continue; make_stat(&stat, slot, i); node = add_inode(parent, pid_files[i].name, i, &stat, (index_t)0, (cbdata_t)0); if (node == NULL) out_of_inodes(); } }
int sfs_fopen(char *name) { int inode_num, fd, i; inode_struct* inode; directory_map new_file; inode_num = get_inode_num_by_name(name); // Check if file is already open for(i = 1; i < MAXOPENFILES; i++) { if( (fd_table[i].status == USED) && (fd_table[i].inode_num == inode_num)) return i; } fd = get_free_fd(); if(fd == -1) return -1; if(inode_num == -1) // File does not exist, create file { // Allocate i-node inode_num = get_free_inode_num(); inode = calloc(1, sizeof(inode_struct)); // Add new file to directory new_file.inode_num = inode_num; strcpy(new_file.file_name, name); // Seek to end of directory and write new file entry fd_table[ROOTFD].rw_pointer = fd_table[ROOTFD].inode->size; sfs_fwrite(ROOTFD, (char*)&new_file, sizeof(directory_map)); write_inode_by_index(fd_table[ROOTFD].inode_num, fd_table[ROOTFD].inode); } else { inode = get_inode_by_index(inode_num); } fd_table[fd].inode_num = inode_num; fd_table[fd].inode = inode; fd_table[fd].rw_pointer = inode->size; return fd; }
int sfs_remove(char *file) { int inode_num; inode_struct* inode; char bitmap[BLKSIZ]; inode_num = get_inode_num_by_name(file); if(inode_num == -1) return -1; inode = get_inode_by_index(inode_num); // Free Data blocks free_blk_pointers(&(inode->blk_pointers)); // Free Inode read_blocks(INBITMAPADD, 1, bitmap); bitmap[inode_num] = FREE; write_blocks(INBITMAPADD, 1, bitmap); remove_inode_from_directory(file); free(inode); return 0; }
/*===========================================================================* * fs_getdents * *===========================================================================*/ ssize_t fs_getdents(ino_t ino_nr, struct fsdriver_data *data, size_t bytes, off_t *posp) { /* Retrieve directory entries. */ struct fsdriver_dentry fsdentry; struct inode *node, *child; const char *name; off_t pos; int r, skip, get_next, indexed; static char buf[GETDENTS_BUFSIZ]; if (*posp >= ULONG_MAX) return EIO; if ((node = find_inode(ino_nr)) == NULL) return EINVAL; indexed = node->i_indexed; get_next = FALSE; child = NULL; /* Call the getdents hook, if any, to "refresh" the directory. */ if (!is_inode_deleted(node) && vtreefs_hooks->getdents_hook != NULL) { r = vtreefs_hooks->getdents_hook(node, get_inode_cbdata(node)); if (r != OK) return r; } fsdriver_dentry_init(&fsdentry, data, bytes, buf, sizeof(buf)); do { /* Determine which inode and name to use for this entry. */ pos = (*posp)++; if (pos == 0) { /* The "." entry. */ child = node; name = "."; } else if (pos == 1) { /* The ".." entry. */ child = get_parent_inode(node); if (child == NULL) child = node; name = ".."; } else if (pos - 2 < indexed) { /* All indexed entries. */ child = get_inode_by_index(node, pos - 2); /* If there is no inode with this particular index, * continue with the next index number. */ if (child == NULL) continue; name = child->i_name; } else { /* All non-indexed entries. */ /* If this is the first loop iteration, first get to * the non-indexed child identified by the current * position. */ if (get_next == FALSE) { skip = pos - indexed - 2; child = get_first_inode(node); /* Skip indexed children. */ while (child != NULL && child->i_index != NO_INDEX) child = get_next_inode(child); /* Skip to the right position. */ while (child != NULL && skip-- > 0) child = get_next_inode(child); get_next = TRUE; } else { child = get_next_inode(child); } /* No more children? Then stop. */ if (child == NULL) break; assert(!is_inode_deleted(child)); name = child->i_name; } /* Add the directory entry to the output. */ r = fsdriver_dentry_add(&fsdentry, (ino_t) get_inode_number(child), name, strlen(name), IFTODT(child->i_stat.mode)); if (r < 0) return r; } while (r > 0); return fsdriver_dentry_finish(&fsdentry); }
/* * Regenerate the set of PID directories in the root directory of the file * system. Add new directories and delete old directories as appropriate; * leave unchanged those that should remain the same. */ static void construct_pid_dirs(void) { /* * We have to make two passes. Otherwise, we would trigger a vtreefs * assert when we add an entry for a PID before deleting the previous * entry for that PID. While rare, such rapid PID reuse does occur in * practice. */ struct inode *root, *node; struct inode_stat stat; char name[PNAME_MAX+1]; pid_t pid; int i; root = get_root_inode(); /* First pass: delete old entries. */ for (i = 0; i < NR_PROCS + NR_TASKS; i++) { /* Do we already have an inode associated with this slot? */ node = get_inode_by_index(root, i); if (node == NULL) continue; /* * If the process slot is not in use, delete the associated * inode. */ if (!slot_in_use(i)) { delete_inode(node); continue; } /* Otherwise, get the process ID. */ if (i < NR_TASKS) pid = (pid_t)(i - NR_TASKS); else pid = mproc[i - NR_TASKS].mp_pid; /* * If there is an old entry, see if the pid matches the current * entry, and the owner is still the same. Otherwise, delete * the old entry first. We reconstruct the entire subtree even * if only the owner changed, for security reasons: if a * process could keep open a file or directory across the owner * change, it might be able to access information it shouldn't. */ if (pid != (pid_t)get_inode_cbdata(node) || !check_owner(node, i)) delete_inode(node); } /* Second pass: add new entries. */ for (i = 0; i < NR_PROCS + NR_TASKS; i++) { /* If the process slot is not in use, skip this slot. */ if (!slot_in_use(i)) continue; /* * If we have an inode associated with this slot, we have * already checked it to be up-to-date above. */ if (get_inode_by_index(root, i) != NULL) continue; /* Get the process ID. */ if (i < NR_TASKS) pid = (pid_t)(i - NR_TASKS); else pid = mproc[i - NR_TASKS].mp_pid; /* Add the entry for the process slot. */ snprintf(name, PNAME_MAX + 1, "%d", pid); make_stat(&stat, i, NO_INDEX); node = add_inode(root, name, i, &stat, nr_pid_entries, (cbdata_t)pid); if (node == NULL) out_of_inodes(); } }
/*===========================================================================* * fs_getdents * *===========================================================================*/ int fs_getdents(void) { /* Retrieve directory entries. */ struct inode *node, *child = NULL; struct dirent *dent; char *name; size_t len, off, user_off, user_left; off_t pos; int r, skip, get_next, indexed; static char buf[GETDENTS_BUFSIZ]; if (fs_m_in.REQ_SEEK_POS_HI != 0) return EIO; if ((node = find_inode(fs_m_in.REQ_INODE_NR)) == NULL) return EINVAL; off = 0; user_off = 0; user_left = fs_m_in.REQ_MEM_SIZE; indexed = node->i_indexed; get_next = FALSE; child = NULL; /* Call the getdents hook, if any, to "refresh" the directory. */ if (!is_inode_deleted(node) && vtreefs_hooks->getdents_hook != NULL) { r = vtreefs_hooks->getdents_hook(node, get_inode_cbdata(node)); if (r != OK) return r; } for (pos = fs_m_in.REQ_SEEK_POS_LO; ; pos++) { /* Determine which inode and name to use for this entry. */ if (pos == 0) { /* The "." entry. */ child = node; name = "."; } else if (pos == 1) { /* The ".." entry. */ child = get_parent_inode(node); if (child == NULL) child = node; name = ".."; } else if (pos - 2 < indexed) { /* All indexed entries. */ child = get_inode_by_index(node, pos - 2); /* If there is no inode with this particular index, * continue with the next index number. */ if (child == NULL) continue; name = child->i_name; } else { /* All non-indexed entries. */ /* If this is the first loop iteration, first get to * the non-indexed child identified by the current * position. */ if (get_next == FALSE) { skip = pos - indexed - 2; child = get_first_inode(node); /* Skip indexed children. */ while (child != NULL && child->i_index != NO_INDEX) child = get_next_inode(child); /* Skip to the right position. */ while (child != NULL && skip-- > 0) child = get_next_inode(child); get_next = TRUE; } else { child = get_next_inode(child); } /* No more children? Then stop. */ if (child == NULL) break; assert(!is_inode_deleted(child)); name = child->i_name; } len = DWORD_ALIGN(sizeof(struct dirent) + strlen(name)); /* Is the user buffer too small to store another record? */ if (user_off + off + len > user_left) { /* Is the user buffer too small for even a single * record? */ if (user_off == 0 && off == 0) return EINVAL; break; } /* If our own buffer cannot contain the new record, copy out * first. */ if (off + len > sizeof(buf)) { r = sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT, user_off, (vir_bytes) buf, off, D); if (r != OK) return r; user_off += off; user_left -= off; off = 0; } /* Fill in the actual directory entry. */ dent = (struct dirent *) &buf[off]; dent->d_ino = get_inode_number(child); dent->d_off = pos; dent->d_reclen = len; strcpy(dent->d_name, name); off += len; } /* If there is anything left in our own buffer, copy that out now. */ if (off > 0) { r = sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT, user_off, (vir_bytes) buf, off, D); if (r != OK) return r; user_off += off; } fs_m_out.RES_SEEK_POS_HI = 0; fs_m_out.RES_SEEK_POS_LO = pos; fs_m_out.RES_NBYTES = user_off; return OK; }
static int do_open(MESSAGE *message){ int i,fd=-1; const char *path; char dirname[MAX_FILENAME_LENGTH]={0}; char filename[MAX_FILENAME_LENGTH]={0}; int flags; int inode_index; struct s_file_descriptor *pfd=NULL; struct s_inode *pinode=NULL; /* struct s_inode parent_dir_inode; */ PROCESS *process; path=message->arg_pointer; flags=message->flags; process=pid2process(message->source_pid); pfd=get_free_fd_from_table(); pinode=get_free_inode_from_table(); if(pfd==NULL || pinode==NULL){ set_error_index(NO_FD_INODE); return -1; } //分离父目录路径和文件名 if(!strip_path(path,dirname,filename)){ return -1; } #ifdef DEBUG_FS printl("dir_name=%s file_name=%s\n",dirname,filename); #endif //搜索文件 inode_index=search_file(dirname,filename,GET_FILE_TYPE(flags)); if(inode_index<0){ if((flags & O_CREATE)==0){ return -1; } inode_index=create_file(dirname,filename,GET_FILE_TYPE(flags)); if(inode_index<0){ return -1; } } assert(inode_index>=0,""); get_inode_by_index(inode_index,pinode); #ifdef DEBUG_FS printl("pinode.start_index=%d(in do_open)",pinode->i_start_sector_index); #endif /*SDTIN=0,STDOUT=1,STDERROR=2*/ for(i=3;i<FILE_COUNT;i++){ if(process->file_descriptor[i]==NULL){ fd=i; break; } } if(fd>=0){ process->file_descriptor[fd]=pfd; pfd->fd_inode=pinode; pfd->fd_op_mode=GET_FILE_OP(flags); pfd->fd_position=0; pinode->i_inode_index=inode_index; #ifdef DEBUG_FS printl("inode_index=%d(in do_open)\n",pinode->i_inode_index); printl("data_sector_index=%d data_sector_length=%d\n",process->file_descriptor[fd]->fd_inode->i_start_sector_index,process->file_descriptor[fd]->fd_inode->i_sectors_length); #endif return fd; }else{ set_error_index(PROCESS_FD_POINTER_NOT_ENOUGH); return -1; } }