Esempio n. 1
0
/*
 * Create a regular file
 */
int
ufs_create(void *v)
{
	struct vop_create_v3_args /* {
		struct vnode		*a_dvp;
		struct vnode		**a_vpp;
		struct componentname	*a_cnp;
		struct vattr		*a_vap;
	} */ *ap = v;
	int	error;
	struct vnode *dvp = ap->a_dvp;
	struct ufs_lookup_results *ulr;

	/* XXX should handle this material another way */
	ulr = &VTOI(dvp)->i_crap;
	UFS_CHECK_CRAPCOUNTER(VTOI(dvp));

	/*
	 * UFS_WAPBL_BEGIN1(dvp->v_mount, dvp) performed by successful
	 * ufs_makeinode
	 */
	fstrans_start(dvp->v_mount, FSTRANS_SHARED);
	error =
	    ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
			  dvp, ulr, ap->a_vpp, ap->a_cnp);
	if (error) {
		fstrans_done(dvp->v_mount);
		return (error);
	}
	UFS_WAPBL_END1(dvp->v_mount, dvp);
	fstrans_done(dvp->v_mount);
	VN_KNOTE(dvp, NOTE_WRITE);
	VOP_UNLOCK(*ap->a_vpp);
	return (0);
}
Esempio n. 2
0
/*
 * Mknod vnode call
 */
int
ufs_mknod(void *v)
{
	struct vop_mknod_args *ap = v;
	struct vattr *vap = ap->a_vap;
        struct vnode **vpp = ap->a_vpp;
	struct inode *ip;
	int error;

	if ((error =
	     ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode),
			   ap->a_dvp, vpp, ap->a_cnp)) != 0)
		return (error);
	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
	ip = VTOI(*vpp);
	ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
	if (vap->va_rdev != VNOVAL) {
		/*
		 * Want to be able to use this to make badblock
		 * inodes, so don't truncate the dev number.
		 */
		DIP_ASSIGN(ip, rdev, vap->va_rdev);
	}
	/*
	 * Remove inode so that it will be reloaded by VFS_VGET and
	 * checked to see if it is an alias of an existing entry in
	 * the inode cache.
	 */
	vput(*vpp);
	(*vpp)->v_type = VNON;
	vgone(*vpp);
	*vpp = NULL;
	return (0);
}
Esempio n. 3
0
/*
    struct vnop_mkdir_args {
	struct vnode *a_dvp;
	struct vnode **a_vpp;
	struct componentname *a_cnp;
	struct vattr *a_vap;
    };
*/
static int
fuse_vnop_mkdir(struct vop_mkdir_args *ap)
{
	struct vnode *dvp = ap->a_dvp;
	struct vnode **vpp = ap->a_vpp;
	struct componentname *cnp = ap->a_cnp;
	struct vattr *vap = ap->a_vap;

	int err = 0;

	struct fuse_mkdir_in fmdi;

	fuse_trace_printf_vnop();

	if (fuse_isdeadfs(dvp)) {
		return ENXIO;
	}
	fmdi.mode = MAKEIMODE(vap->va_type, vap->va_mode);

	err = fuse_internal_newentry(dvp, vpp, cnp, FUSE_MKDIR, &fmdi,
	    sizeof(fmdi), VDIR);

	if (err == 0) {
		fuse_invalidate_attr(dvp);
	}
	return err;
}
Esempio n. 4
0
int
fusefs_mkdir(void *v)
{
	struct vop_mkdir_args *ap = v;
	struct vnode *dvp = ap->a_dvp;
	struct vnode **vpp = ap->a_vpp;
	struct componentname *cnp = ap->a_cnp;
	struct vattr *vap = ap->a_vap;
	struct proc *p = cnp->cn_proc;
	struct vnode *tdp = NULL;
	struct fusefs_node *ip;
	struct fusefs_mnt *fmp;
	struct fusebuf *fbuf;
	int error = 0;

	DPRINTF("fusefs_mkdir %s\n", cnp->cn_nameptr);

	ip = VTOI(dvp);
	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;


	if (!fmp->sess_init || (fmp->undef_op & UNDEF_MKDIR)) {
		error = ENOSYS;
		goto out;
	}

	fbuf = fb_setup(FUSEFDSIZE + cnp->cn_namelen + 1, ip->ufs_ino.i_number,
	    FBT_MKDIR, p);

	fbuf->fb_io_mode = MAKEIMODE(vap->va_type, vap->va_mode);
	memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen);
	fbuf->fb_dat[cnp->cn_namelen] = '\0';

	error = fb_queue(fmp->dev, fbuf);
	if (error) {
		if (error == ENOSYS)
			fmp->undef_op |= UNDEF_MKDIR;

		pool_put(&fusefs_fbuf_pool, fbuf);
		goto out;
	}

	if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp))) {
		pool_put(&fusefs_fbuf_pool, fbuf);
		goto out;
	}

	tdp->v_type = IFTOVT(fbuf->fb_io_mode);
	VTOI(tdp)->vtype = tdp->v_type;

	if (dvp != NULL && dvp->v_type == VDIR)
		VTOI(tdp)->parent = ip->ufs_ino.i_number;

	*vpp = tdp;
	VN_KNOTE(ap->a_dvp, NOTE_WRITE | NOTE_LINK);
	pool_put(&fusefs_fbuf_pool, fbuf);
