1 /* libmspack -- a library for working with Microsoft compression formats.
2  * (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
3  *
4  * libmspack is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU Lesser General Public License (LGPL) version 2.1
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU Lesser General Public License for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15  */
16 
17 /** \mainpage
18  *
19  * \section intro Introduction
20  *
21  * libmspack is a library which provides compressors and decompressors,
22  * archivers and dearchivers for Microsoft compression formats.
23  *
24  * \section formats Formats supported
25  *
26  * The following file formats are supported:
27  * - SZDD files, which use LZSS compression
28  * - KWAJ files, which use LZSS, LZSS+Huffman or deflate compression
29  * - .HLP (MS Help) files, which use LZSS compression
30  * - .CAB (MS Cabinet) files, which use deflate, LZX or Quantum compression
31  * - .CHM (HTML Help) files, which use LZX compression
32  * - .LIT (MS EBook) files, which use LZX compression and DES encryption
33  * - .LZX (Exchange Offline Addressbook) files, which use LZX compression
34  *
35  * To determine the capabilities of the library, and the binary
36  * compatibility version of any particular compressor or decompressor, use
37  * the mspack_version() function. The UNIX library interface version is
38  * defined as the highest-versioned library component.
39  *
40  * \section starting Getting started
41  *
42  * The macro MSPACK_SYS_SELFTEST() should be used to ensure the library can
43  * be used. In particular, it checks if the caller is using 32-bit file I/O
44  * when the library is compiled for 64-bit file I/O and vice versa.
45  *
46  * If compiled normally, the library includes basic file I/O and memory
47  * management functionality using the standard C library. This can be
48  * customised and replaced entirely by creating a mspack_system structure.
49  *
50  * A compressor or decompressor for the required format must be
51  * instantiated before it can be used. Each construction function takes
52  * one parameter, which is either a pointer to a custom mspack_system
53  * structure, or NULL to use the default. The instantiation returned, if
54  * not NULL, contains function pointers (methods) to work with the given
55  * file format.
56  *
57  * For compression:
58  * - mspack_create_cab_compressor() creates a mscab_compressor
59  * - mspack_create_chm_compressor() creates a mschm_compressor
60  * - mspack_create_lit_compressor() creates a mslit_compressor
61  * - mspack_create_hlp_compressor() creates a mshlp_compressor
62  * - mspack_create_szdd_compressor() creates a msszdd_compressor
63  * - mspack_create_kwaj_compressor() creates a mskwaj_compressor
64  * - mspack_create_oab_compressor() creates a msoab_compressor
65  *
66  * For decompression:
67  * - mspack_create_cab_decompressor() creates a mscab_decompressor
68  * - mspack_create_chm_decompressor() creates a mschm_decompressor
69  * - mspack_create_lit_decompressor() creates a mslit_decompressor
70  * - mspack_create_hlp_decompressor() creates a mshlp_decompressor
71  * - mspack_create_szdd_decompressor() creates a msszdd_decompressor
72  * - mspack_create_kwaj_decompressor() creates a mskwaj_decompressor
73  * - mspack_create_oab_decompressor() creates a msoab_decompressor
74  *
75  * Once finished working with a format, each kind of
76  * compressor/decompressor has its own specific destructor:
77  * - mspack_destroy_cab_compressor()
78  * - mspack_destroy_cab_decompressor()
79  * - mspack_destroy_chm_compressor()
80  * - mspack_destroy_chm_decompressor()
81  * - mspack_destroy_lit_compressor()
82  * - mspack_destroy_lit_decompressor()
83  * - mspack_destroy_hlp_compressor()
84  * - mspack_destroy_hlp_decompressor()
85  * - mspack_destroy_szdd_compressor()
86  * - mspack_destroy_szdd_decompressor()
87  * - mspack_destroy_kwaj_compressor()
88  * - mspack_destroy_kwaj_decompressor()
89  * - mspack_destroy_oab_compressor()
90  * - mspack_destroy_oab_decompressor()
91  *
92  * Destroying a compressor or decompressor does not destroy any objects,
93  * structures or handles that have been created using that compressor or
94  * decompressor. Ensure that everything created or opened is destroyed or
95  * closed before compressor/decompressor is itself destroyed.
96  *
97  * \section errors Error codes
98  *
99  * All compressors and decompressors use the same set of error codes. Most
100  * methods return an error code directly. For methods which do not
101  * return error codes directly, the error code can be obtained with the
102  * last_error() method.
103  *
104  * - #MSPACK_ERR_OK is used to indicate success. This error code is defined
105  *   as zero, all other code are non-zero.
106  * - #MSPACK_ERR_ARGS indicates that a method was called with inappropriate
107  *   arguments.
108  * - #MSPACK_ERR_OPEN indicates that mspack_system::open() failed.
109  * - #MSPACK_ERR_READ indicates that mspack_system::read() failed.
110  * - #MSPACK_ERR_WRITE indicates that mspack_system::write() failed.
111  * - #MSPACK_ERR_SEEK indicates that mspack_system::seek() failed.
112  * - #MSPACK_ERR_NOMEMORY indicates that mspack_system::alloc() failed.
113  * - #MSPACK_ERR_SIGNATURE indicates that the file being read does not
114  *   have the correct "signature". It is probably not a valid file for
115  *   whatever format is being read.
116  * - #MSPACK_ERR_DATAFORMAT indicates that the file being used or read
117  *   is corrupt.
118  * - #MSPACK_ERR_CHECKSUM indicates that a data checksum has failed.
119  * - #MSPACK_ERR_CRUNCH indicates an error occured during compression.
120  * - #MSPACK_ERR_DECRUNCH indicates an error occured during decompression.
121  *
122  * \section threading Multi-threading
123  *
124  * libmspack methods are reentrant and multithreading-safe when each
125  * thread has its own compressor or decompressor.
126 
127  * You should not call multiple methods simultaneously on a single
128  * compressor or decompressor instance.
129  *
130  * If this may happen, you can either use one compressor or
131  * decompressor per thread, or you can use your preferred lock,
132  * semaphore or mutex library to ensure no more than one method on a
133  * compressor/decompressor is called simultaneously. libmspack will
134  * not do this locking for you.
135  *
136  * Example of incorrect behaviour:
137  * - thread 1 calls mspack_create_cab_decompressor()
138  * - thread 1 calls open()
139  * - thread 1 calls extract() for one file
140  * - thread 2 simultaneously calls extract() for another file
141  *
142  * Correct behaviour:
143  * - thread 1 calls mspack_create_cab_decompressor()
144  * - thread 2 calls mspack_create_cab_decompressor()
145  * - thread 1 calls its own open() / extract()
146  * - thread 2 simultaneously calls its own open() / extract()
147  *
148  * Also correct behaviour:
149  * - thread 1 calls mspack_create_cab_decompressor()
150  * - thread 1 locks a mutex for with the decompressor before
151  *   calling any methods on it, and unlocks the mutex after each
152  *   method returns.
153  * - thread 1 can share the results of open() with thread 2, and both
154  *   can call extract(), provided they both guard against simultaneous
155  *   use of extract(), and any other methods, with the mutex
156  */
157 
158 #ifndef LIB_MSPACK_H
159 #define LIB_MSPACK_H 1
160 
161 #ifdef __cplusplus
162 extern "C" {
163 #endif
164 
165 #include <sys/types.h>
166 #include <stdlib.h>
167 
168 /**
169  * System self-test function, to ensure both library and calling program
170  * can use one another.
171  *
172  * A result of MSPACK_ERR_OK means the library and caller are
173  * compatible. Any other result indicates that the library and caller are
174  * not compatible and should not be used. In particular, a value of
175  * MSPACK_ERR_SEEK means the library and caller use different off_t
176  * datatypes.
177  *
178  * It should be used like so:
179  *
180  * @code
181  * int selftest_result;
182  * MSPACK_SYS_SELFTEST(selftest_result);
183  * if (selftest_result != MSPACK_ERR_OK) {
184  *   fprintf(stderr, "incompatible with this build of libmspack\n");
185  *   exit(0);
186  * }
187  * @endcode
188  *
189  * @param  result   an int variable to store the result of the self-test
190  */
191 #define MSPACK_SYS_SELFTEST(result)  do { \
192   (result) = mspack_sys_selftest_internal(sizeof(off_t)); \
193 } while (0)
194 
195 /** Part of the MSPACK_SYS_SELFTEST() macro, must not be used directly. */
196 extern int mspack_sys_selftest_internal(int);
197 
198 /**
199  * Enquire about the binary compatibility version of a specific interface in
200  * the library. Currently, the following interfaces are defined:
201  *
202  * - #MSPACK_VER_LIBRARY: the overall library
203  * - #MSPACK_VER_SYSTEM: the mspack_system interface
204  * - #MSPACK_VER_MSCABD: the mscab_decompressor interface
205  * - #MSPACK_VER_MSCABC: the mscab_compressor interface
206  * - #MSPACK_VER_MSCHMD: the mschm_decompressor interface
207  * - #MSPACK_VER_MSCHMC: the mschm_compressor interface
208  * - #MSPACK_VER_MSLITD: the mslit_decompressor interface
209  * - #MSPACK_VER_MSLITC: the mslit_compressor interface
210  * - #MSPACK_VER_MSHLPD: the mshlp_decompressor interface
211  * - #MSPACK_VER_MSHLPC: the mshlp_compressor interface
212  * - #MSPACK_VER_MSSZDDD: the msszdd_decompressor interface
213  * - #MSPACK_VER_MSSZDDC: the msszdd_compressor interface
214  * - #MSPACK_VER_MSKWAJD: the mskwaj_decompressor interface
215  * - #MSPACK_VER_MSKWAJC: the mskwaj_compressor interface
216  * - #MSPACK_VER_MSOABD: the msoab_decompressor interface
217  * - #MSPACK_VER_MSOABC: the msoab_compressor interface
218  *
219  * The result of the function should be interpreted as follows:
220  * - -1: this interface is completely unknown to the library
221  * - 0: this interface is known, but non-functioning
222  * - 1: this interface has all basic functionality
223  * - 2, 3, ...: this interface has additional functionality, clearly marked
224  *   in the documentation as "version 2", "version 3" and so on.
225  *
226  * @param entity the interface to request current version of
227  * @return the version of the requested interface
228  */
229 extern int mspack_version(int entity);
230 
231 /** Pass to mspack_version() to get the overall library version */
232 #define MSPACK_VER_LIBRARY   (0)
233 /** Pass to mspack_version() to get the mspack_system version */
234 #define MSPACK_VER_SYSTEM    (1)
235 /** Pass to mspack_version() to get the mscab_decompressor version */
236 #define MSPACK_VER_MSCABD    (2)
237 /** Pass to mspack_version() to get the mscab_compressor version */
238 #define MSPACK_VER_MSCABC    (3)
239 /** Pass to mspack_version() to get the mschm_decompressor version */
240 #define MSPACK_VER_MSCHMD    (4)
241 /** Pass to mspack_version() to get the mschm_compressor version */
242 #define MSPACK_VER_MSCHMC    (5)
243 /** Pass to mspack_version() to get the mslit_decompressor version */
244 #define MSPACK_VER_MSLITD    (6)
245 /** Pass to mspack_version() to get the mslit_compressor version */
246 #define MSPACK_VER_MSLITC    (7)
247 /** Pass to mspack_version() to get the mshlp_decompressor version */
248 #define MSPACK_VER_MSHLPD    (8)
249 /** Pass to mspack_version() to get the mshlp_compressor version */
250 #define MSPACK_VER_MSHLPC    (9)
251 /** Pass to mspack_version() to get the msszdd_decompressor version */
252 #define MSPACK_VER_MSSZDDD   (10)
253 /** Pass to mspack_version() to get the msszdd_compressor version */
254 #define MSPACK_VER_MSSZDDC   (11)
255 /** Pass to mspack_version() to get the mskwaj_decompressor version */
256 #define MSPACK_VER_MSKWAJD   (12)
257 /** Pass to mspack_version() to get the mskwaj_compressor version */
258 #define MSPACK_VER_MSKWAJC   (13)
259 /** Pass to mspack_version() to get the msoab_decompressor version */
260 #define MSPACK_VER_MSOABD    (14)
261 /** Pass to mspack_version() to get the msoab_compressor version */
262 #define MSPACK_VER_MSOABC    (15)
263 
264 /* --- file I/O abstraction ------------------------------------------------ */
265 
266 /**
267  * A structure which abstracts file I/O and memory management.
268  *
269  * The library always uses the mspack_system structure for interaction
270  * with the file system and to allocate, free and copy all memory. It also
271  * uses it to send literal messages to the library user.
272  *
273  * When the library is compiled normally, passing NULL to a compressor or
274  * decompressor constructor will result in a default mspack_system being
275  * used, where all methods are implemented with the standard C library.
276  * However, all constructors support being given a custom created
277  * mspack_system structure, with the library user's own methods. This
278  * allows for more abstract interaction, such as reading and writing files
279  * directly to memory, or from a network socket or pipe.
280  *
281  * Implementors of an mspack_system structure should read all
282  * documentation entries for every structure member, and write methods
283  * which conform to those standards.
284  */
285 struct mspack_system {
286   /**
287    * Opens a file for reading, writing, appending or updating.
288    *
289    * @param self     a self-referential pointer to the mspack_system
290    *                 structure whose open() method is being called. If
291    *                 this pointer is required by close(), read(), write(),
292    *                 seek() or tell(), it should be stored in the result
293    *                 structure at this time.
294    * @param filename the file to be opened. It is passed directly from the
295    *                 library caller without being modified, so it is up to
296    *                 the caller what this parameter actually represents.
297    * @param mode     one of #MSPACK_SYS_OPEN_READ (open an existing file
298    *                 for reading), #MSPACK_SYS_OPEN_WRITE (open a new file
299    *                 for writing), #MSPACK_SYS_OPEN_UPDATE (open an existing
300    *                 file for reading/writing from the start of the file) or
301    *                 #MSPACK_SYS_OPEN_APPEND (open an existing file for
302    *                 reading/writing from the end of the file)
303    * @return a pointer to a mspack_file structure. This structure officially
304    *         contains no members, its true contents are up to the
305    *         mspack_system implementor. It should contain whatever is needed
306    *         for other mspack_system methods to operate. Returning the NULL
307    *         pointer indicates an error condition.
308    * @see close(), read(), write(), seek(), tell(), message()
309    */
310   struct mspack_file * (*open)(struct mspack_system *self,
311                                const char *filename,
312                                int mode);
313 
314   /**
315    * Closes a previously opened file. If any memory was allocated for this
316    * particular file handle, it should be freed at this time.
317    *
318    * @param file the file to close
319    * @see open()
320    */
321   void (*close)(struct mspack_file *file);
322 
323   /**
324    * Reads a given number of bytes from an open file.
325    *
326    * @param file    the file to read from
327    * @param buffer  the location where the read bytes should be stored
328    * @param bytes   the number of bytes to read from the file.
329    * @return the number of bytes successfully read (this can be less than
330    *         the number requested), zero to mark the end of file, or less
331    *         than zero to indicate an error. The library does not "retry"
332    *         reads and assumes short reads are due to EOF, so you should
333    *         avoid returning short reads because of transient errors.
334    * @see open(), write()
335    */
336   int (*read)(struct mspack_file *file,
337               void *buffer,
338               int bytes);
339 
340   /**
341    * Writes a given number of bytes to an open file.
342    *
343    * @param file    the file to write to
344    * @param buffer  the location where the written bytes should be read from
345    * @param bytes   the number of bytes to write to the file.
346    * @return the number of bytes successfully written, this can be less
347    *         than the number requested. Zero or less can indicate an error
348    *         where no bytes at all could be written. All cases where less
349    *         bytes were written than requested are considered by the library
350    *         to be an error.
351    * @see open(), read()
352    */
353   int (*write)(struct mspack_file *file,
354                void *buffer,
355                int bytes);
356 
357   /**
358    * Seeks to a specific file offset within an open file.
359    *
360    * Sometimes the library needs to know the length of a file. It does
361    * this by seeking to the end of the file with seek(file, 0,
362    * MSPACK_SYS_SEEK_END), then calling tell(). Implementations may want
363    * to make a special case for this.
364    *
365    * Due to the potentially varying 32/64 bit datatype off_t on some
366    * architectures, the #MSPACK_SYS_SELFTEST macro MUST be used before
367    * using the library. If not, the error caused by the library passing an
368    * inappropriate stackframe to seek() is subtle and hard to trace.
369    *
370    * @param file   the file to be seeked
371    * @param offset an offset to seek, measured in bytes
372    * @param mode   one of #MSPACK_SYS_SEEK_START (the offset should be
373    *               measured from the start of the file), #MSPACK_SYS_SEEK_CUR
374    *               (the offset should be measured from the current file offset)
375    *               or #MSPACK_SYS_SEEK_END (the offset should be measured from
376    *               the end of the file)
377    * @return zero for success, non-zero for an error
378    * @see open(), tell()
379    */
380   int (*seek)(struct mspack_file *file,
381               off_t offset,
382               int mode);
383 
384   /**
385    * Returns the current file position (in bytes) of the given file.
386    *
387    * @param file the file whose file position is wanted
388    * @return the current file position of the file
389    * @see open(), seek()
390    */
391   off_t (*tell)(struct mspack_file *file);
392 
393   /**
394    * Used to send messages from the library to the user.
395    *
396    * Occasionally, the library generates warnings or other messages in
397    * plain english to inform the human user. These are informational only
398    * and can be ignored if not wanted.
399    *
400    * @param file   may be a file handle returned from open() if this message
401    *               pertains to a specific open file, or NULL if not related to
402    *               a specific file.
403    * @param format a printf() style format string. It does NOT include a
404    *               trailing newline.
405    * @see open()
406    */
407   void (*message)(struct mspack_file *file,
408                   const char *format,
409                   ...);
410 
411   /**
412    * Allocates memory.
413    *
414    * @param self     a self-referential pointer to the mspack_system
415    *                 structure whose alloc() method is being called.
416    * @param bytes    the number of bytes to allocate
417    * @result a pointer to the requested number of bytes, or NULL if
418    *         not enough memory is available
419    * @see free()
420    */
421   void * (*alloc)(struct mspack_system *self,
422                   size_t bytes);
423 
424   /**
425    * Frees memory.
426    *
427    * @param ptr the memory to be freed. NULL is accepted and ignored.
428    * @see alloc()
429    */
430   void (*free)(void *ptr);
431 
432   /**
433    * Copies from one region of memory to another.
434    *
435    * The regions of memory are guaranteed not to overlap, are usually less
436    * than 256 bytes, and may not be aligned. Please note that the source
437    * parameter comes before the destination parameter, unlike the standard
438    * C function memcpy().
439    *
440    * @param src   the region of memory to copy from
441    * @param dest  the region of memory to copy to
442    * @param bytes the size of the memory region, in bytes
443    */
444   void (*copy)(void *src,
445                void *dest,
446                size_t bytes);
447 
448   /**
449    * A null pointer to mark the end of mspack_system. It must equal NULL.
450    *
451    * Should the mspack_system structure extend in the future, this NULL
452    * will be seen, rather than have an invalid method pointer called.
453    */
454   void *null_ptr;
455 };
456 
457 /** mspack_system::open() mode: open existing file for reading. */
458 #define MSPACK_SYS_OPEN_READ   (0)
459 /** mspack_system::open() mode: open new file for writing */
460 #define MSPACK_SYS_OPEN_WRITE  (1)
461 /** mspack_system::open() mode: open existing file for writing */
462 #define MSPACK_SYS_OPEN_UPDATE (2)
463 /** mspack_system::open() mode: open existing file for writing */
464 #define MSPACK_SYS_OPEN_APPEND (3)
465 
466 /** mspack_system::seek() mode: seek relative to start of file */
467 #define MSPACK_SYS_SEEK_START  (0)
468 /** mspack_system::seek() mode: seek relative to current offset */
469 #define MSPACK_SYS_SEEK_CUR    (1)
470 /** mspack_system::seek() mode: seek relative to end of file */
471 #define MSPACK_SYS_SEEK_END    (2)
472 
473 /**
474  * A structure which represents an open file handle. The contents of this
475  * structure are determined by the implementation of the
476  * mspack_system::open() method.
477  */
478 struct mspack_file {
479   int dummy;
480 };
481 
482 /* --- error codes --------------------------------------------------------- */
483 
484 /** Error code: no error */
485 #define MSPACK_ERR_OK          (0)
486 /** Error code: bad arguments to method */
487 #define MSPACK_ERR_ARGS        (1)
488 /** Error code: error opening file */
489 #define MSPACK_ERR_OPEN        (2)
490 /** Error code: error reading file */
491 #define MSPACK_ERR_READ        (3)
492 /** Error code: error writing file */
493 #define MSPACK_ERR_WRITE       (4)
494 /** Error code: seek error */
495 #define MSPACK_ERR_SEEK        (5)
496 /** Error code: out of memory */
497 #define MSPACK_ERR_NOMEMORY    (6)
498 /** Error code: bad "magic id" in file */
499 #define MSPACK_ERR_SIGNATURE   (7)
500 /** Error code: bad or corrupt file format */
501 #define MSPACK_ERR_DATAFORMAT  (8)
502 /** Error code: bad checksum or CRC */
503 #define MSPACK_ERR_CHECKSUM    (9)
504 /** Error code: error during compression */
505 #define MSPACK_ERR_CRUNCH      (10)
506 /** Error code: error during decompression */
507 #define MSPACK_ERR_DECRUNCH    (11)
508 
509 /* --- functions available in library -------------------------------------- */
510 
511 /** Creates a new CAB compressor.
512  * @param sys a custom mspack_system structure, or NULL to use the default
513  * @return a #mscab_compressor or NULL
514  */
515 extern struct mscab_compressor *
516   mspack_create_cab_compressor(struct mspack_system *sys);
517 
518 /** Creates a new CAB decompressor.
519  * @param sys a custom mspack_system structure, or NULL to use the default
520  * @return a #mscab_decompressor or NULL
521  */
522 extern struct mscab_decompressor *
523   mspack_create_cab_decompressor(struct mspack_system *sys);
524 
525 /** Destroys an existing CAB compressor.
526  * @param self the #mscab_compressor to destroy
527  */
528 extern void mspack_destroy_cab_compressor(struct mscab_compressor *self);
529 
530 /** Destroys an existing CAB decompressor.
531  * @param self the #mscab_decompressor to destroy
532  */
533 extern void mspack_destroy_cab_decompressor(struct mscab_decompressor *self);
534 
535 
536 /** Creates a new CHM compressor.
537  * @param sys a custom mspack_system structure, or NULL to use the default
538  * @return a #mschm_compressor or NULL
539  */
540 extern struct mschm_compressor *
541   mspack_create_chm_compressor(struct mspack_system *sys);
542 
543 /** Creates a new CHM decompressor.
544  * @param sys a custom mspack_system structure, or NULL to use the default
545  * @return a #mschm_decompressor or NULL
546  */
547 extern struct mschm_decompressor *
548   mspack_create_chm_decompressor(struct mspack_system *sys);
549 
550 /** Destroys an existing CHM compressor.
551  * @param self the #mschm_compressor to destroy
552  */
553 extern void mspack_destroy_chm_compressor(struct mschm_compressor *self);
554 
555 /** Destroys an existing CHM decompressor.
556  * @param self the #mschm_decompressor to destroy
557  */
558 extern void mspack_destroy_chm_decompressor(struct mschm_decompressor *self);
559 
560 
561 /** Creates a new LIT compressor.
562  * @param sys a custom mspack_system structure, or NULL to use the default
563  * @return a #mslit_compressor or NULL
564  */
565 extern struct mslit_compressor *
566   mspack_create_lit_compressor(struct mspack_system *sys);
567 
568 /** Creates a new LIT decompressor.
569  * @param sys a custom mspack_system structure, or NULL to use the default
570  * @return a #mslit_decompressor or NULL
571  */
572 extern struct mslit_decompressor *
573   mspack_create_lit_decompressor(struct mspack_system *sys);
574 
575 /** Destroys an existing LIT compressor.
576  * @param self the #mslit_compressor to destroy
577  */
578 extern void mspack_destroy_lit_compressor(struct mslit_compressor *self);
579 
580 /** Destroys an existing LIT decompressor.
581  * @param self the #mslit_decompressor to destroy
582  */
583 extern void mspack_destroy_lit_decompressor(struct mslit_decompressor *self);
584 
585 
586 /** Creates a new HLP compressor.
587  * @param sys a custom mspack_system structure, or NULL to use the default
588  * @return a #mshlp_compressor or NULL
589  */
590 extern struct mshlp_compressor *
591   mspack_create_hlp_compressor(struct mspack_system *sys);
592 
593 /** Creates a new HLP decompressor.
594  * @param sys a custom mspack_system structure, or NULL to use the default
595  * @return a #mshlp_decompressor or NULL
596  */
597 extern struct mshlp_decompressor *
598   mspack_create_hlp_decompressor(struct mspack_system *sys);
599 
600 /** Destroys an existing hlp compressor.
601  * @param self the #mshlp_compressor to destroy
602  */
603 extern void mspack_destroy_hlp_compressor(struct mshlp_compressor *self);
604 
605 /** Destroys an existing hlp decompressor.
606  * @param self the #mshlp_decompressor to destroy
607  */
608 extern void mspack_destroy_hlp_decompressor(struct mshlp_decompressor *self);
609 
610 
611 /** Creates a new SZDD compressor.
612  * @param sys a custom mspack_system structure, or NULL to use the default
613  * @return a #msszdd_compressor or NULL
614  */
615 extern struct msszdd_compressor *
616   mspack_create_szdd_compressor(struct mspack_system *sys);
617 
618 /** Creates a new SZDD decompressor.
619  * @param sys a custom mspack_system structure, or NULL to use the default
620  * @return a #msszdd_decompressor or NULL
621  */
622 extern struct msszdd_decompressor *
623   mspack_create_szdd_decompressor(struct mspack_system *sys);
624 
625 /** Destroys an existing SZDD compressor.
626  * @param self the #msszdd_compressor to destroy
627  */
628 extern void mspack_destroy_szdd_compressor(struct msszdd_compressor *self);
629 
630 /** Destroys an existing SZDD decompressor.
631  * @param self the #msszdd_decompressor to destroy
632  */
633 extern void mspack_destroy_szdd_decompressor(struct msszdd_decompressor *self);
634 
635 
636 /** Creates a new KWAJ compressor.
637  * @param sys a custom mspack_system structure, or NULL to use the default
638  * @return a #mskwaj_compressor or NULL
639  */
640 extern struct mskwaj_compressor *
641   mspack_create_kwaj_compressor(struct mspack_system *sys);
642 
643 /** Creates a new KWAJ decompressor.
644  * @param sys a custom mspack_system structure, or NULL to use the default
645  * @return a #mskwaj_decompressor or NULL
646  */
647 extern struct mskwaj_decompressor *
648   mspack_create_kwaj_decompressor(struct mspack_system *sys);
649 
650 /** Destroys an existing KWAJ compressor.
651  * @param self the #mskwaj_compressor to destroy
652  */
653 extern void mspack_destroy_kwaj_compressor(struct mskwaj_compressor *self);
654 
655 /** Destroys an existing KWAJ decompressor.
656  * @param self the #mskwaj_decompressor to destroy
657  */
658 extern void mspack_destroy_kwaj_decompressor(struct mskwaj_decompressor *self);
659 
660 
661 /** Creates a new OAB compressor.
662  * @param sys a custom mspack_system structure, or NULL to use the default
663  * @return a #msoab_compressor or NULL
664  */
665 extern struct msoab_compressor *
666   mspack_create_oab_compressor(struct mspack_system *sys);
667 
668 /** Creates a new OAB decompressor.
669  * @param sys a custom mspack_system structure, or NULL to use the default
670  * @return a #msoab_decompressor or NULL
671  */
672 extern struct msoab_decompressor *
673   mspack_create_oab_decompressor(struct mspack_system *sys);
674 
675 /** Destroys an existing OAB compressor.
676  * @param self the #msoab_compressor to destroy
677  */
678 extern void mspack_destroy_oab_compressor(struct msoab_compressor *self);
679 
680 /** Destroys an existing OAB decompressor.
681  * @param self the #msoab_decompressor to destroy
682  */
683 extern void mspack_destroy_oab_decompressor(struct msoab_decompressor *self);
684 
685 
686 /* --- support for .CAB (MS Cabinet) file format --------------------------- */
687 
688 /**
689  * A structure which represents a single cabinet file.
690  *
691  * All fields are READ ONLY.
692  *
693  * If this cabinet is part of a merged cabinet set, the #files and #folders
694  * fields are common to all cabinets in the set, and will be identical.
695  *
696  * @see mscab_decompressor::open(), mscab_decompressor::close(),
697  *      mscab_decompressor::search()
698  */
699 struct mscabd_cabinet {
700   /**
701    * The next cabinet in a chained list, if this cabinet was opened with
702    * mscab_decompressor::search(). May be NULL to mark the end of the
703    * list.
704    */
705   struct mscabd_cabinet *next;
706 
707   /**
708    * The filename of the cabinet. More correctly, the filename of the
709    * physical file that the cabinet resides in. This is given by the
710    * library user and may be in any format.
711    */
712   const char *filename;
713 
714   /** The file offset of cabinet within the physical file it resides in. */
715   off_t base_offset;
716 
717   /** The length of the cabinet file in bytes. */
718   unsigned int length;
719 
720   /** The previous cabinet in a cabinet set, or NULL. */
721   struct mscabd_cabinet *prevcab;
722 
723   /** The next cabinet in a cabinet set, or NULL. */
724   struct mscabd_cabinet *nextcab;
725 
726   /** The filename of the previous cabinet in a cabinet set, or NULL. */
727   char *prevname;
728 
729   /** The filename of the next cabinet in a cabinet set, or NULL. */
730   char *nextname;
731 
732   /** The name of the disk containing the previous cabinet in a cabinet
733    * set, or NULL.
734    */
735   char *previnfo;
736 
737   /** The name of the disk containing the next cabinet in a cabinet set,
738    * or NULL.
739    */
740   char *nextinfo;
741 
742   /** A list of all files in the cabinet or cabinet set. */
743   struct mscabd_file *files;
744 
745   /** A list of all folders in the cabinet or cabinet set. */
746   struct mscabd_folder *folders;
747 
748   /**
749    * The set ID of the cabinet. All cabinets in the same set should have
750    * the same set ID.
751    */
752   unsigned short set_id;
753 
754   /**
755    * The index number of the cabinet within the set. Numbering should
756    * start from 0 for the first cabinet in the set, and increment by 1 for
757    * each following cabinet.
758    */
759   unsigned short set_index;
760 
761   /**
762    * The number of bytes reserved in the header area of the cabinet.
763    *
764    * If this is non-zero and flags has MSCAB_HDR_RESV set, this data can
765    * be read by the calling application. It is of the given length,
766    * located at offset (base_offset + MSCAB_HDR_RESV_OFFSET) in the
767    * cabinet file.
768    *
769    * @see flags
770    */
771   unsigned short header_resv;
772 
773   /**
774    * Header flags.
775    *
776    * - MSCAB_HDR_PREVCAB indicates the cabinet is part of a cabinet set, and
777    *                     has a predecessor cabinet.
778    * - MSCAB_HDR_NEXTCAB indicates the cabinet is part of a cabinet set, and
779    *                     has a successor cabinet.
780    * - MSCAB_HDR_RESV indicates the cabinet has reserved header space.
781    *
782    * @see prevname, previnfo, nextname, nextinfo, header_resv
783    */
784   int flags;
785 };
786 
787 /** Offset from start of cabinet to the reserved header data (if present). */
788 #define MSCAB_HDR_RESV_OFFSET (0x28)
789 
790 /** Cabinet header flag: cabinet has a predecessor */
791 #define MSCAB_HDR_PREVCAB (0x01)
792 /** Cabinet header flag: cabinet has a successor */
793 #define MSCAB_HDR_NEXTCAB (0x02)
794 /** Cabinet header flag: cabinet has reserved header space */
795 #define MSCAB_HDR_RESV    (0x04)
796 
797 /**
798  * A structure which represents a single folder in a cabinet or cabinet set.
799  *
800  * All fields are READ ONLY.
801  *
802  * A folder is a single compressed stream of data. When uncompressed, it
803  * holds the data of one or more files. A folder may be split across more
804  * than one cabinet.
805  */
806 struct mscabd_folder {
807   /**
808    * A pointer to the next folder in this cabinet or cabinet set, or NULL
809    * if this is the final folder.
810    */
811   struct mscabd_folder *next;
812 
813   /**
814    * The compression format used by this folder.
815    *
816    * The macro MSCABD_COMP_METHOD() should be used on this field to get
817    * the algorithm used. The macro MSCABD_COMP_LEVEL() should be used to get
818    * the "compression level".
819    *
820    * @see MSCABD_COMP_METHOD(), MSCABD_COMP_LEVEL()
821    */
822   int comp_type;
823 
824   /**
825    * The total number of data blocks used by this folder. This includes
826    * data blocks present in other files, if this folder spans more than
827    * one cabinet.
828    */
829   unsigned int num_blocks;
830 };
831 
832 /**
833  * Returns the compression method used by a folder.
834  *
835  * @param comp_type a mscabd_folder::comp_type value
836  * @return one of #MSCAB_COMP_NONE, #MSCAB_COMP_MSZIP, #MSCAB_COMP_QUANTUM
837  *         or #MSCAB_COMP_LZX
838  */
839 #define MSCABD_COMP_METHOD(comp_type) ((comp_type) & 0x0F)
840 /**
841  * Returns the compression level used by a folder.
842  *
843  * @param comp_type a mscabd_folder::comp_type value
844  * @return the compression level. This is only defined by LZX and Quantum
845  *         compression
846  */
847 #define MSCABD_COMP_LEVEL(comp_type) (((comp_type) >> 8) & 0x1F)
848 
849 /** Compression mode: no compression. */
850 #define MSCAB_COMP_NONE       (0)
851 /** Compression mode: MSZIP (deflate) compression. */
852 #define MSCAB_COMP_MSZIP      (1)
853 /** Compression mode: Quantum compression */
854 #define MSCAB_COMP_QUANTUM    (2)
855 /** Compression mode: LZX compression */
856 #define MSCAB_COMP_LZX        (3)
857 
858 /**
859  * A structure which represents a single file in a cabinet or cabinet set.
860  *
861  * All fields are READ ONLY.
862  */
863 struct mscabd_file {
864   /**
865    * The next file in the cabinet or cabinet set, or NULL if this is the
866    * final file.
867    */
868   struct mscabd_file *next;
869 
870   /**
871    * The filename of the file.
872    *
873    * A null terminated string of up to 255 bytes in length, it may be in
874    * either ISO-8859-1 or UTF8 format, depending on the file attributes.
875    *
876    * @see attribs
877    */
878   char *filename;
879 
880   /** The uncompressed length of the file, in bytes. */
881   unsigned int length;
882 
883   /**
884    * File attributes.
885    *
886    * The following attributes are defined:
887    * - #MSCAB_ATTRIB_RDONLY indicates the file is write protected.
888    * - #MSCAB_ATTRIB_HIDDEN indicates the file is hidden.
889    * - #MSCAB_ATTRIB_SYSTEM indicates the file is a operating system file.
890    * - #MSCAB_ATTRIB_ARCH indicates the file is "archived".
891    * - #MSCAB_ATTRIB_EXEC indicates the file is an executable program.
892    * - #MSCAB_ATTRIB_UTF_NAME indicates the filename is in UTF8 format rather
893    *   than ISO-8859-1.
894    */
895   int attribs;
896 
897   /** File's last modified time, hour field. */
898   char time_h;
899   /** File's last modified time, minute field. */
900   char time_m;
901   /** File's last modified time, second field. */
902   char time_s;
903 
904   /** File's last modified date, day field. */
905   char date_d;
906   /** File's last modified date, month field. */
907   char date_m;
908   /** File's last modified date, year field. */
909   int date_y;
910 
911   /** A pointer to the folder that contains this file. */
912   struct mscabd_folder *folder;
913 
914   /** The uncompressed offset of this file in its folder. */
915   unsigned int offset;
916 };
917 
918 /** mscabd_file::attribs attribute: file is read-only. */
919 #define MSCAB_ATTRIB_RDONLY   (0x01)
920 /** mscabd_file::attribs attribute: file is hidden. */
921 #define MSCAB_ATTRIB_HIDDEN   (0x02)
922 /** mscabd_file::attribs attribute: file is an operating system file. */
923 #define MSCAB_ATTRIB_SYSTEM   (0x04)
924 /** mscabd_file::attribs attribute: file is "archived". */
925 #define MSCAB_ATTRIB_ARCH     (0x20)
926 /** mscabd_file::attribs attribute: file is an executable program. */
927 #define MSCAB_ATTRIB_EXEC     (0x40)
928 /** mscabd_file::attribs attribute: filename is UTF8, not ISO-8859-1. */
929 #define MSCAB_ATTRIB_UTF_NAME (0x80)
930 
931 /** mscab_decompressor::set_param() parameter: search buffer size. */
932 #define MSCABD_PARAM_SEARCHBUF (0)
933 /** mscab_decompressor::set_param() parameter: repair MS-ZIP streams? */
934 #define MSCABD_PARAM_FIXMSZIP  (1)
935 /** mscab_decompressor::set_param() parameter: size of decompression buffer */
936 #define MSCABD_PARAM_DECOMPBUF (2)
937 /** mscab_decompressor::set_param() parameter: salvage data from bad cabinets?
938  * If enabled, open() will skip file with bad folder indices or filenames
939  * rather than reject the whole cabinet, and extract() will limit rather than
940  * reject files with invalid offsets and lengths, and bad data block checksums
941  * will be ignored. Available only in CAB decoder version 2 and above.
942  */
943 #define MSCABD_PARAM_SALVAGE   (3)
944 
945 /** TODO */
946 struct mscab_compressor {
947   int dummy;
948 };
949 
950 /**
951  * A decompressor for .CAB (Microsoft Cabinet) files
952  *
953  * All fields are READ ONLY.
954  *
955  * @see mspack_create_cab_decompressor(), mspack_destroy_cab_decompressor()
956  */
957 struct mscab_decompressor {
958   /**
959    * Opens a cabinet file and reads its contents.
960    *
961    * If the file opened is a valid cabinet file, all headers will be read
962    * and a mscabd_cabinet structure will be returned, with a full list of
963    * folders and files.
964    *
965    * In the case of an error occuring, NULL is returned and the error code
966    * is available from last_error().
967    *
968    * The filename pointer should be considered "in use" until close() is
969    * called on the cabinet.
970    *
971    * @param  self     a self-referential pointer to the mscab_decompressor
972    *                  instance being called
973    * @param  filename the filename of the cabinet file. This is passed
974    *                  directly to mspack_system::open().
975    * @return a pointer to a mscabd_cabinet structure, or NULL on failure
976    * @see close(), search(), last_error()
977    */
978   struct mscabd_cabinet * (*open) (struct mscab_decompressor *self,
979                                    const char *filename);
980 
981   /**
982    * Closes a previously opened cabinet or cabinet set.
983    *
984    * This closes a cabinet, all cabinets associated with it via the
985    * mscabd_cabinet::next, mscabd_cabinet::prevcab and
986    * mscabd_cabinet::nextcab pointers, and all folders and files. All
987    * memory used by these entities is freed.
988    *
989    * The cabinet pointer is now invalid and cannot be used again. All
990    * mscabd_folder and mscabd_file pointers from that cabinet or cabinet
991    * set are also now invalid, and cannot be used again.
992    *
993    * If the cabinet pointer given was created using search(), it MUST be
994    * the cabinet pointer returned by search() and not one of the later
995    * cabinet pointers further along the mscabd_cabinet::next chain.
996 
997    * If extra cabinets have been added using append() or prepend(), these
998    * will all be freed, even if the cabinet pointer given is not the first
999    * cabinet in the set. Do NOT close() more than one cabinet in the set.
1000    *
1001    * The mscabd_cabinet::filename is not freed by the library, as it is
1002    * not allocated by the library. The caller should free this itself if
1003    * necessary, before it is lost forever.
1004    *
1005    * @param  self     a self-referential pointer to the mscab_decompressor
1006    *                  instance being called
1007    * @param  cab      the cabinet to close
1008    * @see open(), search(), append(), prepend()
1009    */
1010   void (*close)(struct mscab_decompressor *self,
1011                 struct mscabd_cabinet *cab);
1012 
1013   /**
1014    * Searches a regular file for embedded cabinets.
1015    *
1016    * This opens a normal file with the given filename and will search the
1017    * entire file for embedded cabinet files
1018    *
1019    * If any cabinets are found, the equivalent of open() is called on each
1020    * potential cabinet file at the offset it was found. All successfully
1021    * open()ed cabinets are kept in a list.
1022    *
1023    * The first cabinet found will be returned directly as the result of
1024    * this method. Any further cabinets found will be chained in a list
1025    * using the mscabd_cabinet::next field.
1026    *
1027    * In the case of an error occuring anywhere other than the simulated
1028    * open(), NULL is returned and the error code is available from
1029    * last_error().
1030    *
1031    * If no error occurs, but no cabinets can be found in the file, NULL is
1032    * returned and last_error() returns MSPACK_ERR_OK.
1033    *
1034    * The filename pointer should be considered in use until close() is
1035    * called on the cabinet.
1036    *
1037    * close() should only be called on the result of search(), not on any
1038    * subsequent cabinets in the mscabd_cabinet::next chain.
1039    *
1040    * @param  self     a self-referential pointer to the mscab_decompressor
1041    *                  instance being called
1042    * @param  filename the filename of the file to search for cabinets. This
1043    *                  is passed directly to mspack_system::open().
1044    * @return a pointer to a mscabd_cabinet structure, or NULL
1045    * @see close(), open(), last_error()
1046    */
1047   struct mscabd_cabinet * (*search) (struct mscab_decompressor *self,
1048                                      const char *filename);
1049 
1050   /**
1051    * Appends one mscabd_cabinet to another, forming or extending a cabinet
1052    * set.
1053    *
1054    * This will attempt to append one cabinet to another such that
1055    * <tt>(cab->nextcab == nextcab) && (nextcab->prevcab == cab)</tt> and
1056    * any folders split between the two cabinets are merged.
1057    *
1058    * The cabinets MUST be part of a cabinet set -- a cabinet set is a
1059    * cabinet that spans more than one physical cabinet file on disk -- and
1060    * must be appropriately matched.
1061    *
1062    * It can be determined if a cabinet has further parts to load by
1063    * examining the mscabd_cabinet::flags field:
1064    *
1065    * - if <tt>(flags & MSCAB_HDR_PREVCAB)</tt> is non-zero, there is a
1066    *   predecessor cabinet to open() and prepend(). Its MS-DOS
1067    *   case-insensitive filename is mscabd_cabinet::prevname
1068    * - if <tt>(flags & MSCAB_HDR_NEXTCAB)</tt> is non-zero, there is a
1069    *   successor cabinet to open() and append(). Its MS-DOS case-insensitive
1070    *   filename is mscabd_cabinet::nextname
1071    *
1072    * If the cabinets do not match, an error code will be returned. Neither
1073    * cabinet has been altered, and both should be closed seperately.
1074    *
1075    * Files and folders in a cabinet set are a single entity. All cabinets
1076    * in a set use the same file list, which is updated as cabinets in the
1077    * set are added. All pointers to mscabd_folder and mscabd_file
1078    * structures in either cabinet must be discarded and re-obtained after
1079    * merging.
1080    *
1081    * @param  self     a self-referential pointer to the mscab_decompressor
1082    *                  instance being called
1083    * @param  cab      the cabinet which will be appended to,
1084    *                  predecessor of nextcab
1085    * @param  nextcab  the cabinet which will be appended,
1086    *                  successor of cab
1087    * @return an error code, or MSPACK_ERR_OK if successful
1088    * @see prepend(), open(), close()
1089    */
1090   int (*append) (struct mscab_decompressor *self,
1091                  struct mscabd_cabinet *cab,
1092                  struct mscabd_cabinet *nextcab);
1093 
1094   /**
1095    * Prepends one mscabd_cabinet to another, forming or extending a
1096    * cabinet set.
1097    *
1098    * This will attempt to prepend one cabinet to another, such that
1099    * <tt>(cab->prevcab == prevcab) && (prevcab->nextcab == cab)</tt>. In
1100    * all other respects, it is identical to append(). See append() for the
1101    * full documentation.
1102    *
1103    * @param  self     a self-referential pointer to the mscab_decompressor
1104    *                  instance being called
1105    * @param  cab      the cabinet which will be prepended to,
1106    *                  successor of prevcab
1107    * @param  prevcab  the cabinet which will be prepended,
1108    *                  predecessor of cab
1109    * @return an error code, or MSPACK_ERR_OK if successful
1110    * @see append(), open(), close()
1111    */
1112   int (*prepend) (struct mscab_decompressor *self,
1113                   struct mscabd_cabinet *cab,
1114                   struct mscabd_cabinet *prevcab);
1115 
1116   /**
1117    * Extracts a file from a cabinet or cabinet set.
1118    *
1119    * This extracts a compressed file in a cabinet and writes it to the given
1120    * filename.
1121    *
1122    * The MS-DOS filename of the file, mscabd_file::filename, is NOT USED
1123    * by extract(). The caller must examine this MS-DOS filename, copy and
1124    * change it as necessary, create directories as necessary, and provide
1125    * the correct filename as a parameter, which will be passed unchanged
1126    * to the decompressor's mspack_system::open()
1127    *
1128    * If the file belongs to a split folder in a multi-part cabinet set,
1129    * and not enough parts of the cabinet set have been loaded and appended
1130    * or prepended, an error will be returned immediately.
1131    *
1132    * @param  self     a self-referential pointer to the mscab_decompressor
1133    *                  instance being called
1134    * @param  file     the file to be decompressed
1135    * @param  filename the filename of the file being written to
1136    * @return an error code, or MSPACK_ERR_OK if successful
1137    */
1138   int (*extract)(struct mscab_decompressor *self,
1139                  struct mscabd_file *file,
1140                  const char *filename);
1141 
1142   /**
1143    * Sets a CAB decompression engine parameter.
1144    *
1145    * The following parameters are defined:
1146    * - #MSCABD_PARAM_SEARCHBUF: How many bytes should be allocated as a
1147    *   buffer when using search()? The minimum value is 4.  The default
1148    *   value is 32768.
1149    * - #MSCABD_PARAM_FIXMSZIP: If non-zero, extract() will ignore bad
1150    *   checksums and recover from decompression errors in MS-ZIP
1151    *   compressed folders. The default value is 0 (don't recover).
1152    * - #MSCABD_PARAM_DECOMPBUF: How many bytes should be used as an input
1153    *   bit buffer by decompressors? The minimum value is 4. The default
1154    *   value is 4096.
1155    *
1156    * @param  self     a self-referential pointer to the mscab_decompressor
1157    *                  instance being called
1158    * @param  param    the parameter to set
1159    * @param  value    the value to set the parameter to
1160    * @return MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS if there
1161    *         is a problem with either parameter or value.
1162    * @see search(), extract()
1163    */
1164   int (*set_param)(struct mscab_decompressor *self,
1165                    int param,
1166                    int value);
1167 
1168   /**
1169    * Returns the error code set by the most recently called method.
1170    *
1171    * This is useful for open() and search(), which do not return an error
1172    * code directly.
1173    *
1174    * @param  self     a self-referential pointer to the mscab_decompressor
1175    *                  instance being called
1176    * @return the most recent error code
1177    * @see open(), search()
1178    */
1179   int (*last_error)(struct mscab_decompressor *self);
1180 };
1181 
1182 /* --- support for .CHM (HTMLHelp) file format ----------------------------- */
1183 
1184 /**
1185  * A structure which represents a file to be placed in a CHM helpfile.
1186  *
1187  * A contiguous array of these structures should be passed to
1188  * mschm_compressor::generate(). The array list is terminated with an
1189  * entry whose mschmc_file::section field is set to #MSCHMC_ENDLIST, the
1190  * other fields in this entry are ignored.
1191  */
1192 struct mschmc_file {
1193   /** One of #MSCHMC_ENDLIST, #MSCHMC_UNCOMP or #MSCHMC_MSCOMP. */
1194   int section;
1195 
1196   /** The filename of the source file that will be added to the CHM. This
1197    * is passed directly to mspack_system::open(). */
1198   const char *filename;
1199 
1200   /** The full path and filename of the file within the CHM helpfile, a
1201    * UTF-1 encoded null-terminated string. */
1202   char *chm_filename;
1203 
1204   /** The length of the file, in bytes. This will be adhered to strictly
1205    * and a read error will be issued if this many bytes cannot be read
1206    * from the real file at CHM generation time. */
1207   off_t length;
1208 };
1209 
1210 /**
1211  * A structure which represents a section of a CHM helpfile.
1212  *
1213  * All fields are READ ONLY.
1214  *
1215  * Not used directly, but used as a generic base type for
1216  * mschmd_sec_uncompressed and mschmd_sec_mscompressed.
1217  */
1218 struct mschmd_section {
1219   /** A pointer to the CHM helpfile that contains this section. */
1220   struct mschmd_header *chm;
1221 
1222   /**
1223    * The section ID. Either 0 for the uncompressed section
1224    * mschmd_sec_uncompressed, or 1 for the LZX compressed section
1225    * mschmd_sec_mscompressed. No other section IDs are known.
1226    */
1227   unsigned int id;
1228 };
1229 
1230 /**
1231  * A structure which represents the uncompressed section of a CHM helpfile.
1232  *
1233  * All fields are READ ONLY.
1234  */
1235 struct mschmd_sec_uncompressed {
1236   /** Generic section data. */
1237   struct mschmd_section base;
1238 
1239   /** The file offset of where this section begins in the CHM helpfile. */
1240   off_t offset;
1241 };
1242 
1243 /**
1244  * A structure which represents the LZX compressed section of a CHM helpfile.
1245  *
1246  * All fields are READ ONLY.
1247  */
1248 struct mschmd_sec_mscompressed {
1249   /** Generic section data. */
1250   struct mschmd_section base;
1251 
1252   /** A pointer to the meta-file which represents all LZX compressed data. */
1253   struct mschmd_file *content;
1254 
1255   /** A pointer to the file which contains the LZX control data. */
1256   struct mschmd_file *control;
1257 
1258   /** A pointer to the file which contains the LZX reset table. */
1259   struct mschmd_file *rtable;
1260 
1261   /** A pointer to the file which contains the LZX span information.
1262    * Available only in CHM decoder version 2 and above.
1263    */
1264   struct mschmd_file *spaninfo;
1265 };
1266 
1267 /**
1268  * A structure which represents a CHM helpfile.
1269  *
1270  * All fields are READ ONLY.
1271  */
1272 struct mschmd_header {
1273   /** The version of the CHM file format used in this file. */
1274   unsigned int version;
1275 
1276   /**
1277    * The "timestamp" of the CHM helpfile.
1278    *
1279    * It is the lower 32 bits of a 64-bit value representing the number of
1280    * centiseconds since 1601-01-01 00:00:00 UTC, plus 42. It is not useful
1281    * as a timestamp, but it is useful as a semi-unique ID.
1282    */
1283   unsigned int timestamp;
1284 
1285   /**
1286    * The default Language and Country ID (LCID) of the user who ran the
1287    * HTMLHelp Compiler. This is not the language of the CHM file itself.
1288    */
1289   unsigned int language;
1290 
1291   /**
1292    * The filename of the CHM helpfile. This is given by the library user
1293    * and may be in any format.
1294    */
1295   const char *filename;
1296 
1297   /** The length of the CHM helpfile, in bytes. */
1298   off_t length;
1299 
1300   /** A list of all non-system files in the CHM helpfile. */
1301   struct mschmd_file *files;
1302 
1303   /**
1304    * A list of all system files in the CHM helpfile.
1305    *
1306    * System files are files which begin with "::". They are meta-files
1307    * generated by the CHM creation process.
1308    */
1309   struct mschmd_file *sysfiles;
1310 
1311   /** The section 0 (uncompressed) data in this CHM helpfile. */
1312   struct mschmd_sec_uncompressed sec0;
1313 
1314   /** The section 1 (MSCompressed) data in this CHM helpfile. */
1315   struct mschmd_sec_mscompressed sec1;
1316 
1317   /** The file offset of the first PMGL/PMGI directory chunk. */
1318   off_t dir_offset;
1319 
1320   /** The number of PMGL/PMGI directory chunks in this CHM helpfile. */
1321   unsigned int num_chunks;
1322 
1323   /** The size of each PMGL/PMGI chunk, in bytes. */
1324   unsigned int chunk_size;
1325 
1326   /** The "density" of the quick-reference section in PMGL/PMGI chunks. */
1327   unsigned int density;
1328 
1329   /** The depth of the index tree.
1330    *
1331    * - if 1, there are no PMGI chunks, only PMGL chunks.
1332    * - if 2, there is 1 PMGI chunk. All chunk indices point to PMGL chunks.
1333    * - if 3, the root PMGI chunk points to secondary PMGI chunks, which in
1334    *         turn point to PMGL chunks.
1335    * - and so on...
1336    */
1337   unsigned int depth;
1338 
1339   /**
1340    * The number of the root PMGI chunk.
1341    *
1342    * If there is no index in the CHM helpfile, this will be 0xFFFFFFFF.
1343    */
1344   unsigned int index_root;
1345 
1346   /**
1347    * The number of the first PMGL chunk. Usually zero.
1348    * Available only in CHM decoder version 2 and above.
1349    */
1350   unsigned int first_pmgl;
1351 
1352   /**
1353    * The number of the last PMGL chunk. Usually num_chunks-1.
1354    * Available only in CHM decoder version 2 and above.
1355    */
1356   unsigned int last_pmgl;
1357 
1358   /**
1359    * A cache of loaded chunks, filled in by mschm_decoder::fast_find().
1360    * Available only in CHM decoder version 2 and above.
1361    */
1362   unsigned char **chunk_cache;
1363 };
1364 
1365 /**
1366  * A structure which represents a file stored in a CHM helpfile.
1367  *
1368  * All fields are READ ONLY.
1369  */
1370 struct mschmd_file {
1371   /**
1372    * A pointer to the next file in the list, or NULL if this is the final
1373    * file.
1374    */
1375   struct mschmd_file *next;
1376 
1377   /**
1378    * A pointer to the section that this file is located in. Indirectly,
1379    * it also points to the CHM helpfile the file is located in.
1380    */
1381   struct mschmd_section *section;
1382 
1383   /** The offset within the section data that this file is located at. */
1384   off_t offset;
1385 
1386   /** The length of this file, in bytes */
1387   off_t length;
1388 
1389   /** The filename of this file -- a null terminated string in UTF-8. */
1390   char *filename;
1391 };
1392 
1393 /** mschmc_file::section value: end of CHM file list */
1394 #define MSCHMC_ENDLIST   (0)
1395 /** mschmc_file::section value: this file is in the Uncompressed section */
1396 #define MSCHMC_UNCOMP    (1)
1397 /** mschmc_file::section value: this file is in the MSCompressed section */
1398 #define MSCHMC_MSCOMP    (2)
1399 
1400 /** mschm_compressor::set_param() parameter: "timestamp" header */
1401 #define MSCHMC_PARAM_TIMESTAMP  (0)
1402 /** mschm_compressor::set_param() parameter: "language" header */
1403 #define MSCHMC_PARAM_LANGUAGE   (1)
1404 /** mschm_compressor::set_param() parameter: LZX window size */
1405 #define MSCHMC_PARAM_LZXWINDOW  (2)
1406 /** mschm_compressor::set_param() parameter: intra-chunk quickref density */
1407 #define MSCHMC_PARAM_DENSITY    (3)
1408 /** mschm_compressor::set_param() parameter: whether to create indices */
1409 #define MSCHMC_PARAM_INDEX      (4)
1410 
1411 /**
1412  * A compressor for .CHM (Microsoft HTMLHelp) files.
1413  *
1414  * All fields are READ ONLY.
1415  *
1416  * @see mspack_create_chm_compressor(), mspack_destroy_chm_compressor()
1417  */
1418 struct mschm_compressor {
1419   /**
1420    * Generates a CHM help file.
1421    *
1422    * The help file will contain up to two sections, an Uncompressed
1423    * section and potentially an MSCompressed (LZX compressed)
1424    * section.
1425    *
1426    * While the contents listing of a CHM file is always in lexical order,
1427    * the file list passed in will be taken as the correct order for files
1428    * within the sections.  It is in your interest to place similar files
1429    * together for better compression.
1430    *
1431    * There are two modes of generation, to use a temporary file or not to
1432    * use one. See use_temporary_file() for the behaviour of generate() in
1433    * these two different modes.
1434    *
1435    * @param  self        a self-referential pointer to the mschm_compressor
1436    *                     instance being called
1437    * @param  file_list   an array of mschmc_file structures, terminated
1438    *                     with an entry whose mschmc_file::section field is
1439    *                     #MSCHMC_ENDLIST. The order of the list is
1440    *                     preserved within each section. The length of any
1441    *                     mschmc_file::chm_filename string cannot exceed
1442    *                     roughly 4096 bytes. Each source file must be able
1443    *                     to supply as many bytes as given in the
1444    *                     mschmc_file::length field.
1445    * @param  output_file the file to write the generated CHM helpfile to.
1446    *                     This is passed directly to mspack_system::open()
1447    * @return an error code, or MSPACK_ERR_OK if successful
1448    * @see use_temporary_file() set_param()
1449    */
1450   int (*generate)(struct mschm_compressor *self,
1451                   struct mschmc_file file_list[],
1452                   const char *output_file);
1453 
1454   /**
1455    * Specifies whether a temporary file is used during CHM generation.
1456    *
1457    * The CHM file format includes data about the compressed section (such
1458    * as its overall size) that is stored in the output CHM file prior to
1459    * the compressed section itself. This unavoidably requires that the
1460    * compressed section has to be generated, before these details can be
1461    * set. There are several ways this can be handled. Firstly, the
1462    * compressed section could be generated entirely in memory before
1463    * writing any of the output CHM file. This approach is not used in
1464    * libmspack, as the compressed section can exceed the addressable
1465    * memory space on most architectures.
1466    *
1467    * libmspack has two options, either to write these unknowable sections
1468    * with blank data, generate the compressed section, then re-open the
1469    * output file for update once the compressed section has been
1470    * completed, or to write the compressed section to a temporary file,
1471    * then write the entire output file at once, performing a simple
1472    * file-to-file copy for the compressed section.
1473    *
1474    * The simple solution of buffering the entire compressed section in
1475    * memory can still be used, if desired. As the temporary file's
1476    * filename is passed directly to mspack_system::open(), it is possible
1477    * for a custom mspack_system implementation to hold this file in memory,
1478    * without writing to a disk.
1479    *
1480    * If a temporary file is set, generate() performs the following
1481    * sequence of events: the temporary file is opened for writing, the
1482    * compression algorithm writes to the temporary file, the temporary
1483    * file is closed.  Then the output file is opened for writing and the
1484    * temporary file is re-opened for reading. The output file is written
1485    * and the temporary file is read from. Both files are then closed. The
1486    * temporary file itself is not deleted. If that is desired, the
1487    * temporary file should be deleted after the completion of generate(),
1488    * if it exists.
1489    *
1490    * If a temporary file is set not to be used, generate() performs the
1491    * following sequence of events: the output file is opened for writing,
1492    * then it is written and closed. The output file is then re-opened for
1493    * update, the appropriate sections are seek()ed to and re-written, then
1494    * the output file is closed.
1495    *
1496    * @param  self          a self-referential pointer to the
1497    *                       mschm_compressor instance being called
1498    * @param  use_temp_file non-zero if the temporary file should be used,
1499    *                       zero if the temporary file should not be used.
1500    * @param  temp_file     a file to temporarily write compressed data to,
1501    *                       before opening it for reading and copying the
1502    *                       contents to the output file. This is passed
1503    *                       directly to mspack_system::open().
1504    * @return an error code, or MSPACK_ERR_OK if successful
1505    * @see generate()
1506    */
1507   int (*use_temporary_file)(struct mschm_compressor *self,
1508                             int use_temp_file,
1509                             const char *temp_file);
1510   /**
1511    * Sets a CHM compression engine parameter.
1512    *
1513    * The following parameters are defined:
1514 
1515    * - #MSCHMC_PARAM_TIMESTAMP: Sets the "timestamp" of the CHM file
1516    *   generated. This is not a timestamp, see mschmd_header::timestamp
1517    *   for a description. If this timestamp is 0, generate() will use its
1518    *   own algorithm for making a unique ID, based on the lengths and
1519    *   names of files in the CHM itself. Defaults to 0, any value between
1520    *   0 and (2^32)-1 is valid.
1521    * - #MSCHMC_PARAM_LANGUAGE: Sets the "language" of the CHM file
1522    *   generated.  This is not the language used in the CHM file, but the
1523    *   language setting of the user who ran the HTMLHelp compiler. It
1524    *   defaults to 0x0409. The valid range is between 0x0000 and 0x7F7F.
1525    * - #MSCHMC_PARAM_LZXWINDOW: Sets the size of the LZX history window,
1526    *   which is also the interval at which the compressed data stream can be
1527    *   randomly accessed. The value is not a size in bytes, but a power of
1528    *   two. The default value is 16 (which makes the window 2^16 bytes, or
1529    *   64 kilobytes), the valid range is from 15 (32 kilobytes) to 21 (2
1530    *   megabytes).
1531    * - #MSCHMC_PARAM_DENSITY: Sets the "density" of quick reference
1532    *   entries stored at the end of directory listing chunk. Each chunk is
1533    *   4096 bytes in size, and contains as many file entries as there is
1534    *   room for. At the other end of the chunk, a list of "quick reference"
1535    *   pointers is included. The offset of every 'N'th file entry is given a
1536    *   quick reference, where N = (2^density) + 1. The default density is
1537    *   2. The smallest density is 0 (N=2), the maximum is 10 (N=1025). As
1538    *   each file entry requires at least 5 bytes, the maximum number of
1539    *   entries in a single chunk is roughly 800, so the maximum value 10
1540    *   can be used to indicate there are no quickrefs at all.
1541    * - #MSCHMC_PARAM_INDEX: Sets whether or not to include quick lookup
1542    *   index chunk(s), in addition to normal directory listing chunks. A
1543    *   value of zero means no index chunks will be created, a non-zero value
1544    *   means index chunks will be created. The default is zero, "don't
1545    *   create an index".
1546    *
1547    * @param  self     a self-referential pointer to the mschm_compressor
1548    *                  instance being called
1549    * @param  param    the parameter to set
1550    * @param  value    the value to set the parameter to
1551    * @return MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS if there
1552    *         is a problem with either parameter or value.
1553    * @see generate()
1554    */
1555   int (*set_param)(struct mschm_compressor *self,
1556                    int param,
1557                    int value);
1558 
1559   /**
1560    * Returns the error code set by the most recently called method.
1561    *
1562    * @param  self     a self-referential pointer to the mschm_compressor
1563    *                  instance being called
1564    * @return the most recent error code
1565    * @see set_param(), generate()
1566    */
1567   int (*last_error)(struct mschm_compressor *self);
1568 };
1569 
1570 /**
1571  * A decompressor for .CHM (Microsoft HTMLHelp) files
1572  *
1573  * All fields are READ ONLY.
1574  *
1575  * @see mspack_create_chm_decompressor(), mspack_destroy_chm_decompressor()
1576  */
1577 struct mschm_decompressor {
1578   /**
1579    * Opens a CHM helpfile and reads its contents.
1580    *
1581    * If the file opened is a valid CHM helpfile, all headers will be read
1582    * and a mschmd_header structure will be returned, with a full list of
1583    * files.
1584    *
1585    * In the case of an error occuring, NULL is returned and the error code
1586    * is available from last_error().
1587    *
1588    * The filename pointer should be considered "in use" until close() is
1589    * called on the CHM helpfile.
1590    *
1591    * @param  self     a self-referential pointer to the mschm_decompressor
1592    *                  instance being called
1593    * @param  filename the filename of the CHM helpfile. This is passed
1594    *                  directly to mspack_system::open().
1595    * @return a pointer to a mschmd_header structure, or NULL on failure
1596    * @see close()
1597    */
1598   struct mschmd_header *(*open)(struct mschm_decompressor *self,
1599                                 const char *filename);
1600 
1601   /**
1602    * Closes a previously opened CHM helpfile.
1603    *
1604    * This closes a CHM helpfile, frees the mschmd_header and all
1605    * mschmd_file structures associated with it (if any). This works on
1606    * both helpfiles opened with open() and helpfiles opened with
1607    * fast_open().
1608    *
1609    * The CHM header pointer is now invalid and cannot be used again. All
1610    * mschmd_file pointers referencing that CHM are also now invalid, and
1611    * cannot be used again.
1612    *
1613    * @param  self     a self-referential pointer to the mschm_decompressor
1614    *                  instance being called
1615    * @param  chm      the CHM helpfile to close
1616    * @see open(), fast_open()
1617    */
1618   void (*close)(struct mschm_decompressor *self,
1619                 struct mschmd_header *chm);
1620 
1621   /**
1622    * Extracts a file from a CHM helpfile.
1623    *
1624    * This extracts a file from a CHM helpfile and writes it to the given
1625    * filename. The filename of the file, mscabd_file::filename, is not
1626    * used by extract(), but can be used by the caller as a guide for
1627    * constructing an appropriate filename.
1628    *
1629    * This method works both with files found in the mschmd_header::files
1630    * and mschmd_header::sysfiles list and mschmd_file structures generated
1631    * on the fly by fast_find().
1632    *
1633    * @param  self     a self-referential pointer to the mschm_decompressor
1634    *                  instance being called
1635    * @param  file     the file to be decompressed
1636    * @param  filename the filename of the file being written to
1637    * @return an error code, or MSPACK_ERR_OK if successful
1638    */
1639   int (*extract)(struct mschm_decompressor *self,
1640                  struct mschmd_file *file,
1641                  const char *filename);
1642 
1643   /**
1644    * Returns the error code set by the most recently called method.
1645    *
1646    * This is useful for open() and fast_open(), which do not return an
1647    * error code directly.
1648    *
1649    * @param  self     a self-referential pointer to the mschm_decompressor
1650    *                  instance being called
1651    * @return the most recent error code
1652    * @see open(), extract()
1653    */
1654   int (*last_error)(struct mschm_decompressor *self);
1655 
1656   /**
1657    * Opens a CHM helpfile quickly.
1658    *
1659    * If the file opened is a valid CHM helpfile, only essential headers
1660    * will be read. A mschmd_header structure will be still be returned, as
1661    * with open(), but the mschmd_header::files field will be NULL. No
1662    * files details will be automatically read.  The fast_find() method
1663    * must be used to obtain file details.
1664    *
1665    * In the case of an error occuring, NULL is returned and the error code
1666    * is available from last_error().
1667    *
1668    * The filename pointer should be considered "in use" until close() is
1669    * called on the CHM helpfile.
1670    *
1671    * @param  self     a self-referential pointer to the mschm_decompressor
1672    *                  instance being called
1673    * @param  filename the filename of the CHM helpfile. This is passed
1674    *                  directly to mspack_system::open().
1675    * @return a pointer to a mschmd_header structure, or NULL on failure
1676    * @see open(), close(), fast_find(), extract()
1677    */
1678   struct mschmd_header *(*fast_open)(struct mschm_decompressor *self,
1679                                      const char *filename);
1680 
1681   /**
1682    * Finds file details quickly.
1683    *
1684    * Instead of reading all CHM helpfile headers and building a list of
1685    * files, fast_open() and fast_find() are intended for finding file
1686    * details only when they are needed. The CHM file format includes an
1687    * on-disk file index to allow this.
1688    *
1689    * Given a case-sensitive filename, fast_find() will search the on-disk
1690    * index for that file.
1691    *
1692    * If the file was found, the caller-provided mschmd_file structure will
1693    * be filled out like so:
1694    * - section: the correct value for the found file
1695    * - offset: the correct value for the found file
1696    * - length: the correct value for the found file
1697    * - all other structure elements: NULL or 0
1698    *
1699    * If the file was not found, MSPACK_ERR_OK will still be returned as the
1700    * result, but the caller-provided structure will be filled out like so:
1701    * - section: NULL
1702    * - offset: 0
1703    * - length: 0
1704    * - all other structure elements: NULL or 0
1705    *
1706    * This method is intended to be used in conjunction with CHM helpfiles
1707    * opened with fast_open(), but it also works with helpfiles opened
1708    * using the regular open().
1709    *
1710    * @param  self     a self-referential pointer to the mschm_decompressor
1711    *                  instance being called
1712    * @param  chm      the CHM helpfile to search for the file
1713    * @param  filename the filename of the file to search for
1714    * @param  f_ptr    a pointer to a caller-provded mschmd_file structure
1715    * @param  f_size   <tt>sizeof(struct mschmd_file)</tt>
1716    * @return an error code, or MSPACK_ERR_OK if successful
1717    * @see open(), close(), fast_find(), extract()
1718    */
1719   int (*fast_find)(struct mschm_decompressor *self,
1720                    struct mschmd_header *chm,
1721                    const char *filename,
1722                    struct mschmd_file *f_ptr,
1723                    int f_size);
1724 };
1725 
1726 /* --- support for .LIT (EBook) file format -------------------------------- */
1727 
1728 /** TODO */
1729 struct mslit_compressor {
1730   int dummy;
1731 };
1732 
1733 /** TODO */
1734 struct mslit_decompressor {
1735   int dummy;
1736 };
1737 
1738 
1739 /* --- support for .HLP (MS Help) file format ------------------------------ */
1740 
1741 /** TODO */
1742 struct mshlp_compressor {
1743   int dummy;
1744 };
1745 
1746 /** TODO */
1747 struct mshlp_decompressor {
1748   int dummy;
1749 };
1750 
1751 
1752 /* --- support for SZDD file format ---------------------------------------- */
1753 
1754 /** msszdd_compressor::set_param() parameter: the missing character */
1755 #define MSSZDDC_PARAM_MISSINGCHAR (0)
1756 
1757 /** msszddd_header::format value - a regular SZDD file */
1758 #define MSSZDD_FMT_NORMAL (0)
1759 
1760 /** msszddd_header::format value - a special QBasic SZDD file */
1761 #define MSSZDD_FMT_QBASIC (1)
1762 
1763 /**
1764  * A structure which represents an SZDD compressed file.
1765  *
1766  * All fields are READ ONLY.
1767  */
1768 struct msszddd_header {
1769   /** The file format; either #MSSZDD_FMT_NORMAL or #MSSZDD_FMT_QBASIC */
1770   int format;
1771 
1772   /** The amount of data in the SZDD file once uncompressed. */
1773   off_t length;
1774 
1775   /**
1776    * The last character in the filename, traditionally replaced with an
1777    * underscore to show the file is compressed. The null character is used
1778    * to show that this character has not been stored (e.g. because the
1779    * filename is not known). Generally, only characters that may appear in
1780    * an MS-DOS filename (except ".") are valid.
1781    */
1782   char missing_char;
1783 };
1784 
1785 /**
1786  * A compressor for the SZDD file format.
1787  *
1788  * All fields are READ ONLY.
1789  *
1790  * @see mspack_create_szdd_compressor(), mspack_destroy_szdd_compressor()
1791  */
1792 struct msszdd_compressor {
1793   /**
1794    * Reads an input file and creates a compressed output file in the
1795    * SZDD compressed file format. The SZDD compression format is quick
1796    * but gives poor compression. It is possible for the compressed output
1797    * file to be larger than the input file.
1798    *
1799    * Conventionally, SZDD compressed files have the final character in
1800    * their filename replaced with an underscore, to show they are
1801    * compressed.  The missing character is stored in the compressed file
1802    * itself. This is due to the restricted filename conventions of MS-DOS,
1803    * most operating systems, such as UNIX, simply append another file
1804    * extension to the existing filename. As mspack does not deal with
1805    * filenames, this is left up to you. If you wish to set the missing
1806    * character stored in the file header, use set_param() with the
1807    * #MSSZDDC_PARAM_MISSINGCHAR parameter.
1808    *
1809    * "Stream" compression (where the length of the input data is not
1810    * known) is not possible. The length of the input data is stored in the
1811    * header of the SZDD file and must therefore be known before any data
1812    * is compressed. Due to technical limitations of the file format, the
1813    * maximum size of uncompressed file that will be accepted is 2147483647
1814    * bytes.
1815    *
1816    * @param  self    a self-referential pointer to the msszdd_compressor
1817    *                 instance being called
1818    * @param  input   the name of the file to compressed. This is passed
1819    *                 passed directly to mspack_system::open()
1820    * @param  output  the name of the file to write compressed data to.
1821    *                 This is passed directly to mspack_system::open().
1822    * @param  length  the length of the uncompressed file, or -1 to indicate
1823    *                 that this should be determined automatically by using
1824    *                 mspack_system::seek() on the input file.
1825    * @return an error code, or MSPACK_ERR_OK if successful
1826    * @see set_param()
1827    */
1828   int (*compress)(struct msszdd_compressor *self,
1829                   const char *input,
1830                   const char *output,
1831                   off_t length);
1832 
1833   /**
1834    * Sets an SZDD compression engine parameter.
1835    *
1836    * The following parameters are defined:
1837 
1838    * - #MSSZDDC_PARAM_CHARACTER: the "missing character", the last character
1839    *   in the uncompressed file's filename, which is traditionally replaced
1840    *   with an underscore to show the file is compressed. Traditionally,
1841    *   this can only be a character that is a valid part of an MS-DOS,
1842    *   filename, but libmspack permits any character between 0x00 and 0xFF
1843    *   to be stored. 0x00 is the default, and it represents "no character
1844    *   stored".
1845    *
1846    * @param  self     a self-referential pointer to the msszdd_compressor
1847    *                  instance being called
1848    * @param  param    the parameter to set
1849    * @param  value    the value to set the parameter to
1850    * @return MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS if there
1851    *         is a problem with either parameter or value.
1852    * @see compress()
1853    */
1854   int (*set_param)(struct msszdd_compressor *self,
1855                    int param,
1856                    int value);
1857 
1858   /**
1859    * Returns the error code set by the most recently called method.
1860    *
1861    * @param  self     a self-referential pointer to the msszdd_compressor
1862    *                  instance being called
1863    * @return the most recent error code
1864    * @see compress()
1865    */
1866   int (*last_error)(struct mschm_decompressor *self);
1867 };
1868 
1869 /**
1870  * A decompressor for SZDD compressed files.
1871  *
1872  * All fields are READ ONLY.
1873  *
1874  * @see mspack_create_szdd_decompressor(), mspack_destroy_szdd_decompressor()
1875  */
1876 struct msszdd_decompressor {
1877   /**
1878    * Opens a SZDD file and reads the header.
1879    *
1880    * If the file opened is a valid SZDD file, all headers will be read and
1881    * a msszddd_header structure will be returned.
1882    *
1883    * In the case of an error occuring, NULL is returned and the error code
1884    * is available from last_error().
1885    *
1886    * The filename pointer should be considered "in use" until close() is
1887    * called on the SZDD file.
1888    *
1889    * @param  self     a self-referential pointer to the msszdd_decompressor
1890    *                  instance being called
1891    * @param  filename the filename of the SZDD compressed file. This is
1892    *                  passed directly to mspack_system::open().
1893    * @return a pointer to a msszddd_header structure, or NULL on failure
1894    * @see close()
1895    */
1896   struct msszddd_header *(*open)(struct msszdd_decompressor *self,
1897                                  const char *filename);
1898 
1899   /**
1900    * Closes a previously opened SZDD file.
1901    *
1902    * This closes a SZDD file and frees the msszddd_header associated with
1903    * it.
1904    *
1905    * The SZDD header pointer is now invalid and cannot be used again.
1906    *
1907    * @param  self     a self-referential pointer to the msszdd_decompressor
1908    *                  instance being called
1909    * @param  szdd     the SZDD file to close
1910    * @see open()
1911    */
1912   void (*close)(struct msszdd_decompressor *self,
1913                 struct msszddd_header *szdd);
1914 
1915   /**
1916    * Extracts the compressed data from a SZDD file.
1917    *
1918    * This decompresses the compressed SZDD data stream and writes it to
1919    * an output file.
1920    *
1921    * @param  self     a self-referential pointer to the msszdd_decompressor
1922    *                  instance being called
1923    * @param  szdd     the SZDD file to extract data from
1924    * @param  filename the filename to write the decompressed data to. This
1925    *                  is passed directly to mspack_system::open().
1926    * @return an error code, or MSPACK_ERR_OK if successful
1927    */
1928   int (*extract)(struct msszdd_decompressor *self,
1929                  struct msszddd_header *szdd,
1930                  const char *filename);
1931 
1932   /**
1933    * Decompresses an SZDD file to an output file in one step.
1934    *
1935    * This opens an SZDD file as input, reads the header, then decompresses
1936    * the compressed data immediately to an output file, finally closing
1937    * both the input and output file. It is more convenient to use than
1938    * open() then extract() then close(), if you do not need to know the
1939    * SZDD output size or missing character.
1940    *
1941    * @param  self     a self-referential pointer to the msszdd_decompressor
1942    *                  instance being called
1943    * @param  input    the filename of the input SZDD file. This is passed
1944    *                  directly to mspack_system::open().
1945    * @param  output   the filename to write the decompressed data to. This
1946    *                  is passed directly to mspack_system::open().
1947    * @return an error code, or MSPACK_ERR_OK if successful
1948    */
1949   int (*decompress)(struct msszdd_decompressor *self,
1950                     const char *input,
1951                     const char *output);
1952 
1953   /**
1954    * Returns the error code set by the most recently called method.
1955    *
1956    * This is useful for open() which does not return an
1957    * error code directly.
1958    *
1959    * @param  self     a self-referential pointer to the msszdd_decompressor
1960    *                  instance being called
1961    * @return the most recent error code
1962    * @see open(), extract(), decompress()
1963    */
1964   int (*last_error)(struct msszdd_decompressor *self);
1965 };
1966 
1967 /* --- support for KWAJ file format ---------------------------------------- */
1968 
1969 /** mskwaj_compressor::set_param() parameter: compression type */
1970 #define MSKWAJC_PARAM_COMP_TYPE  (0)
1971 
1972 /** mskwaj_compressor::set_param() parameter: include the length of the
1973  * uncompressed file in the header?
1974  */
1975 #define MSKWAJC_PARAM_INCLUDE_LENGTH (1)
1976 
1977 /** KWAJ compression type: no compression. */
1978 #define MSKWAJ_COMP_NONE (0)
1979 /** KWAJ compression type: no compression, 0xFF XOR "encryption". */
1980 #define MSKWAJ_COMP_XOR (1)
1981 /** KWAJ compression type: LZSS (same method as SZDD) */
1982 #define MSKWAJ_COMP_SZDD (2)
1983 /** KWAJ compression type: LZ+Huffman compression */
1984 #define MSKWAJ_COMP_LZH (3)
1985 /** KWAJ compression type: MSZIP */
1986 #define MSKWAJ_COMP_MSZIP (4)
1987 
1988 /** KWAJ optional header flag: decompressed file length is included */
1989 #define MSKWAJ_HDR_HASLENGTH (0x01)
1990 
1991 /** KWAJ optional header flag: unknown 2-byte structure is included */
1992 #define MSKWAJ_HDR_HASUNKNOWN1 (0x02)
1993 
1994 /** KWAJ optional header flag: unknown multi-sized structure is included */
1995 #define MSKWAJ_HDR_HASUNKNOWN2 (0x04)
1996 
1997 /** KWAJ optional header flag: file name (no extension) is included */
1998 #define MSKWAJ_HDR_HASFILENAME (0x08)
1999 
2000 /** KWAJ optional header flag: file extension is included */
2001 #define MSKWAJ_HDR_HASFILEEXT (0x10)
2002 
2003 /** KWAJ optional header flag: extra text is included */
2004 #define MSKWAJ_HDR_HASEXTRATEXT (0x20)
2005 
2006 /**
2007  * A structure which represents an KWAJ compressed file.
2008  *
2009  * All fields are READ ONLY.
2010  */
2011 struct mskwajd_header {
2012   /** The compression type; should be one of #MSKWAJ_COMP_NONE,
2013    * #MSKWAJ_COMP_XOR, #MSKWAJ_COMP_SZDD or #MSKWAJ_COMP_LZH
2014    */
2015   unsigned short comp_type;
2016 
2017   /** The offset in the file where the compressed data stream begins */
2018   off_t data_offset;
2019 
2020   /** Flags indicating which optional headers were included. */
2021   int headers;
2022 
2023   /** The amount of uncompressed data in the file, or 0 if not present. */
2024   off_t length;
2025 
2026   /** output filename, or NULL if not present */
2027   char *filename;
2028 
2029   /** extra uncompressed data (usually text) in the header.
2030    * This data can contain nulls so use extra_length to get the size.
2031    */
2032   char *extra;
2033 
2034   /** length of extra uncompressed data in the header */
2035   unsigned short extra_length;
2036 };
2037 
2038 /**
2039  * A compressor for the KWAJ file format.
2040  *
2041  * All fields are READ ONLY.
2042  *
2043  * @see mspack_create_kwaj_compressor(), mspack_destroy_kwaj_compressor()
2044  */
2045 struct mskwaj_compressor {
2046   /**
2047    * Reads an input file and creates a compressed output file in the
2048    * KWAJ compressed file format. The KWAJ compression format is quick
2049    * but gives poor compression. It is possible for the compressed output
2050    * file to be larger than the input file.
2051    *
2052    * @param  self    a self-referential pointer to the mskwaj_compressor
2053    *                 instance being called
2054    * @param  input   the name of the file to compressed. This is passed
2055    *                 passed directly to mspack_system::open()
2056    * @param  output  the name of the file to write compressed data to.
2057    *                 This is passed directly to mspack_system::open().
2058    * @param  length  the length of the uncompressed file, or -1 to indicate
2059    *                 that this should be determined automatically by using
2060    *                 mspack_system::seek() on the input file.
2061    * @return an error code, or MSPACK_ERR_OK if successful
2062    * @see set_param()
2063    */
2064   int (*compress)(struct mskwaj_compressor *self,
2065                   const char *input,
2066                   const char *output,
2067                   off_t length);
2068 
2069   /**
2070    * Sets an KWAJ compression engine parameter.
2071    *
2072    * The following parameters are defined:
2073    *
2074    * - #MSKWAJC_PARAM_COMP_TYPE: the compression method to use. Must
2075    *   be one of #MSKWAJC_COMP_NONE, #MSKWAJC_COMP_XOR, #MSKWAJ_COMP_SZDD
2076    *   or #MSKWAJ_COMP_LZH. The default is #MSKWAJ_COMP_LZH.
2077    *
2078    * - #MSKWAJC_PARAM_INCLUDE_LENGTH: a boolean; should the compressed
2079    *   output file should include the uncompressed length of the input
2080    *   file in the header? This adds 4 bytes to the size of the output
2081    *   file. A value of zero says "no", non-zero says "yes". The default
2082    *   is "no".
2083    *
2084    * @param  self     a self-referential pointer to the mskwaj_compressor
2085    *                  instance being called
2086    * @param  param    the parameter to set
2087    * @param  value    the value to set the parameter to
2088    * @return MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS if there
2089    *         is a problem with either parameter or value.
2090    * @see generate()
2091    */
2092   int (*set_param)(struct mskwaj_compressor *self,
2093                    int param,
2094                    int value);
2095 
2096 
2097   /**
2098    * Sets the original filename of the file before compression,
2099    * which will be stored in the header of the output file.
2100    *
2101    * The filename should be a null-terminated string, it must be an
2102    * MS-DOS "8.3" type filename (up to 8 bytes for the filename, then
2103    * optionally a "." and up to 3 bytes for a filename extension).
2104    *
2105    * If NULL is passed as the filename, no filename is included in the
2106    * header. This is the default.
2107    *
2108    * @param  self     a self-referential pointer to the mskwaj_compressor
2109    *                  instance being called
2110    * @param  filename the original filename to use
2111    * @return MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS if the
2112    *         filename is too long
2113    */
2114   int (*set_filename)(struct mskwaj_compressor *self,
2115                       const char *filename);
2116 
2117   /**
2118    * Sets arbitrary data that will be stored in the header of the
2119    * output file, uncompressed. It can be up to roughly 64 kilobytes,
2120    * as the overall size of the header must not exceed 65535 bytes.
2121    * The data can contain null bytes if desired.
2122    *
2123    * If NULL is passed as the data pointer, or zero is passed as the
2124    * length, no extra data is included in the header. This is the
2125    * default.
2126    *
2127    * @param  self     a self-referential pointer to the mskwaj_compressor
2128    *                  instance being called
2129    * @param  data     a pointer to the data to be stored in the header
2130    * @param  bytes    the length of the data in bytes
2131    * @return MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS extra data
2132    *         is too long
2133    */
2134   int (*set_extra_data)(struct mskwaj_compressor *self,
2135                         void *data,
2136                         size_t bytes);
2137 
2138   /**
2139    * Returns the error code set by the most recently called method.
2140    *
2141    * @param  self     a self-referential pointer to the mskwaj_compressor
2142    *                  instance being called
2143    * @return the most recent error code
2144    * @see compress()
2145    */
2146   int (*last_error)(struct mschm_decompressor *self);
2147 };
2148 
2149 /**
2150  * A decompressor for KWAJ compressed files.
2151  *
2152  * All fields are READ ONLY.
2153  *
2154  * @see mspack_create_kwaj_decompressor(), mspack_destroy_kwaj_decompressor()
2155  */
2156 struct mskwaj_decompressor {
2157   /**
2158    * Opens a KWAJ file and reads the header.
2159    *
2160    * If the file opened is a valid KWAJ file, all headers will be read and
2161    * a mskwajd_header structure will be returned.
2162    *
2163    * In the case of an error occuring, NULL is returned and the error code
2164    * is available from last_error().
2165    *
2166    * The filename pointer should be considered "in use" until close() is
2167    * called on the KWAJ file.
2168    *
2169    * @param  self     a self-referential pointer to the mskwaj_decompressor
2170    *                  instance being called
2171    * @param  filename the filename of the KWAJ compressed file. This is
2172    *                  passed directly to mspack_system::open().
2173    * @return a pointer to a mskwajd_header structure, or NULL on failure
2174    * @see close()
2175    */
2176   struct mskwajd_header *(*open)(struct mskwaj_decompressor *self,
2177                                  const char *filename);
2178 
2179   /**
2180    * Closes a previously opened KWAJ file.
2181    *
2182    * This closes a KWAJ file and frees the mskwajd_header associated
2183    * with it. The KWAJ header pointer is now invalid and cannot be
2184    * used again.
2185    *
2186    * @param  self     a self-referential pointer to the mskwaj_decompressor
2187    *                  instance being called
2188    * @param  kwaj     the KWAJ file to close
2189    * @see open()
2190    */
2191   void (*close)(struct mskwaj_decompressor *self,
2192                 struct mskwajd_header *kwaj);
2193 
2194   /**
2195    * Extracts the compressed data from a KWAJ file.
2196    *
2197    * This decompresses the compressed KWAJ data stream and writes it to
2198    * an output file.
2199    *
2200    * @param  self     a self-referential pointer to the mskwaj_decompressor
2201    *                  instance being called
2202    * @param  kwaj     the KWAJ file to extract data from
2203    * @param  filename the filename to write the decompressed data to. This
2204    *                  is passed directly to mspack_system::open().
2205    * @return an error code, or MSPACK_ERR_OK if successful
2206    */
2207   int (*extract)(struct mskwaj_decompressor *self,
2208                  struct mskwajd_header *kwaj,
2209                  const char *filename);
2210 
2211   /**
2212    * Decompresses an KWAJ file to an output file in one step.
2213    *
2214    * This opens an KWAJ file as input, reads the header, then decompresses
2215    * the compressed data immediately to an output file, finally closing
2216    * both the input and output file. It is more convenient to use than
2217    * open() then extract() then close(), if you do not need to know the
2218    * KWAJ output size or output filename.
2219    *
2220    * @param  self     a self-referential pointer to the mskwaj_decompressor
2221    *                  instance being called
2222    * @param  input    the filename of the input KWAJ file. This is passed
2223    *                  directly to mspack_system::open().
2224    * @param  output   the filename to write the decompressed data to. This
2225    *                  is passed directly to mspack_system::open().
2226    * @return an error code, or MSPACK_ERR_OK if successful
2227    */
2228   int (*decompress)(struct mskwaj_decompressor *self,
2229                     const char *input,
2230                     const char *output);
2231 
2232   /**
2233    * Returns the error code set by the most recently called method.
2234    *
2235    * This is useful for open() which does not return an
2236    * error code directly.
2237    *
2238    * @param  self     a self-referential pointer to the mskwaj_decompressor
2239    *                  instance being called
2240    * @return the most recent error code
2241    * @see open(), search()
2242    */
2243   int (*last_error)(struct mskwaj_decompressor *self);
2244 };
2245 
2246 /* --- support for .LZX (Offline Address Book) file format ----------------- */
2247 
2248 /**
2249  * A compressor for the Offline Address Book (OAB) format.
2250  *
2251  * All fields are READ ONLY.
2252  *
2253  * @see mspack_create_oab_compressor(), mspack_destroy_oab_compressor()
2254  */
2255 struct msoab_compressor {
2256   /**
2257    * Compress a full OAB file.
2258    *
2259    * The input file will be read and the compressed contents written to the
2260    * output file.
2261    *
2262    * @param  self     a self-referential pointer to the msoab_decompressor
2263    *                  instance being called
2264    * @param  input    the filename of the input file. This is passed
2265    *                  directly to mspack_system::open().
2266    * @param  output   the filename of the output file. This is passed
2267    *                  directly to mspack_system::open().
2268    * @return an error code, or MSPACK_ERR_OK if successful
2269    */
2270   int (*compress) (struct msoab_compressor *self,
2271                    const char *input,
2272                    const char *output);
2273 
2274   /**
2275    * Generate a compressed incremental OAB patch file.
2276    *
2277    * The two uncompressed files "input" and "base" will be read, and an
2278    * incremental patch to generate "input" from "base" will be written to
2279    * the output file.
2280    *
2281    * @param  self     a self-referential pointer to the msoab_compressor
2282    *                  instance being called
2283    * @param  input    the filename of the input file containing the new
2284    *                  version of its contents. This is passed directly
2285    *                  to mspack_system::open().
2286    * @param  base     the filename of the original base file containing
2287    *                  the old version of its contents, against which the
2288    *                  incremental patch shall generated. This is passed
2289    *                  directly to mspack_system::open().
2290    * @param  output   the filename of the output file. This is passed
2291    *                  directly to mspack_system::open().
2292    * @return an error code, or MSPACK_ERR_OK if successful
2293    */
2294   int (*compress_incremental) (struct msoab_compressor *self,
2295                                const char *input,
2296                                const char *base,
2297                                const char *output);
2298 };
2299 
2300 /**
2301  * A decompressor for .LZX (Offline Address Book) files
2302  *
2303  * All fields are READ ONLY.
2304  *
2305  * @see mspack_create_oab_decompressor(), mspack_destroy_oab_decompressor()
2306  */
2307 struct msoab_decompressor {
2308   /**
2309    * Decompresses a full Offline Address Book file.
2310    *
2311    * If the input file is a valid compressed Offline Address Book file,
2312    * it will be read and the decompressed contents will be written to
2313    * the output file.
2314    *
2315    * @param  self     a self-referential pointer to the msoab_decompressor
2316    *                  instance being called
2317    * @param  input    the filename of the input file. This is passed
2318    *                  directly to mspack_system::open().
2319    * @param  output   the filename of the output file. This is passed
2320    *                  directly to mspack_system::open().
2321    * @return an error code, or MSPACK_ERR_OK if successful
2322    */
2323   int (*decompress) (struct msoab_decompressor *self,
2324                      const char *input,
2325                      const char *output);
2326 
2327   /**
2328    * Decompresses an Offline Address Book with an incremental patch file.
2329    *
2330    * This requires both a full UNCOMPRESSED Offline Address Book file to
2331    * act as the "base", and a compressed incremental patch file as input.
2332    * If the input file is valid, it will be decompressed with reference to
2333    * the base file, and the decompressed contents will be written to the
2334    * output file.
2335    *
2336    * There is no way to tell what the right base file is for the given
2337    * incremental patch, but if you get it wrong, this will usually result
2338    * in incorrect data being decompressed, which will then fail a checksum
2339    * test.
2340    *
2341    * @param  self     a self-referential pointer to the msoab_decompressor
2342    *                  instance being called
2343    * @param  input    the filename of the input file. This is passed
2344    *                  directly to mspack_system::open().
2345    * @param  base     the filename of the base file to which the
2346    *                  incremental patch shall be applied. This is passed
2347    *                  directly to mspack_system::open().
2348    * @param  output   the filename of the output file. This is passed
2349    *                  directly to mspack_system::open().
2350    * @return an error code, or MSPACK_ERR_OK if successful
2351    */
2352   int (*decompress_incremental) (struct msoab_decompressor *self,
2353                                  const char *input,
2354                                  const char *base,
2355                                  const char *output);
2356 
2357   /**
2358    * Sets an OAB decompression engine parameter. Available only in OAB
2359    * decompressor version 2 and above.
2360    *
2361    * - #MSOABD_PARAM_DECOMPBUF: How many bytes should be used as an input
2362    *   buffer by decompressors? The minimum value is 16. The default value
2363    *   is 4096.
2364    *
2365    * @param  self     a self-referential pointer to the msoab_decompressor
2366    *                  instance being called
2367    * @param  param    the parameter to set
2368    * @param  value    the value to set the parameter to
2369    * @return MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS if there
2370    *         is a problem with either parameter or value.
2371    */
2372   int (*set_param)(struct msoab_decompressor *self,
2373                    int param,
2374                    int value);
2375 
2376 };
2377 
2378 /** msoab_decompressor::set_param() parameter: size of decompression buffer */
2379 #define MSOABD_PARAM_DECOMPBUF (0)
2380 
2381 #ifdef __cplusplus
2382 }
2383 #endif
2384 
2385 #endif
2386