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