Exemple #1
0
int vfs_mkdir(struct thread *t, const char *path, mode_t mode)
{
    int ret;
    struct resp_lookup res;
    struct mount_entry *mount_pt;
    uid_t uid;
    gid_t gid;

    /* Kernel request */
    if (!t) {
        uid = 0;
        gid = 0;
    } else {
        uid = t->uid;
        gid = t->gid;
    }

    ret = vfs_lookup(t, path, &res, &mount_pt);
    if (ret < 0)
        return ret;

    if (!mount_pt->fi->parent->fs_ops->mkdir)
        return -ENOSYS;

    if ((size_t)ret == strlen(path))
        return -EEXIST;

    return mount_pt->fi->parent->fs_ops->mkdir(mount_pt, path + ret,
                                               res.inode.inode, uid, gid,
                                               mode);
}
Exemple #2
0
int
sc_chmod(thread_t *t, syscall_result_t *r, chmod_args_t *args)
{
    int res=0;
    proc_t *p = t->thr_proc;
    vnode_t *node;
    char pname[PATH_MAX];
    if((res = copyinstr(pname, args->fname, PATH_MAX)))
        return res;

    res = vfs_lookup(p->p_curdir, &node, pname, t, LKP_NORMAL);
    if(res)
        return res;
    vattr_t va;
    va.va_mask=VATTR_ALL;
    if((res = VOP_GETATTR(node, &va)))
        goto err;
    res = -EPERM;
    if(p->p_cred->p_euid != 0 && p->p_cred->p_euid != va.va_uid)
        goto err;
    mode_t mode = args->mode & 07777;
    if(ISSET(mode, S_ISGID) && p->p_cred->p_euid!=0 
        && va.va_gid!=p->p_cred->p_egid)
        UNSET(mode, S_ISGID); //mamy prawo kasować bit suid/sgid?
    va.va_mask = VATTR_MODE;
    va.va_mode = mode;
    if((res = VOP_SETATTR(node, &va)))
        goto err;
    vrele(node);    
    return 0;
err:
    vrele(node);
    return res;
}
Exemple #3
0
int char_dev_register(const char *name, const struct kfile_operations *ops) {
	struct path  node;
	struct nas *dev_nas;

	if (vfs_lookup("/dev", &node)) {
		return -1;
	}

	if (node.node == NULL) {
		return -ENODEV;
	}

	vfs_create_child(&node, name, S_IFCHR | S_IRALL | S_IWALL, &node);
	if (!(node.node)) {
		return -1;
	}

	dev_nas = node.node->nas;
	dev_nas->fs = filesystem_create("empty");
	if (dev_nas->fs == NULL) {
		return -ENOMEM;
	}

	dev_nas->fs->file_op = ops;

	return 0;
}
Exemple #4
0
/* Does most of the work for link(). */
int
vfs_link(char *oldpath, char *newpath)
{
	struct vnode *oldfile;
	struct vnode *newdir;
	char newname[NAME_MAX+1];
	int result;

	result = vfs_lookup(oldpath, &oldfile);
	if (result) {
		return result;
	}
	result = vfs_lookparent(newpath, &newdir, newname, sizeof(newname));
	if (result) {
		VOP_DECREF(oldfile);
		return result;
	}

	if (oldfile->vn_fs==NULL || newdir->vn_fs==NULL ||
	    oldfile->vn_fs != newdir->vn_fs) {
		VOP_DECREF(newdir);
		VOP_DECREF(oldfile);
		return EXDEV;
	}

	result = VOP_LINK(newdir, newname, oldfile);

	VOP_DECREF(newdir);
	VOP_DECREF(oldfile);

	return result;
}
Exemple #5
0
int ext2_mount(const char *dir, int flags, void *_args)
{
    printk("ext2_mount(dir=%s, flags=%x, args=%p)\n", dir, flags, _args);

    struct {
        char *dev;
        char *opt;
    } *args = _args;

    struct vnode vnode;
    struct inode *dev;
    int err;

    struct uio uio = {0};   /* FIXME */

    if ((err = vfs_lookup(args->dev, &uio, &vnode, NULL)))
        goto error;

    if ((err = vfs_vget(&vnode, &dev)))
        goto error;

    struct inode *fs;

    if ((err = ext2fs.load(dev, &fs)))
        goto error;

    return vfs_bind(dir, fs);

error:
    return err;
}
Exemple #6
0
int binfmt_load(struct proc *proc, const char *path, struct proc **ref)
{
    struct vnode vnode;
    struct inode *inode = NULL;
    int err = 0;

    struct uio uio;
    memset(&uio, 0, sizeof(struct uio));

    if (proc) {
        uio = PROC_UIO(proc);
    }

    if ((err = vfs_lookup(path, &uio, &vnode, NULL)))
        return err;

    if ((err = vfs_vget(&vnode, &inode)))
        return err;

    for (size_t i = 0; i < NR_BINFMT; ++i) {
        if (!binfmt_list[i].check(inode)) {
            binfmt_fmt_load(proc, path, inode, &binfmt_list[i], ref);
            vfs_close(inode);
            return 0;
        }
    }

    vfs_close(inode);
    return -ENOEXEC;
}
Exemple #7
0
static int vfs_walk(struct vfs_walk_data *data)
{
	if (!strcmp(data->next, ""))
		return -ENOENT;

	if (!strcmp(data->next, ".")) {
		data->tail = vfs_path_next_entry(data->next, data->tail);
		return 0;
	}

	if (!strcmp(data->next, "..")) {
		struct fs_entry *parent = vfs_entry_get(data->entry->parent);

		vfs_entry_put(data->entry);
		data->entry = parent;
		data->tail = vfs_path_next_entry(data->next, data->tail);
		return 0;
	}

	struct fs_entry *entry;
	int rc;

	mutex_lock(&data->entry->node->mux);
	entry = vfs_lookup(data->entry, data->next, false, &rc);
	mutex_unlock(&data->entry->node->mux);

	if (!entry)
		return rc;

	vfs_entry_put(data->entry);
	data->entry = entry;
	data->tail = vfs_path_next_entry(data->next, data->tail);
	return 0;
}
Exemple #8
0
/*
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
 Funtion	:lstat64
 Input		:const char *path
 		 < file path to get its status >
 		 struct stat64_i386 *buf
 		 < stat structure >
 Output		:struct stat64_i386 *buf
 		 < stat structure >
 Return		:int
 		 < result >
 Description	:get file status
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
*/
SYSCALL int lstat64(const char *path, struct stat64_i386 *buf)
{
	struct file_name *fname;
	struct vnode *vnode;
	int err;
	
	//printf("lstat64:path[%s] ", path);
	
	if (UNLIKELY(!path)) {
		return(-EFAULT);
	}
	
	err = vm_check_access((void*)buf, sizeof(struct stat64_i386), PROT_WRITE);
	
	if (UNLIKELY(err)) {
		return(-EFAULT);
	}
	
	err = vfs_lookup(path, &fname, LOOKUP_ENTRY);
	
	if (err) {
		//printf("err:%d\n", -err);
		return(err);
	}
	
	vnode = fname->dentry->d_vnode;
	
	put_file_name(fname);
	
	err = vfs_stat64(vnode, buf);
	
	return(err);
}
Exemple #9
0
void vfs_get_leaf_path(struct path *path) {
	char *leaf_name;

	if ((NULL == (leaf_name = getenv("PWD")))
			|| (0 != vfs_lookup(leaf_name, path))) {
		vfs_get_root_path(path);
	}
}
Exemple #10
0
int
vfs_open(char *path, uint32_t open_flags, struct inode **node_store) {
    bool can_write = 0;
    switch (open_flags & O_ACCMODE) {
    case O_RDONLY:
        break;
    case O_WRONLY:
    case O_RDWR:
        can_write = 1;
        break;
    default:
        return -E_INVAL;
    }

    if (open_flags & O_TRUNC) {
        if (!can_write) {
            return -E_INVAL;
        }
    }

    int ret;
    struct inode *dir, *node;
    if (open_flags & O_CREAT) {
        char *name;
        bool excl = (open_flags & O_EXCL) != 0;
        if ((ret = vfs_lookup_parent(path, &dir, &name)) != 0) {
            return ret;
        }
        ret = vop_create(dir, name, excl, &node);
        vop_ref_dec(dir);
    }
    else {
        ret = vfs_lookup(path, &node);
    }

    if (ret != 0) {
        return ret;
    }
    assert(node != NULL);

    if ((ret = vop_open(node, open_flags)) != 0) {
        vop_ref_dec(node);
        return ret;
    }

    vop_open_inc(node);
    if (open_flags & O_TRUNC) {
        if ((ret = vop_truncate(node, 0)) != 0) {
            vop_open_dec(node);
            vop_ref_dec(node);
            return ret;
        }
    }
    *node_store = node;
    return 0;
}
Exemple #11
0
/*
 * vfs_chdir - Set current directory, as a pathname. Use vfs_lookup to translate
 *             it to a inode.
 */
