Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/fs/udf Implement udf_rename() using the new genfs_rename...
details: https://anonhg.NetBSD.org/src/rev/e5ea585900d5
branches: trunk
changeset: 787870:e5ea585900d5
user: reinoud <reinoud%NetBSD.org@localhost>
date: Wed Jul 10 15:10:56 2013 +0000
description:
Implement udf_rename() using the new genfs_rename() framework.
Fixes PR kern/47986
diffstat:
sys/fs/udf/files.udf | 3 +-
sys/fs/udf/udf_rename.c | 671 ++++++++++++++++++++++++++++++++++++++++++++++++
sys/fs/udf/udf_vnops.c | 266 +------------------
3 files changed, 683 insertions(+), 257 deletions(-)
diffs (truncated from 1000 to 300 lines):
diff -r 46f1e1b5cba8 -r e5ea585900d5 sys/fs/udf/files.udf
--- a/sys/fs/udf/files.udf Wed Jul 10 15:08:38 2013 +0000
+++ b/sys/fs/udf/files.udf Wed Jul 10 15:10:56 2013 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: files.udf,v 1.4 2010/03/02 16:43:48 pooka Exp $
+# $NetBSD: files.udf,v 1.5 2013/07/10 15:10:56 reinoud Exp $
deffs UDF
@@ -12,4 +12,5 @@
file fs/udf/udf_strat_direct.c udf
file fs/udf/udf_strat_rmw.c udf
file fs/udf/udf_allocation.c udf
+file fs/udf/udf_rename.c udf
diff -r 46f1e1b5cba8 -r e5ea585900d5 sys/fs/udf/udf_rename.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/fs/udf/udf_rename.c Wed Jul 10 15:10:56 2013 +0000
@@ -0,0 +1,671 @@
+/* $NetBSD: udf_rename.c,v 1.1 2013/07/10 15:10:56 reinoud Exp $ */
+
+/*
+ * Copyright (c) 2013 Reinoud Zandijk
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Comments and trivial code from the reference implementation in tmpfs.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: udf_rename.c,v 1.1 2013/07/10 15:10:56 reinoud Exp $");
+
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/kauth.h>
+#include <sys/mount.h>
+#include <sys/namei.h>
+#include <sys/stat.h>
+#include <sys/malloc.h>
+#include <sys/dirent.h>
+#include <sys/vnode.h>
+#include <sys/vnode_if.h>
+
+#include <miscfs/genfs/genfs.h>
+
+#include <fs/udf/ecma167-udf.h>
+#include <fs/udf/udf_mount.h>
+#include <sys/dirhash.h>
+
+#include "udf.h"
+#include "udf_subr.h"
+#include "udf_bswap.h"
+
+
+/* forwards */
+static int udf_sane_rename( struct vnode *, struct componentname *,
+ struct vnode *, struct componentname *,
+ kauth_cred_t, bool);
+static bool udf_rmdired_p(struct vnode *);
+static int udf_gro_lock_directory(struct mount *, struct vnode *);
+
+static const struct genfs_rename_ops udf_genfs_rename_ops;
+
+
+#define VTOI(vnode) ((struct udf_node *) (vnode)->v_data)
+
+
+/*
+ * udf_sane_rename: The hairiest vop, with the saner API.
+ *
+ * Arguments:
+ *
+ * . fdvp (from directory vnode),
+ * . fcnp (from component name),
+ * . tdvp (to directory vnode),
+ * . tcnp (to component name),
+ * . cred (credentials structure), and
+ * . posixly_correct (flag for behaviour if target & source link same file).
+ *
+ * fdvp and tdvp may be the same, and must be referenced and unlocked.
+ */
+static int
+udf_sane_rename( struct vnode *fdvp, struct componentname *fcnp,
+ struct vnode *tdvp, struct componentname *tcnp,
+ kauth_cred_t cred, bool posixly_correct)
+{
+ struct dirent fdirent, tdirent; /* XXX OK? XXX */
+
+ DPRINTF(CALL, ("udf_sane_rename '%s' -> '%s'\n",
+ fcnp->cn_nameptr, tcnp->cn_nameptr));
+ return genfs_sane_rename(&udf_genfs_rename_ops,
+ fdvp, fcnp, &fdirent, tdvp, tcnp, &tdirent,
+ cred, posixly_correct);
+}
+
+
+/*
+ * udf_rename: the hairiest vop, with the insanest API. Pass to
+ * genfs_insane_rename immediately.
+ */
+int
+udf_rename(void *v)
+{
+ struct vop_rename_args /* {
+ struct vnode *a_fdvp;
+ struct vnode *a_fvp;
+ struct componentname *a_fcnp;
+ struct vnode *a_tdvp;
+ struct vnode *a_tvp;
+ struct componentname *a_tcnp;
+ } */ *ap = v;
+ DPRINTF(CALL, ("udf_rename called\n"));
+ return genfs_insane_rename(ap, &udf_sane_rename);
+}
+
+
+/*
+ * udf_gro_directory_empty_p: return true if the directory vp is empty. dvp is
+ * its parent.
+ *
+ * vp and dvp must be locked and referenced.
+ */
+static bool
+udf_gro_directory_empty_p(struct mount *mp, kauth_cred_t cred,
+ struct vnode *vp, struct vnode *dvp)
+{
+ struct udf_node *udf_node = VTOI(vp);
+ int error, isempty;
+
+ KASSERT(mp != NULL);
+ KASSERT(vp != NULL);
+ KASSERT(dvp != NULL);
+ KASSERT(vp != dvp);
+ KASSERT(vp->v_mount == mp);
+ KASSERT(dvp->v_mount == mp);
+ KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+ KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
+
+ DPRINTF(CALL, ("udf_gro_directory_empty_p called\n"));
+ /* make sure our `leaf' node's hash is populated */
+ dirhash_get(&udf_node->dir_hash);
+ error = udf_dirhash_fill(udf_node);
+ if (error) {
+ dirhash_put(udf_node->dir_hash);
+ return error;
+ }
+
+ /* check to see if the directory is empty */
+ isempty = dirhash_dir_isempty(udf_node->dir_hash);
+ dirhash_put(udf_node->dir_hash);
+
+ return isempty;
+}
+
+
+/*
+ * udf_gro_rename_check_possible: check whether a rename is possible
+ * independent of credentials.
+ */
+static int
+udf_gro_rename_check_possible(struct mount *mp,
+ struct vnode *fdvp, struct vnode *fvp,
+ struct vnode *tdvp, struct vnode *tvp)
+{
+ (void)mp;
+ KASSERT(mp != NULL);
+ KASSERT(fdvp != NULL);
+ KASSERT(fvp != NULL);
+ KASSERT(tdvp != NULL);
+ KASSERT(fdvp != fvp);
+ KASSERT(fdvp != tvp);
+ KASSERT(tdvp != fvp);
+ KASSERT(tdvp != tvp);
+ KASSERT(fvp != tvp);
+ KASSERT(fdvp->v_type == VDIR);
+ KASSERT(tdvp->v_type == VDIR);
+ KASSERT(fdvp->v_mount == mp);
+ KASSERT(fvp->v_mount == mp);
+ KASSERT(tdvp->v_mount == mp);
+ KASSERT((tvp == NULL) || (tvp->v_mount == mp));
+ KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
+ KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
+ KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
+ KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
+
+ DPRINTF(CALL, ("udf_gro_rename_check_possible called\n"));
+ if (mp->mnt_flag & MNT_RDONLY)
+ return EROFS;
+
+ /* flags not implemented since they are not defined (yet) in UDF */
+ return 0;
+}
+
+
+/*
+ * udf_gro_rename_check_permitted: check whether a rename is permitted given
+ * our credentials.
+ */
+static int
+udf_gro_rename_check_permitted(struct mount *mp, kauth_cred_t cred,
+ struct vnode *fdvp, struct vnode *fvp,
+ struct vnode *tdvp, struct vnode *tvp)
+{
+ struct udf_node *fdir_node = VTOI(fdvp);
+ struct udf_node *tdir_node = VTOI(tdvp);
+ struct udf_node *f_node = VTOI(fvp);
+ struct udf_node *t_node = (tvp? VTOI(tvp): NULL);
+ mode_t fdmode, tdmode;
+ uid_t fduid, tduid, fuid, tuid;
+ gid_t gdummy;
+
+ (void)mp;
+ KASSERT(mp != NULL);
+ KASSERT(fdvp != NULL);
+ KASSERT(fvp != NULL);
+ KASSERT(tdvp != NULL);
+ KASSERT(fdvp != fvp);
+ KASSERT(fdvp != tvp);
+ KASSERT(tdvp != fvp);
+ KASSERT(tdvp != tvp);
+ KASSERT(fvp != tvp);
+ KASSERT(fdvp->v_type == VDIR);
+ KASSERT(tdvp->v_type == VDIR);
+ KASSERT(fdvp->v_mount == mp);
+ KASSERT(fvp->v_mount == mp);
+ KASSERT(tdvp->v_mount == mp);
+ KASSERT((tvp == NULL) || (tvp->v_mount == mp));
+ KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
+ KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
+ KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
+ KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
+
+ DPRINTF(CALL, ("udf_gro_rename_check_permitted called\n"));
+ fdmode = udf_getaccessmode(fdir_node);
+ tdmode = udf_getaccessmode(tdir_node);
+
+ udf_getownership(fdir_node, &fduid, &gdummy);
+ udf_getownership(tdir_node, &tduid, &gdummy);
+ udf_getownership(f_node, &fuid, &gdummy);
+
+ tuid = 0;
+ if (t_node)
+ udf_getownership(t_node, &tuid, &gdummy);
+
+ return genfs_ufslike_rename_check_permitted(cred,
+ fdvp, fdmode, fduid,
+ fvp, fuid,
+ tdvp, tdmode, tduid,
+ tvp, tuid);
+}
+
+
+/*
+ * udf_gro_remove_check_possible: check whether a remove is possible
+ * independent of credentials.
+ *
+ * XXX could check for special attributes?
+ */
+static int
+udf_gro_remove_check_possible(struct mount *mp,
+ struct vnode *dvp, struct vnode *vp)
+{
+ (void)mp;
+ KASSERT(mp != NULL);
+ KASSERT(dvp != NULL);
+ KASSERT(vp != NULL);
+ KASSERT(dvp != vp);
+ KASSERT(dvp->v_type == VDIR);
+ KASSERT(vp->v_type != VDIR);
+ KASSERT(dvp->v_mount == mp);
+ KASSERT(vp->v_mount == mp);
+ KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
+ KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+
+ DPRINTF(CALL, ("udf_gro_remove_check_possible called\n"));
+ if (mp->mnt_flag & MNT_RDONLY)
+ return EROFS;
+
+ /* flags not implemented since they are not defined (yet) in UDF */
+ return 0;
+}
Home |
Main Index |
Thread Index |
Old Index