// static VFSNode VFSNode::_platform_getKnownDirectoryNode(KnownDirectoryIdentifier id, const VString& companyName, const VString& appName) { if (id == CURRENT_WORKING_DIRECTORY) { return VFSNode(VPlatformAPI::getcwd()); } if (id == EXECUTABLE_DIRECTORY) { /* This depends on the structure of the application or tool. If it's an iOS application, it's a bundle where we have: /...../wanted-dir/AppName.app/executable (2 levels up, wanted-dir is a randomized serial number at some path) If it's built as a Mac OS X application bundle we have: /...../wanted-dir/AppName.app/Contents/MacOS/executable (4 levels up, typically wanted-dir is /Applications if installed, but doesn't have to be) If it's built as a simple Unix-y tool we have: /...../wanted-dir/executable (1 level up, wanted-dir is wherever the tool has been placed) */ #ifdef VPLATFORM_MAC_IOS const int NUM_LEVELS_UP = 2; #else #ifdef VAULT_MACOSX_APP_IS_BUNDLE const int NUM_LEVELS_UP = 4; #else const int NUM_LEVELS_UP = 1; #endif #endif VFSNode node = VFSNode::getExecutable(); for (int i = 0; i < NUM_LEVELS_UP; ++i) { VFSNode parentNode; node.getParentNode(parentNode); node = parentNode; } return node; } VFSNode currentUserFolder(_V_NSHomeDirectory()); if (id == USER_HOME_DIRECTORY) { return currentUserFolder; } VFSNode libraryFolder; currentUserFolder.getChildNode("Library", libraryFolder); libraryFolder.mkdir(); VFSNode subFolder; switch (id) { case USER_HOME_DIRECTORY: // handled earlier; we returned above break; case LOG_FILES_DIRECTORY: libraryFolder.getChildNode("Logs", subFolder); break; case USER_PREFERENCES_DIRECTORY: libraryFolder.getChildNode("Preferences", subFolder); break; case CACHED_DATA_DIRECTORY: libraryFolder.getChildNode("Caches", subFolder); break; case APPLICATION_DATA_DIRECTORY: subFolder = libraryFolder; break; case CURRENT_WORKING_DIRECTORY: // handled earlier; we returned above break; case EXECUTABLE_DIRECTORY: // handled earlier; we returned above break; default: throw VStackTraceException(VSTRING_FORMAT("VFSNode::_platform_getKnownDirectoryNode: Requested invalid directory ID %d.", (int) id)); break; } subFolder.mkdir(); VFSNode companyFolder; if (companyName.isEmpty()) { companyFolder = subFolder; } else { subFolder.getChildNode(companyName, companyFolder); companyFolder.mkdir(); } VFSNode resultNode; if (appName.isEmpty()) { resultNode = companyFolder; } else { companyFolder.getChildNode(appName, resultNode); resultNode.mkdir(); } return resultNode; }
// static VFSNode VFSNode::_platform_getKnownDirectoryNode(KnownDirectoryIdentifier id, const VString& companyName, const VString& appName) { if (id == CURRENT_WORKING_DIRECTORY) { return VFSNode(VSystemAPI::getcwd()); } if (id == EXECUTABLE_DIRECTORY) { VFSNode executable = VFSNode::getExecutable(); VFSNode executableDirectory; executable.getParentNode(executableDirectory); return executableDirectory; } struct passwd* pwInfo = ::getpwuid(::getuid()); // Get info about the current user. if (pwInfo == NULL) { throw VStackTraceException( // Oddity: errno 0 can occur and means "no such user". (errno == 0 ? VSystemError(0, "No such user") : VSystemError()), "VFSNode::_platform_getKnownDirectoryNode failed to get current user info from getpwuid()." ); } const VString homePath(pwInfo->pw_dir); if (id == USER_HOME_DIRECTORY) { return VFSNode(homePath); } VString basePath; VString companyFolderName(companyName); switch (id) { case USER_HOME_DIRECTORY: // handled earlier; we returned above break; case LOG_FILES_DIRECTORY: basePath = homePath + "/log"; break; case USER_PREFERENCES_DIRECTORY: basePath = homePath; if (companyName.isNotEmpty()) { companyFolderName.format(".%s", companyName.chars()); } break; case CACHED_DATA_DIRECTORY: basePath = homePath + "/cache"; break; case APPLICATION_DATA_DIRECTORY: basePath = homePath + "/data"; break; case CURRENT_WORKING_DIRECTORY: // handled earlier; we returned above break; case EXECUTABLE_DIRECTORY: // handled earlier; we returned above break; default: throw VStackTraceException(VSTRING_FORMAT("VFSNode::_platform_getKnownDirectoryNode: Requested invalid directory ID %d.", (int) id)); break; } VFSNode baseDir(basePath); baseDir.mkdir(); VFSNode companyFolder; if (companyFolderName.isEmpty()) { companyFolder = baseDir; } else { baseDir.getChildNode(companyFolderName, companyFolder); companyFolder.mkdir(); } VFSNode resultNode; if (appName.isEmpty()) { resultNode = companyFolder; } else { companyFolder.getChildNode(appName, resultNode); resultNode.mkdir(); } return resultNode; }