int
vfs_chdir(char *path) { // 改变当前的路径-
    int ret;
    struct inode *node;
    if ((ret = vfs_lookup(path, &node)) == 0) {
        ret = vfs_set_curdir(node); // 设置当前的目录
        vop_ref_dec(node);
    }
    return ret;
}
Exemple #12
0
int
vfs_readlink(char *path, struct iobuf *iob) {
    int ret;
    struct inode *node;
    if ((ret = vfs_lookup(path, &node)) != 0) {
        return ret;
    }
    ret = vop_readlink(node, iob);
    vop_ref_dec(node);
    return ret;
}
Exemple #13
0
int vfs_link(const char *oldname, const char *newname)
{
	int rc;
	struct fs_entry *oldentry = vfs_resolve_path(oldname, &rc);

	if (!oldentry)
		return rc;

	struct vfs_walk_data wd;

	vfs_walk_start(&wd, newname);
	rc = vfs_walk_parent(&wd);
	if (rc) {
		vfs_walk_stop(&wd);
		vfs_entry_put(oldentry);
		return rc;
	}

	struct fs_entry *dir = wd.entry;
	struct fs_node *node = dir->node;

	if (!node->ops->lookup || !node->ops->link) {
		vfs_walk_stop(&wd);
		vfs_entry_put(oldentry);
		return -ENOTSUP;
	}
	
	mutex_lock(&node->mux);
	struct fs_entry *newentry = vfs_lookup(dir, wd.next, true, &rc);

	if (!newentry) {
		mutex_unlock(&node->mux);
		vfs_walk_stop(&wd);
		vfs_entry_put(oldentry);
		return rc;
	}

	if (newentry->node) {
		mutex_unlock(&node->mux);
		vfs_walk_stop(&wd);
		vfs_entry_put(oldentry);
		vfs_entry_put(newentry);
		return -EEXIST;
	}

	rc = node->ops->link(oldentry, node, newentry);
	mutex_unlock(&node->mux);
	vfs_walk_stop(&wd);
	vfs_entry_put(oldentry);
	vfs_entry_put(newentry);
	return rc;
}
Exemple #14
0
/*
 * Set current directory, as a pathname. Use vfs_lookup to translate
 * it to a vnode.
 */
