Skip to main content

MagicDatabase

Struct MagicDatabase 

Source
#[non_exhaustive]
pub struct MagicDatabase { /* private fields */ }
Expand description

Main interface for magic rule database

Implementations§

Source§

impl MagicDatabase

Source

pub fn with_builtin_rules() -> Result<Self>

Create a database using built-in magic rules.

Loads magic rules that are compiled into the library binary at build time from src/builtin_rules.magic. These rules provide high-confidence detection for common file types including executables (ELF, PE/DOS), archives (ZIP, TAR, GZIP), images (JPEG, PNG, GIF, BMP), and documents (PDF).

§Security

This constructor uses EvaluationConfig::default(), which leaves timeout_ms unset (unbounded). When processing untrusted input (adversarial file buffers, large uploads, etc.), prefer MagicDatabase::with_builtin_rules_and_config with EvaluationConfig::performance() (which sets a 1-second timeout) or construct a config explicitly with a non-None timeout sized for your workload. The Default impl intentionally targets CLI one-shot usage rather than long-running services.

§Thread safety

MagicDatabase is Send + Sync and holds no interior mutability, so an Arc<MagicDatabase> can be shared across threads for parallel file scanning. A fresh evaluation context is constructed per evaluate_buffer / evaluate_file call, so concurrent calls do not interfere.

§Errors

Currently always returns Ok. In future implementations, this may return an error if the built-in rules fail to load or validate.

§Examples
use libmagic_rs::MagicDatabase;

let db = MagicDatabase::with_builtin_rules()?;
let result = db.evaluate_buffer(b"\x7fELF")?;
// Returns actual file type detection (e.g., "ELF")
Source

pub fn with_builtin_rules_and_config(config: EvaluationConfig) -> Result<Self>

Create database with built-in rules and custom configuration.

Loads built-in magic rules compiled at build time and applies the specified evaluation configuration (e.g., custom timeout settings).

§Security

For untrusted input (adversarial file buffers, web uploads, mail scanning), pass a config with an explicit timeout such as EvaluationConfig::performance(). The default config has timeout_ms = None which leaves evaluation unbounded; see the rationale on EvaluationConfig::default.

§Arguments
  • config - Custom evaluation configuration to use with the built-in rules
§Errors

Returns LibmagicError if the configuration is invalid (e.g., timeout is zero).

§Examples
use libmagic_rs::{MagicDatabase, EvaluationConfig};

// Prefer the performance() preset over default() when processing
// untrusted input. default() has no timeout by design.
let config = EvaluationConfig::performance();
let db = MagicDatabase::with_builtin_rules_and_config(config)?;
Source

pub fn load_from_file<P: AsRef<Path>>(path: P) -> Result<Self>

Load magic rules from a file

§Security

This constructor uses EvaluationConfig::default(), which leaves timeout_ms unset. See the security note on Self::with_builtin_rules for the implications and prefer Self::load_from_file_with_config with an explicit timeout when processing untrusted input.

§Arguments
  • path - Path to the magic file to load
§Errors

Returns LibmagicError::IoError if the file cannot be read. Returns LibmagicError::ParseError if the magic file format is invalid.

§Examples
use libmagic_rs::MagicDatabase;

let db = MagicDatabase::load_from_file("magic.db")?;
Source

pub fn load_from_file_with_config<P: AsRef<Path>>( path: P, config: EvaluationConfig, ) -> Result<Self>

Load from file with custom config (e.g., timeout).

§Security

For untrusted input, pass EvaluationConfig::performance() or a config with an explicit non-None timeout_ms. See Self::with_builtin_rules for the full rationale.

§Errors

Returns error if file cannot be read, parsed, or config is invalid

Source

pub fn load_from_bytes(bytes: Vec<u8>) -> Result<Self>

Load text magic rules from owned bytes.

This consumes the supplied Vec<u8> and reuses its allocation when the input is valid UTF-8, avoiding the additional full-buffer copy made when loading already-buffered data through Self::load_from_reader. Invalid UTF-8 is replaced as documented for file and reader loading and may require another allocation. Input is bounded by the same 1 GiB limit as Self::load_from_file. Compiled binary .mgc databases are not supported.

