oma-pm 0.63.1

APT package manager API abstraction library
Documentation
use std::{fs, io, path::Path};

#[cfg(feature = "aosc")]
pub fn pkg_is_current_kernel(
    sysroot: &Path,
    image_name: &once_cell::sync::OnceCell<Option<String>>,
    pkg_name: &str,
    current_kernel_ver: &str,
) -> bool {
    use spdlog::{debug, warn};

    fn is_installed_pkg_contains_file_impl(
        pkg_name: &str,
        image_names: &[impl AsRef<str>],
        sysroot: &Path,
    ) -> bool {
        is_installed_pkg_contains_file(pkg_name, image_names, sysroot).unwrap_or_else(|e| {
            warn!("Failed to get package {pkg_name} file list: {e}");
            false
        })
    }

    let image_name = image_name.get_or_init(get_kernel_image_filename);
    debug!("image name = {image_name:?}");

    if let Some(image_name) = image_name {
        is_installed_pkg_contains_file_impl(pkg_name, &[image_name], sysroot)
    } else {
        is_installed_pkg_contains_file_impl(
            pkg_name,
            &[
                format!("vmlinux-{current_kernel_ver}"),
                format!("vmlinuz-{current_kernel_ver}"),
            ],
            sysroot,
        )
    }
}

#[cfg(feature = "aosc")]
fn get_kernel_image_filename() -> Option<String> {
    let cmdline = fs::read_to_string("/proc/cmdline").ok()?;

    for i in cmdline.split_ascii_whitespace() {
        if let Some(image_path) = i.strip_prefix("BOOT_IMAGE=") {
            return Some(
                Path::new(image_path)
                    .file_name()
                    .map(|x| x.to_string_lossy().to_string())
                    .unwrap_or_else(|| image_path.to_string()),
            );
        }
    }

    None
}

pub fn is_installed_pkg_contains_file(
    pkg_name: &str,
    file_names: &[impl AsRef<str>],
    sysroot: &Path,
) -> io::Result<bool> {
    let p = sysroot.join(format!("var/lib/dpkg/info/{pkg_name}.list"));
    let file = fs::read_to_string(&p)?;

    for line in file.lines() {
        if Path::new(line).file_name().is_some_and(|n| {
            file_names
                .iter()
                .any(|name| name.as_ref() == n.to_string_lossy())
        }) {
            return Ok(true);
        }
    }

    Ok(false)
}