feat: inject env vars in soldier runtime

This commit is contained in:
Gabriele Musco 2025-07-22 07:25:18 +02:00
commit 1ad8a29df1
3 changed files with 94 additions and 21 deletions

View file

@ -17,7 +17,9 @@ use std::{
os::unix::fs::MetadataExt, os::unix::fs::MetadataExt,
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
use steam_linux_runtime_injector::restore_runtime_entrypoint; use steam_linux_runtime_injector::{
restore_sniper_runtime_entrypoint, restore_soldier_runtime_entrypoint,
};
use tracing::{error, warn}; use tracing::{error, warn};
use tracing_subscriber::{ use tracing_subscriber::{
filter::LevelFilter, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer, filter::LevelFilter, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer,
@ -68,7 +70,8 @@ fn restore_steam_xr_files() {
} }
} }
} }
restore_runtime_entrypoint(); restore_sniper_runtime_entrypoint();
restore_soldier_runtime_entrypoint();
} }
const LOGS_MAX_SIZE_BYTES: u64 = 1000000000; // 1GB const LOGS_MAX_SIZE_BYTES: u64 = 1000000000; // 1GB

View file

@ -15,39 +15,67 @@ use std::{
}; };
use tracing::error; use tracing::error;
pub const PRESSURE_VESSEL_STEAM_APPID: u32 = 1628350; pub const SNIPER_RUNTIME_STEAM_APPID: u32 = 1628350;
pub const SOLDIER_RUNTIME_STEAM_APPID: u32 = 1391110;
fn get_runtime_entrypoint_path() -> Option<PathBuf> { fn get_sniper_runtime_entrypoint_path() -> Option<PathBuf> {
match SteamLibraryFolder::get_folders() { match SteamLibraryFolder::get_folders() {
Ok(libraryfolders) => libraryfolders Ok(libraryfolders) => libraryfolders
.iter() .iter()
.find(|(_, folder)| folder.apps.contains_key(&PRESSURE_VESSEL_STEAM_APPID)) .find(|(_, folder)| folder.apps.contains_key(&SNIPER_RUNTIME_STEAM_APPID))
.map(|(_, folder)| { .map(|(_, folder)| {
PathBuf::from(&folder.path) PathBuf::from(&folder.path)
.join("steamapps/common/SteamLinuxRuntime_sniper/_v2-entry-point") .join("steamapps/common/SteamLinuxRuntime_sniper/_v2-entry-point")
}), }),
Err(e) => { Err(e) => {
error!("unable to get runtime entrypoint path: {e}"); error!("unable to get sniper runtime entrypoint path: {e}");
None
}
}
}
fn get_soldier_runtime_entrypoint_path() -> Option<PathBuf> {
match SteamLibraryFolder::get_folders() {
Ok(libraryfolders) => libraryfolders
.iter()
.find(|(_, folder)| folder.apps.contains_key(&SOLDIER_RUNTIME_STEAM_APPID))
.map(|(_, folder)| {
PathBuf::from(&folder.path)
.join("steamapps/common/SteamLinuxRuntime_soldier/_v2-entry-point")
}),
Err(e) => {
error!("unable to get soldier runtime entrypoint path: {e}");
None None
} }
} }
} }
lazy_static! { lazy_static! {
static ref STEAM_RUNTIME_ENTRYPOINT_PATH: Option<PathBuf> = get_runtime_entrypoint_path(); static ref STEAM_SNIPER_RUNTIME_ENTRYPOINT_PATH: Option<PathBuf> =
get_sniper_runtime_entrypoint_path();
static ref STEAM_SOLDIER_RUNTIME_ENTRYPOINT_PATH: Option<PathBuf> =
get_soldier_runtime_entrypoint_path();
} }
fn get_backup_runtime_entrypoint_location() -> PathBuf { fn get_backup_sniper_runtime_entrypoint_location() -> PathBuf {
get_backup_dir().join("_v2-entry-point.bak") get_backup_dir().join("_v2-entry-point.bak")
} }
fn backup_runtime_entrypoint(path: &Path) { fn get_backup_soldier_runtime_entrypoint_location() -> PathBuf {
copy_file(path, &get_backup_runtime_entrypoint_location()); get_backup_dir().join("_v2-entry-point.soldier.bak")
} }
pub fn restore_runtime_entrypoint() { fn backup_sniper_runtime_entrypoint(path: &Path) {
if let Some(path) = STEAM_RUNTIME_ENTRYPOINT_PATH.as_ref() { copy_file(path, &get_backup_sniper_runtime_entrypoint_location());
let backup = get_backup_runtime_entrypoint_location(); }
fn backup_soldier_runtime_entrypoint(path: &Path) {
copy_file(path, &get_backup_soldier_runtime_entrypoint_location());
}
pub fn restore_sniper_runtime_entrypoint() {
if let Some(path) = STEAM_SNIPER_RUNTIME_ENTRYPOINT_PATH.as_ref() {
let backup = get_backup_sniper_runtime_entrypoint_location();
if Path::new(&backup).is_file() { if Path::new(&backup).is_file() {
copy_file(&backup, path); copy_file(&backup, path);
let _ = mark_as_executable(path); let _ = mark_as_executable(path);
@ -55,6 +83,17 @@ pub fn restore_runtime_entrypoint() {
} }
} }
pub fn restore_soldier_runtime_entrypoint() {
if let Some(path) = STEAM_SOLDIER_RUNTIME_ENTRYPOINT_PATH.as_ref() {
let backup = get_backup_soldier_runtime_entrypoint_location();
if Path::new(&backup).is_file() {
copy_file(&backup, path);
let _ = mark_as_executable(path);
}
}
}
/// this implementation is identical for both sniper and soldier runtimes
fn append_to_runtime_entrypoint(data: &str, path: &Path) -> anyhow::Result<()> { fn append_to_runtime_entrypoint(data: &str, path: &Path) -> anyhow::Result<()> {
let existing = read_to_string(path)?; let existing = read_to_string(path)?;
let new = existing.replace( let new = existing.replace(
@ -66,10 +105,12 @@ fn append_to_runtime_entrypoint(data: &str, path: &Path) -> anyhow::Result<()> {
Ok(()) Ok(())
} }
pub fn set_runtime_entrypoint_launch_opts_from_profile(profile: &Profile) -> anyhow::Result<()> { pub fn set_sniper_runtime_entrypoint_launch_opts_from_profile(
restore_runtime_entrypoint(); profile: &Profile,
if let Some(dest) = STEAM_RUNTIME_ENTRYPOINT_PATH.as_ref() { ) -> anyhow::Result<()> {
backup_runtime_entrypoint(dest); restore_sniper_runtime_entrypoint();
if let Some(dest) = STEAM_SNIPER_RUNTIME_ENTRYPOINT_PATH.as_ref() {
backup_sniper_runtime_entrypoint(dest);
append_to_runtime_entrypoint( append_to_runtime_entrypoint(
&profile &profile
.get_env_vars() .get_env_vars()
@ -83,5 +124,27 @@ pub fn set_runtime_entrypoint_launch_opts_from_profile(profile: &Profile) -> any
return Ok(()); return Ok(());
} }
bail!("Could not find valid runtime entrypoint"); bail!("Could not find valid sniper runtime entrypoint");
}
pub fn set_soldier_runtime_entrypoint_launch_opts_from_profile(
profile: &Profile,
) -> anyhow::Result<()> {
restore_soldier_runtime_entrypoint();
if let Some(dest) = STEAM_SOLDIER_RUNTIME_ENTRYPOINT_PATH.as_ref() {
backup_soldier_runtime_entrypoint(dest);
append_to_runtime_entrypoint(
&profile
.get_env_vars()
.iter()
.map(|ev| "export ".to_string() + ev)
.collect::<Vec<String>>()
.join("\n"),
dest,
)?;
mark_as_executable(dest)?;
return Ok(());
}
bail!("Could not find valid soldier runtime entrypoint");
} }

View file

@ -41,7 +41,9 @@ use crate::{
profile::{OvrCompatibilityModuleType, Profile, XRServiceType}, profile::{OvrCompatibilityModuleType, Profile, XRServiceType},
stateless_action, stateless_action,
steam_linux_runtime_injector::{ steam_linux_runtime_injector::{
restore_runtime_entrypoint, set_runtime_entrypoint_launch_opts_from_profile, restore_sniper_runtime_entrypoint, restore_soldier_runtime_entrypoint,
set_sniper_runtime_entrypoint_launch_opts_from_profile,
set_soldier_runtime_entrypoint_launch_opts_from_profile,
}, },
termcolor::TermColor, termcolor::TermColor,
util::file_utils::{ util::file_utils::{
@ -234,13 +236,17 @@ impl App {
); );
worker.start(); worker.start();
self.xrservice_worker = Some(worker); self.xrservice_worker = Some(worker);
let set_sniper_launch_opts_res =
set_sniper_runtime_entrypoint_launch_opts_from_profile(&prof);
let set_soldier_launch_opts_res =
set_soldier_runtime_entrypoint_launch_opts_from_profile(&prof);
self.main_view self.main_view
.sender() .sender()
.emit(MainViewMsg::XRServiceActiveChanged( .emit(MainViewMsg::XRServiceActiveChanged(
true, true,
Some(self.get_selected_profile()), Some(self.get_selected_profile()),
// show launch opts only if setting the runtime entrypoint fails // show launch opts only if setting the runtime entrypoint fails
set_runtime_entrypoint_launch_opts_from_profile(&prof).is_err(), set_sniper_launch_opts_res.is_err() || set_soldier_launch_opts_res.is_err(),
)); ));
self.debug_view self.debug_view
.sender() .sender()
@ -304,7 +310,8 @@ impl App {
} }
pub fn restore_openxr_openvr_files(&self) { pub fn restore_openxr_openvr_files(&self) {
restore_runtime_entrypoint(); restore_sniper_runtime_entrypoint();
restore_soldier_runtime_entrypoint();
if let Err(e) = remove_current_active_runtime() { if let Err(e) = remove_current_active_runtime() {
alert( alert(
"Could not remove profile active runtime", "Could not remove profile active runtime",