### Use Cabarchive Command-Line Interface Source: https://context7.com/hughsie/python-cabarchive/llms.txt Provides examples of using the `cabarchive.cli` module for common operations like decompressing, creating, and profiling cabinet files directly from the command line. ```bash # Inspect and extract a cabinet file python -m cabarchive.cli --decompress --outdir ./extracted firmware.cab # Create a cabinet from local files python -m cabarchive.cli --create output.cab file1.bin file2.txt README.md # Profile parse + write performance on a large cabinet python -m cabarchive.cli --profile large.cab ``` -------------------------------- ### Get Uncompressed Data Size of Cabinet Archive Source: https://context7.com/hughsie/python-cabarchive/llms.txt Calculates and prints the total uncompressed size of all files within a cabinet archive. Requires reading the archive into memory first. ```python from cabarchive import CabArchive with open("large.cab", "rb") as f: arc = CabArchive(f.read()) print(f"Files : {len(arc)}") print(f"Total size : {arc.size} bytes ({arc.size / 1024 / 1024:.2f} MB)") # Files : 3 # Total size : 1572867 bytes (1.50 MB) ``` -------------------------------- ### CabArchive - Create or Open a Cabinet Archive Source: https://context7.com/hughsie/python-cabarchive/llms.txt Demonstrates how to initialize CabArchive to read existing archives from bytes or create new ones from scratch. It also shows how to access individual files within an archive. ```APIDOC ## CabArchive ### Description `CabArchive` inherits from `dict`. Keys are filename strings; values are `CabFile` instances. Pass raw `.cab` bytes to the constructor (or call `parse()`) to load an existing archive. Leave the constructor empty to start a new, blank archive. ### Usage ```python from cabarchive import CabArchive, CabFile, CorruptionError, NotSupportedError # --- Reading an existing .cab file --- with open("firmware.cab", "rb") as f: data = f.read() try: arc = CabArchive(data) except CorruptionError as e: print(f"Archive is corrupt: {e}") except NotSupportedError as e: print(f"Unsupported format: {e}") print(f"Files in archive: {list(arc.keys())}") # Access a file by name readme = arc["README.txt"] print(f"Name : {readme.filename}") print(f"Size : {len(readme.buf)} bytes") print(f"Year : {readme.date.year}") # --- Creating a new .cab file --- arc = CabArchive() arc["hello.txt"] = CabFile(b"Hello, world!") arc["data.bin"] = CabFile(b"\x00\x01\x02\x03") with open("output.cab", "wb") as f: f.write(arc.save()) ``` ``` -------------------------------- ### Create and Modify CabFile Entries Source: https://context7.com/hughsie/python-cabarchive/llms.txt Demonstrates constructing `CabFile` objects with raw bytes and metadata, including modification time and attributes. Shows how to add these entries to a `CabArchive` and save it. ```python import datetime from cabarchive import CabArchive, CabFile # Minimal construction — current date/time is used automatically simple = CabFile(b"Hello from cabarchive!") # Full construction with explicit metadata mtime = datetime.datetime(1997, 3, 12, 11, 13, 52) cff = CabFile(buf=b"#include \r\n", mtime=mtime) cff.is_arch = True # modified since last backup (common for source files) cff.is_readonly = False cff.is_hidden = False cff.is_system = False cff.is_exec = False arc = CabArchive() arc["source.c"] = cff # UTF-8 filenames are fully supported arc["tést.dat"] = CabFile("tést123".encode()) raw = arc.save() print(f"Archive bytes: {len(raw)}") # Read back and verify arc2 = CabArchive(raw) print(arc2["tést.dat"].filename) # tést.dat print(arc2["tést.dat"].buf) # b't\xc3\xa9st123' ``` -------------------------------- ### Read and Create CAB Archives with CabArchive Source: https://context7.com/hughsie/python-cabarchive/llms.txt Demonstrates reading an existing .cab file into a CabArchive object and creating a new archive from scratch. Includes error handling for corrupt or unsupported archives. ```python from cabarchive import CabArchive, CabFile, CorruptionError, NotSupportedError # --- Reading an existing .cab file --- with open("firmware.cab", "rb") as f: data = f.read() try: arc = CabArchive(data) except CorruptionError as e: print(f"Archive is corrupt: {e}") except NotSupportedError as e: print(f"Unsupported format: {e}") print(f"Files in archive: {list(arc.keys())}") # Files in archive: ['firmware.bin', 'README.txt'] # Access a file by name readme = arc["README.txt"] print(f"Name : {readme.filename}") # README.txt print(f"Size : {len(readme.buf)} bytes") # 23 bytes print(f"Year : {readme.date.year}") # e.g. 2024 # --- Creating a new .cab file --- arc = CabArchive() arc["hello.txt"] = CabFile(b"Hello, world!") arc["data.bin"] = CabFile(b"\x00\x01\x02\x03") with open("output.cab", "wb") as f: f.write(arc.save()) ``` -------------------------------- ### Serialise Archive to Bytes with CabArchive.save() Source: https://context7.com/hughsie/python-cabarchive/llms.txt Demonstrates serializing a CabArchive object into bytes, with options for MSZIP compression and alphabetical sorting of file entries. Shows how to write the resulting bytes to a file. ```python import datetime from cabarchive import CabArchive, CabFile arc = CabArchive() arc.set_id = 0x1234 # optional multi-cabinet set identifier fixed_time = datetime.datetime(2024, 1, 15, 10, 30, 0) arc["firmware.bin"] = CabFile(b"\xDE\xAD\xBE\xEF" * 256, mtime=fixed_time) arc["manifest.xml"] = CabFile(b"", mtime=fixed_time) # Uncompressed (default) raw_uncompressed = arc.save() print(f"Uncompressed size: {len(raw_uncompressed)} bytes") # MSZIP compressed raw_compressed = arc.save(compress=True) print(f"Compressed size: {len(raw_compressed)} bytes") # Disable alphabetical sorting to preserve insertion order raw_ordered = arc.save(compress=False, sort=False) with open("release.cab", "wb") as f: f.write(raw_compressed) ``` -------------------------------- ### Parse Raw Cabinet Bytes with CabArchive.parse() Source: https://context7.com/hughsie/python-cabarchive/llms.txt Shows how to parse raw .cab data into an existing CabArchive object, useful for data received from streams or after validation. Includes error handling for corrupt cabinets. ```python from cabarchive import CabArchive, CorruptionError arc = CabArchive() with open("archive.cab", "rb") as f: raw = f.read() try: arc.parse(raw) except CorruptionError as e: print(f"Corrupt cabinet: {e}") raise SystemExit(1) for filename, cab_file in arc.items(): print(f"{filename}: {len(cab_file.buf)} bytes, modified {cab_file.date}") # firmware.bin: 1048575 bytes, modified 2023-11-01 # meta.xml: 512 bytes, modified 2023-11-01 ``` -------------------------------- ### Locate One File by Glob Pattern with CabArchive.find_file() Source: https://context7.com/hughsie/python-cabarchive/llms.txt Illustrates how to find the first file in a CAB archive that matches a given Unix-style glob pattern. Useful when the exact filename is unknown. Shows how to access the found file's content. ```python from cabarchive import CabArchive with open("update.cab", "rb") as f: arc = CabArchive(f.read()) # Find the first .inf file anywhere in the archive inf_file = arc.find_file("*.inf") if inf_file: print(f"Found INF: {inf_file.filename}") print(inf_file.buf.decode("utf-8", errors="replace")) else: print("No .inf file found in archive") # Find a file in a subdirectory path driver = arc.find_file("drivers/*.sys") if driver: with open("extracted_driver.sys", "wb") as f: f.write(driver.buf) ``` -------------------------------- ### Extract Binary Files from Cabinet Archive Source: https://context7.com/hughsie/python-cabarchive/llms.txt Finds all files with a .bin extension and extracts their raw buffer content to a local directory. Also demonstrates finding DLL files within a specific subdirectory. ```python bin_files = arc.find_files("*.bin") print(f"Found {len(bin_files)} .bin files") for cab_file in bin_files: out_path = f"extracted/{cab_file.filename}" with open(out_path, "wb") as f: f.write(cab_file.buf) print(f" Wrote {len(cab_file.buf)} bytes → {out_path}") # Glob also works on path separators stored in archive filenames dlls = arc.find_files("system\*.dll") for cab_file in dlls: print(f" DLL: {cab_file.filename}") ``` -------------------------------- ### Locate Multiple Files by Glob Pattern with CabArchive.find_files() Source: https://context7.com/hughsie/python-cabarchive/llms.txt Demonstrates how to find all files within a CAB archive that match a given glob pattern. Returns a list of matching CabFile objects, or an empty list if no files match. ```python from cabarchive import CabArchive with open("bundle.cab", "rb") as f: arc = CabArchive(f.read()) ``` -------------------------------- ### Load Cabinet Archive with Flattened Paths Source: https://context7.com/hughsie/python-cabarchive/llms.txt Uses the `flattern=True` constructor option to strip directory components from filenames when loading an archive. Useful for archives with Windows-style paths. ```python from cabarchive import CabArchive with open("multi-folder.cab", "rb") as f: raw = f.read() # Normal load: filenames include directory components arc_normal = CabArchive(raw) print(list(arc_normal.keys())) # ['subdir\README.txt', 'subdir\firmware.bin'] # Flattern load: directory components are stripped arc_flat = CabArchive(raw, flattern=True) print(list(arc_flat.keys())) # ['README.txt', 'firmware.bin'] for filename, cab_file in arc_flat.items(): with open(filename, "wb") as f: f.write(cab_file.buf) print(f"Extracted: {filename}") ``` -------------------------------- ### Handle Cabarchive Errors Gracefully Source: https://context7.com/hughsie/python-cabarchive/llms.txt Demonstrates using a `safe_open_cab` function to catch `FileNotFoundError`, `CorruptionError`, and `NotSupportedError` when opening cabinet files. Also shows catching errors for invalid raw bytes. ```python from cabarchive import CabArchive from cabarchive.errors import CorruptionError, NotSupportedError def safe_open_cab(path: str) -> CabArchive | None: try: with open(path, "rb") as f: return CabArchive(f.read()) except FileNotFoundError: print(f"File not found: {path}") except CorruptionError as e: print(f"Corrupt cabinet '{path}': {e}") except NotSupportedError as e: # e.g. "Quantum compression not supported" # e.g. "LZX compression not supported" # e.g. "Chained cab file not supported" print(f"Unsupported cabinet '{path}': {e}") return None arc = safe_open_cab("firmware.cab") if arc: print(f"Loaded {len(arc)} file(s) successfully") # CorruptionError is also raised for corrupt raw bytes try: CabArchive(b"not a cab file at all") except (CorruptionError, NotSupportedError) as e: print(f"Expected error: {e}") # Expected error: Data is not application/vnd.ms-cab-compressed ``` -------------------------------- ### CabArchive Constructor with flatten Source: https://context7.com/hughsie/python-cabarchive/llms.txt The constructor's `flattern=True` option strips all directory components from filenames when loading, placing every file at the top level. ```APIDOC ## CabArchive Constructor - flatten Mode ### Description The constructor's `flattern=True` option strips all directory components from filenames when loading, placing every file at the top level. This is useful when extracting archives that use Windows-style backslash paths. ### Method `CabArchive(data: bytes, flattern: bool = False)` ### Parameters #### Path Parameters - **data** (bytes) - Required - The raw bytes of the cabinet file. - **flattern** (bool) - Optional - If True, strips directory components from filenames. ### Request Example ```python with open("multi-folder.cab", "rb") as f: raw = f.read() # Flattern load: directory components are stripped arc_flat = CabArchive(raw, flattern=True) ``` ``` -------------------------------- ### Error Handling Source: https://context7.com/hughsie/python-cabarchive/llms.txt `cabarchive` raises custom exceptions `CorruptionError` for structurally invalid files and `NotSupportedError` for unsupported cabinet features. ```APIDOC ## Error Handling ### Description `cabarchive` raises two custom exceptions. `CorruptionError` signals a structurally invalid or truncated file. `NotSupportedError` signals a valid cabinet that uses features the library does not implement (e.g., Quantum or LZX compression, chained cabinets, non-1.3 cabinet versions). ### Exceptions - **CorruptionError**: Raised for corrupt or truncated cabinet files. - **NotSupportedError**: Raised for cabinets using unsupported features. ### Example ```python from cabarchive import CabArchive from cabarchive.errors import CorruptionError, NotSupportedError def safe_open_cab(path: str) -> CabArchive | None: try: with open(path, "rb") as f: return CabArchive(f.read()) except FileNotFoundError: print(f"File not found: {path}") except CorruptionError as e: print(f"Corrupt cabinet '{path}': {e}") except NotSupportedError as e: print(f"Unsupported cabinet '{path}': {e}") return None # Example of catching expected errors try: CabArchive(b"not a cab file at all") except (CorruptionError, NotSupportedError) as e: print(f"Expected error: {e}") ``` ``` -------------------------------- ### CabArchive.parse() — Parse Raw Cabinet Bytes Source: https://context7.com/hughsie/python-cabarchive/llms.txt This method parses binary `.cab` data into an existing `CabArchive` object. It is useful when the archive data is loaded separately after the `CabArchive` instance has been created. ```APIDOC ## CabArchive.parse() ### Description Parses binary `.cab` data into the archive object. Useful when the `CabArchive` was constructed empty and the data arrives later (e.g. from a network stream or after validation). ### Usage ```python from cabarchive import CabArchive, CorruptionError arc = CabArchive() with open("archive.cab", "rb") as f: raw = f.read() try: arc.parse(raw) except CorruptionError as e: print(f"Corrupt cabinet: {e}") raise SystemExit(1) for filename, cab_file in arc.items(): print(f"{filename}: {len(cab_file.buf)} bytes, modified {cab_file.date}") ``` ``` -------------------------------- ### CabArchive.find_file() — Locate One File by Glob Pattern Source: https://context7.com/hughsie/python-cabarchive/llms.txt Searches the archive for a file matching a given Unix-style glob pattern and returns the first matching `CabFile` object, or `None` if no match is found. ```APIDOC ## CabArchive.find_file() ### Description Returns the first `CabFile` whose filename matches the given Unix-style glob, or `None` if no file matches. Useful when the exact filename is not known in advance. ### Usage ```python from cabarchive import CabArchive with open("update.cab", "rb") as f: arc = CabArchive(f.read()) # Find the first .inf file anywhere in the archive inf_file = arc.find_file("*.inf") if inf_file: print(f"Found INF: {inf_file.filename}") print(inf_file.buf.decode("utf-8", errors="replace")) else: print("No .inf file found in archive") # Find a file in a subdirectory path driver = arc.find_file("drivers/*.sys") if driver: with open("extracted_driver.sys", "wb") as f: f.write(driver.buf) ``` ``` -------------------------------- ### CabFile Source: https://context7.com/hughsie/python-cabarchive/llms.txt Represents a single archive entry, holding raw bytes and metadata. Attributes are writable, allowing for custom entry construction. ```APIDOC ## CabFile ### Description Represents a single archive entry, holding raw bytes and metadata (filename, modification timestamp, Win32 attributes). All attributes are writable, allowing entries to be constructed from scratch. ### Attributes - **buf** (bytes) - The raw bytes of the file. - **mtime** (datetime.datetime) - The modification timestamp. - **is_arch** (bool) - Modified since last backup. - **is_readonly** (bool) - Read-only flag. - **is_hidden** (bool) - Hidden flag. - **is_system** (bool) - System flag. - **is_exec** (bool) - Executable flag. ### Constructor `CabFile(buf: bytes, mtime: datetime.datetime = None, ...)` ### Example ```python import datetime from cabarchive import CabFile # Minimal construction simple = CabFile(b"Hello from cabarchive!") # Full construction mtime = datetime.datetime(1997, 3, 12, 11, 13, 52) cff = CabFile(buf=b"#include \r\n", mtime=mtime) cff.is_arch = True ``` ``` -------------------------------- ### CabArchive.find_files() — Locate Multiple Files by Glob Pattern Source: https://context7.com/hughsie/python-cabarchive/llms.txt Returns a list of all `CabFile` objects within the archive whose filenames match the provided glob pattern. An empty list is returned if no files match. ```APIDOC ## CabArchive.find_files() ### Description Returns a list of all `CabFile` instances whose filenames match the given glob. Returns an empty list when nothing matches. ### Usage ```python from cabarchive import CabArchive with open("bundle.cab", "rb") as f: arc = CabArchive(f.read()) # Example usage would follow here, but is not provided in the source text. ``` ``` -------------------------------- ### CabArchive.save() — Serialise Archive to Bytes Source: https://context7.com/hughsie/python-cabarchive/llms.txt Serializes the `CabArchive` object into a `bytes` object representing a valid `.cab` file. Supports optional MSZIP compression and control over file entry sorting. ```APIDOC ## CabArchive.save() ### Description Returns the complete cabinet file as a `bytes` object ready to be written to disk or sent over a network. Optionally applies MSZIP compression and controls whether file entries are sorted alphabetically. ### Usage ```python import datetime from cabarchive import CabArchive, CabFile arc = CabArchive() arc.set_id = 0x1234 # optional multi-cabinet set identifier fixed_time = datetime.datetime(2024, 1, 15, 10, 30, 0) arc["firmware.bin"] = CabFile(b"\xDE\xAD\xBE\xEF" * 256, mtime=fixed_time) arc["manifest.xml"] = CabFile(b"", mtime=fixed_time) # Uncompressed (default) raw_uncompressed = arc.save() print(f"Uncompressed size: {len(raw_uncompressed)} bytes") # MSZIP compressed raw_compressed = arc.save(compress=True) print(f"Compressed size: {len(raw_compressed)} bytes") # Disable alphabetical sorting to preserve insertion order raw_ordered = arc.save(compress=False, sort=False) with open("release.cab", "wb") as f: f.write(raw_compressed) ``` ``` -------------------------------- ### CabArchive.size Source: https://context7.com/hughsie/python-cabarchive/llms.txt A read-only integer property that returns the total uncompressed size (in bytes) of all files stored in the archive. ```APIDOC ## CabArchive.size ### Description A read-only integer property that returns the total uncompressed size (in bytes) of all files stored in the archive. ### Method `size` (property) ### Response #### Success Response (int) - Returns the total size in bytes. ``` -------------------------------- ### CabArchive.save Source: https://context7.com/hughsie/python-cabarchive/llms.txt Saves the current state of the CabArchive object into raw bytes, which can then be written to a file or further processed. ```APIDOC ## CabArchive.save ### Description Saves the current state of the CabArchive object into raw bytes, which can then be written to a file or further processed. ### Method `save() -> bytes` ### Response #### Success Response (bytes) - Returns the raw bytes of the cabinet archive. ``` -------------------------------- ### CabArchive.find_files Source: https://context7.com/hughsie/python-cabarchive/llms.txt Finds files within the archive that match a given glob pattern. It returns a list of CabFile objects representing the matching entries. ```APIDOC ## CabArchive.find_files ### Description Finds files within the archive that match a given glob pattern. It returns a list of CabFile objects representing the matching entries. ### Method `find_files(pattern: str)` ### Parameters #### Path Parameters - **pattern** (str) - Required - A glob pattern to match filenames against. ### Request Example ```python bin_files = arc.find_files("*.bin") ``` ### Response #### Success Response (List[CabFile]) - Returns a list of `CabFile` objects that match the provided pattern. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.