2  * Copyright (c) 2000-2010 Apple Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  29  * Copyright 1997,1998 Julian Elischer.  All rights reserved. 
  32  * Redistribution and use in source and binary forms, with or without 
  33  * modification, are permitted provided that the following conditions are 
  35  *  1. Redistributions of source code must retain the above copyright 
  36  *     notice, this list of conditions and the following disclaimer. 
  37  *  2. Redistributions in binary form must reproduce the above copyright notice, 
  38  *     this list of conditions and the following disclaimer in the documentation 
  39  *     and/or other materials provided with the distribution. 
  41  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS 
  42  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  43  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
  44  * DISCLAIMED.  IN NO EVENT SHALL THE HOLDER OR CONTRIBUTORS BE LIABLE FOR 
  45  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
  46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
  47  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
  48  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
  50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
  57  * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce 
  58  * support for mandatory and extensible security protections.  This notice 
  59  * is included in support of clause 2.2 (b) of the Apple Public License, 
  64  *  Dieter Siegmund (dieter@apple.com) Wed Jul 14 13:37:59 PDT 1999 
  65  *  - modified devfs_statfs() to use devfs_stats to calculate the 
  66  *    amount of memory used by devfs 
  70 #include <sys/param.h> 
  71 #include <sys/systm.h> 
  72 #include <sys/kernel.h> 
  73 #include <sys/vnode_internal.h> 
  75 #include <sys/kauth.h> 
  76 #include <sys/mount_internal.h> 
  77 #include <sys/malloc.h> 
  79 #include <libkern/OSAtomic.h> 
  82 #include <security/mac_framework.h> 
  86 #include "devfsdefs.h" 
  93 static int devfs_statfs( struct mount 
*mp
, struct vfsstatfs 
*sbp
, vfs_context_t ctx
); 
  94 static int devfs_vfs_getattr(mount_t mp
, struct vfs_attr 
*fsap
, vfs_context_t ctx
); 
  97 extern boolean_t dev_kmem_enabled
