Home | History | Annotate | Download | only in C
      1 /* Xz.h - Xz interface
      2 2015-05-01 : Igor Pavlov : Public domain */
      3 
      4 #ifndef __XZ_H
      5 #define __XZ_H
      6 
      7 #include "Sha256.h"
      8 
      9 EXTERN_C_BEGIN
     10 
     11 #define XZ_ID_Subblock 1
     12 #define XZ_ID_Delta 3
     13 #define XZ_ID_X86 4
     14 #define XZ_ID_PPC 5
     15 #define XZ_ID_IA64 6
     16 #define XZ_ID_ARM 7
     17 #define XZ_ID_ARMT 8
     18 #define XZ_ID_SPARC 9
     19 #define XZ_ID_LZMA2 0x21
     20 
     21 unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value);
     22 unsigned Xz_WriteVarInt(Byte *buf, UInt64 v);
     23 
     24 /* ---------- xz block ---------- */
     25 
     26 #define XZ_BLOCK_HEADER_SIZE_MAX 1024
     27 
     28 #define XZ_NUM_FILTERS_MAX 4
     29 #define XZ_BF_NUM_FILTERS_MASK 3
     30 #define XZ_BF_PACK_SIZE (1 << 6)
     31 #define XZ_BF_UNPACK_SIZE (1 << 7)
     32 
     33 #define XZ_FILTER_PROPS_SIZE_MAX 20
     34 
     35 typedef struct
     36 {
     37   UInt64 id;
     38   UInt32 propsSize;
     39   Byte props[XZ_FILTER_PROPS_SIZE_MAX];
     40 } CXzFilter;
     41 
     42 typedef struct
     43 {
     44   UInt64 packSize;
     45   UInt64 unpackSize;
     46   Byte flags;
     47   CXzFilter filters[XZ_NUM_FILTERS_MAX];
     48 } CXzBlock;
     49 
     50 #define XzBlock_GetNumFilters(p) (((p)->flags & XZ_BF_NUM_FILTERS_MASK) + 1)
     51 #define XzBlock_HasPackSize(p)   (((p)->flags & XZ_BF_PACK_SIZE) != 0)
     52 #define XzBlock_HasUnpackSize(p) (((p)->flags & XZ_BF_UNPACK_SIZE) != 0)
     53 
     54 SRes XzBlock_Parse(CXzBlock *p, const Byte *header);
     55 SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt32 *headerSizeRes);
     56 
     57 /* ---------- xz stream ---------- */
     58 
     59 #define XZ_SIG_SIZE 6
     60 #define XZ_FOOTER_SIG_SIZE 2
     61 
     62 extern const Byte XZ_SIG[XZ_SIG_SIZE];
     63 extern const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE];
     64 
     65 #define XZ_STREAM_FLAGS_SIZE 2
     66 #define XZ_STREAM_CRC_SIZE 4
     67 
     68 #define XZ_STREAM_HEADER_SIZE (XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE)
     69 #define XZ_STREAM_FOOTER_SIZE (XZ_FOOTER_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE + 4)
     70 
     71 #define XZ_CHECK_MASK 0xF
     72 #define XZ_CHECK_NO 0
     73 #define XZ_CHECK_CRC32 1
     74 #define XZ_CHECK_CRC64 4
     75 #define XZ_CHECK_SHA256 10
     76 
     77 typedef struct
     78 {
     79   unsigned mode;
     80   UInt32 crc;
     81   UInt64 crc64;
     82   CSha256 sha;
     83 } CXzCheck;
     84 
     85 void XzCheck_Init(CXzCheck *p, unsigned mode);
     86 void XzCheck_Update(CXzCheck *p, const void *data, size_t size);
     87 int XzCheck_Final(CXzCheck *p, Byte *digest);
     88 
     89 typedef UInt16 CXzStreamFlags;
     90 
     91 #define XzFlags_IsSupported(f) ((f) <= XZ_CHECK_MASK)
     92 #define XzFlags_GetCheckType(f) ((f) & XZ_CHECK_MASK)
     93 #define XzFlags_HasDataCrc32(f) (Xz_GetCheckType(f) == XZ_CHECK_CRC32)
     94 unsigned XzFlags_GetCheckSize(CXzStreamFlags f);
     95 
     96 SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf);
     97 SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream);
     98 
     99 typedef struct
    100 {
    101   UInt64 unpackSize;
    102   UInt64 totalSize;
    103 } CXzBlockSizes;
    104 
    105 typedef struct
    106 {
    107   CXzStreamFlags flags;
    108   size_t numBlocks;
    109   size_t numBlocksAllocated;
    110   CXzBlockSizes *blocks;
    111   UInt64 startOffset;
    112 } CXzStream;
    113 
    114 void Xz_Construct(CXzStream *p);
    115 void Xz_Free(CXzStream *p, ISzAlloc *alloc);
    116 
    117 #define XZ_SIZE_OVERFLOW ((UInt64)(Int64)-1)
    118 
    119 UInt64 Xz_GetUnpackSize(const CXzStream *p);
    120 UInt64 Xz_GetPackSize(const CXzStream *p);
    121 
    122 typedef struct
    123 {
    124   size_t num;
    125   size_t numAllocated;
    126   CXzStream *streams;
    127 } CXzs;
    128 
    129 void Xzs_Construct(CXzs *p);
    130 void Xzs_Free(CXzs *p, ISzAlloc *alloc);
    131 SRes Xzs_ReadBackward(CXzs *p, ILookInStream *inStream, Int64 *startOffset, ICompressProgress *progress, ISzAlloc *alloc);
    132 
    133 UInt64 Xzs_GetNumBlocks(const CXzs *p);
    134 UInt64 Xzs_GetUnpackSize(const CXzs *p);
    135 
    136 typedef enum
    137 {
    138   CODER_STATUS_NOT_SPECIFIED,               /* use main error code instead */
    139   CODER_STATUS_FINISHED_WITH_MARK,          /* stream was finished with end mark. */
    140   CODER_STATUS_NOT_FINISHED,                /* stream was not finished */
    141   CODER_STATUS_NEEDS_MORE_INPUT             /* you must provide more input bytes */
    142 } ECoderStatus;
    143 
    144 typedef enum
    145 {
    146   CODER_FINISH_ANY,   /* finish at any point */
    147   CODER_FINISH_END    /* block must be finished at the end */
    148 } ECoderFinishMode;
    149 
    150 typedef struct _IStateCoder
    151 {
    152   void *p;
    153   void (*Free)(void *p, ISzAlloc *alloc);
    154   SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAlloc *alloc);
    155   void (*Init)(void *p);
    156   SRes (*Code)(void *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
    157       int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished);
    158 } IStateCoder;
    159 
    160 #define MIXCODER_NUM_FILTERS_MAX 4
    161 
    162 typedef struct
    163 {
    164   ISzAlloc *alloc;
    165   Byte *buf;
    166   unsigned numCoders;
    167   int finished[MIXCODER_NUM_FILTERS_MAX - 1];
    168   size_t pos[MIXCODER_NUM_FILTERS_MAX - 1];
    169   size_t size[MIXCODER_NUM_FILTERS_MAX - 1];
    170   UInt64 ids[MIXCODER_NUM_FILTERS_MAX];
    171   IStateCoder coders[MIXCODER_NUM_FILTERS_MAX];
    172 } CMixCoder;
    173 
    174 void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc);
    175 void MixCoder_Free(CMixCoder *p);
    176 void MixCoder_Init(CMixCoder *p);
    177 SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId);
    178 SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
    179     const Byte *src, SizeT *srcLen, int srcWasFinished,
    180     ECoderFinishMode finishMode, ECoderStatus *status);
    181 
    182 typedef enum
    183 {
    184   XZ_STATE_STREAM_HEADER,
    185   XZ_STATE_STREAM_INDEX,
    186   XZ_STATE_STREAM_INDEX_CRC,
    187   XZ_STATE_STREAM_FOOTER,
    188   XZ_STATE_STREAM_PADDING,
    189   XZ_STATE_BLOCK_HEADER,
    190   XZ_STATE_BLOCK,
    191   XZ_STATE_BLOCK_FOOTER
    192 } EXzState;
    193 
    194 typedef struct
    195 {
    196   EXzState state;
    197   UInt32 pos;
    198   unsigned alignPos;
    199   unsigned indexPreSize;
    200 
    201   CXzStreamFlags streamFlags;
    202 
    203   UInt32 blockHeaderSize;
    204   UInt64 packSize;
    205   UInt64 unpackSize;
    206 
    207   UInt64 numBlocks;
    208   UInt64 indexSize;
    209   UInt64 indexPos;
    210   UInt64 padSize;
    211 
    212   UInt64 numStartedStreams;
    213   UInt64 numFinishedStreams;
    214   UInt64 numTotalBlocks;
    215 
    216   UInt32 crc;
    217   CMixCoder decoder;
    218   CXzBlock block;
    219   CXzCheck check;
    220   CSha256 sha;
    221   Byte shaDigest[SHA256_DIGEST_SIZE];
    222   Byte buf[XZ_BLOCK_HEADER_SIZE_MAX];
    223 } CXzUnpacker;
    224 
    225 void XzUnpacker_Construct(CXzUnpacker *p, ISzAlloc *alloc);
    226 void XzUnpacker_Init(CXzUnpacker *p);
    227 void XzUnpacker_Free(CXzUnpacker *p);
    228 
    229 /*
    230 finishMode:
    231   It has meaning only if the decoding reaches output limit (*destLen).
    232   CODER_FINISH_ANY - use smallest number of input bytes
    233   CODER_FINISH_END - read EndOfStream marker after decoding
    234 
    235 Returns:
    236   SZ_OK
    237     status:
    238       CODER_STATUS_NOT_FINISHED,
    239       CODER_STATUS_NEEDS_MORE_INPUT - maybe there are more xz streams,
    240                                       call XzUnpacker_IsStreamWasFinished to check that current stream was finished
    241   SZ_ERROR_MEM  - Memory allocation error
    242   SZ_ERROR_DATA - Data error
    243   SZ_ERROR_UNSUPPORTED - Unsupported method or method properties
    244   SZ_ERROR_CRC  - CRC error
    245   // SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
    246 
    247   SZ_ERROR_NO_ARCHIVE - the error with xz Stream Header with one of the following reasons:
    248      - xz Stream Signature failure
    249      - CRC32 of xz Stream Header is failed
    250      - The size of Stream padding is not multiple of four bytes.
    251     It's possible to get that error, if xz stream was finished and the stream
    252     contains some another data. In that case you can call XzUnpacker_GetExtraSize()
    253     function to get real size of xz stream.
    254 */
    255 
    256 
    257 SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
    258     const Byte *src, SizeT *srcLen, ECoderFinishMode finishMode,
    259     ECoderStatus *status);
    260 
    261 Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p);
    262 
    263 /*
    264 Call XzUnpacker_GetExtraSize after XzUnpacker_Code function to detect real size of
    265 xz stream in two cases:
    266 XzUnpacker_Code() returns:
    267   res == SZ_OK && status == CODER_STATUS_NEEDS_MORE_INPUT
    268   res == SZ_ERROR_NO_ARCHIVE
    269 */
    270 
    271 UInt64 XzUnpacker_GetExtraSize(CXzUnpacker *p);
    272 
    273 EXTERN_C_END
    274 
    275 #endif
    276