libmspack

libmspack Documentation

# Introduction

libmspack is a library which provides compressors and decompressors, archivers and dearchivers for Microsoft compression formats.

# Formats supported

The following file formats are supported:

- SZDD files, which use LZSS compression
- KWAJ files, which use LZSS, LZSS+Huffman or deflate compression
- .HLP (MS Help) files, which use LZSS compression
- .CAB (MS Cabinet) files, which use deflate, LZX or Quantum compression
- .CHM (HTML Help) files, which use LZX compression
- .LIT (MS EBook) files, which use LZX compression and DES encryption
- .LZX (Exchange Offline Addressbook) files, which use LZX compression

To determine the capabilities of the library, and the binary compatibility version of any particular compressor or decompressor, use the mspack_version() function. The UNIX library interface version is defined as the highest-versioned library component.

# Getting started

The macro MSPACK_SYS_SELFTEST() should be used to ensure the library can be used. In particular, it checks if the caller is using 32-bit file I/O when the library is compiled for 64-bit file I/O and vice versa.

If compiled normally, the library includes basic file I/O and memory management functionality using the standard C library. This can be customised and replaced entirely by creating a mspack_system structure.

A compressor or decompressor for the required format must be instantiated before it can be used. Each construction function takes one parameter, which is either a pointer to a custom mspack_system structure, or NULL to use the default. The instantiation returned, if not NULL, contains function pointers (methods) to work with the given file format.

For compression:

- mspack_create_cab_compressor() creates a mscab_compressor
- mspack_create_chm_compressor() creates a mschm_compressor
- mspack_create_lit_compressor() creates a mslit_compressor
- mspack_create_hlp_compressor() creates a mshlp_compressor
- mspack_create_szdd_compressor() creates a msszdd_compressor
- mspack_create_kwaj_compressor() creates a mskwaj_compressor
- mspack_create_oab_compressor() creates a msoab_compressor

For decompression:

- mspack_create_cab_decompressor() creates a mscab_decompressor
- mspack_create_chm_decompressor() creates a mschm_decompressor
- mspack_create_lit_decompressor() creates a mslit_decompressor
- mspack_create_hlp_decompressor() creates a mshlp_decompressor
- mspack_create_szdd_decompressor() creates a msszdd_decompressor
- mspack_create_kwaj_decompressor() creates a mskwaj_decompressor
- mspack_create_oab_decompressor() creates a msoab_decompressor

Once finished working with a format, each kind of compressor/decompressor has its own specific destructor:

- mspack_destroy_cab_compressor()
- mspack_destroy_cab_decompressor()
- mspack_destroy_chm_compressor()
- mspack_destroy_chm_decompressor()
- mspack_destroy_lit_compressor()
- mspack_destroy_lit_decompressor()
- mspack_destroy_hlp_compressor()
- mspack_destroy_hlp_decompressor()
- mspack_destroy_szdd_compressor()
- mspack_destroy_szdd_decompressor()
- mspack_destroy_kwaj_compressor()
- mspack_destroy_kwaj_decompressor()
- mspack_destroy_oab_compressor()
- mspack_destroy_oab_decompressor()

Destroying a compressor or decompressor does not destroy any objects, structures or handles that have been created using that compressor or decompressor. Ensure that everything created or opened is destroyed or closed before compressor/decompressor is itself destroyed.

# Error codes

All compressors and decompressors use the same set of error codes. Most methods return an error code directly. For methods which do not return error codes directly, the error code can be obtained with the last_error() method.

- MSPACK_ERR_OK is used to indicate success. This error code is defined as zero, all other code are non-zero.
- MSPACK_ERR_ARGS indicates that a method was called with inappropriate arguments.
- MSPACK_ERR_OPEN indicates that mspack_system::open() failed.
- MSPACK_ERR_READ indicates that mspack_system::read() failed.
- MSPACK_ERR_WRITE indicates that mspack_system::write() failed.
- MSPACK_ERR_SEEK indicates that mspack_system::seek() failed.
- MSPACK_ERR_NOMEMORY indicates that mspack_system::alloc() failed.
- MSPACK_ERR_SIGNATURE indicates that the file being read does not have the correct "signature". It is probably not a valid file for whatever format is being read.
- MSPACK_ERR_DATAFORMAT indicates that the file being used or read is corrupt.
- MSPACK_ERR_CHECKSUM indicates that a data checksum has failed.
- MSPACK_ERR_CRUNCH indicates an error occured during compression.
- MSPACK_ERR_DECRUNCH indicates an error occured during decompression.

# Multi-threading

libmspack methods are reentrant and multithreading-safe when each thread has its own compressor or decompressor.

You should not call multiple methods simultaneously on a single compressor or decompressor instance.

If this may happen, you can either use one compressor or decompressor per thread, or you can use your preferred lock, semaphore or mutex library to ensure no more than one method on a compressor/decompressor is called simultaneously. libmspack will not do this locking for you.

Example of incorrect behaviour:

- thread 1 calls mspack_create_cab_decompressor()
- thread 1 calls open()
- thread 1 calls extract() for one file
- thread 2 simultaneously calls extract() for another file

Correct behaviour:

- thread 1 calls mspack_create_cab_decompressor()
- thread 2 calls mspack_create_cab_decompressor()
- thread 1 calls its own open() / extract()
- thread 2 simultaneously calls its own open() / extract()

Also correct behaviour:

- thread 1 calls mspack_create_cab_decompressor()
- thread 1 locks a mutex for with the decompressor before calling any methods on it, and unlocks the mutex after each method returns.
- thread 1 can share the results of open() with thread 2, and both can call extract(), provided they both guard against simultaneous use of extract(), and any other methods, with the mutex