summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormatthew <matthew@openbsd.org>2011-07-14 18:03:06 +0000
committermatthew <matthew@openbsd.org>2011-07-14 18:03:06 +0000
commit73e08533103c791c7ced31e158012ab6eac247f5 (patch)
treee3db161e173fd61245509396587b60563fe27086
parentspacing, no binary change. (diff)
downloadwireguard-openbsd-73e08533103c791c7ced31e158012ab6eac247f5.tar.xz
wireguard-openbsd-73e08533103c791c7ced31e158012ab6eac247f5.zip
Add support for AT_REMOVEDIR to unlinkat(2), and switch sys_rmdir() to
use it. ok tedu@, guenther@
-rw-r--r--sys/kern/vfs_syscalls.c78
-rw-r--r--sys/sys/fcntl.h3
2 files changed, 32 insertions, 49 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 385d3380245..933e9b00774 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_syscalls.c,v 1.175 2011/07/12 23:36:40 matthew Exp $ */
+/* $OpenBSD: vfs_syscalls.c,v 1.176 2011/07/14 18:03:06 matthew Exp $ */
/* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */
/*
@@ -1487,9 +1487,8 @@ dounlinkat(struct proc *p, int fd, const char *path, int flag,
int error;
struct nameidata nd;
- /* XXX: Support AT_REMOVEDIR. */
- if (flag != 0)
- return (ENOTSUP);
+ if (flag & ~AT_REMOVEDIR)
+ return (EINVAL);
NDINITAT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
fd, path, p);
@@ -1497,24 +1496,41 @@ dounlinkat(struct proc *p, int fd, const char *path, int flag,
return (error);
vp = nd.ni_vp;
+ if (flag & AT_REMOVEDIR) {
+ if (vp->v_type != VDIR) {
+ error = ENOTDIR;
+ goto out;
+ }
+ /*
+ * No rmdir "." please.
+ */
+ if (nd.ni_dvp == vp) {
+ error = EBUSY;
+ goto out;
+ }
+ }
+
/*
* The root of a mounted filesystem cannot be deleted.
*/
- if (vp->v_flag & VROOT) {
+ if (vp->v_flag & VROOT)
+ error = EBUSY;
+out:
+ if (!error) {
+ if (flag & AT_REMOVEDIR) {
+ error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
+ } else {
+ (void)uvm_vnp_uncache(vp);
+ error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
+ }
+ } else {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
if (nd.ni_dvp == vp)
vrele(nd.ni_dvp);
else
vput(nd.ni_dvp);
vput(vp);
- error = EBUSY;
- goto out;
}
-
- (void)uvm_vnp_uncache(vp);
-
- error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
-out:
return (error);
}
@@ -2621,43 +2637,9 @@ sys_rmdir(struct proc *p, void *v, register_t *retval)
struct sys_rmdir_args /* {
syscallarg(const char *) path;
} */ *uap = v;
- struct vnode *vp;
- int error;
- struct nameidata nd;
- NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
- SCARG(uap, path), p);
- if ((error = namei(&nd)) != 0)
- return (error);
- vp = nd.ni_vp;
- if (vp->v_type != VDIR) {
- error = ENOTDIR;
- goto out;
- }
- /*
- * No rmdir "." please.
- */
- if (nd.ni_dvp == vp) {
- error = EBUSY;
- goto out;
- }
- /*
- * The root of a mounted filesystem cannot be deleted.
- */
- if (vp->v_flag & VROOT)
- error = EBUSY;
-out:
- if (!error) {
- error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
- } else {
- VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
- if (nd.ni_dvp == vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- vput(vp);
- }
- return (error);
+ return (dounlinkat(p, AT_FDCWD, SCARG(uap, path), AT_REMOVEDIR,
+ retval));
}
/*
diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h
index 249e96a26c8..aa9d297a051 100644
--- a/sys/sys/fcntl.h
+++ b/sys/sys/fcntl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: fcntl.h,v 1.17 2011/07/13 23:19:57 matthew Exp $ */
+/* $OpenBSD: fcntl.h,v 1.18 2011/07/14 18:03:06 matthew Exp $ */
/* $NetBSD: fcntl.h,v 1.8 1995/03/26 20:24:12 jtc Exp $ */
/*-
@@ -202,6 +202,7 @@ struct flock {
#define AT_EACCESS 0x01
#define AT_SYMLINK_NOFOLLOW 0x02
#define AT_SYMLINK_FOLLOW 0x04
+#define AT_REMOVEDIR 0x08
#endif
#endif