Initial commit
This commit is contained in:
383
xbdm/imp/cabinet.h
Normal file
383
xbdm/imp/cabinet.h
Normal file
@@ -0,0 +1,383 @@
|
||||
/*** cabinet.h - Definitions for Cabinet File structure
|
||||
*
|
||||
* Author:
|
||||
* Benjamin W. Slivka
|
||||
*
|
||||
* History:
|
||||
* 15-Aug-1993 bens Initial version
|
||||
* 05-Sep-1993 bens Added Overview section
|
||||
* 29-Nov-1993 chuckst Added disk names to folder first & next
|
||||
* Used "CF" consistently
|
||||
* Eliminated redundant cch fields
|
||||
* 09-Feb-1994 chuckst merged in some related global constants
|
||||
* 09-Mar-1994 bens Add RESERVE defintions (for encryption)
|
||||
* 17-Mar-1994 bens Improve comments about split CFDATA structures
|
||||
* 25-Mar-1994 bens Add cabinet set ID
|
||||
* 13-May-1994 bens Define bad value for iCabinet
|
||||
*
|
||||
* Overview:
|
||||
* This file contains definitions for the Diamond Cabinet File format.
|
||||
* A Cabinet File exists to store one or more files. Usually these
|
||||
* files have been compressed, but that is not required. It is also
|
||||
* possible for a cabinet file to contain only a portion of a larger
|
||||
* file.
|
||||
*
|
||||
* In designing this format, the following goals where achieved:
|
||||
* 1) Minimize overhead in the CF format
|
||||
* ==> Where ever possible BYTEs or USHORTs were used, rather
|
||||
* than using LONGs, even though the latter would be easier
|
||||
* to manipulate on certain RISC platforms.
|
||||
* 2) Support little-endian and big-endian byte ordering.
|
||||
* ==> For simplicity on x86 systems, multi-byte numbers are
|
||||
* stored in a little-endian form, but the code to read and
|
||||
* write these numbers operates correctly on either type of
|
||||
* computer.
|
||||
*
|
||||
* A cabinet file contains the following structures in the following
|
||||
* order:
|
||||
* Name Description
|
||||
* ----------- -------------------
|
||||
* CFHEADER Cabinet description
|
||||
* [CFRESERVE] Optional RESERVED control information in CFHEADER
|
||||
* CFFOLDER(s) Folder descriptions
|
||||
* [reserved] Optional RESERVED data per folder
|
||||
* CFFILE(s) File descriptions
|
||||
* CFDATA(s) Data blocks
|
||||
* [reserved] Optional RESERVED data per data block
|
||||
*
|
||||
* Data Integrity Strategy:
|
||||
* The Cabinet File has built-in data integrity checks, since it is
|
||||
* possible for customers to have damaged diskettes, or for accidental
|
||||
* or malicious damage to occur. Rather than doing an individual
|
||||
* checksum for the entire cabinet file (which would have a dramatic
|
||||
* impact on the speed of installation from floppy disk, since the
|
||||
* entire file would need to be read), we have per-component
|
||||
* checksums, and compute and check them as we read the various
|
||||
* components of the file.
|
||||
*
|
||||
* 1) Checksum CFHEADER
|
||||
* 2) Store cabinet file length in CFHEADER (to detect file truncation)
|
||||
* 3) Checksum entire set of CFFOLDER structures
|
||||
* 4) Checksum entire set of CFFILE structures
|
||||
* 5) Checksum each (compressed) data block independantly
|
||||
*
|
||||
* This approach allows us to avoid reading unnecessary parts of the
|
||||
* file cabinet (though reading all of CFFOLDER and CFFILE structures
|
||||
* would otherwise not be required in all cases), while still providing
|
||||
* adequate integrity checking.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_CABINET
|
||||
#define INCLUDED_CABINET 1
|
||||
|
||||
//** Pack structures tightly in cabinet files!
|
||||
#pragma pack(1)
|
||||
|
||||
|
||||
/*** verCF - Cabinet File format version
|
||||
*
|
||||
* The low-order byte is interpreted as a decimal number for the minor
|
||||
* (1/100ths) portion of the version number.
|
||||
* The high-order byte is interpreted as a decimal number for the major
|
||||
* portion of the version number.
|
||||
*
|
||||
* Examples:
|
||||
* 0x0000 0.00
|
||||
* 0x010A 1.10
|
||||
* 0x0410 4.16
|
||||
*
|
||||
* History:
|
||||
* 1.01 Original
|
||||
* 1.02 Added flags field, changed signature
|
||||
* 1.03 Added setId,iCabinet so FDI can ensure correct cabinet
|
||||
* on continuation.
|
||||
*/
|
||||
#define verCF 0x0103 // CF version 1.03
|
||||
|
||||
|
||||
/*** Various cabinet file limits
|
||||
*
|
||||
*/
|
||||
#define cMAX_FOLDERS_PER_CABINET (ifoldMASK-1)
|
||||
#define cMAX_FILES_PER_CABINET 65535
|
||||
|
||||
|
||||
/*** cbRESERVE_XXX_MAX - Maximum size of RESERVE sections
|
||||
*
|
||||
* NOTE: cbRESERVE_HEADER_MAX is a fair bit less than 64K because in
|
||||
* the 16-bit version of this code, we want to have a USHORT
|
||||
* variable that holds the size of the CFHEADER structure +
|
||||
* the size of the CFRESERVE structure + the size of the per-header
|
||||
* reserved data.
|
||||
*/
|
||||
//BUGBUG 16-Mar-1994 bens Define better bound for cbRESERVE_HEADER_MAX
|
||||
#define cbRESERVE_HEADER_MAX 60000 // Fits in a USHORT
|
||||
#define cbRESERVE_FOLDER_MAX 255 // Fits in a BYTE
|
||||
#define cbRESERVE_DATA_MAX 255 // Fits in a BYTE
|
||||
|
||||
|
||||
/*** ifoldXXXX - Special values for CFFILE.iFolder
|
||||
*
|
||||
*/
|
||||
#define ifoldMASK 0xFFFC // Low two bits zero
|
||||
#define ifoldCONTINUED_FROM_PREV 0xFFFD
|
||||
#define ifoldCONTINUED_TO_NEXT 0xFFFE
|
||||
#define ifoldCONTINUED_PREV_AND_NEXT 0xFFFF
|
||||
|
||||
#define IS_CONTD_FORWARD(ifold) ((ifold & 0xfffe) == ifoldCONTINUED_TO_NEXT)
|
||||
#define IS_CONTD_BACK(ifold) ((ifold & 0xfffd) == ifoldCONTINUED_FROM_PREV)
|
||||
|
||||
|
||||
#ifndef MAKESIG
|
||||
/*** MAKESIG - Construct a 4 byte signature
|
||||
*
|
||||
* Entry:
|
||||
* ch1,ch2,ch3,ch4 - four characters
|
||||
*
|
||||
* Exit:
|
||||
* returns unsigned long
|
||||
*/
|
||||
#define MAKESIG(ch1,ch2,ch3,ch4) \
|
||||
( ((unsigned long)ch1) + \
|
||||
(((unsigned long)ch2)<< 8) + \
|
||||
(((unsigned long)ch3)<<16) + \
|
||||
(((unsigned long)ch4)<<24) )
|
||||
#endif // !MAKESIG
|
||||
|
||||
|
||||
#define sigCFHEADER MAKESIG('M','S','C','F') // CFHEADER signature
|
||||
|
||||
|
||||
/*** cfhdrXXX - bit flags for cfheader.flags field
|
||||
*
|
||||
*/
|
||||
#define cfhdrPREV_CABINET 0x0001 // Set if previous cab/disk present
|
||||
#define cfhdrNEXT_CABINET 0x0002 // Set if next cab/disk present
|
||||
#define cfhdrRESERVE_PRESENT 0x0004 // Set if RESERVE_CONTROL is present
|
||||
|
||||
typedef unsigned long CHECKSUM; /* checksum */
|
||||
typedef unsigned long UOFF; /* uoff - uncompressed offset */
|
||||
typedef unsigned long COFF; /* coff - cabinet file offset */
|
||||
|
||||
/*** CFHEADER - Cabinet File Header
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
//** LONGs are first, to ensure alignment
|
||||
long sig; // Cabinet File identification string
|
||||
CHECKSUM csumHeader; // Structure checksum (excluding csumHeader!)
|
||||
long cbCabinet; // Total length of file (consistency check)
|
||||
CHECKSUM csumFolders; // Checksum of CFFOLDER list
|
||||
COFF coffFiles; // Location in cabinet file of CFFILE list
|
||||
CHECKSUM csumFiles; // Checksum of CFFILE list
|
||||
|
||||
//** SHORTs are next, to ensure alignment
|
||||
USHORT version; // Cabinet File version (verCF)
|
||||
USHORT cFolders; // Count of folders (CFIFOLDERs) in cabinet
|
||||
USHORT cFiles; // Count of files (CFIFILEs) in cabinet
|
||||
USHORT flags; // Flags to indicate optional data presence
|
||||
USHORT setID; // Cabinet set ID (identifies set of cabinets)
|
||||
USHORT iCabinet; // Cabinet number in set (0 based)
|
||||
#define iCABINET_BAD 0xFFFF // Illegal number for iCabinet
|
||||
|
||||
//** If flags has the cfhdrRESERVE_PRESENT bit set, then a CFRESERVE
|
||||
// structure appears here, followed possibly by some CFHEADER reserved
|
||||
// space. The CFRESERVE structure has fields to define how much reserved
|
||||
// space is present in the CFHEADER, CFFOLDER, and CFDATA structures.
|
||||
// If CFRESERVE.cbCFHeader is non-zero, then abReserve[] immediately
|
||||
// follows the CFRESERVE structure. Note that all of these sizes are
|
||||
// multiples of 4 bytes, to ensure structure alignment!
|
||||
//
|
||||
// CFRESERVE cfres; // Reserve information
|
||||
// BYTE abReserve[]; // Reserved data space
|
||||
//
|
||||
|
||||
//** The following fields presence depends upon the settings in the flags
|
||||
// field above. If cfhdrPREV_CABINET is set, then there are two ASCIIZ
|
||||
// strings to describe the previous disk and cabinet.
|
||||
//
|
||||
// NOTE: This "previous" cabinet is not necessarily the immediately
|
||||
// preceding cabinet! While it usually will be, if a file is
|
||||
// continued into the current cabinet, then the "previous"
|
||||
// cabinet identifies the cabinet where the folder that contains
|
||||
// this file *starts*! For example, if EXCEL.EXE starts in
|
||||
// cabinet excel.1 and is continued through excel.2 to excel.3,
|
||||
// then cabinet excel.3 will point back to *cabinet.1*, since
|
||||
// that is where you have to start in order to extract EXCEL.EXE.
|
||||
//
|
||||
// char szCabinetPrev[]; // Prev Cabinet filespec
|
||||
// char szDiskPrev[]; // Prev descriptive disk name
|
||||
//
|
||||
// Similarly, If cfhdrNEXT_CABINET is set, then there are two ASCIIZ
|
||||
// strings to describe the next disk and cabinet:
|
||||
//
|
||||
// char szCabinetNext[]; // Next Cabinet filespec
|
||||
// char szDiskNext[]; // Next descriptive disk name
|
||||
//
|
||||
} CFHEADER; /* cfheader */
|
||||
|
||||
|
||||
/*** CFRESERVE - Cabinet File Reserved data information
|
||||
*
|
||||
* This structure is present in the middle of the CFHEADER structure if
|
||||
* CFHEADER.flags has the cfhdrRESERVE_PRESENT bit set. This structure
|
||||
* defines the sizes of all the reserved data sections in the CFHEADER,
|
||||
* CFFOLDER, and CFDATA structures.
|
||||
*
|
||||
* These reserved sizes can be zero (although it would be silly to have
|
||||
* all of them be zero), but otherwise must be a multiple of 4, to ensure
|
||||
* structure alignment for RISC machines.
|
||||
*/
|
||||
typedef struct {
|
||||
USHORT cbCFHeader; // Size of abReserve in CFHEADER structure
|
||||
BYTE cbCFFolder; // Size of abReserve in CFFOLDER structure
|
||||
BYTE cbCFData; // Size of abReserve in CFDATA structure
|
||||
} CFRESERVE; /* cfreserve */
|
||||
|
||||
#define cbCF_HEADER_BAD 0xFFFF // Bad value for CFRESERVE.cbCFHeader
|
||||
|
||||
|
||||
/*** CFFOLDER - Cabinet Folder
|
||||
*
|
||||
* This structure describes a partial or complete "compression unit".
|
||||
* A folder is by definition a stream of compressed data. To retrieve
|
||||
* an uncompressed data from a folder, you *must* start decompressing
|
||||
* the data at the start of the folder, regardless of how far into the
|
||||
* folder the data you want actually starts.
|
||||
*
|
||||
* Folders may start in one cabinet, and continue on to one or more
|
||||
* succeeding cabinets. In general, if a folder has been continued over
|
||||
* a cabinet boundary, Diamond/FCI will terminate that folder as soon as
|
||||
* the current file has been completely compressed. Generally this means
|
||||
* that a folder would span at most two cabinets, but if the file is really
|
||||
* large, it could span more than two cabinets.
|
||||
*
|
||||
* Note: CFFOLDERs actually refer to folder *fragments*, not necessarily
|
||||
* complete folders. You know that a CFFOLDER is the beginning of a
|
||||
* folder (as opposed to a continuation in a subsequent cabinet file)
|
||||
* if a file starts in it (i.e., the CFFILE.uoffFolderStart field is
|
||||
* 0).
|
||||
*/
|
||||
typedef struct {
|
||||
COFF coffCabStart; // Offset in cabinet file of first CFDATA
|
||||
// block for this folder.
|
||||
|
||||
USHORT cCFData; // Count of CFDATAs for this folder that
|
||||
// are actually in this cabinet. Note that
|
||||
// a folder can continue into another cabinet
|
||||
// and have many more CFDATA blocks in that
|
||||
// cabinet, *and* a folder may have started
|
||||
// in a previous cabinet. This count is
|
||||
// only of CFDATAs for this folder that are
|
||||
// (at least partially) in this cabinet.
|
||||
|
||||
short typeCompress; // Indicates compression type for all CFDATA
|
||||
// blocks for this folder. The valid values
|
||||
// are defined in the types.h built into
|
||||
// fci.h/fdi.h.
|
||||
|
||||
//** If CFHEADER.flags has the cfhdrRESERVE_PRESENT bit set, and
|
||||
// CFRESERVE.cbCFFolder is non-zero, then abReserve[] appears here.
|
||||
//
|
||||
// BYTE abReserve[]; // Reserved data space
|
||||
//
|
||||
} CFFOLDER; /* cffolder */
|
||||
|
||||
|
||||
|
||||
/*** CFFILE - Cabinet File structure describing a single file in the cabinet
|
||||
*
|
||||
* NOTE: iFolder is used to indicatate continuation cases, so we have to
|
||||
* calculate the real iFolder by examining the cabinet files:
|
||||
*
|
||||
* ifoldCONTINUED_FROM_PREV
|
||||
* This file ends in this cabinet, but is continued from a
|
||||
* previous cabinet. Therefore, the portion of the file contained
|
||||
* in *this* cabinet *must* start in the first folder.
|
||||
*
|
||||
* NOTE: szCabinetPrev is the name of the cabinet where this file
|
||||
* *starts*, which is not necessarily the immediately
|
||||
* preceeding cabinet! Since it only makes sense to
|
||||
* decompress a file from its start, the starting cabinet
|
||||
* is what is important!
|
||||
*
|
||||
* ifoldCONTINUED_TO_NEXT
|
||||
* This file starts in this cabinet, but is continued to the next
|
||||
* cabinet. Therfore, this file must start in the *last* folder
|
||||
* in this cabinet.
|
||||
*
|
||||
* ifoldCONTINUED_PREV_AND_NEXT
|
||||
* This file is the *middle* portion of a file that started in a
|
||||
* previous cabinet and is continued in the next cabinet. Since
|
||||
* this cabinet only contain this piece of a single file, there
|
||||
* is only a single folder fragment in this cabinet.
|
||||
*/
|
||||
typedef struct {
|
||||
long cbFile; // Uncompressed size of file
|
||||
|
||||
UOFF uoffFolderStart; // Offset in folder IN UNCOMPRESSED BYTES
|
||||
// of the start of this file
|
||||
|
||||
USHORT iFolder; // Index of folder containing this file;
|
||||
// 0 is first folder in this cabinet.
|
||||
// See ifoldCONTINUED_XXXX values above
|
||||
// for treatment of continuation files.
|
||||
|
||||
USHORT date; // Date stamp in FAT file system format
|
||||
|
||||
USHORT time; // Time stamp in FAT file system format
|
||||
|
||||
USHORT attribs; // Attribute in FAT file system format
|
||||
|
||||
// char szName[]; // File name (may include path characters)
|
||||
} CFFILE; /* cffile */
|
||||
|
||||
|
||||
/*** CFDATA - Cabinet File structure describing a data block
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
CHECKSUM csum; // Checksum (excluding this field itself!)
|
||||
// of this structure and the data that
|
||||
// follows. If this CFDATA structure is
|
||||
// continued to the next cabinet, then
|
||||
// the value of this field is ignored
|
||||
// (and set to zero).
|
||||
|
||||
USHORT cbData; // Size of ab[] data that resides in the
|
||||
// current cabinet. A CFDATA may be split
|
||||
// across a cabinet boundary, so this
|
||||
// value indicates only the amount of data
|
||||
// store in this cabinet.
|
||||
|
||||
USHORT cbUncomp; // Uncompressed size of ab[] data; if this
|
||||
// CFDATA block is continued to the next
|
||||
// cabinet, then this value is zero!
|
||||
// If this CFDATA block the remainder of
|
||||
// of a CFDATA block that started in the
|
||||
// previous cabinet, then this value is
|
||||
// the total size of the uncompressed data
|
||||
// represented by the two CFDATA blocks!
|
||||
|
||||
//** If CFHEADER.flags has the cfhdrRESERVE_PRESENT bit set, and
|
||||
// CFRESERVE.cbCFData is non-zero, then abReserve[] appears here.
|
||||
//
|
||||
// BYTE abReserve[]; // Reserved data space
|
||||
//
|
||||
|
||||
//** The actual data follows here, cbData bytes in length.
|
||||
//
|
||||
// BYTE ab[]; // Data
|
||||
//
|
||||
} CFDATA; /* cfdata */
|
||||
|
||||
|
||||
|
||||
//** Attribute Bit to use for Run after extract
|
||||
#define RUNATTRIB 0x40
|
||||
|
||||
|
||||
//** Revert to default structure packing!
|
||||
#pragma pack()
|
||||
|
||||
#endif // !INCLUDED_CABINET
|
||||
Reference in New Issue
Block a user