Beispiel #1
0
//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;

}
Beispiel #2
0
/* 搜索文件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;
}
Beispiel #3
0
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;
}
Beispiel #4
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;
    }

}
Beispiel #5
0
//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;

}