provenant-cli 0.0.15

Rust-based ScanCode-compatible scanner for licenses, package metadata, SBOMs, and provenance data.
Documentation
use std::fs::File;
use std::io::Read;
use std::path::Path;

use anyhow::{Result, anyhow};
use rusqlite::{Connection, OpenFlags};

use super::BlobReader;

const SQLITE_HEADER_MAGIC: &[u8] = b"SQLite format 3\0";

pub(crate) struct SqliteDatabase {
    connection: Connection,
}

impl SqliteDatabase {
    pub(crate) fn open(path: &Path) -> Result<Self> {
        let mut header = [0_u8; 16];
        File::open(path)?.read_exact(&mut header)?;
        if header != SQLITE_HEADER_MAGIC {
            return Err(anyhow!("RPM sqlite database missing SQLite header magic"));
        }

        let connection = Connection::open_with_flags(path, OpenFlags::SQLITE_OPEN_READ_ONLY)?;
        Ok(Self { connection })
    }
}

impl BlobReader for SqliteDatabase {
    fn read_blobs(&mut self) -> Result<Vec<Vec<u8>>> {
        let mut statement = self
            .connection
            .prepare("SELECT blob FROM Packages ORDER BY hnum")?;
        let rows = statement.query_map([], |row| row.get::<_, Vec<u8>>(0))?;
        let mut blobs = Vec::new();
        for row in rows {
            blobs.push(row?);
        }
        Ok(blobs)
    }
}