#include "FSParticular.h"
#include "DiskVolume.h"
#include "DiskArbitrationServerMain.h"
#include <libc.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <dev/disk.h>
#include <errno.h>
#include <sys/param.h>
#include <sys/mount.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/param.h>
#include <sys/mount.h>
#include <grp.h>
#include <ctype.h>
#include <dirent.h>
#include <mach/boolean.h>
#include <sys/loadable_fs.h>
#include <ufs/ufs/ufsmount.h>
#include <string.h>
#include <fsproperties.h>
#define MAXNAMELEN 256
CFMutableDictionaryRef plistDict = nil;
CFMutableArrayRef matchingArray = nil;
char *
daCreateCStringFromCFString(CFStringRef string)
{
CFStringEncoding encoding = kCFStringEncodingMacRoman;
CFIndex bufferLength = CFStringGetLength(string) + 1;
char *buffer = malloc(bufferLength);
if (buffer) {
if (CFStringGetCString(string, buffer, bufferLength, encoding) == FALSE) {
free(buffer);
buffer = malloc(1);
buffer[0] = '\0';
}
}
return buffer;
}
int
sortfs(const void *v1, const void *v2)
{
char *s1 = &(*(struct dirent **) v1)->d_name[0];
char *s2 = &(*(struct dirent **) v2)->d_name[0];
char udf[16] = FS_TYPE_UDF;
char iso[16] = FS_TYPE_CD9660;
strcat(udf, FS_DIR_SUFFIX);
strcat(iso, FS_DIR_SUFFIX);
if (!strcmp(s1, udf) || !strcmp(s2, iso))
return (-1);
if (!strcmp(s2, udf) || !strcmp(s1, iso))
return (1);
return (0);
}
boolean_t
DiskVolume_mount_ufs(DiskVolumePtr diskVolume)
{
struct ufs_args args;
int mntflags = 0;
char specname[MAXNAMELEN];
sprintf(specname, "/dev/%s", diskVolume->disk_dev_name);
args.fspec = specname;
if (diskVolume->writable == FALSE) {
mntflags |= MNT_RDONLY;
}
if (diskVolume->removable) {
mntflags |= MNT_NOSUID | MNT_NODEV;
}
#define DEFAULT_ROOTUID -2
args.export.ex_root = DEFAULT_ROOTUID;
if (mntflags & MNT_RDONLY) {
args.export.ex_flags = MNT_EXRDONLY;
} else {
args.export.ex_flags = 0;
}
if (mount(FS_TYPE_UFS, diskVolume->mount_point, mntflags, &args) < 0) {
pwarning(("mount %s on %s failed: %s\n", specname, diskVolume->mount_point, strerror(errno)));
return (FALSE);
}
pwarning(("Mounted ufs %s on %s\n", specname, diskVolume->mount_point));
DiskVolume_setMounted(diskVolume, TRUE);
return (TRUE);
}
char *
fsDirForFS(char *fsname)
{
char *fsDir = malloc(MAXPATHLEN);
sprintf(fsDir, "%s/%s%s", FS_DIR_LOCATION, fsname, FS_DIR_SUFFIX);
return fsDir;
}
char *
utilPathForFS(char *fsname)
{
char fsDir[MAXPATHLEN];
char *execPath = malloc(MAXPATHLEN);
sprintf(fsDir, "%s/%s%s", FS_DIR_LOCATION, fsname, FS_DIR_SUFFIX);
sprintf(execPath, "%s/%s%s", fsDir, fsname, FS_UTIL_SUFFIX);
return execPath;
}
int
renameUFSDevice(const char *devName, const char *mountPoint)
{
int result;
char *cmd = "-n";
char *fsName = "ufs";
char *execPath = utilPathForFS((char *) fsName);
const char *childArgv[] = {execPath,
cmd,
devName,
mountPoint, 0};
#warning .util code here - needs to change for pluggable
char *fsDir = fsDirForFS((char *) fsName);
int pid;
dwarning(("%s('%s', '%s')\n",
__FUNCTION__, devName, mountPoint));
if ((pid = fork()) == 0) {
cleanUpAfterFork(NULL);
chdir(fsDir);
execve(execPath, (char * const *)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 = 0;
Return:
free(execPath);
free(fsDir);
dwarning(("%s(...) => %d\n", __FUNCTION__, result));
return result;
}
char *
fsNameForFSWithMediaName(char *fsname, char *mediaName)
{
char *name = malloc(MAXPATHLEN);
if (strcmp(fsname, FS_TYPE_UFS) == 0) {
sprintf(name, "%s", mediaName);
} else {
sprintf(name, "%s", fsname);
}
return name;
}
int
suffixfs(struct dirent * dp)
{
char *s;
if ((s = strstr(&dp->d_name[0], FS_DIR_SUFFIX)))
if (strlen(s) == strlen(FS_DIR_SUFFIX))
return (1);
return (0);
}
void
cacheFileSystemDictionaries()
{
if (!plistDict) {
struct dirent **fsdirs = NULL;
int nfs = 0;
int n;
plistDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
nfs = scandir(FS_DIR_LOCATION, &fsdirs, suffixfs, sortfs);
if (gDebug) {
dwarning(("%d filesystems known:\n", nfs));
}
for (n = 0; n < nfs; n++) {
char buf[MAXPATHLEN];
CFDictionaryRef fsdict;
CFStringRef str;
CFURLRef bar;
CFStringRef zaz;
if (gDebug) {
dwarning(("%s\n", &fsdirs[n]->d_name[0]));
}
sprintf(buf, "%s/%s", FS_DIR_LOCATION, &fsdirs[n]->d_name[0]);
str = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
bar = CFURLCreateWithFileSystemPath(NULL, str, kCFURLPOSIXPathStyle, 1);
fsdict = CFBundleCopyInfoDictionaryInDirectory(bar);
zaz = CFStringCreateWithCString(NULL, &fsdirs[n]->d_name[0], kCFStringEncodingUTF8);
CFDictionaryAddValue(plistDict, zaz, fsdict);
CFRelease(zaz);
CFRelease(bar);
CFRelease(str);
CFRelease(fsdict);
}
if (fsdirs) {
for (n = 0; n < nfs; n++) {
free((void *) fsdirs[n]);
}
free((void *) fsdirs);
}
}
}
CFComparisonResult
compareDicts(const void *val1, const void *val2, void *context)
{
int val1ProbeOrder;
int val2ProbeOrder;
CFNumberRef val1Number = CFDictionaryGetValue(val1, CFSTR(kFSProbeOrderKey));
CFNumberRef val2Number = CFDictionaryGetValue(val2, CFSTR(kFSProbeOrderKey));
CFNumberGetValue(val1Number, kCFNumberIntType, &val1ProbeOrder);
CFNumberGetValue(val2Number, kCFNumberIntType, &val2ProbeOrder);
if (val1ProbeOrder > val2ProbeOrder) {
return kCFCompareGreaterThan;
} else if (val1ProbeOrder < val2ProbeOrder) {
return kCFCompareLessThan;
}
return kCFCompareEqualTo;
}
void
cacheFileSystemMatchingArray()
{
if (!matchingArray) {
struct dirent **fsdirs = NULL;
int nfs = 0;
int n;
int i = 0;
matchingArray = CFArrayCreateMutable(NULL, 0, NULL);
nfs = scandir(FS_DIR_LOCATION, &fsdirs, suffixfs, sortfs);
for (n = 0; n < nfs; n++) {
char buf[MAXPATHLEN];
CFDictionaryRef fsdict;
CFDictionaryRef mediaTypeDict;
CFStringRef str;
CFURLRef bar;
sprintf(buf, "%s/%s", FS_DIR_LOCATION, &fsdirs[n]->d_name[0]);
str = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
bar = CFURLCreateWithFileSystemPath(NULL, str, kCFURLPOSIXPathStyle, 1);
fsdict = CFBundleCopyInfoDictionaryInDirectory(bar);
mediaTypeDict = CFDictionaryGetValue(fsdict, CFSTR(kFSMediaTypesKey));
{
int j = CFDictionaryGetCount(mediaTypeDict);
CFDictionaryRef dicts[j];
CFStringRef keys[j];
CFDictionaryGetKeysAndValues(mediaTypeDict, (const void **) keys, (const void **) dicts);
for (i = 0; i < j; i++) {
CFStringRef zaz;
CFMutableDictionaryRef newDict = CFDictionaryCreateMutableCopy(NULL, 0, dicts[i]);
zaz = CFStringCreateWithCString(NULL, &fsdirs[n]->d_name[0], kCFStringEncodingUTF8);
CFDictionaryAddValue(newDict, CFSTR("FSName"), zaz);
CFArrayAppendValue(matchingArray, newDict);
CFRelease(zaz);
}
}
CFRelease(fsdict);
CFRelease(str);
CFRelease(bar);
}
if (fsdirs) {
for (n = 0; n < nfs; n++) {
free((void *) fsdirs[n]);
}
free((void *) fsdirs);
}
CFArraySortValues(matchingArray, CFRangeMake(0, CFArrayGetCount(matchingArray)), compareDicts, NULL);
}
}
char *
resourcePathForFSName(char *fs)
{
char bundlePath[MAXPATHLEN];
CFBundleRef bundle;
CFURLRef bundleUrl;
CFURLRef resourceUrl;
CFStringRef resourceString;
char *path;
char *resourcePath = malloc(MAXPATHLEN);
CFStringRef str;
sprintf(bundlePath, "%s/%s", FS_DIR_LOCATION, fs);
str = CFStringCreateWithCString(NULL, bundlePath, kCFStringEncodingMacRoman);
bundleUrl = CFURLCreateWithFileSystemPath(NULL, str, kCFURLPOSIXPathStyle, 1);
CFRelease(str);
bundle = CFBundleCreate(NULL, bundleUrl);
resourceUrl = CFBundleCopyResourcesDirectoryURL(bundle);
resourceString = CFURLCopyPath(resourceUrl);
path = daCreateCStringFromCFString(resourceString);
sprintf(resourcePath, "%s/%s", bundlePath, path);
CFRelease(bundleUrl);
CFRelease(bundle);
CFRelease(resourceUrl);
CFRelease(resourceString);
free(path);
return resourcePath;
}
char *
verifyPathForFileSystem(char *fsname)
{
CFDictionaryRef fsDict;
CFDictionaryRef personalities;
CFDictionaryRef personality;
CFStringRef fsckPath1;
char fs[128];
char *fsckPath;
char *finalPath = malloc(MAXPATHLEN);
CFStringRef str;
if (strlen(fsname) == 0) {
return finalPath;
}
sprintf(fs, "%s%s", fsname, FS_DIR_SUFFIX);
str = CFStringCreateWithCString(NULL, fs, kCFStringEncodingMacRoman);
fsDict = (CFDictionaryRef) CFDictionaryGetValue(plistDict, str);
CFRelease(str);
if (!fsDict) {
return finalPath;
}
personalities = (CFDictionaryRef) CFDictionaryGetValue(fsDict, CFSTR(kFSPersonalitiesKey));
{
CFDictionaryRef dicts[CFDictionaryGetCount(personalities)];
CFStringRef keys[CFDictionaryGetCount(personalities)];
CFDictionaryGetKeysAndValues(personalities, (const void **) keys, (const void **) dicts);
personality = (CFDictionaryRef) dicts[0];
}
fsckPath1 = (CFStringRef) CFDictionaryGetValue(personality, CFSTR(kFSVerificationExecutableKey));
if (fsckPath1) {
char *resourcePath = resourcePathForFSName(fs);
fsckPath = daCreateCStringFromCFString(fsckPath1);
sprintf(finalPath, "%s%s", resourcePath, fsckPath);
free(resourcePath);
free(fsckPath);
}
return finalPath;
}
char *
repairPathForFileSystem(char *fsname)
{
CFDictionaryRef fsDict;
CFDictionaryRef personalities;
CFDictionaryRef personality;
CFStringRef fsckPath1;
char fs[128];
char *fsckPath;
char *finalPath = malloc(MAXPATHLEN);
CFStringRef str;
if (strlen(fsname) == 0) {
return finalPath;
}
sprintf(fs, "%s%s", fsname, FS_DIR_SUFFIX);
str = CFStringCreateWithCString(NULL, fs, kCFStringEncodingMacRoman);
fsDict = (CFDictionaryRef) CFDictionaryGetValue(plistDict, str);
CFRelease(str);
if (!fsDict) {
return finalPath;
}
personalities = (CFDictionaryRef) CFDictionaryGetValue(fsDict, CFSTR(kFSPersonalitiesKey));
{
CFDictionaryRef dicts[CFDictionaryGetCount(personalities)];
CFStringRef keys[CFDictionaryGetCount(personalities)];
CFDictionaryGetKeysAndValues(personalities, (const void **) keys, (const void **) dicts);
personality = (CFDictionaryRef) dicts[0];
}
fsckPath1 = (CFStringRef) CFDictionaryGetValue(personality, CFSTR(kFSRepairExecutableKey));
if (fsckPath1) {
char *resourcePath = resourcePathForFSName(fs);
fsckPath = daCreateCStringFromCFString(fsckPath1);
sprintf(finalPath, "%s%s", resourcePath, fsckPath);
free(resourcePath);
free(fsckPath);
}
return finalPath;
}
char *
verifyArgsForFileSystem(char *fsname)
{
CFDictionaryRef fsDict;
CFDictionaryRef personalities;
CFDictionaryRef personality;
CFStringRef repairArgs1;
char fs[128];
char *repairArgs;
CFStringRef str;
if (strlen(fsname) == 0) {
repairArgs = malloc(MAXPATHLEN);
return repairArgs;
}
sprintf(fs, "%s%s", fsname, FS_DIR_SUFFIX);
str = CFStringCreateWithCString(NULL, fs, kCFStringEncodingMacRoman);
fsDict = (CFDictionaryRef) CFDictionaryGetValue(plistDict, str);
CFRelease(str);
if (!fsDict) {
repairArgs = malloc(MAXPATHLEN);
return repairArgs;
}
personalities = (CFDictionaryRef) CFDictionaryGetValue(fsDict, CFSTR(kFSPersonalitiesKey));
{
CFDictionaryRef dicts[CFDictionaryGetCount(personalities)];
CFStringRef keys[CFDictionaryGetCount(personalities)];
CFDictionaryGetKeysAndValues(personalities, (const void **) keys, (const void **) dicts);
personality = (CFDictionaryRef) dicts[0];
}
repairArgs1 = (CFStringRef) CFDictionaryGetValue(personality, CFSTR(kFSVerificationArgumentsKey));
if (repairArgs1) {
repairArgs = daCreateCStringFromCFString(repairArgs1);
} else {
repairArgs = malloc(MAXPATHLEN);
}
return repairArgs;
}
char *
repairArgsForFileSystem(char *fsname)
{
CFDictionaryRef fsDict;
CFDictionaryRef personalities;
CFDictionaryRef personality;
CFStringRef repairArgs1;
char fs[128];
char *repairArgs;
CFStringRef str;
if (strlen(fsname) == 0) {
repairArgs = malloc(MAXPATHLEN);
return repairArgs;
}
sprintf(fs, "%s%s", fsname, FS_DIR_SUFFIX);
str = CFStringCreateWithCString(NULL, fs, kCFStringEncodingMacRoman);
fsDict = (CFDictionaryRef) CFDictionaryGetValue(plistDict, str);
CFRelease(str);
if (!fsDict) {
repairArgs = malloc(MAXPATHLEN);
return repairArgs;
}
personalities = (CFDictionaryRef) CFDictionaryGetValue(fsDict, CFSTR(kFSPersonalitiesKey));
{
CFDictionaryRef dicts[CFDictionaryGetCount(personalities)];
CFStringRef keys[CFDictionaryGetCount(personalities)];
CFDictionaryGetKeysAndValues(personalities, (const void **) keys, (const void **) dicts);
personality = (CFDictionaryRef) dicts[0];
}
repairArgs1 = (CFStringRef) CFDictionaryGetValue(personality, CFSTR(kFSRepairArgumentsKey));
if (repairArgs1) {
repairArgs = daCreateCStringFromCFString(repairArgs1);
} else {
repairArgs = malloc(MAXPATHLEN);
}
return repairArgs;
}
void
printArgsForFsname(char *fsname)
{
printf("arguments for %s\n\tVerify = %s %s\n\tRepair = %s %s\n", fsname, verifyPathForFileSystem(fsname), verifyArgsForFileSystem(fsname), repairPathForFileSystem(fsname), repairArgsForFileSystem(fsname));
}