1/* 2 * Copyright (c) 2014 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 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. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include "open.h" 25 26#include <errno.h> 27#include <util.h> 28#include <DiskArbitration/DiskArbitration.h> 29#include <IOKit/storage/IOMedia.h> 30#include <IOKit/IOKitLibPrivate.h> 31 32static DASessionRef __GetSession( void ) 33{ 34 static dispatch_once_t once; 35 static DASessionRef session; 36 37 dispatch_once( &once, ^ 38 { 39 session = DASessionCreate( kCFAllocatorDefault ); 40 41 if ( session ) 42 { 43 DASessionSetDispatchQueue( session, dispatch_get_main_queue( ) ); 44 } 45 } ); 46 47 return session; 48} 49 50static void __UnmountCallback( DADiskRef disk __unused, DADissenterRef dissenter __unused, void * context ) 51{ 52 dispatch_semaphore_t semaphore = ( __bridge id ) context; 53 54 dispatch_semaphore_signal( semaphore ); 55} 56 57static void __Unmount( DADiskRef disk ) 58{ 59 dispatch_semaphore_t semaphore; 60 61 semaphore = dispatch_semaphore_create( 0 ); 62 63 if ( semaphore ) 64 { 65 DADiskUnmount( disk, kDADiskUnmountOptionDefault, __UnmountCallback, ( __bridge void * ) semaphore ); 66 67 dispatch_semaphore_wait( semaphore, DISPATCH_TIME_FOREVER ); 68 } 69} 70 71int _Open( io_service_t service, int oflag, uint64_t authorizationID ) 72{ 73 uint64_t _authorizationID = 0; 74 int fd = -1; 75 IOReturn status; 76 77 _IOServiceGetAuthorizationID( service, &_authorizationID ); 78 79 if ( _authorizationID ) 80 { 81 if ( _authorizationID == authorizationID ) 82 { 83 if ( IOObjectConformsTo( service, kIOMediaClass ) ) 84 { 85 DADiskRef disk; 86 87 disk = DADiskCreateFromIOMedia( kCFAllocatorDefault, __GetSession( ), service ); 88 89 if ( disk ) 90 { 91 CFDictionaryRef description; 92 93 description = DADiskCopyDescription( disk ); 94 95 if ( description ) 96 { 97 if ( CFDictionaryGetValue( description, kDADiskDescriptionDeviceInternalKey ) == kCFBooleanTrue ) 98 { 99 if ( CFDictionaryGetValue( description, kDADiskDescriptionMediaRemovableKey ) == kCFBooleanFalse ) 100 { 101 if ( CFDictionaryGetValue( description, kDADiskDescriptionVolumePathKey ) ) 102 { 103 __Unmount( disk ); 104 } 105 } 106 } 107 108 CFRelease( description ); 109 } 110 111 description = DADiskCopyDescription( disk ); 112 113 if ( description ) 114 { 115 if ( CFDictionaryGetValue( description, kDADiskDescriptionVolumePathKey ) == 0 ) 116 { 117 fd = opendev( ( void * ) DADiskGetBSDName( disk ), oflag, 0, 0 ); 118 119 if ( fd == -1 ) 120 { 121 status = unix_err( errno ); 122 } 123 else 124 { 125 status = kIOReturnSuccess; 126 } 127 } 128 else 129 { 130 status = unix_err( EBUSY ); 131 } 132 133 CFRelease( description ); 134 } 135 else 136 { 137 status = unix_err( EBUSY ); 138 } 139 140 CFRelease( disk ); 141 } 142 else 143 { 144 status = unix_err( ENOTSUP ); 145 } 146 } 147 else 148 { 149 status = unix_err( ENOTSUP ); 150 } 151 } 152 else 153 { 154 status = unix_err( EPERM ); 155 } 156 } 157 else 158 { 159 status = unix_err( EPERM ); 160 } 161 162 if ( status ) 163 { 164 if ( unix_err( err_get_code( status ) ) == status ) 165 { 166 errno = err_get_code( status ); 167 } 168 } 169 170 return fd; 171} 172