// Asssumes caller already knows the directory doesn't exist. static Boolean _createDirectory(CFURLRef dirURL, Boolean worldReadable) { CFAllocatorRef alloc = __CFPreferencesAllocator(); CFURLRef parentURL = CFURLCreateCopyDeletingLastPathComponent(alloc, dirURL); CFBooleanRef val = (CFBooleanRef) CFURLCreatePropertyFromResource(alloc, parentURL, kCFURLFileExists, NULL); Boolean parentExists = (val && CFBooleanGetValue(val)); SInt32 mode; Boolean result; if (val) CFRelease(val); if (!parentExists) { CFStringRef path = CFURLCopyPath(parentURL); if (!CFEqual(path, CFSTR("/"))) { _createDirectory(parentURL, worldReadable); val = (CFBooleanRef) CFURLCreatePropertyFromResource(alloc, parentURL, kCFURLFileExists, NULL); parentExists = (val && CFBooleanGetValue(val)); if (val) CFRelease(val); } CFRelease(path); } if (parentURL) CFRelease(parentURL); if (!parentExists) return false; #if TARGET_OS_OSX || TARGET_OS_LINUX mode = worldReadable ? S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH : S_IRWXU; #else mode = 0666; #endif result = CFURLWriteDataAndPropertiesToResource(dirURL, (CFDataRef)dirURL, URLPropertyDictForPOSIXMode(mode), NULL); URLPropertyDictRelease(); return result; }
void CrossPlatform::createDirectory(const std::string &path) { char *dir = _copyString(path.c_str()); try { for (char *dirDelim = strchr(dir, '/'); dirDelim != nullptr; dirDelim = strchr(dirDelim + 1, '/')) { *dirDelim = '\0'; // Skip root directory if (dir != dirDelim) _createDirectory(dir); *dirDelim = '/'; } _createDirectory(dir); } catch (const std::runtime_error &) { free(dir); throw; } free(dir); }
// 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; }
void _createTemporaryDirectory(char *directory_path) { _generateTemporaryPath(directory_path); _createDirectory(directory_path); }