Exemplo n.º 1
0
error_t __vfs_lookup(struct vfs_file_s *cwd, 
			struct vfs_lookup_path_s *lkp_path,
			uint32_t lookup_flags, 
			struct vfs_lookup_response_s *lkr)
{
	struct vfs_lookup_s *lkp; struct vfs_lookup_s _lkp; lkp = &_lkp;
	struct vfs_inode_ref_s *current;

START_LOOKUP:

	if(lkp_path->isAbsolute)
		current = &current_task->vfs_root.f_inode;
	else
		current = &cwd->f_inode;

	lkp->current = *current;
	lkp->flags = lkp_path->flags;
	lkp->mode = lkp_path->mode;
	/* The first element is always held (not in a multi-thread env) */
	lkp->lookup_flags = lookup_flags | VFS_LOOKUP_HELD;
	lkp->th_uid = current_thread->task->uid;
	lkp->th_gid = current_thread->task->gid;;

	lkr->inode.cid = CID_NULL;
	lkr->inode.ptr = NULL;
	lkr->inode.gc = 0;
	lkr->ctx = NULL;
	lkr->err = 0;
	lkr->lookup_flags = VFS_LOOKUP_HELD;
	
	for(; *lkp_path->cptr;)
	{
		if(*(lkp_path->cptr+1) == NULL)
		{
			VFS_SET(lkp->lookup_flags, VFS_LOOKUP_LAST);
			if(lkp->lookup_flags & VFS_LOOKUP_PARENT)
			{
				if(!(lkr->inode.ptr))
					lkr->inode = lkp->current;
				return 0;
			}
		}

		vfs_lookup_elem(lkp, lkr, *lkp_path->cptr);

		if(lkr->err)
		{
			vfs_dmsg(1, "%s : lookup failed, path = %s\n", __FUNCTION__, lkp_path->str);
			return lkr->err;
		}
	
		if(VFS_IS(lkr->lookup_flags, VFS_LOOKUP_RETRY))
			continue;

		if(VFS_IS(lkr->lookup_flags, VFS_LOOKUP_RESTART))
			goto START_LOOKUP;

		if(!lkr->ctx)
			lkp->current = lkr->inode;
		else
			lkp->current = lkr->ctx->ctx_root;
		VFS_CLEAR(lkp->lookup_flags, VFS_LOOKUP_HELD);
		vfs_lookup_next(lkp_path);
	}

        /* FIXME : possible SIGSEGV when dereferencing ptr ? */
	vfs_dmsg(1, "%s : lookup succeded, path = %s, inode num %d\n", 
		__FUNCTION__, lkp_path->str, lkr->inode.ptr->i_number);

