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