; 
 101  * Called from the generic VFS startups. 
 102  * This is the second stage of DEVFS initialisation. 
 103  * The probed devices have already been loaded and the  
 104  * basic structure of the DEVFS created. 
 105  * We take the oportunity to mount the hidden DEVFS layer, so that 
 106  * devices from devfs get sync'd. 
 109 devfs_init(__unused 
struct vfsconf 
*vfsp
) 
 113         devfs_make_node(makedev(0, 0), DEVFS_CHAR
,  
 114                                         UID_ROOT
, GID_WHEEL
, 0622, "console"); 
 115         devfs_make_node(makedev(2, 0), DEVFS_CHAR
,  
 116                                         UID_ROOT
, GID_WHEEL
, 0666, "tty"); 
 118         if (dev_kmem_enabled
) { 
 119                 /* (3,0) reserved for /dev/mem physical memory */ 
 120                 devfs_make_node(makedev(3, 1), DEVFS_CHAR
,  
 121                                                 UID_ROOT
, GID_KMEM
, 0640, "kmem"); 
 124         devfs_make_node(makedev(3, 2), DEVFS_CHAR
,  
 125                                         UID_ROOT
, GID_WHEEL
, 0666, "null"); 
 126         devfs_make_node(makedev(3, 3), DEVFS_CHAR
,  
 127                                         UID_ROOT
, GID_WHEEL
, 0666, "zero"); 
 128         devfs_make_node(makedev(6, 0), DEVFS_CHAR
,  
 129                                         UID_ROOT
, GID_WHEEL
, 0600, "klog"); 
 139  *  mp   - pointer to 'mount' structure 
 140  *  path - addr in user space of mount point (ie /usr or whatever) 
 141  *  data - addr in user space of mount params including the 
 142  *         name of the block special file to treat as a filesystem. 
 144  *  ndp  - namei data pointer (NOT USED) 
 146  * devfs is special in that it doesn't require any device to be mounted.. 
 147  * It makes up its data as it goes along. 
 148  * it must be mounted during single user.. until it is, only std{in/out/err} 
 149  * and the root filesystem are available. 
 153 devfs_mount(struct mount 
*mp
, __unused vnode_t devvp
, __unused user_addr_t data
, vfs_context_t ctx
) 
 155         struct devfsmount 
*devfs_mp_p
;  /* devfs specific mount info */ 
 159          *  If they just want to update, we don't need to do anything. 
 161         if (mp
->mnt_flag 
& MNT_UPDATE
) 
 166         /* Advisory locking should be handled at the VFS layer */ 
 167         vfs_setlocklocal(mp
); 
 170          *  Well, it's not an update, it's a real mount request. 
 172          * HERE we should check to see if we are already mounted here. 
 175         MALLOC(devfs_mp_p
, struct devfsmount 
*, sizeof(struct devfsmount
), 
 176                M_DEVFSMNT
, M_WAITOK
); 
 177         if (devfs_mp_p 
== NULL
) 
 179         bzero(devfs_mp_p
,sizeof(*devfs_mp_p
)); 
 180         devfs_mp_p
->mount 
= mp
; 
 183          *  Fill out some fields 
 185         mp
->mnt_data 
= (qaddr_t
)devfs_mp_p
; 
 186         mp
->mnt_vfsstat
.f_fsid
.val
[0] = (int32_t)(uintptr_t)devfs_mp_p
; 
 187         mp
->mnt_vfsstat
.f_fsid
.val
[1] = vfs_typenum(mp
); 
 188         mp
->mnt_flag 
|= MNT_LOCAL
; 
 191         error 
= dev_dup_plane(devfs_mp_p
); 
 195                 mp
->mnt_data 
= (qaddr_t
)0; 
 196                 FREE((caddr_t
)devfs_mp_p
, M_DEVFSMNT
); 
 202          *  Copy in the name of the directory the filesystem 
 203          *  is to be mounted on. 
 204          *  And we clear the remainder of the character strings 
 208         bzero(mp
->mnt_vfsstat
.f_mntfromname
, MAXPATHLEN
); 
 209         bcopy("devfs",mp
->mnt_vfsstat
.f_mntfromname
, 5); 
 210         (void)devfs_statfs(mp
, &mp
->mnt_vfsstat
, ctx
); 
 217 devfs_start(__unused 
struct mount 
*mp
, __unused 
int flags
, __unused vfs_context_t ctx
) 
 223  *  Unmount the filesystem described by mp. 
 226 devfs_unmount( struct mount 
*mp
, int mntflags
, __unused vfs_context_t ctx
) 
 228         struct devfsmount 
*devfs_mp_p 
= (struct devfsmount 
*)mp
->mnt_data
; 
 233         if (mntflags 
& MNT_FORCE
) { 
 237         error 
= vflush(mp
, NULLVP
, flags
); 
 242         devfs_free_plane(devfs_mp_p
); 
 247         FREE((caddr_t
)devfs_mp_p
, M_DEVFSMNT
); 
 248         mp
->mnt_data 
= (qaddr_t
)0; 
 249         mp
->mnt_flag 
&= ~MNT_LOCAL
; 
 254 /* return the address of the root vnode  in *vpp */ 
 256 devfs_root(struct mount 
*mp
, struct vnode 
**vpp
, __unused vfs_context_t ctx
) 
 258         struct devfsmount 
*devfs_mp_p 
= (struct devfsmount 
*)(mp
->mnt_data
); 
 262         /* last parameter to devfs_dntovn() is ignored */ 
 263         error 
= devfs_dntovn(devfs_mp_p
->plane_root
->de_dnp
, vpp
, NULL
); 
 270 devfs_statfs( struct mount 
*mp
, struct vfsstatfs 
*sbp
, __unused vfs_context_t ctx
) 
 272         struct devfsmount 
*devfs_mp_p 
= (struct devfsmount 
*)mp
->mnt_data
; 
 275          *  Fill in the stat block. 
 277         //sbp->f_type   = mp->mnt_vfsstat.f_type; 
 278         sbp
->f_flags  
= 0;              /* XXX */ 
 281         sbp
->f_blocks 
= (devfs_stats
.mounts 
* sizeof(struct devfsmount
) 
 282                          + devfs_stats
.nodes 
* sizeof(devnode_t
) 
 283                          + devfs_stats
.entries 
* sizeof(devdirent_t
) 
 284                          + devfs_stats
.stringspace
 
 288         sbp
->f_files  
= devfs_stats
.nodes
; 
 290         sbp
->f_fsid
.val
[0] = (int32_t)(uintptr_t)devfs_mp_p
; 
 291         sbp
->f_fsid
.val
[1] = vfs_typenum(mp
); 
 297 devfs_vfs_getattr(__unused mount_t mp
, struct vfs_attr 
*fsap
, __unused vfs_context_t ctx
) 
 299         VFSATTR_RETURN(fsap
, f_objcount
, devfs_stats
.nodes
); 
 300         VFSATTR_RETURN(fsap
, f_maxobjcount
, devfs_stats
.nodes
); 
 301         VFSATTR_RETURN(fsap
, f_bsize
, 512); 
 302         VFSATTR_RETURN(fsap
, f_iosize
, 512); 
 303         if (VFSATTR_IS_ACTIVE(fsap
, f_blocks
) || VFSATTR_IS_ACTIVE(fsap
, f_bused
)) { 
 304                 fsap
->f_blocks 
= (devfs_stats
.mounts 
* sizeof(struct devfsmount
) 
 305                          + devfs_stats
.nodes 
* sizeof(devnode_t
) 
 306                          + devfs_stats
.entries 
* sizeof(devdirent_t
) 
 307                          + devfs_stats
.stringspace
 
 309                 fsap
->f_bused 
= fsap
->f_blocks
; 
 310                 VFSATTR_SET_SUPPORTED(fsap
, f_blocks
); 
 311                 VFSATTR_SET_SUPPORTED(fsap
, f_bused
); 
 313         VFSATTR_RETURN(fsap
, f_bfree
, 0); 
 314         VFSATTR_RETURN(fsap
, f_bavail
, 0); 
 315         VFSATTR_RETURN(fsap
, f_files
, devfs_stats
.nodes
); 
 316         VFSATTR_RETURN(fsap
, f_ffree
, 0); 
 317         VFSATTR_RETURN(fsap
, f_fssubtype
, 0); 
 319         if (VFSATTR_IS_ACTIVE(fsap
, f_capabilities
)) { 
 320                 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_FORMAT
] = 
 321                         VOL_CAP_FMT_SYMBOLICLINKS 
| 
 322                         VOL_CAP_FMT_HARDLINKS 
| 
 323                         VOL_CAP_FMT_NO_ROOT_TIMES 
| 
 324                         VOL_CAP_FMT_CASE_SENSITIVE 
| 
 325                         VOL_CAP_FMT_CASE_PRESERVING 
| 
 326                         VOL_CAP_FMT_FAST_STATFS 
| 
 327                         VOL_CAP_FMT_2TB_FILESIZE 
| 
 328                         VOL_CAP_FMT_HIDDEN_FILES
; 
 329                 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_INTERFACES
] = 
 330                         VOL_CAP_INT_ATTRLIST 
; 
 331                 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_RESERVED1
] = 0; 
 332                 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_RESERVED2
] = 0; 
 334                 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_FORMAT
] = 
 335                         VOL_CAP_FMT_PERSISTENTOBJECTIDS 
| 
 336                         VOL_CAP_FMT_SYMBOLICLINKS 
| 
 337                         VOL_CAP_FMT_HARDLINKS 
| 
 338                         VOL_CAP_FMT_JOURNAL 
| 
 339                         VOL_CAP_FMT_JOURNAL_ACTIVE 
| 
 340                         VOL_CAP_FMT_NO_ROOT_TIMES 
| 
 341                         VOL_CAP_FMT_SPARSE_FILES 
| 
 342                         VOL_CAP_FMT_ZERO_RUNS 
| 
 343                         VOL_CAP_FMT_CASE_SENSITIVE 
| 
 344                         VOL_CAP_FMT_CASE_PRESERVING 
| 
 345                         VOL_CAP_FMT_FAST_STATFS 
| 
 346                         VOL_CAP_FMT_2TB_FILESIZE 
| 
 347                         VOL_CAP_FMT_OPENDENYMODES 
| 
 348                         VOL_CAP_FMT_HIDDEN_FILES 
| 
 349                         VOL_CAP_FMT_PATH_FROM_ID 
| 
 350                         VOL_CAP_FMT_NO_VOLUME_SIZES
; 
 351                 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_INTERFACES
] = 
 352                         VOL_CAP_INT_SEARCHFS 
