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