out:
	vput(dvp);
	return (error);
}
Esempio n. 5
0
/*
 * Create a regular file
 */
int
ext2fs_create(void *v)
{
	struct vop_create_args *ap = v;
	return ext2fs_makeinode(MAKEIMODE(ap->a_vap->va_type, 
					  ap->a_vap->va_mode),
			  	ap->a_dvp, ap->a_vpp, ap->a_cnp);
}
Esempio n. 6
0
/*
 * Create a regular file
 */
static int
ext2_create(struct vop_create_args *ap)
{
	int error;

	error =
	    ext2_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
	    ap->a_dvp, ap->a_vpp, ap->a_cnp);
	if (error)
		return (error);
	return (0);
}
Esempio n. 7
0
/*
 * Create a regular file
 */
int
ufs_create(void *v)
{
	struct vop_create_args *ap = v;
	int error;

	error =
	    ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
			  ap->a_dvp, ap->a_vpp, ap->a_cnp);
	if (error)
		return (error);
	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
	return (0);
}
Esempio n. 8
0
/* ARGSUSED */
int
ext2fs_mknod(void *v)
{
	struct vop_mknod_v3_args /* {
		struct vnode *a_dvp;
		struct vnode **a_vpp;
		struct componentname *a_cnp;
		struct vattr *a_vap;
	} */ *ap = v;
	struct vattr *vap = ap->a_vap;
	struct vnode **vpp = ap->a_vpp;
	struct inode *ip;
	int error;
	struct mount	*mp;
	ino_t		ino;

	if ((error = ext2fs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode),
		    ap->a_dvp, vpp, ap->a_cnp)) != 0)
		return (error);
	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
	ip = VTOI(*vpp);
	mp  = (*vpp)->v_mount;
	ino = ip->i_number;
	ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
	if (vap->va_rdev != VNOVAL) {
		/*
		 * Want to be able to use this to make badblock
		 * inodes, so don't truncate the dev number.
		 */
		ip->i_din.e2fs_din->e2di_rdev = h2fs32(vap->va_rdev);
	}
	/*
	 * Remove inode so that it will be reloaded by VFS_VGET and
	 * checked to see if it is an alias of an existing entry in
	 * the inode cache.
	 */
	(*vpp)->v_type = VNON;
	VOP_UNLOCK(*vpp);
	vgone(*vpp);
	error = VFS_VGET(mp, ino, vpp);
	if (error != 0) {
		*vpp = NULL;
		return (error);
	}
	VOP_UNLOCK(*vpp);
	return (0);
}
/*
 * Create a regular file
 */
