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
//! 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](https://en.wikipedia.org/wiki/DEFLATE)) | Yes | //! | [Quantum](https://en.wikipedia.org/wiki/Quantum_compression)| No | //! | [LZX](https://en.wikipedia.org/wiki/LZX_(algorithm)) | No | //! //! # 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 internal::builder::{CabinetBuilder, CabinetWriter, FileBuilder, FileWriter, FolderBuilder}; pub use internal::cabinet::{Cabinet, FileEntries, FileEntry, FileReader, FolderEntries, FolderEntry}; pub use internal::ctype::CompressionType; // ========================================================================= //