1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
//! A library for reading/writing [Windows
//! cabinet](https://en.wikipedia.org/wiki/Cabinet_(file_format)) (CAB) files.
//!
//! # Overview
//!
//! CAB is an archive file format used by Windows. A cabinet file can contain
//! multiple compressed files, which are divided into "folders" (no relation to
//! filesystem folders/directories); files in the same folder are compressed
//! together, and each folder in the cabinet can potentially use a different
//! compression scheme. The CAB file format supports multiple different
//! compression schemes; this library can recognize all of them when reading
//! metadata for an existing cabinet file, but currently only supports
//! encoding/decoding some of them, as shown:
//!
//! | Compression | Supported |
//! |----------------------------|-------------------|
//! | Uncompressed | Yes |
//! | MSZIP ([Deflate][deflate]) | Yes |
//! | [Quantum][quantum] | No |
//! | [LZX][lzx] | Yes (decode only) |
//!
//! [deflate]: https://en.wikipedia.org/wiki/DEFLATE
//! [quantum]: https://en.wikipedia.org/wiki/Quantum_compression
//! [lzx]: https://en.wikipedia.org/wiki/LZX_(algorithm)
//!
//! # Example usage
//!
//! Use the `Cabinet` type to read an existing cabinet file:
//!
//! ```no_run
//! use cab;
//! use std::fs;
//! use std::io;
//!
//! let cab_file = fs::File::open("path/to/cabinet.cab").unwrap();
//! let mut cabinet = cab::Cabinet::new(cab_file).unwrap();
//! // List all files in the cabinet, with file sizes and compression types:
//! for folder in cabinet.folder_entries() {
//! for file in folder.file_entries() {
//! println!("File {} ({} B) is compressed with {:?}",
//! file.name(),
//! file.uncompressed_size(),
//! folder.compression_type());
//! }
//! }
//! // Decompress a particular file in the cabinet and save it to disk:
//! let mut reader = cabinet.read_file("images/example.png").unwrap();
//! let mut writer = fs::File::create("out/example.png").unwrap();
//! io::copy(&mut reader, &mut writer).unwrap();
//! ```
//!
//! Creating a new cabinet file is a little more involved. Because of how the
//! cabinet file is structured on disk, the library has to know the names of
//! all the files that will be in the cabinet up front, before it can start
//! writing anything to disk. However, we don't want to have to hold all the
//! file **contents** in memory at once. Therefore, cabinet creation happens
//! in two steps: first, create a `CabinetBuilder` and specify all filenames
//! and other metadata, and then second, stream each file's data into a
//! `CabinetWriter`, one at a time:
//!
//! ```no_run
//! use cab;
//! use std::fs;
//! use std::io;
//!
//! let mut cab_builder = cab::CabinetBuilder::new();
//! // Add a single file in its own folder:
//! cab_builder.add_folder(cab::CompressionType::None).add_file("img/foo.jpg");
//! // Add several more files, compressed together in a second folder:
//! {
//! let folder = cab_builder.add_folder(cab::CompressionType::MsZip);
//! folder.add_file("documents/README.txt");
//! folder.add_file("documents/license.txt");
//! // We can also specify metadata on individual files:
//! {
//! let file = folder.add_file("documents/hidden.txt");
//! file.set_is_hidden(true);
//! file.set_is_read_only(true);
//! }
//! }
//! // Now, we'll actually construct the cabinet file on disk:
//! let cab_file = fs::File::create("path/to/cabinet.cab").unwrap();
//! let mut cab_writer = cab_builder.build(cab_file).unwrap();
//! while let Some(mut writer) = cab_writer.next_file().unwrap() {
//! let mut reader = fs::File::open(writer.file_name()).unwrap();
//! io::copy(&mut reader, &mut writer).unwrap();
//! }
//! // Print the file size of the cabinet file we just created:
//! let mut cab_file = cab_writer.finish().unwrap();
//! println!("Cabinet size: {} B", cab_file.metadata().unwrap().len());
//! ```
#![warn(missing_docs)]
extern crate byteorder;
extern crate chrono;
extern crate flate2;
mod internal;
pub use crate::internal::builder::{
CabinetBuilder, CabinetWriter, FileBuilder, FileWriter, FolderBuilder,
};
pub use crate::internal::cabinet::{
Cabinet, FileEntries, FileEntry, FileReader, FolderEntries, FolderEntry,
};
pub use crate::internal::ctype::CompressionType;
// ========================================================================= //