int
ext2fs_create(void *v)
{
	struct vop_create_args /* {
		struct vnode *a_dvp;
		struct vnode **a_vpp;
		struct componentname *a_cnp;
		struct vattr *a_vap;
	} */ *ap = v;
	int	error;

	error =
	    ext2fs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
			     ap->a_dvp, ap->a_vpp, ap->a_cnp);

	if (error)
		return (error);
	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
	return (0);
}
Esempio n. 10
0
/* ARGSUSED */
static int
ext2_mknod(struct vop_mknod_args *ap)
{
	struct vattr *vap = ap->a_vap;
	struct vnode **vpp = ap->a_vpp;
	struct inode *ip;
	ino_t ino;
	int error;

	error = ext2_makeinode(MAKEIMODE(vap->va_type, vap->va_mode),
	    ap->a_dvp, vpp, ap->a_cnp);
	if (error)
		return (error);
	ip = VTOI(*vpp);
	ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
	if (vap->va_rdev != VNOVAL) {
		/*
		 * Want to be able to use this to make badblock
		 * inodes, so don't truncate the dev number.
		 */
		ip->i_rdev = vap->va_rdev;
	}
	/*
	 * Remove inode, then reload it through VFS_VGET so it is
	 * checked to see if it is an alias of an existing entry in
	 * the inode cache.	 XXX I don't believe this is necessary now.
	 */
	(*vpp)->v_type = VNON;
	ino = ip->i_number;	/* Save this before vgone() invalidates ip. */
	vgone(*vpp);
	vput(*vpp);
	error = VFS_VGET(ap->a_dvp->v_mount, ino, LK_EXCLUSIVE, vpp);
	if (error) {
		*vpp = NULL;
		return (error);
	}
	return (0);
}
Esempio n. 11
0
/* ARGSUSED */
static int
xattr_file_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
    caller_context_t *ct)
{
	xattr_file_t *np = vp->v_data;
	timestruc_t now;
	size_t size;
	int error;
	vnode_t *pvp;
	vattr_t pvattr;

	vap->va_type = VREG;
	vap->va_mode = MAKEIMODE(vap->va_type,
	    (np->xattr_view == XATTR_VIEW_READONLY ? 0444 : 0644));
	vap->va_nodeid = gfs_file_inode(vp);
	vap->va_nlink = 1;
	pvp = gfs_file_parent(vp);
	(void) memset(&pvattr, 0, sizeof (pvattr));
	pvattr.va_mask = AT_CTIME|AT_MTIME;
	error = VOP_GETATTR(pvp, &pvattr, flags, cr, ct);
	if (error) {
		return (error);
	}
	vap->va_ctime = pvattr.va_ctime;
	vap->va_mtime = pvattr.va_mtime;
	gethrestime(&now);
	vap->va_atime = now;
	vap->va_uid = 0;
	vap->va_gid = 0;
	vap->va_rdev = 0;
	vap->va_blksize = DEV_BSIZE;
	vap->va_seq = 0;
	vap->va_fsid = vp->v_vfsp->vfs_dev;
	error = xattr_file_size(vp, np->xattr_view, &size, cr, ct);
	vap->va_size = size;
	vap->va_nblocks = howmany(vap->va_size, vap->va_blksize);
	return (error);
}
Esempio n. 12
0
int
fusefs_mknod(void *v)
{
	struct vop_mknod_args *ap = v;
	struct componentname *cnp = ap->a_cnp;
	struct vnode **vpp = ap->a_vpp;
	struct vnode *dvp = ap->a_dvp;
	struct vattr *vap = ap->a_vap;
	struct proc *p = cnp->cn_proc;
	struct vnode *tdp = NULL;
	struct fusefs_mnt *fmp;
	struct fusefs_node *ip;
	struct fusebuf *fbuf;
	int error = 0;

	ip = VTOI(dvp);
	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;

	if (!fmp->sess_init || (fmp->undef_op & UNDEF_MKNOD)) {
		error = ENOSYS;
		goto out;
	}

	fbuf = fb_setup(cnp->cn_namelen + 1, ip->ufs_ino.i_number,
	    FBT_MKNOD, p);

	fbuf->fb_io_mode = MAKEIMODE(vap->va_type, vap->va_mode);
	if (vap->va_rdev != VNOVAL)
		fbuf->fb_io_rdev = vap->va_rdev;

	memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen);
	fbuf->fb_dat[cnp->cn_namelen] = '\0';

	error = fb_queue(fmp->dev, fbuf);
	if (error) {
		if (error == ENOSYS)
			fmp->undef_op |= UNDEF_MKNOD;

		fb_delete(fbuf);
		goto out;
	}

	if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp))) {
		fb_delete(fbuf);
		goto out;
	}

	tdp->v_type = IFTOVT(fbuf->fb_io_mode);
	VTOI(tdp)->vtype = tdp->v_type;

	if (dvp != NULL && dvp->v_type == VDIR)
		VTOI(tdp)->parent = ip->ufs_ino.i_number;

	*vpp = tdp;
	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
	fb_delete(fbuf);
	vput(ap->a_dvp);

	/* Remove inode so that it will be reloaded by VFS_VGET and
	 * checked to see if it is an alias of an existing entry in
	 * the inode cache.
	 */
	vput(*vpp);
	(*vpp)->v_type = VNON;
	vgone(*vpp);
	*vpp = NULL;
	return (0);
