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