Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/fs/msdosfs Convert msdosfs_rename() to use genfs_sane_re...
details: https://anonhg.NetBSD.org/src/rev/c455e73a7fc7
branches: trunk
changeset: 989998:c455e73a7fc7
user: hannken <hannken%NetBSD.org@localhost>
date: Sat Oct 23 07:45:03 2021 +0000
description:
Convert msdosfs_rename() to use genfs_sane_rename().
Based on work by Taylor R Campbell.
diffstat:
sys/fs/msdosfs/denode.h | 3 +-
sys/fs/msdosfs/msdosfs_rename.c | 1163 +++++++++++++++++++++++++-------------
2 files changed, 747 insertions(+), 419 deletions(-)
diffs (truncated from 1278 to 300 lines):
diff -r 1f6ae14e61ee -r c455e73a7fc7 sys/fs/msdosfs/denode.h
--- a/sys/fs/msdosfs/denode.h Sat Oct 23 07:41:37 2021 +0000
+++ b/sys/fs/msdosfs/denode.h Sat Oct 23 07:45:03 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: denode.h,v 1.27 2021/10/23 07:38:33 hannken Exp $ */
+/* $NetBSD: denode.h,v 1.28 2021/10/23 07:45:03 hannken Exp $ */
/*-
* Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@@ -318,7 +318,6 @@
#endif
int detrunc(struct denode *, u_long, int, struct kauth_cred *);
int deupdat(struct denode *, int);
-int doscheckpath(struct denode *, struct denode *);
int dosdirempty(struct denode *);
int readde(struct denode *, struct buf **, struct direntry **);
int readep(struct msdosfsmount *, u_long, u_long,
diff -r 1f6ae14e61ee -r c455e73a7fc7 sys/fs/msdosfs/msdosfs_rename.c
--- a/sys/fs/msdosfs/msdosfs_rename.c Sat Oct 23 07:41:37 2021 +0000
+++ b/sys/fs/msdosfs/msdosfs_rename.c Sat Oct 23 07:45:03 2021 +0000
@@ -1,10 +1,11 @@
-/* $NetBSD: msdosfs_rename.c,v 1.1 2021/10/23 07:41:37 hannken Exp $ */
+/* $NetBSD: msdosfs_rename.c,v 1.2 2021/10/23 07:45:03 hannken Exp $ */
/*-
- * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
- * Copyright (C) 1994, 1995, 1997 TooLs GmbH.
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
- * Original code by Paul Popelka (paulp%uts.amdahl.com@localhost) (see below).
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Taylor R Campbell.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -14,60 +15,36 @@
* 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by TooLs GmbH.
- * 4. The name of TooLs GmbH may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
- */
-/*
- * Written by Paul Popelka (paulp%uts.amdahl.com@localhost)
- *
- * You can do anything you want with this software, just don't say you wrote
- * it, and don't remove this notice.
- *
- * This software is provided "as is".
- *
- * The author supplies this software to be publicly redistributed on the
- * understanding that the author is not responsible for the correct
- * functioning of this software in any circumstances and is not liable for
- * any damages caused by this software.
- *
- * October 1992
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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.
*/
+/*
+ * MS-DOS FS Rename
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: msdosfs_rename.c,v 1.2 2021/10/23 07:45:03 hannken Exp $");
+
#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/namei.h>
-#include <sys/resourcevar.h> /* defines plimit structure in proc struct */
-#include <sys/kernel.h>
-#include <sys/file.h> /* define FWRITE ... */
-#include <sys/stat.h>
#include <sys/buf.h>
-#include <sys/proc.h>
-#include <sys/mount.h>
+#include <sys/errno.h>
+#include <sys/kauth.h>
+#include <sys/namei.h>
#include <sys/vnode.h>
-#include <sys/signalvar.h>
-#include <sys/malloc.h>
-#include <sys/dirent.h>
-#include <sys/lockf.h>
-#include <sys/kauth.h>
+#include <sys/vnode_if.h>
#include <miscfs/genfs/genfs.h>
-#include <miscfs/specfs/specdev.h> /* XXX */ /* defines v_rdev */
-
-#include <uvm/uvm_extern.h>
#include <fs/msdosfs/bpb.h>
#include <fs/msdosfs/direntry.h>
@@ -75,10 +52,50 @@
#include <fs/msdosfs/msdosfsmount.h>
#include <fs/msdosfs/fat.h>
+/*
+ * Forward declarations
+ */
+
+static int msdosfs_sane_rename(struct vnode *, struct componentname *,
+ struct vnode *, struct componentname *,
+ kauth_cred_t, bool);
+static bool msdosfs_rmdired_p(struct vnode *);
+static int msdosfs_read_dotdot(struct vnode *, kauth_cred_t, unsigned long *);
+static int msdosfs_rename_replace_dotdot(struct vnode *,
+ struct vnode *, struct vnode *, kauth_cred_t);
+static int msdosfs_gro_lock_directory(struct mount *, struct vnode *);
+
+static const struct genfs_rename_ops msdosfs_genfs_rename_ops;
+
+/*
+ * msdosfs_rename: The hairiest vop, with the insanest API.
+ *
+ * Arguments:
+ *
+ * . fdvp (from directory vnode),
+ * . fvp (from vnode),
+ * . fcnp (from component name),
+ * . tdvp (to directory vnode),
+ * . tvp (to vnode, or NULL), and
+ * . tcnp (to component name).
+ *
+ * Any pair of vnode parameters may have the same vnode.
+ *
+ * On entry,
+ *
+ * . fdvp, fvp, tdvp, and tvp are referenced,
+ * . fdvp and fvp are unlocked, and
+ * . tdvp and tvp (if nonnull) are locked.
+ *
+ * On exit,
+ *
+ * . fdvp, fvp, tdvp, and tvp (if nonnull) are unreferenced, and
+ * . tdvp and tvp are unlocked.
+ */
int
msdosfs_rename(void *v)
{
- struct vop_rename_args /* {
+ struct vop_rename_args /* {
struct vnode *a_fdvp;
struct vnode *a_fvp;
struct componentname *a_fcnp;
@@ -86,165 +103,345 @@
struct vnode *a_tvp;
struct componentname *a_tcnp;
} */ *ap = v;
- struct vnode *tvp = ap->a_tvp;
- struct vnode *tdvp = ap->a_tdvp;
+ struct vnode *fdvp = ap->a_fdvp;
struct vnode *fvp = ap->a_fvp;
- struct vnode *fdvp = ap->a_fdvp;
- struct componentname *tcnp = ap->a_tcnp;
struct componentname *fcnp = ap->a_fcnp;
- struct denode *ip, *xp, *dp, *zp;
- u_char toname[12], oldname[12];
- u_long from_diroffset, to_diroffset;
- u_char to_count;
- int doingdirectory = 0, newparent = 0;
+ struct vnode *tdvp = ap->a_tdvp;
+ struct vnode *tvp = ap->a_tvp;
+ struct componentname *tcnp = ap->a_tcnp;
+ kauth_cred_t cred;
int error;
- u_long cn;
- daddr_t bn;
- struct msdosfsmount *pmp;
- struct direntry *dotdotp;
- struct buf *bp;
-
- pmp = VFSTOMSDOSFS(fdvp->v_mount);
- /*
- * Check for cross-device rename.
- */
- if ((fvp->v_mount != tdvp->v_mount) ||
- (tvp && (fvp->v_mount != tvp->v_mount))) {
- error = EXDEV;
-abortit:
- VOP_ABORTOP(tdvp, tcnp);
- if (tdvp == tvp)
- vrele(tdvp);
- else
- vput(tdvp);
- if (tvp)
- vput(tvp);
- VOP_ABORTOP(fdvp, fcnp);
- vrele(fdvp);
- vrele(fvp);
- return (error);
- }
+ KASSERT(fdvp != NULL);
+ KASSERT(fvp != NULL);
+ KASSERT(fcnp != NULL);
+ KASSERT(fcnp->cn_nameptr != NULL);
+ KASSERT(tdvp != NULL);
+ KASSERT(tcnp != NULL);
+ KASSERT(fcnp->cn_nameptr != NULL);
+ /* 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));
+ KASSERT(fdvp->v_type == VDIR);
+ KASSERT(tdvp->v_type == VDIR);
- /*
- * If source and dest are the same, do nothing.
- */
- if (tvp == fvp) {
- error = 0;
- goto abortit;
- }
-
- /*
- * XXX: This can deadlock since we hold tdvp/tvp locked.
- * But I'm not going to fix it now.
- */
- if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0)
- goto abortit;
- dp = VTODE(fdvp);
- ip = VTODE(fvp);
+ cred = fcnp->cn_cred;
+ KASSERT(tcnp->cn_cred == cred);
/*
- * Be sure we are not renaming ".", "..", or an alias of ".". This
- * leads to a crippled directory tree. It's pretty tough to do a
- * "ls" or "pwd" with the "." directory entry missing, and "cd .."
- * doesn't work if the ".." entry is missing.
+ * Sanitize our world from the VFS insanity. Unlock the target
+ * directory and node, which are locked. Release the children,
+ * which are referenced. Check for rename("x", "y/."), which
+ * it is our responsibility to reject, not the caller's. (But
+ * the caller does reject rename("x/.", "y"). Go figure.)
+ */
+
+ VOP_UNLOCK(tdvp);
+ if ((tvp != NULL) && (tvp != tdvp))
+ VOP_UNLOCK(tvp);
+
+ vrele(fvp);
+ if (tvp != NULL)
+ vrele(tvp);
+
+ if (tvp == tdvp) {
+ error = EINVAL;
+ goto out;
+ }
+
+ error = msdosfs_sane_rename(fdvp, fcnp, tdvp, tcnp, cred, false);
+
+out: /*
+ * All done, whether with success or failure. Release the
+ * directory nodes now, as the caller expects from the VFS
+ * protocol.
*/
- if (ip->de_Attributes & ATTR_DIRECTORY) {
- /*
- * Avoid ".", "..", and aliases of "." for obvious reasons.
- */
- if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
- dp == ip ||
- (fcnp->cn_flags & ISDOTDOT) ||
- (tcnp->cn_flags & ISDOTDOT) ||
- (ip->de_flag & DE_RENAME)) {
- VOP_UNLOCK(fvp);
- error = EINVAL;
- goto abortit;
- }
- ip->de_flag |= DE_RENAME;
- doingdirectory++;
- }
Home |
Main Index |
Thread Index |
Old Index