[yabridgectl] Fix setup checks with 32-bit prefix

This will now run `yabridge-host-32.exe` if `~/.wine` was created with
`WINEARCH=win32`.
This commit is contained in:
Robbert van der Helm
2021-06-25 02:13:16 +02:00
parent 6573b01c2d
commit 5133f07c2c
3 changed files with 79 additions and 17 deletions
+5
View File
@@ -70,6 +70,11 @@ Versioning](https://semver.org/spec/v2.0.0.html).
- Added support for setting up merged VST3 bundles with a 32-bit version of - Added support for setting up merged VST3 bundles with a 32-bit version of
`libyabridge-vst3.so`. `libyabridge-vst3.so`.
- Fixed the post-installation setup checks when the default Wine prefix over at
`~/.wine` was created with `WINEARCH=win32` set. This would otherwise result
in an `00cc:err:process:exec_process` error when running `yabridgectl sync`
because yabridgectl would try to run the 64-bit `yabridge-host.exe` in that
prefix.
- Merged VST3 bundles set up in `~/.vst3/yabridge` are now always cleared before - Merged VST3 bundles set up in `~/.vst3/yabridge` are now always cleared before
yabridgectl adds new files to them. This makes it easier to switch from the yabridgectl adds new files to them. This makes it easier to switch from the
64-bit version of a plugin to the 32-bit version, or from a 64-bit version of 64-bit version of a plugin to the 32-bit version, or from a 64-bit version of
+24 -11
View File
@@ -42,6 +42,10 @@ pub const LIBYABRIDGE_VST2_NAME: &str = "libyabridge-vst2.so";
pub const LIBYABRIDGE_VST3_NAME: &str = "libyabridge-vst3.so"; pub const LIBYABRIDGE_VST3_NAME: &str = "libyabridge-vst3.so";
/// The name of the script we're going to run to verify that everything's working correctly. /// The name of the script we're going to run to verify that everything's working correctly.
pub const YABRIDGE_HOST_EXE_NAME: &str = "yabridge-host.exe"; pub const YABRIDGE_HOST_EXE_NAME: &str = "yabridge-host.exe";
/// The 32-bit verison of `YABRIDGE_HOST_EXE_NAME`. If `~/.wine` was somehow created with
/// `WINEARCH=win32` set, then it won't be possible to run the 64-bit `yabridge-host.exe` in there.
/// In that case we'll just run the 32-bit version isntead, if it exists.
pub const YABRIDGE_HOST_32_EXE_NAME: &str = "yabridge-host-32.exe";
/// The name of the XDG base directory prefix for yabridge's own files, relative to /// The name of the XDG base directory prefix for yabridge's own files, relative to
/// `$XDG_CONFIG_HOME` and `$XDG_DATA_HOME`. /// `$XDG_CONFIG_HOME` and `$XDG_DATA_HOME`.
const YABRIDGE_PREFIX: &str = "yabridge"; const YABRIDGE_PREFIX: &str = "yabridge";
@@ -149,10 +153,15 @@ pub struct YabridgeFiles {
pub libyabridge_vst3: Option<(PathBuf, LibArchitecture)>, pub libyabridge_vst3: Option<(PathBuf, LibArchitecture)>,
/// The path to `yabridge-host.exe`. This is the path yabridge will actually use, and it does /// The path to `yabridge-host.exe`. This is the path yabridge will actually use, and it does
/// not have to be relative to `yabridge_home`. /// not have to be relative to `yabridge_home`.
pub yabridge_host_exe: PathBuf, pub yabridge_host_exe: Option<PathBuf>,
/// The actual Winelib binary for `yabridge-host.exe`. Will be hashed to check whether the user /// The actual Winelib binary for `yabridge-host.exe`. Will be hashed to check whether the user
/// has updated yabridge. /// has updated yabridge.
pub yabridge_host_exe_so: PathBuf, pub yabridge_host_exe_so: Option<PathBuf>,
/// The same as `yabridge_host_exe`, but for the 32-bit verison.
pub yabridge_host_32_exe: Option<PathBuf>,
/// The same as `yabridge_host_exe_so`, but for the 32-bit verison. We will hash this instead of
/// there's no 64-bit version available.
pub yabridge_host_32_exe_so: Option<PathBuf>,
} }
impl Default for Config { impl Default for Config {
@@ -279,22 +288,26 @@ impl Config {
// `yabridge-host.exe` should either be in the search path, or it should be in // `yabridge-host.exe` should either be in the search path, or it should be in
// `~/.local/share/yabridge` // `~/.local/share/yabridge`
let yabridge_host_exe = match which(YABRIDGE_HOST_EXE_NAME) let yabridge_host_exe = which(YABRIDGE_HOST_EXE_NAME)
.ok() .ok()
.or_else(|| xdg_dirs.find_data_file(YABRIDGE_HOST_EXE_NAME)) .or_else(|| xdg_dirs.find_data_file(YABRIDGE_HOST_EXE_NAME));
{ let yabridge_host_exe_so = yabridge_host_exe
Some(path) => path, .as_ref()
_ => { .map(|path| path.with_extension("exe.so"));
return Err(anyhow!("Could not locate '{}'.", YABRIDGE_HOST_EXE_NAME)); let yabridge_host_32_exe = which(YABRIDGE_HOST_32_EXE_NAME)
} .ok()
}; .or_else(|| xdg_dirs.find_data_file(YABRIDGE_HOST_32_EXE_NAME));
let yabridge_host_exe_so = yabridge_host_exe.with_extension("exe.so"); let yabridge_host_32_exe_so = yabridge_host_32_exe
.as_ref()
.map(|path| path.with_extension("exe.so"));
Ok(YabridgeFiles { Ok(YabridgeFiles {
libyabridge_vst2, libyabridge_vst2,
libyabridge_vst3, libyabridge_vst3,
yabridge_host_exe, yabridge_host_exe,
yabridge_host_exe_so, yabridge_host_exe_so,
yabridge_host_32_exe,
yabridge_host_32_exe_so,
}) })
} }
+50 -6
View File
@@ -23,14 +23,14 @@ use std::collections::hash_map::DefaultHasher;
use std::env; use std::env;
use std::fs; use std::fs;
use std::hash::Hasher; use std::hash::Hasher;
use std::io::{Read, Seek, SeekFrom}; use std::io::{BufRead, BufReader, Read, Seek, SeekFrom};
use std::os::unix::fs as unix_fs; use std::os::unix::fs as unix_fs;
use std::os::unix::process::CommandExt; use std::os::unix::process::CommandExt;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use textwrap::Wrapper; use textwrap::Wrapper;
use crate::config::{self, Config, KnownConfig, YABRIDGE_HOST_EXE_NAME}; use crate::config::{self, Config, KnownConfig, YABRIDGE_HOST_32_EXE_NAME, YABRIDGE_HOST_EXE_NAME};
use crate::files::{LibArchitecture, NativeFile}; use crate::files::{LibArchitecture, NativeFile};
/// (Part of) the expected output when running `yabridge-host.exe`. Used to verify that everything's /// (Part of) the expected output when running `yabridge-host.exe`. Used to verify that everything's
@@ -132,6 +132,33 @@ pub fn get_file_type(path: PathBuf) -> Option<NativeFile> {
} }
} }
/// Get the architecture (either 64-bit or 32-bit) of the default Wine prefix in `~/.wine`. Defaults
/// to 64-bit if `~/.wine` doesn't exist or if the prefix is invalid.
pub fn get_default_wine_prefix_arch() -> LibArchitecture {
let wine_system_reg_path = PathBuf::from(env::var("HOME").expect("$HOME is not set"))
.join(".wine")
.join("system.reg");
// Fall back to 64-bit if the prefix doesn't exist
let wine_system_reg = match fs::File::open(wine_system_reg_path) {
Ok(file) => file,
_ => return LibArchitecture::Lib64,
};
for line in BufReader::new(wine_system_reg)
.lines()
.filter_map(|l| l.ok())
{
match line.as_str() {
"#arch=win32" => return LibArchitecture::Lib32,
"#arch=win64" => break,
_ => (),
};
}
LibArchitecture::Lib64
}
/// Hash the conetnts of a file as an `i64` using Rust's built in hasher. Collisions are not a big /// Hash the conetnts of a file as an `i64` using Rust's built in hasher. Collisions are not a big
/// issue in our situation so we can get away with this. /// issue in our situation so we can get away with this.
/// ///
@@ -310,8 +337,14 @@ pub fn verify_wine_setup(config: &mut Config) -> Result<()> {
.context(format!("Could not find '{}'", YABRIDGE_HOST_EXE_NAME))?; .context(format!("Could not find '{}'", YABRIDGE_HOST_EXE_NAME))?;
// Hash the contents of `yabridge-host.exe.so` since `yabridge-host.exe` is only a Wine // Hash the contents of `yabridge-host.exe.so` since `yabridge-host.exe` is only a Wine
// generated shell script // generated shell script. If somehow only the 32-bit verison is installed, we'll just hash that
let yabridge_host_hash = hash_file(&files.yabridge_host_exe_so)?; // one.
let yabridge_host_hash = hash_file(
&files
.yabridge_host_exe_so
.or(files.yabridge_host_32_exe_so)
.with_context(|| format!("Could not locate '{}.so'", YABRIDGE_HOST_EXE_NAME))?,
)?;
// Since these checks can take over a second if wineserver isn't already running we'll only // Since these checks can take over a second if wineserver isn't already running we'll only
// perform them when something has changed // perform them when something has changed
@@ -323,9 +356,20 @@ pub fn verify_wine_setup(config: &mut Config) -> Result<()> {
return Ok(()); return Ok(());
} }
let output = Command::new(&files.yabridge_host_exe) // It could be that the default Wine prefix was created with `WINEARCH=win32` set. In that case
// we should run the 32-bit `yabridge-host.exe` since the 64-bit verison won't be able to run.
let host_binary_path = match get_default_wine_prefix_arch() {
LibArchitecture::Lib32 => files
.yabridge_host_32_exe
.with_context(|| format!("Could not find '{}'", YABRIDGE_HOST_32_EXE_NAME)),
LibArchitecture::Lib64 => files
.yabridge_host_exe
.with_context(|| format!("Could not find '{}'", YABRIDGE_HOST_EXE_NAME)),
}?;
let output = Command::new(&host_binary_path)
.output() .output()
.with_context(|| format!("Could not run '{}'", files.yabridge_host_exe.display()))?; .with_context(|| format!("Could not run '{}'", host_binary_path.display()))?;
let stderr = String::from_utf8(output.stderr)?; let stderr = String::from_utf8(output.stderr)?;
// There are three scenarios here: // There are three scenarios here: