// Try to remove the dynamic MIME file used for dynamic content-type generation. // You cannot rely on registry being sane at this point, as we can't guarantee // the order destructors are called, so please don't access it here. void __destructor fini_remove_dynamic_plist(void) { CFURLRef home_directory = NULL; CFURLRef pref_directory = NULL; CFURLRef mime_file = NULL; CFURLRef mime_file_lock = NULL; SInt32 error_code = -1; // Resolve the home directory. home_directory = CFCopyHomeDirectoryURLForUser(NULL); if (home_directory == NULL) { goto finished; } // Resolve Preferences directory (this is how CoreFoundation does it), I // don't want to have to rely on this, but they don't make it easy. pref_directory = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorDefault, CFSTR("Library/Preferences/"), kCFURLPOSIXPathStyle, true, home_directory); if (pref_directory == NULL) { goto finished; } // Append the name of my cache file. mime_file = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorDefault, CFSTR("com.google.netscapesecurity.plist"), kCFURLPOSIXPathStyle, false, pref_directory); mime_file_lock = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorDefault, CFSTR("com.google.netscapesecurity.plist.lockfile"), kCFURLPOSIXPathStyle, false, pref_directory); if (!mime_file || !mime_file_lock) { goto finished; } // Delete the file, and possibly stale lockfile, I don't care if it fails. CFURLDestroyResource(mime_file, &error_code); CFURLDestroyResource(mime_file_lock, &error_code); finished: CFRelease(home_directory); CFRelease(pref_directory); CFRelease(mime_file); CFRelease(mime_file_lock); return; }
// domain should already be locked. static Boolean _writeXMLFile(CFURLRef url, CFMutableDictionaryRef dict, Boolean isWorldReadable, Boolean *tryAgain) { Boolean success = false; CFAllocatorRef alloc = __CFPreferencesAllocator(); *tryAgain = false; if (CFDictionaryGetCount(dict) == 0) { // Destroy the file CFBooleanRef val = (CFBooleanRef) CFURLCreatePropertyFromResource(alloc, url, kCFURLFileExists, NULL); if (val && CFBooleanGetValue(val)) { success = CFURLDestroyResource(url, NULL); } else { success = true; } if (val) CFRelease(val); } else { CFPropertyListFormat desiredFormat = __CFPreferencesShouldWriteXML() ? kCFPropertyListXMLFormat_v1_0 : kCFPropertyListBinaryFormat_v1_0; CFDataRef data = CFPropertyListCreateData(alloc, dict, desiredFormat, 0, NULL); if (data) { SInt32 mode; #if TARGET_OS_OSX || TARGET_OS_LINUX mode = isWorldReadable ? S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH : S_IRUSR|S_IWUSR; #else mode = 0666; #endif #if TARGET_OS_OSX { // Try quick atomic way first, then fallback to slower ways and error cases CFStringRef scheme = CFURLCopyScheme(url); if (!scheme) { *tryAgain = false; CFRelease(data); return false; } else if (CFStringCompare(scheme, CFSTR("file"), 0) == kCFCompareEqualTo) { SInt32 length = CFDataGetLength(data); const void *bytes = (0 == length) ? (const void *)"" : CFDataGetBytePtr(data); Boolean atomicWriteSuccess = __CFWriteBytesToFileWithAtomicity(url, bytes, length, mode, true); if (atomicWriteSuccess) { CFRelease(scheme); *tryAgain = false; CFRelease(data); return true; } if (!atomicWriteSuccess && thread_errno() == ENOSPC) { CFRelease(scheme); *tryAgain = false; CFRelease(data); return false; } } CFRelease(scheme); } #endif success = CFURLWriteDataAndPropertiesToResource(url, data, URLPropertyDictForPOSIXMode(mode), NULL); URLPropertyDictRelease(); if (success) { CFDataRef readData; if (!CFURLCreateDataAndPropertiesFromResource(alloc, url, &readData, NULL, NULL, NULL) || !CFEqual(readData, data)) { success = false; *tryAgain = true; } if (readData) CFRelease(readData); } else { CFBooleanRef val = (CFBooleanRef) CFURLCreatePropertyFromResource(alloc, url, kCFURLFileExists, NULL); if (!val || !CFBooleanGetValue(val)) { CFURLRef tmpURL = CFURLCreateWithFileSystemPathRelativeToBase(alloc, CFSTR("."), kCFURLPOSIXPathStyle, true, url); // Just "." because url is not a directory URL CFURLRef parentURL = tmpURL ? CFURLCopyAbsoluteURL(tmpURL) : NULL; if (tmpURL) CFRelease(tmpURL); if (val) CFRelease(val); val = (CFBooleanRef) CFURLCreatePropertyFromResource(alloc, parentURL, kCFURLFileExists, NULL); if ((!val || !CFBooleanGetValue(val)) && _createDirectory(parentURL, isWorldReadable)) { // parent directory didn't exist; now it does; try again to write success = CFURLWriteDataAndPropertiesToResource(url, data, URLPropertyDictForPOSIXMode(mode), NULL); URLPropertyDictRelease(); if (success) { CFDataRef rdData; if (!CFURLCreateDataAndPropertiesFromResource(alloc, url, &rdData, NULL, NULL, NULL) || !CFEqual(rdData, data)) { success = false; *tryAgain = true; } if (rdData) CFRelease(rdData); } } if (parentURL) CFRelease(parentURL); } if (val) CFRelease(val); } CFRelease(data); } else { // ??? This should never happen CFLog(__kCFLogAssertion, CFSTR("Could not generate XML data for property list")); success = false; } } return success; }