ewf_image/lib.rs
1//! Rust library for reading and writing Expert Witness Format forensic images.
2//!
3//! `ewf_image` provides direct Rust APIs for working with Expert Witness Format
4//! images. It can open physical, logical, SMART, and EWF2 segment families,
5//! expose metadata and stored hashes, read the logical media stream, walk
6//! logical single-file catalogs, and create EWF output. CLI and mount layers
7//! are not currently implemented.
8//!
9//! # Terminology
10//!
11//! Logical media size is the decoded byte length exposed by [`Image::media_size`]
12//! and [`ImageInfo::logical_size`]. Segment set size is the total byte length of
13//! the opened EWF container files, as reported by [`Image::segment_set_size`].
14//! Chunks are the stored allocation units used by EWF tables. Logical EWF
15//! images can also contain a single-file catalog, where each entry describes a
16//! file-like object stored inside the image.
17//!
18//! # Supported container families
19//!
20//! - EWF1 physical `.E01` / EVF images.
21//! - EWF1 logical `.L01` / LVF images.
22//! - EWF1 SMART `.S01` images.
23//! - EWF2 physical `.Ex01` images.
24//! - EWF2 logical `.Lx01` images.
25//!
26//! # Reading
27//!
28//! ```no_run
29//! use std::io::Read;
30//!
31//! fn main() -> ewf_image::Result<()> {
32//! let image = ewf_image::Image::open("case.E01")?;
33//! let info = image.info();
34//!
35//! println!("{:?}: {} bytes", info.format, info.logical_size);
36//! println!("segments: {}", image.number_of_segments());
37//!
38//! let mut sector = vec![0; 512];
39//! image.cursor().read_exact(&mut sector)?;
40//!
41//! let mut later_sector = vec![0; 512];
42//! image.read_at(&mut later_sector, 4096)?;
43//!
44//! Ok(())
45//! }
46//! ```
47//!
48//! # Metadata and hashes
49//!
50//! ```no_run
51//! fn main() -> ewf_image::Result<()> {
52//! let image = ewf_image::Image::open("case.E01")?;
53//!
54//! if let Some(case_number) = image.header_value("case_number") {
55//! println!("case: {case_number}");
56//! }
57//!
58//! if let Some(md5) = image.hash_value("MD5") {
59//! println!("stored MD5: {md5}");
60//! }
61//!
62//! #[cfg(feature = "verify")]
63//! {
64//! let verification = image.verify()?;
65//! println!("MD5 match: {:?}", verification.md5_match);
66//! println!("SHA1 match: {:?}", verification.sha1_match);
67//! }
68//!
69//! Ok(())
70//! }
71//! ```
72//!
73//! # Writing
74//!
75//! ```no_run
76//! use std::fs::File;
77//!
78//! fn main() -> ewf_image::Result<()> {
79//! let mut input = File::open("disk.raw")?;
80//!
81//! let mut options = ewf_image::WriteOptions::default();
82//! options.format = ewf_image::WriteFormat::Ewf2Physical;
83//! options.compression = ewf_image::WriteCompression::Zlib;
84//! options.metadata.set_header_value("case_number", "CASE-001");
85//!
86//! let mut writer = ewf_image::EwfWriter::create("case.Ex01", options)?;
87//! std::io::copy(&mut input, &mut writer)?;
88//! writer.finish()?;
89//!
90//! Ok(())
91//! }
92//! ```
93//!
94//! # Feature flags
95//!
96//! - `verify` is enabled by default and adds `Image::verify()` plus
97//! `VerifyResult` for streamed MD5/SHA1 verification. Stored hash parsing,
98//! EWF2 section integrity checks, and writer hash support are available
99//! without this feature.
100//! - `external-fixtures` enables ignored integration tests that require local
101//! EWF corpora and external EWF tools. It does not change library behavior.
102//!
103//! # Limitations
104//!
105//! Encrypted EWF2 images are detected and rejected, but decryption and
106//! encrypted writing are not implemented. Secondary/shadow target mirroring is
107//! supported by the file-backed writer. Base-plus-overlay delta/shadow images
108//! are not implemented.
109
110mod codepage;
111mod date_time;
112mod decode;
113mod error;
114mod format;
115mod image;
116mod index;
117mod metadata;
118mod segment;
119mod signature;
120mod single_files;
121mod types;
122#[cfg(feature = "verify")]
123mod verify;
124mod writer;
125
126pub use error::{EwfError, Result};
127pub use image::{Image, ImageCursor, SegmentReader, SingleFileCursor};
128pub use signature::{
129 check_file_corruption, check_file_encryption, check_file_signature,
130 check_segment_files_corruption, check_segment_files_encryption,
131};
132pub use single_files::SINGLE_FILE_PATH_SEPARATOR;
133pub use types::{
134 AcquisitionError, CompressionFlags, CompressionLevel, CompressionMethod, CompressionValues,
135 DataChunk, DataChunkEncoding, EncodedDataChunk, EwfMetadata, Format, FormatProfile,
136 HeaderCodepage, HeaderDateFormat, ImageInfo, MediaFlags, MediaInfo, MediaType, MemoryExtent,
137 OpenOptions, OpenStrictness, SectorRange, SegmentFileVersion, SingleFileAttribute,
138 SingleFileEntry, SingleFileEntryType, SingleFileExtent, SingleFilePermission,
139 SingleFilePermissionGroup, SingleFileSource, SingleFileSubject, SingleFilesAuxTables,
140 SingleFilesInfo, StoredHashes,
141};
142pub use writer::{
143 EwfWriter, WriteCompression, WriteCompressionLevel, WriteCompressionValues, WriteFormat,
144 WriteHashes, WriteMediaProfile, WriteOptions, WriteResult,
145};
146
147#[cfg(feature = "verify")]
148pub use types::VerifyResult;