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 <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[32];
};
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);
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 );
}
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)
{
kern_return_t err = 0;
dwarning(("%s(diskIdentifier = '%s', flags = $%08x, mountpoint = '%s')\n", __FUNCTION__, diskIdentifier, flags, mountpoint));
if ( ! NewDisk( diskIdentifier,
0,
NULL,
kDiskFamily_AFP,
mountpoint,
NULL,
NULL,
NULL,
flags ) )
{
dwarning(("%s: NewDisk() failed!\n", __FUNCTION__));
}
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, "")))) {
diskPtr->mountpoint = 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;
SendDiskAppearedMsgs();
}
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,
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) {
free( diskPtr->mountpoint );
diskPtr->mountpoint = strdup( "" );
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 );
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 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,
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 )
{
pwarning(("%s(diskIdentifier = '%s', flags = $%08x): LookupDiskByIOBDSName failed\n", __FUNCTION__, diskIdentifier, flags));
err = -1;
goto Return;
}
if ( AreWeBusy() )
{
pwarning(("%s(diskIdentifier = '%s', flags = $%08x): already busy\n", __FUNCTION__, diskIdentifier, flags));
err = -1;
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,
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 )
{
pwarning(("%s(diskIdentifier = '%s', flags = $%08x): LookupDiskByIOBDSName failed\n", __FUNCTION__, diskIdentifier, flags));
err = -1;
goto Return;
}
if ( AreWeBusy() )
{
pwarning(("%s(diskIdentifier = '%s', flags = $%08x): already busy\n", __FUNCTION__, diskIdentifier, flags));
err = -1;
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,
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', flags = $%08x): LookupDiskByIOBDSName failed\n", __FUNCTION__, diskIdentifier, flags));
err = -1;
goto Return;
}
if ( AreWeBusy() )
{
pwarning(("%s(diskIdentifier = '%s', flags = $%08x): already busy\n", __FUNCTION__, diskIdentifier, flags));
err = -1;
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->flags |= kDiskArbIAmBlueBox;
}
SetBlueBoxBootVolume( seqno );
return err;
}
kern_return_t DiskArbRequestDiskChange_rpc (
mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
DiskArbMountpoint mountPoint,
int flags)
{
kern_return_t err = 0;
DiskPtr diskPtr;
char deviceName[MAXPATHLEN];
char newMountName[MAXPATHLEN];
char newVolumeName[MAXPATHLEN];
int success = 0;
char cookieFile[MAXPATHLEN];
struct stat sb;
int i = 1;
dwarning(("%s: renaming volume %s to %s\n", __FUNCTION__, diskIdentifier, mountPoint));
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);
diskPtr = LookupDiskByIOBSDName( diskIdentifier );
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++;
}
if ( ! diskPtr )
{
pwarning(("%s(id=%s): no known disk with this diskIdentifier.\n", __FUNCTION__, diskIdentifier));
err = -1;
}
else
{
#warning - renaming devices is FS specific.
boolean_t is_hfs = (strcmp(diskPtr->mountedFilesystemName, "hfs") == 0);
boolean_t 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) {
strcpy(diskPtr->mountpoint, 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) {
strcpy(diskPtr->mountpoint, 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 err;
}
kern_return_t DiskArbSetCurrentUser_rpc (
mach_port_t server,
int user)
{
currentConsoleUser = user;
if (user == -1) {
DiskPtr diskPtr;
for (diskPtr = g.Disks; diskPtr != NULL; diskPtr = diskPtr->next)
{
if (diskPtr->mountedUser != -1) {
UnmountAllPartitions(diskPtr, FALSE);
}
}
} else {
io_iterator_t ioIterator;
mach_port_t masterPort;
kern_return_t err;
err = IOMasterPort(bootstrap_port, &masterPort);
err = IOServiceGetMatchingServices(masterPort, IOServiceMatching("IOMedia"), &ioIterator);
GetDisksFromRegistry( ioIterator );
autodiskmount(FALSE);
}
return 0;
}
kern_return_t DiskArbSetVolumeEncoding_rpc (mach_port_t server,
DiskArbDiskIdentifier diskIdentifier,
int volumeEncoding)
{
char *encodingName;
DiskPtr diskPtr;
int isWritable;
char bsdPath[MAXPATHLEN];
char encodingString[MAXPATHLEN];
boolean_t is_hfs;
diskPtr = LookupDiskByIOBSDName( diskIdentifier );
if (!diskPtr) {
return 0;
}
sprintf(bsdPath,"/dev/%s", diskIdentifier);
isWritable = ( diskPtr->flags & kDiskArbDiskAppearedLockedMask ) == 0;
is_hfs = (strcmp(diskPtr->mountedFilesystemName, "hfs") == 0);
if (!is_hfs) {
return 0;
}
switch (volumeEncoding) {
case 0:
encodingName = "Roman";
break;
case 1:
encodingName = "Japanese";
break;
case 3:
encodingName = "Korean";
break;
case 4:
encodingName = "Arabic";
break;
case 5:
encodingName = "Hebrew";
break;
case 6:
encodingName = "Greek";
break;
case 7:
encodingName = "Cyrillic";
break;
default:
encodingName = "Roman";
break;
}
sprintf(encodingString, "-e=%s", encodingName);
{
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;
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);
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) {
if (strcmp(diskPtr->mountpoint, "/")) {
int ret = rename(diskPtr->mountpoint, newMountName);
if (ret == 0) {
strcpy(diskPtr->mountpoint, 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) {
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;
}
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;
}
static ClientPtr LookupBlueBox( void );
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__));
err = DiskArbPrinter_FinalResponse_rpc( clientPtr->port, locationID, 0x00000001 );
goto Return;
}
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;
}
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"));
err = 0;
goto Return;
}
err = DiskArbPrinter_FinalRelease_rpc( bbClientPtr->port, locationID );
goto Return;
Return:
return err;
}