out:
	vput(ap->a_dvp);
	return (error);
}
Esempio n. 13
0
/* ARGSUSED */
int
ufs_mknod(void *v)
{
	struct vop_mknod_v3_args /* {
		struct vnode		*a_dvp;
		struct vnode		**a_vpp;
		struct componentname	*a_cnp;
		struct vattr		*a_vap;
	} */ *ap = v;
	struct vattr	*vap;
	struct vnode	**vpp;
	struct inode	*ip;
	int		error;
	struct mount	*mp;
	ino_t		ino;
	struct ufs_lookup_results *ulr;

	vap = ap->a_vap;
	vpp = ap->a_vpp;

	/* XXX should handle this material another way */
	ulr = &VTOI(ap->a_dvp)->i_crap;
	UFS_CHECK_CRAPCOUNTER(VTOI(ap->a_dvp));

	/*
	 * UFS_WAPBL_BEGIN1(dvp->v_mount, dvp) performed by successful
	 * ufs_makeinode
	 */
	fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED);
	if ((error =
	    ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode),
	    ap->a_dvp, ulr, vpp, ap->a_cnp)) != 0)
		goto out;
	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
	ip = VTOI(*vpp);
	mp  = (*vpp)->v_mount;
	ino = ip->i_number;
	ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
	if (vap->va_rdev != VNOVAL) {
		struct ufsmount *ump = ip->i_ump;
		/*
		 * Want to be able to use this to make badblock
		 * inodes, so don't truncate the dev number.
		 */
		if (ump->um_fstype == UFS1)
			ip->i_ffs1_rdev = ufs_rw32(vap->va_rdev,
			    UFS_MPNEEDSWAP(ump));
		else
			ip->i_ffs2_rdev = ufs_rw64(vap->va_rdev,
			    UFS_MPNEEDSWAP(ump));
	}
	UFS_WAPBL_UPDATE(*vpp, NULL, NULL, 0);
	UFS_WAPBL_END1(ap->a_dvp->v_mount, ap->a_dvp);
	/*
	 * Remove inode so that it will be reloaded by vcache_get and
	 * checked to see if it is an alias of an existing entry in
	 * the inode cache.
	 */
	(*vpp)->v_type = VNON;
	VOP_UNLOCK(*vpp);
	vgone(*vpp);
	error = vcache_get(mp, &ino, sizeof(ino), vpp);
