feat: clearer messaging around setcap failures; getcap after setcap
Some checks failed
/ cargo-fmtcheck (push) Has been cancelled
/ cargo-clippy (push) Has been cancelled
/ cargo-test (push) Has been cancelled
/ appimage (push) Has been cancelled

This commit is contained in:
Gabriele Musco 2024-12-18 23:19:24 +01:00
commit 0020dcf3d4
2 changed files with 45 additions and 6 deletions

View file

@ -41,7 +41,9 @@ use crate::{
steam_linux_runtime_injector::{ steam_linux_runtime_injector::{
restore_runtime_entrypoint, set_runtime_entrypoint_launch_opts_from_profile, restore_runtime_entrypoint, set_runtime_entrypoint_launch_opts_from_profile,
}, },
util::file_utils::{setcap_cap_sys_nice_eip, setcap_cap_sys_nice_eip_cmd}, util::file_utils::{
setcap_cap_sys_nice_eip, setcap_cap_sys_nice_eip_cmd, verify_cap_sys_nice_eip,
},
vulkaninfo::VulkanInfo, vulkaninfo::VulkanInfo,
wivrn_dbus, wivrn_dbus,
xr_devices::XRDevice, xr_devices::XRDevice,
@ -653,7 +655,23 @@ impl AsyncComponent for App {
error!("pkexec not found, skipping setcap"); error!("pkexec not found, skipping setcap");
} else { } else {
let profile = self.get_selected_profile(); let profile = self.get_selected_profile();
setcap_cap_sys_nice_eip(&profile).await; let setcap_failed_dialog = || {
alert_w_widget(
"Setcap failed to run",
Some("Setting the capabilities automatically failed, you can still try manually using the command below."
),
Some(&copiable_code_snippet(
&format!("sudo {}", setcap_cap_sys_nice_eip_cmd(&profile).join(" "))
)),
Some(&self.app_win.clone().upcast())
);
};
if let Err(e) = setcap_cap_sys_nice_eip(&profile).await {
setcap_failed_dialog();
error!("failed running setcap: {e}");
} else if !verify_cap_sys_nice_eip(&profile).await {
setcap_failed_dialog();
}
} }
} }
Msg::ProfileSelected(prof) => { Msg::ProfileSelected(prof) => {

View file

@ -90,13 +90,34 @@ pub fn setcap_cap_sys_nice_eip_cmd(profile: &Profile) -> Vec<String> {
] ]
} }
pub async fn setcap_cap_sys_nice_eip(profile: &Profile) { pub async fn verify_cap_sys_nice_eip(profile: &Profile) -> bool {
if let Err(e) = async_process("pkexec", Some(&setcap_cap_sys_nice_eip_cmd(profile)), None).await let xrservice_binary = profile.xrservice_binary().to_string_lossy().to_string();
{ match async_process("getcap", Some(&[&xrservice_binary]), None).await {
error!("failed running setcap: {e}"); Err(e) => {
error!("failed to run `getcap {xrservice_binary}`: {e:?}");
false
}
Ok(out) => {
debug!("getcap {xrservice_binary} stdout: {}", out.stdout);
debug!("getcap {xrservice_binary} stderr: {}", out.stderr);
if out.exit_code != 0 {
error!(
"command `getcap {xrservice_binary}` failed with status code {}",
out.exit_code
);
false
} else {
out.stdout.to_lowercase().contains("cap_sys_nice=eip")
}
}
} }
} }
pub async fn setcap_cap_sys_nice_eip(profile: &Profile) -> anyhow::Result<()> {
async_process("pkexec", Some(&setcap_cap_sys_nice_eip_cmd(profile)), None).await?;
Ok(())
}
pub fn rm_rf(path: &Path) { pub fn rm_rf(path: &Path) {
if remove_dir_all(path).is_err() { if remove_dir_all(path).is_err() {
error!("failed to remove path {}", path.to_string_lossy()); error!("failed to remove path {}", path.to_string_lossy());