	return 0;
}
Exemplo n.º 2
0
int sys_mmap(mmap_attr_t *mattr)
{
	error_t err;
	uint_t count;
	struct thread_s *this;
	struct task_s *task;
	struct vfs_file_s *file;
	mmap_attr_t attr;
	int retval;
 
	this = current_thread;
	task = this->task;
	err  = EINVAL;
	file = NULL;

	if((err = cpu_uspace_copy(&attr, mattr, sizeof(mmap_attr_t))))
	{
		printk(INFO, "%s: failed, copying from uspace @%x\n",
		       __FUNCTION__, 
		       mattr);

		this->info.errno = EFAULT;
		return (int)VM_FAILED;
	}

	if((attr.flags  & VM_REG_HEAP)                     ||
	   ((attr.flags & VM_REG_PVSH) == VM_REG_PVSH)     || 
	   ((attr.flags & VM_REG_PVSH) == 0)               ||
	   (attr.length == 0)                              ||
	   (attr.offset & PMM_PAGE_MASK)                   || 
	   ((attr.addr != NULL) && (((uint_t)attr.addr & PMM_PAGE_MASK)           ||
				    ((attr.length + (uint_t)attr.addr) > CONFIG_USR_LIMIT))))
	{
		printk(INFO, "%s: failed, we don't like flags (%x), length (%d), or addr (%x)\n",
		       __FUNCTION__, 
		       attr.flags, 
		       attr.length, 
		       attr.addr);
     
		this->info.errno = EINVAL;
		return (int)VM_FAILED;
	}
   
	if(attr.flags & VM_REG_ANON)
	{
		attr.offset = 0;
		attr.addr   = (attr.flags & VM_REG_FIXED) ? attr.addr : NULL;
	}
	else
	{      
		if((attr.fd > CONFIG_TASK_FILE_MAX_NR) || (task_fd_lookup(task,attr.fd) == NULL))
		{
			printk(INFO, "%s: failed, bad file descriptor (%d)\n", 
			       __FUNCTION__, 
			       attr.fd);

			this->info.errno = EBADFD;
			return (int)VM_FAILED;
		}
     
		/* FIXEME: possible concurent delete of file from another bugy thread closing it */
		file = task_fd_lookup(task,attr.fd);
		atomic_add(&file->f_count, 1);
     
		if((attr.offset + attr.length) > file->f_node->n_size)
		{
			printk(INFO, "%s: failed, offset (%d) + len (%d) >= file's size (%d)\n", 
			       __FUNCTION__, 
			       attr.offset, 
			       attr.length, 
			       file->f_node->n_size);

			this->info.errno = ERANGE;
			goto SYS_MMAP_FILE_ERR;
		}

		if(((attr.prot & VM_REG_RD) && !(VFS_IS(file->f_flags, VFS_O_RDONLY)))   ||
		   ((attr.prot & VM_REG_WR) && !(VFS_IS(file->f_flags, VFS_O_WRONLY)))   ||
		   ((attr.prot & VM_REG_WR) && (VFS_IS(file->f_flags, VFS_O_APPEND))))//    ||
			//(!(attr.prot & VM_REG_RD) && (attr.flags & VM_REG_PRIVATE)))
		{
			printk(INFO, "%s: failed, EACCES prot (%x), f_flags (%x)\n", 
			       __FUNCTION__, 
			       attr.prot, 
			       file->f_flags);

			this->info.errno = EACCES;
			goto SYS_MMAP_FILE_ERR;
		}
	}

	retval = (int) vmm_mmap(task,
				file,
				attr.addr,
				attr.length,
				attr.prot,
				attr.flags,
				attr.offset);
   
	if((retval != (int)VM_FAILED) || (attr.flags & VM_REG_ANON))
		return retval;

SYS_MMAP_FILE_ERR:
	printk(INFO, "%s: Failed, Droping file count (%d)\n", 
	       __FUNCTION__, 
	       file->f_count);
   
	vfs_close(file, &count);

	if(count == 1)
		task_fd_put(task, attr.fd);

	return (int)VM_FAILED;
}
Exemplo n.º 3
0
//TODO: add the case of negatif entrys
RPC_DECLARE( __vfs_lookup_child, 
		RPC_RET(RPC_RET_PTR(struct vfs_lookup_response_s, lkr)), 
		RPC_ARG(RPC_ARG_PTR(char, name),
		RPC_ARG_PTR(struct vfs_lookup_s, lkp)))
{
	struct vfs_inode_ref_s *parent;
	struct vfs_dirent_s *dirent;
	error_t err;
	char isLast;
	char isHeld;

	err = 0;
	dirent = NULL;
	lkr->lookup_flags = 0;
	parent = &lkp->current;
	isLast = VFS_IS(lkp->lookup_flags, VFS_LOOKUP_LAST);
	isHeld = VFS_IS(lkp->lookup_flags, VFS_LOOKUP_HELD);
	
	if(!isHeld && vfs_inode_hold(parent->ptr, parent->gc))
	{
		/* The gc is no longer valid: simply retry */
		VFS_SET(lkr->lookup_flags, VFS_LOOKUP_RESTART);
		goto VFS_DIRENT_LOAD_ERROR;
	}

	if((err = vfs_load_dirent(parent->ptr, name, lkp->flags, isLast, 0, 
						&dirent, &lkr->lookup_flags)))
		goto VFS_DIRENT_LOAD_EXIT;

	if(!dirent->d_mounted)
	{
		/* This multi-field copy should be safe since 	*
		 * dirent content are fix 			*/
		lkr->inode = dirent->d_inode;
		lkr->ctx = NULL;
	}
	else
	{
		lkr->ctx = dirent->d_mounted;
		lkr->inode = (const struct vfs_inode_ref_s){ 0 };
	}

	vfs_dirent_down(dirent);

VFS_DIRENT_LOAD_EXIT:
	if(!isHeld)
		vfs_inode_down(parent->ptr);

VFS_DIRENT_LOAD_ERROR:
	lkr->err = err;
}


RPC_DECLARE( __vfs_lookup_parent, 
		RPC_RET(RPC_RET_PTR(struct vfs_lookup_response_s, lkr)), 
		RPC_ARG(RPC_ARG_PTR(struct vfs_lookup_s, lkp)))
{
	char isHeld;
	struct vfs_inode_s *cinode;
	struct vfs_inode_ref_s *current;

	current = &lkp->current;
	isHeld = VFS_IS(lkp->lookup_flags, VFS_LOOKUP_HELD);

	if((!isHeld) && (vfs_inode_hold(current->ptr, current->gc)))
	{
		/* The gc is no longer valid: simply retry */
		VFS_SET(lkr->lookup_flags, VFS_LOOKUP_RESTART);
		goto VFS_DIRENT_LOAD_EXIT;
	}

	cinode = current->ptr;
	lkr->inode.ptr = cinode->i_parent;
	lkr->inode.cid = cinode->i_pcid;
	lkr->inode.gc = cinode->i_pgc;

	if(!isHeld)
		vfs_inode_down(current->ptr);

VFS_DIRENT_LOAD_EXIT:
	lkr->err = 0;
}