#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <servers/bootstrap.h>
#include <mach/mach.h>
#include <unistd.h>
#include <Security/Authorization.h>
#include <DiskArbitration.h>
#include <CoreFoundation/CoreFoundation.h>
#include "ClientToServer.h"
#ifndef DEBUG
#define DEBUG 0
#endif
#if DEBUG
#define dwarning(args) printf args
#else
#define dwarning(args)
#endif
static mach_port_t gDiskArbSndPort = MACH_PORT_NULL;
static mach_port_t gDiskArbRcvPort = MACH_PORT_NULL;
CFMutableDictionaryRef gDiskArbitration_CallbackHandlers = NULL;
int gDiskArbitration_ClientFlags = kDiskArbNotifyNone;
CFArrayRef
DiskArbCallbackHandlersForCallback(int callbackType)
{
CFNumberRef numberForType = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &callbackType);
CFArrayRef array = nil;
if (!gDiskArbitration_CallbackHandlers) {
CFRelease(numberForType);
return array;
}
if (CFDictionaryContainsKey(gDiskArbitration_CallbackHandlers, numberForType)) {
array = CFDictionaryGetValue(gDiskArbitration_CallbackHandlers, numberForType);
}
CFRelease(numberForType);
return array;
}
boolean_t
updateClientFlags(void)
{
int flags = kDiskArbNotifyNone;
if (DiskArbCallbackHandlersForCallback(kDA_DISK_APPEARED_WITHOUT_MT) != NULL)
flags |= kDiskArbNotifyDiskAppearedWithoutMountpoint;
if (DiskArbCallbackHandlersForCallback(kDA_DISK_APPEARED_WITH_MT) != NULL)
flags |= kDiskArbNotifyDiskAppearedWithMountpoint;
if (DiskArbCallbackHandlersForCallback(kDA_DISK_APPEARED1) != NULL)
flags |= kDiskArbNotifyDiskAppeared;
if (DiskArbCallbackHandlersForCallback(kDA_DISK_APPEARED) != NULL)
flags |= kDiskArbNotifyDiskAppeared2;
if (DiskArbCallbackHandlersForCallback(kDA_DISK_APPEARED_COMPLETE) != NULL)
flags |= kDiskArbNotifyDiskAppearedComplete;
if (DiskArbCallbackHandlersForCallback(kDA_DISK_UNMOUNT) != NULL)
flags |= kDiskArbNotifyUnmount;
if (DiskArbCallbackHandlersForCallback(kDA_DISK_APPROVAL_NOTIFY) != NULL)
flags |= kDiskArbNotifyDiskApproval;
if (DiskArbCallbackHandlersForCallback(kDA_DISK_UNMOUNT_PRE_NOTIFY) != NULL || DiskArbCallbackHandlersForCallback(kDA_DISK_UNMOUNT_POST_NOTIFY) != NULL || DiskArbCallbackHandlersForCallback(kDA_DISK_EJECT_PRE_NOTIFY) != NULL || DiskArbCallbackHandlersForCallback(kDA_DISK_EJECT_POST_NOTIFY) != NULL) {
if (DiskArbCallbackHandlersForCallback(kDA_DISK_UNMOUNT_PRE_NOTIFY) != NULL && DiskArbCallbackHandlersForCallback(kDA_DISK_UNMOUNT_POST_NOTIFY) != NULL && DiskArbCallbackHandlersForCallback(kDA_DISK_EJECT_PRE_NOTIFY) != NULL && DiskArbCallbackHandlersForCallback(kDA_DISK_EJECT_POST_NOTIFY) != NULL) {
flags |= kDiskArbNotifyAsync;
} else {
return FALSE;
}
}
if (DiskArbCallbackHandlersForCallback(kDA_BLUE_BOX_UPDATED) != NULL)
flags |= kDiskArbNotifyBlueBoxBootVolumeUpdated;
if (DiskArbCallbackHandlersForCallback(kDA_NOTIFICATIONS_COMPLETE) != NULL)
flags |= kDiskArbNotifyCompleted;
if (DiskArbCallbackHandlersForCallback(kDA_DISK_CHANGED) != NULL)
flags |= kDiskArbNotifyChangedDisks;
if (DiskArbCallbackHandlersForCallback(kDA_DISK_WILL_BE_CHECKED) != NULL)
flags |= kDiskArbNotifyDiskWillBeChecked;
if (DiskArbCallbackHandlersForCallback(kDA_CALL_FAILED) != NULL)
flags |= kDiskArbNotifyCallFailed;
if (DiskArbCallbackHandlersForCallback(kDA_CALL_SUCCEEDED) != NULL)
flags |= kDiskArbNotifyCallSucceeded;
if (DiskArbCallbackHandlersForCallback(kDA_CLIENT_WILL_HANDLE_UNRECOGNIZED_DISK) != NULL)
flags |= kDiskArbArbitrateUnrecognizedVolumes;
if (DiskArbCallbackHandlersForCallback(kDA_UNKNOWN_DISK_APPEARED) != NULL)
flags |= kDiskArbNotifyUnrecognizedVolumes;
if (flags != gDiskArbitration_ClientFlags) {
gDiskArbitration_ClientFlags = flags;
return TRUE;
}
return FALSE;
}
void
DiskArbAddCallbackHandler(int callbackType, void *callback, int overwrite)
{
CFNumberRef numberForType = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &callbackType);
if (!gDiskArbitration_CallbackHandlers) {
gDiskArbitration_CallbackHandlers = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
}
if (!callback) {
CFRelease(numberForType);
return;
}
if (CFDictionaryContainsKey(gDiskArbitration_CallbackHandlers, numberForType)) {
if (overwrite) {
CFMutableArrayRef callbackArray = CFArrayCreateMutable(NULL, 0, NULL);
CFArrayAppendValue(callbackArray, callback);
CFDictionaryReplaceValue(gDiskArbitration_CallbackHandlers, numberForType, callbackArray);
} else {
CFMutableArrayRef callbackArray = CFDictionaryGetValue(gDiskArbitration_CallbackHandlers, numberForType);
DiskArbRemoveCallbackHandler(callbackType, callback);
CFArrayAppendValue(callbackArray, callback);
}
} else {
CFMutableArrayRef callbackArray = CFArrayCreateMutable(NULL, 0, NULL);
CFArrayAppendValue(callbackArray, callback);
CFDictionaryAddValue(gDiskArbitration_CallbackHandlers, numberForType, callbackArray);
}
if (updateClientFlags()) {
}
CFRelease(numberForType);
return;
}
void
DiskArbRemoveCallbackHandler(int callbackType, void *callback)
{
CFNumberRef numberForType = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &callbackType);
if (!gDiskArbitration_CallbackHandlers) {
CFRelease(numberForType);
return;
}
if (CFDictionaryContainsKey(gDiskArbitration_CallbackHandlers, numberForType)) {
CFMutableArrayRef callbackArray = CFDictionaryGetValue(gDiskArbitration_CallbackHandlers, numberForType);
CFIndex index = CFArrayGetFirstIndexOfValue(callbackArray, CFRangeMake(0, CFArrayGetCount(callbackArray)), callback);
while (index >= 0) {
CFArrayRemoveValueAtIndex(callbackArray, index);
index = CFArrayGetFirstIndexOfValue(callbackArray, CFRangeMake(0, CFArrayGetCount(callbackArray)), callback);
}
}
CFRelease(numberForType);
return;
}
void
DiskArbRegisterCallback_DiskAppearedWithMountpoint(DiskArbCallback_DiskAppearedWithMountpoint_t callback)
{
DiskArbAddCallbackHandler(kDA_DISK_APPEARED_WITH_MT, callback, 0);
}
void
DiskArbRegisterCallback_DiskAppearedWithoutMountpoint(DiskArbCallback_DiskAppearedWithoutMountpoint_t callback)
{
DiskArbAddCallbackHandler(kDA_DISK_APPEARED_WITHOUT_MT, callback, 0);
}
void
DiskArbRegisterCallback_DiskAppeared(DiskArbCallback_DiskAppeared_t callback)
{
DiskArbAddCallbackHandler(kDA_DISK_APPEARED1, callback, 0);
}
void
DiskArbRegisterCallback_DiskAppeared2(DiskArbCallback_DiskAppeared2_t callback)
{
DiskArbAddCallbackHandler(kDA_DISK_APPEARED, callback, 0);
}
void
DiskArbRegisterCallback_UnmountNotification(DiskArbCallback_UnmountNotification_t callback)
{
DiskArbAddCallbackHandler(kDA_DISK_UNMOUNT, callback, 0);
}
void
DiskArbRegisterCallback_UnmountPreNotification(DiskArbCallback_UnmountPreNotification_t callback)
{
DiskArbAddCallbackHandler(kDA_DISK_UNMOUNT_PRE_NOTIFY, callback, 1);
}
void
DiskArbRegisterCallback_UnmountPostNotification(DiskArbCallback_UnmountPostNotification_t callback)
{
DiskArbAddCallbackHandler(kDA_DISK_UNMOUNT_POST_NOTIFY, callback, 0);
}
void
DiskArbRegisterCallback_EjectPreNotification(DiskArbCallback_EjectPreNotification_t callback)
{
DiskArbAddCallbackHandler(kDA_DISK_EJECT_PRE_NOTIFY, callback, 1);
}
void
DiskArbRegisterCallback_EjectPostNotification(DiskArbCallback_EjectPostNotification_t callback)
{
DiskArbAddCallbackHandler(kDA_DISK_EJECT_POST_NOTIFY, callback, 0);
}
void
DiskArbRegisterCallback_ClientDisconnectedNotification(DiskArbCallback_ClientDisconnectedNotification_t callback)
{
DiskArbAddCallbackHandler(kDA_CLIENT_DISCONNECTED, callback, 0);
}
void
DiskArbRegisterCallback_BlueBoxBootVolumeUpdated(DiskArbCallback_BlueBoxBootVolumeUpdated_t callback)
{
DiskArbAddCallbackHandler(kDA_BLUE_BOX_UPDATED, callback, 0);
}
void
DiskArbRegisterCallback_DiskChangedNotification(DiskArbCallback_DiskChangedNotification_t callback)
{
DiskArbAddCallbackHandler(kDA_DISK_CHANGED, callback, 0);
}
void
DiskArbRegisterCallback_DiskWillBeCheckedNotification(DiskArbCallback_DiskWillBeCheckedNotification_t callback)
{
DiskArbAddCallbackHandler(kDA_DISK_WILL_BE_CHECKED, callback, 0);
}
void
DiskArbRegisterCallback_CallFailedNotification(DiskArbCallback_CallFailedNotification_t callback)
{
DiskArbAddCallbackHandler(kDA_CALL_FAILED, callback, 0);
}
void
DiskArbRegisterCallback_CallSucceededNotification(DiskArbCallback_CallSucceededNotification_t callback)
{
DiskArbAddCallbackHandler(kDA_CALL_SUCCEEDED, callback, 0);
}
void
DiskArbRegisterCallback_NotificationComplete(DiskArbCallback_NotificationComplete_t callback)
{
DiskArbAddCallbackHandler(kDA_NOTIFICATIONS_COMPLETE, callback, 0);
}
void
DiskArbRegisterCallback_Will_Client_Release(DiskArbCallback_Will_Client_Release_t callback)
{
DiskArbAddCallbackHandler(kDA_WILL_CLIENT_RELEASE_DEVICE, callback, 0);
}
void
DiskArbRegisterCallback_Device_Reservation_Status(DiskArbCallback_Device_Reservation_Status_t callback)
{
DiskArbAddCallbackHandler(kDA_DEVICE_RESERVATION_STATUS, callback, 0);
}
void
DiskArbRegisterCallback_UnknownFileSystemNotification(DiskArbCallback_UnknownFileSystemNotification_t callback)
{
DiskArbAddCallbackHandler(kDA_UNKNOWN_DISK_APPEARED, callback, 0);
}
boolean_t
DiskArbHandleMsg(
mach_msg_header_t * InHeadP,
mach_msg_header_t * OutHeadP)
{
return ServerToClient_server(InHeadP, OutHeadP);
}
kern_return_t
DiskArbRegister(mach_port_t server, mach_port_t client, unsigned flags)
{
gDiskArbRcvPort = client;
return DiskArbRegister_rpc(server, client, flags);
}
kern_return_t
DiskArbRegister_auto(mach_port_t client, unsigned flags)
{
return DiskArbRegister(gDiskArbSndPort, client, flags);
}
kern_return_t
DiskArbDeregister(mach_port_t server, mach_port_t client)
{
return DiskArbDeregister_rpc(server, client);
}
kern_return_t
DiskArbDeregister_auto(mach_port_t client)
{
return DiskArbDeregister(gDiskArbSndPort, client);
}
kern_return_t
DiskArbDiskAppearedWithMountpointPing(
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
unsigned flags,
DiskArbMountpoint mountpoint)
{
SetSecure();
return DiskArbDiskAppearedWithMountpointPing_rpc(server, diskIdentifier, flags, mountpoint);
}
kern_return_t
DiskArbDiskAppearedWithMountpointPing_auto(DiskArbDiskIdentifier diskIdentifier, unsigned flags, DiskArbMountpoint mountpoint)
{
return DiskArbDiskAppearedWithMountpointPing(gDiskArbSndPort, diskIdentifier, flags, mountpoint);
}
kern_return_t
DiskArbDiskDisappearedPing(mach_port_t server, DiskArbDiskIdentifier diskIdentifier, unsigned flags)
{
SetSecure();
return DiskArbDiskDisappearedPing_rpc(server, diskIdentifier, flags);
}
kern_return_t
DiskArbDiskDisappearedPing_auto(DiskArbDiskIdentifier diskIdentifier, unsigned flags)
{
return DiskArbDiskDisappearedPing(gDiskArbSndPort, diskIdentifier, flags);
}
kern_return_t
DiskArbRequestMount(mach_port_t server, DiskArbDiskIdentifier diskIdentifier)
{
SetSecure();
return DiskArbRequestMount_rpc(server, diskIdentifier, FALSE);
}
kern_return_t
DiskArbRequestMount_auto(DiskArbDiskIdentifier diskIdentifier)
{
return DiskArbRequestMount(gDiskArbSndPort, diskIdentifier);
}
kern_return_t
DiskArbRequestMountAndOwn(mach_port_t server, DiskArbDiskIdentifier diskIdentifier)
{
SetSecure();
return DiskArbRequestMount_rpc(server, diskIdentifier, TRUE);
}
kern_return_t
DiskArbRequestMountAndOwn_auto(DiskArbDiskIdentifier diskIdentifier)
{
return DiskArbRequestMountAndOwn(gDiskArbSndPort, diskIdentifier);
}
kern_return_t
DiskArbRefresh(
mach_port_t server)
{
return DiskArbRefresh_rpc(server);
}
kern_return_t
DiskArbRegisterWithPID(
mach_port_t server,
mach_port_t client,
unsigned flags)
{
gDiskArbRcvPort = client;
return DiskArbRegisterWithPID_rpc(server, client, getpid(), flags);
}
kern_return_t
DiskArbDiskAppearedWithoutMountpoint_rpc(
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
unsigned flags)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_DISK_APPEARED_WITHOUT_MT);
if (NULL == callbacks) {
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_DiskAppearedWithoutMountpoint_t) CFArrayGetValueAtIndex(callbacks, i)) (diskIdentifier, flags);
}
}
Return:
return err;
}
kern_return_t DiskArbDiskAppearedWithMountpoint_rpc(
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
unsigned flags,
DiskArbMountpoint mountpoint)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_DISK_APPEARED_WITH_MT);
if (NULL == callbacks) {
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_DiskAppearedWithMountpoint_t) CFArrayGetValueAtIndex(callbacks, i)) (diskIdentifier, flags, mountpoint);
}
}
Return:
return err;
}
kern_return_t DiskArbDiskAppeared_rpc(
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
unsigned flags,
DiskArbMountpoint mountpoint,
DiskArbIOContent ioContent)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_DISK_APPEARED1);
if (NULL == callbacks) {
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_DiskAppeared_t) CFArrayGetValueAtIndex(callbacks, i)) (diskIdentifier, flags, mountpoint, ioContent);
}
}
Return:
return err;
}
kern_return_t DiskArbDiskAppeared2_rpc(
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
unsigned flags,
DiskArbMountpoint mountpoint,
DiskArbIOContent ioContent,
DiskArbDeviceTreePath deviceTreePath,
unsigned sequenceNumber)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_DISK_APPEARED);
if (NULL == callbacks) {
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_DiskAppeared2_t) CFArrayGetValueAtIndex(callbacks, i)) (diskIdentifier, flags, mountpoint, ioContent, deviceTreePath, sequenceNumber);
}
}
Return:
return err;
}
kern_return_t DiskArbDiskAppearedComplete_rpc(
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
unsigned flags,
DiskArbMountpoint mountpoint,
DiskArbIOContent ioContent,
DiskArbDeviceTreePath deviceTreePath,
unsigned sequenceNumber,
double timeAppeared,
DiskArbGenericString fsType,
DiskArbGenericString fsName)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_DISK_APPEARED_COMPLETE);
if (NULL == callbacks) {
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_DiskAppearedComplete_t) CFArrayGetValueAtIndex(callbacks, i)) (diskIdentifier, flags, mountpoint, ioContent, deviceTreePath, sequenceNumber, timeAppeared, fsType, fsName);
}
}
Return:
return err;
}
kern_return_t DiskArbUnmountNotification_rpc(
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
int pastOrFuture,
int willEject)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_DISK_UNMOUNT);
if (NULL == callbacks) {
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_UnmountNotification_t) CFArrayGetValueAtIndex(callbacks, i)) (diskIdentifier, pastOrFuture, willEject);
}
}
Return:
return err;
}
kern_return_t DiskArbUnmountPreNotify_async_rpc(
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
unsigned flags)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_DISK_UNMOUNT_PRE_NOTIFY);
if (NULL == callbacks) {
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_UnmountPreNotification_t) CFArrayGetValueAtIndex(callbacks, i)) (diskIdentifier, flags);
}
}
Return:
return err;
}
kern_return_t DiskArbUnmountPostNotify_async_rpc(
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
int errorCode,
int dissenter)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_DISK_UNMOUNT_POST_NOTIFY);
if (NULL == callbacks) {
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_UnmountPostNotification_t) CFArrayGetValueAtIndex(callbacks, i)) (diskIdentifier, errorCode, dissenter);
}
}
Return:
return err;
}
kern_return_t DiskArbEjectPreNotify_async_rpc(
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
unsigned flags)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_DISK_EJECT_PRE_NOTIFY);
if (NULL == callbacks) {
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_EjectPreNotification_t) CFArrayGetValueAtIndex(callbacks, i)) (diskIdentifier, flags);
}
}
Return:
return err;
}
kern_return_t DiskArbEjectPostNotify_async_rpc(
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
int errorCode,
int dissenter)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_DISK_EJECT_POST_NOTIFY);
if (NULL == callbacks) {
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_EjectPostNotification_t) CFArrayGetValueAtIndex(callbacks, i)) (diskIdentifier, errorCode, dissenter);
}
}
Return:
return err;
}
kern_return_t DiskArbDiskApprovalPre_rpc(mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
DiskArbMountpoint volName,
DiskArbGenericString ioContent,
DiskArbGenericString deviceTreePath,
unsigned flags,
int isWritable,
int isRemovable,
int isWhole,
DiskArbGenericString fsType)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_DISK_APPROVAL_NOTIFY);
if (NULL == callbacks) {
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_DiskApprovalNotification_t) CFArrayGetValueAtIndex(callbacks, i)) (diskIdentifier, volName, ioContent, deviceTreePath, flags, isWritable, isRemovable, isWhole, fsType);
}
}
Return:
return err;
}
kern_return_t DiskArbClientDisconnected_rpc(
mach_port_t server)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_CLIENT_DISCONNECTED);
if (NULL == callbacks) {
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_ClientDisconnectedNotification_t) CFArrayGetValueAtIndex(callbacks, i)) ();
}
}
Return:
return err;
}
kern_return_t DiskArbBlueBoxBootVolumeUpdated_async_rpc(
mach_port_t server,
int seqno)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_BLUE_BOX_UPDATED);
if (NULL == callbacks) {
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_BlueBoxBootVolumeUpdated_t) CFArrayGetValueAtIndex(callbacks, i)) (seqno);
}
}
Return:
return err;
}
kern_return_t DiskArbDiskChanged_rpc(
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
DiskArbMountpoint newMountPoint,
DiskArbMountpoint newVolumeName,
unsigned flags,
int success)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_DISK_CHANGED);
if (NULL == callbacks) {
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_DiskChangedNotification_t) CFArrayGetValueAtIndex(callbacks, i)) (diskIdentifier, newMountPoint, newVolumeName, flags, success);
}
}
Return:
return err;
}
kern_return_t DiskArbDiskWillBeChecked_rpc(
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
unsigned flags,
DiskArbIOContent content)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_DISK_WILL_BE_CHECKED);
if (NULL == callbacks) {
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_DiskWillBeCheckedNotification_t) CFArrayGetValueAtIndex(callbacks, i)) (diskIdentifier, flags, content);
}
}
Return:
return err;
}
kern_return_t DiskArbPreviousCallFailed_rpc(
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
int failedCallType,
int error)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_CALL_FAILED);
if (NULL == callbacks) {
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_CallFailedNotification_t) CFArrayGetValueAtIndex(callbacks, i)) (diskIdentifier, failedCallType, error);
}
}
Return:
return err;
}
kern_return_t DiskArbPreviousCallSucceeded_rpc(
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
int succeededCallType)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_CALL_SUCCEEDED);
if (NULL == callbacks) {
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_CallSucceededNotification_t) CFArrayGetValueAtIndex(callbacks, i)) (diskIdentifier, succeededCallType);
}
}
Return:
return err;
}
kern_return_t DiskArbNotificationComplete_rpc(
mach_port_t server,
int messageType)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_NOTIFICATIONS_COMPLETE);
if (NULL == callbacks) {
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_NotificationComplete_t) CFArrayGetValueAtIndex(callbacks, i)) (messageType);
}
}
Return:
return err;
}
kern_return_t DiskArbRegistrationComplete_rpc(
mach_port_t server)
{
kern_return_t err = 0;
#warning NOT CURRENTLY DOING A THING!!!!
dwarning(("%s\n", __FUNCTION__));
return err;
}
kern_return_t DiskArbWillClientRelinquish_rpc(
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
int releaseToClientPid)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_WILL_CLIENT_RELEASE_DEVICE);
if (NULL == callbacks) {
DiskArbClientRelinquishesReservation(diskIdentifier, releaseToClientPid, 0);
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_Will_Client_Release_t) CFArrayGetValueAtIndex(callbacks, i)) (diskIdentifier, releaseToClientPid);
}
}
Return:
return err;
}
kern_return_t
DiskArbDeviceReservationStatus_rpc(
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
int status,
int pid)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_DEVICE_RESERVATION_STATUS);
if (NULL == callbacks) {
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_Device_Reservation_Status_t) CFArrayGetValueAtIndex(callbacks, i)) (diskIdentifier, status, pid);
}
}
Return:
return err;
}
kern_return_t
DiskArbWillClientHandleUnrecognizedDisk_rpc(
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
int diskType,
char *fsType,
char *deviceType,
int isWritable,
int isRemovable,
int isWhole)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_CLIENT_WILL_HANDLE_UNRECOGNIZED_DISK);
if (NULL == callbacks) {
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_Will_Client_Handle_Unrecognized_Disk_t) CFArrayGetValueAtIndex(callbacks, i)) (diskIdentifier, diskType, fsType, deviceType, isWritable, isRemovable, isWhole);
}
}
Return:
return err;
}
kern_return_t
DiskArbUnknownFileSystemInserted_rpc(
mach_port_t server,
char *diskIdentifier,
char *fsType,
char *deviceType,
int isWritable,
int isRemovable,
int isWhole)
{
kern_return_t err = 0;
CFArrayRef callbacks = DiskArbCallbackHandlersForCallback(kDA_UNKNOWN_DISK_APPEARED);
if (NULL == callbacks) {
goto Return;
} else {
int i;
for (i = 0; i < CFArrayGetCount(callbacks); i++) {
((DiskArbCallback_UnknownFileSystemNotification_t) CFArrayGetValueAtIndex(callbacks, i)) (diskIdentifier, fsType, deviceType, isWritable, isRemovable, isWhole);
}
}
Return:
return err;
}
kern_return_t DiskArbStart(mach_port_t * portPtr)
{
kern_return_t result;
static mach_port_t pre_registered_port = 0x0;
result = bootstrap_look_up(bootstrap_port, DISKARB_SERVER_NAME, &gDiskArbSndPort);
if (result) {
dwarning(("%s(): {%s:%d} bootstrap_look_up() failed: $%x\n", __FUNCTION__, __FILE__, __LINE__, (int) result));
goto Return;
}
dwarning(("%s(): gDiskArbSndPort = %d\n", __FUNCTION__, (int) gDiskArbSndPort));
if (!pre_registered_port) {
result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, portPtr);
if (result != KERN_SUCCESS) {
dwarning(("%s(): (%s:%d) mach_port_allocate failed: $%x: %s\n", __FUNCTION__, __FILE__, __LINE__, result, mach_error_string(result)));
goto Return;
}
} else {
*portPtr = pre_registered_port;
}
dwarning(("%s(): port = $%x\n", __FUNCTION__, (int) *portPtr));
updateClientFlags();
dwarning(("%s(): flags = %08x\n", __FUNCTION__, gDiskArbitration_ClientFlags));
if (!pre_registered_port) {
result = DiskArbRegisterWithPID_auto(*portPtr, gDiskArbitration_ClientFlags);
DiskArbMsgLoopWithTimeout(5000);
if (result) {
dwarning(("%s(): {%s:%d} DiskArbRegister(sendPort=$%08x, *portPtr=$%08x, flags=$%08x) failed: $%x\n", __FUNCTION__, __FILE__, __LINE__, gDiskArbSndPort, *portPtr, gDiskArbitration_ClientFlags, (int) result));
goto Return;
}
}
pre_registered_port = *portPtr;
Return:
return result;
}
kern_return_t DiskArbInit(void)
{
kern_return_t result;
if (gDiskArbSndPort != MACH_PORT_NULL) {
result = 0;
goto Return;
}
result = bootstrap_look_up(bootstrap_port, DISKARB_SERVER_NAME, &gDiskArbSndPort);
if (result) {
dwarning(("%s(): {%s:%d} bootstrap_look_up() failed: $%x\n", __FUNCTION__, __FILE__, __LINE__, (int) result));
goto Return;
}
dwarning(("%s(): gDiskArbSndPort = %d\n", __FUNCTION__, (int) gDiskArbSndPort));
Return:
return result;
}
kern_return_t DiskArbRefresh_auto()
{
return DiskArbRefresh_rpc(gDiskArbSndPort);
}
kern_return_t
DiskArbRegisterWithPID_auto(
mach_port_t client,
unsigned flags)
{
gDiskArbRcvPort = client;
return DiskArbRegisterWithPID_rpc(gDiskArbSndPort, client, getpid(), flags);
}
kern_return_t
DiskArbUpdateClientWithPID_auto(unsigned flags)
{
return DiskArbUpdateClientWithPID_rpc(gDiskArbSndPort, getpid(), flags);
}
kern_return_t
DiskArbDeregisterWithPID_auto(mach_port_t client)
{
gDiskArbRcvPort = client;
return DiskArbDeregisterWithPID_rpc(gDiskArbSndPort, client, getpid());
}
kern_return_t
DiskArbMarkPIDNew_auto(mach_port_t client, unsigned flags)
{
gDiskArbRcvPort = client;
SetSecure();
return DiskArbMarkPIDNew_rpc(gDiskArbSndPort, client, getpid(), flags);
}
kern_return_t
DiskArbRequestDiskChange_auto(DiskArbDiskIdentifier diskIdentifier, DiskArbGenericString mountPoint, int flags)
{
SetSecure();
return DiskArbRequestDiskChange_rpc(gDiskArbSndPort, getpid(), diskIdentifier, mountPoint, flags);
}
kern_return_t
DiskArbSetCurrentUser_auto(int user)
{
SetSecure();
return DiskArbSetCurrentUser_rpc(gDiskArbSndPort, getpid(), user);
}
kern_return_t
DiskArbVSDBAdoptVolume_auto(DiskArbDiskIdentifier diskIdentifier)
{
SetSecure();
return DiskArbVSDBAdoptVolume_rpc(gDiskArbSndPort, getpid(), diskIdentifier);
}
kern_return_t
DiskArbVSDBDisownVolume_auto(DiskArbDiskIdentifier diskIdentifier)
{
SetSecure();
return DiskArbVSDBDisownVolume_rpc(gDiskArbSndPort, getpid(), diskIdentifier);
}
int
DiskArbVSDBGetVolumeStatus_auto(DiskArbDiskIdentifier diskIdentifier)
{
int status;
SetSecure();
DiskArbVSDBGetVolumeStatus_rpc(gDiskArbSndPort, diskIdentifier, &status);
return status;
}
kern_return_t
DiskArbSetVolumeEncoding_auto(DiskArbDiskIdentifier diskIdentifier, int volumeEncoding)
{
SetSecure();
return DiskArbSetVolumeEncoding_rpc(gDiskArbSndPort, getpid(), diskIdentifier, volumeEncoding);
}
int
DiskArbGetVolumeEncoding_auto(DiskArbDiskIdentifier diskIdentifier)
{
int status;
SetSecure();
DiskArbGetVolumeEncoding_rpc(gDiskArbSndPort, diskIdentifier, &status);
return status;
}
kern_return_t
DiskArbClientHandlesUninitializedDisks_auto(int flag)
{
SetSecure();
return DiskArbClientHandlesUninitializedDisks_rpc(gDiskArbSndPort, getpid(), flag);
}
kern_return_t
DiskArbUnmountRequest_async_auto(
DiskArbDiskIdentifier diskIdentifier,
unsigned flags)
{
SetSecure();
return DiskArbUnmountRequest_async_rpc(gDiskArbSndPort, getpid(), diskIdentifier, flags);
}
kern_return_t
DiskArbUnmountPreNotifyAck_async_auto(
DiskArbDiskIdentifier diskIdentifier,
int errorCode)
{
if (errorCode & kDiskArbRequireAuthentication) {
SetSecure();
}
return DiskArbUnmountPreNotifyAck_async_rpc(gDiskArbSndPort, getpid(), diskIdentifier, errorCode);
}
kern_return_t
DiskArbDiskApprovedAck_auto(
DiskArbDiskIdentifier diskIdentifier,
int status)
{
SetSecure();
return DiskArbDiskApprovedAck_rpc(gDiskArbSndPort, diskIdentifier, getpid(), status);
}
kern_return_t
DiskArbEjectRequest_async_auto(
DiskArbDiskIdentifier diskIdentifier,
unsigned flags)
{
SetSecure();
return DiskArbEjectRequest_async_rpc(gDiskArbSndPort, getpid(), diskIdentifier, flags);
}
kern_return_t
DiskArbEjectPreNotifyAck_async_auto(
DiskArbDiskIdentifier diskIdentifier,
int errorCode)
{
return DiskArbEjectPreNotifyAck_async_rpc(gDiskArbSndPort, getpid(), diskIdentifier, errorCode);
}
kern_return_t
DiskArbUnmountAndEjectRequest_async_auto(
DiskArbDiskIdentifier diskIdentifier,
unsigned flags)
{
SetSecure();
return DiskArbUnmountAndEjectRequest_async_rpc(gDiskArbSndPort, getpid(), diskIdentifier, flags);
}
kern_return_t
DiskArbSetBlueBoxBootVolume_async_auto(
int pid,
int seqno)
{
SetSecure();
return DiskArbSetBlueBoxBootVolume_async_rpc(gDiskArbSndPort, pid, seqno);
}
void
DiskArbNoOp(void)
{
return;
}
kern_return_t
DiskArbMsgLoop(void)
{
return DiskArbMsgLoopWithTimeout(MACH_MSG_TIMEOUT_NONE);
}
kern_return_t
DiskArbMsgLoopWithTimeout(mach_msg_timeout_t millisecondTimeout)
{
kern_return_t err = 0;
unsigned msgReceiveBufLength;
mach_msg_header_t *msgReceiveBufPtr = NULL;
unsigned msgSendBufLength;
mach_msg_header_t *msgSendBufPtr = NULL;
mach_msg_return_t receiveResult;
msgSendBufLength = sizeof(mach_msg_empty_send_t) + 20;
msgSendBufPtr = (mach_msg_header_t *) malloc(msgSendBufLength);
if (msgSendBufPtr == NULL) {
dwarning(("FAILURE: msgSendBufPtr = malloc(%d)\n", msgSendBufLength));
err = -1;
goto Return;
} else {
dwarning(("SUCCESS: msgSendBufPtr = malloc(%d)\n", msgSendBufLength));
}
msgReceiveBufLength = sizeof(mach_msg_empty_rcv_t);
msgReceiveBufPtr = NULL;
while (1) {
if (msgReceiveBufPtr == NULL) {
msgReceiveBufPtr = (mach_msg_header_t *) malloc(msgReceiveBufLength);
if (msgReceiveBufPtr == NULL) {
dwarning(("FAILURE: msgReceiveBufPtr = malloc(%d)\n", msgReceiveBufLength));
err = -2;
goto Return;
} else {
dwarning(("SUCCESS: msgReceiveBufPtr = malloc(%d)\n", msgReceiveBufLength));
}
}
dwarning(("gDiskArbRcvPort = $%x", gDiskArbRcvPort));
dwarning(("%s: Waiting for a message (millisecondTimeount = %d)...\n", __FUNCTION__, millisecondTimeout));
receiveResult = mach_msg(msgReceiveBufPtr,
MACH_RCV_MSG | MACH_RCV_LARGE | (MACH_MSG_TIMEOUT_NONE == millisecondTimeout ? 0 : MACH_RCV_TIMEOUT),
0,
msgReceiveBufLength,
gDiskArbRcvPort,
millisecondTimeout,
MACH_PORT_NULL);
if (receiveResult == MACH_RCV_TOO_LARGE) {
dwarning(("%s(): mach_msg: $%08x: %s\n", __FUNCTION__, receiveResult, mach_error_string(receiveResult)));
dwarning(("msgReceiveBufPtr->msgh_size = %d\n", msgReceiveBufPtr->msgh_size));
msgReceiveBufLength = msgReceiveBufPtr->msgh_size + sizeof(mach_msg_trailer_t);
free(msgReceiveBufPtr);
msgReceiveBufPtr = NULL;
continue;
} else if (receiveResult != MACH_MSG_SUCCESS) {
dwarning(("%s(): mach_msg: $%08x: %s\n", __FUNCTION__, receiveResult, mach_error_string(receiveResult)));
err = receiveResult;
goto Return;
}
if (msgReceiveBufPtr->msgh_local_port == gDiskArbRcvPort) {
bzero(msgSendBufPtr, sizeof(mach_msg_header_t));
dwarning(("%s: DiskArbHandleMsg...\n", __FUNCTION__));
(void) DiskArbHandleMsg(msgReceiveBufPtr, msgSendBufPtr);
dwarning(("%s: mach_msg_send...\n", __FUNCTION__));
(void) mach_msg_send(msgSendBufPtr);
goto Return;
} else {
dwarning(("FAILURE: unrecognized msgh_local_port = $%x\n", (int) msgReceiveBufPtr->msgh_local_port));
err = -3;
goto Return;
}
} Return:
if (msgReceiveBufPtr)
free(msgReceiveBufPtr);
if (msgSendBufPtr)
free(msgSendBufPtr);
return err;
}
kern_return_t DiskArbIsDeviceReservedForClient(DiskArbDiskIdentifier diskIdentifier)
{
SetSecure();
return DiskArbIsDeviceReservedForClient_rpc(gDiskArbSndPort, diskIdentifier, getpid());
}
kern_return_t
DiskArbRetainClientReservationForDevice(DiskArbDiskIdentifier diskIdentifier)
{
SetSecure();
return DiskArbRetainClientReservationForDevice_rpc(gDiskArbSndPort, diskIdentifier, getpid());
}
kern_return_t
DiskArbReleaseClientReservationForDevice(DiskArbDiskIdentifier diskIdentifier)
{
SetSecure();
return DiskArbReleaseClientReservationForDevice_rpc(gDiskArbSndPort, diskIdentifier, getpid());
}
kern_return_t
DiskArbClientRelinquishesReservation(DiskArbDiskIdentifier diskIdentifier, int releaseToClientPid, int status)
{
SetSecure();
return DiskArbClientRelinquishesReservation_rpc(gDiskArbSndPort, diskIdentifier, getpid(), releaseToClientPid, status);
}
kern_return_t
DiskArbClientHandlesUnrecognizedDisks(int diskTypes, int priority)
{
SetSecure();
return DiskArbClientHandlesUnrecognizedDisks_rpc(gDiskArbSndPort, getpid(), diskTypes, priority);
}
kern_return_t
DiskArbClientWillHandleUnrecognizedDisk(DiskArbDiskIdentifier diskIdentifier, int yesNo)
{
SetSecure();
return DiskArbClientWillHandleUnrecognizedDisk_rpc(gDiskArbSndPort, diskIdentifier, getpid(), yesNo);
}
void
DiskArbUpdateClientFlags()
{
DiskArbUpdateClientWithPID_auto(gDiskArbitration_ClientFlags);
return;
}
int
DiskArbIsActive()
{
if (gDiskArbSndPort != NULL && gDiskArbRcvPort != NULL) {
return 1;
}
return 0;
}
void
SetSecure(void)
{
static int securityTokenPassed = 0;
if (!securityTokenPassed) {
static AuthorizationRef ref;
int error;
int flags = kAuthorizationFlagPreAuthorize | kAuthorizationFlagPartialRights | kAuthorizationFlagExtendRights;
error = AuthorizationCreate(NULL, NULL, flags, &ref);
if (!error) {
AuthorizationExternalForm externalForm;
error = AuthorizationMakeExternalForm(ref, &externalForm);
if (!error) {
DiskArbSetSecuritySettingsForClient_rpc(gDiskArbSndPort, getpid(), externalForm.bytes);
}
}
securityTokenPassed++;
}
return;
}
void DiskArb_EjectKeyPressed()
{
return;
}