| 
 353                         VOL_CAP_INT_ATTRLIST 
| 
 354                         VOL_CAP_INT_NFSEXPORT 
| 
 355                         VOL_CAP_INT_READDIRATTR 
| 
 356                         VOL_CAP_INT_EXCHANGEDATA 
| 
 357                         VOL_CAP_INT_COPYFILE 
| 
 358                         VOL_CAP_INT_ALLOCATE 
| 
 359                         VOL_CAP_INT_VOL_RENAME 
| 
 360                         VOL_CAP_INT_ADVLOCK 
| 
 362                         VOL_CAP_INT_EXTENDED_SECURITY 
| 
 363                         VOL_CAP_INT_USERACCESS 
| 
 364                         VOL_CAP_INT_MANLOCK 
| 
 365                         VOL_CAP_INT_EXTENDED_ATTR 
| 
 366                         VOL_CAP_INT_NAMEDSTREAMS
; 
 367                 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_RESERVED1
] = 0; 
 368                 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_RESERVED2
] = 0; 
 370                 VFSATTR_SET_SUPPORTED(fsap
, f_capabilities
); 
 373         if (VFSATTR_IS_ACTIVE(fsap
, f_attributes
)) { 
 374                 fsap
->f_attributes
.validattr
.commonattr 
= 
 375                         ATTR_CMN_NAME 
| ATTR_CMN_DEVID 
| ATTR_CMN_FSID 
| 
 376                         ATTR_CMN_OBJTYPE 
| ATTR_CMN_OBJTAG 
| ATTR_CMN_OBJID 
| 
 378                         ATTR_CMN_MODTIME 
| ATTR_CMN_CHGTIME 
| ATTR_CMN_ACCTIME 
| 
 379                         ATTR_CMN_OWNERID 
| ATTR_CMN_GRPID 
| ATTR_CMN_ACCESSMASK 
| 
 380                         ATTR_CMN_FLAGS 
| ATTR_CMN_USERACCESS 
| ATTR_CMN_FILEID
; 
 381                 fsap
->f_attributes
.validattr
.volattr 
= 
 382                         ATTR_VOL_FSTYPE 
| ATTR_VOL_SIZE 
| ATTR_VOL_SPACEFREE 
| 
 383                         ATTR_VOL_SPACEAVAIL 
| ATTR_VOL_MINALLOCATION 
| 
 384                         ATTR_VOL_OBJCOUNT 
| ATTR_VOL_MAXOBJCOUNT 
| 
 385                         ATTR_VOL_MOUNTPOINT 
| ATTR_VOL_MOUNTFLAGS 
| 
 386                         ATTR_VOL_MOUNTEDDEVICE 
| ATTR_VOL_CAPABILITIES 
| 
 388                 fsap
->f_attributes
.validattr
.dirattr 
= 
 389                         ATTR_DIR_LINKCOUNT 
| ATTR_DIR_MOUNTSTATUS
; 
 390                 fsap
->f_attributes
.validattr
.fileattr 
= 
 391                         ATTR_FILE_LINKCOUNT 
| ATTR_FILE_TOTALSIZE 
| 
 392                         ATTR_FILE_IOBLOCKSIZE 
| ATTR_FILE_DEVTYPE 
| 
 393                         ATTR_FILE_DATALENGTH
; 
 394                 fsap
->f_attributes
.validattr
.forkattr 
= 0; 
 396                 fsap
->f_attributes
.nativeattr
.commonattr 
= 
 397                         ATTR_CMN_NAME 
| ATTR_CMN_DEVID 
| ATTR_CMN_FSID 
| 
 398                         ATTR_CMN_OBJTYPE 
| ATTR_CMN_OBJTAG 
| ATTR_CMN_OBJID 
| 
 400                         ATTR_CMN_MODTIME 
| ATTR_CMN_CHGTIME 
| ATTR_CMN_ACCTIME 
| 
 401                         ATTR_CMN_OWNERID 
| ATTR_CMN_GRPID 
| ATTR_CMN_ACCESSMASK 
| 
 402                         ATTR_CMN_FLAGS 
| ATTR_CMN_USERACCESS 
| ATTR_CMN_FILEID
; 
 403                 fsap
->f_attributes
.nativeattr
.volattr 
= 
 404                         ATTR_VOL_FSTYPE 
| ATTR_VOL_SIZE 
| ATTR_VOL_SPACEFREE 
| 
 405                         ATTR_VOL_SPACEAVAIL 
| ATTR_VOL_MINALLOCATION 
| 
 406                         ATTR_VOL_OBJCOUNT 
| ATTR_VOL_MAXOBJCOUNT 
| 
 407                         ATTR_VOL_MOUNTPOINT 
| ATTR_VOL_MOUNTFLAGS 
| 
 408                         ATTR_VOL_MOUNTEDDEVICE 
| ATTR_VOL_CAPABILITIES 
| 
 410                 fsap
->f_attributes
.nativeattr
.dirattr 
= 
 411                         ATTR_DIR_MOUNTSTATUS
; 
 412                 fsap
->f_attributes
.nativeattr
.fileattr 
= 
 413                         ATTR_FILE_LINKCOUNT 
| ATTR_FILE_TOTALSIZE 
| 
 414                         ATTR_FILE_IOBLOCKSIZE 
| ATTR_FILE_DEVTYPE 
| 
 415                         ATTR_FILE_DATALENGTH
; 
 416                 fsap
->f_attributes
.nativeattr
.forkattr 
= 0; 
 418                 VFSATTR_SET_SUPPORTED(fsap
, f_attributes
); 
 425 devfs_sync(__unused 
struct mount 
*mp
, __unused 
int waitfor
, __unused vfs_context_t ctx
) 
 432 devfs_vget(__unused 
struct mount 
*mp
, __unused ino64_t ino
, __unused 
struct vnode 
**vpp
, __unused vfs_context_t ctx
) 
 437 /************************************************************* 
 438  * The concept of exporting a kernel generated devfs is stupid 
 439  * So don't handle filehandles 
 443 devfs_fhtovp (__unused 
struct mount 
*mp
, __unused 
int fhlen
, __unused 
unsigned char *fhp
, __unused 
struct vnode 
**vpp
, __unused vfs_context_t ctx
) 
 450 devfs_vptofh (__unused 
struct vnode 
*vp
, __unused 
int *fhlenp
, __unused 
unsigned char *fhp
, __unused vfs_context_t ctx
) 
 456 devfs_sysctl(__unused 
int *name
, __unused u_int namelen
, __unused user_addr_t oldp
,  
 457              __unused 
size_t *oldlenp
, __unused user_addr_t newp
,  
 458              __unused 
size_t newlen
, __unused vfs_context_t ctx
) 
 463 #include <sys/namei.h> 
 466  * Function: devfs_kernel_mount 
 468  *   Mount devfs at the given mount point from within the kernel. 
 471 devfs_kernel_mount(char * mntname
) 
 474         vfs_context_t ctx 
= vfs_context_kernel(); 
 475         char fsname
[] = "devfs"; 
 477         error 
= kernel_mount(fsname
, NULLVP
, NULLVP
, mntname
, NULL
, 0, MNT_DONTBROWSE
, KERNEL_MOUNT_NOAUTH
, ctx
); 
 479                 printf("devfs_kernel_mount: kernel_mount failed: %d\n", error
); 
 486 struct vfsops devfs_vfsops 
= {