int
vfs_chdir(char *path)
{
	struct vnode *vn;
	int result;

	result = vfs_lookup(path, &vn);
	if (result) {
		return result;
	}
	result = vfs_setcurdir(vn);
	VOP_DECREF(vn);
	return result;
}
Exemple #15
0
/*
    file_open() - open a file
*/
s32 file_open(ks8 * const path, u32 flags, file_info_t *fp)
{
    vfs_dirent_t *ent;
    s32 ret;

    ent = (vfs_dirent_t *) kmalloc(sizeof(vfs_dirent_t));
    if(!ent)
        return ENOMEM;

    /* Check that the file exists */
    ret = vfs_lookup(path, ent);
    if(ret == SUCCESS)
    {
        /* File exists.  Was exclusive creation requested? */
        if(flags & O_EXCL)
        {
            kfree(ent);
            return EEXIST;
        }

        /* Check perms */

        fp->dirent = ent;
        fp->flags = flags;
        fp->offset = (flags & O_APPEND) ? ent->size : 0;

        return SUCCESS;
    }
    else if(ret == ENOENT)
    {
        /* File does not exist.  Was creation requested? */
        if(flags & O_CREATE)
        {
            /* Check perms; create file; set offset = 0 */
            /* TODO */
            return ENOSYS;
        }
        else
        {
            kfree(ent);
            return ENOENT;      /* File does not exist */
        }
    }
    else
    {
        kfree(ent);
        return ret;     /* Something went wrong in vfs_lookup() */
    }
}
Exemple #16
0
static int vfs_file_open(const char *name, struct fs_file *file, bool create)
{
	struct vfs_walk_data wd;
	int rc;

	vfs_walk_start(&wd, name);
	rc = vfs_walk_parent(&wd);
	if (rc) {
		vfs_walk_stop(&wd);
		return rc;
	}

	struct fs_node *dir = wd.entry->node;
	struct fs_entry *entry;

	if (!dir->ops || !dir->ops->lookup) {
		vfs_walk_stop(&wd);
		return -ENOTSUP;
	}
	
	mutex_lock(&dir->mux);
	entry = vfs_lookup(wd.entry, wd.next, create, &rc);
	if (create && entry && !entry->node) {
		if (!dir->ops->create)
			rc = -ENOTSUP;
		else
			rc = dir->ops->create(dir, entry);
	}
	mutex_unlock(&dir->mux);
	vfs_walk_stop(&wd);

	if (rc) {
		vfs_entry_put(entry);
		return rc;
	}

	file->entry = entry;
	file->node = entry->node;
	file->ops = entry->node->fops;
	file->offset = 0;

	if (file->ops && file->ops->open) {
		rc = file->ops->open(file);
		if (rc)
			vfs_file_cleanup(file);
	}

	return rc;
}
Exemple #17
0
int
sc_access(thread_t *t, syscall_result_t *r, access_args_t *args)
{
    int error = 0;
    vnode_t *node;
    proc_t *proc = t->thr_proc;
    char fname[PATH_MAX];
    if((error = copyinstr(fname, args->fname, PATH_MAX)))
        return error;
    if((error = vfs_lookup(proc->p_curdir, &node, fname, t, LKP_ACCESS_REAL_ID)))
        return error;
    int res = VOP_ACCESS(node, args->mode, proc->p_cred);
    vrele(node);
    return res;
}
Exemple #18
0
/*
 * Does most of the work for readlink().
 *
 * Note, however, if you're implementing symlinks, that various
 * other parts of the VFS layer are missing crucial elements of
 * support for symlinks.
 */
