xref: /minix3/sys/fs/udf/udf_rename.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /* $NetBSD: udf_rename.c,v 1.12 2014/11/10 19:44:08 riz Exp $ */
29f988b79SJean-Baptiste Boric 
39f988b79SJean-Baptiste Boric /*
49f988b79SJean-Baptiste Boric  * Copyright (c) 2013 Reinoud Zandijk
59f988b79SJean-Baptiste Boric  * All rights reserved.
69f988b79SJean-Baptiste Boric  *
79f988b79SJean-Baptiste Boric  * Redistribution and use in source and binary forms, with or without
89f988b79SJean-Baptiste Boric  * modification, are permitted provided that the following conditions
99f988b79SJean-Baptiste Boric  * are met:
109f988b79SJean-Baptiste Boric  * 1. Redistributions of source code must retain the above copyright
119f988b79SJean-Baptiste Boric  *    notice, this list of conditions and the following disclaimer.
129f988b79SJean-Baptiste Boric  * 2. Redistributions in binary form must reproduce the above copyright
139f988b79SJean-Baptiste Boric  *    notice, this list of conditions and the following disclaimer in the
149f988b79SJean-Baptiste Boric  *    documentation and/or other materials provided with the distribution.
159f988b79SJean-Baptiste Boric  *
169f988b79SJean-Baptiste Boric  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
179f988b79SJean-Baptiste Boric  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
189f988b79SJean-Baptiste Boric  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
199f988b79SJean-Baptiste Boric  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
209f988b79SJean-Baptiste Boric  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
219f988b79SJean-Baptiste Boric  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
229f988b79SJean-Baptiste Boric  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
239f988b79SJean-Baptiste Boric  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
249f988b79SJean-Baptiste Boric  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
259f988b79SJean-Baptiste Boric  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
269f988b79SJean-Baptiste Boric  *
279f988b79SJean-Baptiste Boric  * Comments and trivial code from the reference implementation in tmpfs.
289f988b79SJean-Baptiste Boric  */
299f988b79SJean-Baptiste Boric 
309f988b79SJean-Baptiste Boric #include <sys/cdefs.h>
31*0a6a1f1dSLionel Sambuc __KERNEL_RCSID(0, "$NetBSD: udf_rename.c,v 1.12 2014/11/10 19:44:08 riz Exp $");
329f988b79SJean-Baptiste Boric 
339f988b79SJean-Baptiste Boric #include <sys/param.h>
349f988b79SJean-Baptiste Boric #include <sys/errno.h>
359f988b79SJean-Baptiste Boric #include <sys/kauth.h>
369f988b79SJean-Baptiste Boric #include <sys/mount.h>
379f988b79SJean-Baptiste Boric #include <sys/namei.h>
389f988b79SJean-Baptiste Boric #include <sys/stat.h>
399f988b79SJean-Baptiste Boric #include <sys/malloc.h>
409f988b79SJean-Baptiste Boric #include <sys/dirent.h>
419f988b79SJean-Baptiste Boric #include <sys/vnode.h>
429f988b79SJean-Baptiste Boric #include <sys/vnode_if.h>
439f988b79SJean-Baptiste Boric 
449f988b79SJean-Baptiste Boric #include <miscfs/genfs/genfs.h>
459f988b79SJean-Baptiste Boric 
469f988b79SJean-Baptiste Boric #include <fs/udf/ecma167-udf.h>
479f988b79SJean-Baptiste Boric #include <fs/udf/udf_mount.h>
489f988b79SJean-Baptiste Boric #include <sys/dirhash.h>
499f988b79SJean-Baptiste Boric 
509f988b79SJean-Baptiste Boric #include "udf.h"
519f988b79SJean-Baptiste Boric #include "udf_subr.h"
529f988b79SJean-Baptiste Boric #include "udf_bswap.h"
539f988b79SJean-Baptiste Boric 
549f988b79SJean-Baptiste Boric 
559f988b79SJean-Baptiste Boric /* forwards */
569f988b79SJean-Baptiste Boric static int udf_sane_rename( struct vnode *, struct componentname *,
579f988b79SJean-Baptiste Boric     struct vnode *, struct componentname *,
589f988b79SJean-Baptiste Boric     kauth_cred_t, bool);
599f988b79SJean-Baptiste Boric static bool udf_rmdired_p(struct vnode *);
609f988b79SJean-Baptiste Boric static int udf_gro_lock_directory(struct mount *, struct vnode *);
619f988b79SJean-Baptiste Boric 
629f988b79SJean-Baptiste Boric static const struct genfs_rename_ops udf_genfs_rename_ops;
639f988b79SJean-Baptiste Boric 
649f988b79SJean-Baptiste Boric 
659f988b79SJean-Baptiste Boric #define VTOI(vnode) ((struct udf_node *) (vnode)->v_data)
669f988b79SJean-Baptiste Boric 
679f988b79SJean-Baptiste Boric 
689f988b79SJean-Baptiste Boric /*
699f988b79SJean-Baptiste Boric  * udf_sane_rename: The hairiest vop, with the saner API.
709f988b79SJean-Baptiste Boric  *
719f988b79SJean-Baptiste Boric  * Arguments:
729f988b79SJean-Baptiste Boric  *
739f988b79SJean-Baptiste Boric  * . fdvp (from directory vnode),
749f988b79SJean-Baptiste Boric  * . fcnp (from component name),
759f988b79SJean-Baptiste Boric  * . tdvp (to directory vnode),
769f988b79SJean-Baptiste Boric  * . tcnp (to component name),
779f988b79SJean-Baptiste Boric  * . cred (credentials structure), and
789f988b79SJean-Baptiste Boric  * . posixly_correct (flag for behaviour if target & source link same file).
799f988b79SJean-Baptiste Boric  *
809f988b79SJean-Baptiste Boric  * fdvp and tdvp may be the same, and must be referenced and unlocked.
819f988b79SJean-Baptiste Boric  */
829f988b79SJean-Baptiste Boric static int
udf_sane_rename(struct vnode * fdvp,struct componentname * fcnp,struct vnode * tdvp,struct componentname * tcnp,kauth_cred_t cred,bool posixly_correct)839f988b79SJean-Baptiste Boric udf_sane_rename( struct vnode *fdvp, struct componentname *fcnp,
849f988b79SJean-Baptiste Boric     struct vnode *tdvp, struct componentname *tcnp,
859f988b79SJean-Baptiste Boric     kauth_cred_t cred, bool posixly_correct)
869f988b79SJean-Baptiste Boric {
879f988b79SJean-Baptiste Boric 	DPRINTF(CALL, ("udf_sane_rename '%s' -> '%s'\n",
889f988b79SJean-Baptiste Boric 		fcnp->cn_nameptr, tcnp->cn_nameptr));
899f988b79SJean-Baptiste Boric 	return genfs_sane_rename(&udf_genfs_rename_ops,
909f988b79SJean-Baptiste Boric 	    fdvp, fcnp, NULL, tdvp, tcnp, NULL,
919f988b79SJean-Baptiste Boric 	    cred, posixly_correct);
929f988b79SJean-Baptiste Boric }
939f988b79SJean-Baptiste Boric 
949f988b79SJean-Baptiste Boric 
959f988b79SJean-Baptiste Boric /*
969f988b79SJean-Baptiste Boric  * udf_rename: the hairiest vop, with the insanest API. Pass to
979f988b79SJean-Baptiste Boric  * genfs_insane_rename immediately.
989f988b79SJean-Baptiste Boric  */
999f988b79SJean-Baptiste Boric int
udf_rename(void * v)1009f988b79SJean-Baptiste Boric udf_rename(void *v)
1019f988b79SJean-Baptiste Boric {
1029f988b79SJean-Baptiste Boric 	struct vop_rename_args /* {
1039f988b79SJean-Baptiste Boric 		struct vnode *a_fdvp;
1049f988b79SJean-Baptiste Boric 		struct vnode *a_fvp;
1059f988b79SJean-Baptiste Boric 		struct componentname *a_fcnp;
1069f988b79SJean-Baptiste Boric 		struct vnode *a_tdvp;
1079f988b79SJean-Baptiste Boric 		struct vnode *a_tvp;
1089f988b79SJean-Baptiste Boric 		struct componentname *a_tcnp;
1099f988b79SJean-Baptiste Boric 	} */ *ap = v;
1109f988b79SJean-Baptiste Boric 	DPRINTF(CALL, ("udf_rename called\n"));
1119f988b79SJean-Baptiste Boric 	return genfs_insane_rename(ap, &udf_sane_rename);
1129f988b79SJean-Baptiste Boric }
1139f988b79SJean-Baptiste Boric 
1149f988b79SJean-Baptiste Boric 
1159f988b79SJean-Baptiste Boric /*
1169f988b79SJean-Baptiste Boric  * udf_gro_directory_empty_p: return true if the directory vp is empty. dvp is
1179f988b79SJean-Baptiste Boric  * its parent.
1189f988b79SJean-Baptiste Boric  *
1199f988b79SJean-Baptiste Boric  * vp and dvp must be locked and referenced.
1209f988b79SJean-Baptiste Boric  */
1219f988b79SJean-Baptiste Boric static bool
udf_gro_directory_empty_p(struct mount * mp,kauth_cred_t cred,struct vnode * vp,struct vnode * dvp)1229f988b79SJean-Baptiste Boric udf_gro_directory_empty_p(struct mount *mp, kauth_cred_t cred,
1239f988b79SJean-Baptiste Boric     struct vnode *vp, struct vnode *dvp)
1249f988b79SJean-Baptiste Boric {
1259f988b79SJean-Baptiste Boric 	struct udf_node *udf_node = VTOI(vp);
1269f988b79SJean-Baptiste Boric 	int error, isempty;
1279f988b79SJean-Baptiste Boric 
1289f988b79SJean-Baptiste Boric 	KASSERT(mp != NULL);
1299f988b79SJean-Baptiste Boric 	KASSERT(vp != NULL);
1309f988b79SJean-Baptiste Boric 	KASSERT(dvp != NULL);
1319f988b79SJean-Baptiste Boric 	KASSERT(vp != dvp);
1329f988b79SJean-Baptiste Boric 	KASSERT(vp->v_mount == mp);
1339f988b79SJean-Baptiste Boric 	KASSERT(dvp->v_mount == mp);
1349f988b79SJean-Baptiste Boric 	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
1359f988b79SJean-Baptiste Boric 	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
1369f988b79SJean-Baptiste Boric 
1379f988b79SJean-Baptiste Boric 	DPRINTF(CALL, ("udf_gro_directory_empty_p called\n"));
1389f988b79SJean-Baptiste Boric 	/* make sure our `leaf' node's hash is populated */
1399f988b79SJean-Baptiste Boric 	dirhash_get(&udf_node->dir_hash);
1409f988b79SJean-Baptiste Boric 	error = udf_dirhash_fill(udf_node);
1419f988b79SJean-Baptiste Boric 	if (error) {
1429f988b79SJean-Baptiste Boric 		dirhash_put(udf_node->dir_hash);
1439f988b79SJean-Baptiste Boric 		/* VERY unlikely, answer its not empty */
1449f988b79SJean-Baptiste Boric 		return 0;
1459f988b79SJean-Baptiste Boric 	}
1469f988b79SJean-Baptiste Boric 
1479f988b79SJean-Baptiste Boric 	/* check to see if the directory is empty */
1489f988b79SJean-Baptiste Boric 	isempty = dirhash_dir_isempty(udf_node->dir_hash);
1499f988b79SJean-Baptiste Boric 	dirhash_put(udf_node->dir_hash);
1509f988b79SJean-Baptiste Boric 
1519f988b79SJean-Baptiste Boric 	return isempty;
1529f988b79SJean-Baptiste Boric }
1539f988b79SJean-Baptiste Boric 
1549f988b79SJean-Baptiste Boric 
1559f988b79SJean-Baptiste Boric /*
1569f988b79SJean-Baptiste Boric  * udf_gro_rename_check_possible: check whether a rename is possible
1579f988b79SJean-Baptiste Boric  * independent of credentials.
1589f988b79SJean-Baptiste Boric  */
1599f988b79SJean-Baptiste Boric static int
udf_gro_rename_check_possible(struct mount * mp,struct vnode * fdvp,struct vnode * fvp,struct vnode * tdvp,struct vnode * tvp)1609f988b79SJean-Baptiste Boric udf_gro_rename_check_possible(struct mount *mp,
1619f988b79SJean-Baptiste Boric     struct vnode *fdvp, struct vnode *fvp,
1629f988b79SJean-Baptiste Boric     struct vnode *tdvp, struct vnode *tvp)
1639f988b79SJean-Baptiste Boric {
1649f988b79SJean-Baptiste Boric 	(void)mp;
1659f988b79SJean-Baptiste Boric 	KASSERT(mp != NULL);
1669f988b79SJean-Baptiste Boric 	KASSERT(fdvp != NULL);
1679f988b79SJean-Baptiste Boric 	KASSERT(fvp != NULL);
1689f988b79SJean-Baptiste Boric 	KASSERT(tdvp != NULL);
1699f988b79SJean-Baptiste Boric 	KASSERT(fdvp != fvp);
1709f988b79SJean-Baptiste Boric 	KASSERT(fdvp != tvp);
1719f988b79SJean-Baptiste Boric 	KASSERT(tdvp != fvp);
1729f988b79SJean-Baptiste Boric 	KASSERT(tdvp != tvp);
1739f988b79SJean-Baptiste Boric 	KASSERT(fvp != tvp);
1749f988b79SJean-Baptiste Boric 	KASSERT(fdvp->v_type == VDIR);
1759f988b79SJean-Baptiste Boric 	KASSERT(tdvp->v_type == VDIR);
1769f988b79SJean-Baptiste Boric 	KASSERT(fdvp->v_mount == mp);
1779f988b79SJean-Baptiste Boric 	KASSERT(fvp->v_mount == mp);
1789f988b79SJean-Baptiste Boric 	KASSERT(tdvp->v_mount == mp);
1799f988b79SJean-Baptiste Boric 	KASSERT((tvp == NULL) || (tvp->v_mount == mp));
1809f988b79SJean-Baptiste Boric 	KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
1819f988b79SJean-Baptiste Boric 	KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
1829f988b79SJean-Baptiste Boric 	KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
1839f988b79SJean-Baptiste Boric 	KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
1849f988b79SJean-Baptiste Boric 
1859f988b79SJean-Baptiste Boric 	DPRINTF(CALL, ("udf_gro_rename_check_possible called\n"));
1869f988b79SJean-Baptiste Boric 
1879f988b79SJean-Baptiste Boric 	/* flags not implemented since they are not defined (yet) in UDF */
1889f988b79SJean-Baptiste Boric 	return 0;
1899f988b79SJean-Baptiste Boric }
1909f988b79SJean-Baptiste Boric 
1919f988b79SJean-Baptiste Boric 
1929f988b79SJean-Baptiste Boric /*
1939f988b79SJean-Baptiste Boric  * udf_gro_rename_check_permitted: check whether a rename is permitted given
1949f988b79SJean-Baptiste Boric  * our credentials.
1959f988b79SJean-Baptiste Boric  */
1969f988b79SJean-Baptiste Boric 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)1979f988b79SJean-Baptiste Boric udf_gro_rename_check_permitted(struct mount *mp, kauth_cred_t cred,
1989f988b79SJean-Baptiste Boric     struct vnode *fdvp, struct vnode *fvp,
1999f988b79SJean-Baptiste Boric     struct vnode *tdvp, struct vnode *tvp)
2009f988b79SJean-Baptiste Boric {
2019f988b79SJean-Baptiste Boric 	struct udf_node *fdir_node = VTOI(fdvp);
2029f988b79SJean-Baptiste Boric 	struct udf_node *tdir_node = VTOI(tdvp);
2039f988b79SJean-Baptiste Boric 	struct udf_node *f_node = VTOI(fvp);
2049f988b79SJean-Baptiste Boric 	struct udf_node *t_node = (tvp? VTOI(tvp): NULL);
2059f988b79SJean-Baptiste Boric 	mode_t fdmode, tdmode;
2069f988b79SJean-Baptiste Boric 	uid_t fduid, tduid, fuid, tuid;
2079f988b79SJean-Baptiste Boric 	gid_t gdummy;
2089f988b79SJean-Baptiste Boric 
2099f988b79SJean-Baptiste Boric 	(void)mp;
2109f988b79SJean-Baptiste Boric 	KASSERT(mp != NULL);
2119f988b79SJean-Baptiste Boric 	KASSERT(fdvp != NULL);
2129f988b79SJean-Baptiste Boric 	KASSERT(fvp != NULL);
2139f988b79SJean-Baptiste Boric 	KASSERT(tdvp != NULL);
2149f988b79SJean-Baptiste Boric 	KASSERT(fdvp != fvp);
2159f988b79SJean-Baptiste Boric 	KASSERT(fdvp != tvp);
2169f988b79SJean-Baptiste Boric 	KASSERT(tdvp != fvp);
2179f988b79SJean-Baptiste Boric 	KASSERT(tdvp != tvp);
2189f988b79SJean-Baptiste Boric 	KASSERT(fvp != tvp);
2199f988b79SJean-Baptiste Boric 	KASSERT(fdvp->v_type == VDIR);
2209f988b79SJean-Baptiste Boric 	KASSERT(tdvp->v_type == VDIR);
2219f988b79SJean-Baptiste Boric 	KASSERT(fdvp->v_mount == mp);
2229f988b79SJean-Baptiste Boric 	KASSERT(fvp->v_mount == mp);
2239f988b79SJean-Baptiste Boric 	KASSERT(tdvp->v_mount == mp);
2249f988b79SJean-Baptiste Boric 	KASSERT((tvp == NULL) || (tvp->v_mount == mp));
2259f988b79SJean-Baptiste Boric 	KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
2269f988b79SJean-Baptiste Boric 	KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
2279f988b79SJean-Baptiste Boric 	KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
2289f988b79SJean-Baptiste Boric 	KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
2299f988b79SJean-Baptiste Boric 
2309f988b79SJean-Baptiste Boric 	DPRINTF(CALL, ("udf_gro_rename_check_permitted called\n"));
2319f988b79SJean-Baptiste Boric 	fdmode = udf_getaccessmode(fdir_node);
2329f988b79SJean-Baptiste Boric 	tdmode = udf_getaccessmode(tdir_node);
2339f988b79SJean-Baptiste Boric 
2349f988b79SJean-Baptiste Boric 	udf_getownership(fdir_node, &fduid, &gdummy);
2359f988b79SJean-Baptiste Boric 	udf_getownership(tdir_node, &tduid, &gdummy);
2369f988b79SJean-Baptiste Boric 	udf_getownership(f_node,    &fuid, &gdummy);
2379f988b79SJean-Baptiste Boric 
2389f988b79SJean-Baptiste Boric 	tuid = 0;
2399f988b79SJean-Baptiste Boric 	if (t_node)
2409f988b79SJean-Baptiste Boric 		udf_getownership(t_node, &tuid, &gdummy);
2419f988b79SJean-Baptiste Boric 
2429f988b79SJean-Baptiste Boric 	return genfs_ufslike_rename_check_permitted(cred,
2439f988b79SJean-Baptiste Boric 	    fdvp, fdmode, fduid,
2449f988b79SJean-Baptiste Boric 	    fvp,  fuid,
2459f988b79SJean-Baptiste Boric 	    tdvp, tdmode, tduid,
2469f988b79SJean-Baptiste Boric 	    tvp,  tuid);
2479f988b79SJean-Baptiste Boric }
2489f988b79SJean-Baptiste Boric 
2499f988b79SJean-Baptiste Boric 
2509f988b79SJean-Baptiste Boric /*
2519f988b79SJean-Baptiste Boric  * udf_gro_remove_check_possible: check whether a remove is possible
2529f988b79SJean-Baptiste Boric  * independent of credentials.
2539f988b79SJean-Baptiste Boric  *
2549f988b79SJean-Baptiste Boric  * XXX could check for special attributes?
2559f988b79SJean-Baptiste Boric  */
2569f988b79SJean-Baptiste Boric static int
udf_gro_remove_check_possible(struct mount * mp,struct vnode * dvp,struct vnode * vp)2579f988b79SJean-Baptiste Boric udf_gro_remove_check_possible(struct mount *mp,
2589f988b79SJean-Baptiste Boric     struct vnode *dvp, struct vnode *vp)
2599f988b79SJean-Baptiste Boric {
2609f988b79SJean-Baptiste Boric 	(void)mp;
2619f988b79SJean-Baptiste Boric 	KASSERT(mp != NULL);
2629f988b79SJean-Baptiste Boric 	KASSERT(dvp != NULL);
2639f988b79SJean-Baptiste Boric 	KASSERT(vp != NULL);
2649f988b79SJean-Baptiste Boric 	KASSERT(dvp != vp);
2659f988b79SJean-Baptiste Boric 	KASSERT(dvp->v_type == VDIR);
2669f988b79SJean-Baptiste Boric 	KASSERT(vp->v_type != VDIR);
2679f988b79SJean-Baptiste Boric 	KASSERT(dvp->v_mount == mp);
2689f988b79SJean-Baptiste Boric 	KASSERT(vp->v_mount == mp);
2699f988b79SJean-Baptiste Boric 	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
2709f988b79SJean-Baptiste Boric 	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
2719f988b79SJean-Baptiste Boric 
2729f988b79SJean-Baptiste Boric 	DPRINTF(CALL, ("udf_gro_remove_check_possible called\n"));
2739f988b79SJean-Baptiste Boric 
2749f988b79SJean-Baptiste Boric 	/* flags not implemented since they are not defined (yet) in UDF */
2759f988b79SJean-Baptiste Boric 	return 0;
2769f988b79SJean-Baptiste Boric }
2779f988b79SJean-Baptiste Boric 
2789f988b79SJean-Baptiste Boric 
2799f988b79SJean-Baptiste Boric /*
2809f988b79SJean-Baptiste Boric  * udf_gro_remove_check_permitted: check whether a remove is permitted given
2819f988b79SJean-Baptiste Boric  * our credentials.
2829f988b79SJean-Baptiste Boric  */
2839f988b79SJean-Baptiste Boric static int
udf_gro_remove_check_permitted(struct mount * mp,kauth_cred_t cred,struct vnode * dvp,struct vnode * vp)2849f988b79SJean-Baptiste Boric udf_gro_remove_check_permitted(struct mount *mp, kauth_cred_t cred,
2859f988b79SJean-Baptiste Boric     struct vnode *dvp, struct vnode *vp)
2869f988b79SJean-Baptiste Boric {
2879f988b79SJean-Baptiste Boric 	struct udf_node *dir_node = VTOI(dvp);
2889f988b79SJean-Baptiste Boric 	struct udf_node *udf_node = VTOI(vp);
2899f988b79SJean-Baptiste Boric 	mode_t dmode;
2909f988b79SJean-Baptiste Boric 	uid_t duid, uid;
2919f988b79SJean-Baptiste Boric 	gid_t gdummy;
2929f988b79SJean-Baptiste Boric 
2939f988b79SJean-Baptiste Boric 	(void)mp;
2949f988b79SJean-Baptiste Boric 	KASSERT(mp != NULL);
2959f988b79SJean-Baptiste Boric 	KASSERT(dvp != NULL);
2969f988b79SJean-Baptiste Boric 	KASSERT(vp != NULL);
2979f988b79SJean-Baptiste Boric 	KASSERT(dvp != vp);
2989f988b79SJean-Baptiste Boric 	KASSERT(dvp->v_type == VDIR);
2999f988b79SJean-Baptiste Boric 	KASSERT(vp->v_type != VDIR);
3009f988b79SJean-Baptiste Boric 	KASSERT(dvp->v_mount == mp);
3019f988b79SJean-Baptiste Boric 	KASSERT(vp->v_mount == mp);
3029f988b79SJean-Baptiste Boric 	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
3039f988b79SJean-Baptiste Boric 	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
3049f988b79SJean-Baptiste Boric 
3059f988b79SJean-Baptiste Boric 	DPRINTF(CALL, ("udf_gro_remove_check_permitted called\n"));
3069f988b79SJean-Baptiste Boric 	dmode = udf_getaccessmode(dir_node);
3079f988b79SJean-Baptiste Boric 
3089f988b79SJean-Baptiste Boric 	udf_getownership(dir_node, &duid, &gdummy);
3099f988b79SJean-Baptiste Boric 	udf_getownership(udf_node, &uid,  &gdummy);
3109f988b79SJean-Baptiste Boric 
3119f988b79SJean-Baptiste Boric 	return genfs_ufslike_remove_check_permitted(cred,
3129f988b79SJean-Baptiste Boric 	    dvp, dmode, duid,
3139f988b79SJean-Baptiste Boric 	    vp, uid);
3149f988b79SJean-Baptiste Boric }
3159f988b79SJean-Baptiste Boric 
3169f988b79SJean-Baptiste Boric 
3179f988b79SJean-Baptiste Boric /*
3189f988b79SJean-Baptiste Boric  * udf_gro_rename: actually perform the rename operation.
3199f988b79SJean-Baptiste Boric  */
3209f988b79SJean-Baptiste Boric static int
udf_gro_rename(struct mount * mp,kauth_cred_t cred,struct vnode * fdvp,struct componentname * fcnp,void * fde,struct vnode * fvp,struct vnode * tdvp,struct componentname * tcnp,void * tde,struct vnode * tvp)3219f988b79SJean-Baptiste Boric udf_gro_rename(struct mount *mp, kauth_cred_t cred,
3229f988b79SJean-Baptiste Boric     struct vnode *fdvp, struct componentname *fcnp,
3239f988b79SJean-Baptiste Boric     void *fde, struct vnode *fvp,
3249f988b79SJean-Baptiste Boric     struct vnode *tdvp, struct componentname *tcnp,
3259f988b79SJean-Baptiste Boric     void *tde, struct vnode *tvp)
3269f988b79SJean-Baptiste Boric {
3279f988b79SJean-Baptiste Boric 	struct udf_node *fnode, *fdnode, *tnode, *tdnode;
3289f988b79SJean-Baptiste Boric 	struct vattr fvap;
3299f988b79SJean-Baptiste Boric 	int error;
3309f988b79SJean-Baptiste Boric 
3319f988b79SJean-Baptiste Boric 	(void)cred;
3329f988b79SJean-Baptiste Boric 	KASSERT(mp != NULL);
3339f988b79SJean-Baptiste Boric 	KASSERT(fdvp != NULL);
3349f988b79SJean-Baptiste Boric 	KASSERT(fcnp != NULL);
3359f988b79SJean-Baptiste Boric 	KASSERT(fvp != NULL);
3369f988b79SJean-Baptiste Boric 	KASSERT(tdvp != NULL);
3379f988b79SJean-Baptiste Boric 	KASSERT(tcnp != NULL);
3389f988b79SJean-Baptiste Boric 	KASSERT(fdvp != fvp);
3399f988b79SJean-Baptiste Boric 	KASSERT(fdvp != tvp);
3409f988b79SJean-Baptiste Boric 	KASSERT(tdvp != fvp);
3419f988b79SJean-Baptiste Boric 	KASSERT(tdvp != tvp);
3429f988b79SJean-Baptiste Boric 	KASSERT(fvp != tvp);
3439f988b79SJean-Baptiste Boric 	KASSERT(fdvp->v_mount == mp);
3449f988b79SJean-Baptiste Boric 	KASSERT(fvp->v_mount == mp);
3459f988b79SJean-Baptiste Boric 	KASSERT(tdvp->v_mount == mp);
3469f988b79SJean-Baptiste Boric 	KASSERT((tvp == NULL) || (tvp->v_mount == mp));
3479f988b79SJean-Baptiste Boric 	KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
3489f988b79SJean-Baptiste Boric 	KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
3499f988b79SJean-Baptiste Boric 	KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
3509f988b79SJean-Baptiste Boric 	KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
3519f988b79SJean-Baptiste Boric 
3529f988b79SJean-Baptiste Boric 	DPRINTF(CALL, ("udf_gro_rename called\n"));
3539f988b79SJean-Baptiste Boric 	DPRINTF(NODE, ("udf_gro_rename called : %s -> %s\n",
3549f988b79SJean-Baptiste Boric 		fcnp->cn_nameptr, tcnp->cn_nameptr));
3559f988b79SJean-Baptiste Boric 
3569f988b79SJean-Baptiste Boric 	fnode  = VTOI(fvp);
3579f988b79SJean-Baptiste Boric 	fdnode = VTOI(fdvp);
3589f988b79SJean-Baptiste Boric 	tnode  = (tvp == NULL) ? NULL : VTOI(tvp);
3599f988b79SJean-Baptiste Boric 	tdnode = VTOI(tdvp);
3609f988b79SJean-Baptiste Boric 
3619f988b79SJean-Baptiste Boric 	/* get attribute information */
3629f988b79SJean-Baptiste Boric 	error = VOP_GETATTR(fvp, &fvap, NULL);
3639f988b79SJean-Baptiste Boric 	if (error)
3649f988b79SJean-Baptiste Boric 		return error;
3659f988b79SJean-Baptiste Boric 
3669f988b79SJean-Baptiste Boric 	/* remove existing entry if present */
3679f988b79SJean-Baptiste Boric 	if (tvp)
3689f988b79SJean-Baptiste Boric 		udf_dir_detach(tdnode->ump, tdnode, tnode, tcnp);
3699f988b79SJean-Baptiste Boric 
3709f988b79SJean-Baptiste Boric 	/* create new directory entry for the node */
3719f988b79SJean-Baptiste Boric 	error = udf_dir_attach(tdnode->ump, tdnode, fnode, &fvap, tcnp);
3729f988b79SJean-Baptiste Boric 	if (error)
3739f988b79SJean-Baptiste Boric 		return error;
3749f988b79SJean-Baptiste Boric 
3759f988b79SJean-Baptiste Boric 	/* unlink old directory entry for the node, if failing, unattach new */
3769f988b79SJean-Baptiste Boric 	error = udf_dir_detach(tdnode->ump, fdnode, fnode, fcnp);
3779f988b79SJean-Baptiste Boric 	if (error)
3789f988b79SJean-Baptiste Boric 		goto rollback_attach;
3799f988b79SJean-Baptiste Boric 
3809f988b79SJean-Baptiste Boric 	if ((fdnode != tdnode) && (fvp->v_type == VDIR)) {
3819f988b79SJean-Baptiste Boric 		/* update fnode's '..' entry */
3829f988b79SJean-Baptiste Boric 		error = udf_dir_update_rootentry(fnode->ump, fnode, tdnode);
3839f988b79SJean-Baptiste Boric 		if (error)
3849f988b79SJean-Baptiste Boric 			goto rollback;
3859f988b79SJean-Baptiste Boric 	}
3869f988b79SJean-Baptiste Boric 
3879f988b79SJean-Baptiste Boric 	VN_KNOTE(fvp, NOTE_RENAME);
3889f988b79SJean-Baptiste Boric 	genfs_rename_cache_purge(fdvp, fvp, tdvp, tvp);
3899f988b79SJean-Baptiste Boric 	return 0;
3909f988b79SJean-Baptiste Boric 
3919f988b79SJean-Baptiste Boric rollback:
3929f988b79SJean-Baptiste Boric 	/* 'try' to recover from this situation */
3939f988b79SJean-Baptiste Boric 	udf_dir_attach(tdnode->ump, fdnode, fnode, &fvap, fcnp);
3949f988b79SJean-Baptiste Boric rollback_attach:
3959f988b79SJean-Baptiste Boric 	udf_dir_detach(tdnode->ump, tdnode, fnode, tcnp);
3969f988b79SJean-Baptiste Boric 
3979f988b79SJean-Baptiste Boric 	return error;
3989f988b79SJean-Baptiste Boric }
3999f988b79SJean-Baptiste Boric 
4009f988b79SJean-Baptiste Boric 
4019f988b79SJean-Baptiste Boric /*
4029f988b79SJean-Baptiste Boric  * udf_gro_remove: rename an object over another link to itself, effectively
4039f988b79SJean-Baptiste Boric  * removing just the original link.
4049f988b79SJean-Baptiste Boric  */
4059f988b79SJean-Baptiste Boric static int
udf_gro_remove(struct mount * mp,kauth_cred_t cred,struct vnode * dvp,struct componentname * cnp,void * de,struct vnode * vp)4069f988b79SJean-Baptiste Boric udf_gro_remove(struct mount *mp, kauth_cred_t cred,
4079f988b79SJean-Baptiste Boric     struct vnode *dvp, struct componentname *cnp, void *de, struct vnode *vp)
4089f988b79SJean-Baptiste Boric {
4099f988b79SJean-Baptiste Boric 	struct udf_node *dir_node, *udf_node;
4109f988b79SJean-Baptiste Boric 
4119f988b79SJean-Baptiste Boric 	KASSERT(mp != NULL);
4129f988b79SJean-Baptiste Boric 	KASSERT(dvp != NULL);
4139f988b79SJean-Baptiste Boric 	KASSERT(cnp != NULL);
4149f988b79SJean-Baptiste Boric 	KASSERT(vp != NULL);
4159f988b79SJean-Baptiste Boric 	KASSERT(dvp != vp);
4169f988b79SJean-Baptiste Boric 	KASSERT(dvp->v_mount == mp);
4179f988b79SJean-Baptiste Boric 	KASSERT(vp->v_mount == mp);
4189f988b79SJean-Baptiste Boric 	KASSERT(dvp->v_type == VDIR);
4199f988b79SJean-Baptiste Boric 	KASSERT(vp->v_type != VDIR);
4209f988b79SJean-Baptiste Boric 	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
4219f988b79SJean-Baptiste Boric 	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
4229f988b79SJean-Baptiste Boric 
4239f988b79SJean-Baptiste Boric 	DPRINTF(CALL, ("udf_gro_remove called\n"));
4249f988b79SJean-Baptiste Boric 
4259f988b79SJean-Baptiste Boric 	dir_node = VTOI(dvp);
4269f988b79SJean-Baptiste Boric 	udf_node = VTOI(vp);
4279f988b79SJean-Baptiste Boric 	udf_dir_detach(dir_node->ump, dir_node, udf_node, cnp);
4289f988b79SJean-Baptiste Boric 
4299f988b79SJean-Baptiste Boric 	return 0;
4309f988b79SJean-Baptiste Boric }
4319f988b79SJean-Baptiste Boric 
4329f988b79SJean-Baptiste Boric 
4339f988b79SJean-Baptiste Boric /*
4349f988b79SJean-Baptiste Boric  * udf_gro_lookup: look up and save the lookup results.
4359f988b79SJean-Baptiste Boric  */
4369f988b79SJean-Baptiste Boric static int
udf_gro_lookup(struct mount * mp,struct vnode * dvp,struct componentname * cnp,void * de_ret,struct vnode ** vp_ret)4379f988b79SJean-Baptiste Boric udf_gro_lookup(struct mount *mp, struct vnode *dvp,
4389f988b79SJean-Baptiste Boric     struct componentname *cnp, void *de_ret, struct vnode **vp_ret)
4399f988b79SJean-Baptiste Boric {
4409f988b79SJean-Baptiste Boric 	struct udf_node *dir_node, *res_node;
4419f988b79SJean-Baptiste Boric 	struct long_ad   icb_loc;
4429f988b79SJean-Baptiste Boric 	const char *name;
4439f988b79SJean-Baptiste Boric 	int namelen, error;
4449f988b79SJean-Baptiste Boric 	int found;
4459f988b79SJean-Baptiste Boric 
4469f988b79SJean-Baptiste Boric 	(void)mp;
4479f988b79SJean-Baptiste Boric 	KASSERT(mp != NULL);
4489f988b79SJean-Baptiste Boric 	KASSERT(dvp != NULL);
4499f988b79SJean-Baptiste Boric 	KASSERT(cnp != NULL);
4509f988b79SJean-Baptiste Boric 	KASSERT(vp_ret != NULL);
4519f988b79SJean-Baptiste Boric 	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
4529f988b79SJean-Baptiste Boric 
4539f988b79SJean-Baptiste Boric 	dir_node = VTOI(dvp);
4549f988b79SJean-Baptiste Boric 
4559f988b79SJean-Baptiste Boric 	DPRINTF(CALL, ("udf_gro_lookup called\n"));
4569f988b79SJean-Baptiste Boric 
4579f988b79SJean-Baptiste Boric 	/* lookup filename in the directory; location icb_loc */
4589f988b79SJean-Baptiste Boric 	name    = cnp->cn_nameptr;
4599f988b79SJean-Baptiste Boric 	namelen = cnp->cn_namelen;
4609f988b79SJean-Baptiste Boric 	error = udf_lookup_name_in_dir(dvp, name, namelen,
4619f988b79SJean-Baptiste Boric 			&icb_loc, &found);
4629f988b79SJean-Baptiste Boric 	if (error)
4639f988b79SJean-Baptiste Boric 		return error;
4649f988b79SJean-Baptiste Boric 	if (!found)
4659f988b79SJean-Baptiste Boric 		return ENOENT;
4669f988b79SJean-Baptiste Boric 
4679f988b79SJean-Baptiste Boric 	DPRINTF(LOOKUP, ("udf_gro_lookup found '%s'\n", name));
4689f988b79SJean-Baptiste Boric 	error = udf_get_node(dir_node->ump, &icb_loc, &res_node);
4699f988b79SJean-Baptiste Boric 	if (error)
4709f988b79SJean-Baptiste Boric 		return error;
4719f988b79SJean-Baptiste Boric 	*vp_ret = res_node->vnode;
4729f988b79SJean-Baptiste Boric 	VOP_UNLOCK(res_node->vnode);
4739f988b79SJean-Baptiste Boric 
4749f988b79SJean-Baptiste Boric 	return 0;
4759f988b79SJean-Baptiste Boric }
4769f988b79SJean-Baptiste Boric 
4779f988b79SJean-Baptiste Boric 
4789f988b79SJean-Baptiste Boric /*
4799f988b79SJean-Baptiste Boric  * udf_rmdired_p: check whether the directory vp has been rmdired.
4809f988b79SJean-Baptiste Boric  *
4819f988b79SJean-Baptiste Boric  * vp must be locked and referenced.
4829f988b79SJean-Baptiste Boric  */
4839f988b79SJean-Baptiste Boric static bool
udf_rmdired_p(struct vnode * vp)4849f988b79SJean-Baptiste Boric udf_rmdired_p(struct vnode *vp)
4859f988b79SJean-Baptiste Boric {
4869f988b79SJean-Baptiste Boric 	DPRINTF(CALL, ("udf_rmdired_p called\n"));
4879f988b79SJean-Baptiste Boric 
4889f988b79SJean-Baptiste Boric 	KASSERT(vp != NULL);
4899f988b79SJean-Baptiste Boric 	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
4909f988b79SJean-Baptiste Boric 	KASSERT(vp->v_type == VDIR);
4919f988b79SJean-Baptiste Boric 
4929f988b79SJean-Baptiste Boric 	return (VTOI(vp)->i_flags & IN_DELETED);
4939f988b79SJean-Baptiste Boric }
4949f988b79SJean-Baptiste Boric 
4959f988b79SJean-Baptiste Boric 
4969f988b79SJean-Baptiste Boric /*
4979f988b79SJean-Baptiste Boric  * udf_gro_genealogy: analyze the genealogy of the source and target
4989f988b79SJean-Baptiste Boric  * directories.
4999f988b79SJean-Baptiste Boric  */
5009f988b79SJean-Baptiste Boric static int
udf_gro_genealogy(struct mount * mp,kauth_cred_t cred,struct vnode * fdvp,struct vnode * tdvp,struct vnode ** intermediate_node_ret)5019f988b79SJean-Baptiste Boric udf_gro_genealogy(struct mount *mp, kauth_cred_t cred,
5029f988b79SJean-Baptiste Boric     struct vnode *fdvp, struct vnode *tdvp,
5039f988b79SJean-Baptiste Boric     struct vnode **intermediate_node_ret)
5049f988b79SJean-Baptiste Boric {
5059f988b79SJean-Baptiste Boric 	struct udf_mount *ump;
5069f988b79SJean-Baptiste Boric 	struct udf_node *parent_node;
5079f988b79SJean-Baptiste Boric 	struct vnode *vp, *dvp;
5089f988b79SJean-Baptiste Boric 	struct long_ad parent_loc;
5099f988b79SJean-Baptiste Boric 	const char *name;
5109f988b79SJean-Baptiste Boric 	int namelen;
5119f988b79SJean-Baptiste Boric 	int error, found;
5129f988b79SJean-Baptiste Boric 
5139f988b79SJean-Baptiste Boric 	(void)cred;
5149f988b79SJean-Baptiste Boric 	KASSERT(mp != NULL);
5159f988b79SJean-Baptiste Boric 	KASSERT(fdvp != NULL);
5169f988b79SJean-Baptiste Boric 	KASSERT(tdvp != NULL);
5179f988b79SJean-Baptiste Boric 	KASSERT(fdvp != tdvp);
5189f988b79SJean-Baptiste Boric 	KASSERT(intermediate_node_ret != NULL);
5199f988b79SJean-Baptiste Boric 	KASSERT(fdvp->v_mount == mp);
5209f988b79SJean-Baptiste Boric 	KASSERT(tdvp->v_mount == mp);
5219f988b79SJean-Baptiste Boric 	KASSERT(fdvp->v_type == VDIR);
5229f988b79SJean-Baptiste Boric 	KASSERT(tdvp->v_type == VDIR);
5239f988b79SJean-Baptiste Boric 
5249f988b79SJean-Baptiste Boric 	DPRINTF(CALL, ("udf_gro_genealogy called\n"));
5259f988b79SJean-Baptiste Boric 
5269f988b79SJean-Baptiste Boric 	/*
5279f988b79SJean-Baptiste Boric 	 * We need to provisionally lock tdvp to keep rmdir from deleting it
5289f988b79SJean-Baptiste Boric 	 * -- or any ancestor -- at an inopportune moment.
5299f988b79SJean-Baptiste Boric 	 *
5309f988b79SJean-Baptiste Boric 	 * XXX WHY is this not in genfs's rename? XXX
5319f988b79SJean-Baptiste Boric 	 */
5329f988b79SJean-Baptiste Boric 	error = udf_gro_lock_directory(mp, tdvp);
5339f988b79SJean-Baptiste Boric 	if (error)
5349f988b79SJean-Baptiste Boric 		return error;
5359f988b79SJean-Baptiste Boric 
5369f988b79SJean-Baptiste Boric 	name     = "..";
5379f988b79SJean-Baptiste Boric 	namelen  = 2;
5389f988b79SJean-Baptiste Boric 	error    = 0;
5399f988b79SJean-Baptiste Boric 
5409f988b79SJean-Baptiste Boric 	ump = VTOI(tdvp)->ump;
5419f988b79SJean-Baptiste Boric 
5429f988b79SJean-Baptiste Boric 	/* if nodes are equal, it is no use looking */
5439f988b79SJean-Baptiste Boric 	KASSERT(udf_compare_icb(&VTOI(fdvp)->loc, &VTOI(tdvp)->loc) != 0);
5449f988b79SJean-Baptiste Boric 
5459f988b79SJean-Baptiste Boric 	/* start at destination vnode and walk up the tree */
5469f988b79SJean-Baptiste Boric 	vp = tdvp;
5479f988b79SJean-Baptiste Boric 	vref(vp);
5489f988b79SJean-Baptiste Boric 
5499f988b79SJean-Baptiste Boric 	for (;;) {
5509f988b79SJean-Baptiste Boric 		KASSERT(vp != NULL);
5519f988b79SJean-Baptiste Boric 		KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
5529f988b79SJean-Baptiste Boric 		KASSERT(vp->v_mount == mp);
5539f988b79SJean-Baptiste Boric 		KASSERT(vp->v_type == VDIR);
5549f988b79SJean-Baptiste Boric 		KASSERT(!udf_rmdired_p(vp));
5559f988b79SJean-Baptiste Boric 
5569f988b79SJean-Baptiste Boric 		DPRINTF(NODE, ("udf_gro_genealogy : "
5579f988b79SJean-Baptiste Boric 			"fdvp %p, looking at vp %p\n",
5589f988b79SJean-Baptiste Boric 			fdvp, vp));
5599f988b79SJean-Baptiste Boric 
5609f988b79SJean-Baptiste Boric 		/* sanity check */
5619f988b79SJean-Baptiste Boric 		if (vp->v_type != VDIR) {
5629f988b79SJean-Baptiste Boric 			vput(vp);
5639f988b79SJean-Baptiste Boric 			return ENOTDIR;
5649f988b79SJean-Baptiste Boric 		}
5659f988b79SJean-Baptiste Boric 
5669f988b79SJean-Baptiste Boric 		/* go down one level */
5679f988b79SJean-Baptiste Boric 		error = udf_lookup_name_in_dir(vp, name, namelen,
5689f988b79SJean-Baptiste Boric 			&parent_loc, &found);
5699f988b79SJean-Baptiste Boric 		DPRINTF(NODE, ("\tlookup of parent '..' resulted in error %d, "
5709f988b79SJean-Baptiste Boric 			"found %d\n", error, found));
5719f988b79SJean-Baptiste Boric 		if (!found)
5729f988b79SJean-Baptiste Boric 			error = ENOENT;
5739f988b79SJean-Baptiste Boric 		if (error) {
5749f988b79SJean-Baptiste Boric 			vput(vp);
5759f988b79SJean-Baptiste Boric 			return error;
5769f988b79SJean-Baptiste Boric 		}
5779f988b79SJean-Baptiste Boric 
5789f988b79SJean-Baptiste Boric 		/* did we encounter the root node? i.e. loop back */
5799f988b79SJean-Baptiste Boric 		if (udf_compare_icb(&parent_loc, &VTOI(vp)->loc) == 0) {
5809f988b79SJean-Baptiste Boric 			DPRINTF(NODE, ("ROOT found!\n"));
5819f988b79SJean-Baptiste Boric 			vput(vp);
5829f988b79SJean-Baptiste Boric 			*intermediate_node_ret = NULL;
5839f988b79SJean-Baptiste Boric 			return 0;
5849f988b79SJean-Baptiste Boric 		}
5859f988b79SJean-Baptiste Boric 
5869f988b79SJean-Baptiste Boric 		/* Did we find that fdvp is an ancestor of tdvp? */
5879f988b79SJean-Baptiste Boric 		if (udf_compare_icb(&parent_loc, &VTOI(fdvp)->loc) == 0) {
5889f988b79SJean-Baptiste Boric 			DPRINTF(NODE, ("fdvp is ancestor of tdvp\n"));
5899f988b79SJean-Baptiste Boric 			*intermediate_node_ret = vp;
5909f988b79SJean-Baptiste Boric 			VOP_UNLOCK(vp);
5919f988b79SJean-Baptiste Boric 			return 0;
5929f988b79SJean-Baptiste Boric 		}
5939f988b79SJean-Baptiste Boric 
5949f988b79SJean-Baptiste Boric 		/*
5959f988b79SJean-Baptiste Boric 		 * Unlock vp so that we can lock the parent, but keep child vp
5969f988b79SJean-Baptiste Boric 		 * referenced until after we have found the parent, so that
5979f988b79SJean-Baptiste Boric 		 * parent_node will not be recycled.
5989f988b79SJean-Baptiste Boric 		 */
5999f988b79SJean-Baptiste Boric 		DPRINTF(NODE, ("\tgetting the parent node\n"));
6009f988b79SJean-Baptiste Boric 		VOP_UNLOCK(vp);
6019f988b79SJean-Baptiste Boric 		error = udf_get_node(ump, &parent_loc, &parent_node);
6029f988b79SJean-Baptiste Boric 		vrele(vp);
6039f988b79SJean-Baptiste Boric 		if (error)
6049f988b79SJean-Baptiste Boric 			return error;
6059f988b79SJean-Baptiste Boric 
6069f988b79SJean-Baptiste Boric 		dvp = parent_node->vnode;
6079f988b79SJean-Baptiste Boric 
6089f988b79SJean-Baptiste Boric 		/* switch */
6099f988b79SJean-Baptiste Boric 		KASSERT(dvp != NULL);
6109f988b79SJean-Baptiste Boric 		KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
6119f988b79SJean-Baptiste Boric 		vp  = dvp;
6129f988b79SJean-Baptiste Boric 
6139f988b79SJean-Baptiste Boric 		/* sanity check */
6149f988b79SJean-Baptiste Boric 		if (vp->v_type != VDIR) {
6159f988b79SJean-Baptiste Boric 			/*
6169f988b79SJean-Baptiste Boric 			 * Odd, but can happen if we loose the race and the
6179f988b79SJean-Baptiste Boric 			 * '..' node has been recycled.
6189f988b79SJean-Baptiste Boric 			 */
6199f988b79SJean-Baptiste Boric 			vput(vp);
6209f988b79SJean-Baptiste Boric 			return ENOTDIR;
6219f988b79SJean-Baptiste Boric 		}
6229f988b79SJean-Baptiste Boric 
6239f988b79SJean-Baptiste Boric 		if (udf_rmdired_p(vp)) {
6249f988b79SJean-Baptiste Boric 			vput(vp);
6259f988b79SJean-Baptiste Boric 			return ENOENT;
6269f988b79SJean-Baptiste Boric 		}
6279f988b79SJean-Baptiste Boric 	}
6289f988b79SJean-Baptiste Boric }
6299f988b79SJean-Baptiste Boric 
6309f988b79SJean-Baptiste Boric 
6319f988b79SJean-Baptiste Boric /*
6329f988b79SJean-Baptiste Boric  * udf_gro_lock_directory: lock the directory vp, but fail if it has been
6339f988b79SJean-Baptiste Boric  * rmdir'd.
6349f988b79SJean-Baptiste Boric  */
6359f988b79SJean-Baptiste Boric static int
udf_gro_lock_directory(struct mount * mp,struct vnode * vp)6369f988b79SJean-Baptiste Boric udf_gro_lock_directory(struct mount *mp, struct vnode *vp)
6379f988b79SJean-Baptiste Boric {
6389f988b79SJean-Baptiste Boric 
6399f988b79SJean-Baptiste Boric 	(void)mp;
6409f988b79SJean-Baptiste Boric 	KASSERT(mp != NULL);
6419f988b79SJean-Baptiste Boric 	KASSERT(vp != NULL);
6429f988b79SJean-Baptiste Boric 	KASSERT(vp->v_mount == mp);
6439f988b79SJean-Baptiste Boric 
6449f988b79SJean-Baptiste Boric 	DPRINTF(CALL, ("udf_gro_lock_directory called\n"));
6459f988b79SJean-Baptiste Boric 	DPRINTF(LOCKING, ("udf_gro_lock_directory called\n"));
6469f988b79SJean-Baptiste Boric 
6479f988b79SJean-Baptiste Boric 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
6489f988b79SJean-Baptiste Boric 
6499f988b79SJean-Baptiste Boric 	if (udf_rmdired_p(vp)) {
6509f988b79SJean-Baptiste Boric 		VOP_UNLOCK(vp);
6519f988b79SJean-Baptiste Boric 		return ENOENT;
6529f988b79SJean-Baptiste Boric 	}
6539f988b79SJean-Baptiste Boric 
6549f988b79SJean-Baptiste Boric 	return 0;
6559f988b79SJean-Baptiste Boric }
6569f988b79SJean-Baptiste Boric 
6579f988b79SJean-Baptiste Boric 
6589f988b79SJean-Baptiste Boric static const struct genfs_rename_ops udf_genfs_rename_ops = {
6599f988b79SJean-Baptiste Boric 	.gro_directory_empty_p		= udf_gro_directory_empty_p,
6609f988b79SJean-Baptiste Boric 	.gro_rename_check_possible	= udf_gro_rename_check_possible,
6619f988b79SJean-Baptiste Boric 	.gro_rename_check_permitted	= udf_gro_rename_check_permitted,
6629f988b79SJean-Baptiste Boric 	.gro_remove_check_possible	= udf_gro_remove_check_possible,
6639f988b79SJean-Baptiste Boric 	.gro_remove_check_permitted	= udf_gro_remove_check_permitted,
6649f988b79SJean-Baptiste Boric 	.gro_rename			= udf_gro_rename,
6659f988b79SJean-Baptiste Boric 	.gro_remove			= udf_gro_remove,
6669f988b79SJean-Baptiste Boric 	.gro_lookup			= udf_gro_lookup,
6679f988b79SJean-Baptiste Boric 	.gro_genealogy			= udf_gro_genealogy,
6689f988b79SJean-Baptiste Boric 	.gro_lock_directory		= udf_gro_lock_directory,
6699f988b79SJean-Baptiste Boric };
670