Beispiel #1
0
// 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;
}