int
vfs_readlink(char *path, struct uio *uio)
{
	struct vnode *vn;
	int result;

	result = vfs_lookup(path, &vn);
	if (result) {
		return result;
	}

	result = VOP_READLINK(vn, uio);

	VOP_DECREF(vn);

	return result;
}
Exemple #19
0
int vfs_mkdir(const char *name)
{
	struct vfs_walk_data wd;
	int rc;

	vfs_walk_start(&wd, name);
	rc = vfs_walk_parent(&wd);
	if (rc) {
		vfs_walk_stop(&wd);
		return rc;
	}

	struct fs_entry *dir = wd.entry;
	struct fs_node *node = dir->node;

	if (!node->ops->lookup || !node->ops->mkdir) {
		vfs_walk_stop(&wd);
		return -ENOTSUP;
	}

	mutex_lock(&node->mux);
	struct fs_entry *entry = vfs_lookup(dir, wd.next, true, &rc);

	if (!entry) {
		mutex_unlock(&node->mux);
		vfs_walk_stop(&wd);
		return rc;
	}

	if (entry->node) {
		mutex_unlock(&node->mux);
		vfs_walk_stop(&wd);
		vfs_entry_put(entry);
		return -EEXIST;
	}

	rc = node->ops->mkdir(node, entry);
	mutex_unlock(&node->mux);
	vfs_walk_stop(&wd);
	vfs_entry_put(entry);
	return rc;
}
Exemple #20
0
errno_t
sc_stat(thread_t *t, syscall_result_t *r, stat_args *args)
{
    int res=0;
    proc_t *p = t->thr_proc;
    vnode_t *node;
    char pname[PATH_MAX];
    if((res = copyinstr(pname, args->pathname, PATH_MAX)))
        return res;
    if((res = vm_is_avail((vm_addr_t)args->buf, sizeof(struct stat))))
        return res;
    res = vfs_lookup(p->p_curdir, &node, pname, t,
                      (args->mode == STAT_LINK)?LKP_NO_FOLLOW:LKP_NORMAL);
    if(res)
        return res;
    res = vnode_stat(node, args->buf);
    vrele(node);
    if(res)
        return res;
    return 0;
}
Exemple #21
0
static int sys_open(uint32_t syscall, void *stack)
{
    UNUSED_ARGUMENT(syscall);

    char const *path = PEEK_STACK(stack, char const *);
    stack = NEXT_STACK_ITEM(stack);

    /* flags and mode isn't used at the moment */

    ps_t *ps = scheduler_get_current_process();

    vnode_t *vnode = kmalloc(sizeof(vnode_t));
    if(vfs_lookup(path, vnode)) {
        log_info("sys_open",
                 "process %u tried to open non existing file %s.\n",
                 ps->id, path);
        return -1;
    }

    int fd = get_next_fd(ps->file_descriptors, PROCESS_MAX_NUM_FD);
    if (fd == -1) {
        log_info("sys_open",
                 "File descriptor table for ps %u is full.\n",
                 ps->id);
        kfree(vnode);
        return -1;
    }

    if (vnode->v_op->vn_open(vnode)) {
        log_error("sys_open",
                  "Can't open the vnode for path %s for ps %u\n",
                  path, ps->id);
        kfree(vnode);
        return -1;
    }

    ps->file_descriptors[fd].vnode = vnode;

    return fd;
}
Exemple #22
0
static mount_tty(struct tty* tty, const struct kfile_operations *file_ops) {
	struct path node;
	/* register char device */
	node = vfs_lookup("/dev");
	if (!node) {
		return -1;
	}

	mode = S_IFCHR | S_IRALL | S_IWALL;

	node = vfs_create_child(node, name, mode);
	if (!node) {
		return -1;
	}

	nas = node->nas;
	if (NULL == (nas->fs = filesystem_create("empty"))) {
		return -1;
	}

	nas->fs->file_op = file_ops;
	nas->fi = dev;
}
Exemple #23
0
int
vfs_link(char *old_path, char *new_path) {
    int ret;
    char *new_name;
    struct inode *old_node, *new_dir;
    if ((ret = vfs_lookup(old_path, &old_node)) != 0) {
        return ret;
    }
    if ((ret = vfs_lookup_parent(new_path, &new_dir, &new_name)) != 0) {
        vop_ref_dec(old_node);
        return ret;
    }

    if (old_node->in_fs == NULL || old_node->in_fs != new_dir->in_fs) {
        ret = -E_XDEV;
    }
    else {
        ret = vop_link(new_dir, new_name, old_node);
    }
    vop_ref_dec(old_node);
    vop_ref_dec(new_dir);
    return ret;
}
Exemple #24
0
int
_create(vnode_t *vn, vnode_t **vpp, const char *name, vattr_t *attr)
{
    int error;
    *vpp = NULL;
    if(!vn || !name || !attr || vn->v_type != VNODE_TYPE_DIR)
        return -EINVAL;
    ///@todo check for invalid name
    //check
    vnode_t *tmp;
    ///@todo w całym VFS i fs-ach trzeba przemyśleć strategię blokowania...
    error = vfs_lookup(vn, &tmp, name, NULL, LKP_NORMAL);
    if(error != -ENOENT) {
        if(!error)
            vrele(tmp);
        return -EEXIST; // a może raczej powinniśmy zmodyfikować ist. plik?
    }
    //plik nie istnieje -> tworzymy
    devfs_node_t *pn = vn->v_private;
    devfs_node_t *n = kmem_zalloc(sizeof(devfs_node_t), KM_SLEEP);
    if(!n)
        return -ENOMEM;

    str_cpy(n->i_name, name);
    n->i_type = (attr->va_type == VNODE_TYPE_DEV)?
                            _INODE_TYPE_DEV:_INODE_TYPE_DIR;
    n->i_attr = attr->va_mode;
    n->i_uid = attr->va_uid;
    n->i_gid = attr->va_gid;
    n->i_dirvnode = NULL;
    n->i_dev = attr->va_dev;
    n->i_parent = pn;
    n->i_child = NULL;
    n->i_next = pn->i_child;
    pn->i_child = n;
    return _get_vnode(n, vpp, vn->v_vfs);
}
Exemple #25
0
int
sc_chown(thread_t *t, syscall_result_t *r, chown_args_t *args)
{
   int res=0;
    proc_t *p = t->thr_proc;
    vnode_t *node;
    char pname[PATH_MAX];
    if((res = copyinstr(pname, args->fname, PATH_MAX)))
        return res;

    res = vfs_lookup(p->p_curdir, &node, pname, t, LKP_NORMAL);
    if(res)
        return res;
    vattr_t va;
    va.va_mask=VATTR_ALL;
    if((res = VOP_GETATTR(node, &va)))
        goto err;
    res = -EPERM;
    if(p->p_cred->p_euid != 0 && p->p_cred->p_euid != va.va_uid)
        goto err;
    if(p->p_cred->p_euid != 0)  //tak... póki co nie ma zmian dla nie roota
        goto err;
    va.va_mask = VATTR_UID | VATTR_GID | VATTR_MODE;
    if(args->uid!=-1)
        va.va_uid = args->uid;
    if(args->gid!=-1)
        va.va_gid = args->gid;
    if(p->p_cred->p_euid!=0)   //tymczasowo niemożliwe
        UNSET(va.va_mode, S_ISUID | S_ISGID);
    if((res = VOP_SETATTR(node, &va)))
        goto err;
    vrele(node);    
    return 0;
err:
    vrele(node);
    return res;
}
Exemple #26
0
void
dev_init(void) {
    init_device(null);
    init_device(stdin);
    init_device(stdout);
    init_device(disk0);
    /* for Nand flash */
    init_device(disk1);

    init_device(tty);

	//init_device(ashmem);

// link such as stdout
    int ret;
    char *new_name;
    struct inode *old_node, *new_dir; 
    if ((ret = vfs_lookup("stdout:", &old_node)) != 0) {
	kprintf("erho");
        return;// ret;
    }
    if ((ret = vfs_lookup_parent("/dev", &new_dir, &new_name)) != 0) {
        vop_ref_dec(old_node);
        return;// ret;
    }

//    if (old_node->in_fs == NULL || old_node->in_fs != new_dir->in_fs) {
//        ret = -E_XDEV;
//    }
//    else {
        ret = vop_link(new_dir, new_name, old_node);
	kprintf("odife%d\n", ret);
//    }
    vop_ref_dec(old_node);
    vop_ref_dec(new_dir);
}
Exemple #27
0
static int tmpfs_init(void * par) {
	struct path dir_path, dev_path, root;
	struct node *dev_node;
	int res;
	struct ramdisk *ramdisk;

	if (!par) {
		return 0;
	}

	/*TODO */

	if (0 != vfs_lookup(TMPFS_DIR, &dir_path)) {
		return -ENOENT;
	}

	ramdisk = ramdisk_create(tmpfs_dev, FILESYSTEM_SIZE * PAGE_SIZE());
	if (0 != (res = err(ramdisk))) {
		return res;
	}

	dev_node = ramdisk->bdev->dev_vfs_info;
	if (!dev_node) {
		return -1;
	}

	/* format filesystem */
	if (0 != (res = tmpfs_format((void *) dev_node))) {
		return res;
	}

	/* mount filesystem */
	dev_path.node = dev_node;
	dev_path.mnt_desc = root.mnt_desc;
	return tmpfs_mount(dev_path.node, dir_path.node);
}
Exemple #28
0
/*
 * Convert a pathname into a pointer to a vnode.
 *
 * The FOLLOW flag is set when symbolic links are to be followed
 * when they occur at the end of the name translation process.
 * Symbolic links are always followed for all other pathname
 * components other than the last.
 *
 * If the LOCKLEAF flag is set, a locked vnode is returned.
 *
 * The segflg defines whether the name is to be copied from user
 * space or kernel space.
 *
 * Overall outline of namei:
 *
 *	copy in name
 *	get starting directory
 *	while (!done && !error) {
 *		call lookup to search path.
 *		if symbolic link, massage name in buffer and continue
 *	}
 */
