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 "DAQueue.h" 25 26#include "DABase.h" 27#include "DACallback.h" 28#include "DAInternal.h" 29#include "DALog.h" 30#include "DAMain.h" 31#include "DARequest.h" 32#include "DASession.h" 33#include "DAStage.h" 34 35struct __DAResponseContext 36{ 37 DAResponseCallback callback; 38 void * callbackContext; 39 CFTypeRef response; 40}; 41 42typedef struct __DAResponseContext __DAResponseContext; 43 44const CFGregorianUnits __kDAResponseTimerGrace = { 0, 0, 0, 0, 0, 1 }; 45const CFGregorianUnits __kDAResponseTimerLimit = { 0, 0, 0, 0, 0, 10 }; 46 47static void __DAResponseTimerRefresh( void ); 48 49static void __DAQueueCallbacks( _DACallbackKind kind, DADiskRef argument0, CFTypeRef argument1 ) 50{ 51 CFIndex count; 52 CFIndex index; 53 54 count = CFArrayGetCount( gDASessionList ); 55 56 for ( index = 0; index < count; index++ ) 57 { 58 DASessionRef session; 59 60 session = ( void * ) CFArrayGetValueAtIndex( gDASessionList, index ); 61 62 if ( kind == _kDAIdleCallback ) 63 { 64 if ( DASessionGetState( session, kDASessionStateIdle ) ) 65 { 66 continue; 67 } 68 } 69 70 DAQueueCallbacks( session, kind, argument0, argument1 ); 71 72 if ( kind == _kDAIdleCallback ) 73 { 74 DASessionSetState( session, kDASessionStateIdle, TRUE ); 75 } 76 } 77} 78 79static void __DAQueueRequest( _DARequestKind kind, DADiskRef argument0, CFIndex argument1, CFTypeRef argument2, CFTypeRef argument3, DACallbackRef callback ) 80{ 81 DARequestRef request; 82 83///w:start 84 if ( kind == _kDADiskMount ) 85 { 86 request = DARequestCreate( kCFAllocatorDefault, kind, argument0, argument1, argument2, argument3, ___UID_UNKNOWN, ___GID_UNKNOWN, callback ); 87 } 88 else 89///w:stop 90 request = DARequestCreate( kCFAllocatorDefault, kind, argument0, argument1, argument2, argument3, ___UID_ROOT, ___GID_WHEEL, callback ); 91 92 if ( request ) 93 { 94 DAQueueRequest( request ); 95 96 CFRelease( request ); 97 } 98} 99 100static void __DAResponseComplete( DADiskRef disk ) 101{ 102 CFIndex count; 103 CFIndex index; 104 105 count = CFArrayGetCount( gDAResponseList ); 106 107 for ( index = 0; index < count; index++ ) 108 { 109 DACallbackRef callback; 110 111 callback = ( void * ) CFArrayGetValueAtIndex( gDAResponseList, index ); 112 113 if ( DACallbackGetDisk( callback ) == disk ) 114 { 115 break; 116 } 117 } 118 119 if ( index == count ) 120 { 121 __DAResponseContext context; 122 123 context = *( ( __DAResponseContext * ) CFDataGetBytePtr( DADiskGetContextRe( disk ) ) ); 124 125 DADiskSetContextRe( disk, NULL ); 126 127 ( context.callback )( context.response, context.callbackContext ); 128 129 if ( context.response ) CFRelease( context.response ); 130 } 131 132 __DAResponseTimerRefresh( ); 133} 134 135static void __DAResponsePrepare( DADiskRef disk, DAResponseCallback callback, void * callbackContext ) 136{ 137 CFDataRef data; 138 139 data = CFDataCreateMutable( kCFAllocatorDefault, sizeof( __DAResponseContext ) ); 140 141 if ( data ) 142 { 143 __DAResponseContext * context; 144 145 context = ( void * ) CFDataGetBytePtr( data ); 146 147 bzero( context, sizeof( __DAResponseContext ) ); 148 149 context->callback = callback; 150 context->callbackContext = callbackContext; 151 152 DADiskSetContextRe( disk, data ); 153 154 CFRelease( data ); 155 } 156} 157 158static void __DAResponseTimerCallback( CFRunLoopTimerRef timer, void * info ) 159{ 160 CFAbsoluteTime clock; 161 CFIndex count; 162 CFIndex index; 163 164 clock = CFAbsoluteTimeGetCurrent( ); 165 166 count = CFArrayGetCount( gDAResponseList ); 167 168 for ( index = count - 1; index > -1; index-- ) 169 { 170 DACallbackRef callback; 171 172 callback = ( void * ) CFArrayGetValueAtIndex( gDAResponseList, index ); 173 174 if ( callback ) 175 { 176 DASessionRef session; 177 178 session = DACallbackGetSession( callback ); 179 180 if ( DASessionGetOption( session, kDASessionOptionNoTimeout ) == FALSE ) 181 { 182 CFAbsoluteTime timeout; 183 184 timeout = DACallbackGetTime( callback ); 185 186 timeout = CFAbsoluteTimeAddGregorianUnits( timeout, NULL, __kDAResponseTimerLimit ); 187 188 if ( timeout < clock ) 189 { 190 DADiskRef disk; 191 192 disk = DACallbackGetDisk( callback ); 193 194 if ( DASessionGetState( session, kDASessionStateTimeout ) == FALSE ) 195 { 196 DALogDebugHeader( "%s -> %s", gDAProcessNameID, gDAProcessNameID ); 197 198 DALogDebug( " timed out session, id = %@.", session ); 199 200 DALogError( "%@ not responding.", session ); 201 202 DASessionSetState( session, kDASessionStateTimeout, TRUE ); 203 } 204 205 CFRetain( disk ); 206 207 CFArrayRemoveValueAtIndex( gDAResponseList, index ); 208 209 __DAResponseComplete( disk ); 210 211 CFRelease( disk ); 212 } 213 } 214 } 215 } 216} 217 218static void __DAResponseTimerRefresh( void ) 219{ 220 static CFRunLoopTimerRef timer = NULL; 221 222 CFAbsoluteTime clock; 223 CFIndex count; 224 CFIndex index; 225 226 clock = kCFAbsoluteTimeIntervalSince1904; 227 228 count = CFArrayGetCount( gDAResponseList ); 229 230 for ( index = 0; index < count; index++ ) 231 { 232 DACallbackRef callback; 233 234 callback = ( void * ) CFArrayGetValueAtIndex( gDAResponseList, index ); 235 236 if ( callback ) 237 { 238 DASessionRef session; 239 240 session = DACallbackGetSession( callback ); 241 242 if ( DASessionGetOption( session, kDASessionOptionNoTimeout ) == FALSE ) 243 { 244 CFAbsoluteTime timeout; 245 246 timeout = DACallbackGetTime( callback ); 247 248 timeout = CFAbsoluteTimeAddGregorianUnits( timeout, NULL, __kDAResponseTimerLimit ); 249 250 if ( timeout < clock ) 251 { 252 clock = timeout; 253 } 254 } 255 } 256 } 257 258 clock = CFAbsoluteTimeAddGregorianUnits( clock, NULL, __kDAResponseTimerGrace ); 259 260 if ( timer ) 261 { 262 CFRunLoopTimerSetNextFireDate( timer, clock ); 263 } 264 else 265 { 266 timer = CFRunLoopTimerCreate( kCFAllocatorDefault, clock, kCFAbsoluteTimeIntervalSince1904, 0, 0, __DAResponseTimerCallback, NULL ); 267 268 if ( timer ) 269 { 270 CFRunLoopAddTimer( CFRunLoopGetCurrent( ), timer, kCFRunLoopDefaultMode ); 271 } 272 } 273} 274 275Boolean _DAResponseDispatch( CFTypeRef response, SInt32 responseID ) 276{ 277 CFIndex count; 278 CFIndex index; 279 280 count = CFArrayGetCount( gDAResponseList ); 281 282 for ( index = 0; index < count; index++ ) 283 { 284 DACallbackRef callback; 285 286 callback = ( void * ) CFArrayGetValueAtIndex( gDAResponseList, index ); 287 288 if ( ___CFNumberGetIntegerValue( DACallbackGetArgument1( callback ) ) == responseID ) 289 { 290 DADiskRef disk; 291 292 disk = DACallbackGetDisk( callback ); 293 294 switch ( DACallbackGetKind( callback ) ) 295 { 296 case _kDADiskClaimReleaseCallback: 297 case _kDADiskEjectApprovalCallback: 298 case _kDADiskMountApprovalCallback: 299 case _kDADiskUnmountApprovalCallback: 300 { 301 DADissenterRef dissenter; 302 303 dissenter = ( void * ) response; 304 305 if ( dissenter ) 306 { 307 CFDataRef data; 308 309 data = DADiskGetContextRe( disk ); 310 311 if ( data ) 312 { 313 __DAResponseContext * context; 314 315 context = ( void * ) CFDataGetBytePtr( data ); 316 317 if ( context->response == NULL ) 318 { 319 context->response = CFRetain( dissenter ); 320 } 321 } 322 323 DALogDebug( " dispatched response, id = %016llX:%016llX, kind = %s, disk = %@, dissented, status = 0x%08X.", 324 DACallbackGetAddress( callback ), 325 DACallbackGetContext( callback ), 326 _DACallbackKindGetName( DACallbackGetKind( callback ) ), 327 disk, 328 DADissenterGetStatus( dissenter ) ); 329 } 330 else 331 { 332 DALogDebug( " dispatched response, id = %016llX:%016llX, kind = %s, disk = %@, approved.", 333 DACallbackGetAddress( callback ), 334 DACallbackGetContext( callback ), 335 _DACallbackKindGetName( DACallbackGetKind( callback ) ), 336 disk ); 337 } 338 339 break; 340 } 341 case _kDADiskPeekCallback: 342 { 343 DALogDebug( " dispatched response, id = %016llX:%016llX, kind = %s, disk = %@.", 344 DACallbackGetAddress( callback ), 345 DACallbackGetContext( callback ), 346 _DACallbackKindGetName( DACallbackGetKind( callback ) ), 347 disk ); 348 349 break; 350 } 351 } 352 353 CFArrayRemoveValueAtIndex( gDAResponseList, index ); 354 355 __DAResponseComplete( disk ); 356 357 break; 358 } 359 } 360 361 return ( index < count ) ? TRUE : FALSE; 362} 363 364void DADiskAppearedCallback( DADiskRef disk ) 365{ 366 __DAQueueCallbacks( _kDADiskAppearedCallback, disk, NULL ); 367} 368 369void DADiskClaimReleaseCallback( DADiskRef disk, DACallbackRef callback, DAResponseCallback response, void * responseContext ) 370{ 371 __DAResponsePrepare( disk, response, responseContext ); 372 373 DAQueueCallback( callback, disk, NULL ); 374 375 __DAResponseComplete( disk ); 376} 377 378void DADiskDescriptionChangedCallback( DADiskRef disk, CFTypeRef key ) 379{ 380 if ( CFGetTypeID( key ) == CFArrayGetTypeID( ) ) 381 { 382 __DAQueueCallbacks( _kDADiskDescriptionChangedCallback, disk, key ); 383 } 384 else 385 { 386 CFMutableArrayRef keys; 387 388 keys = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks ); 389 390 CFArrayAppendValue( keys, key ); 391 392 __DAQueueCallbacks( _kDADiskDescriptionChangedCallback, disk, keys ); 393 394 CFRelease( keys ); 395 } 396} 397 398void DADiskDisappearedCallback( DADiskRef disk ) 399{ 400 __DAQueueCallbacks( _kDADiskDisappearedCallback, disk, NULL ); 401} 402 403void DADiskEject( DADiskRef disk, DADiskEjectOptions options, DACallbackRef callback ) 404{ 405 __DAQueueRequest( _kDADiskEject, disk, options, NULL, NULL, callback ); 406} 407 408void DADiskEjectApprovalCallback( DADiskRef disk, DAResponseCallback response, void * responseContext ) 409{ 410 __DAResponsePrepare( disk, response, responseContext ); 411 412 __DAQueueCallbacks( _kDADiskEjectApprovalCallback, disk, NULL ); 413 414 __DAResponseComplete( disk ); 415} 416 417void DADiskMount( DADiskRef disk, CFURLRef mountpoint, DADiskMountOptions options, DACallbackRef callback ) 418{ 419 DADiskMountWithArguments( disk, mountpoint, options, callback, NULL ); 420} 421 422void DADiskMountApprovalCallback( DADiskRef disk, DAResponseCallback response, void * responseContext ) 423{ 424 __DAResponsePrepare( disk, response, responseContext ); 425 426 __DAQueueCallbacks( _kDADiskMountApprovalCallback, disk, NULL ); 427 428 __DAResponseComplete( disk ); 429} 430 431void DADiskMountWithArguments( DADiskRef disk, CFURLRef mountpoint, DADiskMountOptions options, DACallbackRef callback, CFStringRef arguments ) 432{ 433 __DAQueueRequest( _kDADiskMount, disk, options, mountpoint, arguments, callback ); 434} 435 436void DADiskPeekCallback( DADiskRef disk, DACallbackRef callback, DAResponseCallback response, void * responseContext ) 437{ 438 __DAResponsePrepare( disk, response, responseContext ); 439 440 DAQueueCallback( callback, disk, NULL ); 441 442 __DAResponseComplete( disk ); 443} 444 445void DADiskProbe( DADiskRef disk, DACallbackRef callback ) 446{ 447 __DAQueueRequest( _kDADiskProbe, disk, 0, NULL, NULL, callback ); 448} 449 450void DADiskRefresh( DADiskRef disk, DACallbackRef callback ) 451{ 452 __DAQueueRequest( _kDADiskRefresh, disk, 0, NULL, NULL, callback ); 453} 454 455void DADiskUnmount( DADiskRef disk, DADiskUnmountOptions options, DACallbackRef callback ) 456{ 457 __DAQueueRequest( _kDADiskUnmount, disk, options, NULL, NULL, callback ); 458} 459 460void DADiskUnmountApprovalCallback( DADiskRef disk, DAResponseCallback response, void * responseContext ) 461{ 462 __DAResponsePrepare( disk, response, responseContext ); 463 464 __DAQueueCallbacks( _kDADiskUnmountApprovalCallback, disk, NULL ); 465 466 __DAResponseComplete( disk ); 467} 468 469void DAIdleCallback( void ) 470{ 471 __DAQueueCallbacks( _kDAIdleCallback, NULL, NULL ); 472} 473 474void DAQueueCallback( DACallbackRef callback, DADiskRef argument0, CFTypeRef argument1 ) 475{ 476 static SInt32 responseID = 0; 477 478 DASessionRef session; 479 480 session = DACallbackGetSession( callback ); 481 482 DALogDebugHeader( "%s -> %@", gDAProcessNameID, session ); 483 484 if ( DASessionGetState( session, kDASessionStateZombie ) == FALSE ) 485 { 486 if ( DACallbackGetAddress( callback ) ) 487 { 488 CFDictionaryRef match; 489 490 match = DACallbackGetMatch( callback ); 491 492 if ( match ) 493 { 494 if ( DADiskMatch( argument0, match ) == FALSE ) 495 { 496 return; 497 } 498 } 499 500 switch ( DACallbackGetKind( callback ) ) 501 { 502 case _kDADiskAppearedCallback: 503 case _kDADiskDisappearedCallback: 504 { 505 if ( DADiskGetOption( argument0, kDADiskOptionPrivate ) == FALSE ) 506 { 507 callback = DACallbackCreateCopy( kCFAllocatorDefault, callback ); 508 509 if ( callback ) 510 { 511 DACallbackSetDisk( callback, argument0 ); 512 513 DACallbackSetArgument0( callback, DADiskGetSerialization( argument0 ) ); 514 515 DASessionQueueCallback( session, callback ); 516 517 DALogDebug( " dispatched callback, id = %016llX:%016llX, kind = %s, disk = %@.", 518 DACallbackGetAddress( callback ), 519 DACallbackGetContext( callback ), 520 _DACallbackKindGetName( DACallbackGetKind( callback ) ), 521 argument0 ); 522 523 CFRelease( callback ); 524 } 525 } 526 527 break; 528 } 529 case _kDADiskClaimCallback: 530 case _kDADiskEjectCallback: 531 case _kDADiskMountCallback: 532 case _kDADiskRenameCallback: 533 case _kDADiskUnmountCallback: 534 { 535 DACallbackSetDisk( callback, argument0 ); 536 537 DACallbackSetArgument0( callback, DADiskGetSerialization( argument0 ) ); 538 539 DACallbackSetArgument1( callback, argument1 ); 540 541 DASessionQueueCallback( session, callback ); 542 543 if ( argument1 ) 544 { 545 DALogDebug( " dispatched callback, id = %016llX:%016llX, kind = %s, disk = %@, status = 0x%08X.", 546 DACallbackGetAddress( callback ), 547 DACallbackGetContext( callback ), 548 _DACallbackKindGetName( DACallbackGetKind( callback ) ), 549 argument0, 550 DADissenterGetStatus( argument1 ) ); 551 } 552 else 553 { 554 DALogDebug( " dispatched callback, id = %016llX:%016llX, kind = %s, disk = %@, success.", 555 DACallbackGetAddress( callback ), 556 DACallbackGetContext( callback ), 557 _DACallbackKindGetName( DACallbackGetKind( callback ) ), 558 argument0 ); 559 } 560 561 break; 562 } 563 case _kDADiskClaimReleaseCallback: 564 { 565 if ( DASessionGetState( session, kDASessionStateTimeout ) == FALSE ) 566 { 567 assert( argument1 == NULL ); 568 569 argument1 = ___CFNumberCreateWithIntegerValue( kCFAllocatorDefault, responseID ); 570 571 if ( argument1 ) 572 { 573 DACallbackRef response; 574 575 response = DACallbackCreateCopy( kCFAllocatorDefault, callback ); 576 577 if ( response ) 578 { 579 DACallbackSetDisk( response, argument0 ); 580 581 DACallbackSetArgument1( response, argument1 ); 582 583 DACallbackSetTime( response, CFAbsoluteTimeGetCurrent( ) ); 584 585 CFArrayAppendValue( gDAResponseList, response ); 586 587 CFRelease( response ); 588 } 589 590 callback = DACallbackCreateCopy( kCFAllocatorDefault, callback ); 591 592 if ( callback ) 593 { 594 DACallbackSetDisk( callback, argument0 ); 595 596 DACallbackSetArgument0( callback, DADiskGetSerialization( argument0 ) ); 597 598 DACallbackSetArgument1( callback, argument1 ); 599 600 DASessionQueueCallback( session, callback ); 601 602 DALogDebug( " dispatched callback, id = %016llX:%016llX, kind = %s, disk = %@.", 603 DACallbackGetAddress( callback ), 604 DACallbackGetContext( callback ), 605 _DACallbackKindGetName( DACallbackGetKind( callback ) ), 606 argument0 ); 607 608 CFRelease( callback ); 609 } 610 611 CFRelease( argument1 ); 612 } 613 614 responseID++; 615 } 616 617 break; 618 } 619 case _kDADiskEjectApprovalCallback: 620 case _kDADiskMountApprovalCallback: 621 case _kDADiskPeekCallback: 622 case _kDADiskUnmountApprovalCallback: 623 { 624 if ( DASessionGetState( session, kDASessionStateTimeout ) == FALSE ) 625 { 626 if ( DADiskGetOption( argument0, kDADiskOptionPrivate ) == FALSE ) 627 { 628 assert( argument1 == NULL ); 629 630 argument1 = ___CFNumberCreateWithIntegerValue( kCFAllocatorDefault, responseID ); 631 632 if ( argument1 ) 633 { 634 DACallbackRef response; 635 636 response = DACallbackCreateCopy( kCFAllocatorDefault, callback ); 637 638 if ( response ) 639 { 640 DACallbackSetDisk( response, argument0 ); 641 642 DACallbackSetArgument1( response, argument1 ); 643 644 DACallbackSetTime( response, CFAbsoluteTimeGetCurrent( ) ); 645 646 CFArrayAppendValue( gDAResponseList, response ); 647 648 CFRelease( response ); 649 } 650 651 callback = DACallbackCreateCopy( kCFAllocatorDefault, callback ); 652 653 if ( callback ) 654 { 655 DACallbackSetDisk( callback, argument0 ); 656 657 DACallbackSetArgument0( callback, DADiskGetSerialization( argument0 ) ); 658 659 DACallbackSetArgument1( callback, argument1 ); 660 661 DASessionQueueCallback( session, callback ); 662 663 DALogDebug( " dispatched callback, id = %016llX:%016llX, kind = %s, disk = %@.", 664 DACallbackGetAddress( callback ), 665 DACallbackGetContext( callback ), 666 _DACallbackKindGetName( DACallbackGetKind( callback ) ), 667 argument0 ); 668 669 CFRelease( callback ); 670 } 671 672 CFRelease( argument1 ); 673 } 674 675 responseID++; 676 } 677 } 678 679 break; 680 } 681 case _kDADiskDescriptionChangedCallback: 682 { 683 if ( DADiskGetState( argument0, kDADiskStateZombie ) == FALSE ) 684 { 685 CFMutableArrayRef intersection; 686 687 if ( DADiskGetOption( argument0, kDADiskOptionPrivate ) == FALSE ) 688 { 689 CFArrayRef watch; 690 691 watch = DACallbackGetWatch( callback ); 692 693 if ( watch ) 694 { 695 intersection = CFArrayCreateMutableCopy( kCFAllocatorDefault, 0, argument1 ); 696 697 if ( intersection ) 698 { 699 ___CFArrayIntersect( intersection, watch ); 700 } 701 } 702 else 703 { 704 intersection = ( void * ) CFRetain( argument1 ); 705 } 706 707 if ( intersection ) 708 { 709 if ( CFArrayGetCount( intersection ) ) 710 { 711 callback = DACallbackCreateCopy( kCFAllocatorDefault, callback ); 712 713 if ( callback ) 714 { 715 CFIndex count; 716 CFIndex index; 717 718 count = CFArrayGetCount( intersection ); 719 720 for ( index = 0; index < count; index++ ) 721 { 722 DALogDebug( " dispatched callback, id = %016llX:%016llX, kind = %s, disk = %@, key = %@.", 723 DACallbackGetAddress( callback ), 724 DACallbackGetContext( callback ), 725 _DACallbackKindGetName( DACallbackGetKind( callback ) ), 726 argument0, 727 CFArrayGetValueAtIndex( intersection, index ) ); 728 } 729 730 DACallbackSetDisk( callback, argument0 ); 731 732 DACallbackSetArgument0( callback, DADiskGetSerialization( argument0 ) ); 733 734 DACallbackSetArgument1( callback, intersection ); 735 736 DASessionQueueCallback( session, callback ); 737 738 CFRelease( callback ); 739 } 740 } 741 742 CFRelease( intersection ); 743 } 744 } 745 } 746 747 break; 748 } 749 case _kDAIdleCallback: 750 { 751 callback = DACallbackCreateCopy( kCFAllocatorDefault, callback ); 752 753 if ( callback ) 754 { 755 DASessionQueueCallback( session, callback ); 756 757 DALogDebug( " dispatched callback, id = %016llX:%016llX, kind = %s.", 758 DACallbackGetAddress( callback ), 759 DACallbackGetContext( callback ), 760 _DACallbackKindGetName( DACallbackGetKind( callback ) ) ); 761 762 CFRelease( callback ); 763 } 764 765 break; 766 } 767 } 768 } 769 } 770} 771 772void DAQueueCallbacks( DASessionRef session, _DACallbackKind kind, DADiskRef argument0, CFTypeRef argument1 ) 773{ 774 CFArrayRef callbacks; 775 776 callbacks = DASessionGetCallbackRegister( session ); 777 778 if ( callbacks ) 779 { 780 CFIndex count; 781 CFIndex index; 782 783 count = CFArrayGetCount( callbacks ); 784 785 for ( index = 0; index < count; index++ ) 786 { 787 DACallbackRef callback; 788 789 callback = ( void * ) CFArrayGetValueAtIndex( callbacks, index ); 790 791 if ( DACallbackGetKind( callback ) == kind ) 792 { 793 DAQueueCallback( callback, argument0, argument1 ); 794 } 795 } 796 } 797} 798 799void DAQueueReleaseDisk( DADiskRef disk ) 800{ 801 CFIndex count; 802 CFIndex index; 803 804 count = CFArrayGetCount( gDAResponseList ); 805 806 for ( index = count - 1; index > -1; index-- ) 807 { 808 DACallbackRef callback; 809 810 callback = ( void * ) CFArrayGetValueAtIndex( gDAResponseList, index ); 811 812 if ( DACallbackGetDisk( callback ) == disk ) 813 { 814 CFArrayRemoveValueAtIndex( gDAResponseList, index ); 815 816 __DAResponseComplete( disk ); 817 } 818 } 819 820 count = CFArrayGetCount( gDARequestList ); 821 822 for ( index = count - 1; index > -1; index-- ) 823 { 824 DARequestRef request; 825 826 request = ( void * ) CFArrayGetValueAtIndex( gDARequestList, index ); 827 828 if ( DARequestGetDisk( request ) == disk ) 829 { 830 DARequestDispatchCallback( request, kDAReturnNotFound ); 831 832 CFArrayRemoveValueAtIndex( gDARequestList, index ); 833 } 834 } 835} 836 837void DAQueueReleaseSession( DASessionRef session ) 838{ 839 CFIndex count; 840 CFIndex index; 841 842 count = CFArrayGetCount( gDAResponseList ); 843 844 for ( index = count - 1; index > -1; index-- ) 845 { 846 DACallbackRef callback; 847 848 callback = ( void * ) CFArrayGetValueAtIndex( gDAResponseList, index ); 849 850 if ( DACallbackGetSession( callback ) == session ) 851 { 852 DADiskRef disk; 853 854 disk = DACallbackGetDisk( callback ); 855 856 CFArrayRemoveValueAtIndex( gDAResponseList, index ); 857 858 __DAResponseComplete( disk ); 859 } 860 } 861 862 count = CFArrayGetCount( gDARequestList ); 863 864 for ( index = count - 1; index > -1; index-- ) 865 { 866 DARequestRef request; 867 868 request = ( void * ) CFArrayGetValueAtIndex( gDARequestList, index ); 869 870 if ( request ) 871 { 872 DACallbackRef callback; 873 874 callback = DARequestGetCallback( request ); 875 876 if ( callback ) 877 { 878 if ( DACallbackGetSession( callback ) == session ) 879 { 880 DARequestSetCallback( request, NULL ); 881 } 882 } 883 } 884 } 885 886 count = CFArrayGetCount( gDADiskList ); 887 888 for ( index = count - 1; index > -1; index-- ) 889 { 890 DADiskRef disk; 891 892 disk = ( void * ) CFArrayGetValueAtIndex( gDADiskList, index ); 893 894 if ( disk ) 895 { 896 DACallbackRef callback; 897 898 callback = DADiskGetClaim( disk ); 899 900 if ( callback ) 901 { 902 if ( DACallbackGetSession( callback ) == session ) 903 { 904 DADiskSetClaim( disk, NULL ); 905 } 906 } 907 } 908 } 909} 910 911void DAQueueRequest( DARequestRef request ) 912{ 913 DAReturn status; 914 915 status = kDAReturnSuccess; 916 917 switch ( DARequestGetKind( request ) ) 918 { 919 case _kDADiskEject: 920 case _kDADiskMount: 921 case _kDADiskUnmount: 922 { 923 DADiskMountOptions options; 924 925 options = DARequestGetArgument1( request ); 926 927 assert( kDADiskMountOptionWhole == kDADiskUnmountOptionWhole ); 928 929 if ( DARequestGetKind( request ) == _kDADiskEject ) 930 { 931 options |= kDADiskMountOptionWhole; 932 } 933 934 if ( ( options & kDADiskMountOptionWhole ) ) 935 { 936 DADiskRef disk; 937 938 disk = DARequestGetDisk( request ); 939 940 if ( DARequestGetArgument2( request ) ) 941 { 942 status = kDAReturnBadArgument; 943 } 944 945 if ( DARequestGetArgument3( request ) ) 946 { 947 status = kDAReturnBadArgument; 948 } 949 950 if ( DADiskGetDescription( disk, kDADiskDescriptionMediaWholeKey ) == NULL ) 951 { 952 status = kDAReturnUnsupported; 953 } 954 955 if ( DADiskGetDescription( disk, kDADiskDescriptionMediaWholeKey ) == kCFBooleanFalse ) 956 { 957 status = kDAReturnUnsupported; 958 } 959 960 if ( status ) 961 { 962 break; 963 } 964 else 965 { 966 CFMutableArrayRef link; 967 968 link = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks ); 969 970 if ( link ) 971 { 972 CFIndex count; 973 CFIndex index; 974 975 count = CFArrayGetCount( gDADiskList ); 976 977 for ( index = 0; index < count; index++ ) 978 { 979 DADiskRef subdisk; 980 981 subdisk = ( void * ) CFArrayGetValueAtIndex( gDADiskList, index ); 982 983 if ( disk != subdisk ) 984 { 985 if ( DADiskGetBSDUnit( disk ) == DADiskGetBSDUnit( subdisk ) ) 986 { 987 DARequestRef subrequest; 988 989 subrequest = DARequestCreate( kCFAllocatorDefault, 990 DARequestGetKind( request ), 991 subdisk, 992 options, 993 NULL, 994 NULL, 995 DARequestGetUserUID( request ), 996 DARequestGetUserGID( request ), 997 NULL ); 998 999 if ( subrequest ) 1000 { 1001 CFArrayAppendValue( link, subrequest ); 1002 1003 CFArrayAppendValue( gDARequestList, subrequest ); 1004 1005 CFRelease( subrequest ); 1006 } 1007 } 1008 } 1009 } 1010 1011 DARequestSetLink( request, link ); 1012 1013 CFRelease( link ); 1014 } 1015 } 1016 } 1017 1018 break; 1019 } 1020 } 1021 1022 if ( status ) 1023 { 1024 DARequestDispatchCallback( request, status ); 1025 } 1026 else 1027 { 1028 CFArrayAppendValue( gDARequestList, request ); 1029 1030 DAStageSignal( ); 1031 } 1032} 1033 1034void DAQueueUnregisterCallback( DACallbackRef callback ) 1035{ 1036 CFIndex count; 1037 CFIndex index; 1038 1039 count = CFArrayGetCount( gDAResponseList ); 1040 1041 for ( index = count - 1; index > -1; index-- ) 1042 { 1043 DACallbackRef item; 1044 1045 item = ( void * ) CFArrayGetValueAtIndex( gDAResponseList, index ); 1046 1047 if ( DACallbackGetSession( item ) == DACallbackGetSession( callback ) ) 1048 { 1049 if ( DACallbackGetAddress( item ) == DACallbackGetAddress( callback ) ) 1050 { 1051 if ( DACallbackGetContext( item ) == DACallbackGetContext( callback ) ) 1052 { 1053 DADiskRef disk; 1054 1055 disk = DACallbackGetDisk( item ); 1056 1057 CFArrayRemoveValueAtIndex( gDAResponseList, index ); 1058 1059 __DAResponseComplete( disk ); 1060 } 1061 } 1062 } 1063 } 1064} 1065