Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
/*
 * 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();
	}
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
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;
}
Esempio n. 9
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);
}
Esempio n. 10
0
/*
 * 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();
	}
}
Esempio n. 11
0
File: read.c Progetto: Sciumo/minix
/*===========================================================================*
 *				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;
}
Esempio n. 12
0
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;
    }
}