3 Commits

Author SHA1 Message Date
Novattz
09e7bcac6f bump version 2026-01-18 09:43:08 +01:00
Novattz
b7f219a25f changelog 2026-01-18 09:43:02 +01:00
Novattz
2b205d8376 reduce time to detect game bitness 2026-01-18 09:42:58 +01:00
6 changed files with 80 additions and 26 deletions

View File

@@ -1,3 +1,8 @@
## [1.4.1] - 18-01-2026
### Added
- Dramatically reduced the time that bitness detection takes to detect game bitness
## [1.4.0] - 17-01-2026 ## [1.4.0] - 17-01-2026
### Added ### Added

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "creamlinux", "name": "creamlinux",
"version": "1.4.0", "version": "1.4.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "creamlinux", "name": "creamlinux",
"version": "1.4.0", "version": "1.4.1",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tauri-apps/api": "^2.5.0", "@tauri-apps/api": "^2.5.0",

View File

@@ -1,7 +1,7 @@
{ {
"name": "creamlinux", "name": "creamlinux",
"private": true, "private": true,
"version": "1.4.0", "version": "1.4.1",
"type": "module", "type": "module",
"author": "Tickbase", "author": "Tickbase",
"repository": "https://github.com/Novattz/creamlinux-installer", "repository": "https://github.com/Novattz/creamlinux-installer",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "creamlinux-installer" name = "creamlinux-installer"
version = "1.4.0" version = "1.4.1"
description = "DLC Manager for Steam games on Linux" description = "DLC Manager for Steam games on Linux"
authors = ["tickbase"] authors = ["tickbase"]
license = "MIT" license = "MIT"

View File

@@ -13,14 +13,19 @@ pub enum Bitness {
/// Detect the bitness of a Linux Binary by reading ELF header /// Detect the bitness of a Linux Binary by reading ELF header
/// ELF format: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format /// ELF format: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
fn detect_binary_bitness(file_path: &Path) -> Option<Bitness> { fn detect_binary_bitness(file_path: &Path) -> Option<Bitness> {
// Read first 5 bytes of the file to check ELF header use std::io::Read;
let bytes = match fs::read(file_path) {
Ok(b) if b.len() >= 5 => b, // Only read first 5 bytes
_ => return None, let mut file = fs::File::open(file_path).ok()?;
}; let mut bytes = [0u8; 5];
// Read exactly 5 bytes or fail
if file.read_exact(&mut bytes).is_err() {
return None;
}
// Check for ELF magic number (0x7F 'E' 'L' 'F') // Check for ELF magic number (0x7F 'E' 'L' 'F')
if bytes.len() < 5 || &bytes[0..4] != b"\x7FELF" { if &bytes[0..4] != b"\x7FELF" {
return None; return None;
} }
@@ -60,14 +65,32 @@ pub fn detect_game_bitness(game_path: &str) -> Result<Bitness, String> {
"logs", "logs",
"assets", "assets",
"_CommonRedist", "_CommonRedist",
"data",
"Data",
"Docs",
"docs",
"screenshots",
"Screenshots",
"saves",
"Saves",
"mods",
"Mods",
"maps",
"Maps",
]; ];
// Limit scan depth to avoid deep recursion // Limit scan depth to avoid deep recursion
const MAX_DEPTH: usize = 5; const MAX_DEPTH: usize = 3;
// Stop after finding reasonable confidence (10 binaries)
const CONFIDENCE_THRESHOLD: usize = 10;
let mut bit64_binaries = Vec::new(); let mut bit64_binaries = Vec::new();
let mut bit32_binaries = Vec::new(); let mut bit32_binaries = Vec::new();
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
// Scan for Linux binaries // Scan for Linux binaries
for entry in WalkDir::new(game_path_obj) for entry in WalkDir::new(game_path_obj)
.max_depth(MAX_DEPTH) .max_depth(MAX_DEPTH)
@@ -83,6 +106,12 @@ pub fn detect_game_bitness(game_path: &str) -> Result<Bitness, String> {
}) })
.filter_map(Result::ok) .filter_map(Result::ok)
{ {
// Early termination when we have high confidence
if bit64_binaries.len() >= CONFIDENCE_THRESHOLD || bit32_binaries.len() >= CONFIDENCE_THRESHOLD {
debug!("Reached confidence threshold, stopping scan early");
break;
}
let path = entry.path(); let path = entry.path();
// Only check files // Only check files
@@ -102,20 +131,24 @@ pub fn detect_game_bitness(game_path: &str) -> Result<Bitness, String> {
|| filename.starts_with("lib"); || filename.starts_with("lib");
// Check if file is executable // Check if file is executable
#[cfg(unix)] let is_executable = {
{ {
use std::os::unix::fs::PermissionsExt; // Get metadata once and check both extension and permissions
if let Ok(metadata) = fs::metadata(path) { if let Ok(metadata) = fs::metadata(path) {
let permissions = metadata.permissions(); let permissions = metadata.permissions();
let is_executable = permissions.mode() & 0o111 != 0; let executable = permissions.mode() & 0o111 != 0;
// Skip files that are neither executable nor have binary extensions // Skip files that are neither executable nor have binary extensions
if !is_executable && !has_binary_extension { executable || has_binary_extension
continue; } else {
// If we can't read metadata, only proceed if it has binary extension
has_binary_extension
} }
} else {
continue;
} }
};
if !is_executable {
continue;
} }
// Detect bitness // Detect bitness
@@ -123,8 +156,24 @@ pub fn detect_game_bitness(game_path: &str) -> Result<Bitness, String> {
debug!("Found {:?} binary: {}", bitness, path.display()); debug!("Found {:?} binary: {}", bitness, path.display());
match bitness { match bitness {
Bitness::Bit64 => bit64_binaries.push(path.to_path_buf()), Bitness::Bit64 => {
Bitness::Bit32 => bit32_binaries.push(path.to_path_buf()), bit64_binaries.push(path.to_path_buf());
// If we find libsteam_api.so and it's 64-bit, we can be very confident
if filename == "libsteam_api.so" {
info!("Found 64-bit libsteam_api.so");
return Ok(Bitness::Bit64);
}
},
Bitness::Bit32 => {
bit32_binaries.push(path.to_path_buf());
// If we find libsteam_api.so and it's 32-bit, we can be very confident
if filename == "libsteam_api.so" {
info!("Found 32-bit libsteam_api.so");
return Ok(Bitness::Bit32);
}
},
} }
} }
} }

View File

@@ -19,7 +19,7 @@
}, },
"productName": "Creamlinux", "productName": "Creamlinux",
"mainBinaryName": "creamlinux", "mainBinaryName": "creamlinux",
"version": "1.4.0", "version": "1.4.1",
"identifier": "com.creamlinux.dev", "identifier": "com.creamlinux.dev",
"app": { "app": {
"withGlobalTauri": false, "withGlobalTauri": false,