Databases loaded from bytes have no filesystem source, so Self::source_path returns None.

§Parsing behavior

Parsing is tolerant, matching Self::load_from_file: a rule line that fails to parse is skipped along with its indented subtree, and a warning is logged rather than returned. Input in which every line fails to parse therefore yields an Ok database with no rules, not an error.

§Security

This constructor uses EvaluationConfig::default(), which leaves timeout_ms unset. See the security note on Self::with_builtin_rules and prefer Self::load_from_bytes_with_config with an explicit timeout when processing untrusted input.

§Errors

Returns LibmagicError::ParseError if the input is oversized, compiled .mgc data, or cannot be parsed as a text magic database.

§Examples
use libmagic_rs::MagicDatabase;

let rules = b"0 string INKMEM in-memory magic\n".to_vec();
let db = MagicDatabase::load_from_bytes(rules)?;
let result = db.evaluate_buffer(b"INKMEM payload")?;
assert!(result.description.contains("in-memory magic"));
Source

pub fn load_from_bytes_with_config( bytes: Vec<u8>, config: EvaluationConfig, ) -> Result<Self>

Load text magic rules from owned bytes with custom evaluation config.

See Self::load_from_bytes for ownership, size limits, and source-path behavior.

§Security

For untrusted input, pass EvaluationConfig::performance() or a config with an explicit non-None timeout_ms.

§Errors

Returns an error if the config is invalid or the input is oversized, compiled .mgc data, or cannot be parsed as a text magic database.

§Examples
use libmagic_rs::{EvaluationConfig, MagicDatabase};

let rules = b"0 string INKMEM in-memory magic\n".to_vec();
let config = EvaluationConfig::performance();
let db = MagicDatabase::load_from_bytes_with_config(rules, config)?;
let result = db.evaluate_buffer(b"INKMEM payload")?;
assert!(result.description.contains("in-memory magic"));
Source

pub fn load_from_reader<R: Read>(reader: R) -> Result<Self>

Load text magic rules from a reader.

This accepts any Read implementation, including byte slices, std::io::Cursor, files, and buffered readers. Input is bounded by the same 1 GiB limit as Self::load_from_file. Compiled binary .mgc databases are not supported.

Databases loaded from a reader have no filesystem source, so Self::source_path returns None.

§Parsing behavior

Parsing is tolerant, matching Self::load_from_file: a rule line that fails to parse is skipped along with its indented subtree, and a warning is logged rather than returned. Input in which every line fails to parse therefore yields an Ok database with no rules, not an error.

The reader is drained until it reports end of input. A stream that ends early – a reset socket, a truncated pipe – is indistinguishable from a short magic database, so it loads successfully with only the rules that arrived. Callers that need completeness guarantees must enforce them on the stream before calling this method.

§Security

This constructor uses EvaluationConfig::default(), which leaves timeout_ms unset. See the security note on Self::with_builtin_rules and prefer Self::load_from_reader_with_config with an explicit timeout when processing untrusted input.

Note that timeout_ms bounds rule evaluation, not this read. The reader is capped in size, but not in time: a reader that blocks or trickles bytes without reaching end of input stalls this call. Apply your own read timeout or deadline before passing in a stream you do not control.

§Errors

Returns LibmagicError::IoError if the reader fails, or LibmagicError::ParseError if the input is oversized, compiled .mgc data, or cannot be parsed as a text magic database.

§Examples
use libmagic_rs::MagicDatabase;

let rules = b"0 string INKMEM in-memory magic\n";
let db = MagicDatabase::load_from_reader(rules.as_slice())?;
let result = db.evaluate_buffer(b"INKMEM payload")?;
assert!(result.description.contains("in-memory magic"));
Source

pub fn load_from_reader_with_config<R: Read>( reader: R, config: EvaluationConfig, ) -> Result<Self>