out:
	fstrans_done(ap->a_dvp->v_mount);
	if (error != 0) {
		*vpp = NULL;
		return (error);
	}
	return (0);
}
Esempio n. 14
0
/*
    struct vnop_create_args {
	struct vnode *a_dvp;
	struct vnode **a_vpp;
	struct componentname *a_cnp;
	struct vattr *a_vap;
    };
*/
static int
fuse_vnop_create(struct vop_create_args *ap)
{
	struct vnode *dvp = ap->a_dvp;
	struct vnode **vpp = ap->a_vpp;
	struct componentname *cnp = ap->a_cnp;
	struct vattr *vap = ap->a_vap;
	struct thread *td = cnp->cn_thread;
	struct ucred *cred = cnp->cn_cred;

	struct fuse_open_in *foi;
	struct fuse_entry_out *feo;
	struct fuse_dispatcher fdi;
	struct fuse_dispatcher *fdip = &fdi;

	int err;

	struct mount *mp = vnode_mount(dvp);
	uint64_t parentnid = VTOFUD(dvp)->nid;
	mode_t mode = MAKEIMODE(vap->va_type, vap->va_mode);
	uint64_t x_fh_id;
	uint32_t x_open_flags;

	fuse_trace_printf_vnop();

	if (fuse_isdeadfs(dvp)) {
		return ENXIO;
	}
	bzero(&fdi, sizeof(fdi));

	/* XXX:	Will we ever want devices ? */
	if ((vap->va_type != VREG)) {
		MPASS(vap->va_type != VFIFO);
		goto bringup;
	}
	debug_printf("parent nid = %ju, mode = %x\n", (uintmax_t)parentnid,
	    mode);

	fdisp_init(fdip, sizeof(*foi) + cnp->cn_namelen + 1);
	if (!fsess_isimpl(mp, FUSE_CREATE)) {
		debug_printf("eh, daemon doesn't implement create?\n");
		return (EINVAL);
	}
	fdisp_make(fdip, FUSE_CREATE, vnode_mount(dvp), parentnid, td, cred);

	foi = fdip->indata;
	foi->mode = mode;
	foi->flags = O_CREAT | O_RDWR;

	memcpy((char *)fdip->indata + sizeof(*foi), cnp->cn_nameptr,
	    cnp->cn_namelen);
	((char *)fdip->indata)[sizeof(*foi) + cnp->cn_namelen] = '\0';

	err = fdisp_wait_answ(fdip);

	if (err) {
		if (err == ENOSYS)
			fsess_set_notimpl(mp, FUSE_CREATE);
		debug_printf("create: got err=%d from daemon\n", err);
		goto out;
	}
bringup:
	feo = fdip->answ;

	if ((err = fuse_internal_checkentry(feo, VREG))) {
		goto out;
	}
	err = fuse_vnode_get(mp, feo->nodeid, dvp, vpp, cnp, VREG);
	if (err) {
		struct fuse_release_in *fri;
		uint64_t nodeid = feo->nodeid;
		uint64_t fh_id = ((struct fuse_open_out *)(feo + 1))->fh;

		fdisp_init(fdip, sizeof(*fri));
		fdisp_make(fdip, FUSE_RELEASE, mp, nodeid, td, cred);
		fri = fdip->indata;
		fri->fh = fh_id;
		fri->flags = OFLAGS(mode);
		fuse_insert_callback(fdip->tick, fuse_internal_forget_callback);
		fuse_insert_message(fdip->tick);
		return err;
	}
	ASSERT_VOP_ELOCKED(*vpp, "fuse_vnop_create");

	fdip->answ = feo + 1;

	x_fh_id = ((struct fuse_open_out *)(feo + 1))->fh;
	x_open_flags = ((struct fuse_open_out *)(feo + 1))->open_flags;
	fuse_filehandle_init(*vpp, FUFH_RDWR, NULL, x_fh_id);
	fuse_vnode_open(*vpp, x_open_flags, td);
	cache_purge_negative(dvp);

out:
	fdisp_destroy(fdip);
	return err;
}
Esempio n. 15
0
/* ARGSUSED */
static int
xattr_dir_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
    caller_context_t *ct)
{
	timestruc_t now;
	vnode_t *pvp;
	int error;

	error = xattr_dir_realdir(vp, &pvp, LOOKUP_XATTR, cr, ct);
	if (error == 0) {
		error = VOP_GETATTR(pvp, vap, 0, cr, ct);
		if (error) {
			return (error);
		}
		vap->va_nlink += XATTRDIR_NENTS;
		vap->va_size += XATTRDIR_NENTS;
		return (0);
	}

	/*
	 * There is no real xattr directory.  Cobble together
	 * an entry using info from the parent object (if needed)
	 * plus information common to all xattrs.
	 */
	if (vap->va_mask & PARENT_ATTRMASK) {
		vattr_t pvattr;
		uint_t  off_bits;

		pvp = gfs_file_parent(vp);
		(void) memset(&pvattr, 0, sizeof (pvattr));
		pvattr.va_mask = PARENT_ATTRMASK;
		error = VOP_GETATTR(pvp, &pvattr, 0, cr, ct);
		if (error) {
			return (error);
		}

		/*
		 * VOP_GETATTR() might have turned off some bits in
		 * pvattr.va_mask.  This means that the underlying
		 * file system couldn't process those attributes.
		 * We need to make sure those bits get turned off
		 * in the vattr_t structure that gets passed back
		 * to the caller.  Figure out which bits were turned
		 * off (if any) then set pvattr.va_mask before it
		 * gets copied to the vattr_t that the caller sees.
		 */
		off_bits = (pvattr.va_mask ^ PARENT_ATTRMASK) & PARENT_ATTRMASK;
		pvattr.va_mask = vap->va_mask & ~off_bits;
		*vap = pvattr;
	}

	vap->va_type = VDIR;
	vap->va_mode = MAKEIMODE(vap->va_type, S_ISVTX | 0777);
	vap->va_fsid = vp->v_vfsp->vfs_dev;
	vap->va_nodeid = gfs_file_inode(vp);
	vap->va_nlink = XATTRDIR_NENTS+2;
	vap->va_size = vap->va_nlink;
	gethrestime(&now);
	vap->va_atime = now;
	vap->va_blksize = 0;
	vap->va_nblocks = 0;
	vap->va_seq = 0;
	return (0);
}
Esempio n. 16
0
static int
ncreate_9p(vnode_t dvp, vnode_t *vpp, struct componentname *cnp, struct vnode_attr *vap, vfs_context_t ctx, char *target)
{
	openfid_9p *op;
	mount_9p *nmp;
	node_9p *dnp, *np;
	uint32_t perm, iounit;
	uint8_t mode;
	fid_9p fid, openfid;
	qid_9p qid;
	char *ext, buf[64];
	int e;

	dnp = NTO9P(dvp);
	nmp = dnp->nmp;
	fid = NOFID;
	openfid = NOFID;
	*vpp = NULL;

	if (vnode_vfsisrdonly(dvp))
		return EROFS;

	if (!ISSET(nmp->flags, F_DOTU) && vap->va_type!=VREG && vap->va_type!=VDIR)
		return ENOTSUP;

	if (!ISSET(nmp->flags, FLAG_DSSTORE) &&
		strncmp(".DS_Store", cnp->cn_nameptr, cnp->cn_namelen)==0)
		return EINVAL;

	ext = "";
	mode = ORDWR;
	perm = MAKEIMODE(vap->va_type, vap->va_mode) & 0777;
	switch (vap->va_type) {
	case VREG:
		break;

	case VDIR:
		mode = OREAD;
		SET(perm, DMDIR);
		break;

	case VBLK:
	case VCHR:
		SET(perm, DMDEVICE);
		snprintf(buf, sizeof(buf), "%c %d %d", vap->va_type==VBLK?'b':'c', vap->va_rdev>>20, vap->va_rdev&((1<<20) - 1));
		ext = buf;
		break;

	case VFIFO:
		SET(perm, DMNAMEDPIPE);
		break;

	case VSOCK:
		SET(perm, DMSOCKET);
		break;

	case VLNK:
		SET(perm, DMSYMLINK);
		ext = target;
		break;

	default:
		return EINVAL;
	}
	
	if (ISSET(vap->va_vaflags, VA_EXCLUSIVE))
		SET(mode, OEXCL);

	
	nlock_9p(dnp, NODE_LCK_EXCLUSIVE);
	if ((e=walk_9p(nmp, dnp->fid, NULL, 0, &openfid, &qid)))
		goto error;
	if ((e=create_9p(nmp, openfid, cnp->cn_nameptr, cnp->cn_namelen, mode, perm, ext, &qid, &iounit)))
		goto error;
	if ((e=walk_9p(nmp, dnp->fid, cnp->cn_nameptr, cnp->cn_namelen, &fid, &qid)))
		goto error;
	if ((e=nget_9p(nmp, fid, qid, dvp, vpp, cnp, ctx)))
		goto error;

	cache_purge_negatives(dvp);
	np = NTO9P(*vpp);
	np->iounit = iounit;
	op = &np->openfid[vap->va_type==VDIR? OREAD: ORDWR];
	op->fid = openfid;
	OSIncrementAtomic(&op->ref);
	nunlock_9p(np);
	nunlock_9p(dnp);
	return 0;

error:
	clunk_9p(nmp, openfid);
	clunk_9p(nmp, fid);
	nunlock_9p(dnp);
	return e;
}
Esempio n. 17
0
int
fusefs_create(void *v)
{
	struct vop_create_args *ap = v;
	struct componentname *cnp = ap->a_cnp;
	struct vnode **vpp = ap->a_vpp;
	struct vnode *dvp = ap->a_dvp;
	struct vattr *vap = ap->a_vap;
	struct proc *p = cnp->cn_proc;
	struct vnode *tdp = NULL;
	struct fusefs_mnt *fmp;
	struct fusefs_node *ip;
	struct fusebuf *fbuf;
	int error = 0;
	mode_t mode;

	ip = VTOI(dvp);
	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
	mode = MAKEIMODE(vap->va_type, vap->va_mode);

	if (!fmp->sess_init || (fmp->undef_op & UNDEF_CREATE)) {
		error = ENOSYS;
		goto out;
	}

	fbuf = fb_setup(cnp->cn_namelen + 1, ip->ufs_ino.i_number,
	    FBT_CREATE, p);

	fbuf->fb_io_mode = mode;
	fbuf->fb_io_flags = O_CREAT | O_RDWR;

	memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen);
	fbuf->fb_dat[cnp->cn_namelen] = '\0';

	error = fb_queue(fmp->dev, fbuf);
	if (error) {
		if (error == ENOSYS)
			fmp->undef_op |= UNDEF_CREATE;

		fb_delete(fbuf);
		goto out;
	}

	if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp))) {
		fb_delete(fbuf);
		goto out;
	}

	tdp->v_type = IFTOVT(fbuf->fb_io_mode);
	VTOI(tdp)->vtype = tdp->v_type;

	if (dvp != NULL && dvp->v_type == VDIR)
		VTOI(tdp)->parent = ip->ufs_ino.i_number;

	*vpp = tdp;
	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
	fb_delete(fbuf);
