7 releases (breaking)

0.6.0 Apr 5, 2024
0.5.0 Nov 24, 2023
0.4.1 Jun 20, 2022
0.4.0 May 4, 2022
0.1.0 Feb 20, 2018

#13 in #archive

Download history 4300/week @ 2023-12-23 6082/week @ 2023-12-30 6860/week @ 2024-01-06 7834/week @ 2024-01-13 8290/week @ 2024-01-20 7964/week @ 2024-01-27 8328/week @ 2024-02-03 6838/week @ 2024-02-10 8665/week @ 2024-02-17 18680/week @ 2024-02-24 25922/week @ 2024-03-02 55462/week @ 2024-03-09 51515/week @ 2024-03-16 12329/week @ 2024-03-23 10875/week @ 2024-03-30 7697/week @ 2024-04-06

86,016 downloads per month
Used in 29 crates (9 directly)

MIT license

94KB
2K SLoC

rust-cab

Build Status Crates.io Documentation

A pure Rust library for reading/writing Windows cabinet (CAB) files.

Documentation: https://docs.rs/cab

License

rust-cab is made available under the MIT License.


lib.rs:

A library for reading/writing Windows cabinet (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) Yes
Quantum No
LZX Yes (decode only)

Example usage

Use the Cabinet type to read an existing cabinet file:

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:

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());

Dependencies

~1.5MB
~24K SLoC