/* * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights * Reserved. This file contains Original Code and/or Modifications of * Original Code as defined in and that are subject to the Apple Public * Source License Version 1.0 (the 'License'). You may not use this file * except in compliance with the License. Please obtain a copy of the * License at http://www.apple.com/publicsource and read it before using * this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License." * * @APPLE_LICENSE_HEADER_END@ */ #include "FSParticular.h" #include "DiskVolume.h" #include "DiskArbitrationServerMain.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAXNAMELEN 256 CFMutableDictionaryRef plistDict = nil; CFMutableArrayRef matchingArray = nil; char * daCreateCStringFromCFString(CFStringRef string) { /* * result of daCreateCStringFromCFString should be released with free() */ 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); // See Radar 2457357. buffer[ 0 ] = '\0'; // See Radar 2457357. } } return buffer; } /* daCreateCStringFromCFString */ mode_t mountModeForFS(char *fsname) { //if (strcmp(fsname, FS_TYPE_HFS) == 0) { // return 0775; //} return 0755; } /* * This function implements ordering for hybrids. It makes 9660/UDF * (DVD-Video bridge format) automount as UDF. Likewise 9660/HFS * will automount as HFS. * * XXX CSM - externalize the dependencies! (ala kext .xml files). */ 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); /* force udf to be first and 9660 to be last */ 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; /* The name of the device file. */ 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; } /* renameUFSDevice */ 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) { /* CHILD PROCESS */ cleanUpAfterFork(); chdir(fsDir); execve(execPath, childArgv, 0); exit(-127); } else if (pid > 0) { int statusp; int waitResult; /* PARENT PROCESS */ 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: dwarning(("%s(...) => %d\n", __FUNCTION__, result)); return result; } /* renameUFSDevice */ char *fsNameForFSWithMediaName(char *fsname, char *mediaName) { char *name = malloc(MAXPATHLEN); if (strcmp(fsname, FS_TYPE_UFS) == 0) { sprintf(name, "%s", mediaName); /* UFS has old-style label */ } 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; /* # filesystems defined in /usr/filesystems */ int n; plistDict = CFDictionaryCreateMutable(NULL,0,&kCFTypeDictionaryKeyCallBacks,&kCFTypeDictionaryValueCallBacks); /* discover known filesystem types */ nfs = scandir(FS_DIR_LOCATION, &fsdirs, suffixfs, sortfs); if ( gDebug ) { dwarning(("%d filesystems known:\n", nfs)); } for (n=0; nd_name[0])); } sprintf(buf, "%s/%s", FS_DIR_LOCATION ,&fsdirs[n]->d_name[0]); // get their dictionaries, test that they are okay and add them into the plistDict fsdict = CFBundleCopyInfoDictionaryInDirectory(CFURLCreateWithFileSystemPath(NULL, CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8), kCFURLPOSIXPathStyle, 1)); CFDictionaryAddValue(plistDict, CFStringCreateWithCString(NULL, &fsdirs[n]->d_name[0], kCFStringEncodingUTF8), fsdict); } //CFShow(plistDict); } } 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); // printf("%d, %d\n", val1ProbeOrder, 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; /* # filesystems defined in /usr/filesystems */ int n; int i = 0; //CFMutableDictionaryRef matchingDict = CFDictionaryCreateMutable(NULL,0,&kCFTypeDictionaryKeyCallBacks,&kCFTypeDictionaryValueCallBacks); matchingArray = CFArrayCreateMutable(NULL, 0, NULL); /* discover known filesystem types */ nfs = scandir(FS_DIR_LOCATION, &fsdirs, suffixfs, sortfs); for (n=0; nd_name[0]); // get their dictionaries, test that they are okay and add them into the plistDict fsdict = CFBundleCopyInfoDictionaryInDirectory(CFURLCreateWithFileSystemPath(NULL, CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8), kCFURLPOSIXPathStyle, 1)); mediaTypeDict = CFDictionaryGetValue(fsdict, CFSTR(kFSMediaTypesKey)); { int j = CFDictionaryGetCount(mediaTypeDict); CFDictionaryRef dicts[j]; CFStringRef keys[j]; CFDictionaryGetKeysAndValues(mediaTypeDict,(void**)keys,(void**)dicts); for (i=0;id_name[0], kCFStringEncodingUTF8)); CFArrayAppendValue(matchingArray, newDict); } } CFRelease(mediaTypeDict); } CFArraySortValues(matchingArray, CFRangeMake(0, CFArrayGetCount(matchingArray)), compareDicts, NULL); /* for (i=0;i