Load text magic rules from a reader with custom evaluation config.

See Self::load_from_reader for supported inputs, size limits, and source-path behavior.

§Security

For untrusted input, pass EvaluationConfig::performance() or a config with an explicit non-None timeout_ms.

§Errors

Returns an error if the config is invalid, the reader fails, or the input is oversized, compiled .mgc data, or cannot be parsed as a text magic database.

§Examples
use libmagic_rs::{EvaluationConfig, MagicDatabase};

let rules = b"0 string INKMEM in-memory magic\n";
let config = EvaluationConfig::performance();
let db = MagicDatabase::load_from_reader_with_config(rules.as_slice(), config)?;
let result = db.evaluate_buffer(b"INKMEM payload")?;
assert!(result.description.contains("in-memory magic"));
Source

pub fn evaluate_file<P: AsRef<Path>>(&self, path: P) -> Result<EvaluationResult>

Evaluate magic rules against a file

§Arguments
  • path - Path to the file to evaluate
§Errors

Returns LibmagicError::IoError if the file cannot be accessed. Returns LibmagicError::EvaluationError if rule evaluation fails.

§Security

This method has a time-of-check/time-of-use (TOCTOU) window between resolving the path and memory-mapping the file (CWE-367). Internally, evaluate_file first calls std::fs::metadata(path) to detect the empty-file case, then opens and memory-maps the file via io::FileBuffer::new, which itself re-validates file metadata (regular file, size bounds) before calling create_memory_mapping. Between these validation steps and the final mmap call, the path may be swapped (for example, via a symlink replacement or rename) by another process. The content that gets mapped may therefore differ from the file that passed validation.

The I/O layer mitigates the common shapes of this attack by canonicalizing the path and rejecting special file types, and the mapping itself is read-only, so a successful exploit cannot corrupt the victim file. The residual risk is that evaluate_file may classify a different file than the caller intended.

For adversarial or untrusted environments, prefer MagicDatabase::evaluate_buffer: load the bytes yourself using whatever resource-bounded, TOCTOU-aware I/O strategy your application requires (e.g., openat with O_NOFOLLOW, holding an open file descriptor across validation and read), then pass the in-memory slice directly to evaluate_buffer. See the security assurance case for the residual-risk discussion.

§Examples
use libmagic_rs::MagicDatabase;

let db = MagicDatabase::load_from_file("magic.db")?;
let result = db.evaluate_file("sample.bin")?;
println!("File type: {}", result.description);
Source

pub fn evaluate_buffer(&self, buffer: &[u8]) -> Result<EvaluationResult>

Evaluate magic rules against an in-memory buffer

This method evaluates a byte buffer directly without reading from disk, which is useful for stdin input or pre-loaded data.

§Arguments
  • buffer - Byte buffer to evaluate
§Errors

Returns LibmagicError::EvaluationError if rule evaluation fails.

§Examples
use libmagic_rs::MagicDatabase;

let db = MagicDatabase::load_from_file("/usr/share/misc/magic")?;
let buffer = b"test data";
let result = db.evaluate_buffer(buffer)?;
println!("Buffer type: {}", result.description);
Source

pub fn config(&self) -> &EvaluationConfig

Returns the evaluation configuration used by this database.

This provides read-only access to the evaluation configuration for callers that need to inspect resource limits or evaluation options.

Source

pub fn source_path(&self) -> Option<&Path>

Returns the path from which magic rules were loaded.

This method returns the source path that was used to load the magic rules into this database. It is useful for debugging, logging, and tracking the origin of magic rules.

§Returns
  • Some(&Path) - If the database was loaded from a file or directory using load_from_file()
  • None - If the database was constructed programmatically or the source path was not recorded
§Examples
use libmagic_rs::MagicDatabase;

let db = MagicDatabase::load_from_file("/usr/share/misc/magic")?;
if let Some(path) = db.source_path() {
    println!("Rules loaded from: {}", path.display());
}

Trait Implementations§

Source§

impl Debug for MagicDatabase

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.