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