summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Pierre André <jpandre@users.sourceforge.net>2012-08-22 10:00:22 +0200
committerJean-Pierre André <jpandre@users.sourceforge.net>2012-08-22 10:00:22 +0200
commit161c6c41d2ee6ae9529b36ad29e4f5123cd09fd1 (patch)
treecd12c8a007fbbf364da6ec2f85d82ba29637bcca
parent281002e1769079472a3dcc771ee0303f769e5852 (diff)
downloadillumos-fusefs-161c6c41d2ee6ae9529b36ad29e4f5123cd09fd1.tar.gz
Made sure the targets for new symlinks, fifos or dirs do not exit
-rw-r--r--kernel/fuse_vnops.c43
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));