udf_rename.c revision 1.10.8.2 1 1.10.8.2 yamt /* $NetBSD: udf_rename.c,v 1.10.8.2 2014/05/22 11:41:02 yamt Exp $ */
2 1.10.8.2 yamt
3 1.10.8.2 yamt /*
4 1.10.8.2 yamt * Copyright (c) 2013 Reinoud Zandijk
5 1.10.8.2 yamt * All rights reserved.
6 1.10.8.2 yamt *
7 1.10.8.2 yamt * Redistribution and use in source and binary forms, with or without
8 1.10.8.2 yamt * modification, are permitted provided that the following conditions
9 1.10.8.2 yamt * are met:
10 1.10.8.2 yamt * 1. Redistributions of source code must retain the above copyright
11 1.10.8.2 yamt * notice, this list of conditions and the following disclaimer.
12 1.10.8.2 yamt * 2. Redistributions in binary form must reproduce the above copyright
13 1.10.8.2 yamt * notice, this list of conditions and the following disclaimer in the
14 1.10.8.2 yamt * documentation and/or other materials provided with the distribution.
15 1.10.8.2 yamt *
16 1.10.8.2 yamt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 1.10.8.2 yamt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 1.10.8.2 yamt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 1.10.8.2 yamt * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 1.10.8.2 yamt * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 1.10.8.2 yamt * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 1.10.8.2 yamt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 1.10.8.2 yamt * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 1.10.8.2 yamt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 1.10.8.2 yamt * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 1.10.8.2 yamt *
27 1.10.8.2 yamt * Comments and trivial code from the reference implementation in tmpfs.
28 1.10.8.2 yamt */
29 1.10.8.2 yamt
30 1.10.8.2 yamt #include <sys/cdefs.h>
31 1.10.8.2 yamt __KERNEL_RCSID(0, "$NetBSD: udf_rename.c,v 1.10.8.2 2014/05/22 11:41:02 yamt Exp $");
32 1.10.8.2 yamt
33 1.10.8.2 yamt #include <sys/param.h>
34 1.10.8.2 yamt #include <sys/errno.h>
35 1.10.8.2 yamt #include <sys/kauth.h>
36 1.10.8.2 yamt #include <sys/mount.h>
37 1.10.8.2 yamt #include <sys/namei.h>
38 1.10.8.2 yamt #include <sys/stat.h>
39 1.10.8.2 yamt #include <sys/malloc.h>
40 1.10.8.2 yamt #include <sys/dirent.h>
41 1.10.8.2 yamt #include <sys/vnode.h>
42 1.10.8.2 yamt #include <sys/vnode_if.h>
43 1.10.8.2 yamt
44 1.10.8.2 yamt #include <miscfs/genfs/genfs.h>
45 1.10.8.2 yamt
46 1.10.8.2 yamt #include <fs/udf/ecma167-udf.h>
47 1.10.8.2 yamt #include <fs/udf/udf_mount.h>
48 1.10.8.2 yamt #include <sys/dirhash.h>
49 1.10.8.2 yamt
50 1.10.8.2 yamt #include "udf.h"
51 1.10.8.2 yamt #include "udf_subr.h"
52 1.10.8.2 yamt #include "udf_bswap.h"
53 1.10.8.2 yamt
54 1.10.8.2 yamt
55 1.10.8.2 yamt /* forwards */
56 1.10.8.2 yamt static int udf_sane_rename( struct vnode *, struct componentname *,
57 1.10.8.2 yamt struct vnode *, struct componentname *,
58 1.10.8.2 yamt kauth_cred_t, bool);
59 1.10.8.2 yamt static bool udf_rmdired_p(struct vnode *);
60 1.10.8.2 yamt static int udf_gro_lock_directory(struct mount *, struct vnode *);
61 1.10.8.2 yamt
62 1.10.8.2 yamt static const struct genfs_rename_ops udf_genfs_rename_ops;
63 1.10.8.2 yamt
64 1.10.8.2 yamt
65 1.10.8.2 yamt #define VTOI(vnode) ((struct udf_node *) (vnode)->v_data)
66 1.10.8.2 yamt
67 1.10.8.2 yamt
68 1.10.8.2 yamt /*
69 1.10.8.2 yamt * udf_sane_rename: The hairiest vop, with the saner API.
70 1.10.8.2 yamt *
71 1.10.8.2 yamt * Arguments:
72 1.10.8.2 yamt *
73 1.10.8.2 yamt * . fdvp (from directory vnode),
74 1.10.8.2 yamt * . fcnp (from component name),
75 1.10.8.2 yamt * . tdvp (to directory vnode),
76 1.10.8.2 yamt * . tcnp (to component name),
77 1.10.8.2 yamt * . cred (credentials structure), and
78 1.10.8.2 yamt * . posixly_correct (flag for behaviour if target & source link same file).
79 1.10.8.2 yamt *
80 1.10.8.2 yamt * fdvp and tdvp may be the same, and must be referenced and unlocked.
81 1.10.8.2 yamt */
82 1.10.8.2 yamt static int
83 1.10.8.2 yamt udf_sane_rename( struct vnode *fdvp, struct componentname *fcnp,
84 1.10.8.2 yamt struct vnode *tdvp, struct componentname *tcnp,
85 1.10.8.2 yamt kauth_cred_t cred, bool posixly_correct)
86 1.10.8.2 yamt {
87 1.10.8.2 yamt DPRINTF(CALL, ("udf_sane_rename '%s' -> '%s'\n",
88 1.10.8.2 yamt fcnp->cn_nameptr, tcnp->cn_nameptr));
89 1.10.8.2 yamt return genfs_sane_rename(&udf_genfs_rename_ops,
90 1.10.8.2 yamt fdvp, fcnp, NULL, tdvp, tcnp, NULL,
91 1.10.8.2 yamt cred, posixly_correct);
92 1.10.8.2 yamt }
93 1.10.8.2 yamt
94 1.10.8.2 yamt
95 1.10.8.2 yamt /*
96 1.10.8.2 yamt * udf_rename: the hairiest vop, with the insanest API. Pass to
97 1.10.8.2 yamt * genfs_insane_rename immediately.
98 1.10.8.2 yamt */
99 1.10.8.2 yamt int
100 1.10.8.2 yamt udf_rename(void *v)
101 1.10.8.2 yamt {
102 1.10.8.2 yamt struct vop_rename_args /* {
103 1.10.8.2 yamt struct vnode *a_fdvp;
104 1.10.8.2 yamt struct vnode *a_fvp;
105 1.10.8.2 yamt struct componentname *a_fcnp;
106 1.10.8.2 yamt struct vnode *a_tdvp;
107 1.10.8.2 yamt struct vnode *a_tvp;
108 1.10.8.2 yamt struct componentname *a_tcnp;
109 1.10.8.2 yamt } */ *ap = v;
110 1.10.8.2 yamt DPRINTF(CALL, ("udf_rename called\n"));
111 1.10.8.2 yamt return genfs_insane_rename(ap, &udf_sane_rename);
112 1.10.8.2 yamt }
113 1.10.8.2 yamt
114 1.10.8.2 yamt
115 1.10.8.2 yamt /*
116 1.10.8.2 yamt * udf_gro_directory_empty_p: return true if the directory vp is empty. dvp is
117 1.10.8.2 yamt * its parent.
118 1.10.8.2 yamt *
119 1.10.8.2 yamt * vp and dvp must be locked and referenced.
120 1.10.8.2 yamt */
121 1.10.8.2 yamt static bool
122 1.10.8.2 yamt udf_gro_directory_empty_p(struct mount *mp, kauth_cred_t cred,
123 1.10.8.2 yamt struct vnode *vp, struct vnode *dvp)
124 1.10.8.2 yamt {
125 1.10.8.2 yamt struct udf_node *udf_node = VTOI(vp);
126 1.10.8.2 yamt int error, isempty;
127 1.10.8.2 yamt
128 1.10.8.2 yamt KASSERT(mp != NULL);
129 1.10.8.2 yamt KASSERT(vp != NULL);
130 1.10.8.2 yamt KASSERT(dvp != NULL);
131 1.10.8.2 yamt KASSERT(vp != dvp);
132 1.10.8.2 yamt KASSERT(vp->v_mount == mp);
133 1.10.8.2 yamt KASSERT(dvp->v_mount == mp);
134 1.10.8.2 yamt KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
135 1.10.8.2 yamt KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
136 1.10.8.2 yamt
137 1.10.8.2 yamt DPRINTF(CALL, ("udf_gro_directory_empty_p called\n"));
138 1.10.8.2 yamt /* make sure our `leaf' node's hash is populated */
139 1.10.8.2 yamt dirhash_get(&udf_node->dir_hash);
140 1.10.8.2 yamt error = udf_dirhash_fill(udf_node);
141 1.10.8.2 yamt if (error) {
142 1.10.8.2 yamt dirhash_put(udf_node->dir_hash);
143 1.10.8.2 yamt /* VERY unlikely, answer its not empty */
144 1.10.8.2 yamt return 0;
145 1.10.8.2 yamt }
146 1.10.8.2 yamt
147 1.10.8.2 yamt /* check to see if the directory is empty */
148 1.10.8.2 yamt isempty = dirhash_dir_isempty(udf_node->dir_hash);
149 1.10.8.2 yamt dirhash_put(udf_node->dir_hash);
150 1.10.8.2 yamt
151 1.10.8.2 yamt return isempty;
152 1.10.8.2 yamt }
153 1.10.8.2 yamt
154 1.10.8.2 yamt
155 1.10.8.2 yamt /*
156 1.10.8.2 yamt * udf_gro_rename_check_possible: check whether a rename is possible
157 1.10.8.2 yamt * independent of credentials.
158 1.10.8.2 yamt */
159 1.10.8.2 yamt static int
160 1.10.8.2 yamt udf_gro_rename_check_possible(struct mount *mp,
161 1.10.8.2 yamt struct vnode *fdvp, struct vnode *fvp,
162 1.10.8.2 yamt struct vnode *tdvp, struct vnode *tvp)
163 1.10.8.2 yamt {
164 1.10.8.2 yamt (void)mp;
165 1.10.8.2 yamt KASSERT(mp != NULL);
166 1.10.8.2 yamt KASSERT(fdvp != NULL);
167 1.10.8.2 yamt KASSERT(fvp != NULL);
168 1.10.8.2 yamt KASSERT(tdvp != NULL);
169 1.10.8.2 yamt KASSERT(fdvp != fvp);
170 1.10.8.2 yamt KASSERT(fdvp != tvp);
171 1.10.8.2 yamt KASSERT(tdvp != fvp);
172 1.10.8.2 yamt KASSERT(tdvp != tvp);
173 1.10.8.2 yamt KASSERT(fvp != tvp);
174 1.10.8.2 yamt KASSERT(fdvp->v_type == VDIR);
175 1.10.8.2 yamt KASSERT(tdvp->v_type == VDIR);
176 1.10.8.2 yamt KASSERT(fdvp->v_mount == mp);
177 1.10.8.2 yamt KASSERT(fvp->v_mount == mp);
178 1.10.8.2 yamt KASSERT(tdvp->v_mount == mp);
179 1.10.8.2 yamt KASSERT((tvp == NULL) || (tvp->v_mount == mp));
180 1.10.8.2 yamt KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
181 1.10.8.2 yamt KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
182 1.10.8.2 yamt KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
183 1.10.8.2 yamt KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
184 1.10.8.2 yamt
185 1.10.8.2 yamt DPRINTF(CALL, ("udf_gro_rename_check_possible called\n"));
186 1.10.8.2 yamt
187 1.10.8.2 yamt /* flags not implemented since they are not defined (yet) in UDF */
188 1.10.8.2 yamt return 0;
189 1.10.8.2 yamt }
190 1.10.8.2 yamt
191 1.10.8.2 yamt
192 1.10.8.2 yamt /*
193 1.10.8.2 yamt * udf_gro_rename_check_permitted: check whether a rename is permitted given
194 1.10.8.2 yamt * our credentials.
195 1.10.8.2 yamt */
196 1.10.8.2 yamt static int
197 1.10.8.2 yamt udf_gro_rename_check_permitted(struct mount *mp, kauth_cred_t cred,
198 1.10.8.2 yamt struct vnode *fdvp, struct vnode *fvp,
199 1.10.8.2 yamt struct vnode *tdvp, struct vnode *tvp)
200 1.10.8.2 yamt {
201 1.10.8.2 yamt struct udf_node *fdir_node = VTOI(fdvp);
202 1.10.8.2 yamt struct udf_node *tdir_node = VTOI(tdvp);
203 1.10.8.2 yamt struct udf_node *f_node = VTOI(fvp);
204 1.10.8.2 yamt struct udf_node *t_node = (tvp? VTOI(tvp): NULL);
205 1.10.8.2 yamt mode_t fdmode, tdmode;
206 1.10.8.2 yamt uid_t fduid, tduid, fuid, tuid;
207 1.10.8.2 yamt gid_t gdummy;
208 1.10.8.2 yamt
209 1.10.8.2 yamt (void)mp;
210 1.10.8.2 yamt KASSERT(mp != NULL);
211 1.10.8.2 yamt KASSERT(fdvp != NULL);
212 1.10.8.2 yamt KASSERT(fvp != NULL);
213 1.10.8.2 yamt KASSERT(tdvp != NULL);
214 1.10.8.2 yamt KASSERT(fdvp != fvp);
215 1.10.8.2 yamt KASSERT(fdvp != tvp);
216 1.10.8.2 yamt KASSERT(tdvp != fvp);
217 1.10.8.2 yamt KASSERT(tdvp != tvp);
218 1.10.8.2 yamt KASSERT(fvp != tvp);
219 1.10.8.2 yamt KASSERT(fdvp->v_type == VDIR);
220 1.10.8.2 yamt KASSERT(tdvp->v_type == VDIR);
221 1.10.8.2 yamt KASSERT(fdvp->v_mount == mp);
222 1.10.8.2 yamt KASSERT(fvp->v_mount == mp);
223 1.10.8.2 yamt KASSERT(tdvp->v_mount == mp);
224 1.10.8.2 yamt KASSERT((tvp == NULL) || (tvp->v_mount == mp));
225 1.10.8.2 yamt KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
226 1.10.8.2 yamt KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
227 1.10.8.2 yamt KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
228 1.10.8.2 yamt KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
229 1.10.8.2 yamt
230 1.10.8.2 yamt DPRINTF(CALL, ("udf_gro_rename_check_permitted called\n"));
231 1.10.8.2 yamt fdmode = udf_getaccessmode(fdir_node);
232 1.10.8.2 yamt tdmode = udf_getaccessmode(tdir_node);
233 1.10.8.2 yamt
234 1.10.8.2 yamt udf_getownership(fdir_node, &fduid, &gdummy);
235 1.10.8.2 yamt udf_getownership(tdir_node, &tduid, &gdummy);
236 1.10.8.2 yamt udf_getownership(f_node, &fuid, &gdummy);
237 1.10.8.2 yamt
238 1.10.8.2 yamt tuid = 0;
239 1.10.8.2 yamt if (t_node)
240 1.10.8.2 yamt udf_getownership(t_node, &tuid, &gdummy);
241 1.10.8.2 yamt
242 1.10.8.2 yamt return genfs_ufslike_rename_check_permitted(cred,
243 1.10.8.2 yamt fdvp, fdmode, fduid,
244 1.10.8.2 yamt fvp, fuid,
245 1.10.8.2 yamt tdvp, tdmode, tduid,
246 1.10.8.2 yamt tvp, tuid);
247 1.10.8.2 yamt }
248 1.10.8.2 yamt
249 1.10.8.2 yamt
250 1.10.8.2 yamt /*
251 1.10.8.2 yamt * udf_gro_remove_check_possible: check whether a remove is possible
252 1.10.8.2 yamt * independent of credentials.
253 1.10.8.2 yamt *
254 1.10.8.2 yamt * XXX could check for special attributes?
255 1.10.8.2 yamt */
256 1.10.8.2 yamt static int
257 1.10.8.2 yamt udf_gro_remove_check_possible(struct mount *mp,
258 1.10.8.2 yamt struct vnode *dvp, struct vnode *vp)
259 1.10.8.2 yamt {
260 1.10.8.2 yamt (void)mp;
261 1.10.8.2 yamt KASSERT(mp != NULL);
262 1.10.8.2 yamt KASSERT(dvp != NULL);
263 1.10.8.2 yamt KASSERT(vp != NULL);
264 1.10.8.2 yamt KASSERT(dvp != vp);
265 1.10.8.2 yamt KASSERT(dvp->v_type == VDIR);
266 1.10.8.2 yamt KASSERT(vp->v_type != VDIR);
267 1.10.8.2 yamt KASSERT(dvp->v_mount == mp);
268 1.10.8.2 yamt KASSERT(vp->v_mount == mp);
269 1.10.8.2 yamt KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
270 1.10.8.2 yamt KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
271 1.10.8.2 yamt
272 1.10.8.2 yamt DPRINTF(CALL, ("udf_gro_remove_check_possible called\n"));
273 1.10.8.2 yamt
274 1.10.8.2 yamt /* flags not implemented since they are not defined (yet) in UDF */
275 1.10.8.2 yamt return 0;
276 1.10.8.2 yamt }
277 1.10.8.2 yamt
278 1.10.8.2 yamt
279 1.10.8.2 yamt /*
280 1.10.8.2 yamt * udf_gro_remove_check_permitted: check whether a remove is permitted given
281 1.10.8.2 yamt * our credentials.
282 1.10.8.2 yamt */
283 1.10.8.2 yamt static int
284 1.10.8.2 yamt udf_gro_remove_check_permitted(struct mount *mp, kauth_cred_t cred,
285 1.10.8.2 yamt struct vnode *dvp, struct vnode *vp)
286 1.10.8.2 yamt {
287 1.10.8.2 yamt struct udf_node *dir_node = VTOI(dvp);
288 1.10.8.2 yamt struct udf_node *udf_node = VTOI(vp);
289 1.10.8.2 yamt mode_t dmode;
290 1.10.8.2 yamt uid_t duid, uid;
291 1.10.8.2 yamt gid_t gdummy;
292 1.10.8.2 yamt
293 1.10.8.2 yamt (void)mp;
294 1.10.8.2 yamt KASSERT(mp != NULL);
295 1.10.8.2 yamt KASSERT(dvp != NULL);
296 1.10.8.2 yamt KASSERT(vp != NULL);
297 1.10.8.2 yamt KASSERT(dvp != vp);
298 1.10.8.2 yamt KASSERT(dvp->v_type == VDIR);
299 1.10.8.2 yamt KASSERT(vp->v_type != VDIR);
300 1.10.8.2 yamt KASSERT(dvp->v_mount == mp);
301 1.10.8.2 yamt KASSERT(vp->v_mount == mp);
302 1.10.8.2 yamt KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
303 1.10.8.2 yamt KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
304 1.10.8.2 yamt
305 1.10.8.2 yamt DPRINTF(CALL, ("udf_gro_remove_check_permitted called\n"));
306 1.10.8.2 yamt dmode = udf_getaccessmode(dir_node);
307 1.10.8.2 yamt
308 1.10.8.2 yamt udf_getownership(dir_node, &duid, &gdummy);
309 1.10.8.2 yamt udf_getownership(udf_node, &uid, &gdummy);
310 1.10.8.2 yamt
311 1.10.8.2 yamt return genfs_ufslike_remove_check_permitted(cred,
312 1.10.8.2 yamt dvp, dmode, duid,
313 1.10.8.2 yamt vp, uid);
314 1.10.8.2 yamt }
315 1.10.8.2 yamt
316 1.10.8.2 yamt
317 1.10.8.2 yamt /*
318 1.10.8.2 yamt * udf_gro_rename: actually perform the rename operation.
319 1.10.8.2 yamt */
320 1.10.8.2 yamt static int
321 1.10.8.2 yamt udf_gro_rename(struct mount *mp, kauth_cred_t cred,
322 1.10.8.2 yamt struct vnode *fdvp, struct componentname *fcnp,
323 1.10.8.2 yamt void *fde, struct vnode *fvp,
324 1.10.8.2 yamt struct vnode *tdvp, struct componentname *tcnp,
325 1.10.8.2 yamt void *tde, struct vnode *tvp)
326 1.10.8.2 yamt {
327 1.10.8.2 yamt struct udf_node *fnode, *fdnode, *tnode, *tdnode;
328 1.10.8.2 yamt struct vattr fvap;
329 1.10.8.2 yamt int error;
330 1.10.8.2 yamt
331 1.10.8.2 yamt (void)cred;
332 1.10.8.2 yamt KASSERT(mp != NULL);
333 1.10.8.2 yamt KASSERT(fdvp != NULL);
334 1.10.8.2 yamt KASSERT(fcnp != NULL);
335 1.10.8.2 yamt KASSERT(fvp != NULL);
336 1.10.8.2 yamt KASSERT(tdvp != NULL);
337 1.10.8.2 yamt KASSERT(tcnp != NULL);
338 1.10.8.2 yamt KASSERT(fdvp != fvp);
339 1.10.8.2 yamt KASSERT(fdvp != tvp);
340 1.10.8.2 yamt KASSERT(tdvp != fvp);
341 1.10.8.2 yamt KASSERT(tdvp != tvp);
342 1.10.8.2 yamt KASSERT(fvp != tvp);
343 1.10.8.2 yamt KASSERT(fdvp->v_mount == mp);
344 1.10.8.2 yamt KASSERT(fvp->v_mount == mp);
345 1.10.8.2 yamt KASSERT(tdvp->v_mount == mp);
346 1.10.8.2 yamt KASSERT((tvp == NULL) || (tvp->v_mount == mp));
347 1.10.8.2 yamt KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
348 1.10.8.2 yamt KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
349 1.10.8.2 yamt KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
350 1.10.8.2 yamt KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
351 1.10.8.2 yamt
352 1.10.8.2 yamt DPRINTF(CALL, ("udf_gro_rename called\n"));
353 1.10.8.2 yamt DPRINTF(NODE, ("udf_gro_rename called : %s -> %s\n",
354 1.10.8.2 yamt fcnp->cn_nameptr, tcnp->cn_nameptr));
355 1.10.8.2 yamt
356 1.10.8.2 yamt fnode = VTOI(fvp);
357 1.10.8.2 yamt fdnode = VTOI(fdvp);
358 1.10.8.2 yamt tnode = (tvp == NULL) ? NULL : VTOI(tvp);
359 1.10.8.2 yamt tdnode = VTOI(tdvp);
360 1.10.8.2 yamt
361 1.10.8.2 yamt /* get attribute information */
362 1.10.8.2 yamt error = VOP_GETATTR(fvp, &fvap, NULL);
363 1.10.8.2 yamt if (error)
364 1.10.8.2 yamt return error;
365 1.10.8.2 yamt
366 1.10.8.2 yamt /* remove existing entry if present */
367 1.10.8.2 yamt if (tvp)
368 1.10.8.2 yamt udf_dir_detach(tdnode->ump, tdnode, tnode, tcnp);
369 1.10.8.2 yamt
370 1.10.8.2 yamt /* create new directory entry for the node */
371 1.10.8.2 yamt error = udf_dir_attach(tdnode->ump, tdnode, fnode, &fvap, tcnp);
372 1.10.8.2 yamt if (error)
373 1.10.8.2 yamt return error;
374 1.10.8.2 yamt
375 1.10.8.2 yamt /* unlink old directory entry for the node, if failing, unattach new */
376 1.10.8.2 yamt error = udf_dir_detach(tdnode->ump, fdnode, fnode, fcnp);
377 1.10.8.2 yamt if (error)
378 1.10.8.2 yamt goto rollback_attach;
379 1.10.8.2 yamt
380 1.10.8.2 yamt if ((fdnode != tdnode) && (fvp->v_type == VDIR)) {
381 1.10.8.2 yamt /* update fnode's '..' entry */
382 1.10.8.2 yamt error = udf_dir_update_rootentry(fnode->ump, fnode, tdnode);
383 1.10.8.2 yamt if (error)
384 1.10.8.2 yamt goto rollback;
385 1.10.8.2 yamt }
386 1.10.8.2 yamt
387 1.10.8.2 yamt VN_KNOTE(fvp, NOTE_RENAME);
388 1.10.8.2 yamt genfs_rename_cache_purge(fdvp, fvp, tdvp, tvp);
389 1.10.8.2 yamt return 0;
390 1.10.8.2 yamt
391 1.10.8.2 yamt rollback:
392 1.10.8.2 yamt /* 'try' to recover from this situation */
393 1.10.8.2 yamt udf_dir_attach(tdnode->ump, fdnode, fnode, &fvap, fcnp);
394 1.10.8.2 yamt rollback_attach:
395 1.10.8.2 yamt udf_dir_detach(tdnode->ump, tdnode, fnode, tcnp);
396 1.10.8.2 yamt
397 1.10.8.2 yamt return error;
398 1.10.8.2 yamt }
399 1.10.8.2 yamt
400 1.10.8.2 yamt
401 1.10.8.2 yamt /*
402 1.10.8.2 yamt * udf_gro_remove: rename an object over another link to itself, effectively
403 1.10.8.2 yamt * removing just the original link.
404 1.10.8.2 yamt */
405 1.10.8.2 yamt static int
406 1.10.8.2 yamt udf_gro_remove(struct mount *mp, kauth_cred_t cred,
407 1.10.8.2 yamt struct vnode *dvp, struct componentname *cnp, void *de, struct vnode *vp)
408 1.10.8.2 yamt {
409 1.10.8.2 yamt struct udf_node *dir_node, *udf_node;
410 1.10.8.2 yamt
411 1.10.8.2 yamt KASSERT(mp != NULL);
412 1.10.8.2 yamt KASSERT(dvp != NULL);
413 1.10.8.2 yamt KASSERT(cnp != NULL);
414 1.10.8.2 yamt KASSERT(vp != NULL);
415 1.10.8.2 yamt KASSERT(dvp != vp);
416 1.10.8.2 yamt KASSERT(dvp->v_mount == mp);
417 1.10.8.2 yamt KASSERT(vp->v_mount == mp);
418 1.10.8.2 yamt KASSERT(dvp->v_type == VDIR);
419 1.10.8.2 yamt KASSERT(vp->v_type != VDIR);
420 1.10.8.2 yamt KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
421 1.10.8.2 yamt KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
422 1.10.8.2 yamt
423 1.10.8.2 yamt DPRINTF(CALL, ("udf_gro_remove called\n"));
424 1.10.8.2 yamt
425 1.10.8.2 yamt dir_node = VTOI(dvp);
426 1.10.8.2 yamt udf_node = VTOI(vp);
427 1.10.8.2 yamt udf_dir_detach(dir_node->ump, dir_node, udf_node, cnp);
428 1.10.8.2 yamt
429 1.10.8.2 yamt return 0;
430 1.10.8.2 yamt }
431 1.10.8.2 yamt
432 1.10.8.2 yamt
433 1.10.8.2 yamt /*
434 1.10.8.2 yamt * udf_gro_lookup: look up and save the lookup results.
435 1.10.8.2 yamt */
436 1.10.8.2 yamt static int
437 1.10.8.2 yamt udf_gro_lookup(struct mount *mp, struct vnode *dvp,
438 1.10.8.2 yamt struct componentname *cnp, void *de_ret, struct vnode **vp_ret)
439 1.10.8.2 yamt {
440 1.10.8.2 yamt struct udf_node *dir_node, *res_node;
441 1.10.8.2 yamt struct long_ad icb_loc;
442 1.10.8.2 yamt const char *name;
443 1.10.8.2 yamt int namelen, error;
444 1.10.8.2 yamt int found;
445 1.10.8.2 yamt
446 1.10.8.2 yamt (void)mp;
447 1.10.8.2 yamt KASSERT(mp != NULL);
448 1.10.8.2 yamt KASSERT(dvp != NULL);
449 1.10.8.2 yamt KASSERT(cnp != NULL);
450 1.10.8.2 yamt KASSERT(vp_ret != NULL);
451 1.10.8.2 yamt KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
452 1.10.8.2 yamt
453 1.10.8.2 yamt dir_node = VTOI(dvp);
454 1.10.8.2 yamt
455 1.10.8.2 yamt DPRINTF(CALL, ("udf_gro_lookup called\n"));
456 1.10.8.2 yamt
457 1.10.8.2 yamt /* lookup filename in the directory; location icb_loc */
458 1.10.8.2 yamt name = cnp->cn_nameptr;
459 1.10.8.2 yamt namelen = cnp->cn_namelen;
460 1.10.8.2 yamt error = udf_lookup_name_in_dir(dvp, name, namelen,
461 1.10.8.2 yamt &icb_loc, &found);
462 1.10.8.2 yamt if (error)
463 1.10.8.2 yamt return error;
464 1.10.8.2 yamt if (!found)
465 1.10.8.2 yamt return ENOENT;
466 1.10.8.2 yamt
467 1.10.8.2 yamt DPRINTF(LOOKUP, ("udf_gro_lookup found '%s'\n", name));
468 1.10.8.2 yamt error = udf_get_node(dir_node->ump, &icb_loc, &res_node);
469 1.10.8.2 yamt if (error)
470 1.10.8.2 yamt return error;
471 1.10.8.2 yamt *vp_ret = res_node->vnode;
472 1.10.8.2 yamt VOP_UNLOCK(res_node->vnode);
473 1.10.8.2 yamt
474 1.10.8.2 yamt return 0;
475 1.10.8.2 yamt }
476 1.10.8.2 yamt
477 1.10.8.2 yamt
478 1.10.8.2 yamt /*
479 1.10.8.2 yamt * udf_rmdired_p: check whether the directory vp has been rmdired.
480 1.10.8.2 yamt *
481 1.10.8.2 yamt * vp must be locked and referenced.
482 1.10.8.2 yamt */
483 1.10.8.2 yamt static bool
484 1.10.8.2 yamt udf_rmdired_p(struct vnode *vp)
485 1.10.8.2 yamt {
486 1.10.8.2 yamt DPRINTF(CALL, ("udf_rmdired_p called\n"));
487 1.10.8.2 yamt
488 1.10.8.2 yamt KASSERT(vp != NULL);
489 1.10.8.2 yamt KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
490 1.10.8.2 yamt KASSERT(vp->v_type == VDIR);
491 1.10.8.2 yamt
492 1.10.8.2 yamt return (VTOI(vp)->i_flags & IN_DELETED);
493 1.10.8.2 yamt }
494 1.10.8.2 yamt
495 1.10.8.2 yamt
496 1.10.8.2 yamt /*
497 1.10.8.2 yamt * udf_gro_genealogy: analyze the genealogy of the source and target
498 1.10.8.2 yamt * directories.
499 1.10.8.2 yamt */
500 1.10.8.2 yamt static int
501 1.10.8.2 yamt udf_gro_genealogy(struct mount *mp, kauth_cred_t cred,
502 1.10.8.2 yamt struct vnode *fdvp, struct vnode *tdvp,
503 1.10.8.2 yamt struct vnode **intermediate_node_ret)
504 1.10.8.2 yamt {
505 1.10.8.2 yamt struct udf_mount *ump;
506 1.10.8.2 yamt struct udf_node *parent_node;
507 1.10.8.2 yamt struct vnode *vp, *dvp;
508 1.10.8.2 yamt struct long_ad parent_loc;
509 1.10.8.2 yamt const char *name;
510 1.10.8.2 yamt int namelen;
511 1.10.8.2 yamt int error, found;
512 1.10.8.2 yamt
513 1.10.8.2 yamt (void)cred;
514 1.10.8.2 yamt KASSERT(mp != NULL);
515 1.10.8.2 yamt KASSERT(fdvp != NULL);
516 1.10.8.2 yamt KASSERT(tdvp != NULL);
517 1.10.8.2 yamt KASSERT(fdvp != tdvp);
518 1.10.8.2 yamt KASSERT(intermediate_node_ret != NULL);
519 1.10.8.2 yamt KASSERT(fdvp->v_mount == mp);
520 1.10.8.2 yamt KASSERT(tdvp->v_mount == mp);
521 1.10.8.2 yamt KASSERT(fdvp->v_type == VDIR);
522 1.10.8.2 yamt KASSERT(tdvp->v_type == VDIR);
523 1.10.8.2 yamt
524 1.10.8.2 yamt DPRINTF(CALL, ("udf_gro_genealogy called\n"));
525 1.10.8.2 yamt
526 1.10.8.2 yamt /*
527 1.10.8.2 yamt * We need to provisionally lock tdvp to keep rmdir from deleting it
528 1.10.8.2 yamt * -- or any ancestor -- at an inopportune moment.
529 1.10.8.2 yamt *
530 1.10.8.2 yamt * XXX WHY is this not in genfs's rename? XXX
531 1.10.8.2 yamt */
532 1.10.8.2 yamt error = udf_gro_lock_directory(mp, tdvp);
533 1.10.8.2 yamt if (error)
534 1.10.8.2 yamt return error;
535 1.10.8.2 yamt
536 1.10.8.2 yamt name = "..";
537 1.10.8.2 yamt namelen = 2;
538 1.10.8.2 yamt error = 0;
539 1.10.8.2 yamt
540 1.10.8.2 yamt ump = VTOI(tdvp)->ump;
541 1.10.8.2 yamt
542 1.10.8.2 yamt /* if nodes are equal, it is no use looking */
543 1.10.8.2 yamt KASSERT(udf_compare_icb(&VTOI(fdvp)->loc, &VTOI(tdvp)->loc) != 0);
544 1.10.8.2 yamt
545 1.10.8.2 yamt /* start at destination vnode and walk up the tree */
546 1.10.8.2 yamt vp = tdvp;
547 1.10.8.2 yamt vref(vp);
548 1.10.8.2 yamt
549 1.10.8.2 yamt for (;;) {
550 1.10.8.2 yamt KASSERT(vp != NULL);
551 1.10.8.2 yamt KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
552 1.10.8.2 yamt KASSERT(vp->v_mount == mp);
553 1.10.8.2 yamt KASSERT(vp->v_type == VDIR);
554 1.10.8.2 yamt KASSERT(!udf_rmdired_p(vp));
555 1.10.8.2 yamt
556 1.10.8.2 yamt DPRINTF(NODE, ("udf_gro_genealogy : "
557 1.10.8.2 yamt "fdvp %p, looking at vp %p\n",
558 1.10.8.2 yamt fdvp, vp));
559 1.10.8.2 yamt
560 1.10.8.2 yamt /* sanity check */
561 1.10.8.2 yamt if (vp->v_type != VDIR) {
562 1.10.8.2 yamt vput(vp);
563 1.10.8.2 yamt return ENOTDIR;
564 1.10.8.2 yamt }
565 1.10.8.2 yamt
566 1.10.8.2 yamt /* go down one level */
567 1.10.8.2 yamt error = udf_lookup_name_in_dir(vp, name, namelen,
568 1.10.8.2 yamt &parent_loc, &found);
569 1.10.8.2 yamt DPRINTF(NODE, ("\tlookup of parent '..' resulted in error %d, "
570 1.10.8.2 yamt "found %d\n", error, found));
571 1.10.8.2 yamt if (!found)
572 1.10.8.2 yamt error = ENOENT;
573 1.10.8.2 yamt if (error) {
574 1.10.8.2 yamt vput(vp);
575 1.10.8.2 yamt return error;
576 1.10.8.2 yamt }
577 1.10.8.2 yamt
578 1.10.8.2 yamt /* did we encounter the root node? i.e. loop back */
579 1.10.8.2 yamt if (udf_compare_icb(&parent_loc, &VTOI(vp)->loc) == 0) {
580 1.10.8.2 yamt DPRINTF(NODE, ("ROOT found!\n"));
581 1.10.8.2 yamt vput(vp);
582 1.10.8.2 yamt *intermediate_node_ret = NULL;
583 1.10.8.2 yamt return 0;
584 1.10.8.2 yamt }
585 1.10.8.2 yamt
586 1.10.8.2 yamt /* Did we find that fdvp is an ancestor of tdvp? */
587 1.10.8.2 yamt if (udf_compare_icb(&parent_loc, &VTOI(fdvp)->loc) == 0) {
588 1.10.8.2 yamt DPRINTF(NODE, ("fdvp is ancestor of tdvp\n"));
589 1.10.8.2 yamt *intermediate_node_ret = vp;
590 1.10.8.2 yamt VOP_UNLOCK(vp);
591 1.10.8.2 yamt return 0;
592 1.10.8.2 yamt }
593 1.10.8.2 yamt
594 1.10.8.2 yamt /*
595 1.10.8.2 yamt * Unlock vp so that we can lock the parent, but keep child vp
596 1.10.8.2 yamt * referenced until after we have found the parent, so that
597 1.10.8.2 yamt * parent_node will not be recycled.
598 1.10.8.2 yamt */
599 1.10.8.2 yamt DPRINTF(NODE, ("\tgetting the parent node\n"));
600 1.10.8.2 yamt VOP_UNLOCK(vp);
601 1.10.8.2 yamt error = udf_get_node(ump, &parent_loc, &parent_node);
602 1.10.8.2 yamt vrele(vp);
603 1.10.8.2 yamt if (error)
604 1.10.8.2 yamt return error;
605 1.10.8.2 yamt
606 1.10.8.2 yamt dvp = parent_node->vnode;
607 1.10.8.2 yamt
608 1.10.8.2 yamt /* switch */
609 1.10.8.2 yamt KASSERT(dvp != NULL);
610 1.10.8.2 yamt KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
611 1.10.8.2 yamt vp = dvp;
612 1.10.8.2 yamt
613 1.10.8.2 yamt /* sanity check */
614 1.10.8.2 yamt if (vp->v_type != VDIR) {
615 1.10.8.2 yamt /*
616 1.10.8.2 yamt * Odd, but can happen if we loose the race and the
617 1.10.8.2 yamt * '..' node has been recycled.
618 1.10.8.2 yamt */
619 1.10.8.2 yamt vput(vp);
620 1.10.8.2 yamt return ENOTDIR;
621 1.10.8.2 yamt }
622 1.10.8.2 yamt
623 1.10.8.2 yamt if (udf_rmdired_p(vp)) {
624 1.10.8.2 yamt vput(vp);
625 1.10.8.2 yamt return ENOENT;
626 1.10.8.2 yamt }
627 1.10.8.2 yamt }
628 1.10.8.2 yamt }
629 1.10.8.2 yamt
630 1.10.8.2 yamt
631 1.10.8.2 yamt /*
632 1.10.8.2 yamt * udf_gro_lock_directory: lock the directory vp, but fail if it has been
633 1.10.8.2 yamt * rmdir'd.
634 1.10.8.2 yamt */
635 1.10.8.2 yamt static int
636 1.10.8.2 yamt udf_gro_lock_directory(struct mount *mp, struct vnode *vp)
637 1.10.8.2 yamt {
638 1.10.8.2 yamt
639 1.10.8.2 yamt (void)mp;
640 1.10.8.2 yamt KASSERT(mp != NULL);
641 1.10.8.2 yamt KASSERT(vp != NULL);
642 1.10.8.2 yamt KASSERT(vp->v_mount == mp);
643 1.10.8.2 yamt
644 1.10.8.2 yamt DPRINTF(CALL, ("udf_gro_lock_directory called\n"));
645 1.10.8.2 yamt DPRINTF(LOCKING, ("udf_gro_lock_directory called\n"));
646 1.10.8.2 yamt
647 1.10.8.2 yamt vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
648 1.10.8.2 yamt
649 1.10.8.2 yamt if (udf_rmdired_p(vp)) {
650 1.10.8.2 yamt VOP_UNLOCK(vp);
651 1.10.8.2 yamt return ENOENT;
652 1.10.8.2 yamt }
653 1.10.8.2 yamt
654 1.10.8.2 yamt return 0;
655 1.10.8.2 yamt }
656 1.10.8.2 yamt
657 1.10.8.2 yamt
658 1.10.8.2 yamt static const struct genfs_rename_ops udf_genfs_rename_ops = {
659 1.10.8.2 yamt .gro_directory_empty_p = udf_gro_directory_empty_p,
660 1.10.8.2 yamt .gro_rename_check_possible = udf_gro_rename_check_possible,
661 1.10.8.2 yamt .gro_rename_check_permitted = udf_gro_rename_check_permitted,
662 1.10.8.2 yamt .gro_remove_check_possible = udf_gro_remove_check_possible,
663 1.10.8.2 yamt .gro_remove_check_permitted = udf_gro_remove_check_permitted,
664 1.10.8.2 yamt .gro_rename = udf_gro_rename,
665 1.10.8.2 yamt .gro_remove = udf_gro_remove,
666 1.10.8.2 yamt .gro_lookup = udf_gro_lookup,
667 1.10.8.2 yamt .gro_genealogy = udf_gro_genealogy,
668 1.10.8.2 yamt .gro_lock_directory = udf_gro_lock_directory,
669 1.10.8.2 yamt };
670