1/* 2 * Copyright (c) 1998-2013 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 "DAInternal.h" 25 26#include <paths.h> 27#include <DiskArbitration/DiskArbitration.h> 28 29__private_extern__ const char * _kDAAuthorizeRightAdopt = "adopt"; 30__private_extern__ const char * _kDAAuthorizeRightEncode = "encode"; 31__private_extern__ const char * _kDAAuthorizeRightMount = "mount"; 32__private_extern__ const char * _kDAAuthorizeRightRename = "rename"; 33__private_extern__ const char * _kDAAuthorizeRightUnmount = "unmount"; 34 35__private_extern__ const CFStringRef _kDACallbackAddressKey = CFSTR( "DACallbackAddress" ); 36__private_extern__ const CFStringRef _kDACallbackArgument0Key = CFSTR( "DACallbackArgument0" ); 37__private_extern__ const CFStringRef _kDACallbackArgument1Key = CFSTR( "DACallbackArgument1" ); 38__private_extern__ const CFStringRef _kDACallbackContextKey = CFSTR( "DACallbackContext" ); 39__private_extern__ const CFStringRef _kDACallbackDiskKey = CFSTR( "DACallbackDisk" ); 40__private_extern__ const CFStringRef _kDACallbackKindKey = CFSTR( "DACallbackKind" ); 41__private_extern__ const CFStringRef _kDACallbackMatchKey = CFSTR( "DACallbackMatch" ); 42__private_extern__ const CFStringRef _kDACallbackOrderKey = CFSTR( "DACallbackOrder" ); 43__private_extern__ const CFStringRef _kDACallbackSessionKey = CFSTR( "DACallbackSession" ); 44__private_extern__ const CFStringRef _kDACallbackTimeKey = CFSTR( "DACallbackTime" ); 45__private_extern__ const CFStringRef _kDACallbackWatchKey = CFSTR( "DACallbackWatch" ); 46 47__private_extern__ const CFStringRef _kDADiskIDKey = CFSTR( "DADiskID" ); 48 49__private_extern__ const CFStringRef _kDADissenterProcessIDKey = CFSTR( "DAProcessID" ); 50__private_extern__ const CFStringRef _kDADissenterStatusKey = CFSTR( "DAStatus" ); 51__private_extern__ const CFStringRef _kDADissenterStatusStringKey = CFSTR( "DAStatusString" ); 52 53__private_extern__ const CFStringRef _kDARequestArgument1Key = CFSTR( "DARequestArgument1" ); 54__private_extern__ const CFStringRef _kDARequestArgument2Key = CFSTR( "DARequestArgument2" ); 55__private_extern__ const CFStringRef _kDARequestArgument3Key = CFSTR( "DARequestArgument3" ); 56__private_extern__ const CFStringRef _kDARequestCallbackKey = CFSTR( "DARequestCallback" ); 57__private_extern__ const CFStringRef _kDARequestDiskKey = CFSTR( "DARequestDisk" ); 58__private_extern__ const CFStringRef _kDARequestDissenterKey = CFSTR( "DARequestDissenter" ); 59__private_extern__ const CFStringRef _kDARequestKindKey = CFSTR( "DARequestKind" ); 60__private_extern__ const CFStringRef _kDARequestLinkKey = CFSTR( "DARequestLink" ); 61__private_extern__ const CFStringRef _kDARequestStateKey = CFSTR( "DARequestState" ); 62__private_extern__ const CFStringRef _kDARequestUserGIDKey = CFSTR( "DARequestUserGID" ); 63__private_extern__ const CFStringRef _kDARequestUserUIDKey = CFSTR( "DARequestUserUID" ); 64 65const CFStringRef kDADiskDescriptionVolumeKindKey = CFSTR( "DAVolumeKind" ); 66const CFStringRef kDADiskDescriptionVolumeMountableKey = CFSTR( "DAVolumeMountable" ); 67const CFStringRef kDADiskDescriptionVolumeNameKey = CFSTR( "DAVolumeName" ); 68const CFStringRef kDADiskDescriptionVolumeNetworkKey = CFSTR( "DAVolumeNetwork" ); 69const CFStringRef kDADiskDescriptionVolumePathKey = CFSTR( "DAVolumePath" ); 70const CFStringRef kDADiskDescriptionVolumeUUIDKey = CFSTR( "DAVolumeUUID" ); 71 72const CFStringRef kDADiskDescriptionMediaBlockSizeKey = CFSTR( "DAMediaBlockSize" ); 73const CFStringRef kDADiskDescriptionMediaBSDMajorKey = CFSTR( "DAMediaBSDMajor" ); 74const CFStringRef kDADiskDescriptionMediaBSDMinorKey = CFSTR( "DAMediaBSDMinor" ); 75const CFStringRef kDADiskDescriptionMediaBSDNameKey = CFSTR( "DAMediaBSDName" ); 76const CFStringRef kDADiskDescriptionMediaBSDUnitKey = CFSTR( "DAMediaBSDUnit" ); 77const CFStringRef kDADiskDescriptionMediaContentKey = CFSTR( "DAMediaContent" ); 78const CFStringRef kDADiskDescriptionMediaEjectableKey = CFSTR( "DAMediaEjectable" ); 79const CFStringRef kDADiskDescriptionMediaIconKey = CFSTR( "DAMediaIcon" ); 80const CFStringRef kDADiskDescriptionMediaKindKey = CFSTR( "DAMediaKind" ); 81const CFStringRef kDADiskDescriptionMediaLeafKey = CFSTR( "DAMediaLeaf" ); 82const CFStringRef kDADiskDescriptionMediaNameKey = CFSTR( "DAMediaName" ); 83const CFStringRef kDADiskDescriptionMediaPathKey = CFSTR( "DAMediaPath" ); 84const CFStringRef kDADiskDescriptionMediaRemovableKey = CFSTR( "DAMediaRemovable" ); 85const CFStringRef kDADiskDescriptionMediaSizeKey = CFSTR( "DAMediaSize" ); 86const CFStringRef kDADiskDescriptionMediaTypeKey = CFSTR( "DAMediaType" ); 87const CFStringRef kDADiskDescriptionMediaUUIDKey = CFSTR( "DAMediaUUID" ); 88const CFStringRef kDADiskDescriptionMediaWholeKey = CFSTR( "DAMediaWhole" ); 89const CFStringRef kDADiskDescriptionMediaWritableKey = CFSTR( "DAMediaWritable" ); 90 91const CFStringRef kDADiskDescriptionDeviceGUIDKey = CFSTR( "DADeviceGUID" ); 92const CFStringRef kDADiskDescriptionDeviceInternalKey = CFSTR( "DADeviceInternal" ); 93const CFStringRef kDADiskDescriptionDeviceModelKey = CFSTR( "DADeviceModel" ); 94const CFStringRef kDADiskDescriptionDevicePathKey = CFSTR( "DADevicePath" ); 95const CFStringRef kDADiskDescriptionDeviceProtocolKey = CFSTR( "DADeviceProtocol" ); 96const CFStringRef kDADiskDescriptionDeviceRevisionKey = CFSTR( "DADeviceRevision" ); 97const CFStringRef kDADiskDescriptionDeviceUnitKey = CFSTR( "DADeviceUnit" ); 98const CFStringRef kDADiskDescriptionDeviceVendorKey = CFSTR( "DADeviceVendor" ); 99 100const CFStringRef kDADiskDescriptionBusNameKey = CFSTR( "DABusName" ); 101const CFStringRef kDADiskDescriptionBusPathKey = CFSTR( "DABusPath" ); 102 103const CFStringRef kDADiskDescriptionAppearanceTimeKey = CFSTR( "DAAppearanceTime" ); 104 105const CFStringRef kDADiskDescriptionMediaMatchKey = CFSTR( "DAMediaMatch" ); 106 107static const char * __kDAKindNameList[] = 108{ 109 "disk appeared", 110 "disk claim", 111 "disk claim release", 112 "disk description changed", 113 "disk disappeared", 114 "disk eject", 115 "disk eject approval", 116 "disk mount", 117 "disk mount approval", 118 "disk peek", 119 "disk probe", 120 "disk refresh", 121 "disk rename", 122 "disk unmount", 123 "disk unmount approval", 124 "idle" 125}; 126 127extern CFIndex __CFBinaryPlistWriteToStream( CFPropertyListRef plist, CFTypeRef stream ); 128 129__private_extern__ int ___statfs( const char * path, struct statfs * buf, int flags ) 130{ 131 struct statfs * mountList; 132 int mountListCount; 133 int mountListIndex; 134 int status; 135 136 status = -1; 137 138 mountListCount = getfsstat( NULL, 0, MNT_NOWAIT ); 139 140 if ( mountListCount > 0 ) 141 { 142 mountList = malloc( mountListCount * sizeof( struct statfs ) ); 143 144 if ( mountList ) 145 { 146 mountListCount = getfsstat( mountList, mountListCount * sizeof( struct statfs ), flags ); 147 148 if ( mountListCount > 0 ) 149 { 150 for ( mountListIndex = 0; mountListIndex < mountListCount; mountListIndex++ ) 151 { 152 if ( strcmp( mountList[mountListIndex].f_mntonname, path ) == 0 ) 153 { 154 status = 0; 155 156 *buf = mountList[mountListIndex]; 157 158 if ( mountList[mountListIndex].f_owner == geteuid( ) ) 159 { 160 break; 161 } 162 } 163 } 164 } 165 166 free( mountList ); 167 } 168 } 169 170 return status; 171} 172 173__private_extern__ Boolean ___CFArrayContainsValue( CFArrayRef array, const void * value ) 174{ 175 return CFArrayContainsValue( array, CFRangeMake( 0, CFArrayGetCount( array ) ), value ); 176} 177 178__private_extern__ void ___CFArrayRemoveValue( CFMutableArrayRef array, const void * value ) 179{ 180 CFIndex index; 181 182 index = CFArrayGetFirstIndexOfValue( array, CFRangeMake( 0, CFArrayGetCount( array ) ), value ); 183 184 if ( index != kCFNotFound ) 185 { 186 CFArrayRemoveValueAtIndex( array, index ); 187 } 188} 189 190__private_extern__ vm_address_t ___CFDataCopyBytes( CFDataRef data, mach_msg_type_number_t * length ) 191{ 192 vm_address_t bytes = 0; 193 194 *length = CFDataGetLength( data ); 195 196 vm_allocate( mach_task_self( ), &bytes, *length, TRUE ); 197 198 if ( bytes ) 199 { 200 bcopy( CFDataGetBytePtr( data ), ( void * ) bytes, *length ); 201 } 202 203 return bytes; 204} 205 206__private_extern__ SInt64 ___CFDictionaryGetIntegerValue( CFDictionaryRef dictionary, const void * key ) 207{ 208 CFNumberRef number; 209 SInt64 value = 0; 210 211 number = CFDictionaryGetValue( dictionary, key ); 212 213 if ( number ) 214 { 215 CFNumberGetValue( number, kCFNumberSInt64Type, &value ); 216 } 217 218 return value; 219} 220 221__private_extern__ void ___CFDictionarySetIntegerValue( CFMutableDictionaryRef dictionary, const void * key, SInt64 value ) 222{ 223 CFNumberRef number; 224 225 number = CFNumberCreate( CFGetAllocator( dictionary ), kCFNumberSInt64Type, &value ); 226 227 if ( number ) 228 { 229 CFDictionarySetValue( dictionary, key, number ); 230 231 CFRelease( number ); 232 } 233} 234 235__private_extern__ CFNumberRef ___CFNumberCreateWithIntegerValue( CFAllocatorRef allocator, SInt64 value ) 236{ 237 CFNumberRef number; 238 239 number = CFNumberCreate( allocator, kCFNumberSInt64Type, &value ); 240 241 return number; 242} 243 244__private_extern__ SInt64 ___CFNumberGetIntegerValue( CFNumberRef number ) 245{ 246 SInt64 value = 0; 247 248 CFNumberGetValue( number, kCFNumberSInt64Type, &value ); 249 250 return value; 251} 252 253__private_extern__ char * ___CFStringCopyCString( CFStringRef string ) 254{ 255 /* 256 * Creates a C string buffer from a CFString object. The string encoding is presumed to be 257 * UTF-8. The result is a reference to a C string buffer or NULL if there was a problem in 258 * creating the buffer. The caller is responsible for releasing the buffer with free(). 259 */ 260 261 char * buffer = NULL; 262 263 if ( string ) 264 { 265 CFIndex length; 266 CFRange range; 267 268 range = CFRangeMake( 0, CFStringGetLength( string ) ); 269 270 if ( CFStringGetBytes( string, range, kCFStringEncodingUTF8, 0, FALSE, NULL, 0, &length ) ) 271 { 272 buffer = malloc( length + 1 ); 273 274 if ( buffer ) 275 { 276 CFStringGetBytes( string, range, kCFStringEncodingUTF8, 0, FALSE, ( void * ) buffer, length, NULL ); 277 278 buffer[length] = 0; 279 } 280 } 281 } 282 283 return buffer; 284} 285 286__private_extern__ char * ___CFURLCopyFileSystemRepresentation( CFURLRef url ) 287{ 288 /* 289 * Creates a buffer with the file system's native string representation of URL's path. 290 * The result is a reference to a C buffer or NULL if there was a problem in creating 291 * the buffer. The caller is responsible for releasing the buffer with free(). 292 */ 293 294 char * path = NULL; 295 296 if ( url ) 297 { 298 CFStringRef string; 299 300 string = CFURLCopyFileSystemPath( url, kCFURLPOSIXPathStyle ); 301 302 if ( string ) 303 { 304 path = ___CFStringCopyCString( string ); 305 306 CFRelease( string ); 307 } 308 } 309 310 return path; 311} 312 313__private_extern__ const char * _DACallbackKindGetName( _DACallbackKind kind ) 314{ 315 return __kDAKindNameList[kind]; 316} 317 318__private_extern__ const char * _DARequestKindGetName( _DARequestKind kind ) 319{ 320 return __kDAKindNameList[kind]; 321} 322 323__private_extern__ CFDataRef _DASerialize( CFAllocatorRef allocator, CFTypeRef object ) 324{ 325 CFDataRef data; 326 327 data = CFDataCreateMutable( allocator, 0 ); 328 329 if ( data ) 330 { 331 if ( __CFBinaryPlistWriteToStream( object, data ) == 0 ) 332 { 333 CFRelease( data ); 334 335 data = NULL; 336 } 337 } 338 339 return data; 340} 341 342__private_extern__ CFDataRef _DASerializeDiskDescription( CFAllocatorRef allocator, CFDictionaryRef description ) 343{ 344 CFDataRef data = NULL; 345 346 if ( description ) 347 { 348 CFMutableDictionaryRef copy; 349 350 copy = CFDictionaryCreateMutableCopy( allocator, 0, description ); 351 352 if ( copy ) 353 { 354 CFTypeRef object; 355 356 object = CFDictionaryGetValue( description, kDADiskDescriptionMediaUUIDKey ); 357 358 if ( object ) 359 { 360 object = CFUUIDCreateString( allocator, object ); 361 362 if ( object ) 363 { 364 CFDictionarySetValue( copy, kDADiskDescriptionMediaUUIDKey, object ); 365 366 CFRelease( object ); 367 } 368 } 369 370 object = CFDictionaryGetValue( description, kDADiskDescriptionVolumePathKey ); 371 372 if ( object ) 373 { 374 object = CFURLCopyFileSystemPath( object, kCFURLPOSIXPathStyle ); 375 376 if ( object ) 377 { 378 CFDictionarySetValue( copy, kDADiskDescriptionVolumePathKey, object ); 379 380 CFRelease( object ); 381 } 382 } 383 384 object = CFDictionaryGetValue( description, kDADiskDescriptionVolumeUUIDKey ); 385 386 if ( object ) 387 { 388 object = CFUUIDCreateString( allocator, object ); 389 390 if ( object ) 391 { 392 CFDictionarySetValue( copy, kDADiskDescriptionVolumeUUIDKey, object ); 393 394 CFRelease( object ); 395 } 396 } 397 398 data = _DASerialize( allocator, copy ); 399 400 CFRelease( copy ); 401 } 402 } 403 404 return data; 405} 406 407__private_extern__ CFTypeRef _DAUnserialize( CFAllocatorRef allocator, CFDataRef data ) 408{ 409 return CFPropertyListCreateFromXMLData( allocator, data, kCFPropertyListImmutable, NULL ); 410} 411 412__private_extern__ CFMutableDictionaryRef _DAUnserializeDiskDescription( CFAllocatorRef allocator, CFDataRef data ) 413{ 414 CFMutableDictionaryRef description; 415 416 description = ( void * ) CFPropertyListCreateFromXMLData( allocator, data, kCFPropertyListMutableContainers, NULL ); 417 418 if ( description ) 419 { 420 CFTypeRef object; 421 422 object = CFDictionaryGetValue( description, kDADiskDescriptionMediaUUIDKey ); 423 424 if ( object ) 425 { 426 object = CFUUIDCreateFromString( allocator, object ); 427 428 if ( object ) 429 { 430 CFDictionarySetValue( description, kDADiskDescriptionMediaUUIDKey, object ); 431 432 CFRelease( object ); 433 } 434 } 435 436 object = CFDictionaryGetValue( description, kDADiskDescriptionVolumePathKey ); 437 438 if ( object ) 439 { 440 object = CFURLCreateWithFileSystemPath( allocator, object, kCFURLPOSIXPathStyle, TRUE ); 441 442 if ( object ) 443 { 444 CFDictionarySetValue( description, kDADiskDescriptionVolumePathKey, object ); 445 446 CFRelease( object ); 447 } 448 } 449 450 object = CFDictionaryGetValue( description, kDADiskDescriptionVolumeUUIDKey ); 451 452 if ( object ) 453 { 454 object = CFUUIDCreateFromString( allocator, object ); 455 456 if ( object ) 457 { 458 CFDictionarySetValue( description, kDADiskDescriptionVolumeUUIDKey, object ); 459 460 CFRelease( object ); 461 } 462 } 463 } 464 465 return description; 466} 467 468__private_extern__ CFMutableDictionaryRef _DAUnserializeDiskDescriptionWithBytes( CFAllocatorRef allocator, vm_address_t bytes, vm_size_t length ) 469{ 470 CFMutableDictionaryRef description = NULL; 471 472 if ( bytes ) 473 { 474 CFDataRef data; 475 476 data = CFDataCreateWithBytesNoCopy( allocator, ( void * ) bytes, length, kCFAllocatorNull ); 477 478 if ( data ) 479 { 480 description = _DAUnserializeDiskDescription( allocator, data ); 481 482 CFRelease( data ); 483 } 484 } 485 486 return description; 487} 488 489__private_extern__ CFTypeRef _DAUnserializeWithBytes( CFAllocatorRef allocator, vm_address_t bytes, vm_size_t length ) 490{ 491 CFTypeRef object = NULL; 492 493 if ( bytes ) 494 { 495 CFDataRef data; 496 497 data = CFDataCreateWithBytesNoCopy( allocator, ( void * ) bytes, length, kCFAllocatorNull ); 498 499 if ( data ) 500 { 501 object = _DAUnserialize( allocator, data ); 502 503 CFRelease( data ); 504 } 505 } 506 507 return object; 508} 509 510__private_extern__ char * _DAVolumeCopyID( const struct statfs * fs ) 511{ 512 char * id; 513 514 if ( strncmp( fs->f_mntfromname, _PATH_DEV, strlen( _PATH_DEV ) ) ) 515 { 516 asprintf( &id, "%s?owner=%u", fs->f_mntonname, fs->f_owner ); 517 } 518 else 519 { 520 asprintf( &id, "%s", fs->f_mntfromname ); 521 } 522 523 return id; 524} 525 526__private_extern__ char * _DAVolumeGetID( const struct statfs * fs ) 527{ 528 static char id[ sizeof( fs->f_mntonname ) + strlen( "?owner=" ) + strlen( "4294967295" ) ]; 529 530 if ( strncmp( fs->f_mntfromname, _PATH_DEV, strlen( _PATH_DEV ) ) ) 531 { 532 snprintf( id, sizeof( id ), "%s?owner=%u", fs->f_mntonname, fs->f_owner ); 533 } 534 else 535 { 536 snprintf( id, sizeof( id ), "%s", fs->f_mntfromname ); 537 } 538 539 return id; 540} 541