1 /* $NetBSD: ufs_vnops.c,v 1.143.2.3 2007/03/10 18:40:49 bouyer Exp $ */
2
3 /*
4 * Copyright (c) 1982, 1986, 1989, 1993, 1995
5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)ufs_vnops.c 8.28 (Berkeley) 7/31/95
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.143.2.3 2007/03/10 18:40:49 bouyer Exp $");
41
42 #if defined(_KERNEL_OPT)
43 #include "opt_ffs.h"
44 #include "opt_quota.h"
45 #include "fs_lfs.h"
46 #endif
47
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/namei.h>
51 #include <sys/resourcevar.h>
52 #include <sys/kernel.h>
53 #include <sys/file.h>
54 #include <sys/stat.h>
55 #include <sys/buf.h>
56 #include <sys/proc.h>
57 #include <sys/mount.h>
58 #include <sys/vnode.h>
59 #include <sys/malloc.h>
60 #include <sys/dirent.h>
61 #include <sys/lockf.h>
62 #include <sys/kauth.h>
63
64 #include <miscfs/specfs/specdev.h>
65 #include <miscfs/fifofs/fifo.h>
66
67 #include <ufs/ufs/quota.h>
68 #include <ufs/ufs/inode.h>
69 #include <ufs/ufs/dir.h>
70 #include <ufs/ufs/ufsmount.h>
71 #include <ufs/ufs/ufs_bswap.h>
72 #include <ufs/ufs/ufs_extern.h>
73 #ifdef UFS_DIRHASH
74 #include <ufs/ufs/dirhash.h>
75 #endif
76 #include <ufs/ext2fs/ext2fs_extern.h>
77 #include <ufs/ffs/ffs_extern.h>
78 #include <ufs/lfs/lfs_extern.h>
79
80 #include <uvm/uvm.h>
81
82 static int ufs_chmod(struct vnode *, int, kauth_cred_t, struct lwp *);
83 static int ufs_chown(struct vnode *, uid_t, gid_t, kauth_cred_t,
84 struct lwp *);
85
86 /*
87 * A virgin directory (no blushing please).
88 */
89 static const struct dirtemplate mastertemplate = {
90 0, 12, DT_DIR, 1, ".",
91 0, DIRBLKSIZ - 12, DT_DIR, 2, ".."
92 };
93
94 /*
95 * Create a regular file
96 */
97 int
98 ufs_create(void *v)
99 {
100 struct vop_create_args /* {
101 struct vnode *a_dvp;
102 struct vnode **a_vpp;
103 struct componentname *a_cnp;
104 struct vattr *a_vap;
105 } */ *ap = v;
106 int error;
107
108 error =
109 ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
110 ap->a_dvp, ap->a_vpp, ap->a_cnp);
111 if (error)
112 return (error);
113 VN_KNOTE(ap->a_dvp, NOTE_WRITE);
114 return (0);
115 }
116
117 /*
118 * Mknod vnode call
119 */
120 /* ARGSUSED */
121 int
122 ufs_mknod(void *v)
123 {
124 struct vop_mknod_args /* {
125 struct vnode *a_dvp;
126 struct vnode **a_vpp;
127 struct componentname *a_cnp;
128 struct vattr *a_vap;
129 } */ *ap = v;
130 struct vattr *vap;
131 struct vnode **vpp;
132 struct inode *ip;
133 int error;
134 struct mount *mp;
135 ino_t ino;
136
137 vap = ap->a_vap;
138 vpp = ap->a_vpp;
139 if ((error =
140 ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode),
141 ap->a_dvp, vpp, ap->a_cnp)) != 0)
142 return (error);
143 VN_KNOTE(ap->a_dvp, NOTE_WRITE);
144 ip = VTOI(*vpp);
145 mp = (*vpp)->v_mount;
146 ino = ip->i_number;
147 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
148 if (vap->va_rdev != VNOVAL) {
149 struct ufsmount *ump = ip->i_ump;
150 /*
151 * Want to be able to use this to make badblock
152 * inodes, so don't truncate the dev number.
153 */
154 if (ump->um_fstype == UFS1)
155 ip->i_ffs1_rdev = ufs_rw32(vap->va_rdev,
156 UFS_MPNEEDSWAP(ump));
157 else
158 ip->i_ffs2_rdev = ufs_rw64(vap->va_rdev,
159 UFS_MPNEEDSWAP(ump));
160 }
161 /*
162 * Remove inode so that it will be reloaded by VFS_VGET and
163 * checked to see if it is an alias of an existing entry in
164 * the inode cache.
165 */
166 vput(*vpp);
167 (*vpp)->v_type = VNON;
168 vgone(*vpp);
169 error = VFS_VGET(mp, ino, vpp);
170 if (error != 0) {
171 *vpp = NULL;
172 return (error);
173 }
174 return (0);
175 }
176
177 /*
178 * Open called.
179 *
180 * Nothing to do.
181 */
182 /* ARGSUSED */
183 int
184 ufs_open(void *v)
185 {
186 struct vop_open_args /* {
187 struct vnode *a_vp;
188 int a_mode;
189 kauth_cred_t a_cred;
190 struct lwp *a_l;
191 } */ *ap = v;
192
193 /*
194 * Files marked append-only must be opened for appending.
195 */
196 if ((VTOI(ap->a_vp)->i_flags & APPEND) &&
197 (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
198 return (EPERM);
199 return (0);
200 }
201
202 /*
203 * Close called.
204 *
205 * Update the times on the inode.
206 */
207 /* ARGSUSED */
208 int
209 ufs_close(void *v)
210 {
211 struct vop_close_args /* {
212 struct vnode *a_vp;
213 int a_fflag;
214 kauth_cred_t a_cred;
215 struct lwp *a_l;
216 } */ *ap = v;
217 struct vnode *vp;
218 struct inode *ip;
219
220 vp = ap->a_vp;
221 ip = VTOI(vp);
222 simple_lock(&vp->v_interlock);
223 if (vp->v_usecount > 1)
224 UFS_ITIMES(vp, NULL, NULL, NULL);
225 simple_unlock(&vp->v_interlock);
226 return (0);
227 }
228
229 int
230 ufs_access(void *v)
231 {
232 struct vop_access_args /* {
233 struct vnode *a_vp;
234 int a_mode;
235 kauth_cred_t a_cred;
236 struct lwp *a_l;
237 } */ *ap = v;
238 struct vnode *vp;
239 struct inode *ip;
240 mode_t mode;
241 #ifdef QUOTA
242 int error;
243 #endif
244
245 vp = ap->a_vp;
246 ip = VTOI(vp);
247 mode = ap->a_mode;
248 /*
249 * Disallow write attempts on read-only file systems;
250 * unless the file is a socket, fifo, or a block or
251 * character device resident on the file system.
252 */
253 if (mode & VWRITE) {
254 switch (vp->v_type) {
255 case VDIR:
256 case VLNK:
257 case VREG:
258 if (vp->v_mount->mnt_flag & MNT_RDONLY)
259 return (EROFS);
260 #ifdef QUOTA
261 if ((error = getinoquota(ip)) != 0)
262 return (error);
263 #endif
264 break;
265 case VBAD:
266 case VBLK:
267 case VCHR:
268 case VSOCK:
269 case VFIFO:
270 case VNON:
271 default:
272 break;
273 }
274 }
275
276 /* If immutable bit set, nobody gets to write it. */
277 if ((mode & VWRITE) && (ip->i_flags & (IMMUTABLE | SF_SNAPSHOT)))
278 return (EPERM);
279
280 return (vaccess(vp->v_type, ip->i_mode & ALLPERMS,
281 ip->i_uid, ip->i_gid, mode, ap->a_cred));
282 }
283
284 /* ARGSUSED */
285 int
286 ufs_getattr(void *v)
287 {
288 struct vop_getattr_args /* {
289 struct vnode *a_vp;
290 struct vattr *a_vap;
291 kauth_cred_t a_cred;
292 struct lwp *a_l;
293 } */ *ap = v;
294 struct vnode *vp;
295 struct inode *ip;
296 struct vattr *vap;
297
298 vp = ap->a_vp;
299 ip = VTOI(vp);
300 vap = ap->a_vap;
301 UFS_ITIMES(vp, NULL, NULL, NULL);
302
303 /*
304 * Copy from inode table
305 */
306 vap->va_fsid = ip->i_dev;
307 vap->va_fileid = ip->i_number;
308 vap->va_mode = ip->i_mode & ALLPERMS;
309 vap->va_nlink = ip->i_ffs_effnlink;
310 vap->va_uid = ip->i_uid;
311 vap->va_gid = ip->i_gid;
312 vap->va_size = vp->v_size;
313 if (ip->i_ump->um_fstype == UFS1) {
314 vap->va_rdev = (dev_t)ufs_rw32(ip->i_ffs1_rdev,
315 UFS_MPNEEDSWAP(ip->i_ump));
316 vap->va_atime.tv_sec = ip->i_ffs1_atime;
317 vap->va_atime.tv_nsec = ip->i_ffs1_atimensec;
318 vap->va_mtime.tv_sec = ip->i_ffs1_mtime;
319 vap->va_mtime.tv_nsec = ip->i_ffs1_mtimensec;
320 vap->va_ctime.tv_sec = ip->i_ffs1_ctime;
321 vap->va_ctime.tv_nsec = ip->i_ffs1_ctimensec;
322 vap->va_birthtime.tv_sec = 0;
323 vap->va_birthtime.tv_nsec = 0;
324 vap->va_bytes = dbtob((u_quad_t)ip->i_ffs1_blocks);
325 } else {
326 vap->va_rdev = (dev_t)ufs_rw64(ip->i_ffs2_rdev,
327 UFS_MPNEEDSWAP(ip->i_ump));
328 vap->va_atime.tv_sec = ip->i_ffs2_atime;
329 vap->va_atime.tv_nsec = ip->i_ffs2_atimensec;
330 vap->va_mtime.tv_sec = ip->i_ffs2_mtime;
331 vap->va_mtime.tv_nsec = ip->i_ffs2_mtimensec;
332 vap->va_ctime.tv_sec = ip->i_ffs2_ctime;
333 vap->va_ctime.tv_nsec = ip->i_ffs2_ctimensec;
334 vap->va_birthtime.tv_sec = ip->i_ffs2_birthtime;
335 vap->va_birthtime.tv_nsec = ip->i_ffs2_birthnsec;
336 vap->va_bytes = dbtob(ip->i_ffs2_blocks);
337 }
338 vap->va_gen = ip->i_gen;
339 vap->va_flags = ip->i_flags;
340
341 /* this doesn't belong here */
342 if (vp->v_type == VBLK)
343 vap->va_blocksize = BLKDEV_IOSIZE;
344 else if (vp->v_type == VCHR)
345 vap->va_blocksize = MAXBSIZE;
346 else
347 vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
348 vap->va_type = vp->v_type;
349 vap->va_filerev = ip->i_modrev;
350 return (0);
351 }
352
353 /*
354 * Set attribute vnode op. called from several syscalls
355 */
356 int
357 ufs_setattr(void *v)
358 {
359 struct vop_setattr_args /* {
360 struct vnode *a_vp;
361 struct vattr *a_vap;
362 kauth_cred_t a_cred;
363 struct lwp *a_l;
364 } */ *ap = v;
365 struct vattr *vap;
366 struct vnode *vp;
367 struct inode *ip;
368 kauth_cred_t cred;
369 struct lwp *l;
370 int error;
371
372 vap = ap->a_vap;
373 vp = ap->a_vp;
374 ip = VTOI(vp);
375 cred = ap->a_cred;
376 l = ap->a_l;
377
378 /*
379 * Check for unsettable attributes.
380 */
381 if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
382 (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
383 (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
384 ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
385 return (EINVAL);
386 }
387 if (vap->va_flags != VNOVAL) {
388 if (vp->v_mount->mnt_flag & MNT_RDONLY)
389 return (EROFS);
390 if (kauth_cred_geteuid(cred) != ip->i_uid &&
391 (error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
392 &l->l_acflag)))
393 return (error);
394 if (kauth_cred_geteuid(cred) == 0) {
395 if ((ip->i_flags & (SF_IMMUTABLE | SF_APPEND)) &&
396 securelevel > 0)
397 return (EPERM);
398 /* Snapshot flag cannot be set or cleared */
399 if ((vap->va_flags & SF_SNAPSHOT) !=
400 (ip->i_flags & SF_SNAPSHOT))
401 return (EPERM);
402 ip->i_flags = vap->va_flags;
403 DIP_ASSIGN(ip, flags, ip->i_flags);
404 } else {
405 if ((ip->i_flags & (SF_IMMUTABLE | SF_APPEND)) ||
406 (vap->va_flags & UF_SETTABLE) != vap->va_flags)
407 return (EPERM);
408 if ((ip->i_flags & SF_SETTABLE) !=
409 (vap->va_flags & SF_SETTABLE))
410 return (EPERM);
411 ip->i_flags &= SF_SETTABLE;
412 ip->i_flags |= (vap->va_flags & UF_SETTABLE);
413 DIP_ASSIGN(ip, flags, ip->i_flags);
414 }
415 ip->i_flag |= IN_CHANGE;
416 if (vap->va_flags & (IMMUTABLE | APPEND))
417 return (0);
418 }
419 if (ip->i_flags & (IMMUTABLE | APPEND))
420 return (EPERM);
421 /*
422 * Go through the fields and update iff not VNOVAL.
423 */
424 if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
425 if (vp->v_mount->mnt_flag & MNT_RDONLY)
426 return (EROFS);
427 error = ufs_chown(vp, vap->va_uid, vap->va_gid, cred, l);
428 if (error)
429 return (error);
430 }
431 if (vap->va_size != VNOVAL) {
432 /*
433 * Disallow write attempts on read-only file systems;
434 * unless the file is a socket, fifo, or a block or
435 * character device resident on the file system.
436 */
437 switch (vp->v_type) {
438 case VDIR:
439 return (EISDIR);
440 case VCHR:
441 case VBLK:
442 case VFIFO:
443 break;
444 case VREG:
445 if (vp->v_mount->mnt_flag & MNT_RDONLY)
446 return (EROFS);
447 if ((ip->i_flags & SF_SNAPSHOT) != 0)
448 return (EPERM);
449 error = UFS_TRUNCATE(vp, vap->va_size, 0, cred, l);
450 if (error)
451 return (error);
452 break;
453 default:
454 return (EOPNOTSUPP);
455 }
456 }
457 ip = VTOI(vp);
458 if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL ||
459 vap->va_birthtime.tv_sec != VNOVAL) {
460 if (vp->v_mount->mnt_flag & MNT_RDONLY)
461 return (EROFS);
462 if ((ip->i_flags & SF_SNAPSHOT) != 0)
463 return (EPERM);
464 if (kauth_cred_geteuid(cred) != ip->i_uid &&
465 (error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
466 &l->l_acflag)) &&
467 ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
468 (error = VOP_ACCESS(vp, VWRITE, cred, l))))
469 return (error);
470 if (vap->va_atime.tv_sec != VNOVAL)
471 if (!(vp->v_mount->mnt_flag & MNT_NOATIME))
472 ip->i_flag |= IN_ACCESS;
473 if (vap->va_mtime.tv_sec != VNOVAL)
474 ip->i_flag |= IN_CHANGE | IN_UPDATE;
475 if (vap->va_birthtime.tv_sec != VNOVAL &&
476 ip->i_ump->um_fstype == UFS2) {
477 ip->i_ffs2_birthtime = vap->va_birthtime.tv_sec;
478 ip->i_ffs2_birthnsec = vap->va_birthtime.tv_nsec;
479 }
480 error = UFS_UPDATE(vp, &vap->va_atime, &vap->va_mtime, 0);
481 if (error)
482 return (error);
483 }
484 error = 0;
485 if (vap->va_mode != (mode_t)VNOVAL) {
486 if (vp->v_mount->mnt_flag & MNT_RDONLY)
487 return (EROFS);
488 if ((ip->i_flags & SF_SNAPSHOT) != 0 &&
489 (vap->va_mode & (S_IXUSR | S_IWUSR | S_IXGRP | S_IWGRP |
490 S_IXOTH | S_IWOTH)))
491 return (EPERM);
492 error = ufs_chmod(vp, (int)vap->va_mode, cred, l);
493 }
494 VN_KNOTE(vp, NOTE_ATTRIB);
495 return (error);
496 }
497
498 /*
499 * Change the mode on a file.
500 * Inode must be locked before calling.
501 */
502 static int
503 ufs_chmod(struct vnode *vp, int mode, kauth_cred_t cred, struct lwp *l)
504 {
505 struct inode *ip;
506 int error, ismember = 0;
507
508 ip = VTOI(vp);
509 if (kauth_cred_geteuid(cred) != ip->i_uid &&
510 (error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
511 &l->l_acflag)))
512 return (error);
513 if (kauth_cred_geteuid(cred)) {
514 if (vp->v_type != VDIR && (mode & S_ISTXT))
515 return (EFTYPE);
516 if ((kauth_cred_ismember_gid(cred, ip->i_gid, &ismember) != 0 ||
517 !ismember) && (mode & ISGID))
518 return (EPERM);
519 }
520 ip->i_mode &= ~ALLPERMS;
521 ip->i_mode |= (mode & ALLPERMS);
522 ip->i_flag |= IN_CHANGE;
523 DIP_ASSIGN(ip, mode, ip->i_mode);
524 return (0);
525 }
526
527 /*
528 * Perform chown operation on inode ip;
529 * inode must be locked prior to call.
530 */
531 static int
532 ufs_chown(struct vnode *vp, uid_t uid, gid_t gid, kauth_cred_t cred,
533 struct lwp *l)
534 {
535 struct inode *ip;
536 int error, ismember = 0;
537 #ifdef QUOTA
538 uid_t ouid;
539 gid_t ogid;
540 int i;
541 int64_t change;
542 #endif
543 ip = VTOI(vp);
544 error = 0;
545
546 if (uid == (uid_t)VNOVAL)
547 uid = ip->i_uid;
548 if (gid == (gid_t)VNOVAL)
549 gid = ip->i_gid;
550 /*
551 * If we don't own the file, are trying to change the owner
552 * of the file, or are not a member of the target group,
553 * the caller's credentials must imply super-user privilege
554 * or the call fails.
555 */
556 if ((kauth_cred_geteuid(cred) != ip->i_uid || uid != ip->i_uid ||
557 (gid != ip->i_gid &&
558 !(kauth_cred_getegid(cred) == gid ||
559 (kauth_cred_ismember_gid(cred, gid, &ismember) == 0 &&
560 ismember)))) &&
561 ((error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
562 &l->l_acflag)) != 0))
563 return (error);
564
565 #ifdef QUOTA
566 ogid = ip->i_gid;
567 ouid = ip->i_uid;
568 if ((error = getinoquota(ip)) != 0)
569 return (error);
570 if (ouid == uid) {
571 dqrele(vp, ip->i_dquot[USRQUOTA]);
572 ip->i_dquot[USRQUOTA] = NODQUOT;
573 }
574 if (ogid == gid) {
575 dqrele(vp, ip->i_dquot[GRPQUOTA]);
576 ip->i_dquot[GRPQUOTA] = NODQUOT;
577 }
578 change = DIP(ip, blocks);
579 (void) chkdq(ip, -change, cred, CHOWN);
580 (void) chkiq(ip, -1, cred, CHOWN);
581 for (i = 0; i < MAXQUOTAS; i++) {
582 dqrele(vp, ip->i_dquot[i]);
583 ip->i_dquot[i] = NODQUOT;
584 }
585 #endif
586 ip->i_gid = gid;
587 DIP_ASSIGN(ip, gid, gid);
588 ip->i_uid = uid;
589 DIP_ASSIGN(ip, uid, uid);
590 #ifdef QUOTA
591 if ((error = getinoquota(ip)) == 0) {
592 if (ouid == uid) {
593 dqrele(vp, ip->i_dquot[USRQUOTA]);
594 ip->i_dquot[USRQUOTA] = NODQUOT;
595 }
596 if (ogid == gid) {
597 dqrele(vp, ip->i_dquot[GRPQUOTA]);
598 ip->i_dquot[GRPQUOTA] = NODQUOT;
599 }
600 if ((error = chkdq(ip, change, cred, CHOWN)) == 0) {
601 if ((error = chkiq(ip, 1, cred, CHOWN)) == 0)
602 goto good;
603 else
604 (void) chkdq(ip, -change, cred, CHOWN|FORCE);
605 }
606 for (i = 0; i < MAXQUOTAS; i++) {
607 dqrele(vp, ip->i_dquot[i]);
608 ip->i_dquot[i] = NODQUOT;
609 }
610 }
611 ip->i_gid = ogid;
612 DIP_ASSIGN(ip, gid, ogid);
613 ip->i_uid = ouid;
614 DIP_ASSIGN(ip, uid, ouid);
615 if (getinoquota(ip) == 0) {
616 if (ouid == uid) {
617 dqrele(vp, ip->i_dquot[USRQUOTA]);
618 ip->i_dquot[USRQUOTA] = NODQUOT;
619 }
620 if (ogid == gid) {
621 dqrele(vp, ip->i_dquot[GRPQUOTA]);
622 ip->i_dquot[GRPQUOTA] = NODQUOT;
623 }
624 (void) chkdq(ip, change, cred, FORCE|CHOWN);
625 (void) chkiq(ip, 1, cred, FORCE|CHOWN);
626 (void) getinoquota(ip);
627 }
628 return (error);
629 good:
630 if (getinoquota(ip))
631 panic("chown: lost quota");
632 #endif /* QUOTA */
633 ip->i_flag |= IN_CHANGE;
634 return (0);
635 }
636
637 int
638 ufs_remove(void *v)
639 {
640 struct vop_remove_args /* {
641 struct vnode *a_dvp;
642 struct vnode *a_vp;
643 struct componentname *a_cnp;
644 } */ *ap = v;
645 struct vnode *vp, *dvp;
646 struct inode *ip;
647 int error;
648
649 vp = ap->a_vp;
650 dvp = ap->a_dvp;
651 ip = VTOI(vp);
652 if (vp->v_type == VDIR || (ip->i_flags & (IMMUTABLE | APPEND)) ||
653 (VTOI(dvp)->i_flags & APPEND))
654 error = EPERM;
655 else
656 error = ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0);
657 VN_KNOTE(vp, NOTE_DELETE);
658 VN_KNOTE(dvp, NOTE_WRITE);
659 if (dvp == vp)
660 vrele(vp);
661 else
662 vput(vp);
663 vput(dvp);
664 return (error);
665 }
666
667 /*
668 * link vnode call
669 */
670 int
671 ufs_link(void *v)
672 {
673 struct vop_link_args /* {
674 struct vnode *a_dvp;
675 struct vnode *a_vp;
676 struct componentname *a_cnp;
677 } */ *ap = v;
678 struct vnode *vp, *dvp;
679 struct componentname *cnp;
680 struct inode *ip;
681 struct direct *newdir;
682 int error;
683
684 dvp = ap->a_dvp;
685 vp = ap->a_vp;
686 cnp = ap->a_cnp;
687 #ifdef DIAGNOSTIC
688 if ((cnp->cn_flags & HASBUF) == 0)
689 panic("ufs_link: no name");
690 #endif
691 if (vp->v_type == VDIR) {
692 VOP_ABORTOP(dvp, cnp);
693 error = EPERM;
694 goto out2;
695 }
696 if (dvp->v_mount != vp->v_mount) {
697 VOP_ABORTOP(dvp, cnp);
698 error = EXDEV;
699 goto out2;
700 }
701 if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE))) {
702 VOP_ABORTOP(dvp, cnp);
703 goto out2;
704 }
705 ip = VTOI(vp);
706 if ((nlink_t)ip->i_nlink >= LINK_MAX) {
707 VOP_ABORTOP(dvp, cnp);
708 error = EMLINK;
709 goto out1;
710 }
711 if (ip->i_flags & (IMMUTABLE | APPEND)) {
712 VOP_ABORTOP(dvp, cnp);
713 error = EPERM;
714 goto out1;
715 }
716 ip->i_ffs_effnlink++;
717 ip->i_nlink++;
718 DIP_ASSIGN(ip, nlink, ip->i_nlink);
719 ip->i_flag |= IN_CHANGE;
720 if (DOINGSOFTDEP(vp))
721 softdep_change_linkcnt(ip);
722 error = UFS_UPDATE(vp, NULL, NULL, UPDATE_DIROP);
723 if (!error) {
724 newdir = pool_get(&ufs_direct_pool, PR_WAITOK);
725 ufs_makedirentry(ip, cnp, newdir);
726 error = ufs_direnter(dvp, vp, newdir, cnp, NULL);
727 pool_put(&ufs_direct_pool, newdir);
728 }
729 if (error) {
730 ip->i_ffs_effnlink--;
731 ip->i_nlink--;
732 DIP_ASSIGN(ip, nlink, ip->i_nlink);
733 ip->i_flag |= IN_CHANGE;
734 if (DOINGSOFTDEP(vp))
735 softdep_change_linkcnt(ip);
736 }
737 PNBUF_PUT(cnp->cn_pnbuf);
738 out1:
739 if (dvp != vp)
740 VOP_UNLOCK(vp, 0);
741 out2:
742 VN_KNOTE(vp, NOTE_LINK);
743 VN_KNOTE(dvp, NOTE_WRITE);
744 vput(dvp);
745 return (error);
746 }
747
748 /*
749 * whiteout vnode call
750 */
751 int
752 ufs_whiteout(void *v)
753 {
754 struct vop_whiteout_args /* {
755 struct vnode *a_dvp;
756 struct componentname *a_cnp;
757 int a_flags;
758 } */ *ap = v;
759 struct vnode *dvp = ap->a_dvp;
760 struct componentname *cnp = ap->a_cnp;
761 struct direct *newdir;
762 int error;
763 struct ufsmount *ump = VFSTOUFS(dvp->v_mount);
764
765 error = 0;
766 switch (ap->a_flags) {
767 case LOOKUP:
768 /* 4.4 format directories support whiteout operations */
769 if (ump->um_maxsymlinklen > 0)
770 return (0);
771 return (EOPNOTSUPP);
772
773 case CREATE:
774 /* create a new directory whiteout */
775 #ifdef DIAGNOSTIC
776 if ((cnp->cn_flags & SAVENAME) == 0)
777 panic("ufs_whiteout: missing name");
778 if (ump->um_maxsymlinklen <= 0)
779 panic("ufs_whiteout: old format filesystem");
780 #endif
781
782 newdir = pool_get(&ufs_direct_pool, PR_WAITOK);
783 newdir->d_ino = WINO;
784 newdir->d_namlen = cnp->cn_namelen;
785 memcpy(newdir->d_name, cnp->cn_nameptr,
786 (size_t)cnp->cn_namelen);
787 newdir->d_name[cnp->cn_namelen] = '\0';
788 newdir->d_type = DT_WHT;
789 error = ufs_direnter(dvp, NULL, newdir, cnp, NULL);
790 pool_put(&ufs_direct_pool, newdir);
791 break;
792
793 case DELETE:
794 /* remove an existing directory whiteout */
795 #ifdef DIAGNOSTIC
796 if (ump->um_maxsymlinklen <= 0)
797 panic("ufs_whiteout: old format filesystem");
798 #endif
799
800 cnp->cn_flags &= ~DOWHITEOUT;
801 error = ufs_dirremove(dvp, NULL, cnp->cn_flags, 0);
802 break;
803 default:
804 panic("ufs_whiteout: unknown op");
805 /* NOTREACHED */
806 }
807 if (cnp->cn_flags & HASBUF) {
808 PNBUF_PUT(cnp->cn_pnbuf);
809 cnp->cn_flags &= ~HASBUF;
810 }
811 return (error);
812 }
813
814
815 /*
816 * Rename system call.
817 * rename("foo", "bar");
818 * is essentially
819 * unlink("bar");
820 * link("foo", "bar");
821 * unlink("foo");
822 * but ``atomically''. Can't do full commit without saving state in the
823 * inode on disk which isn't feasible at this time. Best we can do is
824 * always guarantee the target exists.
825 *
826 * Basic algorithm is:
827 *
828 * 1) Bump link count on source while we're linking it to the
829 * target. This also ensure the inode won't be deleted out
830 * from underneath us while we work (it may be truncated by
831 * a concurrent `trunc' or `open' for creation).
832 * 2) Link source to destination. If destination already exists,
833 * delete it first.
834 * 3) Unlink source reference to inode if still around. If a
835 * directory was moved and the parent of the destination
836 * is different from the source, patch the ".." entry in the
837 * directory.
838 */
839 int
840 ufs_rename(void *v)
841 {
842 struct vop_rename_args /* {
843 struct vnode *a_fdvp;
844 struct vnode *a_fvp;
845 struct componentname *a_fcnp;
846 struct vnode *a_tdvp;
847 struct vnode *a_tvp;
848 struct componentname *a_tcnp;
849 } */ *ap = v;
850 struct vnode *tvp, *tdvp, *fvp, *fdvp;
851 struct componentname *tcnp, *fcnp;
852 struct inode *ip, *xp, *dp;
853 struct direct *newdir;
854 int doingdirectory, oldparent, newparent, error;
855
856 tvp = ap->a_tvp;
857 tdvp = ap->a_tdvp;
858 fvp = ap->a_fvp;
859 fdvp = ap->a_fdvp;
860 tcnp = ap->a_tcnp;
861 fcnp = ap->a_fcnp;
862 doingdirectory = oldparent = newparent = error = 0;
863
864 #ifdef DIAGNOSTIC
865 if ((tcnp->cn_flags & HASBUF) == 0 ||
866 (fcnp->cn_flags & HASBUF) == 0)
867 panic("ufs_rename: no name");
868 #endif
869 /*
870 * Check for cross-device rename.
871 */
872 if ((fvp->v_mount != tdvp->v_mount) ||
873 (tvp && (fvp->v_mount != tvp->v_mount))) {
874 error = EXDEV;
875 abortit:
876 VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
877 if (tdvp == tvp)
878 vrele(tdvp);
879 else
880 vput(tdvp);
881 if (tvp)
882 vput(tvp);
883 VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
884 vrele(fdvp);
885 vrele(fvp);
886 return (error);
887 }
888
889 /*
890 * Check if just deleting a link name.
891 */
892 if (tvp && ((VTOI(tvp)->i_flags & (IMMUTABLE | APPEND)) ||
893 (VTOI(tdvp)->i_flags & APPEND))) {
894 error = EPERM;
895 goto abortit;
896 }
897 if (fvp == tvp) {
898 if (fvp->v_type == VDIR) {
899 error = EINVAL;
900 goto abortit;
901 }
902
903 /* Release destination completely. */
904 VOP_ABORTOP(tdvp, tcnp);
905 vput(tdvp);
906 vput(tvp);
907
908 /* Delete source. */
909 vrele(fvp);
910 fcnp->cn_flags &= ~(MODMASK | SAVESTART);
911 fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
912 fcnp->cn_nameiop = DELETE;
913 vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY);
914 if ((error = relookup(fdvp, &fvp, fcnp))) {
915 vput(fdvp);
916 return (error);
917 }
918 return (VOP_REMOVE(fdvp, fvp, fcnp));
919 }
920 if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0)
921 goto abortit;
922 dp = VTOI(fdvp);
923 ip = VTOI(fvp);
924 if ((nlink_t) ip->i_nlink >= LINK_MAX) {
925 VOP_UNLOCK(fvp, 0);
926 error = EMLINK;
927 goto abortit;
928 }
929 if ((ip->i_flags & (IMMUTABLE | APPEND)) ||
930 (dp->i_flags & APPEND)) {
931 VOP_UNLOCK(fvp, 0);
932 error = EPERM;
933 goto abortit;
934 }
935 if ((ip->i_mode & IFMT) == IFDIR) {
936 /*
937 * Avoid ".", "..", and aliases of "." for obvious reasons.
938 */
939 if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
940 dp == ip ||
941 (fcnp->cn_flags & ISDOTDOT) ||
942 (tcnp->cn_flags & ISDOTDOT) ||
943 (ip->i_flag & IN_RENAME)) {
944 VOP_UNLOCK(fvp, 0);
945 error = EINVAL;
946 goto abortit;
947 }
948 ip->i_flag |= IN_RENAME;
949 oldparent = dp->i_number;
950 doingdirectory = 1;
951 }
952 VN_KNOTE(fdvp, NOTE_WRITE); /* XXXLUKEM/XXX: right place? */
953
954 /*
955 * When the target exists, both the directory
956 * and target vnodes are returned locked.
957 */
958 dp = VTOI(tdvp);
959 xp = NULL;
960 if (tvp)
961 xp = VTOI(tvp);
962
963 /*
964 * 1) Bump link count while we're moving stuff
965 * around. If we crash somewhere before
966 * completing our work, the link count
967 * may be wrong, but correctable.
968 */
969 ip->i_ffs_effnlink++;
970 ip->i_nlink++;
971 DIP_ASSIGN(ip, nlink, ip->i_nlink);
972 ip->i_flag |= IN_CHANGE;
973 if (DOINGSOFTDEP(fvp))
974 softdep_change_linkcnt(ip);
975 if ((error = UFS_UPDATE(fvp, NULL, NULL, UPDATE_DIROP)) != 0) {
976 VOP_UNLOCK(fvp, 0);
977 goto bad;
978 }
979
980 /*
981 * If ".." must be changed (ie the directory gets a new
982 * parent) then the source directory must not be in the
983 * directory hierarchy above the target, as this would
984 * orphan everything below the source directory. Also
985 * the user must have write permission in the source so
986 * as to be able to change "..". We must repeat the call
987 * to namei, as the parent directory is unlocked by the
988 * call to checkpath().
989 */
990 error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_lwp);
991 VOP_UNLOCK(fvp, 0);
992 if (oldparent != dp->i_number)
993 newparent = dp->i_number;
994 if (doingdirectory && newparent) {
995 if (error) /* write access check above */
996 goto bad;
997 if (xp != NULL)
998 vput(tvp);
999 vref(tdvp); /* compensate for the ref checkpath loses */
1000 if ((error = ufs_checkpath(ip, dp, tcnp->cn_cred)) != 0) {
1001 vrele(tdvp);
1002 goto out;
1003 }
1004 tcnp->cn_flags &= ~SAVESTART;
1005 vn_lock(tdvp, LK_EXCLUSIVE | LK_RETRY);
1006 error = relookup(tdvp, &tvp, tcnp);
1007 if (error != 0) {
1008 vput(tdvp);
1009 goto out;
1010 }
1011 dp = VTOI(tdvp);
1012 xp = NULL;
1013 if (tvp)
1014 xp = VTOI(tvp);
1015 }
1016 /*
1017 * 2) If target doesn't exist, link the target
1018 * to the source and unlink the source.
1019 * Otherwise, rewrite the target directory
1020 * entry to reference the source inode and
1021 * expunge the original entry's existence.
1022 */
1023 if (xp == NULL) {
1024 if (dp->i_dev != ip->i_dev)
1025 panic("rename: EXDEV");
1026 /*
1027 * Account for ".." in new directory.
1028 * When source and destination have the same
1029 * parent we don't fool with the link count.
1030 */
1031 if (doingdirectory && newparent) {
1032 if ((nlink_t)dp->i_nlink >= LINK_MAX) {
1033 error = EMLINK;
1034 goto bad;
1035 }
1036 dp->i_ffs_effnlink++;
1037 dp->i_nlink++;
1038 DIP_ASSIGN(dp, nlink, dp->i_nlink);
1039 dp->i_flag |= IN_CHANGE;
1040 if (DOINGSOFTDEP(tdvp))
1041 softdep_change_linkcnt(dp);
1042 if ((error = UFS_UPDATE(tdvp, NULL, NULL,
1043 UPDATE_DIROP)) != 0) {
1044 dp->i_ffs_effnlink--;
1045 dp->i_nlink--;
1046 DIP_ASSIGN(dp, nlink, dp->i_nlink);
1047 dp->i_flag |= IN_CHANGE;
1048 if (DOINGSOFTDEP(tdvp))
1049 softdep_change_linkcnt(dp);
1050 goto bad;
1051 }
1052 }
1053 newdir = pool_get(&ufs_direct_pool, PR_WAITOK);
1054 ufs_makedirentry(ip, tcnp, newdir);
1055 error = ufs_direnter(tdvp, NULL, newdir, tcnp, NULL);
1056 pool_put(&ufs_direct_pool, newdir);
1057 if (error != 0) {
1058 if (doingdirectory && newparent) {
1059 dp->i_ffs_effnlink--;
1060 dp->i_nlink--;
1061 DIP_ASSIGN(dp, nlink, dp->i_nlink);
1062 dp->i_flag |= IN_CHANGE;
1063 if (DOINGSOFTDEP(tdvp))
1064 softdep_change_linkcnt(dp);
1065 (void)UFS_UPDATE(tdvp, NULL, NULL,
1066 UPDATE_WAIT|UPDATE_DIROP);
1067 }
1068 goto bad;
1069 }
1070 VN_KNOTE(tdvp, NOTE_WRITE);
1071 vput(tdvp);
1072 } else {
1073 if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev)
1074 panic("rename: EXDEV");
1075 /*
1076 * Short circuit rename(foo, foo).
1077 */
1078 if (xp->i_number == ip->i_number)
1079 panic("rename: same file");
1080 /*
1081 * If the parent directory is "sticky", then the user must
1082 * own the parent directory, or the destination of the rename,
1083 * otherwise the destination may not be changed (except by
1084 * root). This implements append-only directories.
1085 */
1086 if ((dp->i_mode & S_ISTXT) && kauth_cred_geteuid(tcnp->cn_cred) != 0 &&
1087 kauth_cred_geteuid(tcnp->cn_cred) != dp->i_uid &&
1088 xp->i_uid != kauth_cred_geteuid(tcnp->cn_cred)) {
1089 error = EPERM;
1090 goto bad;
1091 }
1092 /*
1093 * Target must be empty if a directory and have no links
1094 * to it. Also, ensure source and target are compatible
1095 * (both directories, or both not directories).
1096 */
1097 if ((xp->i_mode & IFMT) == IFDIR) {
1098 if (xp->i_ffs_effnlink > 2 ||
1099 !ufs_dirempty(xp, dp->i_number, tcnp->cn_cred)) {
1100 error = ENOTEMPTY;
1101 goto bad;
1102 }
1103 if (!doingdirectory) {
1104 error = ENOTDIR;
1105 goto bad;
1106 }
1107 cache_purge(tdvp);
1108 } else if (doingdirectory) {
1109 error = EISDIR;
1110 goto bad;
1111 }
1112 if ((error = ufs_dirrewrite(dp, xp, ip->i_number,
1113 IFTODT(ip->i_mode), doingdirectory && newparent ?
1114 newparent : doingdirectory, IN_CHANGE | IN_UPDATE)) != 0)
1115 goto bad;
1116 if (doingdirectory) {
1117 if (!newparent) {
1118 dp->i_ffs_effnlink--;
1119 if (DOINGSOFTDEP(tdvp))
1120 softdep_change_linkcnt(dp);
1121 }
1122 xp->i_ffs_effnlink--;
1123 if (DOINGSOFTDEP(tvp))
1124 softdep_change_linkcnt(xp);
1125 }
1126 if (doingdirectory && !DOINGSOFTDEP(tvp)) {
1127 /*
1128 * Truncate inode. The only stuff left in the directory
1129 * is "." and "..". The "." reference is inconsequential
1130 * since we are quashing it. We have removed the "."
1131 * reference and the reference in the parent directory,
1132 * but there may be other hard links. The soft
1133 * dependency code will arrange to do these operations
1134 * after the parent directory entry has been deleted on
1135 * disk, so when running with that code we avoid doing
1136 * them now.
1137 */
1138 if (!newparent) {
1139 dp->i_nlink--;
1140 DIP_ASSIGN(dp, nlink, dp->i_nlink);
1141 dp->i_flag |= IN_CHANGE;
1142 }
1143 xp->i_nlink--;
1144 DIP_ASSIGN(xp, nlink, xp->i_nlink);
1145 xp->i_flag |= IN_CHANGE;
1146 if ((error = UFS_TRUNCATE(tvp, (off_t)0, IO_SYNC,
1147 tcnp->cn_cred, tcnp->cn_lwp)))
1148 goto bad;
1149 }
1150 VN_KNOTE(tdvp, NOTE_WRITE);
1151 vput(tdvp);
1152 VN_KNOTE(tvp, NOTE_DELETE);
1153 vput(tvp);
1154 xp = NULL;
1155 }
1156
1157 /*
1158 * 3) Unlink the source.
1159 */
1160 fcnp->cn_flags &= ~(MODMASK | SAVESTART);
1161 fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
1162 vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY);
1163 if ((error = relookup(fdvp, &fvp, fcnp))) {
1164 vput(fdvp);
1165 vrele(ap->a_fvp);
1166 return (error);
1167 }
1168 if (fvp != NULL) {
1169 xp = VTOI(fvp);
1170 dp = VTOI(fdvp);
1171 } else {
1172 /*
1173 * From name has disappeared.
1174 */
1175 if (doingdirectory)
1176 panic("rename: lost dir entry");
1177 vrele(ap->a_fvp);
1178 return (0);
1179 }
1180 /*
1181 * Ensure that the directory entry still exists and has not
1182 * changed while the new name has been entered. If the source is
1183 * a file then the entry may have been unlinked or renamed. In
1184 * either case there is no further work to be done. If the source
1185 * is a directory then it cannot have been rmdir'ed; The IRENAME
1186 * flag ensures that it cannot be moved by another rename or removed
1187 * by a rmdir.
1188 */
1189 if (xp != ip) {
1190 if (doingdirectory)
1191 panic("rename: lost dir entry");
1192 } else {
1193 /*
1194 * If the source is a directory with a
1195 * new parent, the link count of the old
1196 * parent directory must be decremented
1197 * and ".." set to point to the new parent.
1198 */
1199 if (doingdirectory && newparent) {
1200 KASSERT(dp != NULL);
1201 xp->i_offset = mastertemplate.dot_reclen;
1202 ufs_dirrewrite(xp, dp, newparent, DT_DIR, 0, IN_CHANGE);
1203 cache_purge(fdvp);
1204 }
1205 error = ufs_dirremove(fdvp, xp, fcnp->cn_flags, 0);
1206 xp->i_flag &= ~IN_RENAME;
1207 }
1208 VN_KNOTE(fvp, NOTE_RENAME);
1209 if (dp)
1210 vput(fdvp);
1211 if (xp)
1212 vput(fvp);
1213 vrele(ap->a_fvp);
1214 return (error);
1215
1216 /* exit routines from steps 1 & 2 */
1217 bad:
1218 if (xp)
1219 vput(ITOV(xp));
1220 vput(ITOV(dp));
1221 out:
1222 if (doingdirectory)
1223 ip->i_flag &= ~IN_RENAME;
1224 if (vn_lock(fvp, LK_EXCLUSIVE) == 0) {
1225 ip->i_ffs_effnlink--;
1226 ip->i_nlink--;
1227 DIP_ASSIGN(ip, nlink, ip->i_nlink);
1228 ip->i_flag |= IN_CHANGE;
1229 ip->i_flag &= ~IN_RENAME;
1230 if (DOINGSOFTDEP(fvp))
1231 softdep_change_linkcnt(ip);
1232 vput(fvp);
1233 } else
1234 vrele(fvp);
1235 vrele(fdvp);
1236 return (error);
1237 }
1238
1239 /*
1240 * Mkdir system call
1241 */
1242 int
1243 ufs_mkdir(void *v)
1244 {
1245 struct vop_mkdir_args /* {
1246 struct vnode *a_dvp;
1247 struct vnode **a_vpp;
1248 struct componentname *a_cnp;
1249 struct vattr *a_vap;
1250 } */ *ap = v;
1251 struct vnode *dvp = ap->a_dvp, *tvp;
1252 struct vattr *vap = ap->a_vap;
1253 struct componentname *cnp = ap->a_cnp;
1254 struct inode *ip, *dp = VTOI(dvp);
1255 struct buf *bp;
1256 struct dirtemplate dirtemplate;
1257 struct direct *newdir;
1258 int error, dmode, blkoff;
1259 struct ufsmount *ump = dp->i_ump;
1260 int dirblksiz = ump->um_dirblksiz;
1261
1262 #ifdef DIAGNOSTIC
1263 if ((cnp->cn_flags & HASBUF) == 0)
1264 panic("ufs_mkdir: no name");
1265 #endif
1266 if ((nlink_t)dp->i_nlink >= LINK_MAX) {
1267 error = EMLINK;
1268 goto out;
1269 }
1270 dmode = vap->va_mode & ACCESSPERMS;
1271 dmode |= IFDIR;
1272 /*
1273 * Must simulate part of ufs_makeinode here to acquire the inode,
1274 * but not have it entered in the parent directory. The entry is
1275 * made later after writing "." and ".." entries.
1276 */
1277 if ((error = UFS_VALLOC(dvp, dmode, cnp->cn_cred, ap->a_vpp)) != 0)
1278 goto out;
1279 tvp = *ap->a_vpp;
1280 ip = VTOI(tvp);
1281 ip->i_uid = kauth_cred_geteuid(cnp->cn_cred);
1282 DIP_ASSIGN(ip, uid, ip->i_uid);
1283 ip->i_gid = dp->i_gid;
1284 DIP_ASSIGN(ip, gid, ip->i_gid);
1285 #ifdef QUOTA
1286 if ((error = getinoquota(ip)) ||
1287 (error = chkiq(ip, 1, cnp->cn_cred, 0))) {
1288 PNBUF_PUT(cnp->cn_pnbuf);
1289 UFS_VFREE(tvp, ip->i_number, dmode);
1290 vput(tvp);
1291 vput(dvp);
1292 return (error);
1293 }
1294 #endif
1295 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
1296 ip->i_mode = dmode;
1297 DIP_ASSIGN(ip, mode, dmode);
1298 tvp->v_type = VDIR; /* Rest init'd in getnewvnode(). */
1299 ip->i_ffs_effnlink = 2;
1300 ip->i_nlink = 2;
1301 DIP_ASSIGN(ip, nlink, 2);
1302 if (DOINGSOFTDEP(tvp))
1303 softdep_change_linkcnt(ip);
1304 if (cnp->cn_flags & ISWHITEOUT) {
1305 ip->i_flags |= UF_OPAQUE;
1306 DIP_ASSIGN(ip, flags, ip->i_flags);
1307 }
1308
1309 /*
1310 * Bump link count in parent directory to reflect work done below.
1311 * Should be done before reference is created so cleanup is
1312 * possible if we crash.
1313 */
1314 dp->i_ffs_effnlink++;
1315 dp->i_nlink++;
1316 DIP_ASSIGN(dp, nlink, dp->i_nlink);
1317 dp->i_flag |= IN_CHANGE;
1318 if (DOINGSOFTDEP(dvp))
1319 softdep_change_linkcnt(dp);
1320 if ((error = UFS_UPDATE(dvp, NULL, NULL, UPDATE_DIROP)) != 0)
1321 goto bad;
1322
1323 /*
1324 * Initialize directory with "." and ".." from static template.
1325 */
1326 dirtemplate = mastertemplate;
1327 dirtemplate.dotdot_reclen = dirblksiz - dirtemplate.dot_reclen;
1328 dirtemplate.dot_ino = ufs_rw32(ip->i_number, UFS_MPNEEDSWAP(ump));
1329 dirtemplate.dotdot_ino = ufs_rw32(dp->i_number, UFS_MPNEEDSWAP(ump));
1330 dirtemplate.dot_reclen = ufs_rw16(dirtemplate.dot_reclen,
1331 UFS_MPNEEDSWAP(ump));
1332 dirtemplate.dotdot_reclen = ufs_rw16(dirtemplate.dotdot_reclen,
1333 UFS_MPNEEDSWAP(ump));
1334 if (ump->um_maxsymlinklen <= 0) {
1335 #if BYTE_ORDER == LITTLE_ENDIAN
1336 if (UFS_MPNEEDSWAP(ump) == 0)
1337 #else
1338 if (UFS_MPNEEDSWAP(ump) != 0)
1339 #endif
1340 {
1341 dirtemplate.dot_type = dirtemplate.dot_namlen;
1342 dirtemplate.dotdot_type = dirtemplate.dotdot_namlen;
1343 dirtemplate.dot_namlen = dirtemplate.dotdot_namlen = 0;
1344 } else
1345 dirtemplate.dot_type = dirtemplate.dotdot_type = 0;
1346 }
1347 if ((error = UFS_BALLOC(tvp, (off_t)0, dirblksiz, cnp->cn_cred,
1348 B_CLRBUF, &bp)) != 0)
1349 goto bad;
1350 ip->i_size = dirblksiz;
1351 DIP_ASSIGN(ip, size, dirblksiz);
1352 ip->i_flag |= IN_CHANGE | IN_UPDATE;
1353 uvm_vnp_setsize(tvp, ip->i_size);
1354 memcpy((caddr_t)bp->b_data, (caddr_t)&dirtemplate, sizeof dirtemplate);
1355 if (DOINGSOFTDEP(tvp)) {
1356 /*
1357 * Ensure that the entire newly allocated block is a
1358 * valid directory so that future growth within the
1359 * block does not have to ensure that the block is
1360 * written before the inode.
1361 */
1362 blkoff = dirblksiz;
1363 while (blkoff < bp->b_bcount) {
1364 ((struct direct *)
1365 (bp->b_data + blkoff))->d_reclen = dirblksiz;
1366 blkoff += dirblksiz;
1367 }
1368 }
1369 /*
1370 * Directory set up, now install it's entry in the parent directory.
1371 *
1372 * If we are not doing soft dependencies, then we must write out the
1373 * buffer containing the new directory body before entering the new
1374 * name in the parent. If we are doing soft dependencies, then the
1375 * buffer containing the new directory body will be passed to and
1376 * released in the soft dependency code after the code has attached
1377 * an appropriate ordering dependency to the buffer which ensures that
1378 * the buffer is written before the new name is written in the parent.
1379 */
1380 if (!DOINGSOFTDEP(tvp) && ((error = VOP_BWRITE(bp)) != 0))
1381 goto bad;
1382 if ((error = UFS_UPDATE(tvp, NULL, NULL, UPDATE_DIROP)) != 0) {
1383 if (DOINGSOFTDEP(tvp))
1384 (void)VOP_BWRITE(bp);
1385 goto bad;
1386 }
1387 newdir = pool_get(&ufs_direct_pool, PR_WAITOK);
1388 ufs_makedirentry(ip, cnp, newdir);
1389 error = ufs_direnter(dvp, tvp, newdir, cnp, bp);
1390 pool_put(&ufs_direct_pool, newdir);
1391 bad:
1392 if (error == 0) {
1393 VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
1394 } else {
1395 dp->i_ffs_effnlink--;
1396 dp->i_nlink--;
1397 DIP_ASSIGN(dp, nlink, dp->i_nlink);
1398 dp->i_flag |= IN_CHANGE;
1399 if (DOINGSOFTDEP(dvp))
1400 softdep_change_linkcnt(dp);
1401 /*
1402 * No need to do an explicit UFS_TRUNCATE here, vrele will
1403 * do this for us because we set the link count to 0.
1404 */
1405 ip->i_ffs_effnlink = 0;
1406 ip->i_nlink = 0;
1407 DIP_ASSIGN(ip, nlink, 0);
1408 ip->i_flag |= IN_CHANGE;
1409 #ifdef LFS
1410 /* If IN_ADIROP, account for it */
1411 lfs_unmark_vnode(tvp);
1412 #endif
1413 if (DOINGSOFTDEP(tvp))
1414 softdep_change_linkcnt(ip);
1415 vput(tvp);
1416 }
1417 out:
1418 PNBUF_PUT(cnp->cn_pnbuf);
1419 vput(dvp);
1420 return (error);
1421 }
1422
1423 /*
1424 * Rmdir system call.
1425 */
1426 int
1427 ufs_rmdir(void *v)
1428 {
1429 struct vop_rmdir_args /* {
1430 struct vnode *a_dvp;
1431 struct vnode *a_vp;
1432 struct componentname *a_cnp;
1433 } */ *ap = v;
1434 struct vnode *vp, *dvp;
1435 struct componentname *cnp;
1436 struct inode *ip, *dp;
1437 int error;
1438
1439 vp = ap->a_vp;
1440 dvp = ap->a_dvp;
1441 cnp = ap->a_cnp;
1442 ip = VTOI(vp);
1443 dp = VTOI(dvp);
1444 /*
1445 * No rmdir "." or of mounted directories please.
1446 */
1447 if (dp == ip || vp->v_mountedhere != NULL) {
1448 if (dp == ip)
1449 vrele(vp);
1450 else
1451 vput(vp);
1452 vput(vp);
1453 return (EINVAL);
1454 }
1455 /*
1456 * Do not remove a directory that is in the process of being renamed.
1457 * Verify that the directory is empty (and valid). (Rmdir ".." won't
1458 * be valid since ".." will contain a reference to the current
1459 * directory and thus be non-empty.)
1460 */
1461 error = 0;
1462 if (ip->i_flag & IN_RENAME) {
1463 error = EINVAL;
1464 goto out;
1465 }
1466 if (ip->i_ffs_effnlink != 2 ||
1467 !ufs_dirempty(ip, dp->i_number, cnp->cn_cred)) {
1468 error = ENOTEMPTY;
1469 goto out;
1470 }
1471 if ((dp->i_flags & APPEND) ||
1472 (ip->i_flags & (IMMUTABLE | APPEND))) {
1473 error = EPERM;
1474 goto out;
1475 }
1476 /*
1477 * Delete reference to directory before purging
1478 * inode. If we crash in between, the directory
1479 * will be reattached to lost+found,
1480 */
1481 if (DOINGSOFTDEP(vp)) {
1482 dp->i_ffs_effnlink--;
1483 ip->i_ffs_effnlink--;
1484 softdep_change_linkcnt(dp);
1485 softdep_change_linkcnt(ip);
1486 }
1487 error = ufs_dirremove(dvp, ip, cnp->cn_flags, 1);
1488 if (error) {
1489 if (DOINGSOFTDEP(vp)) {
1490 dp->i_ffs_effnlink++;
1491 ip->i_ffs_effnlink++;
1492 softdep_change_linkcnt(dp);
1493 softdep_change_linkcnt(ip);
1494 }
1495 goto out;
1496 }
1497 VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
1498 cache_purge(dvp);
1499 /*
1500 * Truncate inode. The only stuff left in the directory is "." and
1501 * "..". The "." reference is inconsequential since we're quashing
1502 * it. The soft dependency code will arrange to do these operations
1503 * after the parent directory entry has been deleted on disk, so
1504 * when running with that code we avoid doing them now.
1505 */
1506 if (!DOINGSOFTDEP(vp)) {
1507 dp->i_nlink--;
1508 dp->i_ffs_effnlink--;
1509 DIP_ASSIGN(dp, nlink, dp->i_nlink);
1510 dp->i_flag |= IN_CHANGE;
1511 ip->i_nlink--;
1512 ip->i_ffs_effnlink--;
1513 DIP_ASSIGN(ip, nlink, ip->i_nlink);
1514 ip->i_flag |= IN_CHANGE;
1515 error = UFS_TRUNCATE(vp, (off_t)0, IO_SYNC, cnp->cn_cred,
1516 cnp->cn_lwp);
1517 }
1518 cache_purge(vp);
1519 #ifdef UFS_DIRHASH
1520 if (ip->i_dirhash != NULL)
1521 ufsdirhash_free(ip);
1522 #endif
1523 out:
1524 VN_KNOTE(vp, NOTE_DELETE);
1525 vput(dvp);
1526 vput(vp);
1527 return (error);
1528 }
1529
1530 /*
1531 * symlink -- make a symbolic link
1532 */
1533 int
1534 ufs_symlink(void *v)
1535 {
1536 struct vop_symlink_args /* {
1537 struct vnode *a_dvp;
1538 struct vnode **a_vpp;
1539 struct componentname *a_cnp;
1540 struct vattr *a_vap;
1541 char *a_target;
1542 } */ *ap = v;
1543 struct vnode *vp, **vpp;
1544 struct inode *ip;
1545 int len, error;
1546
1547 vpp = ap->a_vpp;
1548 error = ufs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp,
1549 vpp, ap->a_cnp);
1550 if (error)
1551 return (error);
1552 VN_KNOTE(ap->a_dvp, NOTE_WRITE);
1553 vp = *vpp;
1554 len = strlen(ap->a_target);
1555 ip = VTOI(vp);
1556 if (len < ip->i_ump->um_maxsymlinklen) {
1557 memcpy((char *)SHORTLINK(ip), ap->a_target, len);
1558 ip->i_size = len;
1559 DIP_ASSIGN(ip, size, len);
1560 uvm_vnp_setsize(vp, ip->i_size);
1561 ip->i_flag |= IN_CHANGE | IN_UPDATE;
1562 } else
1563 error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0,
1564 UIO_SYSSPACE, IO_NODELOCKED, ap->a_cnp->cn_cred, NULL,
1565 NULL);
1566 if (error)
1567 vput(vp);
1568 return (error);
1569 }
1570
1571 /*
1572 * Vnode op for reading directories.
1573 *
1574 * This routine handles converting from the on-disk directory format
1575 * "struct direct" to the in-memory format "struct dirent" as well as
1576 * byte swapping the entries if necessary.
1577 */
1578 int
1579 ufs_readdir(void *v)
1580 {
1581 struct vop_readdir_args /* {
1582 struct vnode *a_vp;
1583 struct uio *a_uio;
1584 kauth_cred_t a_cred;
1585 int *a_eofflag;
1586 off_t **a_cookies;
1587 int *ncookies;
1588 } */ *ap = v;
1589 struct vnode *vp = ap->a_vp;
1590 struct direct *cdp, *ecdp;
1591 struct dirent *ndp;
1592 char *cdbuf, *ndbuf, *endp;
1593 struct uio auio, *uio;
1594 struct iovec aiov;
1595 int error;
1596 size_t count, ccount, rcount;
1597 off_t off, *ccp;
1598 off_t startoff;
1599 size_t skipbytes;
1600 struct ufsmount *ump = VFSTOUFS(vp->v_mount);
1601 int nswap = UFS_MPNEEDSWAP(ump);
1602 #if BYTE_ORDER == LITTLE_ENDIAN
1603 int needswap = ump->um_maxsymlinklen <= 0 && nswap == 0;
1604 #else
1605 int needswap = ump->um_maxsymlinklen <= 0 && nswap != 0;
1606 #endif
1607 uio = ap->a_uio;
1608 count = uio->uio_resid;
1609 rcount = count - ((uio->uio_offset + count) & (ump->um_dirblksiz - 1));
1610
1611 if (rcount < _DIRENT_MINSIZE(cdp) || count < _DIRENT_MINSIZE(ndp))
1612 return EINVAL;
1613
1614 startoff = uio->uio_offset & ~(ump->um_dirblksiz - 1);
1615 skipbytes = uio->uio_offset - startoff;
1616 rcount += skipbytes;
1617
1618 auio.uio_iov = &aiov;
1619 auio.uio_iovcnt = 1;
1620 auio.uio_offset = startoff;
1621 auio.uio_resid = rcount;
1622 UIO_SETUP_SYSSPACE(&auio);
1623 auio.uio_rw = UIO_READ;
1624 cdbuf = malloc(rcount, M_TEMP, M_WAITOK);
1625 aiov.iov_base = cdbuf;
1626 aiov.iov_len = rcount;
1627 error = VOP_READ(vp, &auio, 0, ap->a_cred);
1628 if (error != 0) {
1629 free(cdbuf, M_TEMP);
1630 return error;
1631 }
1632
1633 rcount -= auio.uio_resid;
1634
1635 cdp = (struct direct *)(void *)cdbuf;
1636 ecdp = (struct direct *)(void *)&cdbuf[rcount];
1637
1638 ndbuf = malloc(count, M_TEMP, M_WAITOK);
1639 ndp = (struct dirent *)(void *)ndbuf;
1640 endp = &ndbuf[count];
1641
1642 off = uio->uio_offset;
1643 if (ap->a_cookies) {
1644 ccount = rcount / _DIRENT_RECLEN(cdp, 1);
1645 ccp = *(ap->a_cookies) = malloc(ccount * sizeof(*ccp),
1646 M_TEMP, M_WAITOK);
1647 } else {
1648 /* XXX: GCC */
1649 ccount = 0;
1650 ccp = NULL;
1651 }
1652
1653 while (cdp < ecdp) {
1654 cdp->d_reclen = ufs_rw16(cdp->d_reclen, nswap);
1655 if (skipbytes > 0) {
1656 if (cdp->d_reclen <= skipbytes) {
1657 skipbytes -= cdp->d_reclen;
1658 cdp = _DIRENT_NEXT(cdp);
1659 continue;
1660 }
1661 /*
1662 * invlid cookie.
1663 */
1664 error = EINVAL;
1665 goto out;
1666 }
1667 if (cdp->d_reclen == 0) {
1668 struct dirent *ondp = ndp;
1669 ndp->d_reclen = _DIRENT_MINSIZE(ndp);
1670 ndp = _DIRENT_NEXT(ndp);
1671 ondp->d_reclen = 0;
1672 cdp = ecdp;
1673 break;
1674 }
1675 if (needswap) {
1676 ndp->d_type = cdp->d_namlen;
1677 ndp->d_namlen = cdp->d_type;
1678 } else {
1679 ndp->d_type = cdp->d_type;
1680 ndp->d_namlen = cdp->d_namlen;
1681 }
1682 ndp->d_reclen = _DIRENT_RECLEN(ndp, ndp->d_namlen);
1683 if ((char *)(void *)ndp + ndp->d_reclen +
1684 _DIRENT_MINSIZE(ndp) > endp)
1685 break;
1686 ndp->d_fileno = ufs_rw32(cdp->d_ino, nswap);
1687 (void)memcpy(ndp->d_name, cdp->d_name, ndp->d_namlen);
1688 memset(&ndp->d_name[ndp->d_namlen], 0,
1689 ndp->d_reclen - _DIRENT_NAMEOFF(ndp) - ndp->d_namlen);
1690 off += cdp->d_reclen;
1691 if (ap->a_cookies) {
1692 KASSERT(ccp - *(ap->a_cookies) < ccount);
1693 *(ccp++) = off;
1694 }
1695 ndp = _DIRENT_NEXT(ndp);
1696 cdp = _DIRENT_NEXT(cdp);
1697 }
1698
1699 count = ((char *)(void *)ndp - ndbuf);
1700 error = uiomove(ndbuf, count, uio);
1701 out:
1702 if (ap->a_cookies) {
1703 if (error) {
1704 free(*(ap->a_cookies), M_TEMP);
1705 *(ap->a_cookies) = NULL;
1706 *(ap->a_ncookies) = 0;
1707 } else {
1708 *ap->a_ncookies = ccp - *(ap->a_cookies);
1709 }
1710 }
1711 uio->uio_offset = off;
1712 free(ndbuf, M_TEMP);
1713 free(cdbuf, M_TEMP);
1714 *ap->a_eofflag = VTOI(vp)->i_size <= uio->uio_offset;
1715 return error;
1716 }
1717
1718 /*
1719 * Return target name of a symbolic link
1720 */
1721 int
1722 ufs_readlink(void *v)
1723 {
1724 struct vop_readlink_args /* {
1725 struct vnode *a_vp;
1726 struct uio *a_uio;
1727 kauth_cred_t a_cred;
1728 } */ *ap = v;
1729 struct vnode *vp = ap->a_vp;
1730 struct inode *ip = VTOI(vp);
1731 struct ufsmount *ump = VFSTOUFS(vp->v_mount);
1732 int isize;
1733
1734 isize = ip->i_size;
1735 if (isize < ump->um_maxsymlinklen ||
1736 (ump->um_maxsymlinklen == 0 && DIP(ip, blocks) == 0)) {
1737 uiomove((char *)SHORTLINK(ip), isize, ap->a_uio);
1738 return (0);
1739 }
1740 return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
1741 }
1742
1743 /*
1744 * Calculate the logical to physical mapping if not done already,
1745 * then call the device strategy routine.
1746 */
1747 int
1748 ufs_strategy(void *v)
1749 {
1750 struct vop_strategy_args /* {
1751 struct vnode *a_vp;
1752 struct buf *a_bp;
1753 } */ *ap = v;
1754 struct buf *bp;
1755 struct vnode *vp;
1756 struct inode *ip;
1757 int error;
1758
1759 bp = ap->a_bp;
1760 vp = ap->a_vp;
1761 ip = VTOI(vp);
1762 if (vp->v_type == VBLK || vp->v_type == VCHR)
1763 panic("ufs_strategy: spec");
1764 KASSERT(bp->b_bcount != 0);
1765 if (bp->b_blkno == bp->b_lblkno) {
1766 error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno,
1767 NULL);
1768 if (error) {
1769 bp->b_error = error;
1770 bp->b_flags |= B_ERROR;
1771 biodone(bp);
1772 return (error);
1773 }
1774 if (bp->b_blkno == -1) /* no valid data */
1775 clrbuf(bp);
1776 }
1777 if (bp->b_blkno < 0) { /* block is not on disk */
1778 biodone(bp);
1779 return (0);
1780 }
1781 vp = ip->i_devvp;
1782 return (VOP_STRATEGY(vp, bp));
1783 }
1784
1785 /*
1786 * Print out the contents of an inode.
1787 */
1788 int
1789 ufs_print(void *v)
1790 {
1791 struct vop_print_args /* {
1792 struct vnode *a_vp;
1793 } */ *ap = v;
1794 struct vnode *vp;
1795 struct inode *ip;
1796
1797 vp = ap->a_vp;
1798 ip = VTOI(vp);
1799 printf("tag VT_UFS, ino %llu, on dev %d, %d",
1800 (unsigned long long)ip->i_number,
1801 major(ip->i_dev), minor(ip->i_dev));
1802 printf(" flags 0x%x, effnlink %d, nlink %d\n",
1803 ip->i_flag, ip->i_ffs_effnlink, ip->i_nlink);
1804 printf("\tmode 0%o, owner %d, group %d, size %qd",
1805 ip->i_mode, ip->i_uid, ip->i_gid,
1806 (long long)ip->i_size);
1807 if (vp->v_type == VFIFO)
1808 fifo_printinfo(vp);
1809 lockmgr_printinfo(&vp->v_lock);
1810 printf("\n");
1811 return (0);
1812 }
1813
1814 /*
1815 * Read wrapper for special devices.
1816 */
1817 int
1818 ufsspec_read(void *v)
1819 {
1820 struct vop_read_args /* {
1821 struct vnode *a_vp;
1822 struct uio *a_uio;
1823 int a_ioflag;
1824 kauth_cred_t a_cred;
1825 } */ *ap = v;
1826
1827 /*
1828 * Set access flag.
1829 */
1830 if ((ap->a_vp->v_mount->mnt_flag & MNT_NODEVMTIME) == 0)
1831 VTOI(ap->a_vp)->i_flag |= IN_ACCESS;
1832 return (VOCALL (spec_vnodeop_p, VOFFSET(vop_read), ap));
1833 }
1834
1835 /*
1836 * Write wrapper for special devices.
1837 */
1838 int
1839 ufsspec_write(void *v)
1840 {
1841 struct vop_write_args /* {
1842 struct vnode *a_vp;
1843 struct uio *a_uio;
1844 int a_ioflag;
1845 kauth_cred_t a_cred;
1846 } */ *ap = v;
1847
1848 /*
1849 * Set update and change flags.
1850 */
1851 if ((ap->a_vp->v_mount->mnt_flag & MNT_NODEVMTIME) == 0)
1852 VTOI(ap->a_vp)->i_flag |= IN_MODIFY;
1853 return (VOCALL (spec_vnodeop_p, VOFFSET(vop_write), ap));
1854 }
1855
1856 /*
1857 * Close wrapper for special devices.
1858 *
1859 * Update the times on the inode then do device close.
1860 */
1861 int
1862 ufsspec_close(void *v)
1863 {
1864 struct vop_close_args /* {
1865 struct vnode *a_vp;
1866 int a_fflag;
1867 kauth_cred_t a_cred;
1868 struct lwp *a_l;
1869 } */ *ap = v;
1870 struct vnode *vp;
1871 struct inode *ip;
1872
1873 vp = ap->a_vp;
1874 ip = VTOI(vp);
1875 simple_lock(&vp->v_interlock);
1876 if (vp->v_usecount > 1)
1877 UFS_ITIMES(vp, NULL, NULL, NULL);
1878 simple_unlock(&vp->v_interlock);
1879 return (VOCALL (spec_vnodeop_p, VOFFSET(vop_close), ap));
1880 }
1881
1882 /*
1883 * Read wrapper for fifo's
1884 */
1885 int
1886 ufsfifo_read(void *v)
1887 {
1888 struct vop_read_args /* {
1889 struct vnode *a_vp;
1890 struct uio *a_uio;
1891 int a_ioflag;
1892 kauth_cred_t a_cred;
1893 } */ *ap = v;
1894
1895 /*
1896 * Set access flag.
1897 */
1898 VTOI(ap->a_vp)->i_flag |= IN_ACCESS;
1899 return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_read), ap));
1900 }
1901
1902 /*
1903 * Write wrapper for fifo's.
1904 */
1905 int
1906 ufsfifo_write(void *v)
1907 {
1908 struct vop_write_args /* {
1909 struct vnode *a_vp;
1910 struct uio *a_uio;
1911 int a_ioflag;
1912 kauth_cred_t a_cred;
1913 } */ *ap = v;
1914
1915 /*
1916 * Set update and change flags.
1917 */
1918 VTOI(ap->a_vp)->i_flag |= IN_MODIFY;
1919 return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_write), ap));
1920 }
1921
1922 /*
1923 * Close wrapper for fifo's.
1924 *
1925 * Update the times on the inode then do device close.
1926 */
1927 int
1928 ufsfifo_close(void *v)
1929 {
1930 struct vop_close_args /* {
1931 struct vnode *a_vp;
1932 int a_fflag;
1933 kauth_cred_t a_cred;
1934 struct lwp *a_l;
1935 } */ *ap = v;
1936 struct vnode *vp;
1937 struct inode *ip;
1938
1939 vp = ap->a_vp;
1940 ip = VTOI(vp);
1941 simple_lock(&vp->v_interlock);
1942 if (ap->a_vp->v_usecount > 1)
1943 UFS_ITIMES(vp, NULL, NULL, NULL);
1944 simple_unlock(&vp->v_interlock);
1945 return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_close), ap));
1946 }
1947
1948 /*
1949 * Return POSIX pathconf information applicable to ufs filesystems.
1950 */
1951 int
1952 ufs_pathconf(void *v)
1953 {
1954 struct vop_pathconf_args /* {
1955 struct vnode *a_vp;
1956 int a_name;
1957 register_t *a_retval;
1958 } */ *ap = v;
1959
1960 switch (ap->a_name) {
1961 case _PC_LINK_MAX:
1962 *ap->a_retval = LINK_MAX;
1963 return (0);
1964 case _PC_NAME_MAX:
1965 *ap->a_retval = NAME_MAX;
1966 return (0);
1967 case _PC_PATH_MAX:
1968 *ap->a_retval = PATH_MAX;
1969 return (0);
1970 case _PC_PIPE_BUF:
1971 *ap->a_retval = PIPE_BUF;
1972 return (0);
1973 case _PC_CHOWN_RESTRICTED:
1974 *ap->a_retval = 1;
1975 return (0);
1976 case _PC_NO_TRUNC:
1977 *ap->a_retval = 1;
1978 return (0);
1979 case _PC_SYNC_IO:
1980 *ap->a_retval = 1;
1981 return (0);
1982 case _PC_FILESIZEBITS:
1983 *ap->a_retval = 42;
1984 return (0);
1985 default:
1986 return (EINVAL);
1987 }
1988 /* NOTREACHED */
1989 }
1990
1991 /*
1992 * Advisory record locking support
1993 */
1994 int
1995 ufs_advlock(void *v)
1996 {
1997 struct vop_advlock_args /* {
1998 struct vnode *a_vp;
1999 caddr_t a_id;
2000 int a_op;
2001 struct flock *a_fl;
2002 int a_flags;
2003 } */ *ap = v;
2004 struct inode *ip;
2005
2006 ip = VTOI(ap->a_vp);
2007 return lf_advlock(ap, &ip->i_lockf, ip->i_size);
2008 }
2009
2010 /*
2011 * Initialize the vnode associated with a new inode, handle aliased
2012 * vnodes.
2013 */
2014 void
2015 ufs_vinit(struct mount *mntp, int (**specops)(void *), int (**fifoops)(void *),
2016 struct vnode **vpp)
2017 {
2018 struct timeval tv;
2019 struct inode *ip;
2020 struct vnode *vp, *nvp;
2021 dev_t rdev;
2022 struct ufsmount *ump;
2023
2024 vp = *vpp;
2025 ip = VTOI(vp);
2026 switch(vp->v_type = IFTOVT(ip->i_mode)) {
2027 case VCHR:
2028 case VBLK:
2029 vp->v_op = specops;
2030 ump = ip->i_ump;
2031 if (ump->um_fstype == UFS1)
2032 rdev = (dev_t)ufs_rw32(ip->i_ffs1_rdev,
2033 UFS_MPNEEDSWAP(ump));
2034 else
2035 rdev = (dev_t)ufs_rw64(ip->i_ffs2_rdev,
2036 UFS_MPNEEDSWAP(ump));
2037 if ((nvp = checkalias(vp, rdev, mntp)) != NULL) {
2038 /*
2039 * Discard unneeded vnode, but save its inode.
2040 */
2041 nvp->v_data = vp->v_data;
2042 vp->v_data = NULL;
2043 /* XXX spec_vnodeops has no locking, do it explicitly */
2044 VOP_UNLOCK(vp, 0);
2045 vp->v_op = spec_vnodeop_p;
2046 vp->v_flag &= ~VLOCKSWORK;
2047 vrele(vp);
2048 vgone(vp);
2049 lockmgr(&nvp->v_lock, LK_EXCLUSIVE, &nvp->v_interlock);
2050 /*
2051 * Reinitialize aliased inode.
2052 */
2053 vp = nvp;
2054 ip->i_vnode = vp;
2055 }
2056 break;
2057 case VFIFO:
2058 vp->v_op = fifoops;
2059 break;
2060 case VNON:
2061 case VBAD:
2062 case VSOCK:
2063 case VLNK:
2064 case VDIR:
2065 case VREG:
2066 break;
2067 }
2068 if (ip->i_number == ROOTINO)
2069 vp->v_flag |= VROOT;
2070 /*
2071 * Initialize modrev times
2072 */
2073 getmicrouptime(&tv);
2074 ip->i_modrev = (uint64_t)(uint)tv.tv_sec << 32
2075 | tv.tv_usec * 4294u;
2076 *vpp = vp;
2077 }
2078
2079 /*
2080 * Allocate a new inode.
2081 */
2082 int
2083 ufs_makeinode(int mode, struct vnode *dvp, struct vnode **vpp,
2084 struct componentname *cnp)
2085 {
2086 struct inode *ip, *pdir;
2087 struct direct *newdir;
2088 struct vnode *tvp;
2089 int error, ismember = 0;
2090
2091 pdir = VTOI(dvp);
2092 #ifdef DIAGNOSTIC
2093 if ((cnp->cn_flags & HASBUF) == 0)
2094 panic("ufs_makeinode: no name");
2095 #endif
2096 if ((mode & IFMT) == 0)
2097 mode |= IFREG;
2098
2099 if ((error = UFS_VALLOC(dvp, mode, cnp->cn_cred, vpp)) != 0) {
2100 PNBUF_PUT(cnp->cn_pnbuf);
2101 vput(dvp);
2102 return (error);
2103 }
2104 tvp = *vpp;
2105 ip = VTOI(tvp);
2106 ip->i_gid = pdir->i_gid;
2107 DIP_ASSIGN(ip, gid, ip->i_gid);
2108 ip->i_uid = kauth_cred_geteuid(cnp->cn_cred);
2109 DIP_ASSIGN(ip, uid, ip->i_uid);
2110 #ifdef QUOTA
2111 if ((error = getinoquota(ip)) ||
2112 (error = chkiq(ip, 1, cnp->cn_cred, 0))) {
2113 UFS_VFREE(tvp, ip->i_number, mode);
2114 vput(tvp);
2115 PNBUF_PUT(cnp->cn_pnbuf);
2116 vput(dvp);
2117 return (error);
2118 }
2119 #endif
2120 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
2121 ip->i_mode = mode;
2122 DIP_ASSIGN(ip, mode, mode);
2123 tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */
2124 ip->i_ffs_effnlink = 1;
2125 ip->i_nlink = 1;
2126 DIP_ASSIGN(ip, nlink, 1);
2127 if (DOINGSOFTDEP(tvp))
2128 softdep_change_linkcnt(ip);
2129 if ((ip->i_mode & ISGID) && (kauth_cred_ismember_gid(cnp->cn_cred,
2130 ip->i_gid, &ismember) != 0 || !ismember) &&
2131 kauth_authorize_generic(cnp->cn_cred, KAUTH_GENERIC_ISSUSER, NULL)) {
2132 ip->i_mode &= ~ISGID;
2133 DIP_ASSIGN(ip, mode, ip->i_mode);
2134 }
2135
2136 if (cnp->cn_flags & ISWHITEOUT) {
2137 ip->i_flags |= UF_OPAQUE;
2138 DIP_ASSIGN(ip, flags, ip->i_flags);
2139 }
2140
2141 /*
2142 * Make sure inode goes to disk before directory entry.
2143 */
2144 if ((error = UFS_UPDATE(tvp, NULL, NULL, UPDATE_DIROP)) != 0)
2145 goto bad;
2146 newdir = pool_get(&ufs_direct_pool, PR_WAITOK);
2147 ufs_makedirentry(ip, cnp, newdir);
2148 error = ufs_direnter(dvp, tvp, newdir, cnp, NULL);
2149 pool_put(&ufs_direct_pool, newdir);
2150 if (error)
2151 goto bad;
2152 if ((cnp->cn_flags & SAVESTART) == 0)
2153 PNBUF_PUT(cnp->cn_pnbuf);
2154 vput(dvp);
2155 *vpp = tvp;
2156 return (0);
2157
2158 bad:
2159 /*
2160 * Write error occurred trying to update the inode
2161 * or the directory so must deallocate the inode.
2162 */
2163 ip->i_ffs_effnlink = 0;
2164 ip->i_nlink = 0;
2165 DIP_ASSIGN(ip, nlink, 0);
2166 ip->i_flag |= IN_CHANGE;
2167 #ifdef LFS
2168 /* If IN_ADIROP, account for it */
2169 lfs_unmark_vnode(tvp);
2170 #endif
2171 if (DOINGSOFTDEP(tvp))
2172 softdep_change_linkcnt(ip);
2173 tvp->v_type = VNON; /* explodes later if VBLK */
2174 vput(tvp);
2175 PNBUF_PUT(cnp->cn_pnbuf);
2176 vput(dvp);
2177 return (error);
2178 }
2179
2180 /*
2181 * Allocate len bytes at offset off.
2182 */
2183 int
2184 ufs_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags,
2185 kauth_cred_t cred)
2186 {
2187 struct inode *ip = VTOI(vp);
2188 int error, delta, bshift, bsize;
2189 UVMHIST_FUNC("ufs_gop_alloc"); UVMHIST_CALLED(ubchist);
2190
2191 error = 0;
2192 bshift = vp->v_mount->mnt_fs_bshift;
2193 bsize = 1 << bshift;
2194
2195 delta = off & (bsize - 1);
2196 off -= delta;
2197 len += delta;
2198
2199 while (len > 0) {
2200 bsize = MIN(bsize, len);
2201
2202 error = UFS_BALLOC(vp, off, bsize, cred, flags, NULL);
2203 if (error) {
2204 goto out;
2205 }
2206
2207 /*
2208 * increase file size now, UFS_BALLOC() requires that
2209 * EOF be up-to-date before each call.
2210 */
2211
2212 if (ip->i_size < off + bsize) {
2213 UVMHIST_LOG(ubchist, "vp %p old 0x%x new 0x%x",
2214 vp, ip->i_size, off + bsize, 0);
2215 ip->i_size = off + bsize;
2216 DIP_ASSIGN(ip, size, ip->i_size);
2217 }
2218
2219 off += bsize;
2220 len -= bsize;
2221 }
2222
2223 out:
2224 return error;
2225 }
2226
2227 void
2228 ufs_gop_markupdate(struct vnode *vp, int flags)
2229 {
2230 u_int32_t mask = 0;
2231
2232 if ((flags & GOP_UPDATE_ACCESSED) != 0) {
2233 mask = IN_ACCESS;
2234 }
2235 if ((flags & GOP_UPDATE_MODIFIED) != 0) {
2236 if (vp->v_type == VREG) {
2237 mask |= IN_CHANGE | IN_UPDATE;
2238 } else {
2239 mask |= IN_MODIFY;
2240 }
2241 }
2242 if (mask) {
2243 struct inode *ip = VTOI(vp);
2244
2245 ip->i_flag |= mask;
2246 }
2247 }
Cache object: 542399c4194d8d25f036d52c134d1148
|