xref: /xnu-12377.61.12/bsd/miscfs/devfs/devfs_vnops.c (revision 4d495c6e23c53686cf65f45067f79024cf5dcee8)
1*4d495c6eSApple OSS Distributions /*
2*4d495c6eSApple OSS Distributions  * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
3*4d495c6eSApple OSS Distributions  *
4*4d495c6eSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*4d495c6eSApple OSS Distributions  *
6*4d495c6eSApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*4d495c6eSApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*4d495c6eSApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*4d495c6eSApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*4d495c6eSApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*4d495c6eSApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*4d495c6eSApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*4d495c6eSApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*4d495c6eSApple OSS Distributions  *
15*4d495c6eSApple OSS Distributions  * Please obtain a copy of the License at
16*4d495c6eSApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*4d495c6eSApple OSS Distributions  *
18*4d495c6eSApple OSS Distributions  * The Original Code and all software distributed under the License are
19*4d495c6eSApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*4d495c6eSApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*4d495c6eSApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*4d495c6eSApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*4d495c6eSApple OSS Distributions  * Please see the License for the specific language governing rights and
24*4d495c6eSApple OSS Distributions  * limitations under the License.
25*4d495c6eSApple OSS Distributions  *
26*4d495c6eSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*4d495c6eSApple OSS Distributions  */
28*4d495c6eSApple OSS Distributions /*
29*4d495c6eSApple OSS Distributions  * Copyright 1997,1998 Julian Elischer.  All rights reserved.
30*4d495c6eSApple OSS Distributions  * [email protected]
31*4d495c6eSApple OSS Distributions  *
32*4d495c6eSApple OSS Distributions  * Redistribution and use in source and binary forms, with or without
33*4d495c6eSApple OSS Distributions  * modification, are permitted provided that the following conditions are
34*4d495c6eSApple OSS Distributions  * met:
35*4d495c6eSApple OSS Distributions  *  1. Redistributions of source code must retain the above copyright
36*4d495c6eSApple OSS Distributions  *     notice, this list of conditions and the following disclaimer.
37*4d495c6eSApple OSS Distributions  *  2. Redistributions in binary form must reproduce the above copyright notice,
38*4d495c6eSApple OSS Distributions  *     this list of conditions and the following disclaimer in the documentation
39*4d495c6eSApple OSS Distributions  *     and/or other materials provided with the distribution.
40*4d495c6eSApple OSS Distributions  *
41*4d495c6eSApple OSS Distributions  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
42*4d495c6eSApple OSS Distributions  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
43*4d495c6eSApple OSS Distributions  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44*4d495c6eSApple OSS Distributions  * DISCLAIMED.  IN NO EVENT SHALL THE HOLDER OR CONTRIBUTORS BE LIABLE FOR
45*4d495c6eSApple OSS Distributions  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46*4d495c6eSApple OSS Distributions  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
47*4d495c6eSApple OSS Distributions  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
48*4d495c6eSApple OSS Distributions  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49*4d495c6eSApple OSS Distributions  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50*4d495c6eSApple OSS Distributions  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51*4d495c6eSApple OSS Distributions  * SUCH DAMAGE.
52*4d495c6eSApple OSS Distributions  *
53*4d495c6eSApple OSS Distributions  * devfs_vnops.c
54*4d495c6eSApple OSS Distributions  */
55*4d495c6eSApple OSS Distributions 
56*4d495c6eSApple OSS Distributions /*
57*4d495c6eSApple OSS Distributions  * HISTORY
58*4d495c6eSApple OSS Distributions  *  Clark Warner ([email protected]) Tue Feb 10 2000
59*4d495c6eSApple OSS Distributions  *  - Added err_copyfile to the vnode operations table
60*4d495c6eSApple OSS Distributions  *  Dieter Siegmund ([email protected]) Thu Apr  8 14:08:19 PDT 1999
61*4d495c6eSApple OSS Distributions  *  - instead of duplicating specfs here, created a vnode-ops table
62*4d495c6eSApple OSS Distributions  *    that redirects most operations to specfs (as is done with ufs);
63*4d495c6eSApple OSS Distributions  *  - removed routines that made no sense
64*4d495c6eSApple OSS Distributions  *  - cleaned up reclaim: replaced devfs_vntodn() with a macro VTODN()
65*4d495c6eSApple OSS Distributions  *  - cleaned up symlink, link locking
66*4d495c6eSApple OSS Distributions  *  - added the devfs_lock to protect devfs data structures against
67*4d495c6eSApple OSS Distributions  *    driver's calling devfs_add_devswf()/etc.
68*4d495c6eSApple OSS Distributions  *  Dieter Siegmund ([email protected]) Wed Jul 14 13:37:59 PDT 1999
69*4d495c6eSApple OSS Distributions  *  - free the devfs devnode in devfs_inactive(), not just in devfs_reclaim()
70*4d495c6eSApple OSS Distributions  *    to free up kernel memory as soon as it's available
71*4d495c6eSApple OSS Distributions  *  - got rid of devfsspec_{read, write}
72*4d495c6eSApple OSS Distributions  *  Dieter Siegmund ([email protected]) Fri Sep 17 09:58:38 PDT 1999
73*4d495c6eSApple OSS Distributions  *  - update the mod/access times
74*4d495c6eSApple OSS Distributions  */
75*4d495c6eSApple OSS Distributions /*
76*4d495c6eSApple OSS Distributions  * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
77*4d495c6eSApple OSS Distributions  * support for mandatory and extensible security protections.  This notice
78*4d495c6eSApple OSS Distributions  * is included in support of clause 2.2 (b) of the Apple Public License,
79*4d495c6eSApple OSS Distributions  * Version 2.0.
80*4d495c6eSApple OSS Distributions  */
81*4d495c6eSApple OSS Distributions 
82*4d495c6eSApple OSS Distributions #include <sys/param.h>
83*4d495c6eSApple OSS Distributions #include <sys/systm.h>
84*4d495c6eSApple OSS Distributions #include <sys/namei.h>
85*4d495c6eSApple OSS Distributions #include <sys/kernel.h>
86*4d495c6eSApple OSS Distributions #include <sys/fcntl.h>
87*4d495c6eSApple OSS Distributions #include <sys/conf.h>
88*4d495c6eSApple OSS Distributions #include <sys/disklabel.h>
89*4d495c6eSApple OSS Distributions #include <sys/lock.h>
90*4d495c6eSApple OSS Distributions #include <sys/stat.h>
91*4d495c6eSApple OSS Distributions #include <sys/mount_internal.h>
92*4d495c6eSApple OSS Distributions #include <sys/proc.h>
93*4d495c6eSApple OSS Distributions #include <sys/kauth.h>
94*4d495c6eSApple OSS Distributions #include <sys/time.h>
95*4d495c6eSApple OSS Distributions #include <sys/vnode_internal.h>
96*4d495c6eSApple OSS Distributions #include <miscfs/specfs/specdev.h>
97*4d495c6eSApple OSS Distributions #include <sys/dirent.h>
98*4d495c6eSApple OSS Distributions #include <sys/vmmeter.h>
99*4d495c6eSApple OSS Distributions #include <sys/vm.h>
100*4d495c6eSApple OSS Distributions #include <sys/uio_internal.h>
101*4d495c6eSApple OSS Distributions 
102*4d495c6eSApple OSS Distributions #if CONFIG_MACF
103*4d495c6eSApple OSS Distributions #include <security/mac_framework.h>
104*4d495c6eSApple OSS Distributions #endif
105*4d495c6eSApple OSS Distributions 
106*4d495c6eSApple OSS Distributions #include "devfsdefs.h"
107*4d495c6eSApple OSS Distributions #include "devfs.h"
108*4d495c6eSApple OSS Distributions 
109*4d495c6eSApple OSS Distributions #if FDESC
110*4d495c6eSApple OSS Distributions #include "fdesc.h"
111*4d495c6eSApple OSS Distributions #endif /* FDESC */
112*4d495c6eSApple OSS Distributions 
113*4d495c6eSApple OSS Distributions static int              devfs_update(struct vnode *vp, struct timeval *access,
114*4d495c6eSApple OSS Distributions     struct timeval *modify);
115*4d495c6eSApple OSS Distributions void                    devfs_rele_node(devnode_t *);
116*4d495c6eSApple OSS Distributions static void             devfs_consider_time_update(devnode_t *dnp, uint32_t just_changed_flags);
117*4d495c6eSApple OSS Distributions static boolean_t        devfs_update_needed(long now_s, long last_s);
118*4d495c6eSApple OSS Distributions static boolean_t        devfs_is_name_protected(struct vnode *dvp, const char *name);
119*4d495c6eSApple OSS Distributions static boolean_t        devfs_is_vnode_protected(struct vnode *vp);
120*4d495c6eSApple OSS Distributions void                    dn_times_locked(devnode_t * dnp, struct timeval *t1, struct timeval *t2, struct timeval *t3, uint32_t just_changed_flags);
121*4d495c6eSApple OSS Distributions void                    dn_times_now(devnode_t *dnp, uint32_t just_changed_flags);
122*4d495c6eSApple OSS Distributions void                    dn_mark_for_delayed_times_update(devnode_t *dnp, uint32_t just_changed_flags);
123*4d495c6eSApple OSS Distributions 
124*4d495c6eSApple OSS Distributions void
dn_times_locked(devnode_t * dnp,struct timeval * t1,struct timeval * t2,struct timeval * t3,uint32_t just_changed_flags)125*4d495c6eSApple OSS Distributions dn_times_locked(devnode_t * dnp, struct timeval *t1, struct timeval *t2, struct timeval *t3, uint32_t just_changed_flags)
126*4d495c6eSApple OSS Distributions {
127*4d495c6eSApple OSS Distributions 	lck_mtx_assert(&devfs_attr_mutex, LCK_MTX_ASSERT_OWNED);
128*4d495c6eSApple OSS Distributions 
129*4d495c6eSApple OSS Distributions 	if (just_changed_flags & DEVFS_UPDATE_ACCESS) {
130*4d495c6eSApple OSS Distributions 		dnp->dn_atime.tv_sec = t1->tv_sec;
131*4d495c6eSApple OSS Distributions 		dnp->dn_atime.tv_nsec = t1->tv_usec * 1000;
132*4d495c6eSApple OSS Distributions 		dnp->dn_access = 0;
133*4d495c6eSApple OSS Distributions 	} else if (dnp->dn_access) {
134*4d495c6eSApple OSS Distributions 		dnp->dn_atime.tv_sec = MIN(t1->tv_sec, dnp->dn_atime.tv_sec + DEVFS_LAZY_UPDATE_SECONDS);
135*4d495c6eSApple OSS Distributions 		dnp->dn_atime.tv_nsec = t1->tv_usec * 1000;
136*4d495c6eSApple OSS Distributions 		dnp->dn_access = 0;
137*4d495c6eSApple OSS Distributions 	}
138*4d495c6eSApple OSS Distributions 
139*4d495c6eSApple OSS Distributions 	if (just_changed_flags & DEVFS_UPDATE_MOD) {
140*4d495c6eSApple OSS Distributions 		dnp->dn_mtime.tv_sec = t2->tv_sec;
141*4d495c6eSApple OSS Distributions 		dnp->dn_mtime.tv_nsec = t2->tv_usec * 1000;
142*4d495c6eSApple OSS Distributions 		dnp->dn_update = 0;
143*4d495c6eSApple OSS Distributions 	} else if (dnp->dn_update) {
144*4d495c6eSApple OSS Distributions 		dnp->dn_mtime.tv_sec = MIN(t2->tv_sec, dnp->dn_mtime.tv_sec + DEVFS_LAZY_UPDATE_SECONDS);
145*4d495c6eSApple OSS Distributions 		dnp->dn_mtime.tv_nsec = t2->tv_usec * 1000;
146*4d495c6eSApple OSS Distributions 		dnp->dn_update = 0;
147*4d495c6eSApple OSS Distributions 	}
148*4d495c6eSApple OSS Distributions 
149*4d495c6eSApple OSS Distributions 	if (just_changed_flags & DEVFS_UPDATE_CHANGE) {
150*4d495c6eSApple OSS Distributions 		dnp->dn_ctime.tv_sec = t3->tv_sec;
151*4d495c6eSApple OSS Distributions 		dnp->dn_ctime.tv_nsec = t3->tv_usec * 1000;
152*4d495c6eSApple OSS Distributions 		dnp->dn_change = 0;
153*4d495c6eSApple OSS Distributions 	} else if (dnp->dn_change) {
154*4d495c6eSApple OSS Distributions 		dnp->dn_ctime.tv_sec = MIN(t3->tv_sec, dnp->dn_ctime.tv_sec + DEVFS_LAZY_UPDATE_SECONDS);
155*4d495c6eSApple OSS Distributions 		dnp->dn_ctime.tv_nsec = t3->tv_usec * 1000;
156*4d495c6eSApple OSS Distributions 		dnp->dn_change = 0;
157*4d495c6eSApple OSS Distributions 	}
158*4d495c6eSApple OSS Distributions }
159*4d495c6eSApple OSS Distributions 
160*4d495c6eSApple OSS Distributions void
dn_mark_for_delayed_times_update(devnode_t * dnp,uint32_t just_changed_flags)161*4d495c6eSApple OSS Distributions dn_mark_for_delayed_times_update(devnode_t *dnp, uint32_t just_changed_flags)
162*4d495c6eSApple OSS Distributions {
163*4d495c6eSApple OSS Distributions 	if (just_changed_flags & DEVFS_UPDATE_CHANGE) {
164*4d495c6eSApple OSS Distributions 		dnp->dn_change = 1;
165*4d495c6eSApple OSS Distributions 	}
166*4d495c6eSApple OSS Distributions 	if (just_changed_flags & DEVFS_UPDATE_ACCESS) {
167*4d495c6eSApple OSS Distributions 		dnp->dn_access = 1;
168*4d495c6eSApple OSS Distributions 	}
169*4d495c6eSApple OSS Distributions 	if (just_changed_flags & DEVFS_UPDATE_MOD) {
170*4d495c6eSApple OSS Distributions 		dnp->dn_update = 1;
171*4d495c6eSApple OSS Distributions 	}
172*4d495c6eSApple OSS Distributions }
173*4d495c6eSApple OSS Distributions 
174*4d495c6eSApple OSS Distributions /*
175*4d495c6eSApple OSS Distributions  * Update times based on pending updates and optionally a set of new changes.
176*4d495c6eSApple OSS Distributions  */
177*4d495c6eSApple OSS Distributions void
dn_times_now(devnode_t * dnp,uint32_t just_changed_flags)178*4d495c6eSApple OSS Distributions dn_times_now(devnode_t * dnp, uint32_t just_changed_flags)
179*4d495c6eSApple OSS Distributions {
180*4d495c6eSApple OSS Distributions 	struct timeval now;
181*4d495c6eSApple OSS Distributions 
182*4d495c6eSApple OSS Distributions 	DEVFS_ATTR_LOCK_SPIN();
183*4d495c6eSApple OSS Distributions 	microtime(&now);
184*4d495c6eSApple OSS Distributions 	dn_times_locked(dnp, &now, &now, &now, just_changed_flags);
185*4d495c6eSApple OSS Distributions 	DEVFS_ATTR_UNLOCK();
186*4d495c6eSApple OSS Distributions }
187*4d495c6eSApple OSS Distributions 
188*4d495c6eSApple OSS Distributions /*
189*4d495c6eSApple OSS Distributions  * Critical devfs devices cannot be renamed or removed.
190*4d495c6eSApple OSS Distributions  * However, links to them may be moved/unlinked. So we block
191*4d495c6eSApple OSS Distributions  * remove/rename on a per-name basis, rather than per-node.
192*4d495c6eSApple OSS Distributions  */
193*4d495c6eSApple OSS Distributions static boolean_t
devfs_is_name_protected(struct vnode * dvp,const char * name)194*4d495c6eSApple OSS Distributions devfs_is_name_protected(struct vnode *dvp, const char *name)
195*4d495c6eSApple OSS Distributions {
196*4d495c6eSApple OSS Distributions 	/*
197*4d495c6eSApple OSS Distributions 	 * Only names in root are protected. E.g. /dev/null is protected,
198*4d495c6eSApple OSS Distributions 	 * but /dev/foo/null isn't.
199*4d495c6eSApple OSS Distributions 	 */
200*4d495c6eSApple OSS Distributions 	if (!vnode_isvroot(dvp)) {
201*4d495c6eSApple OSS Distributions 		return FALSE;
202*4d495c6eSApple OSS Distributions 	}
203*4d495c6eSApple OSS Distributions 
204*4d495c6eSApple OSS Distributions 	if ((strcmp("console", name) == 0) ||
205*4d495c6eSApple OSS Distributions 	    (strcmp("tty", name) == 0) ||
206*4d495c6eSApple OSS Distributions 	    (strcmp("null", name) == 0) ||
207*4d495c6eSApple OSS Distributions 	    (strcmp("zero", name) == 0) ||
208*4d495c6eSApple OSS Distributions 	    (strcmp("fd", name) == 0) ||
209*4d495c6eSApple OSS Distributions 	    (strcmp("klog", name) == 0)) {
210*4d495c6eSApple OSS Distributions 		return TRUE;
211*4d495c6eSApple OSS Distributions 	}
212*4d495c6eSApple OSS Distributions 
213*4d495c6eSApple OSS Distributions 	return FALSE;
214*4d495c6eSApple OSS Distributions }
215*4d495c6eSApple OSS Distributions 
216*4d495c6eSApple OSS Distributions /*
217*4d495c6eSApple OSS Distributions  * These devfs devices cannot have their permissions updated.
218*4d495c6eSApple OSS Distributions  */
219*4d495c6eSApple OSS Distributions static boolean_t
devfs_is_vnode_protected(struct vnode * vp)220*4d495c6eSApple OSS Distributions devfs_is_vnode_protected(struct vnode *vp)
221*4d495c6eSApple OSS Distributions {
222*4d495c6eSApple OSS Distributions 	struct vnode *dvp = NULLVP;
223*4d495c6eSApple OSS Distributions 	const char *vname = NULL;
224*4d495c6eSApple OSS Distributions 	boolean_t ret = FALSE;
225*4d495c6eSApple OSS Distributions 	vnode_getparent_and_name(vp, &dvp, &vname);
226*4d495c6eSApple OSS Distributions 	if (!dvp || !vname) {
227*4d495c6eSApple OSS Distributions 		ret = FALSE;
228*4d495c6eSApple OSS Distributions 		goto out;
229*4d495c6eSApple OSS Distributions 	}
230*4d495c6eSApple OSS Distributions 
231*4d495c6eSApple OSS Distributions 	ret = devfs_is_name_protected(dvp, vname);
232*4d495c6eSApple OSS Distributions 
233*4d495c6eSApple OSS Distributions out:
234*4d495c6eSApple OSS Distributions 	if (vname) {
235*4d495c6eSApple OSS Distributions 		vnode_putname(vname);
236*4d495c6eSApple OSS Distributions 	}
237*4d495c6eSApple OSS Distributions 	if (dvp != NULLVP) {
238*4d495c6eSApple OSS Distributions 		vnode_put(dvp);
239*4d495c6eSApple OSS Distributions 	}
240*4d495c6eSApple OSS Distributions 
241*4d495c6eSApple OSS Distributions 	return ret;
242*4d495c6eSApple OSS Distributions }
243*4d495c6eSApple OSS Distributions 
244*4d495c6eSApple OSS Distributions /* Walk up to the root to find out the depth of this nested directory. */
245*4d495c6eSApple OSS Distributions static int
devfs_nested_dirs_depth(devnode_t * dir_p)246*4d495c6eSApple OSS Distributions devfs_nested_dirs_depth(devnode_t *dir_p)
247*4d495c6eSApple OSS Distributions {
248*4d495c6eSApple OSS Distributions 	devdirent_t *dirent_p;
249*4d495c6eSApple OSS Distributions 	int depth = 0;
250*4d495c6eSApple OSS Distributions 
251*4d495c6eSApple OSS Distributions 	while ((dir_p = dir_p->dn_typeinfo.Dir.parent) != NULL) {
252*4d495c6eSApple OSS Distributions 		dirent_p = dir_p->dn_typeinfo.Dir.myname;
253*4d495c6eSApple OSS Distributions 		/* If 'de_parent' is NULL, then we are at root. */
254*4d495c6eSApple OSS Distributions 		if (dirent_p->de_parent == NULL) {
255*4d495c6eSApple OSS Distributions 			break;
256*4d495c6eSApple OSS Distributions 		}
257*4d495c6eSApple OSS Distributions 		depth++;
258*4d495c6eSApple OSS Distributions 	}
259*4d495c6eSApple OSS Distributions 
260*4d495c6eSApple OSS Distributions 	return depth;
261*4d495c6eSApple OSS Distributions }
262*4d495c6eSApple OSS Distributions 
263*4d495c6eSApple OSS Distributions /*
264*4d495c6eSApple OSS Distributions  * Recurse down to all subdirs to figure out the max depths of the deepest
265*4d495c6eSApple OSS Distributions  * subdir.
266*4d495c6eSApple OSS Distributions  */
267*4d495c6eSApple OSS Distributions static int
devfs_subdirs_depth(devdirent_t * parent_dirent_p)268*4d495c6eSApple OSS Distributions devfs_subdirs_depth(devdirent_t *parent_dirent_p)
269*4d495c6eSApple OSS Distributions {
270*4d495c6eSApple OSS Distributions 	devnode_t *parent_dnp = parent_dirent_p->de_dnp;
271*4d495c6eSApple OSS Distributions 	devdirent_t *dirent_p;
272*4d495c6eSApple OSS Distributions 	int max_depths = 0;
273*4d495c6eSApple OSS Distributions 
274*4d495c6eSApple OSS Distributions 	/* Return depth of 0 when there is no more subdir(s). */
275*4d495c6eSApple OSS Distributions 	if (parent_dnp->dn_typeinfo.Dir.entrycount == 0) {
276*4d495c6eSApple OSS Distributions 		return 0;
277*4d495c6eSApple OSS Distributions 	}
278*4d495c6eSApple OSS Distributions 
279*4d495c6eSApple OSS Distributions 	/*
280*4d495c6eSApple OSS Distributions 	 * Traverse each subdir at this level to find out the max depth of its
281*4d495c6eSApple OSS Distributions 	 * subdirs.
282*4d495c6eSApple OSS Distributions 	 */
283*4d495c6eSApple OSS Distributions 	for (dirent_p = parent_dnp->dn_typeinfo.Dir.dirlist; dirent_p;
284*4d495c6eSApple OSS Distributions 	    dirent_p = dirent_p->de_next) {
285*4d495c6eSApple OSS Distributions 		if (dirent_p->de_dnp->dn_type == DEV_DIR) {
286*4d495c6eSApple OSS Distributions 			int depths;
287*4d495c6eSApple OSS Distributions 
288*4d495c6eSApple OSS Distributions 			depths = devfs_subdirs_depth(dirent_p);
289*4d495c6eSApple OSS Distributions 			max_depths = MAX(depths, max_depths);
290*4d495c6eSApple OSS Distributions 		}
291*4d495c6eSApple OSS Distributions 	}
292*4d495c6eSApple OSS Distributions 
293*4d495c6eSApple OSS Distributions 	return max_depths + 1;
294*4d495c6eSApple OSS Distributions }
295*4d495c6eSApple OSS Distributions 
296*4d495c6eSApple OSS Distributions /*
297*4d495c6eSApple OSS Distributions  * Convert a component of a pathname into a pointer to a locked node.
298*4d495c6eSApple OSS Distributions  * This is a very central and rather complicated routine.
299*4d495c6eSApple OSS Distributions  * If the file system is not maintained in a strict tree hierarchy,
300*4d495c6eSApple OSS Distributions  * this can result in a deadlock situation (see comments in code below).
301*4d495c6eSApple OSS Distributions  *
302*4d495c6eSApple OSS Distributions  * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on
303*4d495c6eSApple OSS Distributions  * whether the name is to be looked up, created, renamed, or deleted.
304*4d495c6eSApple OSS Distributions  * When CREATE, RENAME, or DELETE is specified, information usable in
305*4d495c6eSApple OSS Distributions  * creating, renaming, or deleting a directory entry may be calculated.
306*4d495c6eSApple OSS Distributions  * If flag has LOCKPARENT or'ed into it and the target of the pathname
307*4d495c6eSApple OSS Distributions  * exists, lookup returns both the target and its parent directory locked.
308*4d495c6eSApple OSS Distributions  * When creating or renaming and LOCKPARENT is specified, the target may
309*4d495c6eSApple OSS Distributions  * not be ".".  When deleting and LOCKPARENT is specified, the target may
310*4d495c6eSApple OSS Distributions  * be "."., but the caller must check to ensure it does an vrele and DNUNLOCK
311*4d495c6eSApple OSS Distributions  * instead of two DNUNLOCKs.
312*4d495c6eSApple OSS Distributions  *
313*4d495c6eSApple OSS Distributions  * Overall outline of devfs_lookup:
314*4d495c6eSApple OSS Distributions  *
315*4d495c6eSApple OSS Distributions  *	check accessibility of directory
316*4d495c6eSApple OSS Distributions  *	null terminate the component (lookup leaves the whole string alone)
317*4d495c6eSApple OSS Distributions  *	look for name in cache, if found, then if at end of path
318*4d495c6eSApple OSS Distributions  *	  and deleting or creating, drop it, else return name
319*4d495c6eSApple OSS Distributions  *	search for name in directory, to found or notfound
320*4d495c6eSApple OSS Distributions  * notfound:
321*4d495c6eSApple OSS Distributions  *	if creating, return locked directory,
322*4d495c6eSApple OSS Distributions  *	else return error
323*4d495c6eSApple OSS Distributions  * found:
324*4d495c6eSApple OSS Distributions  *	if at end of path and deleting, return information to allow delete
325*4d495c6eSApple OSS Distributions  *	if at end of path and rewriting (RENAME and LOCKPARENT), lock target
326*4d495c6eSApple OSS Distributions  *	  node and return info to allow rewrite
327*4d495c6eSApple OSS Distributions  *	if not at end, add name to cache; if at end and neither creating
328*4d495c6eSApple OSS Distributions  *	  nor deleting, add name to cache
329*4d495c6eSApple OSS Distributions  * On return to lookup, remove the null termination we put in at the start.
330*4d495c6eSApple OSS Distributions  *
331*4d495c6eSApple OSS Distributions  * NOTE: (LOOKUP | LOCKPARENT) currently returns the parent node unlocked.
332*4d495c6eSApple OSS Distributions  */
333*4d495c6eSApple OSS Distributions static int
devfs_lookup(struct vnop_lookup_args * ap)334*4d495c6eSApple OSS Distributions devfs_lookup(struct vnop_lookup_args *ap)
335*4d495c6eSApple OSS Distributions /*struct vnop_lookup_args {
336*4d495c6eSApple OSS Distributions  *       struct vnode * a_dvp; directory vnode ptr
337*4d495c6eSApple OSS Distributions  *       struct vnode ** a_vpp; where to put the result
338*4d495c6eSApple OSS Distributions  *       struct componentname * a_cnp; the name we want
339*4d495c6eSApple OSS Distributions  *       vfs_context_t a_context;
340*4d495c6eSApple OSS Distributions  *  };*/
341*4d495c6eSApple OSS Distributions {
342*4d495c6eSApple OSS Distributions 	struct componentname *cnp = ap->a_cnp;
343*4d495c6eSApple OSS Distributions 	vfs_context_t ctx = cnp->cn_context;
344*4d495c6eSApple OSS Distributions 	struct proc *p = vfs_context_proc(ctx);
345*4d495c6eSApple OSS Distributions 	struct vnode *dir_vnode = ap->a_dvp;
346*4d495c6eSApple OSS Distributions 	struct vnode **result_vnode = ap->a_vpp;
347*4d495c6eSApple OSS Distributions 	devnode_t *   dir_node;       /* the directory we are searching */
348*4d495c6eSApple OSS Distributions 	devnode_t *   node = NULL;       /* the node we are searching for */
349*4d495c6eSApple OSS Distributions 	devdirent_t * nodename;
350*4d495c6eSApple OSS Distributions 	int flags = cnp->cn_flags;
351*4d495c6eSApple OSS Distributions 	int op = cnp->cn_nameiop;       /* LOOKUP, CREATE, RENAME, or DELETE */
352*4d495c6eSApple OSS Distributions 	int wantparent = flags & (LOCKPARENT | WANTPARENT);
353*4d495c6eSApple OSS Distributions 	int error = 0;
354*4d495c6eSApple OSS Distributions 	char    heldchar;       /* the char at the end of the name componet */
355*4d495c6eSApple OSS Distributions 
356*4d495c6eSApple OSS Distributions retry:
357*4d495c6eSApple OSS Distributions 
358*4d495c6eSApple OSS Distributions 	*result_vnode = NULL; /* safe not sorry */ /*XXX*/
359*4d495c6eSApple OSS Distributions 
360*4d495c6eSApple OSS Distributions 	/*  okay to look at directory vnodes ourside devfs lock as they are not aliased */
361*4d495c6eSApple OSS Distributions 	dir_node = VTODN(dir_vnode);
362*4d495c6eSApple OSS Distributions 
363*4d495c6eSApple OSS Distributions 	/*
364*4d495c6eSApple OSS Distributions 	 * Make sure that our node is a directory as well.
365*4d495c6eSApple OSS Distributions 	 */
366*4d495c6eSApple OSS Distributions 	if (dir_node->dn_type != DEV_DIR) {
367*4d495c6eSApple OSS Distributions 		return ENOTDIR;
368*4d495c6eSApple OSS Distributions 	}
369*4d495c6eSApple OSS Distributions 
370*4d495c6eSApple OSS Distributions 	DEVFS_LOCK();
371*4d495c6eSApple OSS Distributions 	/*
372*4d495c6eSApple OSS Distributions 	 * temporarily terminate string component
373*4d495c6eSApple OSS Distributions 	 */
374*4d495c6eSApple OSS Distributions 	heldchar = cnp->cn_nameptr[cnp->cn_namelen];
375*4d495c6eSApple OSS Distributions 	cnp->cn_nameptr[cnp->cn_namelen] = '\0';
376*4d495c6eSApple OSS Distributions 
377*4d495c6eSApple OSS Distributions 	nodename = dev_findname(dir_node, cnp->cn_nameptr);
378*4d495c6eSApple OSS Distributions 	/*
379*4d495c6eSApple OSS Distributions 	 * restore saved character
380*4d495c6eSApple OSS Distributions 	 */
381*4d495c6eSApple OSS Distributions 	cnp->cn_nameptr[cnp->cn_namelen] = heldchar;
382*4d495c6eSApple OSS Distributions 
383*4d495c6eSApple OSS Distributions 	if (nodename) {
384*4d495c6eSApple OSS Distributions 		/* entry exists */
385*4d495c6eSApple OSS Distributions 		node = nodename->de_dnp;
386*4d495c6eSApple OSS Distributions 
387*4d495c6eSApple OSS Distributions 		/* Do potential vnode allocation here inside the lock
388*4d495c6eSApple OSS Distributions 		 * to make sure that our device node has a non-NULL dn_vn
389*4d495c6eSApple OSS Distributions 		 * associated with it.  The device node might otherwise
390*4d495c6eSApple OSS Distributions 		 * get deleted out from under us (see devfs_dn_free()).
391*4d495c6eSApple OSS Distributions 		 */
392*4d495c6eSApple OSS Distributions 		error = devfs_dntovn(node, result_vnode, p);
393*4d495c6eSApple OSS Distributions 	}
394*4d495c6eSApple OSS Distributions 	DEVFS_UNLOCK();
395*4d495c6eSApple OSS Distributions 
396*4d495c6eSApple OSS Distributions 	if (error) {
397*4d495c6eSApple OSS Distributions 		if (error == EAGAIN) {
398*4d495c6eSApple OSS Distributions 			goto retry;
399*4d495c6eSApple OSS Distributions 		}
400*4d495c6eSApple OSS Distributions 		return error;
401*4d495c6eSApple OSS Distributions 	}
402*4d495c6eSApple OSS Distributions 	if (!nodename) {
403*4d495c6eSApple OSS Distributions 		/*
404*4d495c6eSApple OSS Distributions 		 * we haven't called devfs_dntovn if we get here
405*4d495c6eSApple OSS Distributions 		 * we have not taken a reference on the node.. no
406*4d495c6eSApple OSS Distributions 		 * vnode_put is necessary on these error returns
407*4d495c6eSApple OSS Distributions 		 *
408*4d495c6eSApple OSS Distributions 		 * If it doesn't exist and we're not the last component,
409*4d495c6eSApple OSS Distributions 		 * or we're at the last component, but we're not creating
410*4d495c6eSApple OSS Distributions 		 * or renaming, return ENOENT.
411*4d495c6eSApple OSS Distributions 		 */
412*4d495c6eSApple OSS Distributions 		if (!(flags & ISLASTCN) || !(op == CREATE || op == RENAME)) {
413*4d495c6eSApple OSS Distributions 			return ENOENT;
414*4d495c6eSApple OSS Distributions 		}
415*4d495c6eSApple OSS Distributions 		/*
416*4d495c6eSApple OSS Distributions 		 * We return with the directory locked, so that
417*4d495c6eSApple OSS Distributions 		 * the parameters we set up above will still be
418*4d495c6eSApple OSS Distributions 		 * valid if we actually decide to add a new entry.
419*4d495c6eSApple OSS Distributions 		 * We return ni_vp == NULL to indicate that the entry
420*4d495c6eSApple OSS Distributions 		 * does not currently exist; we leave a pointer to
421*4d495c6eSApple OSS Distributions 		 * the (locked) directory vnode in namei_data->ni_dvp.
422*4d495c6eSApple OSS Distributions 		 *
423*4d495c6eSApple OSS Distributions 		 * NB - if the directory is unlocked, then this
424*4d495c6eSApple OSS Distributions 		 * information cannot be used.
425*4d495c6eSApple OSS Distributions 		 */
426*4d495c6eSApple OSS Distributions 		return EJUSTRETURN;
427*4d495c6eSApple OSS Distributions 	}
428*4d495c6eSApple OSS Distributions 	/*
429*4d495c6eSApple OSS Distributions 	 * from this point forward, we need to vnode_put the reference
430*4d495c6eSApple OSS Distributions 	 * picked up in devfs_dntovn if we decide to return an error
431*4d495c6eSApple OSS Distributions 	 */
432*4d495c6eSApple OSS Distributions 
433*4d495c6eSApple OSS Distributions 	/*
434*4d495c6eSApple OSS Distributions 	 * If deleting, and at end of pathname, return
435*4d495c6eSApple OSS Distributions 	 * parameters which can be used to remove file.
436*4d495c6eSApple OSS Distributions 	 * If the wantparent flag isn't set, we return only
437*4d495c6eSApple OSS Distributions 	 * the directory (in namei_data->ni_dvp), otherwise we go
438*4d495c6eSApple OSS Distributions 	 * on and lock the node, being careful with ".".
439*4d495c6eSApple OSS Distributions 	 */
440*4d495c6eSApple OSS Distributions 	if (op == DELETE && (flags & ISLASTCN)) {
441*4d495c6eSApple OSS Distributions 		/*
442*4d495c6eSApple OSS Distributions 		 * we are trying to delete '.'.  What does this mean? XXX
443*4d495c6eSApple OSS Distributions 		 */
444*4d495c6eSApple OSS Distributions 		if (dir_node == node) {
445*4d495c6eSApple OSS Distributions 			if (*result_vnode) {
446*4d495c6eSApple OSS Distributions 				vnode_put(*result_vnode);
447*4d495c6eSApple OSS Distributions 				*result_vnode = NULL;
448*4d495c6eSApple OSS Distributions 			}
449*4d495c6eSApple OSS Distributions 			if (((error = vnode_get(dir_vnode)) == 0)) {
450*4d495c6eSApple OSS Distributions 				*result_vnode = dir_vnode;
451*4d495c6eSApple OSS Distributions 			}
452*4d495c6eSApple OSS Distributions 			return error;
453*4d495c6eSApple OSS Distributions 		}
454*4d495c6eSApple OSS Distributions 		return 0;
455*4d495c6eSApple OSS Distributions 	}
456*4d495c6eSApple OSS Distributions 
457*4d495c6eSApple OSS Distributions 	/*
458*4d495c6eSApple OSS Distributions 	 * If rewriting (RENAME), return the vnode and the
459*4d495c6eSApple OSS Distributions 	 * information required to rewrite the present directory
460*4d495c6eSApple OSS Distributions 	 * Must get node of directory entry to verify it's a
461*4d495c6eSApple OSS Distributions 	 * regular file, or empty directory.
462*4d495c6eSApple OSS Distributions 	 */
463*4d495c6eSApple OSS Distributions 	if (op == RENAME && wantparent && (flags & ISLASTCN)) {
464*4d495c6eSApple OSS Distributions 		/*
465*4d495c6eSApple OSS Distributions 		 * Careful about locking second node.
466*4d495c6eSApple OSS Distributions 		 * This can only occur if the target is ".".
467*4d495c6eSApple OSS Distributions 		 */
468*4d495c6eSApple OSS Distributions 		if (dir_node == node) {
469*4d495c6eSApple OSS Distributions 			error = EISDIR;
470*4d495c6eSApple OSS Distributions 			goto drop_ref;
471*4d495c6eSApple OSS Distributions 		}
472*4d495c6eSApple OSS Distributions 		return 0;
473*4d495c6eSApple OSS Distributions 	}
474*4d495c6eSApple OSS Distributions 
475*4d495c6eSApple OSS Distributions 	/*
476*4d495c6eSApple OSS Distributions 	 * Step through the translation in the name.  We do not unlock the
477*4d495c6eSApple OSS Distributions 	 * directory because we may need it again if a symbolic link
478*4d495c6eSApple OSS Distributions 	 * is relative to the current directory.  Instead we save it
479*4d495c6eSApple OSS Distributions 	 * unlocked as "saved_dir_node" XXX.  We must get the target
480*4d495c6eSApple OSS Distributions 	 * node before unlocking
481*4d495c6eSApple OSS Distributions 	 * the directory to insure that the node will not be removed
482*4d495c6eSApple OSS Distributions 	 * before we get it.  We prevent deadlock by always fetching
483*4d495c6eSApple OSS Distributions 	 * nodes from the root, moving down the directory tree. Thus
484*4d495c6eSApple OSS Distributions 	 * when following backward pointers ".." we must unlock the
485*4d495c6eSApple OSS Distributions 	 * parent directory before getting the requested directory.
486*4d495c6eSApple OSS Distributions 	 * There is a potential race condition here if both the current
487*4d495c6eSApple OSS Distributions 	 * and parent directories are removed before the lock for the
488*4d495c6eSApple OSS Distributions 	 * node associated with ".." returns.  We hope that this occurs
489*4d495c6eSApple OSS Distributions 	 * infrequently since we cannot avoid this race condition without
490*4d495c6eSApple OSS Distributions 	 * implementing a sophisticated deadlock detection algorithm.
491*4d495c6eSApple OSS Distributions 	 * Note also that this simple deadlock detection scheme will not
492*4d495c6eSApple OSS Distributions 	 * work if the file system has any hard links other than ".."
493*4d495c6eSApple OSS Distributions 	 * that point backwards in the directory structure.
494*4d495c6eSApple OSS Distributions 	 */
495*4d495c6eSApple OSS Distributions 	if ((flags & ISDOTDOT) == 0 && dir_node == node) {
496*4d495c6eSApple OSS Distributions 		if (*result_vnode) {
497*4d495c6eSApple OSS Distributions 			vnode_put(*result_vnode);
498*4d495c6eSApple OSS Distributions 			*result_vnode = NULL;
499*4d495c6eSApple OSS Distributions 		}
500*4d495c6eSApple OSS Distributions 		if ((error = vnode_get(dir_vnode))) {
501*4d495c6eSApple OSS Distributions 			return error;
502*4d495c6eSApple OSS Distributions 		}
503*4d495c6eSApple OSS Distributions 		*result_vnode = dir_vnode;
504*4d495c6eSApple OSS Distributions 	}
505*4d495c6eSApple OSS Distributions 	return 0;
506*4d495c6eSApple OSS Distributions 
507*4d495c6eSApple OSS Distributions drop_ref:
508*4d495c6eSApple OSS Distributions 	if (*result_vnode) {
509*4d495c6eSApple OSS Distributions 		vnode_put(*result_vnode);
510*4d495c6eSApple OSS Distributions 		*result_vnode = NULL;
511*4d495c6eSApple OSS Distributions 	}
512*4d495c6eSApple OSS Distributions 	return error;
513*4d495c6eSApple OSS Distributions }
514*4d495c6eSApple OSS Distributions 
515*4d495c6eSApple OSS Distributions static int
devfs_getattr(struct vnop_getattr_args * ap)516*4d495c6eSApple OSS Distributions devfs_getattr(struct vnop_getattr_args *ap)
517*4d495c6eSApple OSS Distributions /*struct vnop_getattr_args {
518*4d495c6eSApple OSS Distributions  *       struct vnode *a_vp;
519*4d495c6eSApple OSS Distributions  *       struct vnode_attr *a_vap;
520*4d495c6eSApple OSS Distributions  *       kauth_cred_t a_cred;
521*4d495c6eSApple OSS Distributions  *       struct proc *a_p;
522*4d495c6eSApple OSS Distributions  *  } */
523*4d495c6eSApple OSS Distributions {
524*4d495c6eSApple OSS Distributions 	struct vnode *vp = ap->a_vp;
525*4d495c6eSApple OSS Distributions 	struct vnode_attr *vap = ap->a_vap;
526*4d495c6eSApple OSS Distributions 	devnode_t *     file_node;
527*4d495c6eSApple OSS Distributions 	struct timeval now;
528*4d495c6eSApple OSS Distributions 
529*4d495c6eSApple OSS Distributions 
530*4d495c6eSApple OSS Distributions 	DEVFS_LOCK();
531*4d495c6eSApple OSS Distributions 	file_node = VTODN(vp);
532*4d495c6eSApple OSS Distributions 
533*4d495c6eSApple OSS Distributions 	VATTR_RETURN(vap, va_mode, file_node->dn_mode);
534*4d495c6eSApple OSS Distributions 
535*4d495c6eSApple OSS Distributions 	/*
536*4d495c6eSApple OSS Distributions 	 * Note: for DEV_CDEV and DEV_BDEV, we return the device from
537*4d495c6eSApple OSS Distributions 	 * the vp, not the file_node; if we getting information on a
538*4d495c6eSApple OSS Distributions 	 * cloning device, we want the cloned information, not the template.
539*4d495c6eSApple OSS Distributions 	 */
540*4d495c6eSApple OSS Distributions 	switch (file_node->dn_type) {
541*4d495c6eSApple OSS Distributions 	case    DEV_DIR:
542*4d495c6eSApple OSS Distributions #if FDESC
543*4d495c6eSApple OSS Distributions 	case    DEV_DEVFD:      /* Like a directory */
544*4d495c6eSApple OSS Distributions #endif /* FDESC */
545*4d495c6eSApple OSS Distributions 		VATTR_RETURN(vap, va_rdev, 0);
546*4d495c6eSApple OSS Distributions 		vap->va_mode |= (S_IFDIR);
547*4d495c6eSApple OSS Distributions 		break;
548*4d495c6eSApple OSS Distributions 	case    DEV_CDEV:
549*4d495c6eSApple OSS Distributions 		VATTR_RETURN(vap, va_rdev, vp->v_rdev);
550*4d495c6eSApple OSS Distributions 		vap->va_mode |= (S_IFCHR);
551*4d495c6eSApple OSS Distributions 		break;
552*4d495c6eSApple OSS Distributions 	case    DEV_BDEV:
553*4d495c6eSApple OSS Distributions 		VATTR_RETURN(vap, va_rdev, vp->v_rdev);
554*4d495c6eSApple OSS Distributions 		vap->va_mode |= (S_IFBLK);
555*4d495c6eSApple OSS Distributions 		break;
556*4d495c6eSApple OSS Distributions 	case    DEV_SLNK:
557*4d495c6eSApple OSS Distributions 		VATTR_RETURN(vap, va_rdev, 0);
558*4d495c6eSApple OSS Distributions 		vap->va_mode |= (S_IFLNK);
559*4d495c6eSApple OSS Distributions 		break;
560*4d495c6eSApple OSS Distributions 	default:
561*4d495c6eSApple OSS Distributions 		VATTR_RETURN(vap, va_rdev, 0);  /* default value only */
562*4d495c6eSApple OSS Distributions 	}
563*4d495c6eSApple OSS Distributions 	VATTR_RETURN(vap, va_type, vp->v_type);
564*4d495c6eSApple OSS Distributions 	VATTR_RETURN(vap, va_nlink, file_node->dn_links);
565*4d495c6eSApple OSS Distributions 	VATTR_RETURN(vap, va_uid, file_node->dn_uid);
566*4d495c6eSApple OSS Distributions 	VATTR_RETURN(vap, va_gid, file_node->dn_gid);
567*4d495c6eSApple OSS Distributions 	VATTR_RETURN(vap, va_fsid, (uint32_t)VM_KERNEL_ADDRHASH(file_node->dn_dvm));
568*4d495c6eSApple OSS Distributions 	VATTR_RETURN(vap, va_fileid, (uintptr_t)file_node->dn_ino);
569*4d495c6eSApple OSS Distributions 	VATTR_RETURN(vap, va_data_size, file_node->dn_len);
570*4d495c6eSApple OSS Distributions 
571*4d495c6eSApple OSS Distributions 	/* return an override block size (advisory) */
572*4d495c6eSApple OSS Distributions 	if (vp->v_type == VBLK) {
573*4d495c6eSApple OSS Distributions 		VATTR_RETURN(vap, va_iosize, BLKDEV_IOSIZE);
574*4d495c6eSApple OSS Distributions 	} else if (vp->v_type == VCHR) {
575*4d495c6eSApple OSS Distributions 		VATTR_RETURN(vap, va_iosize, MAXPHYSIO);
576*4d495c6eSApple OSS Distributions 	} else {
577*4d495c6eSApple OSS Distributions 		VATTR_RETURN(vap, va_iosize, (uint32_t)vp->v_mount->mnt_vfsstat.f_iosize);
578*4d495c6eSApple OSS Distributions 	}
579*4d495c6eSApple OSS Distributions 
580*4d495c6eSApple OSS Distributions 
581*4d495c6eSApple OSS Distributions 	DEVFS_ATTR_LOCK_SPIN();
582*4d495c6eSApple OSS Distributions 
583*4d495c6eSApple OSS Distributions 	microtime(&now);
584*4d495c6eSApple OSS Distributions 	dn_times_locked(file_node, &now, &now, &now, 0);
585*4d495c6eSApple OSS Distributions 
586*4d495c6eSApple OSS Distributions 	/* if the time is bogus, set it to the boot time */
587*4d495c6eSApple OSS Distributions 	if (file_node->dn_ctime.tv_sec == 0) {
588*4d495c6eSApple OSS Distributions 		file_node->dn_ctime.tv_sec = boottime_sec();
589*4d495c6eSApple OSS Distributions 		file_node->dn_ctime.tv_nsec = 0;
590*4d495c6eSApple OSS Distributions 	}
591*4d495c6eSApple OSS Distributions 	if (file_node->dn_mtime.tv_sec == 0) {
592*4d495c6eSApple OSS Distributions 		file_node->dn_mtime = file_node->dn_ctime;
593*4d495c6eSApple OSS Distributions 	}
594*4d495c6eSApple OSS Distributions 	if (file_node->dn_atime.tv_sec == 0) {
595*4d495c6eSApple OSS Distributions 		file_node->dn_atime = file_node->dn_ctime;
596*4d495c6eSApple OSS Distributions 	}
597*4d495c6eSApple OSS Distributions 	VATTR_RETURN(vap, va_change_time, file_node->dn_ctime);
598*4d495c6eSApple OSS Distributions 	VATTR_RETURN(vap, va_modify_time, file_node->dn_mtime);
599*4d495c6eSApple OSS Distributions 	VATTR_RETURN(vap, va_access_time, file_node->dn_atime);
600*4d495c6eSApple OSS Distributions 
601*4d495c6eSApple OSS Distributions 	DEVFS_ATTR_UNLOCK();
602*4d495c6eSApple OSS Distributions 
603*4d495c6eSApple OSS Distributions 	VATTR_RETURN(vap, va_gen, 0);
604*4d495c6eSApple OSS Distributions 	VATTR_RETURN(vap, va_filerev, 0);
605*4d495c6eSApple OSS Distributions 	VATTR_RETURN(vap, va_acl, NULL);
606*4d495c6eSApple OSS Distributions 
607*4d495c6eSApple OSS Distributions 	/* Hide the root so Finder doesn't display it */
608*4d495c6eSApple OSS Distributions 	if (vnode_isvroot(vp)) {
609*4d495c6eSApple OSS Distributions 		VATTR_RETURN(vap, va_flags, UF_HIDDEN);
610*4d495c6eSApple OSS Distributions 	} else {
611*4d495c6eSApple OSS Distributions 		VATTR_RETURN(vap, va_flags, 0);
612*4d495c6eSApple OSS Distributions 	}
613*4d495c6eSApple OSS Distributions 
614*4d495c6eSApple OSS Distributions 	DEVFS_UNLOCK();
615*4d495c6eSApple OSS Distributions 
616*4d495c6eSApple OSS Distributions 	return 0;
617*4d495c6eSApple OSS Distributions }
618*4d495c6eSApple OSS Distributions 
619*4d495c6eSApple OSS Distributions static int
devfs_setattr(struct vnop_setattr_args * ap)620*4d495c6eSApple OSS Distributions devfs_setattr(struct vnop_setattr_args *ap)
621*4d495c6eSApple OSS Distributions /*struct vnop_setattr_args  {
622*4d495c6eSApple OSS Distributions  *  struct vnode *a_vp;
623*4d495c6eSApple OSS Distributions  *  struct vnode_attr *a_vap;
624*4d495c6eSApple OSS Distributions  *  vfs_context_t a_context;
625*4d495c6eSApple OSS Distributions  *  } */
626*4d495c6eSApple OSS Distributions {
627*4d495c6eSApple OSS Distributions 	struct vnode *vp = ap->a_vp;
628*4d495c6eSApple OSS Distributions 	struct vnode_attr *vap = ap->a_vap;
629*4d495c6eSApple OSS Distributions 	int error = 0;
630*4d495c6eSApple OSS Distributions 	devnode_t *     file_node;
631*4d495c6eSApple OSS Distributions 	struct timeval atimeval, mtimeval;
632*4d495c6eSApple OSS Distributions 
633*4d495c6eSApple OSS Distributions 	DEVFS_LOCK();
634*4d495c6eSApple OSS Distributions 
635*4d495c6eSApple OSS Distributions 	file_node = VTODN(vp);
636*4d495c6eSApple OSS Distributions 	/*
637*4d495c6eSApple OSS Distributions 	 * Go through the fields and update if set.
638*4d495c6eSApple OSS Distributions 	 */
639*4d495c6eSApple OSS Distributions 	if (VATTR_IS_ACTIVE(vap, va_access_time) || VATTR_IS_ACTIVE(vap, va_modify_time)) {
640*4d495c6eSApple OSS Distributions 		if (VATTR_IS_ACTIVE(vap, va_access_time)) {
641*4d495c6eSApple OSS Distributions 			file_node->dn_access = 1;
642*4d495c6eSApple OSS Distributions 		}
643*4d495c6eSApple OSS Distributions 		if (VATTR_IS_ACTIVE(vap, va_modify_time)) {
644*4d495c6eSApple OSS Distributions 			file_node->dn_change = 1;
645*4d495c6eSApple OSS Distributions 			file_node->dn_update = 1;
646*4d495c6eSApple OSS Distributions 		}
647*4d495c6eSApple OSS Distributions 		atimeval.tv_sec = vap->va_access_time.tv_sec;
648*4d495c6eSApple OSS Distributions 		atimeval.tv_usec = (suseconds_t)(vap->va_access_time.tv_nsec / 1000);
649*4d495c6eSApple OSS Distributions 		mtimeval.tv_sec = vap->va_modify_time.tv_sec;
650*4d495c6eSApple OSS Distributions 		mtimeval.tv_usec = (suseconds_t)(vap->va_modify_time.tv_nsec / 1000);
651*4d495c6eSApple OSS Distributions 
652*4d495c6eSApple OSS Distributions 		if ((error = devfs_update(vp, &atimeval, &mtimeval))) {
653*4d495c6eSApple OSS Distributions 			goto exit;
654*4d495c6eSApple OSS Distributions 		}
655*4d495c6eSApple OSS Distributions 	}
656*4d495c6eSApple OSS Distributions 	VATTR_SET_SUPPORTED(vap, va_access_time);
657*4d495c6eSApple OSS Distributions 	VATTR_SET_SUPPORTED(vap, va_change_time);
658*4d495c6eSApple OSS Distributions 
659*4d495c6eSApple OSS Distributions 	/*
660*4d495c6eSApple OSS Distributions 	 * Change the permissions.
661*4d495c6eSApple OSS Distributions 	 */
662*4d495c6eSApple OSS Distributions 	if (VATTR_IS_ACTIVE(vap, va_mode)) {
663*4d495c6eSApple OSS Distributions 		/*
664*4d495c6eSApple OSS Distributions 		 * Don't allow permission updates of critical devfs devices
665*4d495c6eSApple OSS Distributions 		 */
666*4d495c6eSApple OSS Distributions 		if (devfs_is_vnode_protected(vp)) {
667*4d495c6eSApple OSS Distributions 			error = EPERM;
668*4d495c6eSApple OSS Distributions 			goto exit;
669*4d495c6eSApple OSS Distributions 		}
670*4d495c6eSApple OSS Distributions 		file_node->dn_mode &= ~07777;
671*4d495c6eSApple OSS Distributions 		file_node->dn_mode |= vap->va_mode & 07777;
672*4d495c6eSApple OSS Distributions 	}
673*4d495c6eSApple OSS Distributions 	VATTR_SET_SUPPORTED(vap, va_mode);
674*4d495c6eSApple OSS Distributions 
675*4d495c6eSApple OSS Distributions 	/*
676*4d495c6eSApple OSS Distributions 	 * Change the owner.
677*4d495c6eSApple OSS Distributions 	 */
678*4d495c6eSApple OSS Distributions 	if (VATTR_IS_ACTIVE(vap, va_uid)) {
679*4d495c6eSApple OSS Distributions 		file_node->dn_uid = vap->va_uid;
680*4d495c6eSApple OSS Distributions 	}
681*4d495c6eSApple OSS Distributions 	VATTR_SET_SUPPORTED(vap, va_uid);
682*4d495c6eSApple OSS Distributions 
683*4d495c6eSApple OSS Distributions 	/*
684*4d495c6eSApple OSS Distributions 	 * Change the group.
685*4d495c6eSApple OSS Distributions 	 */
686*4d495c6eSApple OSS Distributions 	if (VATTR_IS_ACTIVE(vap, va_gid)) {
687*4d495c6eSApple OSS Distributions 		file_node->dn_gid = vap->va_gid;
688*4d495c6eSApple OSS Distributions 	}
689*4d495c6eSApple OSS Distributions 	VATTR_SET_SUPPORTED(vap, va_gid);
690*4d495c6eSApple OSS Distributions exit:
691*4d495c6eSApple OSS Distributions 	DEVFS_UNLOCK();
692*4d495c6eSApple OSS Distributions 
693*4d495c6eSApple OSS Distributions 	return error;
694*4d495c6eSApple OSS Distributions }
695*4d495c6eSApple OSS Distributions 
696*4d495c6eSApple OSS Distributions #if CONFIG_MACF
697*4d495c6eSApple OSS Distributions static int
devfs_setlabel(struct vnop_setlabel_args * ap)698*4d495c6eSApple OSS Distributions devfs_setlabel(struct vnop_setlabel_args *ap)
699*4d495c6eSApple OSS Distributions /* struct vnop_setlabel_args {
700*4d495c6eSApple OSS Distributions  *               struct vnodeop_desc *a_desc;
701*4d495c6eSApple OSS Distributions  *               struct vnode *a_vp;
702*4d495c6eSApple OSS Distributions  *               struct label *a_vl;
703*4d495c6eSApple OSS Distributions  *       vfs_context_t a_context;
704*4d495c6eSApple OSS Distributions  *       } */
705*4d495c6eSApple OSS Distributions {
706*4d495c6eSApple OSS Distributions 	struct vnode *vp;
707*4d495c6eSApple OSS Distributions 	struct devnode *de;
708*4d495c6eSApple OSS Distributions 
709*4d495c6eSApple OSS Distributions 	vp = ap->a_vp;
710*4d495c6eSApple OSS Distributions 	de = VTODN(vp);
711*4d495c6eSApple OSS Distributions 
712*4d495c6eSApple OSS Distributions 	mac_vnode_label_update(ap->a_context, vp, ap->a_vl);
713*4d495c6eSApple OSS Distributions 	mac_devfs_label_update(vp->v_mount, de, vp);
714*4d495c6eSApple OSS Distributions 
715*4d495c6eSApple OSS Distributions 	return 0;
716*4d495c6eSApple OSS Distributions }
717*4d495c6eSApple OSS Distributions #endif
718*4d495c6eSApple OSS Distributions 
719*4d495c6eSApple OSS Distributions static int
devfs_read(struct vnop_read_args * ap)720*4d495c6eSApple OSS Distributions devfs_read(struct vnop_read_args *ap)
721*4d495c6eSApple OSS Distributions /* struct vnop_read_args {
722*4d495c6eSApple OSS Distributions  *       struct vnode *a_vp;
723*4d495c6eSApple OSS Distributions  *       struct uio *a_uio;
724*4d495c6eSApple OSS Distributions  *       int  a_ioflag;
725*4d495c6eSApple OSS Distributions  *       vfs_context_t a_context;
726*4d495c6eSApple OSS Distributions  *  } */
727*4d495c6eSApple OSS Distributions {
728*4d495c6eSApple OSS Distributions 	devnode_t * dn_p = VTODN(ap->a_vp);
729*4d495c6eSApple OSS Distributions 
730*4d495c6eSApple OSS Distributions 	switch (ap->a_vp->v_type) {
731*4d495c6eSApple OSS Distributions 	case VDIR: {
732*4d495c6eSApple OSS Distributions 		dn_p->dn_access = 1;
733*4d495c6eSApple OSS Distributions 
734*4d495c6eSApple OSS Distributions 		return VNOP_READDIR(ap->a_vp, ap->a_uio, 0, NULL, NULL, ap->a_context);
735*4d495c6eSApple OSS Distributions 	}
736*4d495c6eSApple OSS Distributions 	default: {
737*4d495c6eSApple OSS Distributions 		printf("devfs_read(): bad file type %d", ap->a_vp->v_type);
738*4d495c6eSApple OSS Distributions 		return EINVAL;
739*4d495c6eSApple OSS Distributions 	}
740*4d495c6eSApple OSS Distributions 	}
741*4d495c6eSApple OSS Distributions }
742*4d495c6eSApple OSS Distributions 
743*4d495c6eSApple OSS Distributions static int
devfs_close(struct vnop_close_args * ap)744*4d495c6eSApple OSS Distributions devfs_close(struct vnop_close_args *ap)
745*4d495c6eSApple OSS Distributions /* struct vnop_close_args {
746*4d495c6eSApple OSS Distributions  *       struct vnode *a_vp;
747*4d495c6eSApple OSS Distributions  *       int  a_fflag;
748*4d495c6eSApple OSS Distributions  *       vfs_context_t a_context;
749*4d495c6eSApple OSS Distributions  *  } */
750*4d495c6eSApple OSS Distributions {
751*4d495c6eSApple OSS Distributions 	struct vnode *          vp = ap->a_vp;
752*4d495c6eSApple OSS Distributions 	devnode_t *     dnp;
753*4d495c6eSApple OSS Distributions 
754*4d495c6eSApple OSS Distributions 	if (vnode_isinuse(vp, 1)) {
755*4d495c6eSApple OSS Distributions 		DEVFS_LOCK();
756*4d495c6eSApple OSS Distributions 		dnp = VTODN(vp);
757*4d495c6eSApple OSS Distributions 		if (dnp) {
758*4d495c6eSApple OSS Distributions 			dn_times_now(dnp, 0);
759*4d495c6eSApple OSS Distributions 		}
760*4d495c6eSApple OSS Distributions 		DEVFS_UNLOCK();
761*4d495c6eSApple OSS Distributions 	}
762*4d495c6eSApple OSS Distributions 	return 0;
763*4d495c6eSApple OSS Distributions }
764*4d495c6eSApple OSS Distributions 
765*4d495c6eSApple OSS Distributions static int
devfsspec_close(struct vnop_close_args * ap)766*4d495c6eSApple OSS Distributions devfsspec_close(struct vnop_close_args *ap)
767*4d495c6eSApple OSS Distributions /* struct vnop_close_args {
768*4d495c6eSApple OSS Distributions  *       struct vnode *a_vp;
769*4d495c6eSApple OSS Distributions  *       int  a_fflag;
770*4d495c6eSApple OSS Distributions  *       vfs_context_t a_context;
771*4d495c6eSApple OSS Distributions  *  } */
772*4d495c6eSApple OSS Distributions {
773*4d495c6eSApple OSS Distributions 	struct vnode *          vp = ap->a_vp;
774*4d495c6eSApple OSS Distributions 	devnode_t *     dnp;
775*4d495c6eSApple OSS Distributions 
776*4d495c6eSApple OSS Distributions 	if (vnode_isinuse(vp, 0)) {
777*4d495c6eSApple OSS Distributions 		DEVFS_LOCK();
778*4d495c6eSApple OSS Distributions 		dnp = VTODN(vp);
779*4d495c6eSApple OSS Distributions 		if (dnp) {
780*4d495c6eSApple OSS Distributions 			dn_times_now(dnp, 0);
781*4d495c6eSApple OSS Distributions 		}
782*4d495c6eSApple OSS Distributions 		DEVFS_UNLOCK();
783*4d495c6eSApple OSS Distributions 	}
784*4d495c6eSApple OSS Distributions 
785*4d495c6eSApple OSS Distributions 	return VOCALL(spec_vnodeop_p, VOFFSET(vnop_close), ap);
786*4d495c6eSApple OSS Distributions }
787*4d495c6eSApple OSS Distributions 
788*4d495c6eSApple OSS Distributions static boolean_t
devfs_update_needed(long now_s,long last_s)789*4d495c6eSApple OSS Distributions devfs_update_needed(long now_s, long last_s)
790*4d495c6eSApple OSS Distributions {
791*4d495c6eSApple OSS Distributions 	if (now_s > last_s) {
792*4d495c6eSApple OSS Distributions 		if (now_s - last_s >= DEVFS_LAZY_UPDATE_SECONDS) {
793*4d495c6eSApple OSS Distributions 			return TRUE;
794*4d495c6eSApple OSS Distributions 		}
795*4d495c6eSApple OSS Distributions 	}
796*4d495c6eSApple OSS Distributions 
797*4d495c6eSApple OSS Distributions 	return FALSE;
798*4d495c6eSApple OSS Distributions }
799*4d495c6eSApple OSS Distributions 
800*4d495c6eSApple OSS Distributions /*
801*4d495c6eSApple OSS Distributions  * Given a set of time updates required [to happen at some point], check
802*4d495c6eSApple OSS Distributions  * either make those changes (and resolve other pending updates) or mark
803*4d495c6eSApple OSS Distributions  * the devnode for a subsequent update.
804*4d495c6eSApple OSS Distributions  */
805*4d495c6eSApple OSS Distributions static void
devfs_consider_time_update(devnode_t * dnp,uint32_t just_changed_flags)806*4d495c6eSApple OSS Distributions devfs_consider_time_update(devnode_t *dnp, uint32_t just_changed_flags)
807*4d495c6eSApple OSS Distributions {
808*4d495c6eSApple OSS Distributions 	struct timeval          now;
809*4d495c6eSApple OSS Distributions 	long now_s;
810*4d495c6eSApple OSS Distributions 
811*4d495c6eSApple OSS Distributions 	microtime(&now);
812*4d495c6eSApple OSS Distributions 	now_s = now.tv_sec;
813*4d495c6eSApple OSS Distributions 
814*4d495c6eSApple OSS Distributions 	if (dnp->dn_change || (just_changed_flags & DEVFS_UPDATE_CHANGE)) {
815*4d495c6eSApple OSS Distributions 		if (devfs_update_needed(now_s, dnp->dn_ctime.tv_sec)) {
816*4d495c6eSApple OSS Distributions 			dn_times_now(dnp, just_changed_flags);
817*4d495c6eSApple OSS Distributions 			return;
818*4d495c6eSApple OSS Distributions 		}
819*4d495c6eSApple OSS Distributions 	}
820*4d495c6eSApple OSS Distributions 	if (dnp->dn_access || (just_changed_flags & DEVFS_UPDATE_ACCESS)) {
821*4d495c6eSApple OSS Distributions 		if (devfs_update_needed(now_s, dnp->dn_atime.tv_sec)) {
822*4d495c6eSApple OSS Distributions 			dn_times_now(dnp, just_changed_flags);
823*4d495c6eSApple OSS Distributions 			return;
824*4d495c6eSApple OSS Distributions 		}
825*4d495c6eSApple OSS Distributions 	}
826*4d495c6eSApple OSS Distributions 	if (dnp->dn_update || (just_changed_flags & DEVFS_UPDATE_MOD)) {
827*4d495c6eSApple OSS Distributions 		if (devfs_update_needed(now_s, dnp->dn_mtime.tv_sec)) {
828*4d495c6eSApple OSS Distributions 			dn_times_now(dnp, just_changed_flags);
829*4d495c6eSApple OSS Distributions 			return;
830*4d495c6eSApple OSS Distributions 		}
831*4d495c6eSApple OSS Distributions 	}
832*4d495c6eSApple OSS Distributions 
833*4d495c6eSApple OSS Distributions 	/* Not going to do anything now--mark for later update */
834*4d495c6eSApple OSS Distributions 	dn_mark_for_delayed_times_update(dnp, just_changed_flags);
835*4d495c6eSApple OSS Distributions 
836*4d495c6eSApple OSS Distributions 	return;
837*4d495c6eSApple OSS Distributions }
838*4d495c6eSApple OSS Distributions 
839*4d495c6eSApple OSS Distributions static int
devfsspec_read(struct vnop_read_args * ap)840*4d495c6eSApple OSS Distributions devfsspec_read(struct vnop_read_args *ap)
841*4d495c6eSApple OSS Distributions /* struct vnop_read_args {
842*4d495c6eSApple OSS Distributions  *       struct vnode *a_vp;
843*4d495c6eSApple OSS Distributions  *       struct uio *a_uio;
844*4d495c6eSApple OSS Distributions  *       int  a_ioflag;
845*4d495c6eSApple OSS Distributions  *       kauth_cred_t a_cred;
846*4d495c6eSApple OSS Distributions  *  } */
847*4d495c6eSApple OSS Distributions {
848*4d495c6eSApple OSS Distributions 	devnode_t *     dnp = VTODN(ap->a_vp);
849*4d495c6eSApple OSS Distributions 
850*4d495c6eSApple OSS Distributions 	devfs_consider_time_update(dnp, DEVFS_UPDATE_ACCESS);
851*4d495c6eSApple OSS Distributions 
852*4d495c6eSApple OSS Distributions 	return VOCALL(spec_vnodeop_p, VOFFSET(vnop_read), ap);
853*4d495c6eSApple OSS Distributions }
854*4d495c6eSApple OSS Distributions 
855*4d495c6eSApple OSS Distributions static int
devfsspec_write(struct vnop_write_args * ap)856*4d495c6eSApple OSS Distributions devfsspec_write(struct vnop_write_args *ap)
857*4d495c6eSApple OSS Distributions /* struct vnop_write_args  {
858*4d495c6eSApple OSS Distributions  *       struct vnode *a_vp;
859*4d495c6eSApple OSS Distributions  *       struct uio *a_uio;
860*4d495c6eSApple OSS Distributions  *       int  a_ioflag;
861*4d495c6eSApple OSS Distributions  *       vfs_context_t a_context;
862*4d495c6eSApple OSS Distributions  *  } */
863*4d495c6eSApple OSS Distributions {
864*4d495c6eSApple OSS Distributions 	devnode_t *     dnp = VTODN(ap->a_vp);
865*4d495c6eSApple OSS Distributions 
866*4d495c6eSApple OSS Distributions 	devfs_consider_time_update(dnp, DEVFS_UPDATE_CHANGE | DEVFS_UPDATE_MOD);
867*4d495c6eSApple OSS Distributions 
868*4d495c6eSApple OSS Distributions 	return VOCALL(spec_vnodeop_p, VOFFSET(vnop_write), ap);
869*4d495c6eSApple OSS Distributions }
870*4d495c6eSApple OSS Distributions 
871*4d495c6eSApple OSS Distributions /*
872*4d495c6eSApple OSS Distributions  *  Write data to a file or directory.
873*4d495c6eSApple OSS Distributions  */
874*4d495c6eSApple OSS Distributions static int
devfs_write(struct vnop_write_args * ap)875*4d495c6eSApple OSS Distributions devfs_write(struct vnop_write_args *ap)
876*4d495c6eSApple OSS Distributions /* struct vnop_write_args  {
877*4d495c6eSApple OSS Distributions  *       struct vnode *a_vp;
878*4d495c6eSApple OSS Distributions  *       struct uio *a_uio;
879*4d495c6eSApple OSS Distributions  *       int  a_ioflag;
880*4d495c6eSApple OSS Distributions  *       kauth_cred_t a_cred;
881*4d495c6eSApple OSS Distributions  *  } */
882*4d495c6eSApple OSS Distributions {
883*4d495c6eSApple OSS Distributions 	switch (ap->a_vp->v_type) {
884*4d495c6eSApple OSS Distributions 	case VDIR:
885*4d495c6eSApple OSS Distributions 		return EISDIR;
886*4d495c6eSApple OSS Distributions 	default:
887*4d495c6eSApple OSS Distributions 		printf("devfs_write(): bad file type %d", ap->a_vp->v_type);
888*4d495c6eSApple OSS Distributions 		return EINVAL;
889*4d495c6eSApple OSS Distributions 	}
890*4d495c6eSApple OSS Distributions }
891*4d495c6eSApple OSS Distributions 
892*4d495c6eSApple OSS Distributions /*
893*4d495c6eSApple OSS Distributions  * Deviates from UFS naming convention because there is a KPI function
894*4d495c6eSApple OSS Distributions  * called devfs_remove().
895*4d495c6eSApple OSS Distributions  */
896*4d495c6eSApple OSS Distributions static int
devfs_vnop_remove(struct vnop_remove_args * ap)897*4d495c6eSApple OSS Distributions devfs_vnop_remove(struct vnop_remove_args *ap)
898*4d495c6eSApple OSS Distributions /* struct vnop_remove_args  {
899*4d495c6eSApple OSS Distributions  *       struct vnode *a_dvp;
900*4d495c6eSApple OSS Distributions  *       struct vnode *a_vp;
901*4d495c6eSApple OSS Distributions  *       struct componentname *a_cnp;
902*4d495c6eSApple OSS Distributions  *  } */
903*4d495c6eSApple OSS Distributions {
904*4d495c6eSApple OSS Distributions 	struct vnode *vp = ap->a_vp;
905*4d495c6eSApple OSS Distributions 	struct vnode *dvp = ap->a_dvp;
906*4d495c6eSApple OSS Distributions 	struct componentname *cnp = ap->a_cnp;
907*4d495c6eSApple OSS Distributions 	devnode_t *  tp;
908*4d495c6eSApple OSS Distributions 	devnode_t *  tdp;
909*4d495c6eSApple OSS Distributions 	devdirent_t * tnp;
910*4d495c6eSApple OSS Distributions 	int doingdirectory = 0;
911*4d495c6eSApple OSS Distributions 	int error = 0;
912*4d495c6eSApple OSS Distributions 
913*4d495c6eSApple OSS Distributions 	/*
914*4d495c6eSApple OSS Distributions 	 * assume that the name is null terminated as they
915*4d495c6eSApple OSS Distributions 	 * are the end of the path. Get pointers to all our
916*4d495c6eSApple OSS Distributions 	 * devfs structures.
917*4d495c6eSApple OSS Distributions 	 */
918*4d495c6eSApple OSS Distributions 
919*4d495c6eSApple OSS Distributions 	DEVFS_LOCK();
920*4d495c6eSApple OSS Distributions 
921*4d495c6eSApple OSS Distributions 	tp = VTODN(vp);
922*4d495c6eSApple OSS Distributions 	tdp = VTODN(dvp);
923*4d495c6eSApple OSS Distributions 
924*4d495c6eSApple OSS Distributions 
925*4d495c6eSApple OSS Distributions 	tnp = dev_findname(tdp, cnp->cn_nameptr);
926*4d495c6eSApple OSS Distributions 
927*4d495c6eSApple OSS Distributions 	if (tnp == NULL) {
928*4d495c6eSApple OSS Distributions 		error = ENOENT;
929*4d495c6eSApple OSS Distributions 		goto abort;
930*4d495c6eSApple OSS Distributions 	}
931*4d495c6eSApple OSS Distributions 
932*4d495c6eSApple OSS Distributions 	/*
933*4d495c6eSApple OSS Distributions 	 * Don't allow removing critical devfs devices
934*4d495c6eSApple OSS Distributions 	 */
935*4d495c6eSApple OSS Distributions 	if (devfs_is_name_protected(dvp, cnp->cn_nameptr)) {
936*4d495c6eSApple OSS Distributions 		error = EINVAL;
937*4d495c6eSApple OSS Distributions 		goto abort;
938*4d495c6eSApple OSS Distributions 	}
939*4d495c6eSApple OSS Distributions 
940*4d495c6eSApple OSS Distributions 	/*
941*4d495c6eSApple OSS Distributions 	 * Make sure that we don't try do something stupid
942*4d495c6eSApple OSS Distributions 	 */
943*4d495c6eSApple OSS Distributions 	if ((tp->dn_type) == DEV_DIR) {
944*4d495c6eSApple OSS Distributions 		/*
945*4d495c6eSApple OSS Distributions 		 * Avoid ".", "..", and aliases of "." for obvious reasons.
946*4d495c6eSApple OSS Distributions 		 */
947*4d495c6eSApple OSS Distributions 		if ((cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.')
948*4d495c6eSApple OSS Distributions 		    || (cnp->cn_flags & ISDOTDOT)) {
949*4d495c6eSApple OSS Distributions 			error = EINVAL;
950*4d495c6eSApple OSS Distributions 			goto abort;
951*4d495c6eSApple OSS Distributions 		}
952*4d495c6eSApple OSS Distributions 		doingdirectory++;
953*4d495c6eSApple OSS Distributions 	}
954*4d495c6eSApple OSS Distributions 
955*4d495c6eSApple OSS Distributions 	/***********************************
956*4d495c6eSApple OSS Distributions 	* Start actually doing things.... *
957*4d495c6eSApple OSS Distributions 	***********************************/
958*4d495c6eSApple OSS Distributions 	devfs_consider_time_update(tdp, DEVFS_UPDATE_CHANGE | DEVFS_UPDATE_MOD);
959*4d495c6eSApple OSS Distributions 
960*4d495c6eSApple OSS Distributions 	/*
961*4d495c6eSApple OSS Distributions 	 * Target must be empty if a directory and have no links
962*4d495c6eSApple OSS Distributions 	 * to it. Also, ensure source and target are compatible
963*4d495c6eSApple OSS Distributions 	 * (both directories, or both not directories).
964*4d495c6eSApple OSS Distributions 	 */
965*4d495c6eSApple OSS Distributions 	if ((doingdirectory) && (tp->dn_links > 2)) {
966*4d495c6eSApple OSS Distributions 		error = ENOTEMPTY;
967*4d495c6eSApple OSS Distributions 		goto abort;
968*4d495c6eSApple OSS Distributions 	}
969*4d495c6eSApple OSS Distributions 	dev_free_name(tnp);
970*4d495c6eSApple OSS Distributions abort:
971*4d495c6eSApple OSS Distributions 	DEVFS_UNLOCK();
972*4d495c6eSApple OSS Distributions 
973*4d495c6eSApple OSS Distributions 	return error;
974*4d495c6eSApple OSS Distributions }
975*4d495c6eSApple OSS Distributions 
976*4d495c6eSApple OSS Distributions /*
977*4d495c6eSApple OSS Distributions  */
978*4d495c6eSApple OSS Distributions static int
devfs_link(struct vnop_link_args * ap)979*4d495c6eSApple OSS Distributions devfs_link(struct vnop_link_args *ap)
980*4d495c6eSApple OSS Distributions /*struct vnop_link_args  {
981*4d495c6eSApple OSS Distributions  *       struct vnode *a_tdvp;
982*4d495c6eSApple OSS Distributions  *       struct vnode *a_vp;
983*4d495c6eSApple OSS Distributions  *       struct componentname *a_cnp;
984*4d495c6eSApple OSS Distributions  *       vfs_context_t a_context;
985*4d495c6eSApple OSS Distributions  *  } */
986*4d495c6eSApple OSS Distributions {
987*4d495c6eSApple OSS Distributions 	struct vnode *vp = ap->a_vp;
988*4d495c6eSApple OSS Distributions 	struct vnode *tdvp = ap->a_tdvp;
989*4d495c6eSApple OSS Distributions 	struct componentname *cnp = ap->a_cnp;
990*4d495c6eSApple OSS Distributions 	devnode_t * fp;
991*4d495c6eSApple OSS Distributions 	devnode_t * tdp;
992*4d495c6eSApple OSS Distributions 	devdirent_t * tnp;
993*4d495c6eSApple OSS Distributions 	int error = 0;
994*4d495c6eSApple OSS Distributions 
995*4d495c6eSApple OSS Distributions 	/*
996*4d495c6eSApple OSS Distributions 	 * First catch an arbitrary restriction for this FS
997*4d495c6eSApple OSS Distributions 	 */
998*4d495c6eSApple OSS Distributions 	if (cnp->cn_namelen > DEVMAXNAMESIZE) {
999*4d495c6eSApple OSS Distributions 		error = ENAMETOOLONG;
1000*4d495c6eSApple OSS Distributions 		goto out1;
1001*4d495c6eSApple OSS Distributions 	}
1002*4d495c6eSApple OSS Distributions 
1003*4d495c6eSApple OSS Distributions 	/*
1004*4d495c6eSApple OSS Distributions 	 * Lock our directories and get our name pointers
1005*4d495c6eSApple OSS Distributions 	 * assume that the names are null terminated as they
1006*4d495c6eSApple OSS Distributions 	 * are the end of the path. Get pointers to all our
1007*4d495c6eSApple OSS Distributions 	 * devfs structures.
1008*4d495c6eSApple OSS Distributions 	 */
1009*4d495c6eSApple OSS Distributions 	/* can lookup dnode safely for tdvp outside of devfs lock as it is not aliased */
1010*4d495c6eSApple OSS Distributions 	tdp = VTODN(tdvp);
1011*4d495c6eSApple OSS Distributions 
1012*4d495c6eSApple OSS Distributions 	if (tdvp->v_mount != vp->v_mount) {
1013*4d495c6eSApple OSS Distributions 		return EXDEV;
1014*4d495c6eSApple OSS Distributions 	}
1015*4d495c6eSApple OSS Distributions 	DEVFS_LOCK();
1016*4d495c6eSApple OSS Distributions 
1017*4d495c6eSApple OSS Distributions 	fp = VTODN(vp);
1018*4d495c6eSApple OSS Distributions 
1019*4d495c6eSApple OSS Distributions 	/***********************************
1020*4d495c6eSApple OSS Distributions 	* Start actually doing things.... *
1021*4d495c6eSApple OSS Distributions 	***********************************/
1022*4d495c6eSApple OSS Distributions 	dn_times_now(fp, DEVFS_UPDATE_CHANGE);
1023*4d495c6eSApple OSS Distributions 
1024*4d495c6eSApple OSS Distributions 	if (!error) {
1025*4d495c6eSApple OSS Distributions 		error = dev_add_name(cnp->cn_nameptr, tdp, NULL, fp, &tnp);
1026*4d495c6eSApple OSS Distributions 	}
1027*4d495c6eSApple OSS Distributions out1:
1028*4d495c6eSApple OSS Distributions 	DEVFS_UNLOCK();
1029*4d495c6eSApple OSS Distributions 
1030*4d495c6eSApple OSS Distributions 	return error;
1031*4d495c6eSApple OSS Distributions }
1032*4d495c6eSApple OSS Distributions 
1033*4d495c6eSApple OSS Distributions #define MAX_NESTED_DIRS  16
1034*4d495c6eSApple OSS Distributions 
1035*4d495c6eSApple OSS Distributions /*
1036*4d495c6eSApple OSS Distributions  * Rename system call. Seems overly complicated to me...
1037*4d495c6eSApple OSS Distributions  *      rename("foo", "bar");
1038*4d495c6eSApple OSS Distributions  * is essentially
1039*4d495c6eSApple OSS Distributions  *	unlink("bar");
1040*4d495c6eSApple OSS Distributions  *	link("foo", "bar");
1041*4d495c6eSApple OSS Distributions  *	unlink("foo");
1042*4d495c6eSApple OSS Distributions  * but ``atomically''.
1043*4d495c6eSApple OSS Distributions  *
1044*4d495c6eSApple OSS Distributions  * When the target exists, both the directory
1045*4d495c6eSApple OSS Distributions  * and target vnodes are locked.
1046*4d495c6eSApple OSS Distributions  * the source and source-parent vnodes are referenced
1047*4d495c6eSApple OSS Distributions  *
1048*4d495c6eSApple OSS Distributions  *
1049*4d495c6eSApple OSS Distributions  * Basic algorithm is:
1050*4d495c6eSApple OSS Distributions  *
1051*4d495c6eSApple OSS Distributions  * 1) Bump link count on source while we're linking it to the
1052*4d495c6eSApple OSS Distributions  *    target.  This also ensure the inode won't be deleted out
1053*4d495c6eSApple OSS Distributions  *    from underneath us while we work (it may be truncated by
1054*4d495c6eSApple OSS Distributions  *    a concurrent `trunc' or `open' for creation).
1055*4d495c6eSApple OSS Distributions  * 2) Link source to destination.  If destination already exists,
1056*4d495c6eSApple OSS Distributions  *    delete it first.
1057*4d495c6eSApple OSS Distributions  * 3) Unlink source reference to node if still around. If a
1058*4d495c6eSApple OSS Distributions  *    directory was moved and the parent of the destination
1059*4d495c6eSApple OSS Distributions  *    is different from the source, patch the ".." entry in the
1060*4d495c6eSApple OSS Distributions  *    directory.
1061*4d495c6eSApple OSS Distributions  */
1062*4d495c6eSApple OSS Distributions static int
devfs_rename(struct vnop_rename_args * ap)1063*4d495c6eSApple OSS Distributions devfs_rename(struct vnop_rename_args *ap)
1064*4d495c6eSApple OSS Distributions /*struct vnop_rename_args  {
1065*4d495c6eSApple OSS Distributions  *       struct vnode *a_fdvp;
1066*4d495c6eSApple OSS Distributions  *       struct vnode *a_fvp;
1067*4d495c6eSApple OSS Distributions  *       struct componentname *a_fcnp;
1068*4d495c6eSApple OSS Distributions  *       struct vnode *a_tdvp;
1069*4d495c6eSApple OSS Distributions  *       struct vnode *a_tvp;
1070*4d495c6eSApple OSS Distributions  *       struct componentname *a_tcnp;
1071*4d495c6eSApple OSS Distributions  *       vfs_context_t a_context;
1072*4d495c6eSApple OSS Distributions  *  } */
1073*4d495c6eSApple OSS Distributions {
1074*4d495c6eSApple OSS Distributions 	struct vnode *tvp = ap->a_tvp;
1075*4d495c6eSApple OSS Distributions 	struct vnode *tdvp = ap->a_tdvp;
1076*4d495c6eSApple OSS Distributions 	struct vnode *fvp = ap->a_fvp;
1077*4d495c6eSApple OSS Distributions 	struct vnode *fdvp = ap->a_fdvp;
1078*4d495c6eSApple OSS Distributions 	struct componentname *tcnp = ap->a_tcnp;
1079*4d495c6eSApple OSS Distributions 	struct componentname *fcnp = ap->a_fcnp;
1080*4d495c6eSApple OSS Distributions 	devnode_t *fp, *fdp, *tp, *tdp;
1081*4d495c6eSApple OSS Distributions 	devdirent_t *fnp, *tnp;
1082*4d495c6eSApple OSS Distributions 	int doingdirectory = 0;
1083*4d495c6eSApple OSS Distributions 	int error = 0;
1084*4d495c6eSApple OSS Distributions 
1085*4d495c6eSApple OSS Distributions 	DEVFS_LOCK();
1086*4d495c6eSApple OSS Distributions 	/*
1087*4d495c6eSApple OSS Distributions 	 * First catch an arbitrary restriction for this FS
1088*4d495c6eSApple OSS Distributions 	 */
1089*4d495c6eSApple OSS Distributions 	if (tcnp->cn_namelen > DEVMAXNAMESIZE) {
1090*4d495c6eSApple OSS Distributions 		error = ENAMETOOLONG;
1091*4d495c6eSApple OSS Distributions 		goto out;
1092*4d495c6eSApple OSS Distributions 	}
1093*4d495c6eSApple OSS Distributions 
1094*4d495c6eSApple OSS Distributions 	/*
1095*4d495c6eSApple OSS Distributions 	 * assume that the names are null terminated as they
1096*4d495c6eSApple OSS Distributions 	 * are the end of the path. Get pointers to all our
1097*4d495c6eSApple OSS Distributions 	 * devfs structures.
1098*4d495c6eSApple OSS Distributions 	 */
1099*4d495c6eSApple OSS Distributions 	tdp = VTODN(tdvp);
1100*4d495c6eSApple OSS Distributions 	fdp = VTODN(fdvp);
1101*4d495c6eSApple OSS Distributions 	fp = VTODN(fvp);
1102*4d495c6eSApple OSS Distributions 
1103*4d495c6eSApple OSS Distributions 	fnp = dev_findname(fdp, fcnp->cn_nameptr);
1104*4d495c6eSApple OSS Distributions 
1105*4d495c6eSApple OSS Distributions 	if (fnp == NULL) {
1106*4d495c6eSApple OSS Distributions 		error = ENOENT;
1107*4d495c6eSApple OSS Distributions 		goto out;
1108*4d495c6eSApple OSS Distributions 	}
1109*4d495c6eSApple OSS Distributions 	tp = NULL;
1110*4d495c6eSApple OSS Distributions 	tnp = NULL;
1111*4d495c6eSApple OSS Distributions 
1112*4d495c6eSApple OSS Distributions 	if (tvp) {
1113*4d495c6eSApple OSS Distributions 		tnp = dev_findname(tdp, tcnp->cn_nameptr);
1114*4d495c6eSApple OSS Distributions 
1115*4d495c6eSApple OSS Distributions 		if (tnp == NULL) {
1116*4d495c6eSApple OSS Distributions 			error = ENOENT;
1117*4d495c6eSApple OSS Distributions 			goto out;
1118*4d495c6eSApple OSS Distributions 		}
1119*4d495c6eSApple OSS Distributions 		tp = VTODN(tvp);
1120*4d495c6eSApple OSS Distributions 	}
1121*4d495c6eSApple OSS Distributions 
1122*4d495c6eSApple OSS Distributions 	/*
1123*4d495c6eSApple OSS Distributions 	 * Make sure that we don't try do something stupid
1124*4d495c6eSApple OSS Distributions 	 */
1125*4d495c6eSApple OSS Distributions 	if ((fp->dn_type) == DEV_DIR) {
1126*4d495c6eSApple OSS Distributions 		/*
1127*4d495c6eSApple OSS Distributions 		 * Avoid ".", "..", and aliases of "." for obvious reasons.
1128*4d495c6eSApple OSS Distributions 		 */
1129*4d495c6eSApple OSS Distributions 		if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.')
1130*4d495c6eSApple OSS Distributions 		    || (fcnp->cn_flags & ISDOTDOT)
1131*4d495c6eSApple OSS Distributions 		    || (tcnp->cn_namelen == 1 && tcnp->cn_nameptr[0] == '.')
1132*4d495c6eSApple OSS Distributions 		    || (tcnp->cn_flags & ISDOTDOT)
1133*4d495c6eSApple OSS Distributions 		    || (tdp == fp)) {
1134*4d495c6eSApple OSS Distributions 			error = EINVAL;
1135*4d495c6eSApple OSS Distributions 			goto out;
1136*4d495c6eSApple OSS Distributions 		}
1137*4d495c6eSApple OSS Distributions 		doingdirectory++;
1138*4d495c6eSApple OSS Distributions 	}
1139*4d495c6eSApple OSS Distributions 
1140*4d495c6eSApple OSS Distributions 	/*
1141*4d495c6eSApple OSS Distributions 	 * Don't allow renaming critical devfs devices
1142*4d495c6eSApple OSS Distributions 	 */
1143*4d495c6eSApple OSS Distributions 	if (devfs_is_name_protected(fdvp, fcnp->cn_nameptr) ||
1144*4d495c6eSApple OSS Distributions 	    devfs_is_name_protected(tdvp, tcnp->cn_nameptr)) {
1145*4d495c6eSApple OSS Distributions 		error = EINVAL;
1146*4d495c6eSApple OSS Distributions 		goto out;
1147*4d495c6eSApple OSS Distributions 	}
1148*4d495c6eSApple OSS Distributions 
1149*4d495c6eSApple OSS Distributions 	/*
1150*4d495c6eSApple OSS Distributions 	 * If ".." must be changed (ie the directory gets a new
1151*4d495c6eSApple OSS Distributions 	 * parent) then the source directory must not be in the
1152*4d495c6eSApple OSS Distributions 	 * directory hierarchy above the target, as this would
1153*4d495c6eSApple OSS Distributions 	 * orphan everything below the source directory. Also
1154*4d495c6eSApple OSS Distributions 	 * the user must have write permission in the source so
1155*4d495c6eSApple OSS Distributions 	 * as to be able to change "..".
1156*4d495c6eSApple OSS Distributions 	 */
1157*4d495c6eSApple OSS Distributions 	if (doingdirectory && (tdp != fdp)) {
1158*4d495c6eSApple OSS Distributions 		devnode_t * tmp, *ntmp;
1159*4d495c6eSApple OSS Distributions 		tmp = tdp;
1160*4d495c6eSApple OSS Distributions 		do {
1161*4d495c6eSApple OSS Distributions 			if (tmp == fp) {
1162*4d495c6eSApple OSS Distributions 				/* XXX unlock stuff here probably */
1163*4d495c6eSApple OSS Distributions 				error = EINVAL;
1164*4d495c6eSApple OSS Distributions 				goto out;
1165*4d495c6eSApple OSS Distributions 			}
1166*4d495c6eSApple OSS Distributions 			ntmp = tmp;
1167*4d495c6eSApple OSS Distributions 		} while ((tmp = tmp->dn_typeinfo.Dir.parent) != ntmp);
1168*4d495c6eSApple OSS Distributions 	}
1169*4d495c6eSApple OSS Distributions 
1170*4d495c6eSApple OSS Distributions 	/*
1171*4d495c6eSApple OSS Distributions 	 * If we are renaming a directory, fail the rename if the deepest subdir
1172*4d495c6eSApple OSS Distributions 	 * in the target after rename is going to exceed the MAX_NESTED_DIRS limit.
1173*4d495c6eSApple OSS Distributions 	 */
1174*4d495c6eSApple OSS Distributions 	if (doingdirectory) {
1175*4d495c6eSApple OSS Distributions 		if ((devfs_subdirs_depth(fnp) + devfs_nested_dirs_depth(tdp)) >=
1176*4d495c6eSApple OSS Distributions 		    MAX_NESTED_DIRS) {
1177*4d495c6eSApple OSS Distributions 			error = EMLINK;
1178*4d495c6eSApple OSS Distributions 			goto out;
1179*4d495c6eSApple OSS Distributions 		}
1180*4d495c6eSApple OSS Distributions 	}
1181*4d495c6eSApple OSS Distributions 
1182*4d495c6eSApple OSS Distributions 	/***********************************
1183*4d495c6eSApple OSS Distributions 	* Start actually doing things.... *
1184*4d495c6eSApple OSS Distributions 	***********************************/
1185*4d495c6eSApple OSS Distributions 	dn_times_now(fp, DEVFS_UPDATE_CHANGE);
1186*4d495c6eSApple OSS Distributions 
1187*4d495c6eSApple OSS Distributions 	/*
1188*4d495c6eSApple OSS Distributions 	 * Check if just deleting a link name.
1189*4d495c6eSApple OSS Distributions 	 */
1190*4d495c6eSApple OSS Distributions 	if (fvp == tvp) {
1191*4d495c6eSApple OSS Distributions 		if (fvp->v_type == VDIR) {
1192*4d495c6eSApple OSS Distributions 			error = EINVAL;
1193*4d495c6eSApple OSS Distributions 			goto out;
1194*4d495c6eSApple OSS Distributions 		}
1195*4d495c6eSApple OSS Distributions 		/* Release destination completely. */
1196*4d495c6eSApple OSS Distributions 		dev_free_name(fnp);
1197*4d495c6eSApple OSS Distributions 
1198*4d495c6eSApple OSS Distributions 		DEVFS_UNLOCK();
1199*4d495c6eSApple OSS Distributions 		return 0;
1200*4d495c6eSApple OSS Distributions 	}
1201*4d495c6eSApple OSS Distributions 	/*
1202*4d495c6eSApple OSS Distributions 	 * 1) Bump link count while we're moving stuff
1203*4d495c6eSApple OSS Distributions 	 *    around.  If we crash somewhere before
1204*4d495c6eSApple OSS Distributions 	 *    completing our work,  too bad :)
1205*4d495c6eSApple OSS Distributions 	 */
1206*4d495c6eSApple OSS Distributions 	fp->dn_links++;
1207*4d495c6eSApple OSS Distributions 	/*
1208*4d495c6eSApple OSS Distributions 	 * If the target exists zap it (unless it's a non-empty directory)
1209*4d495c6eSApple OSS Distributions 	 * We could do that as well but won't
1210*4d495c6eSApple OSS Distributions 	 */
1211*4d495c6eSApple OSS Distributions 	if (tp) {
1212*4d495c6eSApple OSS Distributions 		/*
1213*4d495c6eSApple OSS Distributions 		 * Target must be empty if a directory and have no links
1214*4d495c6eSApple OSS Distributions 		 * to it. Also, ensure source and target are compatible
1215*4d495c6eSApple OSS Distributions 		 * (both directories, or both not directories).
1216*4d495c6eSApple OSS Distributions 		 */
1217*4d495c6eSApple OSS Distributions 		if ((doingdirectory) && (tp->dn_links > 2)) {
1218*4d495c6eSApple OSS Distributions 			error = ENOTEMPTY;
1219*4d495c6eSApple OSS Distributions 			goto bad;
1220*4d495c6eSApple OSS Distributions 		}
1221*4d495c6eSApple OSS Distributions 		dev_free_name(tnp);
1222*4d495c6eSApple OSS Distributions 		tp = NULL;
1223*4d495c6eSApple OSS Distributions 	}
1224*4d495c6eSApple OSS Distributions 	dev_add_name(tcnp->cn_nameptr, tdp, NULL, fp, &tnp);
1225*4d495c6eSApple OSS Distributions 	fnp->de_dnp = NULL;
1226*4d495c6eSApple OSS Distributions 	fp->dn_links--; /* one less link to it.. */
1227*4d495c6eSApple OSS Distributions 
1228*4d495c6eSApple OSS Distributions 	dev_free_name(fnp);
1229*4d495c6eSApple OSS Distributions bad:
1230*4d495c6eSApple OSS Distributions 	fp->dn_links--; /* we added one earlier*/
1231*4d495c6eSApple OSS Distributions out:
1232*4d495c6eSApple OSS Distributions 	DEVFS_UNLOCK();
1233*4d495c6eSApple OSS Distributions 	return error;
1234*4d495c6eSApple OSS Distributions }
1235*4d495c6eSApple OSS Distributions 
1236*4d495c6eSApple OSS Distributions static int
devfs_mkdir(struct vnop_mkdir_args * ap)1237*4d495c6eSApple OSS Distributions devfs_mkdir(struct vnop_mkdir_args *ap)
1238*4d495c6eSApple OSS Distributions /*struct vnop_mkdir_args {
1239*4d495c6eSApple OSS Distributions  *       struct vnode *a_dvp;
1240*4d495c6eSApple OSS Distributions  *       struct vnode **a_vpp;
1241*4d495c6eSApple OSS Distributions  *       struct componentname *a_cnp;
1242*4d495c6eSApple OSS Distributions  *       struct vnode_attr *a_vap;
1243*4d495c6eSApple OSS Distributions  *       vfs_context_t a_context;
1244*4d495c6eSApple OSS Distributions  *  } */
1245*4d495c6eSApple OSS Distributions {
1246*4d495c6eSApple OSS Distributions 	struct componentname * cnp = ap->a_cnp;
1247*4d495c6eSApple OSS Distributions 	vfs_context_t ctx = cnp->cn_context;
1248*4d495c6eSApple OSS Distributions 	struct proc *p = vfs_context_proc(ctx);
1249*4d495c6eSApple OSS Distributions 	int error = 0;
1250*4d495c6eSApple OSS Distributions 	devnode_t * dir_p;
1251*4d495c6eSApple OSS Distributions 	devdirent_t * nm_p;
1252*4d495c6eSApple OSS Distributions 	devnode_t * dev_p;
1253*4d495c6eSApple OSS Distributions 	struct vnode_attr * vap = ap->a_vap;
1254*4d495c6eSApple OSS Distributions 	struct vnode * * vpp = ap->a_vpp;
1255*4d495c6eSApple OSS Distributions 
1256*4d495c6eSApple OSS Distributions 	DEVFS_LOCK();
1257*4d495c6eSApple OSS Distributions 
1258*4d495c6eSApple OSS Distributions 	dir_p = VTODN(ap->a_dvp);
1259*4d495c6eSApple OSS Distributions 
1260*4d495c6eSApple OSS Distributions 	/* Fail the mkdir if the depth of parent dir is already at the limit. */
1261*4d495c6eSApple OSS Distributions 	if (devfs_nested_dirs_depth(dir_p) >= MAX_NESTED_DIRS) {
1262*4d495c6eSApple OSS Distributions 		error = EMLINK;
1263*4d495c6eSApple OSS Distributions 		goto failure;
1264*4d495c6eSApple OSS Distributions 	}
1265*4d495c6eSApple OSS Distributions 
1266*4d495c6eSApple OSS Distributions 	error = dev_add_entry(cnp->cn_nameptr, dir_p, DEV_DIR,
1267*4d495c6eSApple OSS Distributions 	    NULL, NULL, NULL, &nm_p);
1268*4d495c6eSApple OSS Distributions 	if (error) {
1269*4d495c6eSApple OSS Distributions 		goto failure;
1270*4d495c6eSApple OSS Distributions 	}
1271*4d495c6eSApple OSS Distributions 	dev_p = nm_p->de_dnp;
1272*4d495c6eSApple OSS Distributions 	dev_p->dn_uid = dir_p->dn_uid;
1273*4d495c6eSApple OSS Distributions 	dev_p->dn_gid = dir_p->dn_gid;
1274*4d495c6eSApple OSS Distributions 	dev_p->dn_mode = vap->va_mode;
1275*4d495c6eSApple OSS Distributions 	dn_copy_times(dev_p, dir_p);
1276*4d495c6eSApple OSS Distributions 
1277*4d495c6eSApple OSS Distributions 	error = devfs_dntovn(dev_p, vpp, p);
1278*4d495c6eSApple OSS Distributions failure:
1279*4d495c6eSApple OSS Distributions 	DEVFS_UNLOCK();
1280*4d495c6eSApple OSS Distributions 
1281*4d495c6eSApple OSS Distributions 	return error;
1282*4d495c6eSApple OSS Distributions }
1283*4d495c6eSApple OSS Distributions 
1284*4d495c6eSApple OSS Distributions /*
1285*4d495c6eSApple OSS Distributions  * An rmdir is a special type of remove, which we already support; we wrap
1286*4d495c6eSApple OSS Distributions  * and reexpress the arguments to call devfs_remove directly.  The only
1287*4d495c6eSApple OSS Distributions  * different argument is flags, which we do not set, since it's ignored.
1288*4d495c6eSApple OSS Distributions  */
1289*4d495c6eSApple OSS Distributions static int
devfs_rmdir(struct vnop_rmdir_args * ap)1290*4d495c6eSApple OSS Distributions devfs_rmdir(struct vnop_rmdir_args *ap)
1291*4d495c6eSApple OSS Distributions /* struct vnop_rmdir_args {
1292*4d495c6eSApple OSS Distributions  *       struct vnode *a_dvp;
1293*4d495c6eSApple OSS Distributions  *       struct vnode *a_vp;
1294*4d495c6eSApple OSS Distributions  *       struct componentname *a_cnp;
1295*4d495c6eSApple OSS Distributions  *       vfs_context_t a_context;
1296*4d495c6eSApple OSS Distributions  *  } */
1297*4d495c6eSApple OSS Distributions {
1298*4d495c6eSApple OSS Distributions 	struct vnop_remove_args ra;
1299*4d495c6eSApple OSS Distributions 
1300*4d495c6eSApple OSS Distributions 	ra.a_dvp = ap->a_dvp;
1301*4d495c6eSApple OSS Distributions 	ra.a_vp = ap->a_vp;
1302*4d495c6eSApple OSS Distributions 	ra.a_cnp = ap->a_cnp;
1303*4d495c6eSApple OSS Distributions 	ra.a_flags = 0;         /* XXX */
1304*4d495c6eSApple OSS Distributions 	ra.a_context = ap->a_context;
1305*4d495c6eSApple OSS Distributions 
1306*4d495c6eSApple OSS Distributions 	return devfs_vnop_remove(&ra);
1307*4d495c6eSApple OSS Distributions }
1308*4d495c6eSApple OSS Distributions 
1309*4d495c6eSApple OSS Distributions 
1310*4d495c6eSApple OSS Distributions static int
devfs_symlink(struct vnop_symlink_args * ap)1311*4d495c6eSApple OSS Distributions devfs_symlink(struct vnop_symlink_args *ap)
1312*4d495c6eSApple OSS Distributions /*struct vnop_symlink_args {
1313*4d495c6eSApple OSS Distributions  *       struct vnode *a_dvp;
1314*4d495c6eSApple OSS Distributions  *       struct vnode **a_vpp;
1315*4d495c6eSApple OSS Distributions  *       struct componentname *a_cnp;
1316*4d495c6eSApple OSS Distributions  *       struct vnode_attr *a_vap;
1317*4d495c6eSApple OSS Distributions  *       char *a_target;
1318*4d495c6eSApple OSS Distributions  *       vfs_context_t a_context;
1319*4d495c6eSApple OSS Distributions  *  } */
1320*4d495c6eSApple OSS Distributions {
1321*4d495c6eSApple OSS Distributions 	int error;
1322*4d495c6eSApple OSS Distributions 	devdirent_t *newent;
1323*4d495c6eSApple OSS Distributions 
1324*4d495c6eSApple OSS Distributions 	DEVFS_LOCK();
1325*4d495c6eSApple OSS Distributions 	error = devfs_make_symlink(VTODN(ap->a_dvp), ap->a_cnp->cn_nameptr, ap->a_vap->va_mode, ap->a_target, &newent);
1326*4d495c6eSApple OSS Distributions 
1327*4d495c6eSApple OSS Distributions 	if (error == 0) {
1328*4d495c6eSApple OSS Distributions 		error = devfs_dntovn(newent->de_dnp, ap->a_vpp, vfs_context_proc(ap->a_context));
1329*4d495c6eSApple OSS Distributions 	}
1330*4d495c6eSApple OSS Distributions 
1331*4d495c6eSApple OSS Distributions 	DEVFS_UNLOCK();
1332*4d495c6eSApple OSS Distributions 
1333*4d495c6eSApple OSS Distributions 	return error;
1334*4d495c6eSApple OSS Distributions }
1335*4d495c6eSApple OSS Distributions 
1336*4d495c6eSApple OSS Distributions /* Called with devfs locked */
1337*4d495c6eSApple OSS Distributions int
devfs_make_symlink(devnode_t * dir_p,char * name,mode_t mode,char * target,devdirent_t ** newent)1338*4d495c6eSApple OSS Distributions devfs_make_symlink(devnode_t *dir_p, char *name, mode_t mode, char *target, devdirent_t **newent)
1339*4d495c6eSApple OSS Distributions {
1340*4d495c6eSApple OSS Distributions 	int error = 0;
1341*4d495c6eSApple OSS Distributions 	devnode_type_t typeinfo;
1342*4d495c6eSApple OSS Distributions 	devdirent_t * nm_p;
1343*4d495c6eSApple OSS Distributions 	devnode_t * dev_p;
1344*4d495c6eSApple OSS Distributions 
1345*4d495c6eSApple OSS Distributions 	typeinfo.Slnk.name = target;
1346*4d495c6eSApple OSS Distributions 	typeinfo.Slnk.namelen = strlen(target);
1347*4d495c6eSApple OSS Distributions 
1348*4d495c6eSApple OSS Distributions 	error = dev_add_entry(name, dir_p, DEV_SLNK,
1349*4d495c6eSApple OSS Distributions 	    &typeinfo, NULL, NULL, &nm_p);
1350*4d495c6eSApple OSS Distributions 	if (error) {
1351*4d495c6eSApple OSS Distributions 		goto failure;
1352*4d495c6eSApple OSS Distributions 	}
1353*4d495c6eSApple OSS Distributions 	dev_p = nm_p->de_dnp;
1354*4d495c6eSApple OSS Distributions 	dev_p->dn_uid = dir_p->dn_uid;
1355*4d495c6eSApple OSS Distributions 	dev_p->dn_gid = dir_p->dn_gid;
1356*4d495c6eSApple OSS Distributions 	dev_p->dn_mode = mode;
1357*4d495c6eSApple OSS Distributions 	dn_copy_times(dev_p, dir_p);
1358*4d495c6eSApple OSS Distributions 
1359*4d495c6eSApple OSS Distributions 	if (newent) {
1360*4d495c6eSApple OSS Distributions 		*newent = nm_p;
1361*4d495c6eSApple OSS Distributions 	}
1362*4d495c6eSApple OSS Distributions 
1363*4d495c6eSApple OSS Distributions failure:
1364*4d495c6eSApple OSS Distributions 
1365*4d495c6eSApple OSS Distributions 	return error;
1366*4d495c6eSApple OSS Distributions }
1367*4d495c6eSApple OSS Distributions 
1368*4d495c6eSApple OSS Distributions /*
1369*4d495c6eSApple OSS Distributions  * Mknod vnode call
1370*4d495c6eSApple OSS Distributions  */
1371*4d495c6eSApple OSS Distributions static int
devfs_mknod(struct vnop_mknod_args * ap)1372*4d495c6eSApple OSS Distributions devfs_mknod(struct vnop_mknod_args *ap)
1373*4d495c6eSApple OSS Distributions /* struct vnop_mknod_args {
1374*4d495c6eSApple OSS Distributions  *       struct vnode *a_dvp;
1375*4d495c6eSApple OSS Distributions  *       struct vnode **a_vpp;
1376*4d495c6eSApple OSS Distributions  *       struct componentname *a_cnp;
1377*4d495c6eSApple OSS Distributions  *       struct vnode_attr *a_vap;
1378*4d495c6eSApple OSS Distributions  *       vfs_context_t a_context;
1379*4d495c6eSApple OSS Distributions  *  } */
1380*4d495c6eSApple OSS Distributions {
1381*4d495c6eSApple OSS Distributions 	struct componentname * cnp = ap->a_cnp;
1382*4d495c6eSApple OSS Distributions 	vfs_context_t ctx = cnp->cn_context;
1383*4d495c6eSApple OSS Distributions 	struct proc *p = vfs_context_proc(ctx);
1384*4d495c6eSApple OSS Distributions 	devnode_t *     dev_p;
1385*4d495c6eSApple OSS Distributions 	devdirent_t *   devent;
1386*4d495c6eSApple OSS Distributions 	devnode_t *     dir_p;  /* devnode for parent directory */
1387*4d495c6eSApple OSS Distributions 	struct vnode *  dvp = ap->a_dvp;
1388*4d495c6eSApple OSS Distributions 	int             error = 0;
1389*4d495c6eSApple OSS Distributions 	devnode_type_t  typeinfo;
1390*4d495c6eSApple OSS Distributions 	struct vnode_attr *     vap = ap->a_vap;
1391*4d495c6eSApple OSS Distributions 	struct vnode ** vpp = ap->a_vpp;
1392*4d495c6eSApple OSS Distributions 
1393*4d495c6eSApple OSS Distributions 	*vpp = NULL;
1394*4d495c6eSApple OSS Distributions 	if (!(vap->va_type == VBLK) && !(vap->va_type == VCHR)) {
1395*4d495c6eSApple OSS Distributions 		return EINVAL; /* only support mknod of special files */
1396*4d495c6eSApple OSS Distributions 	}
1397*4d495c6eSApple OSS Distributions 	typeinfo.dev = vap->va_rdev;
1398*4d495c6eSApple OSS Distributions 
1399*4d495c6eSApple OSS Distributions 	DEVFS_LOCK();
1400*4d495c6eSApple OSS Distributions 
1401*4d495c6eSApple OSS Distributions 	dir_p = VTODN(dvp);
1402*4d495c6eSApple OSS Distributions 
1403*4d495c6eSApple OSS Distributions 	error = dev_add_entry(cnp->cn_nameptr, dir_p,
1404*4d495c6eSApple OSS Distributions 	    (vap->va_type == VBLK) ? DEV_BDEV : DEV_CDEV,
1405*4d495c6eSApple OSS Distributions 	    &typeinfo, NULL, NULL, &devent);
1406*4d495c6eSApple OSS Distributions 	if (error) {
1407*4d495c6eSApple OSS Distributions 		goto failure;
1408*4d495c6eSApple OSS Distributions 	}
1409*4d495c6eSApple OSS Distributions 	dev_p = devent->de_dnp;
1410*4d495c6eSApple OSS Distributions 	error = devfs_dntovn(dev_p, vpp, p);
1411*4d495c6eSApple OSS Distributions 	if (error) {
1412*4d495c6eSApple OSS Distributions 		goto failure;
1413*4d495c6eSApple OSS Distributions 	}
1414*4d495c6eSApple OSS Distributions 	dev_p->dn_uid = vap->va_uid;
1415*4d495c6eSApple OSS Distributions 	dev_p->dn_gid = vap->va_gid;
1416*4d495c6eSApple OSS Distributions 	dev_p->dn_mode = vap->va_mode;
1417*4d495c6eSApple OSS Distributions 	VATTR_SET_SUPPORTED(vap, va_uid);
1418*4d495c6eSApple OSS Distributions 	VATTR_SET_SUPPORTED(vap, va_gid);
1419*4d495c6eSApple OSS Distributions 	VATTR_SET_SUPPORTED(vap, va_mode);
1420*4d495c6eSApple OSS Distributions failure:
1421*4d495c6eSApple OSS Distributions 	DEVFS_UNLOCK();
1422*4d495c6eSApple OSS Distributions 
1423*4d495c6eSApple OSS Distributions 	return error;
1424*4d495c6eSApple OSS Distributions }
1425*4d495c6eSApple OSS Distributions 
1426*4d495c6eSApple OSS Distributions /*
1427*4d495c6eSApple OSS Distributions  * Vnode op for readdir
1428*4d495c6eSApple OSS Distributions  */
1429*4d495c6eSApple OSS Distributions static int
devfs_readdir(struct vnop_readdir_args * ap)1430*4d495c6eSApple OSS Distributions devfs_readdir(struct vnop_readdir_args *ap)
1431*4d495c6eSApple OSS Distributions /*struct vnop_readdir_args {
1432*4d495c6eSApple OSS Distributions  *       struct vnode *a_vp;
1433*4d495c6eSApple OSS Distributions  *       struct uio *a_uio;
1434*4d495c6eSApple OSS Distributions  *       int a_flags;
1435*4d495c6eSApple OSS Distributions  *       int *a_eofflag;
1436*4d495c6eSApple OSS Distributions  *       int *a_numdirent;
1437*4d495c6eSApple OSS Distributions  *       vfs_context_t a_context;
1438*4d495c6eSApple OSS Distributions  *  } */
1439*4d495c6eSApple OSS Distributions {
1440*4d495c6eSApple OSS Distributions 	struct vnode *vp = ap->a_vp;
1441*4d495c6eSApple OSS Distributions 	struct uio *uio = ap->a_uio;
1442*4d495c6eSApple OSS Distributions 	struct dirent dirent;
1443*4d495c6eSApple OSS Distributions 	devnode_t * dir_node;
1444*4d495c6eSApple OSS Distributions 	devdirent_t *   name_node;
1445*4d495c6eSApple OSS Distributions 	const char *name;
1446*4d495c6eSApple OSS Distributions 	int error = 0;
1447*4d495c6eSApple OSS Distributions 	int reclen;
1448*4d495c6eSApple OSS Distributions 	int nodenumber;
1449*4d495c6eSApple OSS Distributions 	off_t startpos, pos;
1450*4d495c6eSApple OSS Distributions 
1451*4d495c6eSApple OSS Distributions 	if (ap->a_flags & (VNODE_READDIR_EXTENDED | VNODE_READDIR_REQSEEKOFF)) {
1452*4d495c6eSApple OSS Distributions 		return EINVAL;
1453*4d495c6eSApple OSS Distributions 	}
1454*4d495c6eSApple OSS Distributions 
1455*4d495c6eSApple OSS Distributions 	/*  set up refs to dir */
1456*4d495c6eSApple OSS Distributions 	dir_node = VTODN(vp);
1457*4d495c6eSApple OSS Distributions 	if (dir_node->dn_type != DEV_DIR) {
1458*4d495c6eSApple OSS Distributions 		return ENOTDIR;
1459*4d495c6eSApple OSS Distributions 	}
1460*4d495c6eSApple OSS Distributions 	pos = 0;
1461*4d495c6eSApple OSS Distributions 	startpos = uio->uio_offset;
1462*4d495c6eSApple OSS Distributions 
1463*4d495c6eSApple OSS Distributions 	DEVFS_LOCK();
1464*4d495c6eSApple OSS Distributions 
1465*4d495c6eSApple OSS Distributions 	name_node = dir_node->dn_typeinfo.Dir.dirlist;
1466*4d495c6eSApple OSS Distributions 	nodenumber = 0;
1467*4d495c6eSApple OSS Distributions 
1468*4d495c6eSApple OSS Distributions 	while ((name_node || (nodenumber < 2)) && (uio_resid(uio) > 0)) {
1469*4d495c6eSApple OSS Distributions 		switch (nodenumber) {
1470*4d495c6eSApple OSS Distributions 		case    0:
1471*4d495c6eSApple OSS Distributions 			dirent.d_fileno = dir_node->dn_ino;
1472*4d495c6eSApple OSS Distributions 			name = ".";
1473*4d495c6eSApple OSS Distributions 			dirent.d_namlen = 1;
1474*4d495c6eSApple OSS Distributions 			dirent.d_type = DT_DIR;
1475*4d495c6eSApple OSS Distributions 			break;
1476*4d495c6eSApple OSS Distributions 		case    1:
1477*4d495c6eSApple OSS Distributions 			if (dir_node->dn_typeinfo.Dir.parent) {
1478*4d495c6eSApple OSS Distributions 				dirent.d_fileno = dir_node->dn_typeinfo.Dir.parent->dn_ino;
1479*4d495c6eSApple OSS Distributions 			} else {
1480*4d495c6eSApple OSS Distributions 				dirent.d_fileno = dir_node->dn_ino;
1481*4d495c6eSApple OSS Distributions 			}
1482*4d495c6eSApple OSS Distributions 			name = "..";
1483*4d495c6eSApple OSS Distributions 			dirent.d_namlen = 2;
1484*4d495c6eSApple OSS Distributions 			dirent.d_type = DT_DIR;
1485*4d495c6eSApple OSS Distributions 			break;
1486*4d495c6eSApple OSS Distributions 		default:
1487*4d495c6eSApple OSS Distributions 			dirent.d_fileno = name_node->de_dnp->dn_ino;
1488*4d495c6eSApple OSS Distributions 			dirent.d_namlen = (__uint8_t) strlen(name_node->de_name);
1489*4d495c6eSApple OSS Distributions 			name = name_node->de_name;
1490*4d495c6eSApple OSS Distributions 			switch (name_node->de_dnp->dn_type) {
1491*4d495c6eSApple OSS Distributions 			case DEV_BDEV:
1492*4d495c6eSApple OSS Distributions 				dirent.d_type = DT_BLK;
1493*4d495c6eSApple OSS Distributions 				break;
1494*4d495c6eSApple OSS Distributions 			case DEV_CDEV:
1495*4d495c6eSApple OSS Distributions 				dirent.d_type = DT_CHR;
1496*4d495c6eSApple OSS Distributions 				break;
1497*4d495c6eSApple OSS Distributions 			case DEV_DIR:
1498*4d495c6eSApple OSS Distributions 				dirent.d_type = DT_DIR;
1499*4d495c6eSApple OSS Distributions 				break;
1500*4d495c6eSApple OSS Distributions 			case DEV_SLNK:
1501*4d495c6eSApple OSS Distributions 				dirent.d_type = DT_LNK;
1502*4d495c6eSApple OSS Distributions 				break;
1503*4d495c6eSApple OSS Distributions 			default:
1504*4d495c6eSApple OSS Distributions 				dirent.d_type = DT_UNKNOWN;
1505*4d495c6eSApple OSS Distributions 			}
1506*4d495c6eSApple OSS Distributions 		}
1507*4d495c6eSApple OSS Distributions #define GENERIC_DIRSIZ(dp) \
1508*4d495c6eSApple OSS Distributions     ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
1509*4d495c6eSApple OSS Distributions 
1510*4d495c6eSApple OSS Distributions 		reclen = dirent.d_reclen = GENERIC_DIRSIZ(&dirent);
1511*4d495c6eSApple OSS Distributions 
1512*4d495c6eSApple OSS Distributions 		if (pos >= startpos) {   /* made it to the offset yet? */
1513*4d495c6eSApple OSS Distributions 			if (uio_resid(uio) < reclen) { /* will it fit? */
1514*4d495c6eSApple OSS Distributions 				break;
1515*4d495c6eSApple OSS Distributions 			}
1516*4d495c6eSApple OSS Distributions 			strlcpy(dirent.d_name, name, DEVMAXNAMESIZE);
1517*4d495c6eSApple OSS Distributions 			if ((error = uiomove((caddr_t)&dirent,
1518*4d495c6eSApple OSS Distributions 			    dirent.d_reclen, uio)) != 0) {
1519*4d495c6eSApple OSS Distributions 				break;
1520*4d495c6eSApple OSS Distributions 			}
1521*4d495c6eSApple OSS Distributions 		}
1522*4d495c6eSApple OSS Distributions 		pos += reclen;
1523*4d495c6eSApple OSS Distributions 		if ((nodenumber > 1) && name_node) {
1524*4d495c6eSApple OSS Distributions 			name_node = name_node->de_next;
1525*4d495c6eSApple OSS Distributions 		}
1526*4d495c6eSApple OSS Distributions 		nodenumber++;
1527*4d495c6eSApple OSS Distributions 	}
1528*4d495c6eSApple OSS Distributions 	DEVFS_UNLOCK();
1529*4d495c6eSApple OSS Distributions 	uio->uio_offset = pos;
1530*4d495c6eSApple OSS Distributions 
1531*4d495c6eSApple OSS Distributions 	devfs_consider_time_update(dir_node, DEVFS_UPDATE_ACCESS);
1532*4d495c6eSApple OSS Distributions 
1533*4d495c6eSApple OSS Distributions 	return error;
1534*4d495c6eSApple OSS Distributions }
1535*4d495c6eSApple OSS Distributions 
1536*4d495c6eSApple OSS Distributions 
1537*4d495c6eSApple OSS Distributions /*
1538*4d495c6eSApple OSS Distributions  */
1539*4d495c6eSApple OSS Distributions static int
devfs_readlink(struct vnop_readlink_args * ap)1540*4d495c6eSApple OSS Distributions devfs_readlink(struct vnop_readlink_args *ap)
1541*4d495c6eSApple OSS Distributions /*struct vnop_readlink_args {
1542*4d495c6eSApple OSS Distributions  *       struct vnode *a_vp;
1543*4d495c6eSApple OSS Distributions  *       struct uio *a_uio;
1544*4d495c6eSApple OSS Distributions  *       vfs_context_t a_context;
1545*4d495c6eSApple OSS Distributions  *  } */
1546*4d495c6eSApple OSS Distributions {
1547*4d495c6eSApple OSS Distributions 	struct vnode *vp = ap->a_vp;
1548*4d495c6eSApple OSS Distributions 	struct uio *uio = ap->a_uio;
1549*4d495c6eSApple OSS Distributions 	devnode_t * lnk_node;
1550*4d495c6eSApple OSS Distributions 	int error = 0;
1551*4d495c6eSApple OSS Distributions 
1552*4d495c6eSApple OSS Distributions 	/*  set up refs to dir */
1553*4d495c6eSApple OSS Distributions 	lnk_node = VTODN(vp);
1554*4d495c6eSApple OSS Distributions 
1555*4d495c6eSApple OSS Distributions 	if (lnk_node->dn_type != DEV_SLNK) {
1556*4d495c6eSApple OSS Distributions 		error = EINVAL;
1557*4d495c6eSApple OSS Distributions 		goto out;
1558*4d495c6eSApple OSS Distributions 	}
1559*4d495c6eSApple OSS Distributions 	error = uiomove(lnk_node->dn_typeinfo.Slnk.name,
1560*4d495c6eSApple OSS Distributions 	    (int)lnk_node->dn_typeinfo.Slnk.namelen, uio);
1561*4d495c6eSApple OSS Distributions out:
1562*4d495c6eSApple OSS Distributions 	return error;
1563*4d495c6eSApple OSS Distributions }
1564*4d495c6eSApple OSS Distributions 
1565*4d495c6eSApple OSS Distributions static int
devfs_reclaim(struct vnop_reclaim_args * ap)1566*4d495c6eSApple OSS Distributions devfs_reclaim(struct vnop_reclaim_args *ap)
1567*4d495c6eSApple OSS Distributions /*struct vnop_reclaim_args {
1568*4d495c6eSApple OSS Distributions  *       struct vnode *a_vp;
1569*4d495c6eSApple OSS Distributions  *  } */
1570*4d495c6eSApple OSS Distributions {
1571*4d495c6eSApple OSS Distributions 	struct vnode *      vp = ap->a_vp;
1572*4d495c6eSApple OSS Distributions 	devnode_t *         dnp;
1573*4d495c6eSApple OSS Distributions 
1574*4d495c6eSApple OSS Distributions 	DEVFS_LOCK();
1575*4d495c6eSApple OSS Distributions 
1576*4d495c6eSApple OSS Distributions 	dnp = VTODN(vp);
1577*4d495c6eSApple OSS Distributions 
1578*4d495c6eSApple OSS Distributions 	if (dnp) {
1579*4d495c6eSApple OSS Distributions 		/* If this is a cloning device, it didn't have a dn_vn anyway */
1580*4d495c6eSApple OSS Distributions 		dnp->dn_vn = NULL;
1581*4d495c6eSApple OSS Distributions 		vnode_clearfsnode(vp);
1582*4d495c6eSApple OSS Distributions 
1583*4d495c6eSApple OSS Distributions 		/* This could delete the node, if we are the last vnode */
1584*4d495c6eSApple OSS Distributions 		devfs_rele_node(dnp);
1585*4d495c6eSApple OSS Distributions 	}
1586*4d495c6eSApple OSS Distributions 	DEVFS_UNLOCK();
1587*4d495c6eSApple OSS Distributions 
1588*4d495c6eSApple OSS Distributions 	return 0;
1589*4d495c6eSApple OSS Distributions }
1590*4d495c6eSApple OSS Distributions 
1591*4d495c6eSApple OSS Distributions 
1592*4d495c6eSApple OSS Distributions /*
1593*4d495c6eSApple OSS Distributions  * Get configurable pathname variables.
1594*4d495c6eSApple OSS Distributions  */
1595*4d495c6eSApple OSS Distributions static int
devs_vnop_pathconf(struct vnop_pathconf_args * ap)1596*4d495c6eSApple OSS Distributions devs_vnop_pathconf(
1597*4d495c6eSApple OSS Distributions 	struct vnop_pathconf_args /* {
1598*4d495c6eSApple OSS Distributions                                    *  struct vnode *a_vp;
1599*4d495c6eSApple OSS Distributions                                    *  int a_name;
1600*4d495c6eSApple OSS Distributions                                    *  int *a_retval;
1601*4d495c6eSApple OSS Distributions                                    *  vfs_context_t a_context;
1602*4d495c6eSApple OSS Distributions                                    *  } */*ap)
1603*4d495c6eSApple OSS Distributions {
1604*4d495c6eSApple OSS Distributions 	switch (ap->a_name) {
1605*4d495c6eSApple OSS Distributions 	case _PC_LINK_MAX:
1606*4d495c6eSApple OSS Distributions 		/* arbitrary limit matching HFS; devfs has no hard limit */
1607*4d495c6eSApple OSS Distributions 		*ap->a_retval = 32767;
1608*4d495c6eSApple OSS Distributions 		break;
1609*4d495c6eSApple OSS Distributions 	case _PC_NAME_MAX:
1610*4d495c6eSApple OSS Distributions 		*ap->a_retval = DEVMAXNAMESIZE - 1;     /* includes NUL */
1611*4d495c6eSApple OSS Distributions 		break;
1612*4d495c6eSApple OSS Distributions 	case _PC_PATH_MAX:
1613*4d495c6eSApple OSS Distributions 		*ap->a_retval = DEVMAXPATHSIZE - 1;     /* XXX nonconformant */
1614*4d495c6eSApple OSS Distributions 		break;
1615*4d495c6eSApple OSS Distributions 	case _PC_CHOWN_RESTRICTED:
1616*4d495c6eSApple OSS Distributions 		*ap->a_retval = 200112;         /* _POSIX_CHOWN_RESTRICTED */
1617*4d495c6eSApple OSS Distributions 		break;
1618*4d495c6eSApple OSS Distributions 	case _PC_NO_TRUNC:
1619*4d495c6eSApple OSS Distributions 		*ap->a_retval = 0;
1620*4d495c6eSApple OSS Distributions 		break;
1621*4d495c6eSApple OSS Distributions 	case _PC_CASE_SENSITIVE:
1622*4d495c6eSApple OSS Distributions 		*ap->a_retval = 1;
1623*4d495c6eSApple OSS Distributions 		break;
1624*4d495c6eSApple OSS Distributions 	case _PC_CASE_PRESERVING:
1625*4d495c6eSApple OSS Distributions 		*ap->a_retval = 1;
1626*4d495c6eSApple OSS Distributions 		break;
1627*4d495c6eSApple OSS Distributions 	default:
1628*4d495c6eSApple OSS Distributions 		return EINVAL;
1629*4d495c6eSApple OSS Distributions 	}
1630*4d495c6eSApple OSS Distributions 
1631*4d495c6eSApple OSS Distributions 	return 0;
1632*4d495c6eSApple OSS Distributions }
1633*4d495c6eSApple OSS Distributions 
1634*4d495c6eSApple OSS Distributions 
1635*4d495c6eSApple OSS Distributions 
1636*4d495c6eSApple OSS Distributions /**************************************************************************\
1637*4d495c6eSApple OSS Distributions * pseudo ops *
1638*4d495c6eSApple OSS Distributions \**************************************************************************/
1639*4d495c6eSApple OSS Distributions 
1640*4d495c6eSApple OSS Distributions /*
1641*4d495c6eSApple OSS Distributions  *
1642*4d495c6eSApple OSS Distributions  *	struct vnop_inactive_args {
1643*4d495c6eSApple OSS Distributions  *		struct vnode *a_vp;
1644*4d495c6eSApple OSS Distributions  *		vfs_context_t a_context;
1645*4d495c6eSApple OSS Distributions  *	}
1646*4d495c6eSApple OSS Distributions  */
1647*4d495c6eSApple OSS Distributions 
1648*4d495c6eSApple OSS Distributions static int
devfs_inactive(__unused struct vnop_inactive_args * ap)1649*4d495c6eSApple OSS Distributions devfs_inactive(__unused struct vnop_inactive_args *ap)
1650*4d495c6eSApple OSS Distributions {
1651*4d495c6eSApple OSS Distributions 	vnode_t vp = ap->a_vp;
1652*4d495c6eSApple OSS Distributions 	devnode_t *dnp = VTODN(vp);
1653*4d495c6eSApple OSS Distributions 
1654*4d495c6eSApple OSS Distributions 	/*
1655*4d495c6eSApple OSS Distributions 	 * Cloned vnodes are not linked in anywhere, so they
1656*4d495c6eSApple OSS Distributions 	 * can just be recycled.
1657*4d495c6eSApple OSS Distributions 	 */
1658*4d495c6eSApple OSS Distributions 	if (dnp->dn_clone != NULL) {
1659*4d495c6eSApple OSS Distributions 		vnode_recycle(vp);
1660*4d495c6eSApple OSS Distributions 	}
1661*4d495c6eSApple OSS Distributions 
1662*4d495c6eSApple OSS Distributions 	return 0;
1663*4d495c6eSApple OSS Distributions }
1664*4d495c6eSApple OSS Distributions 
1665*4d495c6eSApple OSS Distributions /*
1666*4d495c6eSApple OSS Distributions  * called with DEVFS_LOCK held
1667*4d495c6eSApple OSS Distributions  */
1668*4d495c6eSApple OSS Distributions static int
devfs_update(struct vnode * vp,struct timeval * access,struct timeval * modify)1669*4d495c6eSApple OSS Distributions devfs_update(struct vnode *vp, struct timeval *access, struct timeval *modify)
1670*4d495c6eSApple OSS Distributions {
1671*4d495c6eSApple OSS Distributions 	devnode_t * ip;
1672*4d495c6eSApple OSS Distributions 	struct timeval now;
1673*4d495c6eSApple OSS Distributions 
1674*4d495c6eSApple OSS Distributions 	ip = VTODN(vp);
1675*4d495c6eSApple OSS Distributions 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1676*4d495c6eSApple OSS Distributions 		ip->dn_access = 0;
1677*4d495c6eSApple OSS Distributions 		ip->dn_change = 0;
1678*4d495c6eSApple OSS Distributions 		ip->dn_update = 0;
1679*4d495c6eSApple OSS Distributions 
1680*4d495c6eSApple OSS Distributions 		return 0;
1681*4d495c6eSApple OSS Distributions 	}
1682*4d495c6eSApple OSS Distributions 
1683*4d495c6eSApple OSS Distributions 	DEVFS_ATTR_LOCK_SPIN();
1684*4d495c6eSApple OSS Distributions 	microtime(&now);
1685*4d495c6eSApple OSS Distributions 	dn_times_locked(ip, access, modify, &now, DEVFS_UPDATE_ACCESS | DEVFS_UPDATE_MOD);
1686*4d495c6eSApple OSS Distributions 	DEVFS_ATTR_UNLOCK();
1687*4d495c6eSApple OSS Distributions 
1688*4d495c6eSApple OSS Distributions 	return 0;
1689*4d495c6eSApple OSS Distributions }
1690*4d495c6eSApple OSS Distributions 
1691*4d495c6eSApple OSS Distributions #define VOPFUNC int (*)(void *)
1692*4d495c6eSApple OSS Distributions 
1693*4d495c6eSApple OSS Distributions #define devfs_default_error (void (*)(void))vn_default_error
1694*4d495c6eSApple OSS Distributions 
1695*4d495c6eSApple OSS Distributions /* The following ops are used by directories and symlinks */
1696*4d495c6eSApple OSS Distributions int(**devfs_vnodeop_p)(void *);
1697*4d495c6eSApple OSS Distributions const static struct vnodeopv_entry_desc devfs_vnodeop_entries[] = {
1698*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_default_desc, .opve_impl = (VOPFUNC)devfs_default_error },
1699*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_lookup_desc, .opve_impl = (VOPFUNC)devfs_lookup },           /* lookup */
1700*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_create_desc, .opve_impl = (VOPFUNC)err_create },             /* create */
1701*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_whiteout_desc, .opve_impl = (VOPFUNC)err_whiteout },         /* whiteout */
1702*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_mknod_desc, .opve_impl = (VOPFUNC)devfs_mknod },             /* mknod */
1703*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_open_desc, .opve_impl = (VOPFUNC)nop_open },                 /* open */
1704*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_close_desc, .opve_impl = (VOPFUNC)devfs_close },             /* close */
1705*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_getattr_desc, .opve_impl = (VOPFUNC)devfs_getattr },         /* getattr */
1706*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_setattr_desc, .opve_impl = (VOPFUNC)devfs_setattr },         /* setattr */
1707*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_read_desc, .opve_impl = (VOPFUNC)devfs_read },               /* read */
1708*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_write_desc, .opve_impl = (VOPFUNC)devfs_write },             /* write */
1709*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_ioctl_desc, .opve_impl = (VOPFUNC)err_ioctl },               /* ioctl */
1710*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_select_desc, .opve_impl = (VOPFUNC)err_select },             /* select */
1711*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_revoke_desc, .opve_impl = (VOPFUNC)err_revoke },             /* revoke */
1712*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_mmap_desc, .opve_impl = (VOPFUNC)err_mmap },                 /* mmap */
1713*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_fsync_desc, .opve_impl = (VOPFUNC)nop_fsync },               /* fsync */
1714*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_remove_desc, .opve_impl = (VOPFUNC)devfs_vnop_remove },      /* remove */
1715*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_link_desc, .opve_impl = (VOPFUNC)devfs_link },               /* link */
1716*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_rename_desc, .opve_impl = (VOPFUNC)devfs_rename },           /* rename */
1717*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_mkdir_desc, .opve_impl = (VOPFUNC)devfs_mkdir },             /* mkdir */
1718*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_rmdir_desc, .opve_impl = (VOPFUNC)devfs_rmdir },             /* rmdir */
1719*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_symlink_desc, .opve_impl = (VOPFUNC)devfs_symlink },         /* symlink */
1720*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_readdir_desc, .opve_impl = (VOPFUNC)devfs_readdir },         /* readdir */
1721*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_readlink_desc, .opve_impl = (VOPFUNC)devfs_readlink },       /* readlink */
1722*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_inactive_desc, .opve_impl = (VOPFUNC)devfs_inactive },       /* inactive */
1723*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_reclaim_desc, .opve_impl = (VOPFUNC)devfs_reclaim },         /* reclaim */
1724*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_strategy_desc, .opve_impl = (VOPFUNC)err_strategy },         /* strategy */
1725*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_pathconf_desc, .opve_impl = (VOPFUNC)devs_vnop_pathconf },   /* pathconf */
1726*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_advlock_desc, .opve_impl = (VOPFUNC)err_advlock },           /* advlock */
1727*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_bwrite_desc, .opve_impl = (VOPFUNC)err_bwrite },
1728*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_pagein_desc, .opve_impl = (VOPFUNC)err_pagein },             /* Pagein */
1729*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_pageout_desc, .opve_impl = (VOPFUNC)err_pageout },           /* Pageout */
1730*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_copyfile_desc, .opve_impl = (VOPFUNC)err_copyfile },         /* Copyfile */
1731*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_blktooff_desc, .opve_impl = (VOPFUNC)err_blktooff },         /* blktooff */
1732*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_offtoblk_desc, .opve_impl = (VOPFUNC)err_offtoblk },         /* offtoblk */
1733*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_blockmap_desc, .opve_impl = (VOPFUNC)err_blockmap },         /* blockmap */
1734*4d495c6eSApple OSS Distributions #if CONFIG_MACF
1735*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_setlabel_desc, .opve_impl = (VOPFUNC)devfs_setlabel },       /* setlabel */
1736*4d495c6eSApple OSS Distributions #endif
1737*4d495c6eSApple OSS Distributions 	{ .opve_op = (struct vnodeop_desc*)NULL, .opve_impl = (int (*)(void *))NULL }
1738*4d495c6eSApple OSS Distributions };
1739*4d495c6eSApple OSS Distributions const struct vnodeopv_desc devfs_vnodeop_opv_desc =
1740*4d495c6eSApple OSS Distributions { .opv_desc_vector_p = &devfs_vnodeop_p, .opv_desc_ops = devfs_vnodeop_entries };
1741*4d495c6eSApple OSS Distributions 
1742*4d495c6eSApple OSS Distributions /* The following ops are used by the device nodes */
1743*4d495c6eSApple OSS Distributions int(**devfs_spec_vnodeop_p)(void *);
1744*4d495c6eSApple OSS Distributions const static struct vnodeopv_entry_desc devfs_spec_vnodeop_entries[] = {
1745*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_default_desc, .opve_impl = (VOPFUNC)devfs_default_error },
1746*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_lookup_desc, .opve_impl = (VOPFUNC)spec_lookup },            /* lookup */
1747*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_create_desc, .opve_impl = (VOPFUNC)spec_create },            /* create */
1748*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_mknod_desc, .opve_impl = (VOPFUNC)spec_mknod },              /* mknod */
1749*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_open_desc, .opve_impl = (VOPFUNC)spec_open },                        /* open */
1750*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_close_desc, .opve_impl = (VOPFUNC)devfsspec_close },         /* close */
1751*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_getattr_desc, .opve_impl = (VOPFUNC)devfs_getattr },         /* getattr */
1752*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_setattr_desc, .opve_impl = (VOPFUNC)devfs_setattr },         /* setattr */
1753*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_read_desc, .opve_impl = (VOPFUNC)devfsspec_read },           /* read */
1754*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_write_desc, .opve_impl = (VOPFUNC)devfsspec_write },         /* write */
1755*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_ioctl_desc, .opve_impl = (VOPFUNC)spec_ioctl },              /* ioctl */
1756*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_select_desc, .opve_impl = (VOPFUNC)spec_select },            /* select */
1757*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_revoke_desc, .opve_impl = (VOPFUNC)spec_revoke },            /* revoke */
1758*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_mmap_desc, .opve_impl = (VOPFUNC)spec_mmap },                        /* mmap */
1759*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_fsync_desc, .opve_impl = (VOPFUNC)spec_fsync },              /* fsync */
1760*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_remove_desc, .opve_impl = (VOPFUNC)devfs_vnop_remove },      /* remove */
1761*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_link_desc, .opve_impl = (VOPFUNC)devfs_link },               /* link */
1762*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_rename_desc, .opve_impl = (VOPFUNC)spec_rename },            /* rename */
1763*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_mkdir_desc, .opve_impl = (VOPFUNC)spec_mkdir },              /* mkdir */
1764*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_rmdir_desc, .opve_impl = (VOPFUNC)spec_rmdir },              /* rmdir */
1765*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_symlink_desc, .opve_impl = (VOPFUNC)spec_symlink },          /* symlink */
1766*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_readdir_desc, .opve_impl = (VOPFUNC)spec_readdir },          /* readdir */
1767*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_readlink_desc, .opve_impl = (VOPFUNC)spec_readlink },                /* readlink */
1768*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_inactive_desc, .opve_impl = (VOPFUNC)devfs_inactive },       /* inactive */
1769*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_reclaim_desc, .opve_impl = (VOPFUNC)devfs_reclaim },         /* reclaim */
1770*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_strategy_desc, .opve_impl = (VOPFUNC)spec_strategy },                /* strategy */
1771*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_pathconf_desc, .opve_impl = (VOPFUNC)spec_pathconf },                /* pathconf */
1772*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_advlock_desc, .opve_impl = (VOPFUNC)spec_advlock },          /* advlock */
1773*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_bwrite_desc, .opve_impl = (VOPFUNC)vn_bwrite },
1774*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_pagein_desc, .opve_impl = (VOPFUNC)err_pagein },             /* Pagein */
1775*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_pageout_desc, .opve_impl = (VOPFUNC)err_pageout },           /* Pageout */
1776*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_copyfile_desc, .opve_impl = (VOPFUNC)err_copyfile },         /* Copyfile */
1777*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_blktooff_desc, .opve_impl = (VOPFUNC)spec_blktooff },        /* blktooff */
1778*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_blktooff_desc, .opve_impl = (VOPFUNC)spec_offtoblk  },       /* blkofftoblk */
1779*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_blockmap_desc, .opve_impl = (VOPFUNC)spec_blockmap },        /* blockmap */
1780*4d495c6eSApple OSS Distributions #if CONFIG_MACF
1781*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_setlabel_desc, .opve_impl = (VOPFUNC)devfs_setlabel },       /* setlabel */
1782*4d495c6eSApple OSS Distributions #endif
1783*4d495c6eSApple OSS Distributions 	{ .opve_op = (struct vnodeop_desc*)NULL, .opve_impl = (int (*)(void *))NULL }
1784*4d495c6eSApple OSS Distributions };
1785*4d495c6eSApple OSS Distributions const struct vnodeopv_desc devfs_spec_vnodeop_opv_desc =
1786*4d495c6eSApple OSS Distributions { .opv_desc_vector_p = &devfs_spec_vnodeop_p, .opv_desc_ops = devfs_spec_vnodeop_entries };
1787*4d495c6eSApple OSS Distributions 
1788*4d495c6eSApple OSS Distributions 
1789*4d495c6eSApple OSS Distributions #if FDESC
1790*4d495c6eSApple OSS Distributions int(**devfs_devfd_vnodeop_p)(void*);
1791*4d495c6eSApple OSS Distributions const static struct vnodeopv_entry_desc devfs_devfd_vnodeop_entries[] = {
1792*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_default_desc, .opve_impl = (VOPFUNC)devfs_default_error },
1793*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_lookup_desc, .opve_impl = (VOPFUNC)devfs_devfd_lookup},      /* lookup */
1794*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_open_desc, .opve_impl = (VOPFUNC)nop_open },                 /* open */
1795*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_close_desc, .opve_impl = (VOPFUNC)devfs_close },             /* close */
1796*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_getattr_desc, .opve_impl = (VOPFUNC)devfs_getattr },         /* getattr */
1797*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_setattr_desc, .opve_impl = (VOPFUNC)devfs_setattr },         /* setattr */
1798*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_revoke_desc, .opve_impl = (VOPFUNC)err_revoke },             /* revoke */
1799*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_fsync_desc, .opve_impl = (VOPFUNC)nop_fsync },               /* fsync */
1800*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_readdir_desc, .opve_impl = (VOPFUNC)devfs_devfd_readdir},            /* readdir */
1801*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_inactive_desc, .opve_impl = (VOPFUNC)devfs_inactive },       /* inactive */
1802*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_reclaim_desc, .opve_impl = (VOPFUNC)devfs_reclaim },         /* reclaim */
1803*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_pathconf_desc, .opve_impl = (VOPFUNC)devs_vnop_pathconf },   /* pathconf */
1804*4d495c6eSApple OSS Distributions #if CONFIG_MACF
1805*4d495c6eSApple OSS Distributions 	{ .opve_op = &vnop_setlabel_desc, .opve_impl = (VOPFUNC)devfs_setlabel },       /* setlabel */
1806*4d495c6eSApple OSS Distributions #endif
1807*4d495c6eSApple OSS Distributions 	{ .opve_op = (struct vnodeop_desc*)NULL, .opve_impl = (int (*)(void *))NULL }
1808*4d495c6eSApple OSS Distributions };
1809*4d495c6eSApple OSS Distributions const struct vnodeopv_desc devfs_devfd_vnodeop_opv_desc =
1810*4d495c6eSApple OSS Distributions { .opv_desc_vector_p = &devfs_devfd_vnodeop_p, .opv_desc_ops = devfs_devfd_vnodeop_entries};
1811*4d495c6eSApple OSS Distributions #endif /* FDESC */
1812