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 "DASupport.h" 25 26#include "vsdb.h" 27#include "DABase.h" 28#include "DAFileSystem.h" 29#include "DAInternal.h" 30#include "DALog.h" 31#include "DAMain.h" 32#include "DAThread.h" 33 34#include <dirent.h> 35#include <fsproperties.h> 36#include <fstab.h> 37#include <libgen.h> 38#include <pthread.h> 39#include <sys/loadable_fs.h> 40#include <sys/stat.h> 41#include <IOKit/storage/IOStorageProtocolCharacteristics.h> 42#include <SystemConfiguration/SystemConfiguration.h> 43 44struct __DAAuthorizeWithCallbackContext 45{ 46 DAAuthorizeCallback callback; 47 void * callbackContext; 48 DADiskRef disk; 49 _DAAuthorizeOptions options; 50 char * right; 51 DASessionRef session; 52 DAReturn status; 53 gid_t userGID; 54 uid_t userUID; 55}; 56 57typedef struct __DAAuthorizeWithCallbackContext __DAAuthorizeWithCallbackContext; 58 59static pthread_mutex_t __gDAAuthorizeWithCallbackLock = PTHREAD_MUTEX_INITIALIZER; 60 61int __DAAuthorizeWithCallback( void * parameter ) 62{ 63 __DAAuthorizeWithCallbackContext * context = parameter; 64 65 pthread_mutex_lock( &__gDAAuthorizeWithCallbackLock ); 66 67 context->status = DAAuthorize( context->session, context->options, context->disk, context->userUID, context->userGID, context->right ); 68 69 pthread_mutex_unlock( &__gDAAuthorizeWithCallbackLock ); 70 71 return 0; 72} 73 74void __DAAuthorizeWithCallbackCallback( int status, void * parameter ) 75{ 76 __DAAuthorizeWithCallbackContext * context = parameter; 77 78 ( context->callback )( context->status, context->callbackContext ); 79 80 if ( context->disk ) CFRelease( context->disk ); 81 if ( context->session ) CFRelease( context->session ); 82 83 free( context->right ); 84 free( context ); 85} 86 87DAReturn DAAuthorize( DASessionRef session, 88 _DAAuthorizeOptions options, 89 DADiskRef disk, 90 uid_t userUID, 91 gid_t userGID, 92 const char * right ) 93{ 94 DAReturn status; 95 96 status = kDAReturnNotPrivileged; 97 98 if ( status ) 99 { 100 if ( ( options & _kDAAuthorizeOptionIsOwner ) ) 101 { 102 uid_t diskUID; 103 104 diskUID = DADiskGetUserUID( disk ); 105 106 if ( diskUID == userUID ) 107 { 108 status = kDAReturnSuccess; 109 } 110 } 111 } 112 113 if ( status ) 114 { 115 AuthorizationRef authorization; 116 117 authorization = DASessionGetAuthorization( session ); 118 119 if ( authorization ) 120 { 121 AuthorizationFlags flags; 122 AuthorizationItem item; 123 char * name; 124 AuthorizationRights rights; 125 126 flags = kAuthorizationFlagExtendRights; 127 128 if ( ( options & _kDAAuthorizeOptionAuthenticateAdministrator ) ) 129 { 130 flags |= kAuthorizationFlagInteractionAllowed; 131 132 asprintf( &name, "system.volume.workgroup.%s", right ); 133 } 134 else 135 { 136 if ( DADiskGetDescription( disk, kDADiskDescriptionVolumeNetworkKey ) == kCFBooleanTrue ) 137 { 138 asprintf( &name, "system.volume.network.%s", right ); 139 } 140 else 141 { 142 CFTypeRef object; 143 144 object = DADiskGetDescription( disk, kDADiskDescriptionDeviceProtocolKey ); 145 146 if ( object && CFEqual( object, CFSTR( kIOPropertyPhysicalInterconnectTypeVirtual ) ) ) 147 { 148 asprintf( &name, "system.volume.virtual.%s", right ); 149 } 150 else 151 { 152 if ( DADiskGetDescription( disk, kDADiskDescriptionMediaRemovableKey ) == kCFBooleanTrue ) 153 { 154 if ( DADiskGetDescription( disk, kDADiskDescriptionMediaTypeKey ) ) 155 { 156 asprintf( &name, "system.volume.optical.%s", right ); 157 } 158 else 159 { 160 asprintf( &name, "system.volume.removable.%s", right ); 161 } 162 } 163 else 164 { 165 if ( DADiskGetDescription( disk, kDADiskDescriptionDeviceInternalKey ) == kCFBooleanTrue ) 166 { 167 asprintf( &name, "system.volume.internal.%s", right ); 168 } 169 else 170 { 171 asprintf( &name, "system.volume.external.%s", right ); 172 } 173 } 174 } 175 } 176 } 177 178 if ( name ) 179 { 180 item.flags = 0; 181 item.name = name; 182 item.value = NULL; 183 item.valueLength = 0; 184 185 rights.count = 1; 186 rights.items = &item; 187 188 status = AuthorizationCopyRights( authorization, &rights, NULL, flags, NULL ); 189 190 if ( status ) 191 { 192 status = kDAReturnNotPrivileged; 193 } 194 195 free( name ); 196 } 197 } 198 } 199 200 return status; 201} 202 203void DAAuthorizeWithCallback( DASessionRef session, 204 _DAAuthorizeOptions options, 205 DADiskRef disk, 206 uid_t userUID, 207 gid_t userGID, 208 DAAuthorizeCallback callback, 209 void * callbackContext, 210 const char * right ) 211{ 212 __DAAuthorizeWithCallbackContext * context; 213 214 context = malloc( sizeof( __DAAuthorizeWithCallbackContext ) ); 215 216 if ( context ) 217 { 218 if ( disk ) CFRetain( disk ); 219 if ( session ) CFRetain( session ); 220 221 context->callback = callback; 222 context->callbackContext = callbackContext; 223 context->disk = disk; 224 context->options = options; 225 context->right = strdup( right ); 226 context->session = session; 227 context->status = kDAReturnNotPrivileged; 228 context->userGID = userGID; 229 context->userUID = userUID; 230 231 DAThreadExecute( __DAAuthorizeWithCallback, context, __DAAuthorizeWithCallbackCallback, context ); 232 } 233 else 234 { 235 ( callback )( kDAReturnNotPrivileged, callbackContext ); 236 } 237} 238 239static struct timespec __gDAFileSystemListTime = { 0, 0 }; 240 241const CFStringRef kDAFileSystemKey = CFSTR( "DAFileSystem" ); 242 243static void __DAFileSystemProbeListAppendValue( const void * key, const void * value, void * context ) 244{ 245 CFMutableDictionaryRef probe; 246 247 probe = CFDictionaryCreateMutableCopy( kCFAllocatorDefault, 0, value ); 248 249 if ( probe ) 250 { 251 CFDictionarySetValue( probe, kDAFileSystemKey, context ); 252 CFArrayAppendValue( gDAFileSystemProbeList, probe ); 253 CFRelease( probe ); 254 } 255} 256 257static CFComparisonResult __DAFileSystemProbeListCompare( const void * value1, const void * value2, void * context ) 258{ 259 CFNumberRef order1 = CFDictionaryGetValue( value1, CFSTR( kFSProbeOrderKey ) ); 260 CFNumberRef order2 = CFDictionaryGetValue( value2, CFSTR( kFSProbeOrderKey ) ); 261 262 if ( order1 == NULL ) return kCFCompareGreaterThan; 263 if ( order2 == NULL ) return kCFCompareLessThan; 264 265 return CFNumberCompare( order1, order2, NULL ); 266} 267 268void DAFileSystemListRefresh( void ) 269{ 270 struct stat status; 271 272 /* 273 * Determine whether the file system list is up-to-date. 274 */ 275 276 if ( stat( FS_DIR_LOCATION, &status ) ) 277 { 278 __gDAFileSystemListTime.tv_sec = 0; 279 __gDAFileSystemListTime.tv_nsec = 0; 280 } 281 282 if ( __gDAFileSystemListTime.tv_sec != status.st_mtimespec.tv_sec || 283 __gDAFileSystemListTime.tv_nsec != status.st_mtimespec.tv_nsec ) 284 { 285 CFURLRef base; 286 287 __gDAFileSystemListTime.tv_sec = status.st_mtimespec.tv_sec; 288 __gDAFileSystemListTime.tv_nsec = status.st_mtimespec.tv_nsec; 289 290 /* 291 * Clear the file system list. 292 */ 293 294 CFArrayRemoveAllValues( gDAFileSystemList ); 295 CFArrayRemoveAllValues( gDAFileSystemProbeList ); 296 297 /* 298 * Build the file system list. 299 */ 300 301 base = CFURLCreateWithFileSystemPath( kCFAllocatorDefault, CFSTR( FS_DIR_LOCATION ), kCFURLPOSIXPathStyle, TRUE ); 302 303 if ( base ) 304 { 305 DIR * folder; 306 307 /* 308 * Scan the filesystems in the file system folder. 309 */ 310 311 folder = opendir( FS_DIR_LOCATION ); 312 313 if ( folder ) 314 { 315 struct dirent * item; 316 317 DALogDebugHeader( "filesystems have been refreshed." ); 318 319 while ( ( item = readdir( folder ) ) ) 320 { 321 char * suffix; 322 323 suffix = item->d_name + strlen( item->d_name ) - strlen( FS_DIR_SUFFIX ); 324 325 if ( suffix > item->d_name ) 326 { 327 if ( strcmp( suffix, FS_DIR_SUFFIX ) == 0 ) 328 { 329 CFURLRef path; 330 331 path = CFURLCreateFromFileSystemRepresentationRelativeToBase( kCFAllocatorDefault, 332 ( void * ) item->d_name, 333 strlen( item->d_name ), 334 TRUE, 335 base ); 336 337 if ( path ) 338 { 339 DAFileSystemRef filesystem; 340 341 /* 342 * Create a file system object for this file system. 343 */ 344 345 filesystem = DAFileSystemCreate( kCFAllocatorDefault, path ); 346 347 if ( filesystem ) 348 { 349 CFDictionaryRef probe; 350 351 /* 352 * Add this file system object to our list. 353 */ 354 355 DALogDebug( " created filesystem, id = %@.", filesystem ); 356 357 CFArrayAppendValue( gDAFileSystemList, filesystem ); 358 359 probe = DAFileSystemGetProbeList( filesystem ); 360 361 if ( probe ) 362 { 363 CFDictionaryApplyFunction( probe, __DAFileSystemProbeListAppendValue, filesystem ); 364 } 365 366 CFRelease( filesystem ); 367 } 368 369 CFRelease( path ); 370 } 371 } 372 } 373 } 374 375 closedir( folder ); 376 } 377 378 CFRelease( base ); 379 } 380 381 /* 382 * Order the probe list. 383 */ 384 385 CFArraySortValues( gDAFileSystemProbeList, 386 CFRangeMake( 0, CFArrayGetCount( gDAFileSystemProbeList ) ), 387 __DAFileSystemProbeListCompare, 388 NULL ); 389 } 390} 391 392static struct timespec __gDAMountMapListTime1 = { 0, 0 }; 393static struct timespec __gDAMountMapListTime2 = { 0, 0 }; 394 395const CFStringRef kDAMountMapMountAutomaticKey = CFSTR( "DAMountAutomatic" ); 396const CFStringRef kDAMountMapMountOptionsKey = CFSTR( "DAMountOptions" ); 397const CFStringRef kDAMountMapMountPathKey = CFSTR( "DAMountPath" ); 398const CFStringRef kDAMountMapProbeIDKey = CFSTR( "DAProbeID" ); 399const CFStringRef kDAMountMapProbeKindKey = CFSTR( "DAProbeKind" ); 400 401static CFDictionaryRef __DAMountMapCreate1( CFAllocatorRef allocator, struct fstab * fs ) 402{ 403 CFMutableDictionaryRef map = NULL; 404 405 if ( strcmp( fs->fs_type, FSTAB_SW ) ) 406 { 407 char * idAsCString = fs->fs_spec; 408 409 strsep( &idAsCString, "=" ); 410 411 if ( idAsCString ) 412 { 413 CFStringRef idAsString; 414 415 idAsString = CFStringCreateWithCString( kCFAllocatorDefault, idAsCString, kCFStringEncodingUTF8 ); 416 417 if ( idAsString ) 418 { 419 CFTypeRef id = NULL; 420 421 if ( strcmp( fs->fs_spec, "UUID" ) == 0 ) 422 { 423 id = ___CFUUIDCreateFromString( kCFAllocatorDefault, idAsString ); 424 } 425 else if ( strcmp( fs->fs_spec, "LABEL" ) == 0 ) 426 { 427 id = CFRetain( idAsString ); 428 } 429 else if ( strcmp( fs->fs_spec, "DEVICE" ) == 0 ) 430 { 431 id = ___CFDictionaryCreateFromXMLString( kCFAllocatorDefault, idAsString ); 432 } 433 434 if ( id ) 435 { 436 map = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); 437 438 if ( map ) 439 { 440 CFMutableStringRef options; 441 442 options = CFStringCreateMutable( kCFAllocatorDefault, 0 ); 443 444 if ( options ) 445 { 446 char * argument = NULL; 447 char * arguments = fs->fs_mntops; 448 CFBooleanRef automatic = NULL; 449 450 while ( ( argument = strsep( &arguments, "," ) ) ) 451 { 452 if ( strcmp( argument, "auto" ) == 0 ) 453 { 454 automatic = kCFBooleanTrue; 455 } 456 else if ( strcmp( argument, "noauto" ) == 0 ) 457 { 458 automatic = kCFBooleanFalse; 459 } 460 else 461 { 462 CFStringAppendCString( options, argument, kCFStringEncodingUTF8 ); 463 CFStringAppendCString( options, ",", kCFStringEncodingUTF8 ); 464 } 465 } 466 467 if ( automatic ) 468 { 469 CFDictionarySetValue( map, kDAMountMapMountAutomaticKey, automatic ); 470 } 471 472 if ( CFStringGetLength( options ) ) 473 { 474 CFStringTrim( options, CFSTR( "," ) ); 475 476 CFDictionarySetValue( map, kDAMountMapMountOptionsKey, options ); 477 } 478 479 CFRelease( options ); 480 } 481 482 if ( strcmp( fs->fs_file, "none" ) ) 483 { 484 CFURLRef path; 485 486 path = CFURLCreateFromFileSystemRepresentation( kCFAllocatorDefault, ( void * ) fs->fs_file, strlen( fs->fs_file ), TRUE ); 487 488 if ( path ) 489 { 490 CFDictionarySetValue( map, kDAMountMapMountPathKey, path ); 491 492 CFRelease( path ); 493 } 494 } 495 496 if ( strcmp( fs->fs_vfstype, "auto" ) ) 497 { 498 CFStringRef kind; 499 500 kind = CFStringCreateWithCString( kCFAllocatorDefault, fs->fs_vfstype, kCFStringEncodingUTF8 ); 501 502 if ( kind ) 503 { 504 CFDictionarySetValue( map, kDAMountMapProbeKindKey, kind ); 505 506 CFRelease( kind ); 507 } 508 } 509 510 CFDictionarySetValue( map, kDAMountMapProbeIDKey, id ); 511 } 512 513 CFRelease( id ); 514 } 515 516 CFRelease( idAsString ); 517 } 518 } 519 } 520 521 return map; 522} 523 524void DAMountMapListRefresh1( void ) 525{ 526 struct stat status; 527 528 /* 529 * Determine whether the mount map list is up-to-date. 530 */ 531 532 if ( stat( _PATH_FSTAB, &status ) ) 533 { 534 __gDAMountMapListTime1.tv_sec = 0; 535 __gDAMountMapListTime1.tv_nsec = 0; 536 } 537 538 if ( __gDAMountMapListTime1.tv_sec != status.st_mtimespec.tv_sec || 539 __gDAMountMapListTime1.tv_nsec != status.st_mtimespec.tv_nsec ) 540 { 541 __gDAMountMapListTime1.tv_sec = status.st_mtimespec.tv_sec; 542 __gDAMountMapListTime1.tv_nsec = status.st_mtimespec.tv_nsec; 543 544 /* 545 * Clear the mount map list. 546 */ 547 548 CFArrayRemoveAllValues( gDAMountMapList1 ); 549 550 /* 551 * Build the mount map list. 552 */ 553 554 if ( setfsent( ) ) 555 { 556 struct fstab * item; 557 558 while ( ( item = getfsent( ) ) ) 559 { 560 CFDictionaryRef map; 561 562 map = __DAMountMapCreate1( kCFAllocatorDefault, item ); 563 564 if ( map ) 565 { 566 CFArrayAppendValue( gDAMountMapList1, map ); 567 568 CFRelease( map ); 569 } 570 } 571 572 endfsent( ); 573 } 574 } 575} 576 577static CFDictionaryRef __DAMountMapCreate2( CFAllocatorRef allocator, struct vsdb * vs ) 578{ 579 CFStringRef idAsString; 580 CFMutableDictionaryRef map = NULL; 581 582 idAsString = CFStringCreateWithCString( kCFAllocatorDefault, vs->vs_spec, kCFStringEncodingUTF8 ); 583 584 if ( idAsString ) 585 { 586 CFTypeRef id; 587 588 id = _DAFileSystemCreateUUIDFromString( kCFAllocatorDefault, idAsString ); 589 590 if ( id ) 591 { 592 map = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); 593 594 if ( map ) 595 { 596 CFMutableStringRef options; 597 598 options = CFStringCreateMutable( kCFAllocatorDefault, 0 ); 599 600 if ( options ) 601 { 602 if ( ( vs->vs_ops & VSDB_PERM ) ) 603 { 604 CFStringAppend( options, CFSTR( "owners" ) ); 605 CFStringAppend( options, CFSTR( "," ) ); 606 } 607 else 608 { 609 CFStringAppend( options, CFSTR( "noowners" ) ); 610 CFStringAppend( options, CFSTR( "," ) ); 611 } 612 613 if ( CFStringGetLength( options ) ) 614 { 615 CFStringTrim( options, CFSTR( "," ) ); 616 617 CFDictionarySetValue( map, kDAMountMapMountOptionsKey, options ); 618 } 619 620 CFRelease( options ); 621 } 622 623 CFDictionarySetValue( map, kDAMountMapProbeIDKey, id ); 624 } 625 626 CFRelease( id ); 627 } 628 629 CFRelease( idAsString ); 630 } 631 632 return map; 633} 634 635void DAMountMapListRefresh2( void ) 636{ 637 struct stat status; 638 639 /* 640 * Determine whether the mount map list is up-to-date. 641 */ 642 643 if ( stat( _PATH_VSDB, &status ) ) 644 { 645 __gDAMountMapListTime2.tv_sec = 0; 646 __gDAMountMapListTime2.tv_nsec = 0; 647 } 648 649 if ( __gDAMountMapListTime2.tv_sec != status.st_mtimespec.tv_sec || 650 __gDAMountMapListTime2.tv_nsec != status.st_mtimespec.tv_nsec ) 651 { 652 __gDAMountMapListTime2.tv_sec = status.st_mtimespec.tv_sec; 653 __gDAMountMapListTime2.tv_nsec = status.st_mtimespec.tv_nsec; 654 655 /* 656 * Clear the mount map list. 657 */ 658 659 CFArrayRemoveAllValues( gDAMountMapList2 ); 660 661 /* 662 * Build the mount map list. 663 */ 664 665 if ( setvsent( ) ) 666 { 667 struct vsdb * item; 668 669 while ( ( item = getvsent( ) ) ) 670 { 671 CFDictionaryRef map; 672 673 map = __DAMountMapCreate2( kCFAllocatorDefault, item ); 674 675 if ( map ) 676 { 677 CFArrayAppendValue( gDAMountMapList2, map ); 678 679 CFRelease( map ); 680 } 681 } 682 683 endvsent( ); 684 } 685 } 686} 687 688static struct timespec __gDAPreferenceListTime1 = { 0, 0 }; 689static struct timespec __gDAPreferenceListTime2 = { 0, 0 }; 690 691const CFStringRef kDAPreferenceMountDeferExternalKey = CFSTR( "DAMountDeferExternal" ); 692const CFStringRef kDAPreferenceMountDeferInternalKey = CFSTR( "DAMountDeferInternal" ); 693const CFStringRef kDAPreferenceMountDeferRemovableKey = CFSTR( "DAMountDeferRemovable" ); 694const CFStringRef kDAPreferenceMountTrustExternalKey = CFSTR( "DAMountTrustExternal" ); 695const CFStringRef kDAPreferenceMountTrustInternalKey = CFSTR( "DAMountTrustInternal" ); 696const CFStringRef kDAPreferenceMountTrustRemovableKey = CFSTR( "DAMountTrustRemovable" ); 697 698void DAPreferenceListRefresh( void ) 699{ 700 struct stat status1; 701 struct stat status2; 702 703 /* 704 * Determine whether the preference list is up-to-date. 705 */ 706 707 if ( stat( ___PREFS_DEFAULT_DIR "/" "autodiskmount.plist", &status1 ) ) 708 { 709 __gDAPreferenceListTime1.tv_sec = 0; 710 __gDAPreferenceListTime1.tv_nsec = 0; 711 } 712 713 if ( stat( ___PREFS_DEFAULT_DIR "/" _kDADaemonName ".plist", &status2 ) ) 714 { 715 __gDAPreferenceListTime2.tv_sec = 0; 716 __gDAPreferenceListTime2.tv_nsec = 0; 717 } 718 719 if ( __gDAPreferenceListTime1.tv_sec != status1.st_mtimespec.tv_sec || 720 __gDAPreferenceListTime1.tv_nsec != status1.st_mtimespec.tv_nsec || 721 __gDAPreferenceListTime2.tv_sec != status2.st_mtimespec.tv_sec || 722 __gDAPreferenceListTime2.tv_nsec != status2.st_mtimespec.tv_nsec ) 723 { 724 SCPreferencesRef preferences; 725 726 __gDAPreferenceListTime1.tv_sec = status1.st_mtimespec.tv_sec; 727 __gDAPreferenceListTime1.tv_nsec = status1.st_mtimespec.tv_nsec; 728 __gDAPreferenceListTime2.tv_sec = status2.st_mtimespec.tv_sec; 729 __gDAPreferenceListTime2.tv_nsec = status2.st_mtimespec.tv_nsec; 730 731 /* 732 * Clear the preference list. 733 */ 734 735 CFDictionaryRemoveAllValues( gDAPreferenceList ); 736 737 /* 738 * Build the preference list. 739 */ 740 741 preferences = SCPreferencesCreate( kCFAllocatorDefault, CFSTR( "autodiskmount" ), CFSTR( "autodiskmount.plist" ) ); 742 743 if ( preferences ) 744 { 745 CFTypeRef value; 746 747 value = SCPreferencesGetValue( preferences, CFSTR( "AutomountDisksWithoutUserLogin" ) ); 748 749 if ( value == kCFBooleanTrue ) 750 { 751 CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountDeferExternalKey, kCFBooleanFalse ); 752 CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountDeferRemovableKey, kCFBooleanFalse ); 753 CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountTrustExternalKey, kCFBooleanTrue ); 754 } 755 else if ( value == kCFBooleanFalse ) 756 { 757 CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountDeferExternalKey, kCFBooleanFalse ); 758 CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountDeferRemovableKey, kCFBooleanTrue ); 759 CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountTrustExternalKey, kCFBooleanTrue ); 760 } 761 762 CFRelease( preferences ); 763 } 764 765 preferences = SCPreferencesCreate( kCFAllocatorDefault, CFSTR( _kDADaemonName ), CFSTR( _kDADaemonName ".plist" ) ); 766 767 if ( preferences ) 768 { 769 CFTypeRef value; 770 771 value = SCPreferencesGetValue( preferences, kDAPreferenceMountDeferExternalKey ); 772 773 if ( value ) 774 { 775 if ( CFGetTypeID( value ) == CFBooleanGetTypeID( ) ) 776 { 777 CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountDeferExternalKey, value ); 778 } 779 } 780 781 value = SCPreferencesGetValue( preferences, kDAPreferenceMountDeferInternalKey ); 782 783 if ( value ) 784 { 785 if ( CFGetTypeID( value ) == CFBooleanGetTypeID( ) ) 786 { 787 CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountDeferInternalKey, value ); 788 } 789 } 790 791 value = SCPreferencesGetValue( preferences, kDAPreferenceMountDeferRemovableKey ); 792 793 if ( value ) 794 { 795 if ( CFGetTypeID( value ) == CFBooleanGetTypeID( ) ) 796 { 797 CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountDeferRemovableKey, value ); 798 } 799 } 800 801 value = SCPreferencesGetValue( preferences, kDAPreferenceMountTrustExternalKey ); 802 803 if ( value ) 804 { 805 if ( CFGetTypeID( value ) == CFBooleanGetTypeID( ) ) 806 { 807 CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountTrustExternalKey, value ); 808 } 809 } 810 811 value = SCPreferencesGetValue( preferences, kDAPreferenceMountTrustInternalKey ); 812 813 if ( value ) 814 { 815 if ( CFGetTypeID( value ) == CFBooleanGetTypeID( ) ) 816 { 817 CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountTrustInternalKey, value ); 818 } 819 } 820 821 value = SCPreferencesGetValue( preferences, kDAPreferenceMountTrustRemovableKey ); 822 823 if ( value ) 824 { 825 if ( CFGetTypeID( value ) == CFBooleanGetTypeID( ) ) 826 { 827 CFDictionarySetValue( gDAPreferenceList, kDAPreferenceMountTrustRemovableKey, value ); 828 } 829 } 830 831 CFRelease( preferences ); 832 } 833 } 834} 835 836struct __DAUnit 837{ 838 DAUnitState state; 839}; 840 841typedef struct __DAUnit __DAUnit; 842 843Boolean DAUnitGetState( DADiskRef disk, DAUnitState state ) 844{ 845 CFNumberRef key; 846 847 key = DADiskGetDescription( disk, kDADiskDescriptionMediaBSDUnitKey ); 848 849 if ( key ) 850 { 851 CFMutableDataRef data; 852 853 data = ( CFMutableDataRef ) CFDictionaryGetValue( gDAUnitList, key ); 854 855 if ( data ) 856 { 857 __DAUnit * unit; 858 859 unit = ( void * ) CFDataGetMutableBytePtr( data ); 860 861 return ( unit->state & state ) ? TRUE : FALSE; 862 } 863 } 864 865 return FALSE; 866} 867 868void DAUnitSetState( DADiskRef disk, DAUnitState state, Boolean value ) 869{ 870 CFNumberRef key; 871 872 key = DADiskGetDescription( disk, kDADiskDescriptionMediaBSDUnitKey ); 873 874 if ( key ) 875 { 876 CFMutableDataRef data; 877 878 data = ( CFMutableDataRef ) CFDictionaryGetValue( gDAUnitList, key ); 879 880 if ( data ) 881 { 882 __DAUnit * unit; 883 884 unit = ( void * ) CFDataGetMutableBytePtr( data ); 885 886 unit->state &= ~state; 887 unit->state |= value ? state : 0; 888 } 889 else 890 { 891 data = CFDataCreateMutable( kCFAllocatorDefault, sizeof( __DAUnit ) ); 892 893 if ( data ) 894 { 895 __DAUnit * unit; 896 897 unit = ( void * ) CFDataGetMutableBytePtr( data ); 898 899 unit->state = value ? state : 0; 900 901 CFDictionarySetValue( gDAUnitList, key, data ); 902 903 CFRelease( data ); 904 } 905 } 906 } 907} 908