//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()); } }