int
namei(struct nameidata *ndp)
{
	struct filedesc *fdp;		/* pointer to file descriptor state */
	char *cp;			/* pointer into pathname argument */
	struct vnode *dp;		/* the directory we are searching */
	struct iovec aiov;		/* uio for reading symbolic links */
	struct uio auio;
	int error, linklen;
	struct componentname *cnp = &ndp->ni_cnd;
	struct proc *p = cnp->cn_proc;

	ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_proc->p_ucred;
#ifdef DIAGNOSTIC
	if (!cnp->cn_cred || !cnp->cn_proc)
		panic ("namei: bad cred/proc");
	if (cnp->cn_nameiop & (~OPMASK))
		panic ("namei: nameiop contaminated with flags");
	if (cnp->cn_flags & OPMASK)
		panic ("namei: flags contaminated with nameiops");
#endif
	fdp = cnp->cn_proc->p_fd;

	/*
	 * Get a buffer for the name to be translated, and copy the
	 * name into the buffer.
	 */
	if ((cnp->cn_flags & HASBUF) == 0)
		cnp->cn_pnbuf = pool_get(&namei_pool, PR_WAITOK);
	if (ndp->ni_segflg == UIO_SYSSPACE)
		error = copystr(ndp->ni_dirp, cnp->cn_pnbuf,
			    MAXPATHLEN, &ndp->ni_pathlen);
	else
		error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf,
			    MAXPATHLEN, &ndp->ni_pathlen);

	/*
	 * Fail on null pathnames
	 */
	if (error == 0 && ndp->ni_pathlen == 1)
		error = ENOENT;

	if (error) {
fail:
		pool_put(&namei_pool, cnp->cn_pnbuf);
		ndp->ni_vp = NULL;
		return (error);
	}

