-/* $OpenBSD: fuse_ops.c,v 1.19 2014/01/02 15:39:12 syl Exp $ */
+/* $OpenBSD: fuse_ops.c,v 1.20 2014/01/16 09:31:44 syl Exp $ */
/*
* Copyright (c) 2013 Sylvestre Gallon <ccna.syl@gmail.com>
*
return (0);
}
+static int
+ifuse_ops_mknod(struct fuse *f, struct fusebuf *fbuf)
+{
+ struct fuse_vnode *vn;
+ char *realname;
+ uint32_t mode;
+ dev_t dev;
+
+ CHECK_OPT(mknod);
+
+ mode = fbuf->fb_io_mode;
+ dev = fbuf->fb_io_rdev;
+ vn = get_vn_by_name_and_parent(f, fbuf->fb_dat, fbuf->fb_ino);
+
+ free(fbuf->fb_dat);
+ realname = build_realname(f, vn->ino);
+ fbuf->fb_err = f->op.mknod(realname, mode, dev);
+
+ if (!fbuf->fb_err) {
+ fbuf->fb_err = update_vattr(f, &fbuf->fb_vattr, realname, vn);
+ fbuf->fb_io_mode = fbuf->fb_vattr.va_mode;
+ fbuf->fb_ino = fbuf->fb_vattr.va_fileid;
+ }
+ free(realname);
+
+ return (0);
+}
+
int
ifuse_exec_opcode(struct fuse *f, struct fusebuf *fbuf)
{
case FBT_RECLAIM:
ret = ifuse_ops_reclaim(f, fbuf);
break;
+ case FBT_MKNOD:
+ ret = ifuse_ops_mknod(f, fbuf);
+ break;
default:
DPRINTF("Opcode:\t%i not supported\n", fbuf->fb_type);
DPRINTF("Inode:\t%llu\n", (unsigned long long)fbuf->fb_ino);
-/* $OpenBSD: fuse_vnops.c,v 1.12 2013/12/20 22:03:26 syl Exp $ */
+/* $OpenBSD: fuse_vnops.c,v 1.13 2014/01/16 09:31:44 syl Exp $ */
/*
* Copyright (c) 2012-2013 Sylvestre Gallon <ccna.syl@gmail.com>
*
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);
- return (EINVAL);
+
+ /* 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);
}
int
-/* $OpenBSD: fusefs.h,v 1.5 2013/12/10 13:43:05 pelikan Exp $ */
+/* $OpenBSD: fusefs.h,v 1.6 2014/01/16 09:31:44 syl Exp $ */
/*
* Copyright (c) 2012-2013 Sylvestre Gallon <ccna.syl@gmail.com>
*
#define UNDEF_SETATTR 1<<7
#define UNDEF_RENAME 1<<8
#define UNDEF_SYMLINK 1<<9
+#define UNDEF_MKNOD 1<<10
extern struct vops fusefs_vops;
extern struct pool fusefs_fbuf_pool;
-/* $OpenBSD: fusebuf.h,v 1.8 2013/12/03 09:59:40 syl Exp $ */
+/* $OpenBSD: fusebuf.h,v 1.9 2014/01/16 09:31:44 syl Exp $ */
/*
* Copyright (c) 2013 Sylvestre Gallon
* Copyright (c) 2013 Martin Pieuchot
size_t fi_len; /* Length of data */
mode_t fi_mode; /* mode for fd */
uint32_t fi_flags; /* flags on transfer */
+ dev_t fi_rdev; /* dev for mknod */
};
/*
#define fb_io_len FD.FD_io.fi_len
#define fb_io_mode FD.FD_io.fi_mode
#define fb_io_flags FD.FD_io.fi_flags
+#define fb_io_rdev FD.FD_io.fi_rdev
#define fb_dat F_databuf
/*