//TODO: error handling? int VMBase::Create(Str::StringRef name, Type type) { if (module) { Com_Printf(S_ERROR "Attempting to re-create an already-loaded VM"); return -1; } const std::string& libPath = FS::GetLibPath(); bool debug = Cvar_Get("vm_debug", "0", CVAR_INIT)->integer; if (type == TYPE_NATIVE) { std::string exe = FS::Path::Build(libPath, name + EXE_EXT); Com_Printf("Trying to load native module %s\n", exe.c_str()); module = NaCl::LoadModule(exe.c_str(), nullptr, debug); } else if (type == TYPE_NACL) { // Extract the nexe from the pak so that sel_ldr can load it std::string nexe = name + "-" ARCH_STRING ".nexe"; try { FS::File out = FS::HomePath::OpenWrite(nexe); FS::PakPath::CopyFile(nexe, out); out.Close(); } catch (std::system_error& err) { Com_Printf(S_ERROR "Failed to extract NaCl module %s: %s\n", nexe.c_str(), err.what()); return -1; } std::string sel_ldr = FS::Path::Build(libPath, "sel_ldr" EXE_EXT); std::string irt = FS::Path::Build(libPath, "irt_core-" ARCH_STRING ".nexe"); #ifdef __linux__ std::string bootstrap = FS::Path::Build(libPath, "nacl_helper_bootstrap"); NaCl::LoaderParams params = {sel_ldr.c_str(), irt.c_str(), bootstrap.c_str()}; #else NaCl::LoaderParams params = {sel_ldr.c_str(), irt.c_str(), nullptr}; #endif Com_Printf("Trying to load NaCl module %s\n", nexe.c_str()); module = NaCl::LoadModule(FS::Path::Build(FS::GetHomePath(), nexe).c_str(), ¶ms, debug); } else { Com_Printf(S_ERROR "Invalid VM type"); return -1; } if (!module) { Com_Printf(S_ERROR "Couldn't load VM %s", name.c_str()); return -1; } if (debug) Com_Printf("Waiting for GDB connection on localhost:4014\n"); // Read the ABI version from the root socket. // If this fails, we assume the remote process failed to start std::vector<char> buffer; if (!module.GetRootSocket().RecvMsg(buffer) || buffer.size() != sizeof(int)) { Com_Printf(S_ERROR "The '%s' VM did not start.", name.c_str()); return -1; } Com_Printf("Loaded module with the NaCl ABI"); return *reinterpret_cast<int*>(buffer.data()); }
void FS_WriteFile(const char* path, const void* buffer, int size) { try { FS::File f = FS::HomePath::OpenWrite(path); f.Write(buffer, size); f.Close(); } catch (std::system_error& err) { Log::Notice("Failed to write file '%s': %s\n", path, err.what()); } }
void History::Save() { try { FS::File f = FS::HomePath::OpenWrite(GetFilename()); auto lock = Lock(); Container::size_type i = 0; if ( lines.size() > SAVED_HISTORY_LINES ) i = lines.size() - SAVED_HISTORY_LINES; for (; i < lines.size(); i++) { f.Write(lines[i].data(), lines[i].size()); f.Write("\n", 1); } } catch (const std::system_error& error) { Log::Warn("Couldn't write %s: %s", GetFilename(), error.what()); } }
void History::Load() { std::string buffer; try { FS::File f = FS::HomePath::OpenRead(GetFilename()); buffer = f.ReadAll(); } catch (const std::system_error& error) { Log::Warn("Couldn't read %s: %s", GetFilename(), error.what()); } auto lock = Lock(); lines.clear(); std::size_t currentPos = 0; std::size_t nextPos = 0; while (true) { nextPos = buffer.find('\n', currentPos); if ( nextPos == std::string::npos ) break; lines.emplace_back(buffer, currentPos, (nextPos - currentPos)); currentPos = nextPos + 1; } }