#ifdef KTRACE
	if (KTRPOINT(cnp->cn_proc, KTR_NAMEI))
		ktrnamei(cnp->cn_proc, cnp->cn_pnbuf);
#endif
#if NSYSTRACE > 0
	if (ISSET(cnp->cn_proc->p_flag, P_SYSTRACE))
		systrace_namei(ndp);
#endif

	/*
	 *  Strip trailing slashes, as requested
	 */
	if (cnp->cn_flags & STRIPSLASHES) {
		char *end = cnp->cn_pnbuf + ndp->ni_pathlen - 2;

		cp = end;
		while (cp >= cnp->cn_pnbuf && (*cp == '/'))
			cp--;

		/* Still some remaining characters in the buffer */
		if (cp >= cnp->cn_pnbuf) {
			ndp->ni_pathlen -= (end - cp);
			*(cp + 1) = '\0';
		}
	}

	ndp->ni_loopcnt = 0;

	/*
	 * Get starting point for the translation.
	 */
	if ((ndp->ni_rootdir = fdp->fd_rdir) == NULL)
		ndp->ni_rootdir = rootvnode;
	if ((p->p_p->ps_flags & PS_TAMED)) {
		error = tame_namei(p, cnp->cn_pnbuf);
		if (error)
			goto fail;
	}

	/*
	 * Check if starting from root directory or current directory.
	 */
	if (cnp->cn_pnbuf[0] == '/') {
		dp = ndp->ni_rootdir;
		vref(dp);
	} else if (ndp->ni_dirfd == AT_FDCWD) {
		dp = fdp->fd_cdir;
		vref(dp);
	} else {
		struct file *fp = fd_getfile(fdp, ndp->ni_dirfd);
		if (fp == NULL) {
			pool_put(&namei_pool, cnp->cn_pnbuf);
			return (EBADF);
		}
		dp = (struct vnode *)fp->f_data;
		if (fp->f_type != DTYPE_VNODE || dp->v_type != VDIR) {
			pool_put(&namei_pool, cnp->cn_pnbuf);
			return (ENOTDIR);
		}
		vref(dp);
	}
	for (;;) {
		if (!dp->v_mount) {
			/* Give up if the directory is no longer mounted */
			pool_put(&namei_pool, cnp->cn_pnbuf);
			return (ENOENT);
		}
		cnp->cn_nameptr = cnp->cn_pnbuf;
		ndp->ni_startdir = dp;
		if ((error = vfs_lookup(ndp)) != 0) {
			pool_put(&namei_pool, cnp->cn_pnbuf);
			return (error);
		}
		/*
		 * If not a symbolic link, return search result.
		 */
		if ((cnp->cn_flags & ISSYMLINK) == 0) {
			if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0)
				pool_put(&namei_pool, cnp->cn_pnbuf);
			else
				cnp->cn_flags |= HASBUF;
			return (0);
		}
		if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN))
			VOP_UNLOCK(ndp->ni_dvp, 0, p);
		if (ndp->ni_loopcnt++ >= SYMLOOP_MAX) {
			error = ELOOP;
			break;
		}
		if (ndp->ni_pathlen > 1)
			cp = pool_get(&namei_pool, PR_WAITOK);
		else
			cp = cnp->cn_pnbuf;
		aiov.iov_base = cp;
		aiov.iov_len = MAXPATHLEN;
		auio.uio_iov = &aiov;
		auio.uio_iovcnt = 1;
		auio.uio_offset = 0;
		auio.uio_rw = UIO_READ;
		auio.uio_segflg = UIO_SYSSPACE;
		auio.uio_procp = cnp->cn_proc;
		auio.uio_resid = MAXPATHLEN;
		error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
		if (error) {
badlink:
			if (ndp->ni_pathlen > 1)
				pool_put(&namei_pool, cp);
			break;
		}
		linklen = MAXPATHLEN - auio.uio_resid;
		if (linklen == 0) {
			error = ENOENT;
			goto badlink;
		}
		if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
			error = ENAMETOOLONG;
			goto badlink;
		}
		if (ndp->ni_pathlen > 1) {
			memcpy(cp + linklen, ndp->ni_next, ndp->ni_pathlen);
			pool_put(&namei_pool, cnp->cn_pnbuf);
			cnp->cn_pnbuf = cp;
		} else
			cnp->cn_pnbuf[linklen] = '\0';
		ndp->ni_pathlen += linklen;
		vput(ndp->ni_vp);
		dp = ndp->ni_dvp;
		/*
		 * Check if root directory should replace current directory.
		 */
		if (cnp->cn_pnbuf[0] == '/') {
			vrele(dp);
			dp = ndp->ni_rootdir;
			vref(dp);
		}
	}
	pool_put(&namei_pool, cnp->cn_pnbuf);
	vrele(ndp->ni_dvp);
	vput(ndp->ni_vp);
	ndp->ni_vp = NULL;
	return (error);
}
Exemple #29
0
/* Does most of the work for open(). */
int
vfs_open(char *path, int openflags, struct vnode **ret)
{
	int how;
	int result;
	int canwrite;
	struct vnode *vn = NULL;

	how = openflags & O_ACCMODE;

	switch (how) {
	    case O_RDONLY:
		canwrite=0;
		break;
	    case O_WRONLY:
	    case O_RDWR:
		canwrite=1;
		break;
	    default:
		return EINVAL;
	}

	if (openflags & O_CREAT) {
		char name[NAME_MAX+1];
		struct vnode *dir;
		int excl = (openflags & O_EXCL)!=0;
		
		result = vfs_lookparent(path, &dir, name, sizeof(name));
		if (result) {
			return result;
		}

		result = VOP_CREAT(dir, name, excl, &vn);

		VOP_DECREF(dir);
	}
	else {
		result = vfs_lookup(path, &vn);
	}

	if (result) {
		return result;
	}

	assert(vn != NULL);

	result = VOP_OPEN(vn, openflags);
	if (result) {
		VOP_DECREF(vn);
		return result;
	}

	VOP_INCOPEN(vn);
	
	if (openflags & O_TRUNC) {
		if (canwrite==0) {
			result = EINVAL;
		}
		else {
			result = VOP_TRUNCATE(vn, 0);
		}
		if (result) {
			VOP_DECOPEN(vn);
			VOP_DECREF(vn);
			return result;
		}
	}

	*ret = vn;

	return 0;
}
Exemple #30
0
errno_t
sc_open(thread_t *p, syscall_result_t *r, sc_open_args *arg)
{
    int fd;
    int flags = arg->flags;
    int error = 0;
    vnode_t *node;
    proc_t *proc = p->thr_proc;
    char fname[PATH_MAX+1];
    if((error = copyinstr(fname, arg->fname, PATH_MAX)))
        return error;
    KASSERT(proc->p_rootdir!=NULL);
    error = vfs_lookup(proc->p_curdir, &node, fname, p, LKP_NORMAL);
    if(error) {
        if(!(flags & O_CREAT))
            return error;
        vnode_t *parent;
        error = vfs_lookup_parent(proc->p_curdir, &parent, fname, p);
        if(error)
            return error;
        if((error = VOP_ACCESS(parent, W_OK, proc->p_cred))) {
            vrele(parent);
            return error;
        }
        vattr_t attr;
        attr.va_mode = arg->mode & ~(proc->p_umask) & 0777;
        attr.va_type = VNODE_TYPE_REG;
        attr.va_uid = proc->p_cred->p_uid;
        attr.va_gid = proc->p_cred->p_gid;
        attr.va_size = 0;
        attr.va_dev = NULL;
        error = VOP_CREATE(parent, &node, _get_last_cmpt(fname), &attr);
        VOP_UNLOCK(parent);
        if(error)
            return error;
        VOP_LOCK(node);
    } else {
        //plik istnieje
        if((flags & O_CREAT) && (flags & O_EXCL)) {
            vrele(node);
            return -EEXIST;
        }
        if((node->v_type == VNODE_TYPE_DIR) && (flags & (O_RDWR | O_WRONLY))) {
            vrele(node);
            return -EISDIR;
        }
    }
    int wmode = (flags & O_RDWR) ? (W_OK | R_OK) :
                (flags & O_RDONLY) ? (R_OK) : (W_OK);
    if((error = VOP_ACCESS(node, wmode, proc->p_cred))) {
        vrele(node);
        return error;
    }
    if((error = VOP_OPEN(node, flags, arg->mode))) {
        vrele(node);
        return error;
    }
    if(ISSET(flags, O_RDWR | O_WRONLY) && ISSET(flags, O_TRUNC)
       && node->v_type == VNODE_TYPE_REG)
        VOP_TRUNCATE(node, 0);

    if((error = f_alloc(proc, node, flags, &fd))) {
        vrele(node); // <- powinno to tutaj być, dopisałem bo nie było.
        return error;
    }
    VOP_UNLOCK(node);
    r->result = fd;
    return 0;
}