DiskArbitrationServer.c [plain text]
#include <stdio.h>
#include <stdlib.h>
#include <mach/port.h>
#include <mach/kern_return.h>
#include <mach/mach_error.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <sys/ucred.h>
#include <sys/mount.h>
#include <sys/loadable_fs.h>
#include <sys/time.h>
#include <sys/attr.h>
#include <libc.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <bsd/dev/disk.h>
#include <errno.h>
#include <sys/wait.h>
#include <grp.h>
#include <ctype.h>
#include <dirent.h>
#include <mach/boolean.h>
#include <sys/loadable_fs.h>
#include <Security/Authorization.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include "ClientToServer.h"
#include "ServerToClient.h"
#include "DiskArbitrationTypes.h"
#include "DiskArbitrationServerMain.h"
#include "GetRegistry.h"
#include "FSParticular.h"
#define FILESYSTEM_ERROR 0
#define FILESYSTEM_MOUNTED 1
#define FILESYSTEM_MOUNTED_ALREADY 2
#define FILESYSTEM_NEEDS_REPAIR 3
#define ATTRREFDATA(ref) (((char *)(&(ref))) + (ref).attr_dataoffset)
struct volattr {
attrreference_t volnameref;
unsigned char volumenamestorage[140];
};
struct volattrbuf {
unsigned long length;
struct volattr va;
};
struct cominfo {
text_encoding_t encoding;
};
struct cominfobuf {
unsigned long length;
struct cominfo ci;
};
int currentConsoleUser = -1;
extern void autodiskmount(int ownership);
static ClientPtr LookupBlueBox( void );
void cleanUpAfterFork(void)
{
int fd, maxfd = getdtablesize();
for (fd = 0; fd < maxfd; fd++)
{
close(fd);
}
if ((fd = open("/dev/tty", O_NDELAY)) >= 0)
{
ioctl(fd, TIOCNOTTY, 0);
close(fd);
}
setgid(getgid());
setuid(getuid());
fd = open("/dev/null", O_RDONLY);
fd = open("/dev/console", O_WRONLY);
dup2(1, 2);
}
void ClientDeath(mach_port_t client);
void ClientDeath(mach_port_t client)
{
ClientPtr thisPtr, previousPtr;
dwarning(("%s(client = $%08x)\n", __FUNCTION__, client));
if ( g.Clients == NULL )
{
goto NotFound;
}
if ( g.Clients->port == client )
{
thisPtr = g.Clients;
g.Clients = g.Clients->next;
goto FoundIt;
}
previousPtr = g.Clients;
thisPtr = previousPtr->next;
while ( thisPtr != NULL )
{
if ( thisPtr->port == client )
{
previousPtr->next = thisPtr->next;
goto FoundIt;
}
previousPtr = thisPtr;
thisPtr = previousPtr->next;
}
goto NotFound;
FoundIt:
dwarning(("Found client record to delete:\n"));
PrintClient( thisPtr );
MakeDeadClientAgreeable( thisPtr );
{
kern_return_t r;
r = mach_port_deallocate( mach_task_self(), thisPtr->port );
if ( r ) dwarning(("%s(client = $%08x): mach_port_deallocate(...,$%08x) => $%08x: %s\n", __FUNCTION__, client, client, r, mach_error_string(r)));
}
if ( thisPtr->flags & kDiskArbIAmBlueBox )
{
dwarning(("%s: Blue Box died, resetting gBlueBoxBootVolume = -1\n",__FUNCTION__));
SetBlueBoxBootVolume( -1 );
}
{
DiskPtr diskPtr;
for (diskPtr = g.Disks; diskPtr != NULL; diskPtr = diskPtr->next)
{
if (diskPtr->retainingClient == thisPtr->pid) {
if (diskPtr->flags & kDiskArbDiskAppearedUnrecognizableFormat) {
diskPtr->state = kDiskStateNew;
}
diskPtr->retainingClient = 0;
}
}
}
if (thisPtr->ackOnUnrecognizedDisk) {
DiskPtr ackDisk = (DiskPtr)thisPtr->ackOnUnrecognizedDisk;
ackDisk->retainingClient = 0;
ackDisk->state = kDiskStateNew;
ackDisk->lastClientAttemptedForUnrecognizedMessages = nil;
thisPtr->ackOnUnrecognizedDisk = nil;
}
if (thisPtr->clientAuthRef) {
AuthorizationFree(thisPtr->clientAuthRef, NULL);
}
free( thisPtr );
g.NumClients--;
goto Return;
NotFound:
dwarning(("%s(client = $%08x): no matching client found!\n", __FUNCTION__, client));
goto Return;
Return:
dwarning(("%s($%08x), After:\n", __FUNCTION__, client));
PrintClients();
return;
}
kern_return_t DiskArbRegister_rpc (
mach_port_t server,
mach_port_t client,
unsigned flags)
{
kern_return_t err = 0;
ClientPtr newClient = NULL;
dwarning(("%s(client = $%08x, flags = $%08x)\n", __FUNCTION__, client, flags));
if ( EnableDeathNotifications( client ) )
{
dwarning(("%s(client = $%08x, flags = $%08x): EnableDeathNotifications() failed!\n", __FUNCTION__, (int)client, (int)flags));
{
kern_return_t r;
r = mach_port_deallocate( mach_task_self(), client );
dwarning(("%s(client = $%08x): mach_port_deallocate(...,$%08x) => $%08x: %s\n", __FUNCTION__, client, client, r, mach_error_string(r)));
}
err = -1;
goto Return;
}
newClient = NewClient(client, 0, flags);
if ( newClient == NULL )
{
dwarning(("%s(client = $%08x, flags = $%08x): NewClient failed!\n", __FUNCTION__, client, flags));
err = -1;
goto Return;
} else {
StartDiskRegistrationCompleteThread(newClient);
}
PrintClients();
Return:
return err;
}
kern_return_t DiskArbDiskAppearedWithMountpointPing_rpc (
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
unsigned flags,
DiskArbMountpoint mountpoint)
{
DiskPtr newDisk;
kern_return_t err = 0;
dwarning(("%s(diskIdentifier = '%s', flags = $%08x, mountpoint = '%s')\n", __FUNCTION__, diskIdentifier, flags, mountpoint));
newDisk = NewDisk( diskIdentifier,
0,
NULL,
kDiskFamily_AFP,
mountpoint,
NULL,
NULL,
NULL,
-1,
flags );
if ( !newDisk )
{
dwarning(("%s: NewDisk() failed!\n", __FUNCTION__));
} else {
newDisk->admCreatedMountPoint = 1; }
goto Return;
Return:
return err;
}
kern_return_t DiskArbDiskDisappearedPing_rpc (
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
unsigned flags)
{
kern_return_t err = 0;
DiskPtr diskPtr;
dwarning(("%s(diskIdentifier = '%s', flags = $%08x)\n", __FUNCTION__, diskIdentifier, flags));
diskPtr = LookupDiskByIOBSDName( diskIdentifier );
if ( NULL == diskPtr )
{
dwarning(("%s(diskIdentifier = '%s'): LookupDiskByIOBDSName failed\n", __FUNCTION__, diskIdentifier));
err = -1;
goto Return;
}
err = UnmountAllPartitions( diskPtr, FALSE );
SendUnmountPostNotifyMsgsForOnePartition( diskPtr->ioBSDName, 0, 0 );
SendEjectPostNotifyMsgsForOnePartition( diskPtr->ioBSDName, 0, 0 );
FreeDisk( diskPtr );
if ( err ) goto Return;
goto Return;
Return:
return err;
}
static int DiskExistsInMountTable(DiskPtr diskPtr)
{
struct statfs *mntbuf;
int numMounts;
int index = 1;
if ((numMounts = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) {
pwarning(("getmntinfo() call failed!\n"));
}
for (index=0; index < numMounts; index++) {
char devdName[MAXPATHLEN];
if (strcmp(diskPtr->ioBSDName, mntbuf[index].f_mntfromname) == 0) {
dwarning(("%s: Disk discovered in mount table as %s.\n", __FUNCTION__, mntbuf[index].f_mntfromname));
return TRUE;
}
sprintf(devdName, "/dev/%s", diskPtr->ioBSDName);
if (strcmp(mntbuf[index].f_mntfromname, devdName) == 0) {
dwarning(("%s: Disk discovered in mount table as %s.\n", __FUNCTION__, devdName));
return TRUE;
}
}
dwarning(("%s: Disk NOT discovered in mount table at %s(did someone umount it)?\n", __FUNCTION__, diskPtr->ioBSDName));
return FALSE;
}
kern_return_t DiskArbRefresh_rpc (
mach_port_t server)
{
kern_return_t err = 0;
int index = 1;
struct statfs *mntbuf;
int numMounts;
DiskPtr diskPtr;
if ((numMounts = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) {
dwarning(("getmntinfo() call failed!\n"));
}
for (index=0; index < numMounts; index++) {
char *dev_removed_name = NULL;
if (strstr(mntbuf[index].f_mntfromname, "/dev/")) {
dev_removed_name = mntbuf[index].f_mntfromname + 5;
}
if (strcmp(mntbuf[index].f_mntfromname, "fdesc") == 0) {
continue;
}
else if (strcmp(mntbuf[index].f_mntfromname, "devfs") == 0) {
continue;
}
else if (strcmp(mntbuf[index].f_mntfromname, "<volfs>") == 0) {
continue;
}
else if (strstr(mntbuf[index].f_mntfromname, "automount -fstab") != 0) {
continue;
}
if (!dev_removed_name) {
diskPtr = LookupDiskByIOBSDName( mntbuf[index].f_mntfromname );
} else {
diskPtr = LookupDiskByIOBSDName( dev_removed_name );
}
if (diskPtr && (diskPtr->mountpoint == NULL || (!strcmp(diskPtr->mountpoint, "")))) {
int newDisks;
DiskSetMountpoint(diskPtr, mntbuf[index].f_mntonname);
dwarning(("%s: Disk updated in mount table (did someone mount one)?\n", __FUNCTION__));
dwarning(("%s %s %s\n", mntbuf[index].f_fstypename, mntbuf[index].f_mntonname, mntbuf[index].f_mntfromname));
diskPtr->state = kDiskStateNew;
newDisks = SendDiskAppearedMsgs();
SendCompletedMsgs(kDiskArbCompletedDiskAppeared, newDisks);
}
else if (!diskPtr) {
if ( ! NewDisk( dev_removed_name?dev_removed_name:mntbuf[index].f_mntfromname,
0,
NULL,
kDiskFamily_SCSI,
mntbuf[index].f_mntonname,
NULL,
NULL,
NULL,
-1,
kDiskArbDiskAppearedNoFlags ) )
{
dwarning(("%s: NewDisk() failed!\n", __FUNCTION__));
} else {
dwarning(("%s: NewDisk() discovered (did someone mount one)?\n", __FUNCTION__));
dwarning(("%s %s %s\n", mntbuf[index].f_fstypename, mntbuf[index].f_mntonname, mntbuf[index].f_mntfromname));
}
}
}
for (diskPtr = g.Disks; diskPtr != NULL; diskPtr = diskPtr->next)
{
int exists = 0;
if (diskPtr->mountpoint == NULL || (strcmp(diskPtr->mountpoint, "") == 0)) {
continue;
}
exists = DiskExistsInMountTable(diskPtr);
if (!exists) {
DiskSetMountpoint(diskPtr, "");
SetStateForOnePartition( diskPtr, kDiskStateNewlyUnmounted );
SendUnmountPostNotifyMsgsForOnePartition( diskPtr->ioBSDName, 0, 0 );
}
}
return err;
}
kern_return_t DiskArbRequestMount_rpc (
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
int takeUserOwnership)
{
kern_return_t err = 0;
io_iterator_t ioIterator;
mach_port_t masterPort;
DiskPtr diskPtr;
err = IOMasterPort(bootstrap_port, &masterPort);
dwarning(("%s(diskIdentifier = '%s')\n", __FUNCTION__, diskIdentifier));
err = IOServiceGetMatchingServices(masterPort, IOServiceMatching("IOMedia"), &ioIterator);
diskPtr = LookupDiskByIOBSDName( diskIdentifier );
if (diskPtr)
{
UnmountAllPartitions(diskPtr, FALSE);
FreeDisk(diskPtr);
}
GetDisksFromRegistry( ioIterator, 0 );
autodiskmount(takeUserOwnership);
return err;
}
kern_return_t DiskArbRegisterWithPID_rpc (
mach_port_t server,
mach_port_t client,
int pid,
unsigned flags)
{
kern_return_t err = 0;
ClientPtr clientPtr = NULL;
dwarning(("%s(client = $%08x, pid = %d, flags = $%08x)\n", __FUNCTION__, client, pid, flags));
if ( EnableDeathNotifications( client ) )
{
dwarning(("%s(client = $%08x, pid = %d, flags = $%08x): EnableDeathNotifications() failed!\n", __FUNCTION__, (int)client, pid, (int)flags));
{
kern_return_t r;
r = mach_port_deallocate( mach_task_self(), client );
if ( r ) dwarning(("%s(client = $%08x): mach_port_deallocate(...,$%08x) => $%08x: %s\n", __FUNCTION__, client, client, r, mach_error_string(r)));
}
err = -1;
goto Return;
}
clientPtr = LookupClientByPID( pid );
if ( clientPtr )
{
dwarning(("%s(client = $%08x, pid = %d, flags = $%08x): updating existing client record:\n", __FUNCTION__, client, pid, flags));
PrintClient( clientPtr );
mach_port_deallocate( mach_task_self(), client );
clientPtr->port = client; clientPtr->flags = flags;
clientPtr->state = kDiskStateNew; }
else
{
clientPtr = NewClient(client, pid, flags);
if ( clientPtr == NULL )
{
dwarning(("%s(client = $%08x, pid = %d, flags = $%08x): NewClient failed!\n", __FUNCTION__, client, pid, flags));
err = -1;
} else {
dwarning(("%s(client = $%08x, pid = %d, flags = $%08x): Starting Complete Registration Thread!\n", __FUNCTION__, client, pid, flags));
StartDiskRegistrationCompleteThread(clientPtr);
}
}
PrintClients();
Return:
return err;
}
kern_return_t DiskArbMarkPIDNew_rpc (
mach_port_t server,
mach_port_t client,
int pid,
unsigned flags)
{
dwarning(("%s(client = $%08x, pid = %d, flags = $%08x)\n", __FUNCTION__, client, pid, flags));
ClientDeath(client);
EnableDeathNotifications( client );
NewClient(client, pid, flags);
return 0;
}
kern_return_t DiskArbUpdateClientWithPID_rpc (
mach_port_t server,
int pid,
unsigned flags)
{
ClientPtr clientPtr = LookupClientByPID( pid );
if ( clientPtr )
{
dwarning(("%s(pid = %d, flags = $%08x): updating existing client record:\n", __FUNCTION__, pid, flags));
PrintClient( clientPtr );
clientPtr->flags = flags;
clientPtr->state = kDiskStateNew; }
return 0;
}
kern_return_t DiskArbDeregister_rpc (
mach_port_t server,
mach_port_t client)
{
dwarning(("%s(client = $%08x)\n", __FUNCTION__, client));
ClientDeath(client);
return 0;
}
kern_return_t DiskArbDeregisterWithPID_rpc (
mach_port_t server,
mach_port_t client,
int pid)
{
dwarning(("%s(client = $%08x)\n", __FUNCTION__, client));
ClientDeath(client);
return 0;
}
kern_return_t DiskArbUnmountRequest_async_rpc (
mach_port_t server,
pid_t clientPid,
DiskArbDiskIdentifier diskIdentifier,
unsigned flags)
{
kern_return_t err = 0;
DiskPtr diskPtr;
ClientPtr clientPtr = LookupClientByPID(clientPid);
dwarning(("%s(diskIdentifier = '%s', flags = $%08x)\n", __FUNCTION__, diskIdentifier, flags));
diskPtr = LookupDiskByIOBSDName( diskIdentifier );
if ( NULL == diskPtr )
{
pwarning(("%s(diskIdentifier = '%s', flags = $%08x): LookupDiskByIOBDSName failed\n", __FUNCTION__, diskIdentifier, flags));
err = -1;
if (clientPtr) {
SendCallFailedMessage(clientPtr, NULL, kDiskArbUnmountRequestFailed, kDiskArbVolumeDoesNotExist);
}
goto Return;
}
if (!requestingClientHasPermissionToModifyDisk(clientPid, diskPtr, "system.volume.unmount")) {
err = -1;
if (clientPtr) {
SendCallFailedMessage(clientPtr, diskPtr, kDiskArbUnmountRequestFailed, kDiskArbInsecureRequest);
}
goto Return;
}
if ( AreWeBusyForDisk(diskPtr) )
{
pwarning(("%s(diskIdentifier = '%s', flags = $%08x): already busy\n", __FUNCTION__, diskIdentifier, flags));
err = -1;
if (clientPtr) {
SendCallFailedMessage(clientPtr, diskPtr, kDiskArbUnmountRequestFailed, kDiskArbIsBusy);
}
goto Return;
}
if (flags & kDiskArbForceUnmountFlag) {
if (flags & kDiskArbUnmountOneFlag) {
UnmountDisk( diskPtr, TRUE );
} else {
UnmountAllPartitions( diskPtr, TRUE );
}
}
if (flags & kDiskArbUnmountOneFlag) {
SetStateForOnePartition( diskPtr, kDiskStateToBeUnmounted );
} else {
SetStateForAllPartitions( diskPtr, kDiskStateToBeUnmounted );
}
PrepareToSendPreUnmountMsgs();
Return:
return err;
}
kern_return_t DiskArbUnmountPreNotifyAck_async_rpc(
mach_port_t server,
pid_t pid,
DiskArbDiskIdentifier diskIdentifier,
int errorCode)
{
kern_return_t err = 0;
DiskPtr diskPtr;
ClientPtr clientPtr;
dwarning(("%s(pid = %d, diskIdentifier = '%s', errorCode = %d)\n", __FUNCTION__, pid, diskIdentifier, errorCode));
clientPtr = LookupClientByPID( pid );
if ( ! clientPtr )
{
pwarning(("%s(pid = %d, diskIdentifier = '%s', errorCode = %d): no known client with this pid.\n", __FUNCTION__, pid, diskIdentifier, errorCode));
err = -1;
goto Return;
}
clientPtr->numAcksRequired--;
diskPtr = LookupDiskByIOBSDName( diskIdentifier );
if ( NULL == diskPtr )
{
dwarning(("%s(pid = %d, diskIdentifier = '%s', errorCode = %d): LookupDiskByIOBDSName failed\n", __FUNCTION__, pid, diskIdentifier, errorCode));
err = -1;
goto Return;
}
UpdateAckValue( diskPtr->ackValues, pid, errorCode );
dwarning(("%s: ack values for '%s'\n", __FUNCTION__, diskPtr->ioBSDName));
PrintAckValues( diskPtr->ackValues );
Return:
return err;
}
kern_return_t DiskArbEjectRequest_async_rpc (
mach_port_t server,
pid_t clientPid,
DiskArbDiskIdentifier diskIdentifier,
unsigned flags)
{
kern_return_t err = 0;
DiskPtr diskPtr;
ClientPtr clientPtr = LookupClientByPID(clientPid);
dwarning(("%s(diskIdentifier = '%s', flags = $%08x)\n", __FUNCTION__, diskIdentifier, flags));
diskPtr = LookupDiskByIOBSDName( diskIdentifier );
if ( NULL == diskPtr )
{
pwarning(("%s(diskIdentifier = '%s', flags = $%08x): LookupDiskByIOBDSName failed\n", __FUNCTION__, diskIdentifier, flags));
err = -1;
if (clientPtr) {
SendCallFailedMessage(clientPtr, NULL, kDiskArbEjectRequestFailed, kDiskArbVolumeDoesNotExist);
}
goto Return;
}
if (!requestingClientHasPermissionToModifyDisk(clientPid, diskPtr, "system.volume.eject")) {
err = -1;
if (clientPtr) {
SendCallFailedMessage(clientPtr, diskPtr, kDiskArbEjectRequestFailed, kDiskArbInsecureRequest);
}
goto Return;
}
if ( AreWeBusyForDisk(diskPtr) )
{
pwarning(("%s(diskIdentifier = '%s', flags = $%08x): already busy\n", __FUNCTION__, diskIdentifier, flags));
err = -1;
if (clientPtr) {
SendCallFailedMessage(clientPtr, diskPtr, kDiskArbEjectRequestFailed, kDiskArbIsBusy);
}
goto Return;
}
SetStateForAllPartitions( diskPtr, kDiskStateToBeEjected );
PrepareToSendPreEjectMsgs();
Return:
return err;
}
kern_return_t DiskArbEjectPreNotifyAck_async_rpc(
mach_port_t server,
pid_t pid,
DiskArbDiskIdentifier diskIdentifier,
int errorCode)
{
kern_return_t err = 0;
DiskPtr diskPtr;
ClientPtr clientPtr;
dwarning(("%s(pid = %d, diskIdentifier = '%s', errorCode = %d)\n", __FUNCTION__, pid, diskIdentifier, errorCode));
clientPtr = LookupClientByPID( pid );
if ( ! clientPtr )
{
pwarning(("%s(pid = %d, diskIdentifier = '%s', errorCode = %d): no known client with this pid.\n", __FUNCTION__, pid, diskIdentifier, errorCode));
err = -1;
goto Return;
}
clientPtr->numAcksRequired--;
diskPtr = LookupDiskByIOBSDName( diskIdentifier );
if ( NULL == diskPtr )
{
dwarning(("%s(pid = %d, diskIdentifier = '%s', errorCode = %d): LookupDiskByIOBDSName failed\n", __FUNCTION__, pid, diskIdentifier, errorCode));
err = -1;
goto Return;
}
UpdateAckValue( diskPtr->ackValues, pid, errorCode );
dwarning(("%s: ack values for '%s'\n", __FUNCTION__, diskPtr->ioBSDName));
PrintAckValues( diskPtr->ackValues );
Return:
return err;
}
kern_return_t DiskArbUnmountAndEjectRequest_async_rpc (
mach_port_t server,
pid_t clientPid,
DiskArbDiskIdentifier diskIdentifier,
unsigned flags)
{
kern_return_t err = 0;
DiskPtr diskPtr;
ClientPtr clientPtr = LookupClientByPID(clientPid);
dwarning(("%s(diskIdentifier = '%s', flags = $%08x)\n", __FUNCTION__, diskIdentifier, flags));
diskPtr = LookupDiskByIOBSDName( diskIdentifier );
if ( NULL == diskPtr )
{
pwarning(("%s(diskIdentifier = '%s', flags = $%08x): LookupDiskByIOBDSName failed\n", __FUNCTION__, diskIdentifier, flags));
err = -1;
if (clientPtr) {
SendCallFailedMessage(clientPtr, NULL, kDiskArbUnmountAndEjectRequestFailed, kDiskArbVolumeDoesNotExist);
}
goto Return;
}
if (!requestingClientHasPermissionToModifyDisk(clientPid, diskPtr, "system.volume.unmount.eject")) {
err = -1;
if (clientPtr) {
SendCallFailedMessage(clientPtr, diskPtr, kDiskArbUnmountAndEjectRequestFailed, kDiskArbInsecureRequest);
}
goto Return;
}
if ( AreWeBusyForDisk(diskPtr) )
{
pwarning(("%s(diskIdentifier = '%s', flags = $%08x): already busy\n", __FUNCTION__, diskIdentifier, flags));
err = -1;
if (clientPtr) {
SendCallFailedMessage(clientPtr, diskPtr, kDiskArbUnmountAndEjectRequestFailed, kDiskArbIsBusy);
}
goto Return;
}
if (flags & kDiskArbForceUnmountFlag) {
UnmountAllPartitions( diskPtr, TRUE );
}
SetStateForAllPartitions( diskPtr, kDiskStateToBeUnmountedAndEjected );
PrepareToSendPreUnmountMsgs();
Return:
return err;
}
kern_return_t DiskArbSetBlueBoxBootVolume_async_rpc (
mach_port_t server,
pid_t pid,
int seqno)
{
kern_return_t err = 0;
ClientPtr clientPtr;
dwarning(("%s(%d): old gBlueBoxBootVolume = %d\n", __FUNCTION__, seqno, GetBlueBoxBootVolume()));
clientPtr = LookupClientByPID( pid );
if ( ! clientPtr )
{
pwarning(("%s(pid=%d,seqno=%d): no known client with this pid.\n", __FUNCTION__, pid, seqno));
err = -1;
}
else
{
ClientPtr newClientPtr = LookupBlueBox();
if ( newClientPtr != NULL )
{
dwarning(("%s(pid=%d,seqno=%d): BlueBox client already exists with pid=%d\n",
__FUNCTION__, pid, seqno, newClientPtr->pid));
}
clientPtr->flags |= kDiskArbIAmBlueBox;
}
SetBlueBoxBootVolume( seqno );
return err;
}
kern_return_t DiskArbRequestDiskChange_rpc (
mach_port_t server,
pid_t clientPid,
DiskArbDiskIdentifier diskIdentifier,
DiskArbMountpoint mountPoint,
int flags)
{
kern_return_t err = 0;
DiskPtr diskPtr;
char deviceName[MAXPATHLEN];
int success = 0;
char cookieFile[MAXPATHLEN];
struct stat sb;
int i = 1;
ClientPtr clientPtr = LookupClientByPID(clientPid);
char newMountName[MAXPATHLEN];
char newVolumeName[MAXPATHLEN];
sprintf(deviceName, "/dev/r%s", (char *)diskIdentifier);
sprintf(newMountName, "%s/%s", (char *)mountPath(), (char *)mountPoint);
sprintf(newVolumeName, "%s", (char *)mountPoint);
sprintf(cookieFile, "/%s/%s", newMountName, ADM_COOKIE_FILE);
dwarning(("%s: renaming volume %s to %s and attempting to mount at %s\n", __FUNCTION__, diskIdentifier, mountPoint, newMountName));
diskPtr = LookupDiskByIOBSDName( diskIdentifier );
if ( NULL == diskPtr )
{
pwarning(("%s(diskIdentifier = '%s', flags = $%08x): LookupDiskByIOBDSName failed\n", __FUNCTION__, diskIdentifier, flags));
err = -1;
if (clientPtr) {
SendCallFailedMessage(clientPtr, NULL, kDiskArbDiskChangeRequestFailed, kDiskArbVolumeDoesNotExist);
}
goto Return;
}
if (diskPtr && IsNetwork(diskPtr)) {
err = -1;
if (clientPtr) {
SendCallFailedMessage(clientPtr, diskPtr, kDiskArbDiskChangeRequestFailed, kDiskArbDiskIsNetwork);
}
goto Return;
}
if (strcmp(newMountName, diskPtr->mountpoint) == 0) { dwarning(("%s: attempt to rename volume %s to %s. The name is the same.\n", __FUNCTION__, diskIdentifier, diskPtr->mountpoint));
SendDiskChangedMsgs(diskIdentifier, newMountName, newVolumeName, flags, kDiskArbRenameSuccessful);
return err;
}
while (1) {
if (stat(newMountName, &sb) < 0)
{
if (errno == ENOENT)
{
break;
}
else if (errno == EIO)
{
}
else
{
pwarning(("stat(%s) failed, %s\n", newMountName, strerror(errno)));
return (FALSE);
}
}
else if (rmdir(newMountName) == 0)
{
dwarning(("The asked for directory (%s) has been removed\n", newMountName));
break;
} else if (errno == ENOTEMPTY) {
if (stat(cookieFile, &sb) == 0) {
if (remove(cookieFile) == 0) {
if (rmdir(newMountName) == 0) {
break;
}
}
}
} else {
dwarning(("The asked for directory (%s) was not removed with errno = %d\n", newMountName, errno));
}
sprintf(newMountName, "%s/%s %d", mountPath(), mountPoint, i);
i++;
}
{
#warning - renaming devices is FS specific.
boolean_t is_hfs;
boolean_t is_ufs;
if (!diskPtr->mountedFilesystemName || !strlen(diskPtr->mountedFilesystemName)) {
err = -1;
goto Return;
} else {
is_hfs = (strcmp(diskPtr->mountedFilesystemName, "hfs") == 0);
is_ufs = (strcmp(diskPtr->mountedFilesystemName, "ufs") == 0);
}
if (is_hfs) {
struct attrlist alist;
struct volattrbuf volinfobuf;
int result;
alist.bitmapcount = 5;
alist.commonattr = 0;
alist.volattr = ATTR_VOL_INFO | ATTR_VOL_NAME;
alist.dirattr = 0;
alist.fileattr = 0;
alist.forkattr = 0;
result = getattrlist(diskPtr->mountpoint, &alist, &volinfobuf, sizeof(volinfobuf), 0);
if (result != 0) {
dwarning(("Hey! Couldn't get current volume name"));
};
strncpy(volinfobuf.va.volumenamestorage, mountPoint, sizeof(volinfobuf.va.volumenamestorage) - 1);
volinfobuf.va.volumenamestorage[sizeof(volinfobuf.va.volumenamestorage) - 1] = (char)0;
volinfobuf.va.volnameref.attr_dataoffset =
(char *)(&volinfobuf.va.volumenamestorage) - (char *)(&volinfobuf.va.volnameref);
volinfobuf.va.volnameref.attr_length = strlen(mountPoint);
result = setattrlist(diskPtr->mountpoint, &alist, &volinfobuf.va, sizeof(volinfobuf.va), 0);
if (result != 0) {
dwarning(("Hey! Couldn't change volume name"));
success = kDiskArbRenameUnsuccessful;
strcpy(newMountName, diskPtr->mountpoint);
} else {
if (strcmp(diskPtr->mountpoint, "/")) {
int ret = rename(diskPtr->mountpoint, newMountName);
if (ret == 0) {
DiskSetMountpoint(diskPtr, newMountName);
success = kDiskArbRenameSuccessful;
} else {
dwarning(("Hey! Couldn't change volume name, %d, %d return from rename\n", ret, errno));
success = kDiskArbRenameSuccessful | kDiskArbRenameRequiresRemount;
}
} else {
strcpy(newMountName, "/");
strcpy(diskPtr->mountpoint, "/");
}
success = kDiskArbRenameSuccessful;
}
}
else if (is_ufs)
{
if (renameUFSDevice(diskIdentifier, mountPoint)) {
if (strcmp(diskPtr->mountpoint, "/")) {
int ret = rename(diskPtr->mountpoint, newMountName);
if (ret == 0) {
DiskSetMountpoint(diskPtr, newMountName);
success = kDiskArbRenameSuccessful;
} else {
dwarning(("Hey! Couldn't change volume name, %d, %d return from rename\n", ret, errno));
success = kDiskArbRenameSuccessful | kDiskArbRenameRequiresRemount;
}
} else {
strcpy(diskPtr->mountpoint, "/");
strcpy(newMountName, "/");
}
success = kDiskArbRenameSuccessful;
} else {
dwarning(("Hey! Couldn't change volume name!"));
success = kDiskArbRenameUnsuccessful;
}
} else {
dwarning(("Hey! Couldn't change volume name since it isn't hfs or ufs!"));
success = kDiskArbRenameUnsuccessful;
}
SendDiskChangedMsgs(diskIdentifier, newMountName, newVolumeName, flags, success);
PrintDisks();
}
Return:
if (err == -1) {
SendDiskChangedMsgs(diskIdentifier, newMountName, newVolumeName, flags, kDiskArbRenameUnsuccessful);
}
return err;
}
kern_return_t DiskArbSetCurrentUser_rpc (
mach_port_t server,
pid_t clientPid,
int user)
{
if (user == -1) {
DiskPtr diskPtr;
for (diskPtr = g.Disks; diskPtr != NULL; diskPtr = diskPtr->next)
{
if (diskPtr->mountedUser == currentConsoleUser && ( diskPtr->flags & kDiskArbDiskAppearedEjectableMask ) ) {
if (diskPtr->ejectOnLogout) {
DiskArbUnmountAndEjectRequest_async_rpc( 0, 0, diskPtr->ioBSDName, FALSE);
} else {
DiskArbUnmountRequest_async_rpc( 0, 0, diskPtr->ioBSDName, FALSE);
diskPtr->mountedUser = user;
}
}
}
currentConsoleUser = user;
} else {
io_iterator_t ioIterator;
mach_port_t masterPort;
kern_return_t err;
currentConsoleUser = user;
err = IOMasterPort(bootstrap_port, &masterPort);
err = IOServiceGetMatchingServices(masterPort, IOServiceMatching("IOMedia"), &ioIterator);
GetDisksFromRegistry( ioIterator, 0 );
dwarning(("autodiskmount: Setting user to %d\n", user));
autodiskmount(TRUE);
}
return 0;
}
kern_return_t DiskArbSetVolumeEncoding_rpc (mach_port_t server,
pid_t clientPid,
DiskArbDiskIdentifier diskIdentifier,
int volumeEncoding)
{
DiskPtr diskPtr;
int isWritable;
char bsdPath[MAXPATHLEN];
char encodingString[MAXPATHLEN];
boolean_t is_hfs;
ClientPtr clientPtr = LookupClientByPID(clientPid);
diskPtr = LookupDiskByIOBSDName( diskIdentifier );
dwarning(("%s: change volume %s encoding to %d\n", __FUNCTION__, diskIdentifier, volumeEncoding));
if ( NULL == diskPtr )
{
pwarning(("%s(diskIdentifier = '%s'): LookupDiskByIOBDSName failed\n", __FUNCTION__, diskIdentifier));
if (clientPtr) {
SendCallFailedMessage(clientPtr, NULL, kDiskArbSetEncodingRequestFailed, kDiskArbVolumeDoesNotExist);
}
return -1;
}
if (!requestingClientHasPermissionToModifyDisk(clientPid, diskPtr, "system.volume.setencoding")) {
if (clientPtr) {
SendCallFailedMessage(clientPtr, diskPtr, kDiskArbSetEncodingRequestFailed, kDiskArbInsecureRequest);
}
return -1;
}
sprintf(bsdPath,"/dev/%s", diskIdentifier);
isWritable = ( diskPtr->flags & kDiskArbDiskAppearedLockedMask ) == 0;
is_hfs = (strcmp(diskPtr->mountedFilesystemName, "hfs") == 0);
if (!is_hfs) {
if (clientPtr) {
SendCallFailedMessage(clientPtr, diskPtr, kDiskArbSetEncodingRequestFailed, kDiskArbInvalidVolumeFormat);
}
return -1;
}
sprintf(encodingString, "-e=%d", volumeEncoding);
{
const char *childArgv[] = {
"/sbin/mount",
isWritable?"-u":"-ur",
"-o",
encodingString,
"-t",
"hfs",
bsdPath,
diskPtr->mountpoint,
0 };
int pid;
if ((pid = fork()) == 0)
{
cleanUpAfterFork();
execve("/sbin/mount", childArgv, 0);
exit(-127);
}
else if (pid > 0)
{
int statusp;
int waitResult;
int result;
dwarning(("wait4(pid=%d,&statusp,0,NULL)...\n", pid));
waitResult = wait4(pid,&statusp,0,NULL);
dwarning(("wait4(pid=%d,&statusp,0,NULL) => %d\n", pid, waitResult));
if (waitResult > 0)
{
if (WIFEXITED(statusp))
{
result = (int)(char)(WEXITSTATUS(statusp));
}
}
}
}
{
struct attrlist alist;
struct volattrbuf volinfobuf;
int result;
int success = kDiskArbRenameSuccessful;
struct stat sb;
char newMountName[MAXPATHLEN];
char cookieFile[MAXPATHLEN];
int i = 1;
alist.bitmapcount = 5;
alist.commonattr = 0;
alist.volattr = ATTR_VOL_INFO | ATTR_VOL_NAME;
alist.dirattr = 0;
alist.fileattr = 0;
alist.forkattr = 0;
result = getattrlist(diskPtr->mountpoint, &alist, &volinfobuf, sizeof(volinfobuf), 0);
if (result != 0) {
dwarning(("Hey! Couldn't get current volume name"));
};
sprintf(newMountName, "%s/%s", (char *)mountPath(), volinfobuf.va.volumenamestorage);
sprintf(cookieFile, "/%s/%s", newMountName, ADM_COOKIE_FILE);
if (strcmp(newMountName, diskPtr->mountpoint) != 0) {
while (1) {
if (stat(newMountName, &sb) < 0)
{
if (errno == ENOENT)
{
break;
}
else if (errno == EIO)
{
}
else
{
pwarning(("stat(%s) failed, %s\n", newMountName, strerror(errno)));
return (FALSE);
}
}
else if (rmdir(newMountName) == 0)
{
dwarning(("The asked for directory (%s) has been removed\n", newMountName));
break;
} else if (errno == ENOTEMPTY) {
if (stat(cookieFile, &sb) == 0) {
if (remove(cookieFile) == 0) {
if (rmdir(newMountName) == 0) {
break;
}
}
}
} else {
dwarning(("The asked for directory (%s) was not removed with errno = %d\n", newMountName, errno));
}
sprintf(newMountName, "%s/%s %d", mountPath(), volinfobuf.va.volumenamestorage, i);
i++;
}
dwarning(("Encoding changed which is forcing a rename on %s to %s\n", diskPtr->mountpoint, newMountName));
if (strcmp(newMountName, diskPtr->mountpoint) != 0) {
dwarning(("Encoding changed which is forcing a rename on %s to %s\n", diskPtr->mountpoint, newMountName));
if (strcmp(diskPtr->mountpoint, "/")) {
int ret = rename(diskPtr->mountpoint, newMountName);
if (ret == 0) {
DiskSetMountpoint(diskPtr, newMountName);
success = kDiskArbRenameSuccessful;
dwarning(("Changed volume name\n"));
} else {
dwarning(("Hey! Couldn't change volume name, %d, %d return from rename\n", ret, errno));
success = kDiskArbRenameUnsuccessful;
}
} else {
strcpy(diskPtr->mountpoint, "/");
success = kDiskArbRenameUnsuccessful;
}
}
}
SendDiskChangedMsgs(diskIdentifier, newMountName, volinfobuf.va.volumenamestorage, 0, success);
}
return 0;
}
kern_return_t DiskArbGetVolumeEncoding_rpc (mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
int *volumeEncoding)
{
DiskPtr diskPtr;
boolean_t is_hfs;
*volumeEncoding = -1;
diskPtr = LookupDiskByIOBSDName( diskIdentifier );
if (!diskPtr || !diskPtr->mountedFilesystemName) {
return 0;
}
is_hfs = (strcmp(diskPtr->mountedFilesystemName, "hfs") == 0);
if (is_hfs) {
struct attrlist alist;
struct cominfobuf cibuf;
int result;
alist.bitmapcount = 5;
alist.commonattr = ATTR_CMN_SCRIPT;
alist.volattr = 0;
alist.dirattr = 0;
alist.fileattr = 0;
alist.forkattr = 0;
result = getattrlist(diskPtr->mountpoint, &alist, &cibuf, sizeof(cibuf), 0);
if (result != 0) {
*volumeEncoding = -1;
} else {
*volumeEncoding = cibuf.ci.encoding;
}
}
return 0;
}
static ClientPtr LookupBlueBox( void )
{
ClientPtr result = NULL;
ClientPtr clientPtr;
dwarning(("=> %s()\n", __FUNCTION__));
for (clientPtr = g.Clients; clientPtr != NULL; clientPtr = clientPtr->next)
{
if ( clientPtr->flags & kDiskArbIAmBlueBox )
{
result = clientPtr;
goto Return;
}
}
result = NULL;
goto Return;
Return:
dwarning(("<= %s(): 0x%08x\n", __FUNCTION__, (int)result));
return result;
}
kern_return_t DiskArbPrinter_Request_rpc (
mach_port_t server,
pid_t pid,
int locationID)
{
kern_return_t err = 0;
ClientPtr clientPtr;
ClientPtr bbClientPtr;
dwarning(("=> %s(pid=%d,locationID=0x%08x)\n", __FUNCTION__, pid, locationID));
bbClientPtr = LookupBlueBox();
if ( ! bbClientPtr )
{
clientPtr = LookupClientByPID( pid );
if ( ! clientPtr )
{
dwarning(("%s(pid=%d,locationID=0x%08x): no known client with this pid.\n", __FUNCTION__, pid, locationID));
err = -1;
goto Return;
}
dwarning(("%s: Blue Box is not registered\n", __FUNCTION__));
#warning Should this be in a thread
err = DiskArbPrinter_FinalResponse_rpc( clientPtr->port, locationID, 0x00000001 );
goto Return;
}
#warning Should this be in a thread
err = DiskArbPrinter_FinalRequest_rpc( bbClientPtr->port, pid, locationID );
goto Return;
Return:
return err;
}
kern_return_t DiskArbPrinter_Response_rpc (
mach_port_t server,
pid_t pid,
int locationID,
int answer)
{
kern_return_t err = 0;
ClientPtr clientPtr;
dwarning(("%s(pid=%d,locationID=0x%08x,answer=0x%08x)\n", __FUNCTION__, pid, locationID, answer));
clientPtr = LookupClientByPID( pid );
if ( ! clientPtr )
{
dwarning(("%s(pid=%d,locationID=0x%08x,answer=0x%08x): no known client with this pid.\n", __FUNCTION__, pid, locationID, answer));
err = -1;
goto Return;
}
#warning Should this be in a thread
err = DiskArbPrinter_FinalResponse_rpc( clientPtr->port, locationID, answer );
goto Return;
Return:
return err;
}
kern_return_t DiskArbPrinter_Release_rpc (
mach_port_t server,
int locationID)
{
kern_return_t err = 0;
ClientPtr bbClientPtr;
dwarning(("=> %s(locationID=0x%08x)\n", __FUNCTION__, locationID));
bbClientPtr = LookupBlueBox();
if ( ! bbClientPtr )
{
dwarning(("%s: Blue Box is not registered\n", __FUNCTION__));
err = 0;
goto Return;
}
#warning Should this be in a thread
err = DiskArbPrinter_FinalRelease_rpc( bbClientPtr->port, locationID );
goto Return;
Return:
return err;
}
kern_return_t DiskArbIsDeviceReservedForClient_rpc ( mach_port_t server, DiskArbDiskIdentifier diskIdentifier, pid_t clientPid)
{
DiskPtr diskPtr;
DiskPtr wholePtr;
ClientPtr clientPtr;
int status = kDiskArbDeviceIsNotReserved;
int pid = 0;
clientPtr = LookupClientByPID(clientPid);
if ( ! clientPtr )
{
dwarning(("%s: client ptr not found %d", __FUNCTION__, clientPid));
return 0;
}
dwarning(("%s(diskIdentifier = '%s', from pid = '%d')\n", __FUNCTION__, diskIdentifier, clientPid));
diskPtr = LookupDiskByIOBSDName( diskIdentifier );
if (diskPtr) {
wholePtr = LookupWholeDiskForThisPartition( diskPtr );
} else {
dwarning(("%s: diskPtr not found %s", __FUNCTION__, diskIdentifier));
return 0;
}
if (!wholePtr) {
pwarning(("%s: wholePtr not found, cannot retain reservation on %s", __FUNCTION__, diskIdentifier));
}
if (wholePtr->retainingClient) {
status = kDiskArbDeviceIsReserved;
pid = wholePtr->retainingClient;
}
#warning Should this be in a thread
DiskArbDeviceReservationStatus_rpc(clientPtr->port, diskIdentifier, status, pid);
return 0;
}
kern_return_t DiskArbRetainClientReservationForDevice_rpc ( mach_port_t server, DiskArbDiskIdentifier diskIdentifier, pid_t clientPid)
{
DiskPtr diskPtr;
DiskPtr wholePtr;
ClientPtr clientPtr = LookupClientByPID(clientPid);
int pid = 0;
if ( ! clientPtr )
{
dwarning(("%s: client ptr not found %d", __FUNCTION__, clientPid));
return 0;
}
dwarning(("%s(diskIdentifier = '%s', pid = '%d')\n", __FUNCTION__, diskIdentifier, clientPid));
diskPtr = LookupDiskByIOBSDName( diskIdentifier );
if (diskPtr) {
wholePtr = LookupWholeDiskForThisPartition( diskPtr );
} else {
dwarning(("%s: diskPtr not found %s", __FUNCTION__, diskIdentifier));
return 0;
}
if (!wholePtr) {
pwarning(("%s: wholePtr not found, cannot retain reservation on %s", __FUNCTION__, diskIdentifier));
}
if (wholePtr->retainingClient) {
ClientPtr remoteClientPtr = LookupClientByPID(wholePtr->retainingClient);
if ( ! remoteClientPtr )
{
dwarning(("%s: client ptr not found %d", __FUNCTION__, wholePtr->retainingClient));
return 0;
}
#warning Should this be in a thread
DiskArbWillClientRelinquish_rpc(remoteClientPtr->port, diskIdentifier, clientPid);
} else {
wholePtr->retainingClient = clientPid;
pid = wholePtr->retainingClient;
#warning Should this be in a thread
DiskArbDeviceReservationStatus_rpc(clientPtr->port, diskIdentifier, kDiskArbDeviceReservationObtained, pid);
}
return 0;
}
kern_return_t DiskArbReleaseClientReservationForDevice_rpc ( mach_port_t server, DiskArbDiskIdentifier diskIdentifier, pid_t pid)
{
DiskPtr diskPtr;
DiskPtr wholePtr;
dwarning(("%s(diskIdentifier = '%s', pid = '%d')\n", __FUNCTION__, diskIdentifier, pid));
diskPtr = LookupDiskByIOBSDName( diskIdentifier );
if (diskPtr) {
wholePtr = LookupWholeDiskForThisPartition( diskPtr );
} else {
dwarning(("%s: diskPtr not found %s", __FUNCTION__, diskIdentifier));
return 0;
}
if (!wholePtr) {
pwarning(("%s: wholePtr not found, cannot release reservation on %s", __FUNCTION__, diskIdentifier));
} else if (wholePtr->retainingClient == pid) {
wholePtr->retainingClient = 0;
}
return 0;
}
kern_return_t DiskArbClientRelinquishesReservation_rpc ( mach_port_t server, DiskArbDiskIdentifier diskIdentifier, pid_t pid, pid_t releaseToClientPid, int status)
{
DiskPtr diskPtr;
DiskPtr wholePtr;
ClientPtr clientPtr = LookupClientByPID(releaseToClientPid);
if ( ! clientPtr )
{
dwarning(("%s: client ptr not found %d", __FUNCTION__, releaseToClientPid));
return 0;
}
dwarning(("%s(diskIdentifier = '%s', my pid = '%d', release to pid = '%d', status = '%d')\n", __FUNCTION__, diskIdentifier, pid, releaseToClientPid, status));
diskPtr = LookupDiskByIOBSDName( diskIdentifier );
if (diskPtr) {
wholePtr = LookupWholeDiskForThisPartition( diskPtr );
} else {
dwarning(("%s: diskPtr not found %s", __FUNCTION__, diskIdentifier));
return 0;
}
if (!wholePtr) {
pwarning(("%s: wholePtr not found, cannot release reservation on %s", __FUNCTION__, diskIdentifier));
return 0;
}
if (status) {
wholePtr->retainingClient = releaseToClientPid;
#warning Should this be in a thread
DiskArbDeviceReservationStatus_rpc(clientPtr->port, diskIdentifier, kDiskArbDeviceReservationObtained, releaseToClientPid);
} else {
wholePtr->retainingClient = pid;
#warning Should this be in a thread
DiskArbDeviceReservationStatus_rpc(clientPtr->port, diskIdentifier, kDiskArbDeviceReservationRefused, pid);
}
return 0;
}
kern_return_t DiskArbClientHandlesUnrecognizedDisks_rpc ( mach_port_t server, pid_t pid, int types, int priority)
{
ClientPtr clientPtr = LookupClientByPID(pid);
if (!clientPtr) {
dwarning(("%s : No client ptr for client pid %d\n", __FUNCTION__, pid));
} else {
clientPtr->unrecognizedPriority = priority;
clientPtr->notifyOnDiskTypes = types;
}
return 0;
}
kern_return_t DiskArbClientHandlesUninitializedDisks_rpc (
mach_port_t server,
int clientPid,
int flags)
{
kern_return_t err = 0;
ClientPtr clientPtr;
dwarning(("%s(%d:%d)\n", __FUNCTION__, clientPid, flags));
clientPtr = LookupClientByPID( clientPid );
if ( ! clientPtr )
{
dwarning(("%s(pid=%d,flags=%d): no known client with this pid.\n", __FUNCTION__, clientPid, flags));
err = -1;
}
else
{
if (flags) {
clientPtr->flags |= kDiskArbClientHandlesUninitializedDisks;
} else {
clientPtr->flags &= ~kDiskArbClientHandlesUninitializedDisks;
}
}
return err;
}
kern_return_t DiskArbClientWillHandleUnrecognizedDisk_rpc ( mach_port_t server, DiskArbDiskIdentifier diskIdentifier, pid_t pid, int yesNo)
{
DiskPtr diskPtr = LookupDiskByIOBSDName( diskIdentifier );
ClientPtr clientPtr = LookupClientByPID( pid );
clientPtr->ackOnUnrecognizedDisk = nil;
if (!clientPtr || !diskPtr) {
return 0;
}
if (yesNo == FALSE) {
diskPtr->state = kDiskStateNew;
} else {
DiskPtr wholePtr = LookupWholeDiskForThisPartition( diskPtr );
diskPtr->retainingClient = pid;
if (wholePtr) {
wholePtr->retainingClient = pid;
}
}
return 0;
}
kern_return_t DiskArbSetSecuritySettingsForClient_rpc ( mach_port_t server, pid_t pid, DiskArbSecurityToken token)
{
kern_return_t err = 0;
ClientPtr clientPtr = LookupClientByPID( pid );
if (!clientPtr) {
dwarning(("%s(pid=%d): no known client with this pid.\n", __FUNCTION__, pid));
err = -1;
} else {
AuthorizationRef ref;
int ok = AuthorizationCreateFromExternalForm((const AuthorizationExternalForm *)token, &ref);
if (0 == ok && ref) {
dwarning(("%s Setting token for (pid=%d)\n", __FUNCTION__, pid));
clientPtr->clientAuthRef = ref;
} else {
}
}
return err;
}
static void EjectAllCDAndDVDMedia()
{
DiskPtr diskPtr;
for (diskPtr = g.Disks; diskPtr != NULL; diskPtr = diskPtr->next)
{
DiskPtr wholePtr = LookupWholeDiskForThisPartition(diskPtr);
if (wholePtr == diskPtr) {
if ((diskPtr->flags & kDiskArbDiskAppearedCDROMMask) || (diskPtr->flags & kDiskArbDiskAppearedDVDROMMask)) {
DiskArbUnmountAndEjectRequest_async_rpc( 0, 0, diskPtr->ioBSDName, FALSE);
}
}
}
}
static void OpenVacantDriveDoor(io_registry_entry_t device)
{
io_registry_entry_t driver = 0;
io_registry_entry_t media = 0;
kern_return_t status = KERN_SUCCESS;
status = IORegistryEntryGetChildEntry(device, kIOServicePlane, &driver);
if (status != KERN_SUCCESS) goto OpenVacantDriveDoorErr;
status = IORegistryEntryGetChildEntry(driver, kIOServicePlane, &media);
if (status == KERN_SUCCESS) goto OpenVacantDriveDoorErr;
IORegistryEntrySetCFProperty(device, CFSTR("TrayState"), kCFBooleanTrue);
OpenVacantDriveDoorErr:
if (driver) IOObjectRelease(driver);
if (media) IOObjectRelease(media);
}
static void OpenAllVacantCDAndDVDDriveDoors()
{
CFMutableDictionaryRef description = 0;
mach_port_t masterPort = 0;
io_registry_entry_t device = 0;
io_iterator_t devices = 0;
kern_return_t status = KERN_SUCCESS;
status = IOMasterPort(bootstrap_port, &masterPort);
if (status != KERN_SUCCESS) goto OpenAllVacantCDAndDVDDriveDoorsErr;
description = IOServiceMatching("IOCDBlockStorageDevice");
if (description == 0) goto OpenAllVacantCDAndDVDDriveDoorsErr;
status = IOServiceGetMatchingServices(masterPort, description, &devices);
if (status != KERN_SUCCESS) goto OpenAllVacantCDAndDVDDriveDoorsErr;
description = 0;
while ( (device = IOIteratorNext(devices)) )
{
OpenVacantDriveDoor(device);
IOObjectRelease(device);
}
OpenAllVacantCDAndDVDDriveDoorsErr:
if (description) CFRelease(description);
if (devices) IOObjectRelease(devices);
}
kern_return_t DiskArbOpenVacantDriveDoors_rpc ( mach_port_t server )
{
OpenAllVacantCDAndDVDDriveDoors();
return 0;
}
kern_return_t DiskArbEjectKeyPressed_rpc ( mach_port_t server )
{
OpenAllVacantCDAndDVDDriveDoors();
EjectAllCDAndDVDMedia();
return 0;
}