From e94d48085fb2e64f61b09053d0c6578d2e7761cb Mon Sep 17 00:00:00 2001 From: Rabindra Dhakal Date: Wed, 30 Oct 2024 20:59:57 +0545 Subject: [PATCH] feat(flatimage): integrate flatimage using remote files --- src/core/constant.rs | 4 +-- src/core/file.rs | 29 ++++++++++++++++++ src/core/mod.rs | 1 + src/registry/package/appimage.rs | 31 ++++++------------- src/registry/package/install.rs | 51 ++++++++++++++++++++++++-------- 5 files changed, 80 insertions(+), 36 deletions(-) create mode 100644 src/core/file.rs diff --git a/src/core/constant.rs b/src/core/constant.rs index 5cacbde..8b2b7eb 100644 --- a/src/core/constant.rs +++ b/src/core/constant.rs @@ -13,9 +13,9 @@ pub static INSTALL_TRACK_PATH: LazyLock = pub static PACKAGES_PATH: LazyLock = LazyLock::new(|| build_path(&CONFIG.soar_path).unwrap().join("packages")); -pub const APPIMAGE_MAGIC_OFFSET: u64 = 8; -pub const APPIMAGE_MAGIC_BYTES: [u8; 4] = [0x41, 0x49, 0x02, 0x00]; pub const ELF_MAGIC_BYTES: [u8; 4] = [0x7f, 0x45, 0x4c, 0x46]; +pub const APPIMAGE_MAGIC_BYTES: [u8; 4] = [0x41, 0x49, 0x02, 0x00]; +pub const FLATIMAGE_MAGIC_BYTES: [u8; 4] = [0x46, 0x49, 0x02, 0x00]; pub const CAP_SYS_ADMIN: i32 = 21; pub const CAP_MKNOD: i32 = 27; diff --git a/src/core/file.rs b/src/core/file.rs new file mode 100644 index 0000000..1ccdcd6 --- /dev/null +++ b/src/core/file.rs @@ -0,0 +1,29 @@ +use std::{ + fs::File, + io::{BufReader, Read}, +}; + +use super::constant::{APPIMAGE_MAGIC_BYTES, ELF_MAGIC_BYTES, FLATIMAGE_MAGIC_BYTES}; + +pub enum FileType { + AppImage, + FlatImage, + ELF, + Unknown, +} + +pub fn get_file_type(file: &mut BufReader) -> FileType { + let mut magic_bytes = [0u8; 12]; + if file.read_exact(&mut magic_bytes).is_ok() { + if magic_bytes[8..] == APPIMAGE_MAGIC_BYTES { + return FileType::AppImage; + } else if magic_bytes[8..] == FLATIMAGE_MAGIC_BYTES { + return FileType::FlatImage; + } else if magic_bytes[..4] == ELF_MAGIC_BYTES { + return FileType::ELF; + } else { + return FileType::Unknown; + } + } + FileType::Unknown +} diff --git a/src/core/mod.rs b/src/core/mod.rs index de687c4..1be17ac 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -1,6 +1,7 @@ pub mod color; pub mod config; pub mod constant; +pub mod file; pub mod health; pub mod log; pub mod util; diff --git a/src/registry/package/appimage.rs b/src/registry/package/appimage.rs index d4a46a1..9f335c3 100644 --- a/src/registry/package/appimage.rs +++ b/src/registry/package/appimage.rs @@ -1,7 +1,7 @@ use std::{ collections::HashSet, fs::File, - io::{BufReader, BufWriter, Read, Seek, SeekFrom, Write}, + io::{BufReader, BufWriter, Read, Seek, Write}, path::{Path, PathBuf}, }; @@ -13,7 +13,7 @@ use tokio::{fs, try_join}; use crate::{ core::{ color::{Color, ColorExt}, - constant::{APPIMAGE_MAGIC_BYTES, APPIMAGE_MAGIC_OFFSET, BIN_PATH, PACKAGES_PATH}, + constant::{BIN_PATH, PACKAGES_PATH}, util::{download, home_data_path}, }, error, info, @@ -78,16 +78,6 @@ fn normalize_image(image: DynamicImage) -> DynamicImage { } } -fn is_appimage(file: &mut BufReader) -> bool { - if file.seek(SeekFrom::Start(APPIMAGE_MAGIC_OFFSET)).is_ok() { - let mut magic_bytes = [0_u8; 4]; - if file.read_exact(&mut magic_bytes).is_ok() { - return APPIMAGE_MAGIC_BYTES == magic_bytes; - } - } - false -} - async fn create_symlink(from: &Path, to: &Path) -> Result<()> { if to.is_symlink() { if to.exists() && !to.read_link()?.starts_with(&*PACKAGES_PATH) { @@ -146,14 +136,12 @@ pub async fn remove_applinks(name: &str, bin_name: &str, file_path: &Path) -> Re Ok(()) } -pub async fn integrate_appimage(package: &Package, file_path: &Path) -> Result { - let mut file = BufReader::new(File::open(file_path)?); - - if !is_appimage(&mut file) { - return Ok(false); - } - - let offset = find_offset(&mut file).await?; +pub async fn integrate_appimage( + file: &mut BufReader, + package: &Package, + file_path: &Path, +) -> Result { + let offset = find_offset(file).await?; let squashfs = FilesystemReader::from_reader_with_offset(file, offset)?; let home_data = home_data_path(); @@ -301,8 +289,7 @@ async fn process_desktop( Ok(()) } -// TODO: use this if the package don't contain the required files -pub async fn _use_remote_files(package: &Package, file_path: &Path) -> Result<()> { +pub async fn integrate_using_remote_files(package: &Package, file_path: &Path) -> Result<()> { let home_data = home_data_path(); let data_path = Path::new(&home_data); diff --git a/src/registry/package/install.rs b/src/registry/package/install.rs index a12504d..affcd83 100644 --- a/src/registry/package/install.rs +++ b/src/registry/package/install.rs @@ -1,4 +1,10 @@ -use std::{fs::Permissions, io::Write, os::unix::fs::PermissionsExt, path::PathBuf, sync::Arc}; +use std::{ + fs::{File, Permissions}, + io::{BufReader, Write}, + os::unix::fs::PermissionsExt, + path::PathBuf, + sync::Arc, +}; use anyhow::{Context, Result}; use futures::StreamExt; @@ -9,6 +15,7 @@ use crate::{ core::{ color::{Color, ColorExt}, constant::{BIN_PATH, PACKAGES_PATH}, + file::{get_file_type, FileType}, util::{calculate_checksum, format_bytes, validate_checksum}, }, registry::{ @@ -18,7 +25,7 @@ use crate::{ warn, }; -use super::ResolvedPackage; +use super::{appimage::integrate_using_remote_files, ResolvedPackage}; pub struct Installer { resolved_package: ResolvedPackage, @@ -202,16 +209,36 @@ impl Installer { self.save_file().await?; self.symlink_bin(&installed_packages).await?; - let ai_integrated = integrate_appimage(package, &self.install_path).await?; - if ai_integrated { - setup_portable_dir( - &package.bin_name, - &self.install_path, - portable, - portable_home, - portable_config, - ) - .await?; + let mut file = BufReader::new(File::open(&self.install_path)?); + let file_type = get_file_type(&mut file); + + match file_type { + FileType::AppImage => { + if integrate_appimage(&mut file, package, &self.install_path) + .await + .is_ok() + { + setup_portable_dir( + &package.bin_name, + &self.install_path, + portable, + portable_home, + portable_config, + ) + .await?; + } else { + warn!("{}: Failed to integrate AppImage", prefix); + }; + } + FileType::FlatImage => { + if integrate_using_remote_files(package, &self.install_path) + .await + .is_err() + { + warn!("{}: Failed to integrate FlatImage", prefix); + }; + } + _ => {} } {