void FileHandler::Read(std::vector<Process>& processes) { processes.clear(); if (_File) { long file_size = GetFileSize(); if (file_size <= 0) return; char* buf = (char*)malloc(file_size + 1); memset(buf, 0, file_size+1); fread(buf, 1, file_size, _File); const std::string str(buf); free(buf); std::string::size_type prev = 0; std::string::size_type pos = 0; while (true) { pos = str.find_first_of("\r\n", pos); Process process; if (pos == std::string::npos) { std::string exe_file(str.substr(prev)); if (!exe_file.empty()) { process.ExeFile(exe_file); processes.push_back(process); } break; } if (pos > prev) { process.ExeFile(str.substr(prev, pos-prev)); processes.push_back(process); } ++pos; prev = pos; } } }
String Get(Key key) { switch(key) { case FILE_EXE: { #if SIRIKATA_PLATFORM == SIRIKATA_PLATFORM_MAC // Executable path can have relative references ("..") depending on // how the app was launched. uint32_t executable_length = 0; _NSGetExecutablePath(NULL, &executable_length); std::string executable_path(executable_length, '\0'); char* executable_path_c = (char*)executable_path.c_str(); int rv = _NSGetExecutablePath(executable_path_c, &executable_length); assert(rv == 0); if ((rv != 0) || (executable_path.empty())) return ""; // _NSGetExecutablePath will return whatever gets execed, so if // the command line is ./foo, you'll get the '.'. We use the // aggressive mode here to handle '..' parts that could interfere // with finding other paths that start from FILE_EXE. return canonicalize(executable_path, true); #elif SIRIKATA_PLATFORM == SIRIKATA_PLATFORM_LINUX // boost::filesystem can't chase symlinks, do it manually const char* selfExe = "/proc/self/exe"; char bin_dir[MAX_PATH + 1]; int bin_dir_size = readlink(selfExe, bin_dir, MAX_PATH); if (bin_dir_size < 0 || bin_dir_size > MAX_PATH) { SILOG(core,fatal,"Couldn't read self symlink to setup dynamic loading paths."); return ""; } bin_dir[bin_dir_size] = 0; return String(bin_dir, bin_dir_size); #elif SIRIKATA_PLATFORM == SIRIKATA_PLATFORM_WINDOWS char system_buffer[MAX_PATH]; system_buffer[0] = 0; GetModuleFileName(NULL, system_buffer, MAX_PATH); // Go through boost::filesystem to canonicalize our formatting. // If we don't, we can get \ or / in filenames depending on where // they came from/whether we went through boost::filesystem String exe_file(system_buffer); if (exe_file.empty()) return ""; boost::filesystem::path exe_file_path(exe_file); return exe_file_path.string(); #else return ""; #endif } break; case DIR_EXE: { String exe_file = Get(FILE_EXE); if (exe_file.empty()) return ""; boost::filesystem::path exe_file_path(exe_file); return exe_file_path.parent_path().string(); } break; case DIR_EXE_BUNDLE: { #if SIRIKATA_PLATFORM == SIRIKATA_PLATFORM_WINDOWS || SIRIKATA_PLATFORM == SIRIKATA_PLATFORM_LINUX // Windows and Linux don't have bundles return Get(DIR_EXE); #elif SIRIKATA_PLATFORM == SIRIKATA_PLATFORM_MAC // On mac we need to detect that we're in a .app. We assume this // only applies if the binaries are in the standard location, // i.e. foo.app/Contents/MacOS/bar_binary String exe_dir = Get(DIR_EXE); boost::filesystem::path exe_dir_path(exe_dir); // Work our way back up verifying the path names, finally // returning if we actually find the .app. if (exe_dir_path.has_filename() && exe_dir_path.filename() == "MacOS") { exe_dir_path = exe_dir_path.parent_path(); if (exe_dir_path.has_filename() && exe_dir_path.filename() == "Contents") { exe_dir_path = exe_dir_path.parent_path(); if (exe_dir_path.has_filename()) { String app_dir_name = exe_dir_path.filename(); if (app_dir_name.substr(app_dir_name.size()-4, 4) == ".app") return exe_dir_path.parent_path().string(); } } } // Otherwise dump the original return exe_dir; #endif } break; case DIR_CURRENT: { #if SIRIKATA_PLATFORM == SIRIKATA_PLATFORM_MAC || SIRIKATA_PLATFORM == SIRIKATA_PLATFORM_LINUX char system_buffer[MAX_PATH] = ""; if (!getcwd(system_buffer, sizeof(system_buffer))) { return ""; } return String(system_buffer); #elif SIRIKATA_PLATFORM == SIRIKATA_PLATFORM_WINDOWS char system_buffer[MAX_PATH]; system_buffer[0] = 0; DWORD len = ::GetCurrentDirectory(MAX_PATH, system_buffer); if (len == 0 || len > MAX_PATH) return ""; return String(system_buffer); #else return "."; #endif } break; case DIR_USER: { #if SIRIKATA_PLATFORM == SIRIKATA_PLATFORM_LINUX || SIRIKATA_PLATFORM == SIRIKATA_PLATFORM_MAC uid_t uid = getuid(); passwd* pw = getpwuid(uid); if (pw != NULL && pw->pw_dir != NULL) { boost::filesystem::path homedir(pw->pw_dir); if (boost::filesystem::exists(homedir) && boost::filesystem::is_directory(homedir)) return homedir.string(); } #elif SIRIKATA_PLATFORM == SIRIKATA_PLATFORM_WINDOWS char system_buffer[MAX_PATH]; system_buffer[0] = 0; if (FAILED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, system_buffer))) return ""; std::string appdata_str(system_buffer); boost::filesystem::path user_appdata(appdata_str); user_appdata /= "Sirikata"; if (!boost::filesystem::exists(user_appdata)) boost::filesystem::create_directory(user_appdata); if (boost::filesystem::exists(user_appdata) && boost::filesystem::is_directory(user_appdata)) return user_appdata.string(); #endif // Last resort (and default for unknown platform) is to try to use // the current directory return "."; } break; case DIR_USER_HIDDEN: { #if SIRIKATA_PLATFORM == SIRIKATA_PLATFORM_WINDOWS // On windows there's no difference from the user-specific data directory since that's already hidden. return Get(DIR_USER); #else // We just compute this as an offset from the user directory boost::filesystem::path user_dir(Get(DIR_USER)); user_dir /= ".sirikata"; if (!boost::filesystem::exists(user_dir)) boost::filesystem::create_directory(user_dir); if (boost::filesystem::exists(user_dir) && boost::filesystem::is_directory(user_dir)) return user_dir.string(); #endif return "."; } case DIR_TEMP: { #if SIRIKATA_PLATFORM == SIRIKATA_PLATFORM_LINUX || SIRIKATA_PLATFORM == SIRIKATA_PLATFORM_MAC // On Mac and Linux we try to work under tmp using our own directory boost::filesystem::path tmp_path("/tmp"); if (boost::filesystem::exists(tmp_path) && boost::filesystem::is_directory(tmp_path)) { tmp_path /= "sirikata"; // If it doesn't exist, try creating it if (!boost::filesystem::exists(tmp_path)) boost::filesystem::create_directory(tmp_path); if (boost::filesystem::exists(tmp_path) && boost::filesystem::is_directory(tmp_path)) return tmp_path.string(); } #elif SIRIKATA_PLATFORM == SIRIKATA_PLATFORM_WINDOWS // Windows doesn't seem to suggest a good location for this, so we // put it under the app data directory in its own temp directory boost::filesystem::path sirikata_temp_dir = boost::filesystem::path(Get(DIR_USER_HIDDEN)) / "temp"; if (!boost::filesystem::exists(sirikata_temp_dir)) boost::filesystem::create_directory(sirikata_temp_dir); if (boost::filesystem::exists(sirikata_temp_dir) && boost::filesystem::is_directory(sirikata_temp_dir)) return sirikata_temp_dir.string(); #endif // Last resort (and default for unknown platform) is to try to use // the current directory return "."; } break; case DIR_SYSTEM_CONFIG: { #if SIRIKATA_PLATFORM == SIRIKATA_PLATFORM_LINUX || SIRIKATA_PLATFORM == SIRIKATA_PLATFORM_MAC // This is sirikata specific, so we're looking for more // than just /etc. if (boost::filesystem::exists("/etc") && boost::filesystem::is_directory("/etc") && boost::filesystem::exists("/etc/sirikata") && boost::filesystem::is_directory("/etc/sirikata")) return "/etc/sirikata"; return ""; #else // Other platforms don't have an equivalent? return ""; #endif } break; case RESOURCE: { SILOG(core,fatal,"Can't request RESOURCE without specifiying an in-tree path and path to resource."); assert(key != RESOURCE); return ""; } break; default: return ""; } }