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