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 "DAServer.h" 25#include "DAServerServer.h" 26 27#include "DABase.h" 28#include "DACallback.h" 29#include "DADialog.h" 30#include "DADisk.h" 31#include "DAFileSystem.h" 32#include "DAInternal.h" 33#include "DALog.h" 34#include "DAMain.h" 35#include "DAMount.h" 36#include "DAPrivate.h" 37#include "DAQueue.h" 38#include "DASession.h" 39#include "DAStage.h" 40#include "DASupport.h" 41 42#include <paths.h> 43#include <servers/bootstrap.h> 44#include <sys/stat.h> 45#include <IOKit/IOMessage.h> 46#include <IOKit/storage/IOMedia.h> 47///w:start 48#include <SystemConfiguration/SCDynamicStoreCopySpecificPrivate.h> 49///w:end 50 51static CFMachPortRef __gDAServer = NULL; 52static mach_port_t __gDAServerPort = MACH_PORT_NULL; 53static mach_msg_header_t * __gDAServerReply = NULL; 54 55static void __DAMediaBusyStateChangedCallback( void * context, io_service_t service, void * argument ); 56static void __DAMediaPropertyChangedCallback( void * context, io_service_t service, void * argument ); 57 58static DADiskRef __DADiskListGetDisk( const char * diskID ) 59{ 60 CFIndex count; 61 CFIndex index; 62 63 count = CFArrayGetCount( gDADiskList ); 64 65 for ( index = 0; index < count; index++ ) 66 { 67 DADiskRef disk; 68 69 disk = ( void * ) CFArrayGetValueAtIndex( gDADiskList, index ); 70 71 if ( strcmp( DADiskGetID( disk ), diskID ) == 0 ) 72 { 73 return disk; 74 } 75 } 76 77 return NULL; 78} 79 80static DADiskRef __DADiskListGetDiskWithIOMedia( io_service_t media ) 81{ 82 CFIndex count; 83 CFIndex index; 84 85 count = CFArrayGetCount( gDADiskList ); 86 87 for ( index = 0; index < count; index++ ) 88 { 89 DADiskRef disk; 90 91 disk = ( void * ) CFArrayGetValueAtIndex( gDADiskList, index ); 92 93 if ( IOObjectIsEqualTo( DADiskGetIOMedia( disk ), media ) ) 94 { 95 return disk; 96 } 97 } 98 99 return NULL; 100} 101 102static void __DAMediaBusyStateChangedCallback( void * context, io_service_t service, void * argument ) 103{ 104 DADiskRef disk; 105 106 disk = __DADiskListGetDiskWithIOMedia( service ); 107 108 if ( disk ) 109 { 110 if ( argument ) 111 { 112 DADiskSetBusy( disk, CFAbsoluteTimeGetCurrent( ) ); 113 } 114 else 115 { 116 DADiskSetBusy( disk, 0 ); 117 } 118 } 119} 120 121static void __DAMediaChangedCallback( void * context, io_service_t service, natural_t message, void * argument ) 122{ 123 switch ( message ) 124 { 125 case kIOMessageServiceBusyStateChange: 126 { 127 __DAMediaBusyStateChangedCallback( context, service, argument ); 128 129 break; 130 } 131 case kIOMessageServicePropertyChange: 132 { 133 __DAMediaPropertyChangedCallback( context, service, argument ); 134 135 break; 136 } 137 } 138} 139 140static void __DAMediaPropertyChangedCallback( void * context, io_service_t service, void * argument ) 141{ 142 DADiskRef disk; 143 144 disk = __DADiskListGetDiskWithIOMedia( service ); 145 146 if ( disk ) 147 { 148 CFMutableArrayRef keys; 149 150 keys = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks ); 151 152 if ( keys ) 153 { 154 CFMutableDictionaryRef properties = NULL; 155 156 IORegistryEntryCreateCFProperties( service, &properties, CFGetAllocator( disk ), 0 ); 157 158 if ( properties ) 159 { 160 CFTypeRef object; 161 162 object = CFDictionaryGetValue( properties, CFSTR( kIOMediaContentKey ) ); 163 164 if ( DADiskCompareDescription( disk, kDADiskDescriptionMediaContentKey, object ) ) 165 { 166 DADiskSetDescription( disk, kDADiskDescriptionMediaContentKey, object ); 167 168 CFArrayAppendValue( keys, kDADiskDescriptionMediaContentKey ); 169 } 170 171 object = CFDictionaryGetValue( properties, CFSTR( kIOMediaEjectableKey ) ); 172 173 if ( DADiskCompareDescription( disk, kDADiskDescriptionMediaEjectableKey, object ) ) 174 { 175 DADiskSetDescription( disk, kDADiskDescriptionMediaEjectableKey, object ); 176 177 CFArrayAppendValue( keys, kDADiskDescriptionMediaEjectableKey ); 178 } 179 180 object = CFDictionaryGetValue( properties, CFSTR( kIOMediaLeafKey ) ); 181 182 if ( DADiskCompareDescription( disk, kDADiskDescriptionMediaLeafKey, object ) ) 183 { 184 DADiskSetDescription( disk, kDADiskDescriptionMediaLeafKey, object ); 185 186 CFArrayAppendValue( keys, kDADiskDescriptionMediaLeafKey ); 187 } 188 189 object = CFDictionaryGetValue( properties, CFSTR( kIOMediaPreferredBlockSizeKey ) ); 190 191 if ( DADiskCompareDescription( disk, kDADiskDescriptionMediaBlockSizeKey, object ) ) 192 { 193 DADiskSetDescription( disk, kDADiskDescriptionMediaBlockSizeKey, object ); 194 195 CFArrayAppendValue( keys, kDADiskDescriptionMediaBlockSizeKey ); 196 } 197 198 object = CFDictionaryGetValue( properties, CFSTR( kIOMediaRemovableKey ) ); 199 200 if ( DADiskCompareDescription( disk, kDADiskDescriptionMediaRemovableKey, object ) ) 201 { 202 DADiskSetDescription( disk, kDADiskDescriptionMediaRemovableKey, object ); 203 204 CFArrayAppendValue( keys, kDADiskDescriptionMediaRemovableKey ); 205 } 206 207 object = CFDictionaryGetValue( properties, CFSTR( kIOMediaSizeKey ) ); 208 209 if ( DADiskCompareDescription( disk, kDADiskDescriptionMediaSizeKey, object ) ) 210 { 211 DADiskSetDescription( disk, kDADiskDescriptionMediaSizeKey, object ); 212 213 CFArrayAppendValue( keys, kDADiskDescriptionMediaSizeKey ); 214 } 215 216 object = CFDictionaryGetValue( properties, CFSTR( kIOMediaWholeKey ) ); 217 218 if ( DADiskCompareDescription( disk, kDADiskDescriptionMediaWholeKey, object ) ) 219 { 220 DADiskSetDescription( disk, kDADiskDescriptionMediaWholeKey, object ); 221 222 CFArrayAppendValue( keys, kDADiskDescriptionMediaWholeKey ); 223 } 224 225 object = CFDictionaryGetValue( properties, CFSTR( kIOMediaWritableKey ) ); 226 227 if ( DADiskCompareDescription( disk, kDADiskDescriptionMediaWritableKey, object ) ) 228 { 229 DADiskSetDescription( disk, kDADiskDescriptionMediaWritableKey, object ); 230 231 CFArrayAppendValue( keys, kDADiskDescriptionMediaWritableKey ); 232 } 233 234 if ( CFArrayGetCount( keys ) ) 235 { 236 DALogDebugHeader( "iokit [0] -> %s", gDAProcessNameID ); 237 238 DALogDebug( " updated disk, id = %@.", disk ); 239 240 if ( DADiskGetState( disk, kDADiskStateStagedAppear ) ) 241 { 242 DADiskDescriptionChangedCallback( disk, keys ); 243 } 244 } 245 246 CFRelease( properties ); 247 } 248 249 CFRelease( keys ); 250 } 251 } 252} 253 254static DASessionRef __DASessionListGetSession( mach_port_t sessionID ) 255{ 256 CFIndex count; 257 CFIndex index; 258 259 count = CFArrayGetCount( gDASessionList ); 260 261 for ( index = 0; index < count; index++ ) 262 { 263 DASessionRef session; 264 265 session = ( void * ) CFArrayGetValueAtIndex( gDASessionList, index ); 266 267 if ( DASessionGetID( session ) == sessionID ) 268 { 269 return session; 270 } 271 } 272 273 return NULL; 274} 275 276void _DAConfigurationCallback( SCDynamicStoreRef session, CFArrayRef keys, void * info ) 277{ 278 /* 279 * A console user has logged in or logged out. 280 */ 281 282 CFStringRef previousUser; 283 gid_t previousUserGID; 284 uid_t previousUserUID; 285 CFArrayRef previousUserList; 286 CFStringRef user; 287 gid_t userGID; 288 uid_t userUID; 289 CFArrayRef userList; 290 291 DALogDebugHeader( "configd [0] -> %s", gDAProcessNameID ); 292 293 previousUser = gDAConsoleUser; 294 previousUserGID = gDAConsoleUserGID; 295 previousUserUID = gDAConsoleUserUID; 296 previousUserList = gDAConsoleUserList; 297 298 user = ___SCDynamicStoreCopyConsoleUser( session, &userUID, &userGID ); 299///w:start 300 if ( user ) 301 { 302 /* 303 * Determine whether we need to wait for SystemUIServer. 304 */ 305 306 if ( session ) /* not SystemUIServer */ 307 { 308 CFIndex count; 309 CFIndex index; 310 311 count = 0; 312 313 if ( previousUserList ) 314 { 315 count = CFArrayGetCount( previousUserList ); 316 } 317 318 for ( index = 0; index < count; index++ ) 319 { 320 CFDictionaryRef dictionary; 321 322 dictionary = ( void * ) CFArrayGetValueAtIndex( previousUserList, index ); 323 324 if ( dictionary ) 325 { 326 CFStringRef string; 327 328 string = CFDictionaryGetValue( dictionary, kSCConsoleSessionUserName ); 329 330 if ( CFEqual( string, user ) ) 331 { 332 break; 333 } 334 } 335 } 336 337 if ( index == count ) /* not Fast User Switch */ 338 { 339 userList = SCDynamicStoreCopyConsoleInformation( session ); 340 341 if ( userList ) /* not OS X Installer */ 342 { 343 CFRelease( user ); 344 CFRelease( userList ); 345 346 return; /* wait */ 347 } 348 } 349 } 350 } 351///w:stop 352 userList = ___SCDynamicStoreCopyConsoleInformation( session ); 353 354 gDAConsoleUser = user; 355 gDAConsoleUserGID = userGID; 356 gDAConsoleUserUID = userUID; 357 gDAConsoleUserList = userList; 358 359 if ( gDAConsoleUser ) 360 { 361 /* 362 * A console user has logged in. 363 */ 364 365 DALogDebug( " console user = %@ [%d].", gDAConsoleUser, gDAConsoleUserUID ); 366 } 367 else 368 { 369 CFIndex count; 370 CFIndex index; 371 372 /* 373 * A console user has logged out. 374 */ 375 376 DALogDebug( " console user = none." ); 377 378 count = 0; 379 380 if ( gDAConsoleUserList ) 381 { 382 count = CFArrayGetCount( gDAConsoleUserList ); 383 } 384 385 for ( index = 0; index < count; index++ ) 386 { 387 CFDictionaryRef dictionary; 388 389 dictionary = CFArrayGetValueAtIndex( gDAConsoleUserList, index ); 390 391 if ( ___CFDictionaryGetIntegerValue( dictionary, kSCConsoleSessionUID ) == previousUserUID ) 392 { 393 break; 394 } 395 } 396 397 if ( index == count ) 398 { 399 count = CFArrayGetCount( gDADiskList ); 400 401 for ( index = 0; index < count; index++ ) 402 { 403 DADiskRef disk; 404 405 disk = ( void * ) CFArrayGetValueAtIndex( gDADiskList, index ); 406 407 /* 408 * Unmount this volume. 409 */ 410 411 if ( DADiskGetDescription( disk, kDADiskDescriptionVolumeMountableKey ) == kCFBooleanTrue ) 412 { 413 Boolean unmount; 414 415 unmount = FALSE; 416 417 if ( DADiskGetUserUID( disk ) ) 418 { 419 if ( DADiskGetUserUID( disk ) == previousUserUID ) 420 { 421 unmount = TRUE; 422 } 423 } 424 425 if ( unmount ) 426 { 427 DADiskUnmount( disk, kDADiskUnmountOptionDefault, NULL ); 428 } 429 } 430 } 431 432 for ( index = 0; index < count; index++ ) 433 { 434 DADiskRef disk; 435 436 disk = ( void * ) CFArrayGetValueAtIndex( gDADiskList, index ); 437 438 /* 439 * Eject this disk. 440 */ 441 442 if ( DADiskGetDescription( disk, kDADiskDescriptionMediaWholeKey ) == kCFBooleanTrue ) 443 { 444 Boolean eject; 445 446 eject = FALSE; 447 448 if ( DADiskGetUserUID( disk ) ) 449 { 450 if ( DADiskGetUserUID( disk ) == previousUserUID ) 451 { 452 eject = TRUE; 453 } 454 } 455 456 if ( eject ) 457 { 458 DADiskEject( disk, kDADiskEjectOptionDefault, NULL ); 459 } 460 } 461 } 462 } 463 } 464 465 if ( gDAConsoleUserList ) 466 { 467 CFIndex count; 468 CFIndex index; 469 470 /* 471 * A console user is logged in. 472 */ 473 474 count = CFArrayGetCount( gDADiskList ); 475 476 for ( index = 0; index < count; index++ ) 477 { 478 DADiskRef disk; 479 480 disk = ( void * ) CFArrayGetValueAtIndex( gDADiskList, index ); 481///w:start 482 /* 483 * Set the BSD permissions for this media object. 484 */ 485 486 if ( DADiskGetDescription( disk, kDADiskDescriptionMediaTypeKey ) ) 487 { 488 mode_t deviceMode; 489 uid_t deviceUser; 490 491 deviceMode = 0640; 492 deviceUser = gDAConsoleUserUID; 493 494 if ( CFArrayGetCount( gDAConsoleUserList ) > 1 ) 495 { 496 deviceMode = 0666; 497 deviceUser = ___UID_ROOT; 498 } 499 500 if ( DADiskGetDescription( disk, kDADiskDescriptionMediaWritableKey ) == kCFBooleanFalse ) 501 { 502 deviceMode &= 0444; 503 } 504 505 chmod( DADiskGetBSDPath( disk, TRUE ), deviceMode ); 506 chmod( DADiskGetBSDPath( disk, FALSE ), deviceMode ); 507 508 chown( DADiskGetBSDPath( disk, TRUE ), deviceUser, -1 ); 509 chown( DADiskGetBSDPath( disk, FALSE ), deviceUser, -1 ); 510 } 511///w:stop 512 513 /* 514 * Mount this volume. 515 */ 516 517 if ( previousUserList == NULL ) 518 { 519 if ( DADiskGetDescription( disk, kDADiskDescriptionVolumeMountableKey ) == kCFBooleanTrue ) 520 { 521 if ( DAMountGetPreference( disk, kDAMountPreferenceDefer ) ) 522 { 523 DADiskMountWithArguments( disk, NULL, kDADiskMountOptionDefault, NULL, CFSTR( "automatic" ) ); 524 } 525 } 526 } 527 } 528 } 529 else 530 { 531 CFIndex count; 532 CFIndex index; 533 534 /* 535 * A console user is not logged in. 536 */ 537 538 DAPreferenceListRefresh( ); 539 540 count = CFArrayGetCount( gDADiskList ); 541 542 for ( index = 0; index < count; index++ ) 543 { 544 DADiskRef disk; 545 546 disk = ( void * ) CFArrayGetValueAtIndex( gDADiskList, index ); 547///w:start 548 /* 549 * Set the BSD permissions for this media object. 550 */ 551 552 if ( DADiskGetDescription( disk, kDADiskDescriptionMediaTypeKey ) ) 553 { 554 mode_t deviceMode; 555 uid_t deviceUser; 556 557 deviceMode = 0640; 558 deviceUser = ___UID_ROOT; 559 560 if ( DADiskGetDescription( disk, kDADiskDescriptionMediaWritableKey ) == kCFBooleanFalse ) 561 { 562 deviceMode &= 0444; 563 } 564 565 chmod( DADiskGetBSDPath( disk, TRUE ), deviceMode ); 566 chmod( DADiskGetBSDPath( disk, FALSE ), deviceMode ); 567 568 chown( DADiskGetBSDPath( disk, TRUE ), deviceUser, -1 ); 569 chown( DADiskGetBSDPath( disk, FALSE ), deviceUser, -1 ); 570 } 571///w:stop 572 573 /* 574 * Unmount this volume. 575 */ 576 577 if ( DADiskGetDescription( disk, kDADiskDescriptionVolumeMountableKey ) == kCFBooleanTrue ) 578 { 579 Boolean unmount; 580 581 unmount = FALSE; 582 583 if ( DAMountGetPreference( disk, kDAMountPreferenceDefer ) ) 584 { 585 if ( DADiskGetOption( disk, kDADiskOptionMountAutomaticNoDefer ) == FALSE ) 586 { 587 unmount = TRUE; 588 } 589 } 590 591 if ( DADiskGetOption( disk, kDADiskOptionEjectUponLogout ) ) 592 { 593 unmount = TRUE; 594 } 595 596 if ( unmount ) 597 { 598 DADiskUnmount( disk, kDADiskUnmountOptionDefault, NULL ); 599 } 600 } 601 } 602 603 for ( index = 0; index < count; index++ ) 604 { 605 DADiskRef disk; 606 607 disk = ( void * ) CFArrayGetValueAtIndex( gDADiskList, index ); 608 609 /* 610 * Eject this disk. 611 */ 612 613 if ( DADiskGetDescription( disk, kDADiskDescriptionMediaWholeKey ) == kCFBooleanTrue ) 614 { 615 Boolean eject; 616 617 eject = FALSE; 618 619 if ( DADiskGetOption( disk, kDADiskOptionEjectUponLogout ) ) 620 { 621 eject = TRUE; 622 } 623 624 if ( eject ) 625 { 626 DADiskEject( disk, kDADiskEjectOptionDefault, NULL ); 627 } 628 } 629 } 630 } 631 632 if ( previousUser ) 633 { 634 CFRelease( previousUser ); 635 } 636 637 if ( previousUserList ) 638 { 639 CFRelease( previousUserList ); 640 } 641 642 DAStageSignal( ); 643} 644 645void _DAMediaAppearedCallback( void * context, io_iterator_t notification ) 646{ 647 /* 648 * Process the appearance of media objects in I/O Kit. 649 */ 650 651 io_service_t media; 652 653 /* 654 * Iterate through the media objects. 655 */ 656 657 while ( ( media = IOIteratorNext( notification ) ) ) 658 { 659 DADiskRef disk; 660 661 /* 662 * Determine whether this is a re-registration. 663 */ 664 665 disk = __DADiskListGetDiskWithIOMedia( media ); 666 667 if ( disk ) 668 { 669 __DAMediaPropertyChangedCallback( NULL, media, NULL ); 670///w:start 671 if ( DADiskGetDescription( disk, kDADiskDescriptionVolumeMountableKey ) == kCFBooleanTrue ) 672 { 673 if ( DADiskGetDescription( disk, kDADiskDescriptionMediaLeafKey ) == kCFBooleanFalse ) 674 { 675 DADiskProbe( disk, NULL ); 676 } 677 } 678///w:stop 679 } 680 else 681 { 682 io_object_t busyNotification; 683 io_object_t propertyNotification; 684 685 /* 686 * Create the "media changed" notification. 687 */ 688 689 busyNotification = IO_OBJECT_NULL; 690 691 IOServiceAddInterestNotification( gDAMediaPort, media, kIOBusyInterest, __DAMediaChangedCallback, NULL, &busyNotification ); 692 693 propertyNotification = IO_OBJECT_NULL; 694 695 IOServiceAddInterestNotification( gDAMediaPort, media, kIOGeneralInterest, __DAMediaChangedCallback, NULL, &propertyNotification ); 696 697 /* 698 * Create a disk object for this media object. 699 */ 700 701 DALogDebugHeader( "iokit [0] -> %s", gDAProcessNameID ); 702 703 disk = DADiskCreateFromIOMedia( kCFAllocatorDefault, media ); 704 705 if ( disk ) 706 { 707 /* 708 * Determine whether a media object disappearance and appearance occurred. We must do this 709 * since the I/O Kit appearance queue is separate from the I/O Kit disappearance queue, and 710 * we are in the midst of processing the appearance queue when we see a duplicate, which is 711 * to say, there is a disappearance on the queue we have not processed yet and must process 712 * it first. The appearances and disappearances within each queue do occur in proper order. 713 */ 714 715 if ( ___CFArrayContainsValue( gDADiskList, disk ) ) 716 { 717 /* 718 * Process the disappearance. 719 */ 720 721 _DAMediaDisappearedCallback( ( void * ) ___CFArrayGetValue( gDADiskList, disk ), IO_OBJECT_NULL ); 722 723 assert( ___CFArrayContainsValue( gDADiskList, disk ) == FALSE ); 724 } 725 726 /* 727 * Set the "media changed" notification. 728 */ 729 730 if ( busyNotification ) 731 { 732 DADiskSetBusyNotification( disk, busyNotification ); 733 } 734 735 if ( propertyNotification ) 736 { 737 DADiskSetPropertyNotification( disk, propertyNotification ); 738 } 739 740 /* 741 * Set the BSD permissions for this media object. 742 */ 743 744 if ( DADiskGetDescription( disk, kDADiskDescriptionMediaTypeKey ) ) 745 { 746 if ( DADiskGetMode( disk ) ) 747 { 748 chmod( DADiskGetBSDPath( disk, TRUE ), DADiskGetMode( disk ) & 0666 ); 749 chmod( DADiskGetBSDPath( disk, FALSE ), DADiskGetMode( disk ) & 0666 ); 750 } 751 752 if ( gDAConsoleUserList ) 753 { 754///w:start 755 mode_t deviceMode; 756 uid_t deviceUser; 757 758 deviceMode = 0640; 759 deviceUser = gDAConsoleUserUID; 760 761 if ( CFArrayGetCount( gDAConsoleUserList ) > 1 ) 762 { 763 deviceMode = 0666; 764 deviceUser = ___UID_ROOT; 765 } 766 767 if ( DADiskGetDescription( disk, kDADiskDescriptionMediaWritableKey ) == kCFBooleanFalse ) 768 { 769 deviceMode &= 0444; 770 } 771 772 chmod( DADiskGetBSDPath( disk, TRUE ), deviceMode ); 773 chmod( DADiskGetBSDPath( disk, FALSE ), deviceMode ); 774 775 chown( DADiskGetBSDPath( disk, TRUE ), deviceUser, -1 ); 776 chown( DADiskGetBSDPath( disk, FALSE ), deviceUser, -1 ); 777///w:stop 778 } 779 } 780 else 781 { 782 if ( DADiskGetMode( disk ) ) 783 { 784 chmod( DADiskGetBSDPath( disk, TRUE ), DADiskGetMode( disk ) & 0666 ); 785 chmod( DADiskGetBSDPath( disk, FALSE ), DADiskGetMode( disk ) & 0666 ); 786 } 787 788 if ( DADiskGetUserGID( disk ) ) 789 { 790 chown( DADiskGetBSDPath( disk, TRUE ), -1, DADiskGetUserGID( disk ) ); 791 chown( DADiskGetBSDPath( disk, FALSE ), -1, DADiskGetUserGID( disk ) ); 792 } 793 794 if ( DADiskGetUserUID( disk ) ) 795 { 796 chown( DADiskGetBSDPath( disk, TRUE ), DADiskGetUserUID( disk ), -1 ); 797 chown( DADiskGetBSDPath( disk, FALSE ), DADiskGetUserUID( disk ), -1 ); 798 } 799 } 800 801 /* 802 * Set the BSD link for this media object. 803 */ 804 805 if ( DADiskGetBSDLink( disk, TRUE ) ) 806 { 807 int status; 808 809 status = strncmp( DADiskGetBSDLink( disk, TRUE ), _PATH_DEV "disk", strlen( _PATH_DEV "disk" ) ); 810 811 if ( status ) 812 { 813 status = link( DADiskGetBSDPath( disk, TRUE ), DADiskGetBSDLink( disk, TRUE ) ); 814 815 if ( status == 0 ) 816 { 817 status = link( DADiskGetBSDPath( disk, FALSE ), DADiskGetBSDLink( disk, FALSE ) ); 818 819 if ( status ) 820 { 821 unlink( DADiskGetBSDLink( disk, TRUE ) ); 822 } 823 } 824 } 825 826 if ( status ) 827 { 828 DALogDebugHeader( "iokit [0] -> %s", gDAProcessNameID ); 829 830 DALogError( "unable to link %@ to %s.", disk, DADiskGetBSDLink( disk, TRUE ) ); 831 832 DADiskSetBSDLink( disk, TRUE, NULL ); 833 DADiskSetBSDLink( disk, FALSE, NULL ); 834 } 835 } 836 837 /* 838 * Add the disk object to our tables. 839 */ 840 841 DALogDebugHeader( "iokit [0] -> %s", gDAProcessNameID ); 842 843 DALogDebug( " created disk, id = %@.", disk ); 844 845 DAUnitSetState( disk, kDAUnitStateStagedUnreadable, FALSE ); 846 847 CFArrayInsertValueAtIndex( gDADiskList, 0, disk ); 848 849 CFRelease( disk ); 850 } 851 852 if ( busyNotification ) 853 { 854 IOObjectRelease( busyNotification ); 855 } 856 857 if ( propertyNotification ) 858 { 859 IOObjectRelease( propertyNotification ); 860 } 861 } 862 863 IOObjectRelease( media ); 864 } 865 866 DAStageSignal( ); 867} 868 869void _DAMediaDisappearedCallback( void * context, io_iterator_t notification ) 870{ 871 /* 872 * Process the disappearance of media objects in I/O Kit. 873 */ 874 875 io_service_t media; 876 877 /* 878 * Iterate through the media objects. 879 */ 880 881 if ( context ) 882 { 883 media = DADiskGetIOMedia( context ); 884 } 885 else 886 { 887 media = IOIteratorNext( notification ); 888 } 889 890 for ( ; media ; media = IOIteratorNext( notification ) ) 891 { 892 DADiskRef disk; 893 894 /* 895 * Obtain the disk object for this media object. 896 */ 897 898 disk = __DADiskListGetDiskWithIOMedia( media ); 899 900 /* 901 * Determine whether a media object appearance and disappearance occurred. We must do this 902 * since the I/O Kit appearance queue is separate from the I/O Kit disappearance queue, and 903 * we are in the midst of processing the disappearance queue when we see one missing, which 904 * is to say, there is an appearance on the queue we haven't processed yet and must process 905 * it first. The appearances and disappearances within each queue do occur in proper order. 906 */ 907 908 if ( disk == NULL ) 909 { 910 /* 911 * Process the appearance. 912 */ 913 914 assert( context == NULL ); 915 916 _DAMediaAppearedCallback( NULL, gDAMediaAppearedNotification ); 917 918 disk = __DADiskListGetDiskWithIOMedia( media ); 919 } 920 921 if ( disk ) 922 { 923 /* 924 * Remove the disk object from our tables. 925 */ 926 927 DALogDebugHeader( "iokit [0] -> %s", gDAProcessNameID ); 928 929 DALogDebug( " removed disk, id = %@.", disk ); 930 931 if ( DADiskGetBSDLink( disk, TRUE ) ) 932 { 933 unlink( DADiskGetBSDLink( disk, TRUE ) ); 934 } 935 936 if ( DADiskGetBSDLink( disk, FALSE ) ) 937 { 938 unlink( DADiskGetBSDLink( disk, FALSE ) ); 939 } 940 941 DAQueueReleaseDisk( disk ); 942 943 if ( DADiskGetState( disk, kDADiskStateStagedAppear ) ) 944 { 945 DADiskDisappearedCallback( disk ); 946 } 947 948 if ( DADiskGetState( disk, kDADiskStateStagedMount ) ) 949 { 950 DADiskUnmount( disk, kDADiskUnmountOptionForce, NULL ); 951 } 952 953 DADiskSetState( disk, kDADiskStateZombie, TRUE ); 954 955 ___CFArrayRemoveValue( gDADiskList, disk ); 956 } 957 958 if ( context ) 959 { 960 break; 961 } 962 963 IOObjectRelease( media ); 964 } 965 966 DAStageSignal( ); 967} 968 969void _DAServerCallback( CFMachPortRef port, void * parameter, CFIndex messageSize, void * info ) 970{ 971 mach_msg_header_t * message = parameter; 972 973 if ( message->msgh_id == MACH_NOTIFY_NO_SENDERS ) 974 { 975 _DAServerSessionRelease( message->msgh_local_port ); 976 } 977 else if ( DAServer_server( message, __gDAServerReply ) ) 978 { 979 kern_return_t status; 980 981 status = ( __gDAServerReply->msgh_bits & MACH_MSGH_BITS_COMPLEX ) 982 ? KERN_SUCCESS 983 : ( ( mig_reply_error_t * ) __gDAServerReply )->RetCode; 984 985 /* 986 * Any resources present in the request message are the responsibility of the service 987 * function, if it is successful in responding to the request. Success is defined in 988 * two ways: 989 * 990 * o KERN_SUCCESS: This says that the user�s request was processed, and all incoming 991 * resources have been recorded or deallocated by the server routine. 992 * o MIG_NO_REPLY: This says that the user�s request was accepted, and all incoming 993 * resources have been recorded or deallocated by the server routine. 994 * 995 * A reply should always be returned for any message received, unless the return code 996 * from the server was MIG_NO_REPLY or the request message does not have a reply port. 997 */ 998 999 if ( status != MIG_NO_REPLY ) 1000 { 1001 if ( status != KERN_SUCCESS ) 1002 { 1003 message->msgh_remote_port = MACH_PORT_NULL; 1004 1005 mach_msg_destroy( message ); 1006 } 1007 1008 if ( __gDAServerReply->msgh_remote_port ) 1009 { 1010 status = mach_msg_send( __gDAServerReply ); 1011 1012 if ( status == MACH_SEND_INVALID_DEST ) 1013 { 1014 mach_msg_destroy( __gDAServerReply ); 1015 } 1016 } 1017 } 1018 } 1019} 1020 1021kern_return_t _DAServerDiskCopyDescription( mach_port_t _session, caddr_t _disk, vm_address_t * _description, mach_msg_type_number_t * _descriptionSize ) 1022{ 1023 kern_return_t status; 1024 1025 status = kDAReturnBadArgument; 1026 1027 DALogDebugHeader( "? [?]:%d -> %s", _session, gDAProcessNameID ); 1028 1029 if ( _session ) 1030 { 1031 DASessionRef session; 1032 1033 session = __DASessionListGetSession( _session ); 1034 1035 if ( session ) 1036 { 1037 DADiskRef disk; 1038 1039 DALogDebugHeader( "%@ -> %s", session, gDAProcessNameID ); 1040 1041 disk = __DADiskListGetDisk( _disk ); 1042 1043 if ( disk ) 1044 { 1045 CFDataRef description; 1046 1047 description = DADiskGetSerialization( disk ); 1048 1049 if ( description ) 1050 { 1051 *_description = ___CFDataCopyBytes( description, _descriptionSize ); 1052 1053 if ( *_description ) 1054 { 1055 DALogDebug( " copied disk description, id = %@.", disk ); 1056 1057 status = kDAReturnSuccess; 1058 } 1059 } 1060 } 1061 } 1062 } 1063 1064 if ( status ) 1065 { 1066 DALogDebug( "unable to copy disk description, id = %s (status code 0x%08X).", _disk, status ); 1067 } 1068 1069 return status; 1070} 1071 1072kern_return_t _DAServerDiskGetOptions( mach_port_t _session, caddr_t _disk, int32_t * _options ) 1073{ 1074 kern_return_t status; 1075 1076 status = kDAReturnBadArgument; 1077 1078 DALogDebugHeader( "? [?]:%d -> %s", _session, gDAProcessNameID ); 1079 1080 if ( _session ) 1081 { 1082 DASessionRef session; 1083 1084 session = __DASessionListGetSession( _session ); 1085 1086 if ( session ) 1087 { 1088 DADiskRef disk; 1089 1090 DALogDebugHeader( "%@ -> %s", session, gDAProcessNameID ); 1091 1092 disk = __DADiskListGetDisk( _disk ); 1093 1094 if ( disk ) 1095 { 1096 *_options = DADiskGetOptions( disk ); 1097 1098 DALogDebug( " got disk options, id = %@, options = 0x%08X.", disk, *_options ); 1099 1100 status = kDAReturnSuccess; 1101 } 1102 } 1103 } 1104 1105 if ( status ) 1106 { 1107 DALogDebug( "unable to get disk options, id = %s (status code 0x%08X).", _disk, status ); 1108 } 1109 1110 return status; 1111} 1112 1113kern_return_t _DAServerDiskGetUserUID( mach_port_t _session, caddr_t _disk, uid_t * _userUID ) 1114{ 1115 kern_return_t status; 1116 1117 status = kDAReturnBadArgument; 1118 1119 if ( _session ) 1120 { 1121 DASessionRef session; 1122 1123 session = __DASessionListGetSession( _session ); 1124 1125 if ( session ) 1126 { 1127 DADiskRef disk; 1128 1129 disk = __DADiskListGetDisk( _disk ); 1130 1131 if ( disk ) 1132 { 1133 *_userUID = DADiskGetUserUID( disk ); 1134 1135 status = kDAReturnSuccess; 1136 } 1137 } 1138 } 1139 1140 return status; 1141} 1142 1143kern_return_t _DAServerDiskIsClaimed( mach_port_t _session, caddr_t _disk, boolean_t * _claimed ) 1144{ 1145 kern_return_t status; 1146 1147 status = kDAReturnBadArgument; 1148 1149 DALogDebugHeader( "? [?]:%d -> %s", _session, gDAProcessNameID ); 1150 1151 if ( _session ) 1152 { 1153 DASessionRef session; 1154 1155 session = __DASessionListGetSession( _session ); 1156 1157 if ( session ) 1158 { 1159 DADiskRef disk; 1160 1161 DALogDebugHeader( "%@ -> %s", session, gDAProcessNameID ); 1162 1163 disk = __DADiskListGetDisk( _disk ); 1164 1165 if ( disk ) 1166 { 1167 *_claimed = DADiskGetClaim( disk ) ? TRUE : FALSE; 1168 1169 DALogDebug( " got disk claim state, id = %@, claimed = %s.", disk, *_claimed ? "true" : "false" ); 1170 1171 status = kDAReturnSuccess; 1172 } 1173 } 1174 } 1175 1176 if ( status ) 1177 { 1178 DALogDebug( "unable to get disk claim state, id = %s (status code 0x%08X).", _disk, status ); 1179 } 1180 1181 return status; 1182} 1183 1184kern_return_t _DAServerDiskSetAdoption( mach_port_t _session, caddr_t _disk, boolean_t _adoption, security_token_t _token ) 1185{ 1186 kern_return_t status; 1187 1188 status = kDAReturnBadArgument; 1189 1190 DALogDebugHeader( "? [?]:%d -> %s", _session, gDAProcessNameID ); 1191 1192 if ( _session ) 1193 { 1194 DASessionRef session; 1195 1196 session = __DASessionListGetSession( _session ); 1197 1198 if ( session ) 1199 { 1200 DADiskRef disk; 1201 1202 DALogDebugHeader( "%@ -> %s", session, gDAProcessNameID ); 1203 1204 disk = __DADiskListGetDisk( _disk ); 1205 1206 if ( disk ) 1207 { 1208 status = DAAuthorize( session, _kDAAuthorizeOptionDefault, disk, _token.val[0], _token.val[1], _kDAAuthorizeRightAdopt ); 1209 1210 if ( status == kDAReturnSuccess ) 1211 { 1212 DALogDebug( " set disk adoption, id = %@, adoption = %s.", disk, _adoption ? "true" : "false" ); 1213 1214 status = _DADiskSetAdoption( disk, _adoption ); 1215 } 1216 } 1217 } 1218 } 1219 1220 if ( status ) 1221 { 1222 DALogDebug( "unable to set disk adoption, id = %s (status code 0x%08X).", _disk, status ); 1223 } 1224 1225 return status; 1226} 1227 1228kern_return_t _DAServerDiskSetEncoding( mach_port_t _session, caddr_t _disk, int32_t encoding, security_token_t _token ) 1229{ 1230 kern_return_t status; 1231 1232 status = kDAReturnBadArgument; 1233 1234 DALogDebugHeader( "? [?]:%d -> %s", _session, gDAProcessNameID ); 1235 1236 if ( _session ) 1237 { 1238 DASessionRef session; 1239 1240 session = __DASessionListGetSession( _session ); 1241 1242 if ( session ) 1243 { 1244 DADiskRef disk; 1245 1246 DALogDebugHeader( "%@ -> %s", session, gDAProcessNameID ); 1247 1248 disk = __DADiskListGetDisk( _disk ); 1249 1250 if ( disk ) 1251 { 1252 status = DAAuthorize( session, _kDAAuthorizeOptionIsOwner, disk, _token.val[0], _token.val[1], _kDAAuthorizeRightEncode ); 1253 1254 if ( status == kDAReturnSuccess ) 1255 { 1256 DALogDebug( " set disk encoding, id = %@, encoding = %d.", disk, encoding ); 1257 1258 status = _DADiskSetEncoding( disk, encoding ); 1259 } 1260 } 1261 } 1262 } 1263 1264 if ( status ) 1265 { 1266 DALogDebug( "unable to set disk encoding, id = %s (status code 0x%08X).", _disk, status ); 1267 } 1268 1269 return status; 1270} 1271 1272kern_return_t _DAServerDiskSetOptions( mach_port_t _session, caddr_t _disk, int32_t _options, int32_t _value ) 1273{ 1274 kern_return_t status; 1275 1276 status = kDAReturnBadArgument; 1277 1278 DALogDebugHeader( "? [?]:%d -> %s", _session, gDAProcessNameID ); 1279 1280 if ( _session ) 1281 { 1282 DASessionRef session; 1283 1284 session = __DASessionListGetSession( _session ); 1285 1286 if ( session ) 1287 { 1288 DADiskRef disk; 1289 1290 DALogDebugHeader( "%@ -> %s", session, gDAProcessNameID ); 1291 1292 disk = __DADiskListGetDisk( _disk ); 1293 1294 if ( disk ) 1295 { 1296 DALogDebug( " set disk options, id = %@, options = 0x%08X, value = %s.", disk, _options, _value ? "true" : "false" ); 1297 1298 if ( DADiskGetState( disk, kDADiskStateStagedAppear ) ) 1299 { 1300 if ( ( _options & kDADiskOptionPrivate ) ) 1301 { 1302 if ( _value ) 1303 { 1304 if ( DADiskGetOption( disk, kDADiskOptionPrivate ) == FALSE ) 1305 { 1306 DADiskDisappearedCallback( disk ); 1307 1308 DAStageSignal( ); 1309 } 1310 } 1311 else 1312 { 1313 if ( DADiskGetOption( disk, kDADiskOptionPrivate ) ) 1314 { 1315 DADiskSetOption( disk, kDADiskOptionPrivate, FALSE ); 1316 1317 DADiskAppearedCallback( disk ); 1318 1319 DAStageSignal( ); 1320 } 1321 } 1322 } 1323 } 1324 1325 DADiskSetOptions( disk, _options, _value ); 1326 1327 status = kDAReturnSuccess; 1328 } 1329 } 1330 } 1331 1332 if ( status ) 1333 { 1334 DALogDebug( "unable to set disk options, id = %s (status code 0x%08X).", _disk, status ); 1335 } 1336 1337 return status; 1338} 1339 1340kern_return_t _DAServerDiskUnclaim( mach_port_t _session, caddr_t _disk ) 1341{ 1342 kern_return_t status; 1343 1344 status = kDAReturnBadArgument; 1345 1346 DALogDebugHeader( "? [?]:%d -> %s", _session, gDAProcessNameID ); 1347 1348 if ( _session ) 1349 { 1350 DASessionRef session; 1351 1352 session = __DASessionListGetSession( _session ); 1353 1354 if ( session ) 1355 { 1356 DADiskRef disk; 1357 1358 DALogDebugHeader( "%@ -> %s", session, gDAProcessNameID ); 1359 1360 disk = __DADiskListGetDisk( _disk ); 1361 1362 if ( disk ) 1363 { 1364 DACallbackRef callback; 1365 1366 callback = DADiskGetClaim( disk ); 1367 1368 if ( callback ) 1369 { 1370 if ( DACallbackGetSession( callback ) == session ) 1371 { 1372 DALogDebug( " unclaimed disk, id = %@.", disk ); 1373 1374 DADiskSetClaim( disk, NULL ); 1375 1376 status = kDAReturnSuccess; 1377 } 1378 } 1379 } 1380 } 1381 } 1382 1383 if ( status ) 1384 { 1385 DALogDebug( "unable to unclaim disk, id = %s (status code 0x%08X).", _disk, status ); 1386 } 1387 1388 return status; 1389} 1390 1391kern_return_t _DAServerSessionCopyCallbackQueue( mach_port_t _session, vm_address_t * _queue, mach_msg_type_number_t * _queueSize ) 1392{ 1393 kern_return_t status; 1394 1395 status = kDAReturnBadArgument; 1396 1397 DALogDebugHeader( "? [?]:%d -> %s", _session, gDAProcessNameID ); 1398 1399 if ( _session ) 1400 { 1401 DASessionRef session; 1402 1403 session = __DASessionListGetSession( _session ); 1404 1405 if ( session ) 1406 { 1407 CFMutableArrayRef callbacks; 1408 1409 DALogDebugHeader( "%s -> %@", gDAProcessNameID, session ); 1410 1411 callbacks = DASessionGetCallbackQueue( session ); 1412 1413 if ( callbacks ) 1414 { 1415 CFIndex count; 1416 CFIndex index; 1417 CFDataRef queue; 1418 1419 count = CFArrayGetCount( callbacks ); 1420 1421 for ( index = 0; index < count; index++ ) 1422 { 1423 DACallbackRef callback; 1424 1425 callback = ( void * ) CFArrayGetValueAtIndex( callbacks, index ); 1426 1427 DACallbackSetDisk( callback, NULL ); 1428 1429 DACallbackSetMatch( callback, NULL ); 1430 1431 DACallbackSetSession( callback, NULL ); 1432 } 1433 1434 queue = _DASerialize( kCFAllocatorDefault, callbacks ); 1435 1436 if ( queue ) 1437 { 1438 *_queue = ___CFDataCopyBytes( queue, _queueSize ); 1439 1440 if ( *_queue ) 1441 { 1442 DALogDebug( " dispatched callback queue." ); 1443 1444 status = kDAReturnSuccess; 1445 } 1446 1447 CFRelease( queue ); 1448 } 1449 1450 CFArrayRemoveAllValues( callbacks ); 1451 } 1452 1453 DASessionSetState( session, kDASessionStateTimeout, FALSE ); 1454 } 1455 } 1456 1457 if ( status ) 1458 { 1459 DALogDebug( "unable to copy callback queue (status code 0x%08X).", status ); 1460 } 1461 1462 return status; 1463} 1464 1465kern_return_t _DAServerSessionCreate( mach_port_t _session, 1466 caddr_t _name, 1467 pid_t _pid, 1468 mach_port_t * _server ) 1469{ 1470 kern_return_t status; 1471 1472 status = kDAReturnBadArgument; 1473 1474 DALogDebugHeader( "%s [%d] -> %s", _name, _pid, gDAProcessNameID ); 1475 1476 if ( _session ) 1477 { 1478 DASessionRef session; 1479 1480 /* 1481 * Create the session. 1482 */ 1483 1484 session = DASessionCreate( kCFAllocatorDefault, _name, _pid ); 1485 1486 if ( session ) 1487 { 1488 DALogDebugHeader( "%@ -> %s", session, gDAProcessNameID ); 1489 1490 DALogDebug( " created session, id = %@.", session ); 1491 1492 *_server = DASessionGetServerPort( session ); 1493 1494 /* 1495 * Add the session object to our tables. 1496 */ 1497 1498 ___vproc_transaction_begin( ); 1499 1500 CFArrayAppendValue( gDASessionList, session ); 1501 1502 /* 1503 * Add the session to our run loop. 1504 */ 1505 1506 DASessionScheduleWithRunLoop( session, CFRunLoopGetCurrent( ), kCFRunLoopDefaultMode ); 1507 1508 CFRelease( session ); 1509 1510 status = kDAReturnSuccess; 1511 } 1512 } 1513 1514 if ( status ) 1515 { 1516 DALogDebug( "unable to create session, id = %s [%d].", _name, _pid ); 1517 } 1518 1519 return status; 1520} 1521 1522kern_return_t _DAServerSessionQueueRequest( mach_port_t _session, 1523 int32_t _kind, 1524 caddr_t _argument0, 1525 int32_t _argument1, 1526 vm_address_t _argument2, 1527 mach_msg_type_number_t _argument2Size, 1528 vm_address_t _argument3, 1529 mach_msg_type_number_t _argument3Size, 1530 mach_vm_offset_t _address, 1531 mach_vm_offset_t _context, 1532 security_token_t _token ) 1533{ 1534 kern_return_t status; 1535 1536 status = kDAReturnBadArgument; 1537 1538 DALogDebugHeader( "? [?]:%d -> %s", _session, gDAProcessNameID ); 1539 1540 if ( _session ) 1541 { 1542 DASessionRef session; 1543 1544 session = __DASessionListGetSession( _session ); 1545 1546 if ( session ) 1547 { 1548 DADiskRef disk; 1549 1550 DALogDebugHeader( "%@ -> %s", session, gDAProcessNameID ); 1551 1552 disk = __DADiskListGetDisk( _argument0 ); 1553 1554 if ( disk ) 1555 { 1556 CFTypeRef argument2 = NULL; 1557 CFTypeRef argument3 = NULL; 1558 DACallbackRef callback; 1559 DARequestRef request; 1560 1561 DALogDebugHeader( "%@ -> %s", session, gDAProcessNameID ); 1562 1563 if ( _argument2 ) 1564 { 1565 argument2 = _DAUnserializeWithBytes( kCFAllocatorDefault, _argument2, _argument2Size ); 1566 } 1567 1568 if ( _argument3 ) 1569 { 1570 argument3 = _DAUnserializeWithBytes( kCFAllocatorDefault, _argument3, _argument3Size ); 1571 } 1572 1573 callback = DACallbackCreate( kCFAllocatorDefault, session, _address, _context, _kind, 0, NULL, NULL ); 1574 1575 request = DARequestCreate( kCFAllocatorDefault, _kind, disk, _argument1, argument2, argument3, _token.val[0], _token.val[1], callback ); 1576 1577 if ( request ) 1578 { 1579 switch ( _kind ) 1580 { 1581 case _kDADiskEject: 1582 { 1583 status = DAAuthorize( session, _kDAAuthorizeOptionIsOwner, disk, _token.val[0], _token.val[1], _kDAAuthorizeRightUnmount ); 1584 1585 break; 1586 } 1587 case _kDADiskMount: 1588 { 1589 status = DAAuthorize( session, _kDAAuthorizeOptionIsOwner, disk, _token.val[0], _token.val[1], _kDAAuthorizeRightMount ); 1590 1591 break; 1592 } 1593 case _kDADiskRename: 1594 { 1595 status = DAAuthorize( session, _kDAAuthorizeOptionIsOwner, disk, _token.val[0], _token.val[1], _kDAAuthorizeRightRename ); 1596 1597 break; 1598 } 1599 case _kDADiskUnmount: 1600 { 1601 status = DAAuthorize( session, _kDAAuthorizeOptionIsOwner, disk, _token.val[0], _token.val[1], _kDAAuthorizeRightUnmount ); 1602 1603 break; 1604 } 1605 default: 1606 { 1607 status = kDAReturnSuccess; 1608 1609 break; 1610 } 1611 } 1612 1613 if ( status == kDAReturnSuccess ) 1614 { 1615 DAQueueRequest( request ); 1616 1617 DALogDebug( " queued solicitation, id = %016llX:%016llX, kind = %s, disk = %@, options = 0x%08X.", 1618 _address, 1619 _context, 1620 _DARequestKindGetName( _kind ), 1621 disk, 1622 _argument1 ); 1623 } 1624 1625 CFRelease( request ); 1626 } 1627 1628 if ( callback ) 1629 { 1630 CFRelease( callback ); 1631 } 1632 1633 if ( argument2 ) 1634 { 1635 CFRelease( argument2 ); 1636 } 1637 1638 if ( argument3 ) 1639 { 1640 CFRelease( argument3 ); 1641 } 1642 } 1643 } 1644 } 1645 1646 if ( status ) 1647 { 1648 DALogDebug( "unable to queue solicitation, id = %016llX:%016llX, kind = %s, disk = %s (status code 0x%08X).", 1649 _address, 1650 _context, 1651 _DACallbackKindGetName( _kind ), 1652 _argument0, 1653 status ); 1654 } 1655 1656 return status; 1657} 1658 1659kern_return_t _DAServerSessionQueueResponse( mach_port_t _session, 1660 mach_vm_offset_t _address, 1661 mach_vm_offset_t _context, 1662 int32_t _kind, 1663 caddr_t _disk, 1664 vm_address_t _response, 1665 mach_msg_type_number_t _responseSize, 1666 int32_t _responseID ) 1667{ 1668 kern_return_t status; 1669 1670 status = kDAReturnBadArgument; 1671 1672 DALogDebugHeader( "? [?]:%d -> %s", _session, gDAProcessNameID ); 1673 1674 if ( _session ) 1675 { 1676 DASessionRef session; 1677 1678 session = __DASessionListGetSession( _session ); 1679 1680 if ( session ) 1681 { 1682 CFTypeRef response = NULL; 1683 1684 DALogDebugHeader( "%@ -> %s", session, gDAProcessNameID ); 1685 1686 if ( _response ) 1687 { 1688 response = _DAUnserializeWithBytes( kCFAllocatorDefault, _response, _responseSize ); 1689 } 1690 1691 if ( _DAResponseDispatch( response, _responseID ) == FALSE ) 1692 { 1693 DALogDebug( " dispatched response, id = %016llX:%016llX, kind = %s, disk = %s, orphaned.", _address, _context, _DACallbackKindGetName( _kind ), _disk ); 1694 } 1695 1696 if ( response ) 1697 { 1698 CFRelease( response ); 1699 } 1700 1701 status = kDAReturnSuccess; 1702 } 1703 } 1704 1705 if ( status ) 1706 { 1707 DALogDebug( "unable to dispatch response, id = %016llX:%016llX, disk = %s (status code 0x%08X).", _address, _context, _disk, status ); 1708 } 1709 1710 return status; 1711} 1712 1713kern_return_t _DAServerSessionRegisterCallback( mach_port_t _session, 1714 mach_vm_offset_t _address, 1715 mach_vm_offset_t _context, 1716 int32_t _kind, 1717 int32_t _order, 1718 vm_address_t _match, 1719 mach_msg_type_number_t _matchSize, 1720 vm_address_t _watch, 1721 mach_msg_type_number_t _watchSize ) 1722{ 1723 kern_return_t status; 1724 1725 status = kDAReturnBadArgument; 1726 1727 DALogDebugHeader( "? [?]:%d -> %s", _session, gDAProcessNameID ); 1728 1729 if ( _session ) 1730 { 1731 DASessionRef session; 1732 1733 session = __DASessionListGetSession( _session ); 1734 1735 if ( session ) 1736 { 1737 DACallbackRef callback; 1738 CFDictionaryRef match = NULL; 1739 CFArrayRef watch = NULL; 1740 1741 DALogDebugHeader( "%@ -> %s", session, gDAProcessNameID ); 1742 1743 if ( _match ) 1744 { 1745 match = _DAUnserializeDiskDescriptionWithBytes( kCFAllocatorDefault, _match, _matchSize ); 1746 } 1747 1748 if ( _watch ) 1749 { 1750 watch = _DAUnserializeWithBytes( kCFAllocatorDefault, _watch, _watchSize ); 1751 } 1752 1753 callback = DACallbackCreate( kCFAllocatorDefault, session, _address, _context, _kind, _order, match, watch ); 1754 1755 if ( callback ) 1756 { 1757 DASessionRegisterCallback( session, callback ); 1758 1759 DALogDebug( " registered callback, id = %016llX:%016llX, kind = %s.", _address, _context, _DACallbackKindGetName( _kind ) ); 1760 1761 if ( DACallbackGetKind( callback ) == _kDADiskAppearedCallback ) 1762 { 1763 CFIndex count; 1764 CFIndex index; 1765 1766 count = CFArrayGetCount( gDADiskList ); 1767 1768 for ( index = 0; index < count; index++ ) 1769 { 1770 DADiskRef disk; 1771 1772 disk = ( void * ) CFArrayGetValueAtIndex( gDADiskList, index ); 1773 1774 if ( DADiskGetState( disk, kDADiskStateStagedAppear ) ) 1775 { 1776 DAQueueCallback( callback, disk, NULL ); 1777 } 1778 } 1779 1780 if ( gDAIdle ) 1781 { 1782 DAQueueCallbacks( session, _kDAIdleCallback, NULL, NULL ); 1783 1784 DASessionSetState( session, kDASessionStateIdle, TRUE ); 1785 } 1786 } 1787 else if ( DACallbackGetKind( callback ) == _kDAIdleCallback ) 1788 { 1789 if ( gDAIdle ) 1790 { 1791 DAQueueCallback( callback, NULL, NULL ); 1792 1793 DASessionSetState( session, kDASessionStateIdle, TRUE ); 1794 } 1795 else 1796 { 1797 DASessionSetState( session, kDASessionStateIdle, FALSE ); 1798 } 1799 } 1800///w:start 1801 else if ( DACallbackGetKind( callback ) == _kDADiskEjectApprovalCallback ) 1802 { 1803 if ( strcmp( _DASessionGetName( session ), "SystemUIServer" ) == 0 ) 1804 { 1805 CFStringRef key; 1806 1807 key = SCDynamicStoreKeyCreateConsoleUser( kCFAllocatorDefault ); 1808 1809 if ( key ) 1810 { 1811 CFMutableArrayRef keys; 1812 1813 keys = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks ); 1814 1815 if ( keys ) 1816 { 1817 CFArrayAppendValue( keys, key ); 1818 1819 _DAConfigurationCallback( NULL, keys, NULL ); 1820 1821 CFRelease( keys ); 1822 } 1823 1824 CFRelease( key ); 1825 } 1826 } 1827 } 1828///w:stop 1829 1830 CFRelease( callback ); 1831 1832 status = kDAReturnSuccess; 1833 } 1834 1835 if ( match ) 1836 { 1837 CFRelease( match ); 1838 } 1839 1840 if ( watch ) 1841 { 1842 CFRelease( watch ); 1843 } 1844 } 1845 } 1846 1847 if ( status ) 1848 { 1849 DALogDebug( "unable to register callback, id = %016llX:%016llX, kind = %s (status code 0x%08X).", _address, _context, _DACallbackKindGetName( _kind ), status ); 1850 } 1851 1852 return status; 1853} 1854 1855kern_return_t _DAServerSessionRelease( mach_port_t _session ) 1856{ 1857 kern_return_t status; 1858 1859 status = kDAReturnBadArgument; 1860 1861 DALogDebugHeader( "? [?]:%d -> %s", _session, gDAProcessNameID ); 1862 1863 if ( _session ) 1864 { 1865 DASessionRef session; 1866 1867 session = __DASessionListGetSession( _session ); 1868 1869 if ( session ) 1870 { 1871 CFMutableArrayRef callbacks; 1872 1873 DALogDebugHeader( "%@ -> %s", session, gDAProcessNameID ); 1874 1875 DALogDebug( " removed session, id = %@.", session ); 1876 1877 callbacks = DASessionGetCallbackQueue( session ); 1878 1879 if ( callbacks ) 1880 { 1881 CFArrayRemoveAllValues( callbacks ); 1882 } 1883 1884 callbacks = DASessionGetCallbackRegister( session ); 1885 1886 if ( callbacks ) 1887 { 1888 CFArrayRemoveAllValues( callbacks ); 1889 } 1890 1891 DAQueueReleaseSession( session ); 1892 1893 /* 1894 * Remove the session from our run loop. 1895 */ 1896 1897 DASessionUnscheduleFromRunLoop( session, CFRunLoopGetCurrent( ), kCFRunLoopDefaultMode ); 1898 1899 /* 1900 * Remove the session object from our tables. 1901 */ 1902 1903 DASessionSetState( session, kDASessionStateZombie, TRUE ); 1904 1905 ___CFArrayRemoveValue( gDASessionList, session ); 1906 1907 ___vproc_transaction_end( ); 1908 1909 status = kDAReturnSuccess; 1910 } 1911 } 1912 1913 if ( status ) 1914 { 1915 DALogDebug( "unable to release session, id = ? [?]:%d.", _session ); 1916 } 1917 1918 return status; 1919} 1920 1921kern_return_t _DAServerSessionSetAuthorization( mach_port_t _session, AuthorizationExternalForm _authorization ) 1922{ 1923 kern_return_t status; 1924 1925 status = kDAReturnBadArgument; 1926 1927 DALogDebugHeader( "? [?]:%d -> %s", _session, gDAProcessNameID ); 1928 1929 if ( _session ) 1930 { 1931 DASessionRef session; 1932 1933 session = __DASessionListGetSession( _session ); 1934 1935 if ( session ) 1936 { 1937 AuthorizationRef authorization; 1938 1939 DALogDebugHeader( "%@ -> %s", session, gDAProcessNameID ); 1940 1941 status = AuthorizationCreateFromExternalForm( &_authorization, &authorization ); 1942 1943 if ( status == errAuthorizationSuccess ) 1944 { 1945 DASessionSetAuthorization( session, authorization ); 1946 1947 DALogDebug( " set authorization, id = %@.", session ); 1948 1949 status = kDAReturnSuccess; 1950 } 1951 } 1952 } 1953 1954 if ( status ) 1955 { 1956 DALogDebug( "unable to set authorization, id = ? [?]:%d.", _session ); 1957 } 1958 1959 return status; 1960} 1961 1962kern_return_t _DAServerSessionSetClientPort( mach_port_t _session, mach_port_t _client ) 1963{ 1964 kern_return_t status; 1965 1966 status = kDAReturnBadArgument; 1967 1968 DALogDebugHeader( "? [?]:%d -> %s", _session, gDAProcessNameID ); 1969 1970 if ( _session ) 1971 { 1972 DASessionRef session; 1973 1974 session = __DASessionListGetSession( _session ); 1975 1976 if ( session ) 1977 { 1978 DALogDebugHeader( "%@ -> %s", session, gDAProcessNameID ); 1979 1980 DASessionSetClientPort( session, _client ); 1981 1982 DALogDebug( " set client port, id = %@.", session ); 1983 1984 status = kDAReturnSuccess; 1985 } 1986 } 1987 1988 if ( status ) 1989 { 1990 DALogDebug( "unable to set client port, id = ? [?]:%d.", _session ); 1991 } 1992 1993 return status; 1994} 1995 1996kern_return_t _DAServerSessionUnregisterCallback( mach_port_t _session, mach_vm_offset_t _address, mach_vm_offset_t _context ) 1997{ 1998 kern_return_t status; 1999 2000 status = kDAReturnBadArgument; 2001 2002 DALogDebugHeader( "? [?]:%d -> %s", _session, gDAProcessNameID ); 2003 2004 if ( _session ) 2005 { 2006 DASessionRef session; 2007 2008 session = __DASessionListGetSession( _session ); 2009 2010 if ( session ) 2011 { 2012 DACallbackRef callback; 2013 2014 DALogDebugHeader( "%@ -> %s", session, gDAProcessNameID ); 2015 2016 callback = DACallbackCreate( kCFAllocatorDefault, session, _address, _context, 0, 0, NULL, NULL ); 2017 2018 if ( callback ) 2019 { 2020 DAQueueUnregisterCallback( callback ); 2021 2022 DASessionUnregisterCallback( session, callback ); 2023 2024 DALogDebug( " unregistered callback, id = %016llX:%016llX.", _address, _context ); 2025 2026 CFRelease( callback ); 2027 2028 status = kDAReturnSuccess; 2029 } 2030 } 2031 } 2032 2033 if ( status ) 2034 { 2035 DALogDebug( "unable to unregister callback, id = %016llX:%016llX (status code 0x%08X).", _address, _context, status ); 2036 } 2037 2038 return status; 2039} 2040 2041void _DAVolumeMountedCallback( CFMachPortRef port, void * parameter, CFIndex messageSize, void * info ) 2042{ 2043 struct statfs * mountList; 2044 int mountListCount; 2045 int mountListIndex; 2046 2047 mountListCount = getmntinfo( &mountList, MNT_NOWAIT ); 2048 2049 for ( mountListIndex = 0; mountListIndex < mountListCount; mountListIndex++ ) 2050 { 2051 DADiskRef disk; 2052 2053 disk = __DADiskListGetDisk( _DAVolumeGetID( mountList + mountListIndex ) ); 2054 2055 if ( disk ) 2056 { 2057 if ( DADiskGetDescription( disk, kDADiskDescriptionVolumePathKey ) == NULL ) 2058 { 2059///w:start 2060 if ( DADiskGetDescription( disk, kDADiskDescriptionVolumeMountableKey ) == kCFBooleanFalse ) 2061 { 2062 DADiskProbe( disk, NULL ); 2063 } 2064///w:stop 2065 DADiskRefresh( disk, NULL ); 2066 } 2067 } 2068 else 2069 { 2070///w:start 2071 if ( strncmp( mountList[mountListIndex].f_mntfromname, _PATH_DEV "disk", strlen( _PATH_DEV "disk" ) ) ) 2072///w:stop 2073 if ( ( mountList[mountListIndex].f_flags & MNT_UNION ) == 0 ) 2074 { 2075 if ( strcmp( mountList[mountListIndex].f_fstypename, "devfs" ) ) 2076 { 2077 disk = DADiskCreateFromVolumePath( kCFAllocatorDefault, mountList + mountListIndex ); 2078 2079 if ( disk ) 2080 { 2081 DALogDebugHeader( "bsd [0] -> %s", gDAProcessNameID ); 2082 2083 DALogDebug( " created disk, id = %@.", disk ); 2084 2085 CFArrayInsertValueAtIndex( gDADiskList, 0, disk ); 2086 2087 DAStageSignal( ); 2088 2089 CFRelease( disk ); 2090 } 2091 } 2092 } 2093 } 2094 } 2095} 2096 2097void _DAVolumeUnmountedCallback( CFMachPortRef port, void * parameter, CFIndex messageSize, void * info ) 2098{ 2099 CFIndex count; 2100 CFIndex index; 2101 2102 count = CFArrayGetCount( gDADiskList ); 2103 2104 for ( index = 0; index < count; index++ ) 2105 { 2106 DADiskRef disk; 2107 2108 disk = ( void * ) CFArrayGetValueAtIndex( gDADiskList, index ); 2109 2110 if ( DADiskGetDescription( disk, kDADiskDescriptionVolumePathKey ) ) 2111 { 2112 DADiskRefresh( disk, NULL ); 2113 } 2114 } 2115} 2116 2117CFRunLoopSourceRef DAServerCreateRunLoopSource( CFAllocatorRef allocator, CFIndex order ) 2118{ 2119 /* 2120 * Create a CFRunLoopSource for DAServer remote procedure calls. 2121 */ 2122 2123 CFRunLoopSourceRef source = NULL; 2124 2125 /* 2126 * Initialize our minimal state. 2127 */ 2128 2129 if ( __gDAServer == NULL ) 2130 { 2131 /* 2132 * Register the Disk Arbitration master port. 2133 */ 2134 2135 if ( __gDAServerPort == MACH_PORT_NULL ) 2136 { 2137 bootstrap_check_in( bootstrap_port, _kDADaemonName, &__gDAServerPort ); 2138 } 2139 2140 if ( __gDAServerPort ) 2141 { 2142 /* 2143 * Create the Disk Arbitration master port. 2144 */ 2145 2146 __gDAServer = CFMachPortCreateWithPort( allocator, __gDAServerPort, _DAServerCallback, NULL, NULL ); 2147 2148 if ( __gDAServer ) 2149 { 2150 __gDAServerReply = malloc( DAServer_subsystem.maxsize ); 2151 2152 assert( __gDAServerReply ); 2153 } 2154 } 2155 } 2156 2157 /* 2158 * Obtain the CFRunLoopSource for our CFMachPort. 2159 */ 2160 2161 if ( __gDAServer ) 2162 { 2163 source = CFMachPortCreateRunLoopSource( allocator, __gDAServer, order ); 2164 } 2165 2166 return source; 2167} 2168