1/*
2 * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under both the BSD-style license (found in the
6 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7 * in the COPYING file in the root directory of this source tree).
8 * You may select, at your option, one of the above-listed licenses.
9 */
10
11#ifndef ZSTD_LEGACY_H
12#define ZSTD_LEGACY_H
13
14#if defined (__cplusplus)
15extern "C" {
16#endif
17
18/* *************************************
19*  Includes
20***************************************/
21#include "../common/mem.h"            /* MEM_STATIC */
22#include "../common/error_private.h"  /* ERROR */
23#include "../common/zstd_internal.h"  /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTD_frameSizeInfo */
24
25#if !defined (ZSTD_LEGACY_SUPPORT) || (ZSTD_LEGACY_SUPPORT == 0)
26#  undef ZSTD_LEGACY_SUPPORT
27#  define ZSTD_LEGACY_SUPPORT 8
28#endif
29
30#if (ZSTD_LEGACY_SUPPORT <= 1)
31#  include "zstd_v01.h"
32#endif
33#if (ZSTD_LEGACY_SUPPORT <= 2)
34#  include "zstd_v02.h"
35#endif
36#if (ZSTD_LEGACY_SUPPORT <= 3)
37#  include "zstd_v03.h"
38#endif
39#if (ZSTD_LEGACY_SUPPORT <= 4)
40#  include "zstd_v04.h"
41#endif
42#if (ZSTD_LEGACY_SUPPORT <= 5)
43#  include "zstd_v05.h"
44#endif
45#if (ZSTD_LEGACY_SUPPORT <= 6)
46#  include "zstd_v06.h"
47#endif
48#if (ZSTD_LEGACY_SUPPORT <= 7)
49#  include "zstd_v07.h"
50#endif
51
52/** ZSTD_isLegacy() :
53    @return : > 0 if supported by legacy decoder. 0 otherwise.
54              return value is the version.
55*/
56MEM_STATIC unsigned ZSTD_isLegacy(const void* src, size_t srcSize)
57{
58    U32 magicNumberLE;
59    if (srcSize<4) return 0;
60    magicNumberLE = MEM_readLE32(src);
61    switch(magicNumberLE)
62    {
63#if (ZSTD_LEGACY_SUPPORT <= 1)
64        case ZSTDv01_magicNumberLE:return 1;
65#endif
66#if (ZSTD_LEGACY_SUPPORT <= 2)
67        case ZSTDv02_magicNumber : return 2;
68#endif
69#if (ZSTD_LEGACY_SUPPORT <= 3)
70        case ZSTDv03_magicNumber : return 3;
71#endif
72#if (ZSTD_LEGACY_SUPPORT <= 4)
73        case ZSTDv04_magicNumber : return 4;
74#endif
75#if (ZSTD_LEGACY_SUPPORT <= 5)
76        case ZSTDv05_MAGICNUMBER : return 5;
77#endif
78#if (ZSTD_LEGACY_SUPPORT <= 6)
79        case ZSTDv06_MAGICNUMBER : return 6;
80#endif
81#if (ZSTD_LEGACY_SUPPORT <= 7)
82        case ZSTDv07_MAGICNUMBER : return 7;
83#endif
84        default : return 0;
85    }
86}
87
88
89MEM_STATIC unsigned long long ZSTD_getDecompressedSize_legacy(const void* src, size_t srcSize)
90{
91    U32 const version = ZSTD_isLegacy(src, srcSize);
92    if (version < 5) return 0;  /* no decompressed size in frame header, or not a legacy format */
93#if (ZSTD_LEGACY_SUPPORT <= 5)
94    if (version==5) {
95        ZSTDv05_parameters fParams;
96        size_t const frResult = ZSTDv05_getFrameParams(&fParams, src, srcSize);
97        if (frResult != 0) return 0;
98        return fParams.srcSize;
99    }
100#endif
101#if (ZSTD_LEGACY_SUPPORT <= 6)
102    if (version==6) {
103        ZSTDv06_frameParams fParams;
104        size_t const frResult = ZSTDv06_getFrameParams(&fParams, src, srcSize);
105        if (frResult != 0) return 0;
106        return fParams.frameContentSize;
107    }
108#endif
109#if (ZSTD_LEGACY_SUPPORT <= 7)
110    if (version==7) {
111        ZSTDv07_frameParams fParams;
112        size_t const frResult = ZSTDv07_getFrameParams(&fParams, src, srcSize);
113        if (frResult != 0) return 0;
114        return fParams.frameContentSize;
115    }
116#endif
117    return 0;   /* should not be possible */
118}
119
120
121MEM_STATIC size_t ZSTD_decompressLegacy(
122                     void* dst, size_t dstCapacity,
123               const void* src, size_t compressedSize,
124               const void* dict,size_t dictSize)
125{
126    U32 const version = ZSTD_isLegacy(src, compressedSize);
127    (void)dst; (void)dstCapacity; (void)dict; (void)dictSize;  /* unused when ZSTD_LEGACY_SUPPORT >= 8 */
128    switch(version)
129    {
130#if (ZSTD_LEGACY_SUPPORT <= 1)
131        case 1 :
132            return ZSTDv01_decompress(dst, dstCapacity, src, compressedSize);
133#endif
134#if (ZSTD_LEGACY_SUPPORT <= 2)
135        case 2 :
136            return ZSTDv02_decompress(dst, dstCapacity, src, compressedSize);
137#endif
138#if (ZSTD_LEGACY_SUPPORT <= 3)
139        case 3 :
140            return ZSTDv03_decompress(dst, dstCapacity, src, compressedSize);
141#endif
142#if (ZSTD_LEGACY_SUPPORT <= 4)
143        case 4 :
144            return ZSTDv04_decompress(dst, dstCapacity, src, compressedSize);
145#endif
146#if (ZSTD_LEGACY_SUPPORT <= 5)
147        case 5 :
148            {   size_t result;
149                ZSTDv05_DCtx* const zd = ZSTDv05_createDCtx();
150                if (zd==NULL) return ERROR(memory_allocation);
151                result = ZSTDv05_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize);
152                ZSTDv05_freeDCtx(zd);
153                return result;
154            }
155#endif
156#if (ZSTD_LEGACY_SUPPORT <= 6)
157        case 6 :
158            {   size_t result;
159                ZSTDv06_DCtx* const zd = ZSTDv06_createDCtx();
160                if (zd==NULL) return ERROR(memory_allocation);
161                result = ZSTDv06_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize);
162                ZSTDv06_freeDCtx(zd);
163                return result;
164            }
165#endif
166#if (ZSTD_LEGACY_SUPPORT <= 7)
167        case 7 :
168            {   size_t result;
169                ZSTDv07_DCtx* const zd = ZSTDv07_createDCtx();
170                if (zd==NULL) return ERROR(memory_allocation);
171                result = ZSTDv07_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize);
172                ZSTDv07_freeDCtx(zd);
173                return result;
174            }
175#endif
176        default :
177            return ERROR(prefix_unknown);
178    }
179}
180
181MEM_STATIC ZSTD_frameSizeInfo ZSTD_findFrameSizeInfoLegacy(const void *src, size_t srcSize)
182{
183    ZSTD_frameSizeInfo frameSizeInfo;
184    U32 const version = ZSTD_isLegacy(src, srcSize);
185    switch(version)
186    {
187#if (ZSTD_LEGACY_SUPPORT <= 1)
188        case 1 :
189            ZSTDv01_findFrameSizeInfoLegacy(src, srcSize,
190                &frameSizeInfo.compressedSize,
191                &frameSizeInfo.decompressedBound);
192            break;
193#endif
194#if (ZSTD_LEGACY_SUPPORT <= 2)
195        case 2 :
196            ZSTDv02_findFrameSizeInfoLegacy(src, srcSize,
197                &frameSizeInfo.compressedSize,
198                &frameSizeInfo.decompressedBound);
199            break;
200#endif
201#if (ZSTD_LEGACY_SUPPORT <= 3)
202        case 3 :
203            ZSTDv03_findFrameSizeInfoLegacy(src, srcSize,
204                &frameSizeInfo.compressedSize,
205                &frameSizeInfo.decompressedBound);
206            break;
207#endif
208#if (ZSTD_LEGACY_SUPPORT <= 4)
209        case 4 :
210            ZSTDv04_findFrameSizeInfoLegacy(src, srcSize,
211                &frameSizeInfo.compressedSize,
212                &frameSizeInfo.decompressedBound);
213            break;
214#endif
215#if (ZSTD_LEGACY_SUPPORT <= 5)
216        case 5 :
217            ZSTDv05_findFrameSizeInfoLegacy(src, srcSize,
218                &frameSizeInfo.compressedSize,
219                &frameSizeInfo.decompressedBound);
220            break;
221#endif
222#if (ZSTD_LEGACY_SUPPORT <= 6)
223        case 6 :
224            ZSTDv06_findFrameSizeInfoLegacy(src, srcSize,
225                &frameSizeInfo.compressedSize,
226                &frameSizeInfo.decompressedBound);
227            break;
228#endif
229#if (ZSTD_LEGACY_SUPPORT <= 7)
230        case 7 :
231            ZSTDv07_findFrameSizeInfoLegacy(src, srcSize,
232                &frameSizeInfo.compressedSize,
233                &frameSizeInfo.decompressedBound);
234            break;
235#endif
236        default :
237            frameSizeInfo.compressedSize = ERROR(prefix_unknown);
238            frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
239            break;
240    }
241    if (!ZSTD_isError(frameSizeInfo.compressedSize) && frameSizeInfo.compressedSize > srcSize) {
242        frameSizeInfo.compressedSize = ERROR(srcSize_wrong);
243        frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
244    }
245    return frameSizeInfo;
246}
247
248MEM_STATIC size_t ZSTD_findFrameCompressedSizeLegacy(const void *src, size_t srcSize)
249{
250    ZSTD_frameSizeInfo frameSizeInfo = ZSTD_findFrameSizeInfoLegacy(src, srcSize);
251    return frameSizeInfo.compressedSize;
252}
253
254MEM_STATIC size_t ZSTD_freeLegacyStreamContext(void* legacyContext, U32 version)
255{
256    switch(version)
257    {
258        default :
259        case 1 :
260        case 2 :
261        case 3 :
262            (void)legacyContext;
263            return ERROR(version_unsupported);
264#if (ZSTD_LEGACY_SUPPORT <= 4)
265        case 4 : return ZBUFFv04_freeDCtx((ZBUFFv04_DCtx*)legacyContext);
266#endif
267#if (ZSTD_LEGACY_SUPPORT <= 5)
268        case 5 : return ZBUFFv05_freeDCtx((ZBUFFv05_DCtx*)legacyContext);
269#endif
270#if (ZSTD_LEGACY_SUPPORT <= 6)
271        case 6 : return ZBUFFv06_freeDCtx((ZBUFFv06_DCtx*)legacyContext);
272#endif
273#if (ZSTD_LEGACY_SUPPORT <= 7)
274        case 7 : return ZBUFFv07_freeDCtx((ZBUFFv07_DCtx*)legacyContext);
275#endif
276    }
277}
278
279
280MEM_STATIC size_t ZSTD_initLegacyStream(void** legacyContext, U32 prevVersion, U32 newVersion,
281                                        const void* dict, size_t dictSize)
282{
283    DEBUGLOG(5, "ZSTD_initLegacyStream for v0.%u", newVersion);
284    if (prevVersion != newVersion) ZSTD_freeLegacyStreamContext(*legacyContext, prevVersion);
285    switch(newVersion)
286    {
287        default :
288        case 1 :
289        case 2 :
290        case 3 :
291            (void)dict; (void)dictSize;
292            return 0;
293#if (ZSTD_LEGACY_SUPPORT <= 4)
294        case 4 :
295        {
296            ZBUFFv04_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv04_createDCtx() : (ZBUFFv04_DCtx*)*legacyContext;
297            if (dctx==NULL) return ERROR(memory_allocation);
298            ZBUFFv04_decompressInit(dctx);
299            ZBUFFv04_decompressWithDictionary(dctx, dict, dictSize);
300            *legacyContext = dctx;
301            return 0;
302        }
303#endif
304#if (ZSTD_LEGACY_SUPPORT <= 5)
305        case 5 :
306        {
307            ZBUFFv05_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv05_createDCtx() : (ZBUFFv05_DCtx*)*legacyContext;
308            if (dctx==NULL) return ERROR(memory_allocation);
309            ZBUFFv05_decompressInitDictionary(dctx, dict, dictSize);
310            *legacyContext = dctx;
311            return 0;
312        }
313#endif
314#if (ZSTD_LEGACY_SUPPORT <= 6)
315        case 6 :
316        {
317            ZBUFFv06_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv06_createDCtx() : (ZBUFFv06_DCtx*)*legacyContext;
318            if (dctx==NULL) return ERROR(memory_allocation);
319            ZBUFFv06_decompressInitDictionary(dctx, dict, dictSize);
320            *legacyContext = dctx;
321            return 0;
322        }
323#endif
324#if (ZSTD_LEGACY_SUPPORT <= 7)
325        case 7 :
326        {
327            ZBUFFv07_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv07_createDCtx() : (ZBUFFv07_DCtx*)*legacyContext;
328            if (dctx==NULL) return ERROR(memory_allocation);
329            ZBUFFv07_decompressInitDictionary(dctx, dict, dictSize);
330            *legacyContext = dctx;
331            return 0;
332        }
333#endif
334    }
335}
336
337
338
339MEM_STATIC size_t ZSTD_decompressLegacyStream(void* legacyContext, U32 version,
340                                              ZSTD_outBuffer* output, ZSTD_inBuffer* input)
341{
342    DEBUGLOG(5, "ZSTD_decompressLegacyStream for v0.%u", version);
343    switch(version)
344    {
345        default :
346        case 1 :
347        case 2 :
348        case 3 :
349            (void)legacyContext; (void)output; (void)input;
350            return ERROR(version_unsupported);
351#if (ZSTD_LEGACY_SUPPORT <= 4)
352        case 4 :
353            {
354                ZBUFFv04_DCtx* dctx = (ZBUFFv04_DCtx*) legacyContext;
355                const void* src = (const char*)input->src + input->pos;
356                size_t readSize = input->size - input->pos;
357                void* dst = (char*)output->dst + output->pos;
358                size_t decodedSize = output->size - output->pos;
359                size_t const hintSize = ZBUFFv04_decompressContinue(dctx, dst, &decodedSize, src, &readSize);
360                output->pos += decodedSize;
361                input->pos += readSize;
362                return hintSize;
363            }
364#endif
365#if (ZSTD_LEGACY_SUPPORT <= 5)
366        case 5 :
367            {
368                ZBUFFv05_DCtx* dctx = (ZBUFFv05_DCtx*) legacyContext;
369                const void* src = (const char*)input->src + input->pos;
370                size_t readSize = input->size - input->pos;
371                void* dst = (char*)output->dst + output->pos;
372                size_t decodedSize = output->size - output->pos;
373                size_t const hintSize = ZBUFFv05_decompressContinue(dctx, dst, &decodedSize, src, &readSize);
374                output->pos += decodedSize;
375                input->pos += readSize;
376                return hintSize;
377            }
378#endif
379#if (ZSTD_LEGACY_SUPPORT <= 6)
380        case 6 :
381            {
382                ZBUFFv06_DCtx* dctx = (ZBUFFv06_DCtx*) legacyContext;
383                const void* src = (const char*)input->src + input->pos;
384                size_t readSize = input->size - input->pos;
385                void* dst = (char*)output->dst + output->pos;
386                size_t decodedSize = output->size - output->pos;
387                size_t const hintSize = ZBUFFv06_decompressContinue(dctx, dst, &decodedSize, src, &readSize);
388                output->pos += decodedSize;
389                input->pos += readSize;
390                return hintSize;
391            }
392#endif
393#if (ZSTD_LEGACY_SUPPORT <= 7)
394        case 7 :
395            {
396                ZBUFFv07_DCtx* dctx = (ZBUFFv07_DCtx*) legacyContext;
397                const void* src = (const char*)input->src + input->pos;
398                size_t readSize = input->size - input->pos;
399                void* dst = (char*)output->dst + output->pos;
400                size_t decodedSize = output->size - output->pos;
401                size_t const hintSize = ZBUFFv07_decompressContinue(dctx, dst, &decodedSize, src, &readSize);
402                output->pos += decodedSize;
403                input->pos += readSize;
404                return hintSize;
405            }
406#endif
407    }
408}
409
410
411#if defined (__cplusplus)
412}
413#endif
414
415#endif   /* ZSTD_LEGACY_H */
416