diff --git a/src/database.rs b/src/database.rs new file mode 100644 index 0000000..2ea6e37 --- /dev/null +++ b/src/database.rs @@ -0,0 +1,3 @@ +pub trait LocateDb { + fn is(magic: &[u8]) -> bool; +} diff --git a/src/lib.rs b/src/lib.rs index 75ada27..3f0ad99 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,15 +1,33 @@ -extern crate structview; -use structview::{u32_be, View}; +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#[derive(Clone, Copy, View)] -#[repr(C)] -pub struct MlHeader { - magic: [u8; 8], /* '\0', 'm', 'l', 'o', 'c', 'a', 't', 'e' */ - conf_size: u32_be, - version: u8, - check_visibility: u8, - pad: [u8; 2], -} +//! MLocate +//! +//! The readme has the full explanation, but the `locate` suite of +//! tools present in all Linux distributions is used to locate files +//! on your storage device. Rather than search the device directly, +//! `locate` scans a catalog file created during downtime. +//! +//! `MLocate` is the most popular implementation of the locate system, +//! but it has three annoying flaws: +//! +//! 1. The archive file isn't very compressed. +//! 2. The archive file is always an average of 12 hours out of date. +//! 3. The archive is accessible only through a command line program. +//! +//! This program intends to read one of two different formats, the +//! classic mlocate format, or a new format that exploits a few nifty +//! tricks to try and make the database file smaller and access +//! faster. + +extern crate structview; + +pub mod database; +pub mod mlocate_db; + +use crate::database::LocateDb; +use crate::mlocate_db::MlHeader; #[cfg(test)] mod tests { @@ -22,20 +40,10 @@ mod tests { let db = File::open("/var/lib/mlocate/mlocate.db").expect("Unable to open file"); let mut reader = BufReader::new(db); match reader.fill_buf() { - Ok(buffer) => match MlHeader::view(&buffer[0..32]) { - Ok(header) => { - let text = &header.magic[1..8]; - assert_eq!(text, *b"mlocate"); - assert_eq!(header.version, 0); - let magic = std::str::from_utf8(text).unwrap_or("ERROR"); - println!( - "magic: {}\nversion: {}\nconf_size: {}\nvisibility: {}", - magic, header.version, header.conf_size, header.check_visibility - ); - Ok(()) - } - Err(_) => Err("The header did not unpack.".to_owned()), - }, + Ok(buffer) => { + assert!(MlHeader::is(buffer), "Could not read DB"); + Ok(()) + } Err(_) => Err("The header could not be read".to_owned()), } } diff --git a/src/mlocate_db/mod.rs b/src/mlocate_db/mod.rs new file mode 100644 index 0000000..a7cd4c2 --- /dev/null +++ b/src/mlocate_db/mod.rs @@ -0,0 +1,25 @@ +use crate::database::LocateDb; +use structview::{u32_be, View}; + +#[derive(Clone, Copy, View)] +#[repr(C)] +pub struct MlHeader { + magic: [u8; 8], /* '\0', 'm', 'l', 'o', 'c', 'a', 't', 'e' */ + conf_size: u32_be, + version: u8, + check_visibility: u8, + pad: [u8; 2], +} + +impl LocateDb for MlHeader { + fn is(magic: &[u8]) -> bool { + if magic.len() < 32 { + false + } else { + match MlHeader::view(&magic[0..32]) { + Ok(header) => header.magic[0..8] == *b"\0mlocate" && header.version == 0, + Err(_) => false, + } + } + } +}