fast-shlibdeps 0.2.1

A fast ELF shared library dependency analyzer for Debian-based systems
use anyhow::Result;
use elf::{ElfBytes, endian::AnyEndian};
use std::fs;
use std::path::Path;

/// Get the shared libraries that the file at path depends on. If path isn't a valid ELF file, returns an empty vec.
pub(crate) fn get_file_dependencies(path: &Path) -> Result<Vec<String>> {
    let file_data = match fs::read(path) {
        Ok(data) => data,
        Err(_) => return Ok(Vec::new()),
    };

    let file = match ElfBytes::<AnyEndian>::minimal_parse(&file_data) {
        Ok(elf) => elf,
        Err(_) => return Ok(Vec::new()),
    };

    let mut dependencies = Vec::new();

    if let Ok(Some(dynamic)) = file.dynamic() {
        if let Ok(Some(strtab)) = file.section_header_by_name(".dynstr") {
            if let Ok(string_table) = file.section_data(&strtab) {
                for entry in dynamic.iter() {
                    if entry.d_tag == elf::abi::DT_NEEDED {
                        let offset = entry.d_val() as usize;
                        if let Some(null_pos) =
                            string_table.0[offset..].iter().position(|&b| b == 0)
                        {
                            if let Ok(lib_name) =
                                std::str::from_utf8(&string_table.0[offset..offset + null_pos])
                            {
                                dependencies.push(lib_name.to_string());
                            }
                        }
                    }
                }
            }
        }
    }

    Ok(dependencies)
}