void initializePaths() { #if RUN_IN_PLACE char buf[BUFSIZ]; infostream << "Using relative paths (RUN_IN_PLACE)" << std::endl; bool success = getCurrentExecPath(buf, sizeof(buf)) || getExecPathFromProcfs(buf, sizeof(buf)); if (success) { pathRemoveFile(buf, DIR_DELIM_CHAR); std::string execpath(buf); path_share = execpath + DIR_DELIM ".."; path_user = execpath + DIR_DELIM ".."; if (detectMSVCBuildDir(execpath)) { path_share += DIR_DELIM ".."; path_user += DIR_DELIM ".."; } } else { errorstream << "Failed to get paths by executable location, " "trying cwd" << std::endl; if (!getCurrentWorkingDir(buf, sizeof(buf))) FATAL_ERROR("Ran out of methods to get paths"); size_t cwdlen = strlen(buf); if (cwdlen >= 1 && buf[cwdlen - 1] == DIR_DELIM_CHAR) { cwdlen--; buf[cwdlen] = '\0'; } if (cwdlen >= 4 && !strcmp(buf + cwdlen - 4, DIR_DELIM "bin")) pathRemoveFile(buf, DIR_DELIM_CHAR); std::string execpath(buf); path_share = execpath; path_user = execpath; } #else infostream << "Using system-wide paths (NOT RUN_IN_PLACE)" << std::endl; if (!setSystemPaths()) errorstream << "Failed to get one or more system-wide path" << std::endl; #endif infostream << "Detected share path: " << path_share << std::endl; infostream << "Detected user path: " << path_user << std::endl; }
bool setSystemPaths() { char buf[BUFSIZ]; if (!getCurrentExecPath(buf, sizeof(buf))) { #ifdef __ANDROID__ errorstream << "Unable to read bindir "<< std::endl; #else FATAL_ERROR("Unable to read bindir"); #endif return false; } pathRemoveFile(buf, '/'); std::string bindir(buf); // Find share directory from these. // It is identified by containing the subdirectory "builtin". std::list<std::string> trylist; std::string static_sharedir = STATIC_SHAREDIR; if (!static_sharedir.empty() && static_sharedir != ".") trylist.push_back(static_sharedir); trylist.push_back(bindir + DIR_DELIM ".." DIR_DELIM "share" DIR_DELIM + PROJECT_NAME); trylist.push_back(bindir + DIR_DELIM ".."); #ifdef __ANDROID__ trylist.push_back(path_user); #endif for (std::list<std::string>::const_iterator i = trylist.begin(); i != trylist.end(); ++i) { const std::string &trypath = *i; if (!fs::PathExists(trypath) || !fs::PathExists(trypath + DIR_DELIM + "builtin")) { warningstream << "system-wide share not found at \"" << trypath << "\""<< std::endl; continue; } // Warn if was not the first alternative if (i != trylist.begin()) { warningstream << "system-wide share found at \"" << trypath << "\"" << std::endl; } path_share = trypath; break; } #ifndef __ANDROID__ path_user = std::string(getHomeOrFail()) + DIR_DELIM "." + PROJECT_NAME; #endif return true; }
char* posix_guess_path(char* argv0) { char buf[BUFSIZ]; size_t l = BUFSIZ; buf[0] = 0; if (argv0[0] != '/') { if (!getcwd(buf,BUFSIZ)) return strdup(".."); l -= (strlen(buf)+1); strncat(buf,"/",l); l--; } strncat(buf,argv0,l); pathRemoveFile(buf, '/'); pathRemoveFile(buf, '/'); /* get rid of any path trickery */ if (strstr(buf,"..")) { char buff[BUFSIZ]; char* t; strcpy(buff,buf); buf[0] = 0; t = strtok(buff,"/"); while (t) { if (!strcmp(t,"..")) { pathRemoveFile(buf,'/'); }else{ strcat(buf,"/"); strcat(buf,t); } t = strtok(NULL,"/"); } } return strdup(buf); }
bool setSystemPaths() { char buf[BUFSIZ]; // Find path of executable and set path_share relative to it FATAL_ERROR_IF(!getCurrentExecPath(buf, sizeof(buf)), "Failed to get current executable path"); pathRemoveFile(buf, '\\'); // Use ".\bin\.." path_share = std::string(buf) + "\\.."; // Use "C:\Documents and Settings\user\Application Data\<PROJECT_NAME>" DWORD len = GetEnvironmentVariable("APPDATA", buf, sizeof(buf)); FATAL_ERROR_IF(len == 0 || len > sizeof(buf), "Failed to get APPDATA"); path_user = std::string(buf) + DIR_DELIM + PROJECT_NAME; return true; }
void initializePaths() { #ifdef RUN_IN_PLACE /* Use relative paths if RUN_IN_PLACE */ dstream<<"Using relative paths (RUN_IN_PLACE)"<<std::endl; /* Windows */ #if defined(_WIN32) #include <windows.h> const DWORD buflen = 1000; char buf[buflen]; DWORD len; // Find path of executable and set path_data relative to it len = GetModuleFileName(GetModuleHandle(NULL), buf, buflen); assert(len < buflen); pathRemoveFile(buf, '\\'); // Use "./bin/../data" path_data = std::string(buf) + DIR_DELIM ".." DIR_DELIM "data"; // Use "./bin/.." path_userdata = std::string(buf) + DIR_DELIM ".."; /* Linux */ #elif defined(linux) #include <unistd.h> char buf[BUFSIZ]; memset(buf, 0, BUFSIZ); // Get path to executable assert(readlink("/proc/self/exe", buf, BUFSIZ-1) != -1); pathRemoveFile(buf, '/'); // Use "./bin/../data" path_data = std::string(buf) + "/../data"; // Use "./bin/../" path_userdata = std::string(buf) + "/.."; /* OS X */ #elif defined(__APPLE__) || defined(__FreeBSD__) //TODO: Get path of executable. This assumes working directory is bin/ dstream<<"WARNING: Relative path not properly supported on OS X and FreeBSD" <<std::endl; path_data = std::string("../data"); path_userdata = std::string(".."); #endif #else // RUN_IN_PLACE /* Use platform-specific paths otherwise */ dstream<<"Using system-wide paths (NOT RUN_IN_PLACE)"<<std::endl; /* Windows */ #if defined(_WIN32) #include <windows.h> const DWORD buflen = 1000; char buf[buflen]; DWORD len; // Find path of executable and set path_data relative to it len = GetModuleFileName(GetModuleHandle(NULL), buf, buflen); assert(len < buflen); pathRemoveFile(buf, '\\'); // Use "./bin/../data" path_data = std::string(buf) + DIR_DELIM ".." DIR_DELIM "data"; //path_data = std::string(buf) + "/../share/" + PROJECT_NAME; // Use "C:\Documents and Settings\user\Application Data\<PROJECT_NAME>" len = GetEnvironmentVariable("APPDATA", buf, buflen); assert(len < buflen); path_userdata = std::string(buf) + DIR_DELIM + PROJECT_NAME; /* Linux */ #elif defined(linux) #include <unistd.h> char buf[BUFSIZ]; memset(buf, 0, BUFSIZ); // Get path to executable assert(readlink("/proc/self/exe", buf, BUFSIZ-1) != -1); pathRemoveFile(buf, '/'); path_data = std::string(buf) + "/../share/" + PROJECT_NAME; //path_data = std::string(INSTALL_PREFIX) + "/share/" + PROJECT_NAME; if (!fs::PathExists(path_data)) { dstream<<"WARNING: data path " << path_data << " not found!"; path_data = std::string(buf) + "/../data"; dstream<<" Trying " << path_data << std::endl; } path_userdata = std::string(getenv("HOME")) + "/." + PROJECT_NAME; /* OS X */ #elif defined(__APPLE__) #include <unistd.h> // Code based on // http://stackoverflow.com/questions/516200/relative-paths-not-working-in-xcode-c CFBundleRef main_bundle = CFBundleGetMainBundle(); CFURLRef resources_url = CFBundleCopyResourcesDirectoryURL(main_bundle); char path[PATH_MAX]; if(CFURLGetFileSystemRepresentation(resources_url, TRUE, (UInt8 *)path, PATH_MAX)) { dstream<<"Bundle resource path: "<<path<<std::endl; //chdir(path); path_data = std::string(path) + "/data"; } else { // error! dstream<<"WARNING: Could not determine bundle resource path"<<std::endl; } CFRelease(resources_url); path_userdata = std::string(getenv("HOME")) + "/Library/Application Support/" + PROJECT_NAME; #elif defined(__FreeBSD__) path_data = std::string(INSTALL_PREFIX) + "/share/" + PROJECT_NAME; path_userdata = std::string(getenv("HOME")) + "/." + PROJECT_NAME; #endif #endif // RUN_IN_PLACE dstream<<"path_data = "<<path_data<<std::endl; dstream<<"path_userdata = "<<path_userdata<<std::endl; }
void initializePaths() { #if RUN_IN_PLACE /* Use relative paths if RUN_IN_PLACE */ infostream<<"Using relative paths (RUN_IN_PLACE)"<<std::endl; /* Windows */ #if defined(_WIN32) const DWORD buflen = 1000; char buf[buflen]; DWORD len; // Find path of executable and set path_share relative to it len = GetModuleFileName(GetModuleHandle(NULL), buf, buflen); assert(len < buflen); pathRemoveFile(buf, '\\'); if(detectMSVCBuildDir(buf)){ infostream<<"MSVC build directory detected"<<std::endl; path_share = std::string(buf) + "\\..\\.."; path_user = std::string(buf) + "\\..\\.."; } else{ #if STATIC_BUILD path_share = std::string(buf) + "\\."; path_user = std::string(buf) + "\\."; #else path_share = std::string(buf) + "\\.."; path_user = std::string(buf) + "\\.."; #endif } /* Linux */ #elif defined(linux) || defined(__linux) char buf[BUFSIZ]; memset(buf, 0, BUFSIZ); // Get path to executable assert(readlink("/proc/self/exe", buf, BUFSIZ-1) != -1); pathRemoveFile(buf, '/'); path_share = std::string(buf) + "/.."; path_user = std::string(buf) + "/.."; /* OS X */ #elif defined(__APPLE__) //https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/dyld.3.html //TODO: Test this code char buf[BUFSIZ]; uint32_t len = sizeof(buf); assert(_NSGetExecutablePath(buf, &len) != -1); pathRemoveFile(buf, '/'); path_share = std::string(buf) + "/.."; path_user = std::string(buf) + "/.."; /* FreeBSD */ #elif defined(__FreeBSD__) int mib[4]; char buf[BUFSIZ]; size_t len = sizeof(buf); mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_PATHNAME; mib[3] = -1; assert(sysctl(mib, 4, buf, &len, NULL, 0) != -1); pathRemoveFile(buf, '/'); path_share = std::string(buf) + "/.."; path_user = std::string(buf) + "/.."; #else //TODO: Get path of executable. This assumes working directory is bin/ dstream<<"WARNING: Relative path not properly supported on this platform" <<std::endl; /* scriptapi no longer allows paths that start with "..", so assuming that the current working directory is bin/, strip off the last component. */ char *cwd = getcwd(NULL, 0); pathRemoveFile(cwd, '/'); path_share = std::string(cwd); path_user = std::string(cwd); #endif #else // RUN_IN_PLACE /* Use platform-specific paths otherwise */ infostream<<"Using system-wide paths (NOT RUN_IN_PLACE)"<<std::endl; /* Windows */ #if defined(_WIN32) const DWORD buflen = 1000; char buf[buflen]; DWORD len; // Find path of executable and set path_share relative to it len = GetModuleFileName(GetModuleHandle(NULL), buf, buflen); assert(len < buflen); pathRemoveFile(buf, '\\'); // Use ".\bin\.." path_share = std::string(buf) + "\\.."; // Use "C:\Documents and Settings\user\Application Data\<PROJECT_NAME>" len = GetEnvironmentVariable("APPDATA", buf, buflen); assert(len < buflen); path_user = std::string(buf) + DIR_DELIM + PROJECT_NAME; /* Linux */ #elif defined(linux) || defined(__linux) // Get path to executable std::string bindir = ""; { char buf[BUFSIZ]; memset(buf, 0, BUFSIZ); if (readlink("/proc/self/exe", buf, BUFSIZ-1) == -1) { errorstream << "Unable to read bindir "<< std::endl; #ifndef __ANDROID__ assert("Unable to read bindir" == 0); #endif } else { pathRemoveFile(buf, '/'); bindir = buf; } } // Find share directory from these. // It is identified by containing the subdirectory "builtin". std::list<std::string> trylist; std::string static_sharedir = STATIC_SHAREDIR; if(static_sharedir != "" && static_sharedir != ".") trylist.push_back(static_sharedir); trylist.push_back( bindir + DIR_DELIM + ".." + DIR_DELIM + "share" + DIR_DELIM + PROJECT_NAME); trylist.push_back(bindir + DIR_DELIM + ".."); #ifdef __ANDROID__ trylist.push_back(DIR_DELIM "sdcard" DIR_DELIM PROJECT_NAME); #endif for(std::list<std::string>::const_iterator i = trylist.begin(); i != trylist.end(); i++) { const std::string &trypath = *i; if(!fs::PathExists(trypath) || !fs::PathExists(trypath + DIR_DELIM + "builtin")){ dstream<<"WARNING: system-wide share not found at \"" <<trypath<<"\""<<std::endl; continue; } // Warn if was not the first alternative if(i != trylist.begin()){ dstream<<"WARNING: system-wide share found at \"" <<trypath<<"\""<<std::endl; } path_share = trypath; break; } #ifndef __ANDROID__ path_user = std::string(getenv("HOME")) + DIR_DELIM + "." + PROJECT_NAME; #else path_user = std::string(DIR_DELIM "sdcard" DIR_DELIM PROJECT_NAME DIR_DELIM); #endif /* OS X */ #elif defined(__APPLE__) // Code based on // http://stackoverflow.com/questions/516200/relative-paths-not-working-in-xcode-c CFBundleRef main_bundle = CFBundleGetMainBundle(); CFURLRef resources_url = CFBundleCopyResourcesDirectoryURL(main_bundle); char path[PATH_MAX]; if(CFURLGetFileSystemRepresentation(resources_url, TRUE, (UInt8 *)path, PATH_MAX)) { dstream<<"Bundle resource path: "<<path<<std::endl; //chdir(path); path_share = std::string(path) + DIR_DELIM + "share"; } else { // error! dstream<<"WARNING: Could not determine bundle resource path"<<std::endl; } CFRelease(resources_url); path_user = std::string(getenv("HOME")) + "/Library/Application Support/" + PROJECT_NAME; #else // FreeBSD, and probably many other POSIX-like systems. path_share = STATIC_SHAREDIR; path_user = std::string(getenv("HOME")) + DIR_DELIM + "." + PROJECT_NAME; #endif #endif // RUN_IN_PLACE }
void initializePaths() { #if RUN_IN_PLACE char buf[BUFSIZ]; infostream << "Using relative paths (RUN_IN_PLACE)" << std::endl; bool success = getCurrentExecPath(buf, sizeof(buf)) || getExecPathFromProcfs(buf, sizeof(buf)); if (success) { pathRemoveFile(buf, DIR_DELIM_CHAR); std::string execpath(buf); path_share = execpath + DIR_DELIM ".."; path_user = execpath + DIR_DELIM ".."; if (detectMSVCBuildDir(execpath)) { path_share += DIR_DELIM ".."; path_user += DIR_DELIM ".."; } } else { errorstream << "Failed to get paths by executable location, " "trying cwd" << std::endl; if (!getCurrentWorkingDir(buf, sizeof(buf))) FATAL_ERROR("Ran out of methods to get paths"); size_t cwdlen = strlen(buf); if (cwdlen >= 1 && buf[cwdlen - 1] == DIR_DELIM_CHAR) { cwdlen--; buf[cwdlen] = '\0'; } if (cwdlen >= 4 && !strcmp(buf + cwdlen - 4, DIR_DELIM "bin")) pathRemoveFile(buf, DIR_DELIM_CHAR); std::string execpath(buf); path_share = execpath; path_user = execpath; } path_cache = path_user + DIR_DELIM + "cache"; #else infostream << "Using system-wide paths (NOT RUN_IN_PLACE)" << std::endl; if (!setSystemPaths()) errorstream << "Failed to get one or more system-wide path" << std::endl; // Initialize path_cache // First try $XDG_CACHE_HOME/PROJECT_NAME const char *cache_dir = getenv("XDG_CACHE_HOME"); const char *home_dir = getenv("HOME"); if (cache_dir) { path_cache = std::string(cache_dir) + DIR_DELIM + PROJECT_NAME; } else if (home_dir) { // Then try $HOME/.cache/PROJECT_NAME path_cache = std::string(home_dir) + DIR_DELIM + ".cache" + DIR_DELIM + PROJECT_NAME; } else { // If neither works, use $PATH_USER/cache path_cache = path_user + DIR_DELIM + "cache"; } // Migrate cache folder to new location if possible migrateCachePath(); #endif infostream << "Detected share path: " << path_share << std::endl; infostream << "Detected user path: " << path_user << std::endl; infostream << "Detected cache path: " << path_cache << std::endl; #if USE_GETTEXT bool found_localedir = false; # ifdef STATIC_LOCALEDIR if (STATIC_LOCALEDIR[0] && fs::PathExists(STATIC_LOCALEDIR)) { found_localedir = true; path_locale = STATIC_LOCALEDIR; infostream << "Using locale directory " << STATIC_LOCALEDIR << std::endl; } else { path_locale = getDataPath("locale"); if (fs::PathExists(path_locale)) { found_localedir = true; infostream << "Using in-place locale directory " << path_locale << " even though a static one was provided " << "(RUN_IN_PLACE or CUSTOM_LOCALEDIR)." << std::endl; } } # else path_locale = getDataPath("locale"); if (fs::PathExists(path_locale)) { found_localedir = true; } # endif if (!found_localedir) { warningstream << "Couldn't find a locale directory!" << std::endl; } #endif // USE_GETTEXT }
void initializePaths() { #if RUN_IN_PLACE char buf[BUFSIZ]; infostream << "Using relative paths (RUN_IN_PLACE)" << std::endl; bool success = getCurrentExecPath(buf, sizeof(buf)) || getExecPathFromProcfs(buf, sizeof(buf)); if (success) { pathRemoveFile(buf, DIR_DELIM_CHAR); std::string execpath(buf); path_share = execpath + DIR_DELIM ".."; path_user = execpath + DIR_DELIM ".."; if (detectMSVCBuildDir(execpath)) { path_share += DIR_DELIM ".."; path_user += DIR_DELIM ".."; } } else { errorstream << "Failed to get paths by executable location, " "trying cwd" << std::endl; if (!getCurrentWorkingDir(buf, sizeof(buf))) FATAL_ERROR("Ran out of methods to get paths"); size_t cwdlen = strlen(buf); if (cwdlen >= 1 && buf[cwdlen - 1] == DIR_DELIM_CHAR) { cwdlen--; buf[cwdlen] = '\0'; } if (cwdlen >= 4 && !strcmp(buf + cwdlen - 4, DIR_DELIM "bin")) pathRemoveFile(buf, DIR_DELIM_CHAR); std::string execpath(buf); path_share = execpath; path_user = execpath; } #else infostream << "Using system-wide paths (NOT RUN_IN_PLACE)" << std::endl; if (!setSystemPaths()) errorstream << "Failed to get one or more system-wide path" << std::endl; #endif infostream << "Detected share path: " << path_share << std::endl; infostream << "Detected user path: " << path_user << std::endl; bool found_localedir = false; #ifdef STATIC_LOCALEDIR if (STATIC_LOCALEDIR[0] && fs::PathExists(STATIC_LOCALEDIR)) { found_localedir = true; path_locale = STATIC_LOCALEDIR; infostream << "Using locale directory " << STATIC_LOCALEDIR << std::endl; } else { path_locale = getDataPath("locale"); if (fs::PathExists(path_locale)) { found_localedir = true; infostream << "Using in-place locale directory " << path_locale << " even though a static one was provided " << "(RUN_IN_PLACE or CUSTOM_LOCALEDIR)." << std::endl; } } #else path_locale = getDataPath("locale"); if (fs::PathExists(path_locale)) { found_localedir = true; } #endif if (!found_localedir) { errorstream << "Couldn't find a locale directory!" << std::endl; } }