]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/ufs/ufs/ufs_vnops.c
This commit was generated by cvs2svn to compensate for changes in r170349,
[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  * 4. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  *      @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95
35  */
36
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD$");
39
40 #include "opt_mac.h"
41 #include "opt_quota.h"
42 #include "opt_suiddir.h"
43 #include "opt_ufs.h"
44 #include "opt_ffs.h"
45
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/malloc.h>
49 #include <sys/namei.h>
50 #include <sys/kernel.h>
51 #include <sys/fcntl.h>
52 #include <sys/stat.h>
53 #include <sys/bio.h>
54 #include <sys/buf.h>
55 #include <sys/mount.h>
56 #include <sys/priv.h>
57 #include <sys/refcount.h>
58 #include <sys/unistd.h>
59 #include <sys/vnode.h>
60 #include <sys/dirent.h>
61 #include <sys/lockf.h>
62 #include <sys/conf.h>
63 #include <sys/acl.h>
64 #include <sys/jail.h>
65
66 #include <machine/mutex.h>
67
68 #include <security/mac/mac_framework.h>
69
70 #include <sys/file.h>           /* XXX */
71
72 #include <vm/vm.h>
73 #include <vm/vm_extern.h>
74
75 #include <fs/fifofs/fifo.h>
76
77 #include <ufs/ufs/acl.h>
78 #include <ufs/ufs/extattr.h>
79 #include <ufs/ufs/quota.h>
80 #include <ufs/ufs/inode.h>
81 #include <ufs/ufs/dir.h>
82 #include <ufs/ufs/ufsmount.h>
83 #include <ufs/ufs/ufs_extern.h>
84 #ifdef UFS_DIRHASH
85 #include <ufs/ufs/dirhash.h>
86 #endif
87 #ifdef UFS_GJOURNAL
88 #include <ufs/ufs/gjournal.h>
89 #endif
90
91 #include <ufs/ffs/ffs_extern.h>
92
93 static vop_access_t     ufs_access;
94 static vop_advlock_t    ufs_advlock;
95 static int ufs_chmod(struct vnode *, int, struct ucred *, struct thread *);
96 static int ufs_chown(struct vnode *, uid_t, gid_t, struct ucred *, struct thread *);
97 static vop_close_t      ufs_close;
98 static vop_create_t     ufs_create;
99 static vop_getattr_t    ufs_getattr;
100 static vop_link_t       ufs_link;
101 static int ufs_makeinode(int mode, struct vnode *, struct vnode **, struct componentname *);
102 static vop_mkdir_t      ufs_mkdir;
103 static vop_mknod_t      ufs_mknod;
104 static vop_open_t       ufs_open;
105 static vop_pathconf_t   ufs_pathconf;
106 static vop_print_t      ufs_print;
107 static vop_readlink_t   ufs_readlink;
108 static vop_remove_t     ufs_remove;
109 static vop_rename_t     ufs_rename;
110 static vop_rmdir_t      ufs_rmdir;
111 static vop_setattr_t    ufs_setattr;
112 static vop_strategy_t   ufs_strategy;
113 static vop_symlink_t    ufs_symlink;
114 static vop_whiteout_t   ufs_whiteout;
115 static vop_close_t      ufsfifo_close;
116 static vop_kqfilter_t   ufsfifo_kqfilter;
117
118 /*
119  * A virgin directory (no blushing please).
120  */
121 static struct dirtemplate mastertemplate = {
122         0, 12, DT_DIR, 1, ".",
123         0, DIRBLKSIZ - 12, DT_DIR, 2, ".."
124 };
125 static struct odirtemplate omastertemplate = {
126         0, 12, 1, ".",
127         0, DIRBLKSIZ - 12, 2, ".."
128 };
129
130 static void
131 ufs_itimes_locked(struct vnode *vp)
132 {
133         struct inode *ip;
134         struct timespec ts;
135
136         ASSERT_VI_LOCKED(vp, __func__);
137
138         ip = VTOI(vp);
139         if ((vp->v_mount->mnt_flag & MNT_RDONLY) != 0)
140                 goto out;
141         if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0)
142                 return;
143
144         if ((vp->v_type == VBLK || vp->v_type == VCHR) && !DOINGSOFTDEP(vp))
145                 ip->i_flag |= IN_LAZYMOD;
146         else if (((vp->v_mount->mnt_kern_flag &
147                     (MNTK_SUSPENDED | MNTK_SUSPEND)) == 0) ||
148                     (ip->i_flag & (IN_CHANGE | IN_UPDATE)))
149                 ip->i_flag |= IN_MODIFIED;
150         else if (ip->i_flag & IN_ACCESS)
151                 ip->i_flag |= IN_LAZYACCESS;
152         vfs_timestamp(&ts);
153         if (ip->i_flag & IN_ACCESS) {
154                 DIP_SET(ip, i_atime, ts.tv_sec);
155                 DIP_SET(ip, i_atimensec, ts.tv_nsec);
156         }
157         if (ip->i_flag & IN_UPDATE) {
158                 DIP_SET(ip, i_mtime, ts.tv_sec);
159                 DIP_SET(ip, i_mtimensec, ts.tv_nsec);
160                 ip->i_modrev++;
161         }
162         if (ip->i_flag & IN_CHANGE) {
163                 DIP_SET(ip, i_ctime, ts.tv_sec);
164                 DIP_SET(ip, i_ctimensec, ts.tv_nsec);
165         }
166
167  out:
168         ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE);
169 }
170
171 void
172 ufs_itimes(struct vnode *vp)
173 {
174
175         VI_LOCK(vp);
176         ufs_itimes_locked(vp);
177         VI_UNLOCK(vp);
178 }
179
180 /*
181  * Create a regular file
182  */
183 static int
184 ufs_create(ap)
185         struct vop_create_args /* {
186                 struct vnode *a_dvp;
187                 struct vnode **a_vpp;
188                 struct componentname *a_cnp;
189                 struct vattr *a_vap;
190         } */ *ap;
191 {
192         int error;
193
194         error =
195             ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
196             ap->a_dvp, ap->a_vpp, ap->a_cnp);
197         if (error)
198                 return (error);
199         return (0);
200 }
201
202 /*
203  * Mknod vnode call
204  */
205 /* ARGSUSED */
206 static int
207 ufs_mknod(ap)
208         struct vop_mknod_args /* {
209                 struct vnode *a_dvp;
210                 struct vnode **a_vpp;
211                 struct componentname *a_cnp;
212                 struct vattr *a_vap;
213         } */ *ap;
214 {
215         struct vattr *vap = ap->a_vap;
216         struct vnode **vpp = ap->a_vpp;
217         struct inode *ip;
218         ino_t ino;
219         int error;
220
221         error = ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode),
222             ap->a_dvp, vpp, ap->a_cnp);
223         if (error)
224                 return (error);
225         ip = VTOI(*vpp);
226         ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
227         if (vap->va_rdev != VNOVAL) {
228                 /*
229                  * Want to be able to use this to make badblock
230                  * inodes, so don't truncate the dev number.
231                  */
232                 DIP_SET(ip, i_rdev, vap->va_rdev);
233         }
234         /*
235          * Remove inode, then reload it through VFS_VGET so it is
236          * checked to see if it is an alias of an existing entry in
237          * the inode cache.  XXX I don't believe this is necessary now.
238          */
239         (*vpp)->v_type = VNON;
240         ino = ip->i_number;     /* Save this before vgone() invalidates ip. */
241         vgone(*vpp);
242         vput(*vpp);
243         error = VFS_VGET(ap->a_dvp->v_mount, ino, LK_EXCLUSIVE, vpp);
244         if (error) {
245                 *vpp = NULL;
246                 return (error);
247         }
248         return (0);
249 }
250
251 /*
252  * Open called.
253  */
254 /* ARGSUSED */
255 static int
256 ufs_open(struct vop_open_args *ap)
257 {
258         struct vnode *vp = ap->a_vp;
259         struct inode *ip;
260
261         if (vp->v_type == VCHR || vp->v_type == VBLK)
262                 return (EOPNOTSUPP);
263
264         ip = VTOI(vp);
265         /*
266          * Files marked append-only must be opened for appending.
267          */
268         if ((ip->i_flags & APPEND) &&
269             (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
270                 return (EPERM);
271         vnode_create_vobject(vp, DIP(ip, i_size), ap->a_td);
272         return (0);
273 }
274
275 /*
276  * Close called.
277  *
278  * Update the times on the inode.
279  */
280 /* ARGSUSED */
281 static int
282 ufs_close(ap)
283         struct vop_close_args /* {
284                 struct vnode *a_vp;
285                 int  a_fflag;
286                 struct ucred *a_cred;
287                 struct thread *a_td;
288         } */ *ap;
289 {
290         struct vnode *vp = ap->a_vp;
291         int usecount;
292
293         VI_LOCK(vp);
294         usecount = vp->v_usecount;
295         if (usecount > 1)
296                 ufs_itimes_locked(vp);
297         VI_UNLOCK(vp);
298         return (0);
299 }
300
301 static int
302 ufs_access(ap)
303         struct vop_access_args /* {
304                 struct vnode *a_vp;
305                 int  a_mode;
306                 struct ucred *a_cred;
307                 struct thread *a_td;
308         } */ *ap;
309 {
310         struct vnode *vp = ap->a_vp;
311         struct inode *ip = VTOI(vp);
312         mode_t mode = ap->a_mode;
313         int error;
314 #ifdef UFS_ACL
315         struct acl *acl;
316 #endif
317
318         /*
319          * Disallow write attempts on read-only filesystems;
320          * unless the file is a socket, fifo, or a block or
321          * character device resident on the filesystem.
322          */
323         if (mode & VWRITE) {
324                 switch (vp->v_type) {
325                 case VDIR:
326                 case VLNK:
327                 case VREG:
328                         if (vp->v_mount->mnt_flag & MNT_RDONLY)
329                                 return (EROFS);
330                         break;
331                 default:
332                         break;
333                 }
334         }
335
336         /* If immutable bit set, nobody gets to write it. */
337         if ((mode & VWRITE) && (ip->i_flags & (IMMUTABLE | SF_SNAPSHOT)))
338                 return (EPERM);
339
340 #ifdef UFS_ACL
341         if ((vp->v_mount->mnt_flag & MNT_ACLS) != 0) {
342                 acl = uma_zalloc(acl_zone, M_WAITOK);
343                 error = VOP_GETACL(vp, ACL_TYPE_ACCESS, acl, ap->a_cred,
344                     ap->a_td);
345                 switch (error) {
346                 case EOPNOTSUPP:
347                         error = vaccess(vp->v_type, ip->i_mode, ip->i_uid,
348                             ip->i_gid, ap->a_mode, ap->a_cred, NULL);
349                         break;
350                 case 0:
351                         error = vaccess_acl_posix1e(vp->v_type, ip->i_uid,
352                             ip->i_gid, acl, ap->a_mode, ap->a_cred, NULL);
353                         break;
354                 default:
355                         printf(
356 "ufs_access(): Error retrieving ACL on object (%d).\n",
357                             error);
358                         /*
359                          * XXX: Fall back until debugged.  Should
360                          * eventually possibly log an error, and return
361                          * EPERM for safety.
362                          */
363                         error = vaccess(vp->v_type, ip->i_mode, ip->i_uid,
364                             ip->i_gid, ap->a_mode, ap->a_cred, NULL);
365                 }
366                 uma_zfree(acl_zone, acl);
367         } else
368 #endif /* !UFS_ACL */
369                 error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid,
370                     ap->a_mode, ap->a_cred, NULL);
371         return (error);
372 }
373
374 /* ARGSUSED */
375 static 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 thread *a_td;
382         } */ *ap;
383 {
384         struct vnode *vp = ap->a_vp;
385         struct inode *ip = VTOI(vp);
386         struct vattr *vap = ap->a_vap;
387
388         VI_LOCK(vp);
389         ufs_itimes_locked(vp);
390         if (ip->i_ump->um_fstype == UFS1) {
391                 vap->va_atime.tv_sec = ip->i_din1->di_atime;
392                 vap->va_atime.tv_nsec = ip->i_din1->di_atimensec;
393         } else {
394                 vap->va_atime.tv_sec = ip->i_din2->di_atime;
395                 vap->va_atime.tv_nsec = ip->i_din2->di_atimensec;
396         }
397         VI_UNLOCK(vp);
398         /*
399          * Copy from inode table
400          */
401         vap->va_fsid = dev2udev(ip->i_dev);
402         vap->va_fileid = ip->i_number;
403         vap->va_mode = ip->i_mode & ~IFMT;
404         vap->va_nlink = ip->i_effnlink;
405         vap->va_uid = ip->i_uid;
406         vap->va_gid = ip->i_gid;
407         if (ip->i_ump->um_fstype == UFS1) {
408                 vap->va_rdev = ip->i_din1->di_rdev;
409                 vap->va_size = ip->i_din1->di_size;
410                 vap->va_mtime.tv_sec = ip->i_din1->di_mtime;
411                 vap->va_mtime.tv_nsec = ip->i_din1->di_mtimensec;
412                 vap->va_ctime.tv_sec = ip->i_din1->di_ctime;
413                 vap->va_ctime.tv_nsec = ip->i_din1->di_ctimensec;
414                 vap->va_birthtime.tv_sec = 0;
415                 vap->va_birthtime.tv_nsec = 0;
416                 vap->va_bytes = dbtob((u_quad_t)ip->i_din1->di_blocks);
417         } else {
418                 vap->va_rdev = ip->i_din2->di_rdev;
419                 vap->va_size = ip->i_din2->di_size;
420                 vap->va_mtime.tv_sec = ip->i_din2->di_mtime;
421                 vap->va_mtime.tv_nsec = ip->i_din2->di_mtimensec;
422                 vap->va_ctime.tv_sec = ip->i_din2->di_ctime;
423                 vap->va_ctime.tv_nsec = ip->i_din2->di_ctimensec;
424                 vap->va_birthtime.tv_sec = ip->i_din2->di_birthtime;
425                 vap->va_birthtime.tv_nsec = ip->i_din2->di_birthnsec;
426                 vap->va_bytes = dbtob((u_quad_t)ip->i_din2->di_blocks);
427         }
428         vap->va_flags = ip->i_flags;
429         vap->va_gen = ip->i_gen;
430         vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
431         vap->va_type = IFTOVT(ip->i_mode);
432         vap->va_filerev = ip->i_modrev;
433         return (0);
434 }
435
436 /*
437  * Set attribute vnode op. called from several syscalls
438  */
439 static int
440 ufs_setattr(ap)
441         struct vop_setattr_args /* {
442                 struct vnode *a_vp;
443                 struct vattr *a_vap;
444                 struct ucred *a_cred;
445                 struct thread *a_td;
446         } */ *ap;
447 {
448         struct vattr *vap = ap->a_vap;
449         struct vnode *vp = ap->a_vp;
450         struct inode *ip = VTOI(vp);
451         struct ucred *cred = ap->a_cred;
452         struct thread *td = ap->a_td;
453         int error;
454
455         /*
456          * Check for unsettable attributes.
457          */
458         if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
459             (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
460             (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
461             ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
462                 return (EINVAL);
463         }
464         /*
465          * Mark for update the file's access time for vfs_mark_atime().
466          * We are doing this here to avoid some of the checks done
467          * below -- this operation is done by request of the kernel and
468          * should bypass some security checks.  Things like read-only
469          * checks get handled by other levels (e.g., ffs_update()).
470          */
471         if (vap->va_vaflags & VA_MARK_ATIME) {
472                 ip->i_flag |= IN_ACCESS;
473                 return (0);
474         }
475         if (vap->va_flags != VNOVAL) {
476                 if (vp->v_mount->mnt_flag & MNT_RDONLY)
477                         return (EROFS);
478                 /*
479                  * Callers may only modify the file flags on objects they
480                  * have VADMIN rights for.
481                  */
482                 if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
483                         return (error);
484                 /*
485                  * Unprivileged processes are not permitted to unset system
486                  * flags, or modify flags if any system flags are set.
487                  * Privileged non-jail processes may not modify system flags
488                  * if securelevel > 0 and any existing system flags are set.
489                  * Privileged jail processes behave like privileged non-jail
490                  * processes if the security.jail.chflags_allowed sysctl is
491                  * is non-zero; otherwise, they behave like unprivileged
492                  * processes.
493                  *
494                  * XXXRW: Move implementation of jail_chflags_allowed to
495                  * kern_jail.c.
496                  */
497                 if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS,
498                     jail_chflags_allowed ? SUSER_ALLOWJAIL : 0)) {
499                         if (ip->i_flags
500                             & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) {
501                                 error = securelevel_gt(cred, 0);
502                                 if (error)
503                                         return (error);
504                         }
505                         /* Snapshot flag cannot be set or cleared */
506                         if (((vap->va_flags & SF_SNAPSHOT) != 0 &&
507                              (ip->i_flags & SF_SNAPSHOT) == 0) ||
508                             ((vap->va_flags & SF_SNAPSHOT) == 0 &&
509                              (ip->i_flags & SF_SNAPSHOT) != 0))
510                                 return (EPERM);
511                         ip->i_flags = vap->va_flags;
512                         DIP_SET(ip, i_flags, vap->va_flags);
513                 } else {
514                         if (ip->i_flags
515                             & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND) ||
516                             (vap->va_flags & UF_SETTABLE) != vap->va_flags)
517                                 return (EPERM);
518                         ip->i_flags &= SF_SETTABLE;
519                         ip->i_flags |= (vap->va_flags & UF_SETTABLE);
520                         DIP_SET(ip, i_flags, ip->i_flags);
521                 }
522                 ip->i_flag |= IN_CHANGE;
523                 if (vap->va_flags & (IMMUTABLE | APPEND))
524                         return (0);
525         }
526         if (ip->i_flags & (IMMUTABLE | APPEND))
527                 return (EPERM);
528         /*
529          * Go through the fields and update iff not VNOVAL.
530          */
531         if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
532                 if (vp->v_mount->mnt_flag & MNT_RDONLY)
533                         return (EROFS);
534                 if ((error = ufs_chown(vp, vap->va_uid, vap->va_gid, cred,
535                     td)) != 0)
536                         return (error);
537         }
538         if (vap->va_size != VNOVAL) {
539                 /*
540                  * XXX most of the following special cases should be in
541                  * callers instead of in N filesystems.  The VDIR check
542                  * mostly already is.
543                  */
544                 switch (vp->v_type) {
545                 case VDIR:
546                         return (EISDIR);
547                 case VLNK:
548                 case VREG:
549                         /*
550                          * Truncation should have an effect in these cases.
551                          * Disallow it if the filesystem is read-only or
552                          * the file is being snapshotted.
553                          */
554                         if (vp->v_mount->mnt_flag & MNT_RDONLY)
555                                 return (EROFS);
556                         if ((ip->i_flags & SF_SNAPSHOT) != 0)
557                                 return (EPERM);
558                         break;
559                 default:
560                         /*
561                          * According to POSIX, the result is unspecified
562                          * for file types other than regular files,
563                          * directories and shared memory objects.  We
564                          * don't support shared memory objects in the file
565                          * system, and have dubious support for truncating
566                          * symlinks.  Just ignore the request in other cases.
567                          */
568                         return (0);
569                 }
570                 if ((error = UFS_TRUNCATE(vp, vap->va_size, IO_NORMAL,
571                     cred, td)) != 0)
572                         return (error);
573         }
574         if (vap->va_atime.tv_sec != VNOVAL ||
575             vap->va_mtime.tv_sec != VNOVAL ||
576             vap->va_birthtime.tv_sec != VNOVAL) {
577                 if (vp->v_mount->mnt_flag & MNT_RDONLY)
578                         return (EROFS);
579                 if ((ip->i_flags & SF_SNAPSHOT) != 0)
580                         return (EPERM);
581                 /*
582                  * From utimes(2):
583                  * If times is NULL, ... The caller must be the owner of
584                  * the file, have permission to write the file, or be the
585                  * super-user.
586                  * If times is non-NULL, ... The caller must be the owner of
587                  * the file or be the super-user.
588                  *
589                  * Possibly for historical reasons, try to use VADMIN in
590                  * preference to VWRITE for a NULL timestamp.  This means we
591                  * will return EACCES in preference to EPERM if neither
592                  * check succeeds.
593                  */
594                 if (vap->va_vaflags & VA_UTIMES_NULL) {
595                         error = VOP_ACCESS(vp, VADMIN, cred, td);
596                         if (error)
597                                 error = VOP_ACCESS(vp, VWRITE, cred, td);
598                 } else
599                         error = VOP_ACCESS(vp, VADMIN, cred, td);
600                 if (error)
601                         return (error);
602                 if (vap->va_atime.tv_sec != VNOVAL)
603                         ip->i_flag |= IN_ACCESS;
604                 if (vap->va_mtime.tv_sec != VNOVAL)
605                         ip->i_flag |= IN_CHANGE | IN_UPDATE;
606                 if (vap->va_birthtime.tv_sec != VNOVAL &&
607                     ip->i_ump->um_fstype == UFS2)
608                         ip->i_flag |= IN_MODIFIED;
609                 ufs_itimes(vp);
610                 if (vap->va_atime.tv_sec != VNOVAL) {
611                         DIP_SET(ip, i_atime, vap->va_atime.tv_sec);
612                         DIP_SET(ip, i_atimensec, vap->va_atime.tv_nsec);
613                 }
614                 if (vap->va_mtime.tv_sec != VNOVAL) {
615                         DIP_SET(ip, i_mtime, vap->va_mtime.tv_sec);
616                         DIP_SET(ip, i_mtimensec, vap->va_mtime.tv_nsec);
617                 }
618                 if (vap->va_birthtime.tv_sec != VNOVAL &&
619                     ip->i_ump->um_fstype == UFS2) {
620                         ip->i_din2->di_birthtime = vap->va_birthtime.tv_sec;
621                         ip->i_din2->di_birthnsec = vap->va_birthtime.tv_nsec;
622                 }
623                 error = UFS_UPDATE(vp, 0);
624                 if (error)
625                         return (error);
626         }
627         error = 0;
628         if (vap->va_mode != (mode_t)VNOVAL) {
629                 if (vp->v_mount->mnt_flag & MNT_RDONLY)
630                         return (EROFS);
631                 if ((ip->i_flags & SF_SNAPSHOT) != 0 && (vap->va_mode &
632                    (S_IXUSR | S_IWUSR | S_IXGRP | S_IWGRP | S_IXOTH | S_IWOTH)))
633                         return (EPERM);
634                 error = ufs_chmod(vp, (int)vap->va_mode, cred, td);
635         }
636         return (error);
637 }
638
639 /*
640  * Change the mode on a file.
641  * Inode must be locked before calling.
642  */
643 static int
644 ufs_chmod(vp, mode, cred, td)
645         struct vnode *vp;
646         int mode;
647         struct ucred *cred;
648         struct thread *td;
649 {
650         struct inode *ip = VTOI(vp);
651         int error;
652
653         /*
654          * To modify the permissions on a file, must possess VADMIN
655          * for that file.
656          */
657         if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
658                 return (error);
659         /*
660          * Privileged processes may set the sticky bit on non-directories,
661          * as well as set the setgid bit on a file with a group that the
662          * process is not a member of.  Both of these are allowed in
663          * jail(8).
664          */
665         if (vp->v_type != VDIR && (mode & S_ISTXT)) {
666                 if (priv_check_cred(cred, PRIV_VFS_STICKYFILE,
667                     SUSER_ALLOWJAIL))
668                         return (EFTYPE);
669         }
670         if (!groupmember(ip->i_gid, cred) && (mode & ISGID)) {
671                 error = priv_check_cred(cred, PRIV_VFS_SETGID,
672                     SUSER_ALLOWJAIL);
673                 if (error)
674                         return (error);
675         }
676         ip->i_mode &= ~ALLPERMS;
677         ip->i_mode |= (mode & ALLPERMS);
678         DIP_SET(ip, i_mode, ip->i_mode);
679         ip->i_flag |= IN_CHANGE;
680         return (0);
681 }
682
683 /*
684  * Perform chown operation on inode ip;
685  * inode must be locked prior to call.
686  */
687 static int
688 ufs_chown(vp, uid, gid, cred, td)
689         struct vnode *vp;
690         uid_t uid;
691         gid_t gid;
692         struct ucred *cred;
693         struct thread *td;
694 {
695         struct inode *ip = VTOI(vp);
696         uid_t ouid;
697         gid_t ogid;
698         int error = 0;
699 #ifdef QUOTA
700         int i;
701         ufs2_daddr_t change;
702 #endif
703
704         if (uid == (uid_t)VNOVAL)
705                 uid = ip->i_uid;
706         if (gid == (gid_t)VNOVAL)
707                 gid = ip->i_gid;
708         /*
709          * To modify the ownership of a file, must possess VADMIN for that
710          * file.
711          */
712         if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
713                 return (error);
714         /*
715          * To change the owner of a file, or change the group of a file to a
716          * group of which we are not a member, the caller must have
717          * privilege.
718          */
719         if ((uid != ip->i_uid || 
720             (gid != ip->i_gid && !groupmember(gid, cred))) &&
721             (error = priv_check_cred(cred, PRIV_VFS_CHOWN, SUSER_ALLOWJAIL)))
722                 return (error);
723         ogid = ip->i_gid;
724         ouid = ip->i_uid;
725 #ifdef QUOTA
726         if ((error = getinoquota(ip)) != 0)
727                 return (error);
728         if (ouid == uid) {
729                 dqrele(vp, ip->i_dquot[USRQUOTA]);
730                 ip->i_dquot[USRQUOTA] = NODQUOT;
731         }
732         if (ogid == gid) {
733                 dqrele(vp, ip->i_dquot[GRPQUOTA]);
734                 ip->i_dquot[GRPQUOTA] = NODQUOT;
735         }
736         change = DIP(ip, i_blocks);
737         (void) chkdq(ip, -change, cred, CHOWN);
738         (void) chkiq(ip, -1, cred, CHOWN);
739         for (i = 0; i < MAXQUOTAS; i++) {
740                 dqrele(vp, ip->i_dquot[i]);
741                 ip->i_dquot[i] = NODQUOT;
742         }
743 #endif
744         ip->i_gid = gid;
745         DIP_SET(ip, i_gid, gid);
746         ip->i_uid = uid;
747         DIP_SET(ip, i_uid, uid);
748 #ifdef QUOTA
749         if ((error = getinoquota(ip)) == 0) {
750                 if (ouid == uid) {
751                         dqrele(vp, ip->i_dquot[USRQUOTA]);
752                         ip->i_dquot[USRQUOTA] = NODQUOT;
753                 }
754                 if (ogid == gid) {
755                         dqrele(vp, ip->i_dquot[GRPQUOTA]);
756                         ip->i_dquot[GRPQUOTA] = NODQUOT;
757                 }
758                 if ((error = chkdq(ip, change, cred, CHOWN)) == 0) {
759                         if ((error = chkiq(ip, 1, cred, CHOWN)) == 0)
760                                 goto good;
761                         else
762                                 (void) chkdq(ip, -change, cred, CHOWN|FORCE);
763                 }
764                 for (i = 0; i < MAXQUOTAS; i++) {
765                         dqrele(vp, ip->i_dquot[i]);
766                         ip->i_dquot[i] = NODQUOT;
767                 }
768         }
769         ip->i_gid = ogid;
770         DIP_SET(ip, i_gid, ogid);
771         ip->i_uid = ouid;
772         DIP_SET(ip, i_uid, ouid);
773         if (getinoquota(ip) == 0) {
774                 if (ouid == uid) {
775                         dqrele(vp, ip->i_dquot[USRQUOTA]);
776                         ip->i_dquot[USRQUOTA] = NODQUOT;
777                 }
778                 if (ogid == gid) {
779                         dqrele(vp, ip->i_dquot[GRPQUOTA]);
780                         ip->i_dquot[GRPQUOTA] = NODQUOT;
781                 }
782                 (void) chkdq(ip, change, cred, FORCE|CHOWN);
783                 (void) chkiq(ip, 1, cred, FORCE|CHOWN);
784                 (void) getinoquota(ip);
785         }
786         return (error);
787 good:
788         if (getinoquota(ip))
789                 panic("ufs_chown: lost quota");
790 #endif /* QUOTA */
791         ip->i_flag |= IN_CHANGE;
792         if ((ip->i_mode & (ISUID | ISGID)) && (ouid != uid || ogid != gid)) {
793                 if (priv_check_cred(cred, PRIV_VFS_RETAINSUGID,
794                     SUSER_ALLOWJAIL)) {
795                         ip->i_mode &= ~(ISUID | ISGID);
796                         DIP_SET(ip, i_mode, ip->i_mode);
797                 }
798         }
799         return (0);
800 }
801
802 static int
803 ufs_remove(ap)
804         struct vop_remove_args /* {
805                 struct vnode *a_dvp;
806                 struct vnode *a_vp;
807                 struct componentname *a_cnp;
808         } */ *ap;
809 {
810         struct inode *ip;
811         struct vnode *vp = ap->a_vp;
812         struct vnode *dvp = ap->a_dvp;
813         int error;
814         struct thread *td;
815
816         td = curthread;
817         ip = VTOI(vp);
818         if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
819             (VTOI(dvp)->i_flags & APPEND)) {
820                 error = EPERM;
821                 goto out;
822         }
823 #ifdef UFS_GJOURNAL
824         ufs_gjournal_orphan(vp);
825 #endif
826         error = ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0);
827         if (ip->i_nlink <= 0)
828                 vp->v_vflag |= VV_NOSYNC;
829         if ((ip->i_flags & SF_SNAPSHOT) != 0) {
830                 /*
831                  * Avoid deadlock where another thread is trying to
832                  * update the inodeblock for dvp and is waiting on
833                  * snaplk.  Temporary unlock the vnode lock for the
834                  * unlinked file and sync the directory.  This should
835                  * allow vput() of the directory to not block later on
836                  * while holding the snapshot vnode locked, assuming
837                  * that the directory hasn't been unlinked too.
838                  */
839                 VOP_UNLOCK(vp, 0, td);
840                 (void) VOP_FSYNC(dvp, MNT_WAIT, td);
841                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
842         }
843 out:
844         return (error);
845 }
846
847 /*
848  * link vnode call
849  */
850 static int
851 ufs_link(ap)
852         struct vop_link_args /* {
853                 struct vnode *a_tdvp;
854                 struct vnode *a_vp;
855                 struct componentname *a_cnp;
856         } */ *ap;
857 {
858         struct vnode *vp = ap->a_vp;
859         struct vnode *tdvp = ap->a_tdvp;
860         struct componentname *cnp = ap->a_cnp;
861         struct inode *ip;
862         struct direct newdir;
863         int error;
864
865 #ifdef DIAGNOSTIC
866         if ((cnp->cn_flags & HASBUF) == 0)
867                 panic("ufs_link: no name");
868 #endif
869         if (tdvp->v_mount != vp->v_mount) {
870                 error = EXDEV;
871                 goto out;
872         }
873         ip = VTOI(vp);
874         if ((nlink_t)ip->i_nlink >= LINK_MAX) {
875                 error = EMLINK;
876                 goto out;
877         }
878         if (ip->i_flags & (IMMUTABLE | APPEND)) {
879                 error = EPERM;
880                 goto out;
881         }
882         ip->i_effnlink++;
883         ip->i_nlink++;
884         DIP_SET(ip, i_nlink, ip->i_nlink);
885         ip->i_flag |= IN_CHANGE;
886         if (DOINGSOFTDEP(vp))
887                 softdep_change_linkcnt(ip);
888         error = UFS_UPDATE(vp, !(DOINGSOFTDEP(vp) | DOINGASYNC(vp)));
889         if (!error) {
890                 ufs_makedirentry(ip, cnp, &newdir);
891                 error = ufs_direnter(tdvp, vp, &newdir, cnp, NULL);
892         }
893
894         if (error) {
895                 ip->i_effnlink--;
896                 ip->i_nlink--;
897                 DIP_SET(ip, i_nlink, ip->i_nlink);
898                 ip->i_flag |= IN_CHANGE;
899                 if (DOINGSOFTDEP(vp))
900                         softdep_change_linkcnt(ip);
901         }
902 out:
903         return (error);
904 }
905
906 /*
907  * whiteout vnode call
908  */
909 static int
910 ufs_whiteout(ap)
911         struct vop_whiteout_args /* {
912                 struct vnode *a_dvp;
913                 struct componentname *a_cnp;
914                 int a_flags;
915         } */ *ap;
916 {
917         struct vnode *dvp = ap->a_dvp;
918         struct componentname *cnp = ap->a_cnp;
919         struct direct newdir;
920         int error = 0;
921
922         switch (ap->a_flags) {
923         case LOOKUP:
924                 /* 4.4 format directories support whiteout operations */
925                 if (dvp->v_mount->mnt_maxsymlinklen > 0)
926                         return (0);
927                 return (EOPNOTSUPP);
928
929         case CREATE:
930                 /* create a new directory whiteout */
931 #ifdef DIAGNOSTIC
932                 if ((cnp->cn_flags & SAVENAME) == 0)
933                         panic("ufs_whiteout: missing name");
934                 if (dvp->v_mount->mnt_maxsymlinklen <= 0)
935                         panic("ufs_whiteout: old format filesystem");
936 #endif
937
938                 newdir.d_ino = WINO;
939                 newdir.d_namlen = cnp->cn_namelen;
940                 bcopy(cnp->cn_nameptr, newdir.d_name, (unsigned)cnp->cn_namelen + 1);
941                 newdir.d_type = DT_WHT;
942                 error = ufs_direnter(dvp, NULL, &newdir, cnp, NULL);
943                 break;
944
945         case DELETE:
946                 /* remove an existing directory whiteout */
947 #ifdef DIAGNOSTIC
948                 if (dvp->v_mount->mnt_maxsymlinklen <= 0)
949                         panic("ufs_whiteout: old format filesystem");
950 #endif
951
952                 cnp->cn_flags &= ~DOWHITEOUT;
953                 error = ufs_dirremove(dvp, NULL, cnp->cn_flags, 0);
954                 break;
955         default:
956                 panic("ufs_whiteout: unknown op");
957         }
958         return (error);
959 }
960
961 /*
962  * Rename system call.
963  *      rename("foo", "bar");
964  * is essentially
965  *      unlink("bar");
966  *      link("foo", "bar");
967  *      unlink("foo");
968  * but ``atomically''.  Can't do full commit without saving state in the
969  * inode on disk which isn't feasible at this time.  Best we can do is
970  * always guarantee the target exists.
971  *
972  * Basic algorithm is:
973  *
974  * 1) Bump link count on source while we're linking it to the
975  *    target.  This also ensure the inode won't be deleted out
976  *    from underneath us while we work (it may be truncated by
977  *    a concurrent `trunc' or `open' for creation).
978  * 2) Link source to destination.  If destination already exists,
979  *    delete it first.
980  * 3) Unlink source reference to inode if still around. If a
981  *    directory was moved and the parent of the destination
982  *    is different from the source, patch the ".." entry in the
983  *    directory.
984  */
985 static int
986 ufs_rename(ap)
987         struct vop_rename_args  /* {
988                 struct vnode *a_fdvp;
989                 struct vnode *a_fvp;
990                 struct componentname *a_fcnp;
991                 struct vnode *a_tdvp;
992                 struct vnode *a_tvp;
993                 struct componentname *a_tcnp;
994         } */ *ap;
995 {
996         struct vnode *tvp = ap->a_tvp;
997         struct vnode *tdvp = ap->a_tdvp;
998         struct vnode *fvp = ap->a_fvp;
999         struct vnode *fdvp = ap->a_fdvp;
1000         struct componentname *tcnp = ap->a_tcnp;
1001         struct componentname *fcnp = ap->a_fcnp;
1002         struct thread *td = fcnp->cn_thread;
1003         struct inode *ip, *xp, *dp;
1004         struct direct newdir;
1005         int doingdirectory = 0, oldparent = 0, newparent = 0;
1006         int error = 0, ioflag;
1007
1008 #ifdef DIAGNOSTIC
1009         if ((tcnp->cn_flags & HASBUF) == 0 ||
1010             (fcnp->cn_flags & HASBUF) == 0)
1011                 panic("ufs_rename: no name");
1012 #endif
1013         /*
1014          * Check for cross-device rename.
1015          */
1016         if ((fvp->v_mount != tdvp->v_mount) ||
1017             (tvp && (fvp->v_mount != tvp->v_mount))) {
1018                 error = EXDEV;
1019 abortit:
1020                 if (tdvp == tvp)
1021                         vrele(tdvp);
1022                 else
1023                         vput(tdvp);
1024                 if (tvp)
1025                         vput(tvp);
1026                 vrele(fdvp);
1027                 vrele(fvp);
1028                 return (error);
1029         }
1030
1031         if (tvp && ((VTOI(tvp)->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
1032             (VTOI(tdvp)->i_flags & APPEND))) {
1033                 error = EPERM;
1034                 goto abortit;
1035         }
1036
1037         /*
1038          * Renaming a file to itself has no effect.  The upper layers should
1039          * not call us in that case.  Temporarily just warn if they do.
1040          */
1041         if (fvp == tvp) {
1042                 printf("ufs_rename: fvp == tvp (can't happen)\n");
1043                 error = 0;
1044                 goto abortit;
1045         }
1046
1047         if ((error = vn_lock(fvp, LK_EXCLUSIVE, td)) != 0)
1048                 goto abortit;
1049         dp = VTOI(fdvp);
1050         ip = VTOI(fvp);
1051         if (ip->i_nlink >= LINK_MAX) {
1052                 VOP_UNLOCK(fvp, 0, td);
1053                 error = EMLINK;
1054                 goto abortit;
1055         }
1056         if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND))
1057             || (dp->i_flags & APPEND)) {
1058                 VOP_UNLOCK(fvp, 0, td);
1059                 error = EPERM;
1060                 goto abortit;
1061         }
1062         if ((ip->i_mode & IFMT) == IFDIR) {
1063                 /*
1064                  * Avoid ".", "..", and aliases of "." for obvious reasons.
1065                  */
1066                 if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
1067                     dp == ip || (fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT ||
1068                     (ip->i_flag & IN_RENAME)) {
1069                         VOP_UNLOCK(fvp, 0, td);
1070                         error = EINVAL;
1071                         goto abortit;
1072                 }
1073                 ip->i_flag |= IN_RENAME;
1074                 oldparent = dp->i_number;
1075                 doingdirectory = 1;
1076         }
1077         vrele(fdvp);
1078
1079         /*
1080          * When the target exists, both the directory
1081          * and target vnodes are returned locked.
1082          */
1083         dp = VTOI(tdvp);
1084         xp = NULL;
1085         if (tvp)
1086                 xp = VTOI(tvp);
1087
1088         /*
1089          * 1) Bump link count while we're moving stuff
1090          *    around.  If we crash somewhere before
1091          *    completing our work, the link count
1092          *    may be wrong, but correctable.
1093          */
1094         ip->i_effnlink++;
1095         ip->i_nlink++;
1096         DIP_SET(ip, i_nlink, ip->i_nlink);
1097         ip->i_flag |= IN_CHANGE;
1098         if (DOINGSOFTDEP(fvp))
1099                 softdep_change_linkcnt(ip);
1100         if ((error = UFS_UPDATE(fvp, !(DOINGSOFTDEP(fvp) |
1101                                        DOINGASYNC(fvp)))) != 0) {
1102                 VOP_UNLOCK(fvp, 0, td);
1103                 goto bad;
1104         }
1105
1106         /*
1107          * If ".." must be changed (ie the directory gets a new
1108          * parent) then the source directory must not be in the
1109          * directory hierarchy above the target, as this would
1110          * orphan everything below the source directory. Also
1111          * the user must have write permission in the source so
1112          * as to be able to change "..". We must repeat the call
1113          * to namei, as the parent directory is unlocked by the
1114          * call to checkpath().
1115          */
1116         error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_thread);
1117         VOP_UNLOCK(fvp, 0, td);
1118         if (oldparent != dp->i_number)
1119                 newparent = dp->i_number;
1120         if (doingdirectory && newparent) {
1121                 if (error)      /* write access check above */
1122                         goto bad;
1123                 if (xp != NULL)
1124                         vput(tvp);
1125                 error = ufs_checkpath(ip, dp, tcnp->cn_cred);
1126                 if (error)
1127                         goto out;
1128                 if ((tcnp->cn_flags & SAVESTART) == 0)
1129                         panic("ufs_rename: lost to startdir");
1130                 VREF(tdvp);
1131                 error = relookup(tdvp, &tvp, tcnp);
1132                 if (error)
1133                         goto out;
1134                 vrele(tdvp);
1135                 dp = VTOI(tdvp);
1136                 xp = NULL;
1137                 if (tvp)
1138                         xp = VTOI(tvp);
1139         }
1140         /*
1141          * 2) If target doesn't exist, link the target
1142          *    to the source and unlink the source.
1143          *    Otherwise, rewrite the target directory
1144          *    entry to reference the source inode and
1145          *    expunge the original entry's existence.
1146          */
1147         if (xp == NULL) {
1148                 if (dp->i_dev != ip->i_dev)
1149                         panic("ufs_rename: EXDEV");
1150                 /*
1151                  * Account for ".." in new directory.
1152                  * When source and destination have the same
1153                  * parent we don't fool with the link count.
1154                  */
1155                 if (doingdirectory && newparent) {
1156                         if ((nlink_t)dp->i_nlink >= LINK_MAX) {
1157                                 error = EMLINK;
1158                                 goto bad;
1159                         }
1160                         dp->i_effnlink++;
1161                         dp->i_nlink++;
1162                         DIP_SET(dp, i_nlink, dp->i_nlink);
1163                         dp->i_flag |= IN_CHANGE;
1164                         if (DOINGSOFTDEP(tdvp))
1165                                 softdep_change_linkcnt(dp);
1166                         error = UFS_UPDATE(tdvp, !(DOINGSOFTDEP(tdvp) |
1167                                                    DOINGASYNC(tdvp)));
1168                         if (error)
1169                                 goto bad;
1170                 }
1171                 ufs_makedirentry(ip, tcnp, &newdir);
1172                 error = ufs_direnter(tdvp, NULL, &newdir, tcnp, NULL);
1173                 if (error) {
1174                         if (doingdirectory && newparent) {
1175                                 dp->i_effnlink--;
1176                                 dp->i_nlink--;
1177                                 DIP_SET(dp, i_nlink, dp->i_nlink);
1178                                 dp->i_flag |= IN_CHANGE;
1179                                 if (DOINGSOFTDEP(tdvp))
1180                                         softdep_change_linkcnt(dp);
1181                                 (void)UFS_UPDATE(tdvp, 1);
1182                         }
1183                         goto bad;
1184                 }
1185                 vput(tdvp);
1186         } else {
1187                 if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev)
1188                         panic("ufs_rename: EXDEV");
1189                 /*
1190                  * Short circuit rename(foo, foo).
1191                  */
1192                 if (xp->i_number == ip->i_number)
1193                         panic("ufs_rename: same file");
1194                 /*
1195                  * If the parent directory is "sticky", then the caller
1196                  * must possess VADMIN for the parent directory, or the
1197                  * destination of the rename.  This implements append-only
1198                  * directories.
1199                  */
1200                 if ((dp->i_mode & S_ISTXT) &&
1201                     VOP_ACCESS(tdvp, VADMIN, tcnp->cn_cred, td) &&
1202                     VOP_ACCESS(tvp, VADMIN, tcnp->cn_cred, td)) {
1203                         error = EPERM;
1204                         goto bad;
1205                 }
1206                 /*
1207                  * Target must be empty if a directory and have no links
1208                  * to it. Also, ensure source and target are compatible
1209                  * (both directories, or both not directories).
1210                  */
1211                 if ((xp->i_mode&IFMT) == IFDIR) {
1212                         if ((xp->i_effnlink > 2) ||
1213                             !ufs_dirempty(xp, dp->i_number, tcnp->cn_cred)) {
1214                                 error = ENOTEMPTY;
1215                                 goto bad;
1216                         }
1217                         if (!doingdirectory) {
1218                                 error = ENOTDIR;
1219                                 goto bad;
1220                         }
1221                         cache_purge(tdvp);
1222                 } else if (doingdirectory) {
1223                         error = EISDIR;
1224                         goto bad;
1225                 }
1226                 error = ufs_dirrewrite(dp, xp, ip->i_number,
1227                     IFTODT(ip->i_mode),
1228                     (doingdirectory && newparent) ? newparent : doingdirectory);
1229                 if (error)
1230                         goto bad;
1231                 if (doingdirectory) {
1232                         if (!newparent) {
1233                                 dp->i_effnlink--;
1234                                 if (DOINGSOFTDEP(tdvp))
1235                                         softdep_change_linkcnt(dp);
1236                         }
1237                         xp->i_effnlink--;
1238                         if (DOINGSOFTDEP(tvp))
1239                                 softdep_change_linkcnt(xp);
1240                 }
1241                 if (doingdirectory && !DOINGSOFTDEP(tvp)) {
1242                         /*
1243                          * Truncate inode. The only stuff left in the directory
1244                          * is "." and "..". The "." reference is inconsequential
1245                          * since we are quashing it. We have removed the "."
1246                          * reference and the reference in the parent directory,
1247                          * but there may be other hard links. The soft
1248                          * dependency code will arrange to do these operations
1249                          * after the parent directory entry has been deleted on
1250                          * disk, so when running with that code we avoid doing
1251                          * them now.
1252                          */
1253                         if (!newparent) {
1254                                 dp->i_nlink--;
1255                                 DIP_SET(dp, i_nlink, dp->i_nlink);
1256                                 dp->i_flag |= IN_CHANGE;
1257                         }
1258                         xp->i_nlink--;
1259                         DIP_SET(xp, i_nlink, xp->i_nlink);
1260                         xp->i_flag |= IN_CHANGE;
1261                         ioflag = IO_NORMAL;
1262                         if (!DOINGASYNC(tvp))
1263                                 ioflag |= IO_SYNC;
1264                         if ((error = UFS_TRUNCATE(tvp, (off_t)0, ioflag,
1265                             tcnp->cn_cred, tcnp->cn_thread)) != 0)
1266                                 goto bad;
1267                 }
1268                 vput(tdvp);
1269                 vput(tvp);
1270                 xp = NULL;
1271         }
1272
1273         /*
1274          * 3) Unlink the source.
1275          */
1276         fcnp->cn_flags &= ~MODMASK;
1277         fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
1278         if ((fcnp->cn_flags & SAVESTART) == 0)
1279                 panic("ufs_rename: lost from startdir");
1280         VREF(fdvp);
1281         error = relookup(fdvp, &fvp, fcnp);
1282         if (error == 0)
1283                 vrele(fdvp);
1284         if (fvp != NULL) {
1285                 xp = VTOI(fvp);
1286                 dp = VTOI(fdvp);
1287         } else {
1288                 /*
1289                  * From name has disappeared.  IN_RENAME is not sufficient
1290                  * to protect against directory races due to timing windows,
1291                  * so we have to remove the panic.  XXX the only real way
1292                  * to solve this issue is at a much higher level.  By the
1293                  * time we hit ufs_rename() it's too late.
1294                  */
1295 #if 0
1296                 if (doingdirectory)
1297                         panic("ufs_rename: lost dir entry");
1298 #endif
1299                 vrele(ap->a_fvp);
1300                 return (0);
1301         }
1302         /*
1303          * Ensure that the directory entry still exists and has not
1304          * changed while the new name has been entered. If the source is
1305          * a file then the entry may have been unlinked or renamed. In
1306          * either case there is no further work to be done. If the source
1307          * is a directory then it cannot have been rmdir'ed; the IN_RENAME
1308          * flag ensures that it cannot be moved by another rename or removed
1309          * by a rmdir.
1310          */
1311         if (xp != ip) {
1312                 /*
1313                  * From name resolves to a different inode.  IN_RENAME is
1314                  * not sufficient protection against timing window races
1315                  * so we can't panic here.  XXX the only real way
1316                  * to solve this issue is at a much higher level.  By the
1317                  * time we hit ufs_rename() it's too late.
1318                  */
1319 #if 0
1320                 if (doingdirectory)
1321                         panic("ufs_rename: lost dir entry");
1322 #endif
1323         } else {
1324                 /*
1325                  * If the source is a directory with a
1326                  * new parent, the link count of the old
1327                  * parent directory must be decremented
1328                  * and ".." set to point to the new parent.
1329                  */
1330                 if (doingdirectory && newparent) {
1331                         xp->i_offset = mastertemplate.dot_reclen;
1332                         ufs_dirrewrite(xp, dp, newparent, DT_DIR, 0);
1333                         cache_purge(fdvp);
1334                 }
1335                 error = ufs_dirremove(fdvp, xp, fcnp->cn_flags, 0);
1336                 xp->i_flag &= ~IN_RENAME;
1337         }
1338         if (dp)
1339                 vput(fdvp);
1340         if (xp)
1341                 vput(fvp);
1342         vrele(ap->a_fvp);
1343         return (error);
1344
1345 bad:
1346         if (xp)
1347                 vput(ITOV(xp));
1348         vput(ITOV(dp));
1349 out:
1350         if (doingdirectory)
1351                 ip->i_flag &= ~IN_RENAME;
1352         if (vn_lock(fvp, LK_EXCLUSIVE, td) == 0) {
1353                 ip->i_effnlink--;
1354                 ip->i_nlink--;
1355                 DIP_SET(ip, i_nlink, ip->i_nlink);
1356                 ip->i_flag |= IN_CHANGE;
1357                 ip->i_flag &= ~IN_RENAME;
1358                 if (DOINGSOFTDEP(fvp))
1359                         softdep_change_linkcnt(ip);
1360                 vput(fvp);
1361         } else
1362                 vrele(fvp);
1363         return (error);
1364 }
1365
1366 /*
1367  * Mkdir system call
1368  */
1369 static int
1370 ufs_mkdir(ap)
1371         struct vop_mkdir_args /* {
1372                 struct vnode *a_dvp;
1373                 struct vnode **a_vpp;
1374                 struct componentname *a_cnp;
1375                 struct vattr *a_vap;
1376         } */ *ap;
1377 {
1378         struct vnode *dvp = ap->a_dvp;
1379         struct vattr *vap = ap->a_vap;
1380         struct componentname *cnp = ap->a_cnp;
1381         struct inode *ip, *dp;
1382         struct vnode *tvp;
1383         struct buf *bp;
1384         struct dirtemplate dirtemplate, *dtp;
1385         struct direct newdir;
1386 #ifdef UFS_ACL
1387         struct acl *acl, *dacl;
1388 #endif
1389         int error, dmode;
1390         long blkoff;
1391
1392 #ifdef DIAGNOSTIC
1393         if ((cnp->cn_flags & HASBUF) == 0)
1394                 panic("ufs_mkdir: no name");
1395 #endif
1396         dp = VTOI(dvp);
1397         if ((nlink_t)dp->i_nlink >= LINK_MAX) {
1398                 error = EMLINK;
1399                 goto out;
1400         }
1401         dmode = vap->va_mode & 0777;
1402         dmode |= IFDIR;
1403         /*
1404          * Must simulate part of ufs_makeinode here to acquire the inode,
1405          * but not have it entered in the parent directory. The entry is
1406          * made later after writing "." and ".." entries.
1407          */
1408         error = UFS_VALLOC(dvp, dmode, cnp->cn_cred, &tvp);
1409         if (error)
1410                 goto out;
1411         ip = VTOI(tvp);
1412         ip->i_gid = dp->i_gid;
1413         DIP_SET(ip, i_gid, dp->i_gid);
1414 #ifdef SUIDDIR
1415         {
1416 #ifdef QUOTA
1417                 struct ucred ucred, *ucp;
1418                 ucp = cnp->cn_cred;
1419 #endif
1420                 /*
1421                  * If we are hacking owners here, (only do this where told to)
1422                  * and we are not giving it TO root, (would subvert quotas)
1423                  * then go ahead and give it to the other user.
1424                  * The new directory also inherits the SUID bit.
1425                  * If user's UID and dir UID are the same,
1426                  * 'give it away' so that the SUID is still forced on.
1427                  */
1428                 if ((dvp->v_mount->mnt_flag & MNT_SUIDDIR) &&
1429                     (dp->i_mode & ISUID) && dp->i_uid) {
1430                         dmode |= ISUID;
1431                         ip->i_uid = dp->i_uid;
1432                         DIP_SET(ip, i_uid, dp->i_uid);
1433 #ifdef QUOTA
1434                         if (dp->i_uid != cnp->cn_cred->cr_uid) {
1435                                 /*
1436                                  * Make sure the correct user gets charged
1437                                  * for the space.
1438                                  * Make a dummy credential for the victim.
1439                                  * XXX This seems to never be accessed out of
1440                                  * our context so a stack variable is ok.
1441                                  */
1442                                 refcount_init(&ucred.cr_ref, 1);
1443                                 ucred.cr_uid = ip->i_uid;
1444                                 ucred.cr_ngroups = 1;
1445                                 ucred.cr_groups[0] = dp->i_gid;
1446                                 ucp = &ucred;
1447                         }
1448 #endif
1449                 } else {
1450                         ip->i_uid = cnp->cn_cred->cr_uid;
1451                         DIP_SET(ip, i_uid, ip->i_uid);
1452                 }
1453 #ifdef QUOTA
1454                 if ((error = getinoquota(ip)) ||
1455                     (error = chkiq(ip, 1, ucp, 0))) {
1456                         UFS_VFREE(tvp, ip->i_number, dmode);
1457                         vput(tvp);
1458                         return (error);
1459                 }
1460 #endif
1461         }
1462 #else   /* !SUIDDIR */
1463         ip->i_uid = cnp->cn_cred->cr_uid;
1464         DIP_SET(ip, i_uid, ip->i_uid);
1465 #ifdef QUOTA
1466         if ((error = getinoquota(ip)) ||
1467             (error = chkiq(ip, 1, cnp->cn_cred, 0))) {
1468                 UFS_VFREE(tvp, ip->i_number, dmode);
1469                 vput(tvp);
1470                 return (error);
1471         }
1472 #endif
1473 #endif  /* !SUIDDIR */
1474         ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
1475 #ifdef UFS_ACL
1476         acl = dacl = NULL;
1477         if ((dvp->v_mount->mnt_flag & MNT_ACLS) != 0) {
1478                 acl = uma_zalloc(acl_zone, M_WAITOK);
1479                 dacl = uma_zalloc(acl_zone, M_WAITOK);
1480
1481                 /*
1482                  * Retrieve default ACL from parent, if any.
1483                  */
1484                 error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cnp->cn_cred,
1485                     cnp->cn_thread);
1486                 switch (error) {
1487                 case 0:
1488                         /*
1489                          * Retrieved a default ACL, so merge mode and ACL if
1490                          * necessary.  If the ACL is empty, fall through to
1491                          * the "not defined or available" case.
1492                          */
1493                         if (acl->acl_cnt != 0) {
1494                                 dmode = acl_posix1e_newfilemode(dmode, acl);
1495                                 ip->i_mode = dmode;
1496                                 DIP_SET(ip, i_mode, dmode);
1497                                 *dacl = *acl;
1498                                 ufs_sync_acl_from_inode(ip, acl);
1499                                 break;
1500                         }
1501                         /* FALLTHROUGH */
1502         
1503                 case EOPNOTSUPP:
1504                         /*
1505                          * Just use the mode as-is.
1506                          */
1507                         ip->i_mode = dmode;
1508                         DIP_SET(ip, i_mode, dmode);
1509                         uma_zfree(acl_zone, acl);
1510                         uma_zfree(acl_zone, dacl);
1511                         dacl = acl = NULL;
1512                         break;
1513                 
1514                 default:
1515                         UFS_VFREE(tvp, ip->i_number, dmode);
1516                         vput(tvp);
1517                         uma_zfree(acl_zone, acl);
1518                         uma_zfree(acl_zone, dacl);
1519                         return (error);
1520                 }
1521         } else {
1522 #endif /* !UFS_ACL */
1523                 ip->i_mode = dmode;
1524                 DIP_SET(ip, i_mode, dmode);
1525 #ifdef UFS_ACL
1526         }
1527 #endif
1528         tvp->v_type = VDIR;     /* Rest init'd in getnewvnode(). */
1529         ip->i_effnlink = 2;
1530         ip->i_nlink = 2;
1531         DIP_SET(ip, i_nlink, 2);
1532         if (DOINGSOFTDEP(tvp))
1533                 softdep_change_linkcnt(ip);
1534         if (cnp->cn_flags & ISWHITEOUT) {
1535                 ip->i_flags |= UF_OPAQUE;
1536                 DIP_SET(ip, i_flags, ip->i_flags);
1537         }
1538
1539         /*
1540          * Bump link count in parent directory to reflect work done below.
1541          * Should be done before reference is created so cleanup is
1542          * possible if we crash.
1543          */
1544         dp->i_effnlink++;
1545         dp->i_nlink++;
1546         DIP_SET(dp, i_nlink, dp->i_nlink);
1547         dp->i_flag |= IN_CHANGE;
1548         if (DOINGSOFTDEP(dvp))
1549                 softdep_change_linkcnt(dp);
1550         error = UFS_UPDATE(tvp, !(DOINGSOFTDEP(dvp) | DOINGASYNC(dvp)));
1551         if (error)
1552                 goto bad;
1553 #ifdef MAC
1554         if (dvp->v_mount->mnt_flag & MNT_MULTILABEL) {
1555                 error = mac_create_vnode_extattr(cnp->cn_cred, dvp->v_mount,
1556                     dvp, tvp, cnp);
1557                 if (error)
1558                         goto bad;
1559         }
1560 #endif
1561 #ifdef UFS_ACL
1562         if (acl != NULL) {
1563                 /*
1564                  * XXX: If we abort now, will Soft Updates notify the extattr
1565                  * code that the EAs for the file need to be released?
1566                  */
1567                 error = VOP_SETACL(tvp, ACL_TYPE_ACCESS, acl, cnp->cn_cred,
1568                     cnp->cn_thread);
1569                 if (error == 0)
1570                         error = VOP_SETACL(tvp, ACL_TYPE_DEFAULT, dacl,
1571                             cnp->cn_cred, cnp->cn_thread);
1572                 switch (error) {
1573                 case 0:
1574                         break;
1575
1576                 case EOPNOTSUPP:
1577                         /*
1578                          * XXX: This should not happen, as EOPNOTSUPP above
1579                          * was supposed to free acl.
1580                          */
1581                         printf("ufs_mkdir: VOP_GETACL() but no VOP_SETACL()\n");
1582                         /*
1583                         panic("ufs_mkdir: VOP_GETACL() but no VOP_SETACL()");
1584                          */
1585                         break;
1586
1587                 default:
1588                         uma_zfree(acl_zone, acl);
1589                         uma_zfree(acl_zone, dacl);
1590                         dacl = acl = NULL;
1591                         goto bad;
1592                 }
1593                 uma_zfree(acl_zone, acl);
1594                 uma_zfree(acl_zone, dacl);
1595                 dacl = acl = NULL;
1596         }
1597 #endif /* !UFS_ACL */
1598
1599         /*
1600          * Initialize directory with "." and ".." from static template.
1601          */
1602         if (dvp->v_mount->mnt_maxsymlinklen > 0)
1603                 dtp = &mastertemplate;
1604         else
1605                 dtp = (struct dirtemplate *)&omastertemplate;
1606         dirtemplate = *dtp;
1607         dirtemplate.dot_ino = ip->i_number;
1608         dirtemplate.dotdot_ino = dp->i_number;
1609         if ((error = UFS_BALLOC(tvp, (off_t)0, DIRBLKSIZ, cnp->cn_cred,
1610             BA_CLRBUF, &bp)) != 0)
1611                 goto bad;
1612         ip->i_size = DIRBLKSIZ;
1613         DIP_SET(ip, i_size, DIRBLKSIZ);
1614         ip->i_flag |= IN_CHANGE | IN_UPDATE;
1615         vnode_pager_setsize(tvp, (u_long)ip->i_size);
1616         bcopy((caddr_t)&dirtemplate, (caddr_t)bp->b_data, sizeof dirtemplate);
1617         if (DOINGSOFTDEP(tvp)) {
1618                 /*
1619                  * Ensure that the entire newly allocated block is a
1620                  * valid directory so that future growth within the
1621                  * block does not have to ensure that the block is
1622                  * written before the inode.
1623                  */
1624                 blkoff = DIRBLKSIZ;
1625                 while (blkoff < bp->b_bcount) {
1626                         ((struct direct *)
1627                            (bp->b_data + blkoff))->d_reclen = DIRBLKSIZ;
1628                         blkoff += DIRBLKSIZ;
1629                 }
1630         }
1631         if ((error = UFS_UPDATE(tvp, !(DOINGSOFTDEP(tvp) |
1632                                        DOINGASYNC(tvp)))) != 0) {
1633                 (void)bwrite(bp);
1634                 goto bad;
1635         }
1636         /*
1637          * Directory set up, now install its entry in the parent directory.
1638          *
1639          * If we are not doing soft dependencies, then we must write out the
1640          * buffer containing the new directory body before entering the new 
1641          * name in the parent. If we are doing soft dependencies, then the
1642          * buffer containing the new directory body will be passed to and
1643          * released in the soft dependency code after the code has attached
1644          * an appropriate ordering dependency to the buffer which ensures that
1645          * the buffer is written before the new name is written in the parent.
1646          */
1647         if (DOINGASYNC(dvp))
1648                 bdwrite(bp);
1649         else if (!DOINGSOFTDEP(dvp) && ((error = bwrite(bp))))
1650                 goto bad;
1651         ufs_makedirentry(ip, cnp, &newdir);
1652         error = ufs_direnter(dvp, tvp, &newdir, cnp, bp);
1653         
1654 bad:
1655         if (error == 0) {
1656                 *ap->a_vpp = tvp;
1657         } else {
1658 #ifdef UFS_ACL
1659                 if (acl != NULL)
1660                         uma_zfree(acl_zone, acl);
1661                 if (dacl != NULL)
1662                         uma_zfree(acl_zone, dacl);
1663 #endif
1664                 dp->i_effnlink--;
1665                 dp->i_nlink--;
1666                 DIP_SET(dp, i_nlink, dp->i_nlink);
1667                 dp->i_flag |= IN_CHANGE;
1668                 if (DOINGSOFTDEP(dvp))
1669                         softdep_change_linkcnt(dp);
1670                 /*
1671                  * No need to do an explicit VOP_TRUNCATE here, vrele will
1672                  * do this for us because we set the link count to 0.
1673                  */
1674                 ip->i_effnlink = 0;
1675                 ip->i_nlink = 0;
1676                 DIP_SET(ip, i_nlink, 0);
1677                 ip->i_flag |= IN_CHANGE;
1678                 if (DOINGSOFTDEP(tvp))
1679                         softdep_change_linkcnt(ip);
1680                 vput(tvp);
1681         }
1682 out:
1683         return (error);
1684 }
1685
1686 /*
1687  * Rmdir system call.
1688  */
1689 static int
1690 ufs_rmdir(ap)
1691         struct vop_rmdir_args /* {
1692                 struct vnode *a_dvp;
1693                 struct vnode *a_vp;
1694                 struct componentname *a_cnp;
1695         } */ *ap;
1696 {
1697         struct vnode *vp = ap->a_vp;
1698         struct vnode *dvp = ap->a_dvp;
1699         struct componentname *cnp = ap->a_cnp;
1700         struct inode *ip, *dp;
1701         int error, ioflag;
1702
1703         ip = VTOI(vp);
1704         dp = VTOI(dvp);
1705
1706         /*
1707          * Do not remove a directory that is in the process of being renamed.
1708          * Verify the directory is empty (and valid). Rmdir ".." will not be
1709          * valid since ".." will contain a reference to the current directory
1710          * and thus be non-empty. Do not allow the removal of mounted on
1711          * directories (this can happen when an NFS exported filesystem
1712          * tries to remove a locally mounted on directory).
1713          */
1714         error = 0;
1715         if ((ip->i_flag & IN_RENAME) || ip->i_effnlink < 2) {
1716                 error = EINVAL;
1717                 goto out;
1718         }
1719         if (!ufs_dirempty(ip, dp->i_number, cnp->cn_cred)) {
1720                 error = ENOTEMPTY;
1721                 goto out;
1722         }
1723         if ((dp->i_flags & APPEND)
1724             || (ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND))) {
1725                 error = EPERM;
1726                 goto out;
1727         }
1728         if (vp->v_mountedhere != 0) {
1729                 error = EINVAL;
1730                 goto out;
1731         }
1732 #ifdef UFS_GJOURNAL
1733         ufs_gjournal_orphan(vp);
1734 #endif
1735         /*
1736          * Delete reference to directory before purging
1737          * inode.  If we crash in between, the directory
1738          * will be reattached to lost+found,
1739          */
1740         dp->i_effnlink--;
1741         ip->i_effnlink--;
1742         if (DOINGSOFTDEP(vp)) {
1743                 softdep_change_linkcnt(dp);
1744                 softdep_change_linkcnt(ip);
1745         }
1746         error = ufs_dirremove(dvp, ip, cnp->cn_flags, 1);
1747         if (error) {
1748                 dp->i_effnlink++;
1749                 ip->i_effnlink++;
1750                 if (DOINGSOFTDEP(vp)) {
1751                         softdep_change_linkcnt(dp);
1752                         softdep_change_linkcnt(ip);
1753                 }
1754                 goto out;
1755         }
1756         cache_purge(dvp);
1757         /*
1758          * Truncate inode. The only stuff left in the directory is "." and
1759          * "..". The "." reference is inconsequential since we are quashing
1760          * it. The soft dependency code will arrange to do these operations
1761          * after the parent directory entry has been deleted on disk, so
1762          * when running with that code we avoid doing them now.
1763          */
1764         if (!DOINGSOFTDEP(vp)) {
1765                 dp->i_nlink--;
1766                 DIP_SET(dp, i_nlink, dp->i_nlink);
1767                 dp->i_flag |= IN_CHANGE;
1768                 ip->i_nlink--;
1769                 DIP_SET(ip, i_nlink, ip->i_nlink);
1770                 ip->i_flag |= IN_CHANGE;
1771                 ioflag = IO_NORMAL;
1772                 if (!DOINGASYNC(vp))
1773                         ioflag |= IO_SYNC;
1774                 error = UFS_TRUNCATE(vp, (off_t)0, ioflag, cnp->cn_cred,
1775                     cnp->cn_thread);
1776         }
1777         cache_purge(vp);
1778 #ifdef UFS_DIRHASH
1779         /* Kill any active hash; i_effnlink == 0, so it will not come back. */
1780         if (ip->i_dirhash != NULL)
1781                 ufsdirhash_free(ip);
1782 #endif
1783 out:
1784         return (error);
1785 }
1786
1787 /*
1788  * symlink -- make a symbolic link
1789  */
1790 static int
1791 ufs_symlink(ap)
1792         struct vop_symlink_args /* {
1793                 struct vnode *a_dvp;
1794                 struct vnode **a_vpp;
1795                 struct componentname *a_cnp;
1796                 struct vattr *a_vap;
1797                 char *a_target;
1798         } */ *ap;
1799 {
1800         struct vnode *vp, **vpp = ap->a_vpp;
1801         struct inode *ip;
1802         int len, error;
1803
1804         error = ufs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp,
1805             vpp, ap->a_cnp);
1806         if (error)
1807                 return (error);
1808         vp = *vpp;
1809         len = strlen(ap->a_target);
1810         if (len < vp->v_mount->mnt_maxsymlinklen) {
1811                 ip = VTOI(vp);
1812                 bcopy(ap->a_target, SHORTLINK(ip), len);
1813                 ip->i_size = len;
1814                 DIP_SET(ip, i_size, len);
1815                 ip->i_flag |= IN_CHANGE | IN_UPDATE;
1816         } else
1817                 error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0,
1818                     UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK,
1819                     ap->a_cnp->cn_cred, NOCRED, (int *)0, (struct thread *)0);
1820         if (error)
1821                 vput(vp);
1822         return (error);
1823 }
1824
1825 /*
1826  * Vnode op for reading directories.
1827  *
1828  * The routine below assumes that the on-disk format of a directory
1829  * is the same as that defined by <sys/dirent.h>. If the on-disk
1830  * format changes, then it will be necessary to do a conversion
1831  * from the on-disk format that read returns to the format defined
1832  * by <sys/dirent.h>.
1833  */
1834 int
1835 ufs_readdir(ap)
1836         struct vop_readdir_args /* {
1837                 struct vnode *a_vp;
1838                 struct uio *a_uio;
1839                 struct ucred *a_cred;
1840                 int *a_eofflag;
1841                 int *a_ncookies;
1842                 u_long **a_cookies;
1843         } */ *ap;
1844 {
1845         struct uio *uio = ap->a_uio;
1846         int error;
1847         size_t count, lost;
1848         off_t off;
1849
1850         if (ap->a_ncookies != NULL)
1851                 /*
1852                  * Ensure that the block is aligned.  The caller can use
1853                  * the cookies to determine where in the block to start.
1854                  */
1855                 uio->uio_offset &= ~(DIRBLKSIZ - 1);
1856         off = uio->uio_offset;
1857         count = uio->uio_resid;
1858         /* Make sure we don't return partial entries. */
1859         if (count <= ((uio->uio_offset + count) & (DIRBLKSIZ -1)))
1860                 return (EINVAL);
1861         count -= (uio->uio_offset + count) & (DIRBLKSIZ -1);
1862         lost = uio->uio_resid - count;
1863         uio->uio_resid = count;
1864         uio->uio_iov->iov_len = count;
1865 #       if (BYTE_ORDER == LITTLE_ENDIAN)
1866                 if (ap->a_vp->v_mount->mnt_maxsymlinklen > 0) {
1867                         error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred);
1868                 } else {
1869                         struct dirent *dp, *edp;
1870                         struct uio auio;
1871                         struct iovec aiov;
1872                         caddr_t dirbuf;
1873                         int readcnt;
1874                         u_char tmp;
1875
1876                         auio = *uio;
1877                         auio.uio_iov = &aiov;
1878                         auio.uio_iovcnt = 1;
1879                         auio.uio_segflg = UIO_SYSSPACE;
1880                         aiov.iov_len = count;
1881                         MALLOC(dirbuf, caddr_t, count, M_TEMP, M_WAITOK);
1882                         aiov.iov_base = dirbuf;
1883                         error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred);
1884                         if (error == 0) {
1885                                 readcnt = count - auio.uio_resid;
1886                                 edp = (struct dirent *)&dirbuf[readcnt];
1887                                 for (dp = (struct dirent *)dirbuf; dp < edp; ) {
1888                                         tmp = dp->d_namlen;
1889                                         dp->d_namlen = dp->d_type;
1890                                         dp->d_type = tmp;
1891                                         if (dp->d_reclen > 0) {
1892                                                 dp = (struct dirent *)
1893                                                     ((char *)dp + dp->d_reclen);
1894                                         } else {
1895                                                 error = EIO;
1896                                                 break;
1897                                         }
1898                                 }
1899                                 if (dp >= edp)
1900                                         error = uiomove(dirbuf, readcnt, uio);
1901                         }
1902                         FREE(dirbuf, M_TEMP);
1903                 }
1904 #       else
1905                 error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred);
1906 #       endif
1907         if (!error && ap->a_ncookies != NULL) {
1908                 struct dirent* dpStart;
1909                 struct dirent* dpEnd;
1910                 struct dirent* dp;
1911                 int ncookies;
1912                 u_long *cookies;
1913                 u_long *cookiep;
1914
1915                 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
1916                         panic("ufs_readdir: unexpected uio from NFS server");
1917                 dpStart = (struct dirent *)
1918                     ((char *)uio->uio_iov->iov_base - (uio->uio_offset - off));
1919                 dpEnd = (struct dirent *) uio->uio_iov->iov_base;
1920                 for (dp = dpStart, ncookies = 0;
1921                      dp < dpEnd;
1922                      dp = (struct dirent *)((caddr_t) dp + dp->d_reclen))
1923                         ncookies++;
1924                 MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP,
1925                     M_WAITOK);
1926                 for (dp = dpStart, cookiep = cookies;
1927                      dp < dpEnd;
1928                      dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) {
1929                         off += dp->d_reclen;
1930                         *cookiep++ = (u_long) off;
1931                 }
1932                 *ap->a_ncookies = ncookies;
1933                 *ap->a_cookies = cookies;
1934         }
1935         uio->uio_resid += lost;
1936         if (ap->a_eofflag)
1937             *ap->a_eofflag = VTOI(ap->a_vp)->i_size <= uio->uio_offset;
1938         return (error);
1939 }
1940
1941 /*
1942  * Return target name of a symbolic link
1943  */
1944 static int
1945 ufs_readlink(ap)
1946         struct vop_readlink_args /* {
1947                 struct vnode *a_vp;
1948                 struct uio *a_uio;
1949                 struct ucred *a_cred;
1950         } */ *ap;
1951 {
1952         struct vnode *vp = ap->a_vp;
1953         struct inode *ip = VTOI(vp);
1954         doff_t isize;
1955
1956         isize = ip->i_size;
1957         if ((isize < vp->v_mount->mnt_maxsymlinklen) ||
1958             DIP(ip, i_blocks) == 0) { /* XXX - for old fastlink support */
1959                 return (uiomove(SHORTLINK(ip), isize, ap->a_uio));
1960         }
1961         return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
1962 }
1963
1964 /*
1965  * Calculate the logical to physical mapping if not done already,
1966  * then call the device strategy routine.
1967  *
1968  * In order to be able to swap to a file, the ufs_bmaparray() operation may not
1969  * deadlock on memory.  See ufs_bmap() for details.
1970  */
1971 static int
1972 ufs_strategy(ap)
1973         struct vop_strategy_args /* {
1974                 struct vnode *a_vp;
1975                 struct buf *a_bp;
1976         } */ *ap;
1977 {
1978         struct buf *bp = ap->a_bp;
1979         struct vnode *vp = ap->a_vp;
1980         struct bufobj *bo;
1981         struct inode *ip;
1982         ufs2_daddr_t blkno;
1983         int error;
1984
1985         ip = VTOI(vp);
1986         if (bp->b_blkno == bp->b_lblkno) {
1987                 error = ufs_bmaparray(vp, bp->b_lblkno, &blkno, bp, NULL, NULL);
1988                 bp->b_blkno = blkno;
1989                 if (error) {
1990                         bp->b_error = error;
1991                         bp->b_ioflags |= BIO_ERROR;
1992                         bufdone(bp);
1993                         return (error);
1994                 }
1995                 if ((long)bp->b_blkno == -1)
1996                         vfs_bio_clrbuf(bp);
1997         }
1998         if ((long)bp->b_blkno == -1) {
1999                 bufdone(bp);
2000                 return (0);
2001         }
2002         bp->b_iooffset = dbtob(bp->b_blkno);
2003         bo = ip->i_umbufobj;
2004         BO_STRATEGY(bo, bp);
2005         return (0);
2006 }
2007
2008 /*
2009  * Print out the contents of an inode.
2010  */
2011 static int
2012 ufs_print(ap)
2013         struct vop_print_args /* {
2014                 struct vnode *a_vp;
2015         } */ *ap;
2016 {
2017         struct vnode *vp = ap->a_vp;
2018         struct inode *ip = VTOI(vp);
2019
2020         printf("\tino %lu, on dev %s", (u_long)ip->i_number,
2021             devtoname(ip->i_dev));
2022         if (vp->v_type == VFIFO)
2023                 fifo_printinfo(vp);
2024         printf("\n");
2025         return (0);
2026 }
2027
2028 /*
2029  * Close wrapper for fifos.
2030  *
2031  * Update the times on the inode then do device close.
2032  */
2033 static int
2034 ufsfifo_close(ap)
2035         struct vop_close_args /* {
2036                 struct vnode *a_vp;
2037                 int  a_fflag;
2038                 struct ucred *a_cred;
2039                 struct thread *a_td;
2040         } */ *ap;
2041 {
2042         struct vnode *vp = ap->a_vp;
2043         int usecount;
2044
2045         VI_LOCK(vp);
2046         usecount = vp->v_usecount;
2047         if (usecount > 1)
2048                 ufs_itimes_locked(vp);
2049         VI_UNLOCK(vp);
2050         return (fifo_specops.vop_close(ap));
2051 }
2052
2053 /*
2054  * Kqfilter wrapper for fifos.
2055  *
2056  * Fall through to ufs kqfilter routines if needed 
2057  */
2058 static int
2059 ufsfifo_kqfilter(ap)
2060         struct vop_kqfilter_args *ap;
2061 {
2062         int error;
2063
2064         error = fifo_specops.vop_kqfilter(ap);
2065         if (error)
2066                 error = vfs_kqfilter(ap);
2067         return (error);
2068 }
2069
2070 /*
2071  * Return POSIX pathconf information applicable to ufs filesystems.
2072  */
2073 static int
2074 ufs_pathconf(ap)
2075         struct vop_pathconf_args /* {
2076                 struct vnode *a_vp;
2077                 int a_name;
2078                 int *a_retval;
2079         } */ *ap;
2080 {
2081         int error;
2082
2083         error = 0;
2084         switch (ap->a_name) {
2085         case _PC_LINK_MAX:
2086                 *ap->a_retval = LINK_MAX;
2087                 break;
2088         case _PC_NAME_MAX:
2089                 *ap->a_retval = NAME_MAX;
2090                 break;
2091         case _PC_PATH_MAX:
2092                 *ap->a_retval = PATH_MAX;
2093                 break;
2094         case _PC_PIPE_BUF:
2095                 *ap->a_retval = PIPE_BUF;
2096                 break;
2097         case _PC_CHOWN_RESTRICTED:
2098                 *ap->a_retval = 1;
2099                 break;
2100         case _PC_NO_TRUNC:
2101                 *ap->a_retval = 1;
2102                 break;
2103         case _PC_ACL_EXTENDED:
2104 #ifdef UFS_ACL
2105                 if (ap->a_vp->v_mount->mnt_flag & MNT_ACLS)
2106                         *ap->a_retval = 1;
2107                 else
2108                         *ap->a_retval = 0;
2109 #else
2110                 *ap->a_retval = 0;
2111 #endif
2112                 break;
2113         case _PC_ACL_PATH_MAX:
2114 #ifdef UFS_ACL
2115                 if (ap->a_vp->v_mount->mnt_flag & MNT_ACLS)
2116                         *ap->a_retval = ACL_MAX_ENTRIES;
2117                 else
2118                         *ap->a_retval = 3;
2119 #else
2120                 *ap->a_retval = 3;
2121 #endif
2122                 break;
2123         case _PC_MAC_PRESENT:
2124 #ifdef MAC
2125                 if (ap->a_vp->v_mount->mnt_flag & MNT_MULTILABEL)
2126                         *ap->a_retval = 1;
2127                 else
2128                         *ap->a_retval = 0;
2129 #else
2130                 *ap->a_retval = 0;
2131 #endif
2132                 break;
2133         case _PC_ASYNC_IO:
2134                 /* _PC_ASYNC_IO should have been handled by upper layers. */
2135                 KASSERT(0, ("_PC_ASYNC_IO should not get here"));
2136                 error = EINVAL;
2137                 break;
2138         case _PC_PRIO_IO:
2139                 *ap->a_retval = 0;
2140                 break;
2141         case _PC_SYNC_IO:
2142                 *ap->a_retval = 0;
2143                 break;
2144         case _PC_ALLOC_SIZE_MIN:
2145                 *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_bsize;
2146                 break;
2147         case _PC_FILESIZEBITS:
2148                 *ap->a_retval = 64;
2149                 break;
2150         case _PC_REC_INCR_XFER_SIZE:
2151                 *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize;
2152                 break;
2153         case _PC_REC_MAX_XFER_SIZE:
2154                 *ap->a_retval = -1; /* means ``unlimited'' */
2155                 break;
2156         case _PC_REC_MIN_XFER_SIZE:
2157                 *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize;
2158                 break;
2159         case _PC_REC_XFER_ALIGN:
2160                 *ap->a_retval = PAGE_SIZE;
2161                 break;
2162         case _PC_SYMLINK_MAX:
2163                 *ap->a_retval = MAXPATHLEN;
2164                 break;
2165
2166         default:
2167                 error = EINVAL;
2168                 break;
2169         }
2170         return (error);
2171 }
2172
2173 /*
2174  * Advisory record locking support
2175  */
2176 static int
2177 ufs_advlock(ap)
2178         struct vop_advlock_args /* {
2179                 struct vnode *a_vp;
2180                 caddr_t  a_id;
2181                 int  a_op;
2182                 struct flock *a_fl;
2183                 int  a_flags;
2184         } */ *ap;
2185 {
2186         struct inode *ip = VTOI(ap->a_vp);
2187
2188         return (lf_advlock(ap, &(ip->i_lockf), ip->i_size));
2189 }
2190
2191 /*
2192  * Initialize the vnode associated with a new inode, handle aliased
2193  * vnodes.
2194  */
2195 int
2196 ufs_vinit(mntp, fifoops, vpp)
2197         struct mount *mntp;
2198         struct vop_vector *fifoops;
2199         struct vnode **vpp;
2200 {
2201         struct inode *ip;
2202         struct vnode *vp;
2203
2204         vp = *vpp;
2205         ip = VTOI(vp);
2206         vp->v_type = IFTOVT(ip->i_mode);
2207         if (vp->v_type == VFIFO)
2208                 vp->v_op = fifoops;
2209         ASSERT_VOP_LOCKED(vp, "ufs_vinit");
2210         if (ip->i_number == ROOTINO)
2211                 vp->v_vflag |= VV_ROOT;
2212         ip->i_modrev = init_va_filerev();
2213         *vpp = vp;
2214         return (0);
2215 }
2216
2217 /*
2218  * Allocate a new inode.
2219  * Vnode dvp must be locked.
2220  */
2221 static int
2222 ufs_makeinode(mode, dvp, vpp, cnp)
2223         int mode;
2224         struct vnode *dvp;
2225         struct vnode **vpp;
2226         struct componentname *cnp;
2227 {
2228         struct inode *ip, *pdir;
2229         struct direct newdir;
2230         struct vnode *tvp;
2231 #ifdef UFS_ACL
2232         struct acl *acl;
2233 #endif
2234         int error;
2235
2236         pdir = VTOI(dvp);
2237 #ifdef DIAGNOSTIC
2238         if ((cnp->cn_flags & HASBUF) == 0)
2239                 panic("ufs_makeinode: no name");
2240 #endif
2241         *vpp = NULL;
2242         if ((mode & IFMT) == 0)
2243                 mode |= IFREG;
2244
2245         error = UFS_VALLOC(dvp, mode, cnp->cn_cred, &tvp);
2246         if (error)
2247                 return (error);
2248         ip = VTOI(tvp);
2249         ip->i_gid = pdir->i_gid;
2250         DIP_SET(ip, i_gid, pdir->i_gid);
2251 #ifdef SUIDDIR
2252         {
2253 #ifdef QUOTA
2254                 struct ucred ucred, *ucp;
2255                 ucp = cnp->cn_cred;
2256 #endif
2257                 /*
2258                  * If we are not the owner of the directory,
2259                  * and we are hacking owners here, (only do this where told to)
2260                  * and we are not giving it TO root, (would subvert quotas)
2261                  * then go ahead and give it to the other user.
2262                  * Note that this drops off the execute bits for security.
2263                  */
2264                 if ((dvp->v_mount->mnt_flag & MNT_SUIDDIR) &&
2265                     (pdir->i_mode & ISUID) &&
2266                     (pdir->i_uid != cnp->cn_cred->cr_uid) && pdir->i_uid) {
2267                         ip->i_uid = pdir->i_uid;
2268                         DIP_SET(ip, i_uid, ip->i_uid);
2269                         mode &= ~07111;
2270 #ifdef QUOTA
2271                         /*
2272                          * Make sure the correct user gets charged
2273                          * for the space.
2274                          * Quickly knock up a dummy credential for the victim.
2275                          * XXX This seems to never be accessed out of our
2276                          * context so a stack variable is ok.
2277                          */
2278                         refcount_init(&ucred.cr_ref, 1);
2279                         ucred.cr_uid = ip->i_uid;
2280                         ucred.cr_ngroups = 1;
2281                         ucred.cr_groups[0] = pdir->i_gid;
2282                         ucp = &ucred;
2283 #endif
2284                 } else {
2285                         ip->i_uid = cnp->cn_cred->cr_uid;
2286                         DIP_SET(ip, i_uid, ip->i_uid);
2287                 }
2288
2289 #ifdef QUOTA
2290                 if ((error = getinoquota(ip)) ||
2291                     (error = chkiq(ip, 1, ucp, 0))) {
2292                         UFS_VFREE(tvp, ip->i_number, mode);
2293                         vput(tvp);
2294                         return (error);
2295                 }
2296 #endif
2297         }
2298 #else   /* !SUIDDIR */
2299         ip->i_uid = cnp->cn_cred->cr_uid;
2300         DIP_SET(ip, i_uid, ip->i_uid);
2301 #ifdef QUOTA
2302         if ((error = getinoquota(ip)) ||
2303             (error = chkiq(ip, 1, cnp->cn_cred, 0))) {
2304                 UFS_VFREE(tvp, ip->i_number, mode);
2305                 vput(tvp);
2306                 return (error);
2307         }
2308 #endif
2309 #endif  /* !SUIDDIR */
2310         ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
2311 #ifdef UFS_ACL
2312         acl = NULL;
2313         if ((dvp->v_mount->mnt_flag & MNT_ACLS) != 0) {
2314                 acl = uma_zalloc(acl_zone, M_WAITOK);
2315
2316                 /*
2317                  * Retrieve default ACL for parent, if any.
2318                  */
2319                 error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cnp->cn_cred,
2320                     cnp->cn_thread);
2321                 switch (error) {
2322                 case 0:
2323                         /*
2324                          * Retrieved a default ACL, so merge mode and ACL if
2325                          * necessary.
2326                          */
2327                         if (acl->acl_cnt != 0) {
2328                                 /*
2329                                  * Two possible ways for default ACL to not
2330                                  * be present.  First, the EA can be
2331                                  * undefined, or second, the default ACL can
2332                                  * be blank.  If it's blank, fall through to
2333                                  * the it's not defined case.
2334                                  */
2335                                 mode = acl_posix1e_newfilemode(mode, acl);
2336                                 ip->i_mode = mode;
2337                                 DIP_SET(ip, i_mode, mode);
2338                                 ufs_sync_acl_from_inode(ip, acl);
2339                                 break;
2340                         }
2341                         /* FALLTHROUGH */
2342         
2343                 case EOPNOTSUPP:
2344                         /*
2345                          * Just use the mode as-is.
2346                          */
2347                         ip->i_mode = mode;
2348                         DIP_SET(ip, i_mode, mode);
2349                         uma_zfree(acl_zone, acl);
2350                         acl = NULL;
2351                         break;
2352         
2353                 default:
2354                         UFS_VFREE(tvp, ip->i_number, mode);
2355                         vput(tvp);
2356                         uma_zfree(acl_zone, acl);
2357                         acl = NULL;
2358                         return (error);
2359                 }
2360         } else {
2361 #endif
2362                 ip->i_mode = mode;
2363                 DIP_SET(ip, i_mode, mode);
2364 #ifdef UFS_ACL
2365         }
2366 #endif
2367         tvp->v_type = IFTOVT(mode);     /* Rest init'd in getnewvnode(). */
2368         ip->i_effnlink = 1;
2369         ip->i_nlink = 1;
2370         DIP_SET(ip, i_nlink, 1);
2371         if (DOINGSOFTDEP(tvp))
2372                 softdep_change_linkcnt(ip);
2373         if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) &&
2374             priv_check_cred(cnp->cn_cred, PRIV_VFS_SETGID,
2375             SUSER_ALLOWJAIL)) {
2376                 ip->i_mode &= ~ISGID;
2377                 DIP_SET(ip, i_mode, ip->i_mode);
2378         }
2379
2380         if (cnp->cn_flags & ISWHITEOUT) {
2381                 ip->i_flags |= UF_OPAQUE;
2382                 DIP_SET(ip, i_flags, ip->i_flags);
2383         }
2384
2385         /*
2386          * Make sure inode goes to disk before directory entry.
2387          */
2388         error = UFS_UPDATE(tvp, !(DOINGSOFTDEP(tvp) | DOINGASYNC(tvp)));
2389         if (error)
2390                 goto bad;
2391 #ifdef MAC
2392         if (dvp->v_mount->mnt_flag & MNT_MULTILABEL) {
2393                 error = mac_create_vnode_extattr(cnp->cn_cred, dvp->v_mount,
2394                     dvp, tvp, cnp);
2395                 if (error)
2396                         goto bad;
2397         }
2398 #endif
2399 #ifdef UFS_ACL
2400         if (acl != NULL) {
2401                 /*
2402                  * XXX: If we abort now, will Soft Updates notify the extattr
2403                  * code that the EAs for the file need to be released?
2404                  */
2405                 error = VOP_SETACL(tvp, ACL_TYPE_ACCESS, acl, cnp->cn_cred,
2406                     cnp->cn_thread);
2407                 switch (error) {
2408                 case 0:
2409                         break;
2410
2411                 case EOPNOTSUPP:
2412                         /*
2413                          * XXX: This should not happen, as EOPNOTSUPP above was
2414                          * supposed to free acl.
2415                          */
2416                         printf("ufs_makeinode: VOP_GETACL() but no "
2417                             "VOP_SETACL()\n");
2418                         /* panic("ufs_makeinode: VOP_GETACL() but no "
2419                             "VOP_SETACL()"); */
2420                         break;
2421
2422                 default:
2423                         uma_zfree(acl_zone, acl);
2424                         goto bad;
2425                 }
2426                 uma_zfree(acl_zone, acl);
2427         }
2428 #endif /* !UFS_ACL */
2429         ufs_makedirentry(ip, cnp, &newdir);
2430         error = ufs_direnter(dvp, tvp, &newdir, cnp, NULL);
2431         if (error)
2432                 goto bad;
2433         *vpp = tvp;
2434         return (0);
2435
2436 bad:
2437         /*
2438          * Write error occurred trying to update the inode
2439          * or the directory so must deallocate the inode.
2440          */
2441         ip->i_effnlink = 0;
2442         ip->i_nlink = 0;
2443         DIP_SET(ip, i_nlink, 0);
2444         ip->i_flag |= IN_CHANGE;
2445         if (DOINGSOFTDEP(tvp))
2446                 softdep_change_linkcnt(ip);
2447         vput(tvp);
2448         return (error);
2449 }
2450
2451 /* Global vfs data structures for ufs. */
2452 struct vop_vector ufs_vnodeops = {
2453         .vop_default =          &default_vnodeops,
2454         .vop_fsync =            VOP_PANIC,
2455         .vop_read =             VOP_PANIC,
2456         .vop_reallocblks =      VOP_PANIC,
2457         .vop_write =            VOP_PANIC,
2458         .vop_access =           ufs_access,
2459         .vop_advlock =          ufs_advlock,
2460         .vop_bmap =             ufs_bmap,
2461         .vop_cachedlookup =     ufs_lookup,
2462         .vop_close =            ufs_close,
2463         .vop_create =           ufs_create,
2464         .vop_getattr =          ufs_getattr,
2465         .vop_inactive =         ufs_inactive,
2466         .vop_link =             ufs_link,
2467         .vop_lookup =           vfs_cache_lookup,
2468         .vop_mkdir =            ufs_mkdir,
2469         .vop_mknod =            ufs_mknod,
2470         .vop_open =             ufs_open,
2471         .vop_pathconf =         ufs_pathconf,
2472         .vop_poll =             vop_stdpoll,
2473         .vop_print =            ufs_print,
2474         .vop_readdir =          ufs_readdir,
2475         .vop_readlink =         ufs_readlink,
2476         .vop_reclaim =          ufs_reclaim,
2477         .vop_remove =           ufs_remove,
2478         .vop_rename =           ufs_rename,
2479         .vop_rmdir =            ufs_rmdir,
2480         .vop_setattr =          ufs_setattr,
2481 #ifdef MAC
2482         .vop_setlabel =         vop_stdsetlabel_ea,
2483 #endif
2484         .vop_strategy =         ufs_strategy,
2485         .vop_symlink =          ufs_symlink,
2486         .vop_whiteout =         ufs_whiteout,
2487 #ifdef UFS_EXTATTR
2488         .vop_getextattr =       ufs_getextattr,
2489         .vop_deleteextattr =    ufs_deleteextattr,
2490         .vop_setextattr =       ufs_setextattr,
2491 #endif
2492 #ifdef UFS_ACL
2493         .vop_getacl =           ufs_getacl,
2494         .vop_setacl =           ufs_setacl,
2495         .vop_aclcheck =         ufs_aclcheck,
2496 #endif
2497 };
2498
2499 struct vop_vector ufs_fifoops = {
2500         .vop_default =          &fifo_specops,
2501         .vop_fsync =            VOP_PANIC,
2502         .vop_access =           ufs_access,
2503         .vop_close =            ufsfifo_close,
2504         .vop_getattr =          ufs_getattr,
2505         .vop_inactive =         ufs_inactive,
2506         .vop_kqfilter =         ufsfifo_kqfilter,
2507         .vop_print =            ufs_print,
2508         .vop_read =             VOP_PANIC,
2509         .vop_reclaim =          ufs_reclaim,
2510         .vop_setattr =          ufs_setattr,
2511 #ifdef MAC
2512         .vop_setlabel =         vop_stdsetlabel_ea,
2513 #endif
2514         .vop_write =            VOP_PANIC,
2515 #ifdef UFS_EXTATTR
2516         .vop_getextattr =       ufs_getextattr,
2517         .vop_deleteextattr =    ufs_deleteextattr,
2518         .vop_setextattr =       ufs_setextattr,
2519 #endif
2520 #ifdef UFS_ACL
2521         .vop_getacl =           ufs_getacl,
2522         .vop_setacl =           ufs_setacl,
2523         .vop_aclcheck =         ufs_aclcheck,
2524 #endif
2525 };