diff options
author | Jean-Pierre André <jpandre@users.sourceforge.net> | 2012-08-22 10:00:22 +0200 |
---|---|---|
committer | Jean-Pierre André <jpandre@users.sourceforge.net> | 2012-08-22 10:00:22 +0200 |
commit | 161c6c41d2ee6ae9529b36ad29e4f5123cd09fd1 (patch) | |
tree | cd12c8a007fbbf364da6ec2f85d82ba29637bcca | |
parent | 281002e1769079472a3dcc771ee0303f769e5852 (diff) | |
download | illumos-fusefs-161c6c41d2ee6ae9529b36ad29e4f5123cd09fd1.tar.gz |
Made sure the targets for new symlinks, fifos or dirs do not exit
-rw-r--r-- | kernel/fuse_vnops.c | 43 |
1 files changed, 35 insertions, 8 deletions
diff --git a/kernel/fuse_vnops.c b/kernel/fuse_vnops.c index 9e8cd02..f7982e6 100644 --- a/kernel/fuse_vnops.c +++ b/kernel/fuse_vnops.c @@ -1612,6 +1612,7 @@ fuse_link(struct vnode *dvp, struct vnode *srcvp, char *tnm, struct fuse_entry_out *feo; fuse_msg_node_t *msgp; char *name; + struct vnode *vp; fuse_session_t *sep; int err = DDI_SUCCESS; int nmlen = strlen(tnm) + 1; @@ -1627,6 +1628,13 @@ fuse_link(struct vnode *dvp, struct vnode *srcvp, char *tnm, if (srcvp->v_type == VDIR) return (EPERM); + /* Make sure the target does not exist */ + err = fuse_lookup_i(dvp, tnm, &vp, credp); + if (!err && vp) { + VN_RELE(vp); + return (EEXIST); + } + msgp = fuse_setup_message(sizeof (*fli) + nmlen, FUSE_LINK, VNODE_TO_NODEID(dvp), credp, FUSE_GET_UNIQUE(sep)); @@ -2295,6 +2303,7 @@ fuse_create(struct vnode *dvp, char *nm, struct vattr *vap, vcexcl_t excl, { struct fuse_vnode_data *fvdata; uint32_t stringlen; + int err; if (!nm || *nm == '\0') { DTRACE_PROBE2(fuse_create_err_invalid_name, @@ -2302,6 +2311,17 @@ fuse_create(struct vnode *dvp, char *nm, struct vattr *vap, vcexcl_t excl, return (EEXIST); } + /* Check whether the target exists */ + err = fuse_lookup_i(dvp, nm, vpp, cred_p); + if (!err && *vpp) { + VN_RELE(*vpp); + /* Recreating an existing file without O_EXCL is allowed */ + if ((vap->va_type == VREG) && !excl) + return (0); + else + return (EEXIST); + } + if (vap->va_type == VDIR) { return (VOP_MKDIR(dvp, nm, vap, vpp, cred_p, ct, 0, va)); } @@ -2318,14 +2338,6 @@ fuse_create(struct vnode *dvp, char *nm, struct vattr *vap, vcexcl_t excl, return (EINVAL); } - int lku = fuse_lookup_i(dvp, nm, vpp, cred_p); - if (*vpp) - VN_RELE(*vpp); - if (!lku) { - /* Cannot create an existing file with O_EXCL */ - return (excl ? EEXIST : 0); - } - /* * We follow the approach as in FreeBSD Fuse and provide atomic * create + open. So this create method for a regular file doesn't send @@ -3211,6 +3223,13 @@ fuse_symlink(vnode_t *dvp, char *name, vattr_t *vap, char *target, return (ENODEV); } + /* Make sure the target does not exist */ + err = fuse_lookup_i(dvp, name, &vp, credp); + if (!err && vp) { + VN_RELE(vp); + return (EEXIST); + } + msgp = fuse_setup_message(namelen + targlen, FUSE_SYMLINK, VNODE_TO_NODEID(dvp), credp, FUSE_GET_UNIQUE(sep)); @@ -3911,6 +3930,7 @@ fuse_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp, struct fuse_mkdir_in *fmkdi; fuse_msg_node_t *msgp; int err = 0; + vnode_t *vp; fuse_session_t *sep; int namelen; @@ -3927,6 +3947,13 @@ fuse_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp, return (ENAMETOOLONG); } + /* Make sure the target does not exist */ + err = fuse_lookup_i(dvp, dirname, &vp, credp); + if (!err && vp) { + VN_RELE(vp); + return (EEXIST); + } + msgp = fuse_setup_message((sizeof (*fmkdi) + namelen), FUSE_MKDIR, VTOFD(dvp)->nodeid, credp, FUSE_GET_UNIQUE(sep)); |