DiskArbitrationServerMain.h [plain text]
#ifndef __DISK_ARB_SERVER_MAIN__
#define __DISK_ARB_SERVER_MAIN__
#include <mach/mach.h>
#include <sys/types.h>
#include <CoreFoundation/CoreFoundation.h>
#include <Security/Authorization.h>
#include <IOKit/IOKitLib.h>
#include "DiskArbitrationTypes.h"
#define PID_FILE "/var/run/autodiskmount.pid"
void LogErrorMessage(const char *format, ...);
extern int gDebug;
#define dwarning(a) { if (gDebug) { printf a; fflush(stdout); } }
#if 1
#define pwarning(a) { LogErrorMessage a; }
#else
#define pwarning(a) { printf a; fflush(stdout); }
#endif
#define DISKSTATE(x) (x)==kDiskStateIdle ? "Idle" : \
(x)==kDiskStateNew ? "New" : \
(x)==kDiskStateNewlyUnmounted ? "NewlyUnmounted" : \
(x)==kDiskStateNewlyEjected ? "NewlyEjected" : \
(x)==kDiskStateToBeUnmounted ? "ToBeUnmounted" : \
(x)==kDiskStateToBeEjected ? "ToBeEjected" : \
(x)==kDiskStateToBeUnmountedAndEjected ? "ToBeUnmountedAndEjected" : \
(x)==kDiskStateWaitingForMountApproval ? "WaitingForMountApproval" : \
(x)==kDiskStateMountApprovalDenied ? "ApprovalDenied" : \
"<UNKNOWN>"
#define STR(x) (x) ? (x) : "(null)"
void SetBlueBoxBootVolume( int seqno );
int GetBlueBoxBootVolume( void );
enum ClientState {
kClientStateIdle = 0,
kClientStateNew,
};
typedef enum ClientState ClientState;
enum
{
kDiskArbIAmBlueBox = 1 << 31,
kDiskArbClientHandlesUninitializedDisks = 1 << 30,
};
struct Client {
struct Client * next;
mach_port_t port;
pid_t pid;
unsigned flags;
ClientState state;
unsigned numAcksRequired;
int notifyOnDiskTypes;
int unrecognizedPriority;
void * ackOnUnrecognizedDisk;
AuthorizationRef clientAuthRef;
};
typedef struct Client Client;
typedef struct Client * ClientPtr;
ClientPtr NewClient( mach_port_t port, unsigned pid, unsigned flags );
void PrintClient(ClientPtr clientPtr);
void PrintClients(void);
ClientPtr LookupClientByPID( pid_t pid );
ClientPtr LookupClientByMachPort( mach_port_t port );
unsigned NumClientsDesiringAsyncNotification( void );
unsigned NumClientsDesiringAsyncNotificationOfType( int type );
enum AckState {
kSendMsg,
kWaitingForAck,
kAckReceived,
};
typedef enum AckState AckState;
struct AckValue {
pid_t pid;
AckState state;
int errorCode;
};
typedef struct AckValue AckValue;
struct AckValues {
int physicalLength;
int logicalLength;
AckValue * ackValues; };
typedef struct AckValues AckValues;
extern int currentConsoleUser;
AckValues * NewAckValues( int size );
void FreeAckValues( AckValues * p );
void InitAckValue( AckValues * p, pid_t pid );
void UpdateAckValue( AckValues * p, pid_t pid, int errorCode );
int NumUnsetAckValues( AckValues * p );
int NumUnsetAckValuesForAllDisks( void );
void PrintAckValues( AckValues * p );
AckValue * GetDissenterFromAckValues( AckValues * ackValuesPtr );
AckValue * GetDissenterFromAckValuesForAllDisks( void );
AckValue * GetUnresponderFromAckValues( AckValues * ackValuesPtr );
AckValue * GetUnresponderFromAckValuesForAllDisks( void );
void MakeDeadClientAgreeable( ClientPtr clientPtr );
void StartDiskRegistrationCompleteThread(ClientPtr client);
enum DiskState {
kDiskStateIdle = 0,
kDiskStateNew,
kDiskStateNewlyUnmounted,
kDiskStateNewlyEjected,
kDiskStateToBeUnmounted,
kDiskStateToBeEjected,
kDiskStateToBeUnmountedAndEjected,
kDiskStateUnrecognized,
kDiskStatePostponed,
kDiskStateWaitingForMountApproval,
kDiskStateMountApprovalDenied,
};
typedef enum DiskState DiskState;
enum DiskFamily {
kDiskFamily_Null = 0,
kDiskFamily_SCSI,
kDiskFamily_IDE,
kDiskFamily_Floppy,
kDiskFamily_File,
kDiskFamily_AFP,
};
typedef enum DiskFamily DiskFamily;
struct Disk {
struct Disk * next;
char * ioBSDName;
int ioBSDUnit;
char * ioContent;
char * ioMediaNameOrNull;
char * ioDeviceTreePath;
char * mountpoint;
char * mountedFilesystemName;
DiskFamily family;
unsigned flags;
int sequenceNumber; DiskState state;
AckValues * ackValues; int mountedUser;
io_object_t service;
int retainingClient; ClientPtr lastClientAttemptedForUnrecognizedMessages;
UInt64 ioSize;
unsigned int wholeDiskContainsMountedChild:1; unsigned int wholeDiskHasBeenYanked:1; unsigned int mountAttempted:1; unsigned int admCreatedMountPoint:1;
unsigned int ejectOnLogout:1; unsigned int forceTakeOwnershipOnDisk:1; unsigned int approvedForMounting:1;
double timeAppeared; char * volName; unsigned int unmountOrEjectRequestorUID;
};
typedef struct Disk Disk;
typedef struct Disk * DiskPtr;
DiskState AreWeBusyForDisk( DiskPtr diskPtr );
DiskPtr NewDisk( char * ioBSDName,
int ioBSDUnit,
char * ioContentOrNull,
DiskFamily family,
char * mountpoint,
char * ioMediaNameOrNull,
char * ioDeviceTreePathOrNull,
io_object_t service,
int mountingUIDFromDevice,
unsigned flags,
UInt64 size );
void FreeDisk( DiskPtr diskPtr );
void FreeAllPartitions( DiskPtr diskPtr );
void PrintDisks(void);
void DiskSetMountpoint( DiskPtr diskPtr, const char * mountpoint );
void DiskSetVolumeName( DiskPtr diskPtr, const char * volName );
DiskPtr LookupDiskByIOBSDName( char * ioBSDName );
int UnmountDisk( DiskPtr diskPtr, int forceUnmount );
int UnmountAllPartitions( DiskPtr diskPtr, int forceUnmount );
int EjectDisk( DiskPtr diskPtr );
void SetStateForOnePartition( DiskPtr diskPtr, DiskState newState );
void SetStateForAllPartitions( DiskPtr diskPtr, DiskState newState );
int NumPartitionsMountedFromThisDisk( DiskPtr diskPtr );
int NumPartitionsToBeUnmountedAndEjectedFromThisDisk( DiskPtr diskPtr );
DiskPtr LookupWholeDiskForThisPartition( DiskPtr diskPtr );
typedef void (*LookupWholeDisksForThisPartitionApplierFunction)( DiskPtr diskPtr );
void LookupWholeDisksForThisPartition( io_registry_entry_t service, LookupWholeDisksForThisPartitionApplierFunction applier );
DiskPtr LookupWholeDiskToBeEjected( void );
boolean_t IsWhole( DiskPtr diskPtr );
boolean_t IsNetwork( DiskPtr diskPtr );
void PrepareToSendPreUnmountMsgs( );
void PrepareToSendPreEjectMsgs( );
void PrepareToSendPreMountMsgsForDisk( DiskPtr diskPtr );
void SendUnrecognizedDiskMsgs(mach_port_t port, char *devname, char *fstype, char *deviceType, int isWritable, int isRemovable, int isWhole );
void SendUnrecognizedDiskArbitrationMsgs(mach_port_t port, char *devname, char *fstype, char *deviceType, int isWritable, int isRemovable, int isWhole, int diskType );
void SendDiskChangedMsgs(char *devname, char *newMountpoint, char *newVolumeName, int flags, int success);
void SendDiskWillBeCheckedMessages( DiskPtr disk );
void SendCallFailedMessage(ClientPtr clientPtr, DiskPtr diskPtr, int failedType, int error);
void SendCallSucceededMessage(ClientPtr clientPtr, DiskPtr diskPtr, int succeededType);
int SendDiskAppearedMsgs( void );
void SendPreMountMsgsForDisk( DiskPtr diskPtr );
void SendPreUnmountMsgsForDisk( DiskPtr diskPtr );
void SendPreEjectMsgsForDisk( DiskPtr diskPtr );
void SendUnmountPostNotifyMsgsForOnePartition( char * ioBSDName, int errorCode, pid_t pid );
void SendEjectPostNotifyMsgsForOnePartition( char * ioBSDName, int errorCode, pid_t pid );
void SendEjectPostNotifyMsgsForAllPartitions( DiskPtr diskPtr, int errorCode, pid_t pid );
void SendBlueBoxBootVolumeUpdatedMsgs( void );
void SendCompletedMsgs( int messageType, int newDisks );
void SendClientWasDisconnectedMsg(ClientPtr Client);
void CompleteEjectForDisk( DiskPtr diskPtr );
void CompleteUnmountForDisk( DiskPtr diskPtr );
char *mountPath( void );
void cleanUpAfterFork(int fdp[]);
boolean_t
do_exec(const char * dir, const char * argv[], int * result, char * * output);
int requestingClientHasPermissionToModifyDisk(pid_t pid, DiskPtr diskPtr, char *right);
kern_return_t DiskArbUnmountAndEjectRequest_async_rpc (
mach_port_t server, pid_t pid,
DiskArbDiskIdentifier diskIdentifier,
unsigned flags);
int DiskTypeForDisk(DiskPtr diskPtr);
ClientPtr GetNextClientForDisk(DiskPtr diskPtr);
int authorizationAllowedForEvent(ClientPtr client, char *event);
int DiskArbitrationServerMain(int argc, char* argv[]);
kern_return_t EnableDeathNotifications(mach_port_t port);
typedef struct {
boolean_t verbose;
boolean_t debug;
DiskPtr Disks;
unsigned NumDisks;
int NumDisksAddedOrDeleted; ClientPtr Clients;
unsigned NumClients;
int readOnlyBoot;
} GlobalStruct;
extern GlobalStruct g;
#define INTERNAL_MSG 10 // some random number I picked :)
typedef struct {
int diskAppearedType;
mach_port_t port;
char *ioBSDName; unsigned flags;
char *mountpoint; int pid;
char *ioDeviceTreePath;
char *ioContent; int sequenceNumber;
int diskType;
int isWritable;
int isRemovable;
int isWhole;
double timeAppeared;
char *fsName;
char *fsType;
} DiskThreadRecord;
DiskThreadRecord * NewDiskThreadRecord();
extern CFStringRef yankedHeader;
extern CFStringRef yankedMessage;
extern CFStringRef unrecognizedHeader;
extern CFStringRef unrecognizedHeaderNoInitialize;
extern CFStringRef unrecognizedMessage;
extern CFStringRef ejectString;
extern CFStringRef ignoreString;
extern CFStringRef initString;
extern CFStringRef launchString;
extern CFStringRef someDisk;
extern CFStringRef mountOrFsckFailed;
extern CFStringRef unknownString;
extern CFStringRef mountOrFsckFailedWithDiskUtility;
#define YANKED_MESSAGE CFSTR("")
#define UNINITED_MESSAGE CFSTR("")
#define UNINITED_HEADER CFSTR("You have inserted a disk containing no volumes that Mac OS X can read. To use the unreadable volumes, click Initialize. To continue with the disk inserted, click Ignore.")
#define UNINITED_HEADER_NO_INIT CFSTR("You have inserted a disk containing no volumes that Mac OS X can read. To continue with the disk inserted, click Ignore.")
#define YANKED_HEADER CFSTR("The device you removed was not properly put away. Data might have been lost or damaged. Before disconnecting a device, you should select its icon in the Finder and choose Eject from the File menu.")
#define EJECT_BUTTON CFSTR("Eject")
#define IGNORE_BUTTON CFSTR("Ignore")
#define INIT_BUTTON CFSTR("Initialize...")
#define LAUNCH_BUTTON CFSTR("Launch Disk Utility...")
#define A_DISK CFSTR("A disk attempting to mount as ")
#define MOUNT_FAILED_WITH_DU CFSTR(" has failed verification or has failed to mount. Please use Disk Utility to check the disk and correct any errors.")
#define MOUNT_FAILED CFSTR(" has failed verification or has failed to mount.")
#define UNKNOWN_STRING CFSTR("Unknown")
#endif