pmv_encryption_rs 1.0.0

Implementation of PersonalMediaVault encrypted storage model. This library allows to encrypt and decrypt data, and also read ans write files in the same format PersonalMediaVault uses.
Documentation
// Read stream

use std::{
    fs::File,
    io::{self, Read, Seek},
    path::Path,
};

use byteorder::{BigEndian, ByteOrder};

use crate::MultiFilePackReadError;

pub struct MultiFilePackReadStream {
    /// File descriptor
    file: File,

    /// Number of files inside the packed file
    file_count: u64,

    // Size of the file
    file_size: u64,
}

impl MultiFilePackReadStream {
    /// Creates a new instance of MultiFilePackReadStream
    /// Opens the file and reads the header
    ///
    /// Parameters:
    ///  - `file_path` - Path to the file to open
    ///
    /// Returns an instance of MultiFilePackReadStream, or an error
    pub fn new<P>(file_path: P) -> Result<MultiFilePackReadStream, io::Error>
    where
        P: AsRef<Path>,
    {
        let mut file = File::open(file_path)?;

        let file_size = file.metadata()?.len();

        // Read file count

        let mut buf: [u8; 8] = [0; 8];

        file.read_exact(&mut buf)?;

        let file_count = BigEndian::read_u64(&buf);

        Ok(MultiFilePackReadStream {
            file,
            file_count,
            file_size,
        })
    }

    /// Gets the number of files
    pub fn get_file_count(&self) -> u64 {
        self.file_count
    }

    /// Reads a file by its index
    /// Puts the data inside of a vector
    /// Resizes the vector to match the size of the file
    ///
    /// Parameters:
    ///  - `index` - The index of the file (Starts with 0, up to file_count - 1)
    ///  - `vec` - the vector
    ///
    /// May return an error if it fails
    pub fn get_file_in_vector(
        &mut self,
        index: u64,
        vec: &mut Vec<u8>,
    ) -> Result<(), MultiFilePackReadError> {
        if index >= self.file_count {
            return Err(MultiFilePackReadError::IndexOutOfBounds);
        }

        // Read file index

        let mut buf_file_index: [u8; 16] = [0; 16];

        self.file.seek(io::SeekFrom::Start(8 + index * 16))?;
        self.file.read_exact(&mut buf_file_index)?;

        let file_start = BigEndian::read_u64(&buf_file_index[0..8]);
        let file_length = BigEndian::read_u64(&buf_file_index[8..16]);

        if file_start > self.file_size
            || file_length > self.file_size
            || file_start + file_length > self.file_size
        {
            return Err(MultiFilePackReadError::IoError(
                "Invalid size found in file index entry".to_string(),
            ));
        }

        // Read file

        vec.resize(file_length as usize, 0);

        self.file.seek(io::SeekFrom::Start(file_start))?;
        self.file.read_exact(vec)?;

        Ok(())
    }

    /// Reads a file by its index
    ///
    /// Parameters:
    ///  - `index` - The index of the file (Starts with 0, up to file_count - 1)
    ///
    /// Returns the file data, or an error
    pub fn get_file(&mut self, index: u64) -> Result<Vec<u8>, MultiFilePackReadError> {
        let mut data: Vec<u8> = Vec::new();

        self.get_file_in_vector(index, &mut data)?;

        Ok(data)
    }

    /// Closes the file and drops the instance of the stream
    pub fn close(self) {}
}