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