#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 <sys/param.h>
#include <sys/mount.h>
#include <grp.h>
#include <ctype.h>
#include <dirent.h>
#include <pthread.h>
#include <mach/boolean.h>
#include <sys/loadable_fs.h>
#include <bsd/fsproperties.h>
#include <CoreFoundation/CoreFoundation.h>
#include "DiskVolume.h"
#include "GetRegistry.h"
#include "DiskArbitrationServerMain.h"
#include <errno.h>
#include <stdio.h>
#include <sys/attr.h>
#define kIsInvisible 0x4000
struct FinderInfo {
u_int32_t opaque_1[2];
u_int16_t fdFlags;
int16_t opaque_2[11];
};
typedef struct FinderInfo FinderInfo;
struct FinderAttrBuf {
unsigned long infoLength;
FinderInfo finderInfo;
};
typedef struct FinderAttrBuf FinderAttrBuf;
#define MAXNAMELEN 256
extern CFMutableArrayRef matchingArray;
int DiskArbIsHandlingUnrecognizedDisks(void)
{
ClientPtr clientPtr;
int i;
for (clientPtr = g.Clients, i = 0; clientPtr != NULL; clientPtr = clientPtr->next, i++)
{
if (clientPtr->flags & kDiskArbClientHandlesUninitializedDisks) {
return FALSE;
}
}
return TRUE;
}
extern mach_port_t gNotifyPort;
void * UnrecognizedDiskDiscovered(void * args)
{
DiskPtr diskPtr = args;
SInt32 retval = ERR_SUCCESS;
CFOptionFlags responseFlags;
CFURLRef daFrameworkURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("/System/Library/PrivateFrameworks/DiskArbitration.framework"), kCFURLPOSIXPathStyle, TRUE);
if (currentConsoleUser >= 0 ) { retval = CFUserNotificationDisplayAlert(60.0, kCFUserNotificationStopAlertLevel, NULL, NULL, daFrameworkURL, unrecognizedHeader, unrecognizedMessage, ejectString, ignoreString, initString, &responseFlags);
} else { retval = CFUserNotificationDisplayAlert(60.0, kCFUserNotificationStopAlertLevel, NULL, NULL, daFrameworkURL, unrecognizedHeader, unrecognizedMessage, ejectString, ignoreString, NULL, &responseFlags);
}
if (responseFlags == kCFUserNotificationDefaultResponse) {
DiskPtr localPtr = LookupWholeDiskForThisPartition(diskPtr);
if (localPtr && localPtr->state != kDiskStateNewlyEjected) {
mach_msg_empty_send_t msg;
if (diskPtr->ioBSDName) {
DiskArbUnmountAndEjectRequest_async_rpc( 0, diskPtr->ioBSDName, FALSE);
}
msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
msg.header.msgh_size = sizeof(msg);
msg.header.msgh_remote_port = gNotifyPort;
msg.header.msgh_local_port = NULL;
msg.header.msgh_id = INTERNAL_MSG;
mach_msg(&msg.header,
MACH_SEND_MSG,
msg.header.msgh_size,
0,
MACH_PORT_NULL,
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL);
}
} else if (responseFlags == kCFUserNotificationAlternateResponse) {
} else if (responseFlags == kCFUserNotificationOtherResponse) {
if (currentConsoleUser >= 0) {
seteuid(currentConsoleUser);
system("/usr/bin/open \"/Applications/Utilities/Disk Utility.app\"");
seteuid(0);
}
}
CFRelease(daFrameworkURL);
return NULL;
}
void StartUnrecognizedDiskDialogThread(DiskPtr disk)
{
pthread_attr_t attr;
pthread_t tid;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&tid, &attr, UnrecognizedDiskDiscovered, disk);
pthread_attr_destroy(&attr);
}
static void
eject_media(char * dev)
{
int fd;
char specName[MAXNAMELEN];
sprintf(specName, "/dev/r%s", dev);
fd = open(specName, O_RDONLY | O_NDELAY);
if ( fd >= 0 )
{
if (ioctl(fd, DKIOCEJECT, 0) < 0)
{
pwarning(("eject %s failed: %s\n", dev, strerror(errno)));
}
close(fd);
}
return;
}
static struct statfs *
get_fsstat_list(int * number)
{
int n;
struct statfs * stat_p;
n = getfsstat(NULL, 0, MNT_NOWAIT);
if (n <= 0)
{
return (NULL);
}
stat_p = (struct statfs *)malloc(n * sizeof(*stat_p));
if (stat_p == NULL)
{
return (NULL);
}
if (getfsstat(stat_p, n * sizeof(*stat_p), MNT_NOWAIT) <= 0)
{
free(stat_p);
return (NULL);
}
*number = n;
return (stat_p);
}
static struct statfs *
fsstat_lookup_spec(struct statfs * list_p, int n, char * spec, char * fstype)
{
char alt_spec[MAXNAMELEN];
int i;
struct statfs * scan;
sprintf(alt_spec, "/private%s", spec);
for (i = 0, scan = list_p; i < n; i++, scan++)
{
if (strcmp(scan->f_fstypename, fstype) == 0
&& (strcmp(scan->f_mntfromname, spec) == 0
|| strcmp(scan->f_mntfromname, alt_spec) == 0))
{
return (scan);
}
}
return (NULL);
}
boolean_t
fsck_needed(char * devname, char * fstype)
{
char command[1024];
FILE * f;
int ret;
struct stat sb;
char fsck_command_line[1024];
char *fsckCmd = repairPathForFileSystem(fstype);
sprintf(command, "%s -q /dev/r%s", fsckCmd, devname);
sprintf(fsck_command_line, fsckCmd);
{
if (stat(fsck_command_line, &sb) != 0) {
dwarning(("%s: '%s' not found...\n", __FUNCTION__, fsck_command_line));
return (FALSE);
}
}
dwarning(("%s('%s'): '%s'...\n", __FUNCTION__, devname, command));
f = popen(command, "w");
if (f == NULL)
{
dwarning(("%s('%s'): popen('%s') failed", __FUNCTION__, devname, command));
return (FALSE);
}
fflush(f);
ret = pclose(f);
free(fsckCmd);
dwarning(("%s('%s'): '%s' => %d\n", __FUNCTION__, devname, command, ret));
if (ret <= 0)
{
return (FALSE);
}
return (TRUE);
}
#define FILESYSTEM_ERROR 0
#define FILESYSTEM_MOUNTED 1
#define FILESYSTEM_MOUNTED_ALREADY 2
#define FILESYSTEM_NEEDS_REPAIR 3
static char *
foreignLabel(char * fsName)
{
int fd;
static char theLabel[MAXNAMELEN], buf[MAXPATHLEN];
sprintf(buf, "%s/%s%s/%s%s", FS_DIR_LOCATION, fsName, FS_DIR_SUFFIX, fsName, FS_LABEL_SUFFIX);
fd = open(buf, O_RDONLY, 0);
if (fd >= 0)
{
int i = read(fd, theLabel, 255);
close(fd);
if (i > 0)
{
theLabel[i] = '\0';
return (theLabel);
}
}
return (NULL);
}
static int
foreignProbe(const char *fsName, const char *execPath, const char *probeCmd, const char *devName, int removable, int writable)
{
int result;
const char *childArgv[] = { execPath,
probeCmd,
devName,
removable ? DEVICE_REMOVABLE : DEVICE_FIXED,
writable? DEVICE_WRITABLE : DEVICE_READONLY,
0 };
char *fsDir = fsDirForFS((char *)fsName);
int pid;
dwarning(("%s('%s', '%s', removable=%d, writable=%d):\n'%s %s %s %s %s'\n",
__FUNCTION__, fsName, devName, removable, writable, execPath, childArgv[1], childArgv[2], childArgv[3], childArgv[4]));
if (access(execPath,F_OK) == 0)
{
if ((pid = fork()) == 0)
{
cleanUpAfterFork();
chdir(fsDir);
execve(execPath, childArgv, 0);
exit(-127);
}
else if (pid > 0)
{
int statusp;
int waitResult;
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));
goto Return;
}
}
}
}
result = FSUR_IO_FAIL;
Return:
free(fsDir);
dwarning(("%s(...) => %d\n", __FUNCTION__, result));
return result;
}
static int foreignMountDevice(const char *fsName, const char *execPath, const char *devName, int removable, int writable, const char *mountPoint)
{
int result;
char cmd[] = {'-', FSUC_MOUNT, 0};
const char *childArgv[] = { execPath,
cmd,
devName,
mountPoint,
removable ? DEVICE_REMOVABLE : DEVICE_FIXED,
writable? DEVICE_WRITABLE : DEVICE_READONLY,
0 };
char *fsDir = fsDirForFS((char *)fsName);
int pid;
dwarning(("%s('%s', '%s', removable=%d, writable=%d, '%s'):\n'%s %s %s %s %s %s'\n",
__FUNCTION__, fsName, devName, removable, writable, mountPoint, execPath, childArgv[1], childArgv[2], childArgv[3], childArgv[4], childArgv[5]));
if ((pid = fork()) == 0)
{
cleanUpAfterFork();
chdir(fsDir);
execve(execPath, childArgv, 0);
exit(-127);
}
else if (pid > 0)
{
int statusp;
int waitResult;
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))
{
int i = (int)(char)(WEXITSTATUS(statusp));
if (i == FSUR_IO_SUCCESS)
{
result = FILESYSTEM_MOUNTED;
goto Return;
}
else if (i == FSUR_IO_UNCLEAN)
{
result = FILESYSTEM_NEEDS_REPAIR;
goto Return;
}
}
}
}
result = FILESYSTEM_ERROR;
Return:
free(execPath);
free(fsDir);
dwarning(("%s(...) => %d\n", __FUNCTION__, result));
return result;
}
boolean_t DiskVolume_mount_foreign(DiskVolumePtr diskVolume)
{
int ret;
ret = foreignMountDevice(diskVolume->fs_type,diskVolume->util_path, diskVolume->disk_dev_name,diskVolume->removable,diskVolume->writable,diskVolume->mount_point);
if (ret == FILESYSTEM_MOUNTED)
{
printf("Mounted %s /dev/%s on %s\n", diskVolume->fs_type, diskVolume->disk_dev_name, diskVolume->mount_point);
DiskVolume_setMounted(diskVolume,TRUE);
return (TRUE);
}
else if (ret == FILESYSTEM_NEEDS_REPAIR)
{
char m_command[1024];
char *fsckCmd = repairPathForFileSystem(diskVolume->fs_type);
char *rprCmd = repairArgsForFileSystem(diskVolume->fs_type);
sprintf(m_command, "%s %s /dev/r%s", fsckCmd, rprCmd, diskVolume->disk_dev_name);
{
FILE * f;
int ret;
dwarning(("%s: command to execute is '%s'\n", __FUNCTION__, m_command));
f = popen(m_command, "w");
if (f == NULL)
{
dwarning(("%s: popen('%s') failed", __FUNCTION__, m_command));
ret = 0;
} else {
fflush(f);
ret = pclose(f);
if ( ret >= 0 )
{
pwarning(("%s: pclose('%s') failed\n", __FUNCTION__, m_command));
return (FALSE);
}
}
}
ret = foreignMountDevice(diskVolume->fs_type, diskVolume->util_path, diskVolume->disk_dev_name, diskVolume->removable, diskVolume->writable, diskVolume->mount_point);
if (ret == FILESYSTEM_MOUNTED)
{
pwarning(("Mounted %s /dev/%s on %s\n", diskVolume->fs_type, diskVolume->disk_dev_name, diskVolume->mount_point));
DiskVolume_setMounted(diskVolume,TRUE);
return (TRUE);
}
else
{
return (FALSE);
}
free(fsckCmd);
free(rprCmd);
}
else if (ret == FILESYSTEM_ERROR)
{
pwarning(("%s: There is a filesystem error with the device %s which was attempting to mount at %s\n", __FUNCTION__, diskVolume->disk_dev_name, diskVolume->mount_point));
}
else
{
pwarning(("%s: unrecognized return code from foreignMountDevice: %d\n", __FUNCTION__, ret));
}
return (FALSE);
}
boolean_t DiskVolume_mount(DiskVolumePtr diskVolume)
{
DiskPtr dp = LookupDiskByIOBSDName( diskVolume->disk_dev_name );
if (dp) {
if ((dp->flags & kDiskArbDiskAppearedNoMountMask) != 0) {
return (FALSE); };
}
#warning Using mount command to mount UFS here - this needs to change to using ufs.util through pluggable
if (strcmp(diskVolume->fs_type, FS_TYPE_UFS) == 0)
return DiskVolume_mount_ufs(diskVolume);
else
return DiskVolume_mount_foreign(diskVolume);
return (FALSE);
}
#define FORMAT_STRING "%-10s %-6s %-8s %-5s %-5s %-16s %-16s\n"
void DiskVolume_print(DiskVolumePtr diskVolume){
pwarning((FORMAT_STRING,
diskVolume->disk_dev_name,
diskVolume->dev_type,
diskVolume->fs_type,
!diskVolume->removable ? "yes" : "no",
diskVolume->writable ? "yes" : "no",
diskVolume->disk_name,
diskVolume->mounted ? diskVolume->mount_point : "[not mounted]" ));
}
void setVar(char **var,char *val)
{
if (*var)
{
free(*var);
}
if (val == NULL)
{
*var = NULL;
}
else
{
*var = strdup(val);
}
}
void DiskVolume_setFSType(DiskVolumePtr diskVolume,char *t)
{
setVar(&(diskVolume->fs_type),t);
}
void DiskVolume_setDeviceType(DiskVolumePtr diskVolume,char *t)
{
setVar(&(diskVolume->dev_type),t);
}
void DiskVolume_setDiskName(DiskVolumePtr diskVolume,char *t)
{
setVar(&(diskVolume->disk_name),t);
}
void DiskVolume_setUtilPath(DiskVolumePtr diskVolume,char *t)
{
setVar(&(diskVolume->util_path),t);
}
void DiskVolume_setDiskDevName(DiskVolumePtr diskVolume,char *t)
{
setVar(&(diskVolume->disk_dev_name),t);
}
void DiskVolume_setMountPoint(DiskVolumePtr diskVolume,char *t)
{
setVar(&(diskVolume->mount_point),t);
}
void DiskVolume_setMounted(DiskVolumePtr diskVolume,boolean_t val)
{
if(val) {
DiskPtr dp = LookupDiskByIOBSDName( diskVolume->disk_dev_name );
if (dp) {
dp->mountedFilesystemName = strdup(diskVolume->fs_type);
}
}
diskVolume->mounted = val;
}
void DiskVolume_setWritable(DiskVolumePtr diskVolume,boolean_t val)
{
diskVolume->writable = val;
}
void DiskVolume_setRemovable(DiskVolumePtr diskVolume,boolean_t val)
{
diskVolume->removable = val;
}
void DiskVolume_setDirtyFS(DiskVolumePtr diskVolume,boolean_t val)
{
diskVolume->dirty = val;
}
void DiskVolume_new(DiskVolumePtr *diskVolume)
{
*diskVolume = malloc(sizeof(DiskVolume));
(*diskVolume)->fs_type = nil;
(*diskVolume)->disk_dev_name = nil;
(*diskVolume)->dev_type = nil;
(*diskVolume)->disk_name = nil;
(*diskVolume)->mount_point = nil;
(*diskVolume)->util_path = nil;
}
void DiskVolume_delete(DiskVolumePtr diskVolume)
{
int i;
char * * l[] = { &(diskVolume->fs_type),
&(diskVolume->disk_dev_name),
&(diskVolume->dev_type),
&(diskVolume->disk_name),
&(diskVolume->mount_point),
NULL };
if(!diskVolume)
free(diskVolume);
for (i = 0; l[i] != NULL; i++)
{
if (*(l[i]))
{
free(*(l[i]));
}
*(l[i]) = NULL;
}
free(diskVolume);
}
extern mach_port_t ioMasterPort;
DiskVolumePtr DiskVolumes_newVolume(DiskVolumesPtr diskList,DiskPtr media,boolean_t isRemovable,boolean_t isWritable,char *type,struct statfs* stat_p,int stat_number)
{
char * devname = media->ioBSDName;
struct statfs * fs_p;
char * fsname;
int ret;
char specName[MAXNAMELEN];
DiskVolumePtr volume = nil;
int matchingPointer = 0;
for (matchingPointer = 0;matchingPointer < CFArrayGetCount(matchingArray);matchingPointer++) {
int matches;
CFDictionaryRef dictPointer = CFArrayGetValueAtIndex(matchingArray, matchingPointer);
CFDictionaryRef mediaProps = CFDictionaryGetValue(dictPointer, CFSTR(kFSMediaPropertiesKey));
kern_return_t error;
error = IOServiceMatchPropertyTable(media->service, mediaProps, &matches);
if (error) {
dwarning(("some kind of error while matching service to array... %d\n", error));
}
if (matches) {
CFStringRef utilArgsFromDict;
CFStringRef fsNameFromDict;
CFArrayRef fsNameArray;
CFStringRef utilPathFromDict;
char *utilPathFromDict2;
char *utilArgsFromDict2;
char *fsNameFromDict2;
char *fstype;
char utilPath[MAXPATHLEN];
dwarning(("********We have a match for devname = %s!!!**********\n", devname));
utilArgsFromDict = CFDictionaryGetValue(dictPointer, CFSTR(kFSProbeArgumentsKey));
fsNameFromDict = CFDictionaryGetValue(dictPointer, CFSTR("FSName"));
fsNameArray = CFStringCreateArrayBySeparatingStrings(NULL, fsNameFromDict, CFSTR("."));
utilPathFromDict = CFDictionaryGetValue(dictPointer, CFSTR(kFSProbeExecutableKey));
utilPathFromDict2 = daCreateCStringFromCFString(utilPathFromDict);
utilArgsFromDict2 = daCreateCStringFromCFString(utilArgsFromDict);
fsNameFromDict2 = daCreateCStringFromCFString(fsNameFromDict);
fstype = daCreateCStringFromCFString(CFArrayGetValueAtIndex(fsNameArray, 0));
sprintf(utilPath, "%s%s", resourcePathForFSName(fsNameFromDict2), utilPathFromDict2);
sprintf(specName,"/dev/%s",devname);
ret = foreignProbe(fstype, utilPath, utilArgsFromDict2, devname, isRemovable, isWritable);
if (ret == FSUR_RECOGNIZED || ret == -9)
{
fsname = foreignLabel(fstype);
if (fsname == NULL) {
#warning This is a leak. foreignLabel returns a static char * - I am returning a malloced char *
printf("**************** Label not used ...\n");
fsname = fsNameForFSWithMediaName(fstype, media->ioMediaNameOrNull);
}
DiskVolume_new(&volume);
DiskVolume_setDiskDevName(volume,devname);
DiskVolume_setFSType(volume,fstype);
DiskVolume_setDiskName(volume,fsname);
DiskVolume_setDeviceType(volume,type);
DiskVolume_setWritable(volume,isWritable);
DiskVolume_setRemovable(volume,isRemovable);
DiskVolume_setMounted(volume,FALSE);
DiskVolume_setDirtyFS(volume,FALSE);
DiskVolume_setUtilPath(volume, utilPath);
fs_p = fsstat_lookup_spec(stat_p, stat_number, specName, fstype);
if (fs_p)
{
DiskVolume_setMounted(volume,TRUE);
DiskVolume_setMountPoint(volume,fs_p->f_mntonname);
}
else if (isWritable)
{
DiskVolume_setDirtyFS(volume,fsck_needed(devname,fstype));
}
break;
}
CFRelease(fsNameArray);
free(utilPathFromDict2);
free(utilArgsFromDict2);
free(fsNameFromDict2);
free(fstype);
}
}
return volume;
}
void DiskVolumes_new(DiskVolumesPtr *diskList)
{
*diskList = malloc(sizeof(DiskVolumes));
(*diskList)->list = CFArrayCreateMutable(NULL,0,NULL);
CFRetain((*diskList)->list);
}
void DiskVolumes_delete(DiskVolumesPtr diskList)
{
int i;
int count = CFArrayGetCount(diskList->list);
if(!diskList)
return;
for (i = 0; i < count; i++)
{
DiskVolume_delete((DiskVolumePtr)CFArrayGetValueAtIndex(diskList->list,i));
}
CFArrayRemoveAllValues(diskList->list);
CFRelease(diskList->list);
free(diskList);
}
static int CanSkipContentType(char * contentType) {
if (strcmp(contentType, "Apple_partition_map") == 0) {
return 1;
} else if (strcmp(contentType, "Apple_Partition_Map") == 0) {
return 1;
} else if (strcmp(contentType, "Apple_Driver") == 0) {
return 1;
} else if (strcmp(contentType, "Apple_Driver43") == 0) {
return 1;
} else if (strcmp(contentType, "Apple_Driver43_CD") == 0) {
return 1;
} else if (strcmp(contentType, "Apple_Driver_ATA") == 0) {
return 1;
} else if (strcmp(contentType, "Apple_Driver_ATAPI") == 0) {
return 1;
} else if (strcmp(contentType, "Apple_Driver_IOKit") == 0) {
return 1;
} else if (strcmp(contentType, "Apple_FWDriver") == 0) {
return 1;
} else if (strcmp(contentType, "Apple_Patches") == 0) {
return 1;
} else if (strcmp(contentType, "Apple_Boot") == 0) {
return 1;
} else if (strcmp(contentType, "Apple_Bootstrap") == 0) {
return 1;
} else if (strcmp(contentType, "Apple_Loader") == 0) {
return 1;
} else if (strcmp(contentType, "Apple_Rhapsody_Loader") == 0) {
return 1;
} else if (strcmp(contentType, "Apple_Free") == 0) {
return 1;
} else if (strcmp(contentType, "Apple_Void") == 0) {
return 1;
} else if (strcmp(contentType, "CD_DA") == 0) {
return 1;
} else if (strcmp(contentType, "CD_ROM_Mode_2") == 0) {
return 1;
} else if (strcmp(contentType, "CD_ROM_Mode_2_XA_Form_2") == 0) {
return 1;
}
return 0;
}
DiskVolumesPtr DiskVolumes_do_removable(DiskVolumesPtr diskList,boolean_t do_removable,boolean_t eject_removable)
{
DiskPtr diskPtr;
boolean_t success = FALSE;
struct statfs * stat_p;
int stat_number;
char * type = "???";
int nfs = 0;
struct dirent **fsdirs = NULL;
int n;
stat_p = get_fsstat_list(&stat_number);
if (stat_p == NULL || stat_number == 0)
{
goto Return;
}
nfs = scandir(FS_DIR_LOCATION, &fsdirs, suffixfs, sortfs);
for (n = 0; n < nfs; n++)
{
*strrchr(&fsdirs[n]->d_name[0], '.') = '\0';
}
if ( gDebug ) {
dwarning(("%d filesystems known:\n", nfs));
for (n=0; n<nfs; n++)
{
dwarning(("%s\n", &fsdirs[n]->d_name[0]));
}
}
for (diskPtr = g.Disks; diskPtr != NULL; diskPtr = diskPtr->next )
{
int isWhole, isWritable, isRemovable;
DiskVolumePtr volume = nil;
if ( kDiskStateNew != diskPtr->state )
{
continue;
}
isWhole = ( diskPtr->flags & kDiskArbDiskAppearedWholeDiskMask ) != 0;
isWritable = ( diskPtr->flags & kDiskArbDiskAppearedLockedMask ) == 0;
isRemovable = ( diskPtr->flags & kDiskArbDiskAppearedEjectableMask ) != 0;
if (isRemovable && do_removable == FALSE)
{
if (eject_removable)
{
eject_media(diskPtr->ioBSDName);
}
continue;
}
if (CanSkipContentType(diskPtr->ioContent)) {
continue;
}
volume = DiskVolumes_newVolume(diskList,
diskPtr,
isRemovable,
isWritable,
type,
stat_p,
stat_number);
if (!volume && strncmp(FS_RESERVED_PREFIX, diskPtr->ioContent, strlen(FS_RESERVED_PREFIX))) {
diskPtr->flags = diskPtr->flags | kDiskArbDiskAppearedUnrecognizableFormat;
}
if (volume != nil) {
CFArrayAppendValue(diskList->list,volume);
}
}
success = TRUE;
Return:
if (fsdirs) {
for (n = 0; n < nfs; n++) {
free((void *)fsdirs[n]);
}
free((void *)fsdirs);
}
if (stat_p)
{
free(stat_p);
}
if (success)
{
return diskList;
}
DiskVolumes_delete(diskList);
return nil;
}
DiskVolumesPtr DiskVolumes_print(DiskVolumesPtr diskList)
{
int i;
printf( FORMAT_STRING,
"DiskDev",
"Type",
"FileSys",
"Fixed",
"Write",
"Volume Name",
"Mounted On" );
for (i = 0; i < CFArrayGetCount(diskList->list); i++)
{
DiskVolume_print((DiskVolumePtr)CFArrayGetValueAtIndex(diskList->list,i));
}
return diskList;
}
unsigned DiskVolumes_count(DiskVolumesPtr diskList)
{
return CFArrayGetCount(diskList->list);
}
DiskVolumePtr DiskVolumes_objectAtIndex(DiskVolumesPtr diskList,int index)
{
return (DiskVolumePtr)CFArrayGetValueAtIndex(diskList->list,index);
}
DiskVolumePtr DiskVolumes_volumeWithMount(DiskVolumesPtr diskList,char *path)
{
int i;
int listSize = CFArrayGetCount(diskList->list);
for (i = 0; i < listSize; i++) {
DiskVolumePtr d = (DiskVolumePtr)CFArrayGetValueAtIndex(diskList->list,i);
if (d->mounted && d->mount_point && strcmp(d->mount_point, path) == 0){
return (d);
}
}
return (nil);
}
char *mountPath(void)
{
struct stat sb;
char * mountPath = "/Volumes";
if (stat(mountPath, &sb) < 0)
{
if (errno == ENOENT)
{
if (mkdir(mountPath, 01777) < 0)
{
pwarning(("mountDisks: mkdir(%s) failed, %s\n", mountPath, strerror(errno)));
return "/";
}
}
else
{
pwarning(("stat(%s) failed, %s\n", mountPath, strerror(errno)));
return "/";
}
}
if (chmod(mountPath, 01777) < 0)
{
pwarning(("%s: chmod(%s) failed: %s\n", __FUNCTION__, mountPath, strerror(errno)));
}
return "/Volumes";
}
boolean_t DiskVolumes_setVolumeMountPoint(DiskVolumesPtr diskList,DiskVolumePtr vol)
{
DiskVolumePtr disk = vol;
int i = 1;
mode_t mode = mountModeForFS(disk->fs_type);
char mount_path[MAXLBLLEN + 32];
char possible_mount_path[MAXLBLLEN + 32];
struct stat sb;
FILE *fp;
char cookieFile[MAXPATHLEN];
char *index;
sprintf(possible_mount_path, "%s", disk->disk_name);
index = strchr(possible_mount_path, '/');
while (index != NULL) {
*index = ':';
index = strchr(possible_mount_path, '/');
}
sprintf(mount_path, "%s/%s", mountPath(), possible_mount_path);
sprintf(cookieFile, "/%s/%s", mount_path, ADM_COOKIE_FILE);
while (1)
{
if (stat(mount_path, &sb) < 0)
{
if (errno == ENOENT)
{
break;
}
else if (errno == EIO)
{
}
else
{
pwarning(("stat(%s) failed, %s\n", mount_path, strerror(errno)));
return (FALSE);
}
}
else if (DiskVolumes_volumeWithMount(diskList,mount_path))
{
}
else if (rmdir(mount_path) == 0)
{
break;
}
else if (errno == ENOTEMPTY) {
if (stat(cookieFile, &sb) == 0) {
if (remove(cookieFile) == 0) {
if (rmdir(mount_path) == 0) {
break;
}
}
}
}
sprintf(mount_path, "%s/%s %d", mountPath() ,disk->disk_name, i);
sprintf(cookieFile, "/%s/%s", mount_path, ADM_COOKIE_FILE);
i++;
}
if (mkdir(mount_path, mode) < 0)
{
pwarning(("mountDisks: mkdir(%s) failed, %s\n", mount_path, strerror(errno)));
return (FALSE);
}
if (chmod(mount_path, mode) < 0)
{
pwarning(("mountDisks: chmod(%s) failed: %s\n", mount_path, strerror(errno)));
}
fp = fopen(cookieFile, "w");
fclose(fp);
DiskVolume_setMountPoint(disk,mount_path);
return (TRUE);
}
int HideFile(const char * file)
{
struct attrlist alist = {0};
FinderAttrBuf finderInfoBuf = {0};
int result;
alist.bitmapcount = ATTR_BIT_MAP_COUNT;
alist.commonattr = ATTR_CMN_FNDRINFO;
result = getattrlist(file, &alist, &finderInfoBuf, sizeof(finderInfoBuf), 0);
if (result) return (errno);
if (finderInfoBuf.finderInfo.fdFlags & kIsInvisible) {
dwarning(("hide: %s is alreadly invisible\n", file));
return (0);
}
finderInfoBuf.finderInfo.fdFlags |= kIsInvisible;
result = setattrlist(file, &alist, &finderInfoBuf.finderInfo, sizeof(FinderInfo), 0);
return (result == -1 ? errno : result);
}
void DiskVolume_SetTrashes(DiskVolumePtr dptr)
{
struct stat sb;
char trashesLocation[1024];
if (!(dptr->writable)) {
return;
}
sprintf(trashesLocation, "%s/.Trashes", dptr->mount_point);
if (stat(trashesLocation, &sb) != 0) {
dwarning(("%s: '%s' not found...\n", __FUNCTION__, trashesLocation));
if (mkdir(trashesLocation, 0333) < 0)
{
pwarning(("%s: mkdir(%s) failed, %s\n", __FUNCTION__, trashesLocation, strerror(errno)));
}
if (chmod(trashesLocation, 0333) < 0)
{
pwarning(("%s: chmod(%s) failed: %s\n", __FUNCTION__, trashesLocation, strerror(errno)));
}
} else {
dwarning(("%s: '%s' found with incorrect permissions, fixing ...\n", __FUNCTION__, trashesLocation));
if (chmod(trashesLocation, 0333) < 0)
{
pwarning(("%s: chmod(%s) failed: %s\n", __FUNCTION__, trashesLocation, strerror(errno)));
}
}
HideFile(trashesLocation);
return;
}