예제 #1
0
//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(), &params, 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());
}
예제 #2
0
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());
	}
}
예제 #3
0
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());
	}
}
예제 #4
0
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;
	}
}