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 = ¤t_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; }
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; }
//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; }