1 /* Xz.h - Xz interface
2 2010-09-17 : 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 Byte XZ_SIG[XZ_SIG_SIZE];
63 extern 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   int mode;
80   UInt32 crc;
81   UInt64 crc64;
82   CSha256 sha;
83 } CXzCheck;
84 
85 void XzCheck_Init(CXzCheck *p, int 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   int 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, int 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 numStreams;
213 
214   UInt32 crc;
215   CMixCoder decoder;
216   CXzBlock block;
217   CXzCheck check;
218   CSha256 sha;
219   Byte shaDigest[SHA256_DIGEST_SIZE];
220   Byte buf[XZ_BLOCK_HEADER_SIZE_MAX];
221 } CXzUnpacker;
222 
223 SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc);
224 void XzUnpacker_Free(CXzUnpacker *p);
225 
226 /*
227 finishMode:
228   It has meaning only if the decoding reaches output limit (*destLen).
229   LZMA_FINISH_ANY - use smallest number of input bytes
230   LZMA_FINISH_END - read EndOfStream marker after decoding
231 
232 Returns:
233   SZ_OK
234     status:
235       LZMA_STATUS_FINISHED_WITH_MARK
236       LZMA_STATUS_NOT_FINISHED
237   SZ_ERROR_DATA - Data error
238   SZ_ERROR_MEM  - Memory allocation error
239   SZ_ERROR_UNSUPPORTED - Unsupported properties
240   SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
241 */
242 
243 
244 SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
245     const Byte *src, SizeT *srcLen, /* int srcWasFinished, */ int finishMode,
246     ECoderStatus *status);
247 
248 Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p);
249 
250 EXTERN_C_END
251 
252 #endif
253