out:
	vput(ap->a_dvp);
	return (error);
}
/*
 * Allocate a new inode.
 */
int
ulfs_makeinode(struct vattr *vap, struct vnode *dvp,
	const struct ulfs_lookup_results *ulr,
	struct vnode **vpp, struct componentname *cnp)
{
	struct inode	*ip;
	struct vnode	*tvp;
	int		error;

	error = vcache_new(dvp->v_mount, dvp, vap, cnp->cn_cred, &tvp);
	if (error)
		return error;
	error = vn_lock(tvp, LK_EXCLUSIVE);
	if (error) {
		vrele(tvp);
		return error;
	}
	lfs_mark_vnode(tvp);
	*vpp = tvp;
	ip = VTOI(tvp);
	ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
	ip->i_nlink = 1;
	DIP_ASSIGN(ip, nlink, 1);

	/* Authorize setting SGID if needed. */
	if (ip->i_mode & ISGID) {
		error = kauth_authorize_vnode(cnp->cn_cred, KAUTH_VNODE_WRITE_SECURITY,
		    tvp, NULL, genfs_can_chmod(tvp->v_type, cnp->cn_cred, ip->i_uid,
		    ip->i_gid, MAKEIMODE(vap->va_type, vap->va_mode)));
		if (error) {
			ip->i_mode &= ~ISGID;
			DIP_ASSIGN(ip, mode, ip->i_mode);
		}
	}

	if (cnp->cn_flags & ISWHITEOUT) {
		ip->i_flags |= UF_OPAQUE;
		DIP_ASSIGN(ip, flags, ip->i_flags);
	}

	/*
	 * Make sure inode goes to disk before directory entry.
	 */
	if ((error = lfs_update(tvp, NULL, NULL, UPDATE_DIROP)) != 0)
		goto bad;
	error = ulfs_direnter(dvp, ulr, tvp,
			      cnp, ip->i_number, LFS_IFTODT(ip->i_mode), NULL);
	if (error)
		goto bad;
	*vpp = tvp;
	return (0);

 bad:
	/*
	 * Write error occurred trying to update the inode
	 * or the directory so must deallocate the inode.
	 */
	ip->i_nlink = 0;
	DIP_ASSIGN(ip, nlink, 0);
	ip->i_flag |= IN_CHANGE;
	/* If IN_ADIROP, account for it */
	lfs_unmark_vnode(tvp);
	vput(tvp);
	return (error);
}