lz4io.c revision 1833be1cf0e545f8b24bb4a786e274a9e419e280
169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* 269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. LZ4io.c - LZ4 File/Stream Interface 38b233b228dbda484d1d545c5a3ecaf06aef3e930Yann Collet Copyright (C) Yann Collet 2011-2016 445a357fd1704e9c6d2d8037277bda62e8c86308eYann Collet 569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. GPL v2 License 669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. This program is free software; you can redistribute it and/or modify 869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. it under the terms of the GNU General Public License as published by 969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. the Free Software Foundation; either version 2 of the License, or 1069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. (at your option) any later version. 1169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 1269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. This program is distributed in the hope that it will be useful, 1369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. but WITHOUT ANY WARRANTY; without even the implied warranty of 1469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. GNU General Public License for more details. 1669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 1769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. You should have received a copy of the GNU General Public License along 1869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. with this program; if not, write to the Free Software Foundation, Inc., 1969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 2069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 2169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. You can contact the author at : 2284cedb4632ab87fbb108b4f7ed6e9ec164b6a4d4Przemyslaw Skibinski - LZ4 source repository : https://github.com/lz4/lz4 2369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c 2469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.*/ 2569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* 2669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. Note : this is stand-alone program. 2769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. It is not part of LZ4 compression library, it is a user code of the LZ4 library. 2869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. - The license of LZ4 library is BSD. 2969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. - The license of xxHash library is BSD. 3069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. - The license of this source file is GPLv2. 3169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.*/ 3269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 338a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet/************************************** 348a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet* Compiler Options 35d11ac4087254db4b9391039ce862e7305874fe97Yann Collet**************************************/ 368a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet#define _LARGE_FILES /* Large file support on 32-bits AIX */ 371abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet#define _FILE_OFFSET_BITS 64 /* off_t width */ 381abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet#define _LARGEFILE_SOURCE 3969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 40c1864f69e87d68fe79420c9303ecf97eb66bc7c7inikep#if defined(__MINGW32__) && !defined(_POSIX_SOURCE) 41c1864f69e87d68fe79420c9303ecf97eb66bc7c7inikep# define _POSIX_SOURCE 1 /* disable %llu warnings with MinGW on Windows */ 42c1864f69e87d68fe79420c9303ecf97eb66bc7c7inikep#endif 4369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 44d11ac4087254db4b9391039ce862e7305874fe97Yann Collet/***************************** 458a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet* Includes 468a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet*****************************/ 4798be008479486f60b0a98289eee2f57c28650964Przemyslaw Skibinski#include "util.h" /* Compiler options, UTIL_getFileStat */ 48c64200dd85a85d9cc69a6fda682362d851be863bYann Collet#include <stdio.h> /* fprintf, fopen, fread, stdin, stdout, fflush, getchar */ 497f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet#include <stdlib.h> /* malloc, free */ 507f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet#include <string.h> /* strcmp, strlen */ 517f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet#include <time.h> /* clock */ 527f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet#include <sys/types.h> /* stat64 */ 537f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet#include <sys/stat.h> /* stat64 */ 5469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#include "lz4io.h" 558b8e5efefe2dfdfbeb3ebc7591d2c345c34552f5Yann Collet#include "lz4.h" /* still required for legacy format */ 568b8e5efefe2dfdfbeb3ebc7591d2c345c34552f5Yann Collet#include "lz4hc.h" /* still required for legacy format */ 576de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet#include "lz4frame.h" 5869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 5969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 60248b761f55b92a34eacbfe2ac5d6f1b94e69d7bfYann Collet/****************************** 618a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet* OS-specific Includes 62248b761f55b92a34eacbfe2ac5d6f1b94e69d7bfYann Collet******************************/ 631d3ab5d85d8c7536111d2c2e5d64d3b887b16b8amauro.persano#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32) 648a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet# include <fcntl.h> /* _O_BINARY */ 65248b761f55b92a34eacbfe2ac5d6f1b94e69d7bfYann Collet# include <io.h> /* _setmode, _fileno, _get_osfhandle */ 66b2bbb2790d50f09b594f6588ebdade62966b5d5cLouis P. Santillan# if !defined(__DJGPP__) 67dfabec2d1817e08fda70c19ed9248819b6a1fb22Yann Collet# define SET_BINARY_MODE(file) { int unused=_setmode(_fileno(file), _O_BINARY); (void)unused; } 6814b40fb6d713211132524f6245d128bbb75a6f15Kouhei Sutou# include <windows.h> /* DeviceIoControl, HANDLE, FSCTL_SET_SPARSE */ 6946a7b94e8cf4c56eafcddeca09c63df368bfa4cbKouhei Sutou# include <winioctl.h> /* FSCTL_SET_SPARSE */ 70b2bbb2790d50f09b594f6588ebdade62966b5d5cLouis P. Santillan# define SET_SPARSE_FILE_MODE(file) { DWORD dw; DeviceIoControl((HANDLE) _get_osfhandle(_fileno(file)), FSCTL_SET_SPARSE, 0, 0, 0, 0, &dw, 0); } 71b2bbb2790d50f09b594f6588ebdade62966b5d5cLouis P. Santillan# if defined(_MSC_VER) && (_MSC_VER >= 1400) /* Avoid MSVC fseek()'s 2GiB barrier */ 72b2bbb2790d50f09b594f6588ebdade62966b5d5cLouis P. Santillan# define fseek _fseeki64 73b2bbb2790d50f09b594f6588ebdade62966b5d5cLouis P. Santillan# endif 74b2bbb2790d50f09b594f6588ebdade62966b5d5cLouis P. Santillan# else 75b2bbb2790d50f09b594f6588ebdade62966b5d5cLouis P. Santillan# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) 76b2bbb2790d50f09b594f6588ebdade62966b5d5cLouis P. Santillan# define SET_SPARSE_FILE_MODE(file) 7741b6ed3c5bc7f0c85f1bfe3abc940d9b74581e7dTakayuki MATSUOKA# endif 7869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#else 791abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet# if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || (defined(__APPLE__) && defined(__MACH__)) 801abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet# define fseek fseeko 811abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet# endif 8269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.# define SET_BINARY_MODE(file) 83248b761f55b92a34eacbfe2ac5d6f1b94e69d7bfYann Collet# define SET_SPARSE_FILE_MODE(file) 8469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#endif 8569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 8669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 87248b761f55b92a34eacbfe2ac5d6f1b94e69d7bfYann Collet/***************************** 888a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet* Constants 898a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet*****************************/ 906de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet#define KB *(1 <<10) 916de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet#define MB *(1 <<20) 9269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define GB *(1U<<30) 9369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 9469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define _1BIT 0x01 9569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define _2BITS 0x03 9669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define _3BITS 0x07 9769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define _4BITS 0x0F 9869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define _8BITS 0xFF 9969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 1007d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet#define MAGICNUMBER_SIZE 4 1017d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet#define LZ4IO_MAGICNUMBER 0x184D2204 1027d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet#define LZ4IO_SKIPPABLE0 0x184D2A50 1037d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet#define LZ4IO_SKIPPABLEMASK 0xFFFFFFF0 1047d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet#define LEGACY_MAGICNUMBER 0x184C2102 10569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 10669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define CACHELINE 64 10769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define LEGACY_BLOCKSIZE (8 MB) 108d517d609d95bdbab665a6ddb6e018c450d1e5ae6Yann Collet#define MIN_STREAM_BUFSIZE (192 KB) 1097d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet#define LZ4IO_BLOCKSIZEID_DEFAULT 7 1107d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet 11169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 1128a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet/************************************** 1138a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet* Macros 114d11ac4087254db4b9391039ce862e7305874fe97Yann Collet**************************************/ 11569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define DISPLAY(...) fprintf(stderr, __VA_ARGS__) 11612ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet#define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); } 11712ab41571ef7fd11b8b2013aa943beae373cef8aYann Colletstatic int g_displayLevel = 0; /* 0 : no display ; 1: errors ; 2 : + result + interaction + warnings ; 3 : + progression; 4 : + information */ 11812ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet 11912ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet#define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \ 12059adfd82d6c00c005a88ef5bdd405204d71d5729Yann Collet if (((clock_t)(g_time - clock()) > refreshRate) || (g_displayLevel>=4)) \ 1216de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet { g_time = clock(); DISPLAY(__VA_ARGS__); \ 122d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (g_displayLevel>=4) fflush(stderr); } } 12359adfd82d6c00c005a88ef5bdd405204d71d5729Yann Colletstatic const clock_t refreshRate = CLOCKS_PER_SEC / 6; 1246de52c2a8c40b7381e364ad87af9e80a60d95229Yann Colletstatic clock_t g_time = 0; 12569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 12669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 1278a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet/************************************** 1288a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet* Local Parameters 129d11ac4087254db4b9391039ce862e7305874fe97Yann Collet**************************************/ 13012ab41571ef7fd11b8b2013aa943beae373cef8aYann Colletstatic int g_overwrite = 1; 131136caa552bdc5657449e540b8becff826b80ade7Nick Terrellstatic int g_testMode = 0; 1327d87d43e619b0296bbe3f1674f10575b3f68c189Yann Colletstatic int g_blockSizeId = LZ4IO_BLOCKSIZEID_DEFAULT; 13312ab41571ef7fd11b8b2013aa943beae373cef8aYann Colletstatic int g_blockChecksum = 0; 13412ab41571ef7fd11b8b2013aa943beae373cef8aYann Colletstatic int g_streamChecksum = 1; 13512ab41571ef7fd11b8b2013aa943beae373cef8aYann Colletstatic int g_blockIndependence = 1; 1369fd4f1f9f780f1be38ad6695d62a9ba2ea426d6dYann Colletstatic int g_sparseFileSupport = 1; 1377f436a1215f11b0fb872c34f088b8b5888d0630dYann Colletstatic int g_contentSizeFlag = 0; 13869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 139c5decf7562a3b4065922ae6460b7785eb91366f8Yann Collet 1408a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet/************************************** 1418a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet* Exceptions 1428a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet***************************************/ 143d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet#ifndef DEBUG 144d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet# define DEBUG 0 145d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet#endif 14669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define DEBUGOUTPUT(...) if (DEBUG) DISPLAY(__VA_ARGS__); 14769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define EXM_THROW(error, ...) \ 14869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ \ 14969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. DEBUGOUTPUT("Error defined at %s, line %i : \n", __FILE__, __LINE__); \ 15069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. DISPLAYLEVEL(1, "Error %i : ", error); \ 15169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. DISPLAYLEVEL(1, __VA_ARGS__); \ 152c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet DISPLAYLEVEL(1, " \n"); \ 15369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. exit(error); \ 15469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 15569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 15669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 1578a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet/************************************** 1588a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet* Version modifiers 1597d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet**************************************/ 16069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define EXTENDED_ARGUMENTS 16169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define EXTENDED_HELP 16269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define EXTENDED_FORMAT 163a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet#define DEFAULT_DECOMPRESSOR LZ4IO_decompressLZ4F 16469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 16569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 16669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* ************************************************** */ 16769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* ****************** Parameters ******************** */ 16869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* ************************************************** */ 16969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 17069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* Default setting : overwrite = 1; return : overwrite mode (0/1) */ 17169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.int LZ4IO_setOverwrite(int yes) 17269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 17312ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet g_overwrite = (yes!=0); 17412ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet return g_overwrite; 17569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 17669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 177136caa552bdc5657449e540b8becff826b80ade7Nick Terrell/* Default setting : testMode = 0; return : testMode (0/1) */ 178136caa552bdc5657449e540b8becff826b80ade7Nick Terrellint LZ4IO_setTestMode(int yes) 1793dcafd35d409380182393fdb0d5666f6a64ff841Nick Terrell{ 180136caa552bdc5657449e540b8becff826b80ade7Nick Terrell g_testMode = (yes!=0); 181136caa552bdc5657449e540b8becff826b80ade7Nick Terrell return g_testMode; 1823dcafd35d409380182393fdb0d5666f6a64ff841Nick Terrell} 1833dcafd35d409380182393fdb0d5666f6a64ff841Nick Terrell 18469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* blockSizeID : valid values : 4-5-6-7 */ 185d2be69b144d6c5fd9a3dcbc4133e93e710cda998Yann Colletsize_t LZ4IO_setBlockSizeID(unsigned bsid) 18669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 187d2be69b144d6c5fd9a3dcbc4133e93e710cda998Yann Collet static const size_t blockSizeTable[] = { 64 KB, 256 KB, 1 MB, 4 MB }; 188929badd611544f28ed887c380f55e282a101e6bdYann Collet static const unsigned minBlockSizeID = 4; 189929badd611544f28ed887c380f55e282a101e6bdYann Collet static const unsigned maxBlockSizeID = 7; 190d2be69b144d6c5fd9a3dcbc4133e93e710cda998Yann Collet if ((bsid < minBlockSizeID) || (bsid > maxBlockSizeID)) return 0; 19112ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet g_blockSizeId = bsid; 19212ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet return blockSizeTable[g_blockSizeId-minBlockSizeID]; 19369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 19469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 1956de52c2a8c40b7381e364ad87af9e80a60d95229Yann Colletint LZ4IO_setBlockMode(LZ4IO_blockMode_t blockMode) 19669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 19712ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet g_blockIndependence = (blockMode == LZ4IO_blockIndependent); 19812ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet return g_blockIndependence; 19969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 20069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 20169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* Default setting : no checksum */ 20269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.int LZ4IO_setBlockChecksumMode(int xxhash) 20369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 20412ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet g_blockChecksum = (xxhash != 0); 20512ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet return g_blockChecksum; 20669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 20769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 20869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* Default setting : checksum enabled */ 20969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.int LZ4IO_setStreamChecksumMode(int xxhash) 21069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 21112ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet g_streamChecksum = (xxhash != 0); 21212ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet return g_streamChecksum; 21369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 21469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 21569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* Default setting : 0 (no notification) */ 21669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.int LZ4IO_setNotificationLevel(int level) 21769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 21812ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet g_displayLevel = level; 21912ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet return g_displayLevel; 22012ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet} 22112ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet 22212ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet/* Default setting : 0 (disabled) */ 22312ab41571ef7fd11b8b2013aa943beae373cef8aYann Colletint LZ4IO_setSparseFile(int enable) 22412ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet{ 225e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet g_sparseFileSupport = (enable!=0); 22612ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet return g_sparseFileSupport; 22769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 22869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 2297f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet/* Default setting : 0 (disabled) */ 2307f436a1215f11b0fb872c34f088b8b5888d0630dYann Colletint LZ4IO_setContentSize(int enable) 2317f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet{ 2327f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet g_contentSizeFlag = (enable!=0); 2337f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet return g_contentSizeFlag; 2347f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet} 2357f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet 236ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinskistatic U32 g_removeSrcFile = 0; 237ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinskivoid LZ4IO_setRemoveSrcFile(unsigned flag) { g_removeSrcFile = (flag>0); } 238ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski 2397f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet 24069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 241d11ac4087254db4b9391039ce862e7305874fe97Yann Collet/* ************************************************************************ ** 242d11ac4087254db4b9391039ce862e7305874fe97Yann Collet** ********************** LZ4 File / Pipe compression ********************* ** 243d11ac4087254db4b9391039ce862e7305874fe97Yann Collet** ************************************************************************ */ 24469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 2457d87d43e619b0296bbe3f1674f10575b3f68c189Yann Colletstatic int LZ4IO_GetBlockSize_FromBlockId (int id) { return (1 << (8 + (2 * id))); } 2467d87d43e619b0296bbe3f1674f10575b3f68c189Yann Colletstatic int LZ4IO_isSkippableMagicNumber(unsigned int magic) { return (magic & LZ4IO_SKIPPABLEMASK) == LZ4IO_SKIPPABLE0; } 24769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 24869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 249f34808e4ae183d049e5e13949941d44876fdb90cYann Collet/** LZ4IO_openSrcFile() : 250f34808e4ae183d049e5e13949941d44876fdb90cYann Collet * condition : `dstFileName` must be non-NULL. 251f34808e4ae183d049e5e13949941d44876fdb90cYann Collet * @result : FILE* to `dstFileName`, or NULL if it fails */ 252f34808e4ae183d049e5e13949941d44876fdb90cYann Colletstatic FILE* LZ4IO_openSrcFile(const char* srcFileName) 253f34808e4ae183d049e5e13949941d44876fdb90cYann Collet{ 254f34808e4ae183d049e5e13949941d44876fdb90cYann Collet FILE* f; 25569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 256f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (!strcmp (srcFileName, stdinmark)) { 257f34808e4ae183d049e5e13949941d44876fdb90cYann Collet DISPLAYLEVEL(4,"Using stdin for input\n"); 258f34808e4ae183d049e5e13949941d44876fdb90cYann Collet f = stdin; 259f34808e4ae183d049e5e13949941d44876fdb90cYann Collet SET_BINARY_MODE(stdin); 260f34808e4ae183d049e5e13949941d44876fdb90cYann Collet } else { 261f34808e4ae183d049e5e13949941d44876fdb90cYann Collet f = fopen(srcFileName, "rb"); 2625b37837e6e872bb57c8c7d07d6d4ff94176b8c59Nick Terrell if ( f==NULL ) DISPLAYLEVEL(1, "%s: %s \n", srcFileName, strerror(errno)); 263c64200dd85a85d9cc69a6fda682362d851be863bYann Collet } 264c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 265f34808e4ae183d049e5e13949941d44876fdb90cYann Collet return f; 266f34808e4ae183d049e5e13949941d44876fdb90cYann Collet} 267f34808e4ae183d049e5e13949941d44876fdb90cYann Collet 268f34808e4ae183d049e5e13949941d44876fdb90cYann Collet/** FIO_openDstFile() : 269f34808e4ae183d049e5e13949941d44876fdb90cYann Collet * condition : `dstFileName` must be non-NULL. 270f34808e4ae183d049e5e13949941d44876fdb90cYann Collet * @result : FILE* to `dstFileName`, or NULL if it fails */ 271f34808e4ae183d049e5e13949941d44876fdb90cYann Colletstatic FILE* LZ4IO_openDstFile(const char* dstFileName) 272f34808e4ae183d049e5e13949941d44876fdb90cYann Collet{ 273f34808e4ae183d049e5e13949941d44876fdb90cYann Collet FILE* f; 274fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet 275f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (!strcmp (dstFileName, stdoutmark)) { 276f34808e4ae183d049e5e13949941d44876fdb90cYann Collet DISPLAYLEVEL(4,"Using stdout for output\n"); 277f34808e4ae183d049e5e13949941d44876fdb90cYann Collet f = stdout; 27869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. SET_BINARY_MODE(stdout); 279d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (g_sparseFileSupport==1) { 280acae59a73969f436f95ed31130efe0ee9f7b3e48Yann Collet g_sparseFileSupport = 0; 281acae59a73969f436f95ed31130efe0ee9f7b3e48Yann Collet DISPLAYLEVEL(4, "Sparse File Support is automatically disabled on stdout ; try --sparse \n"); 282acae59a73969f436f95ed31130efe0ee9f7b3e48Yann Collet } 283d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet } else { 284f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (!g_overwrite && strcmp (dstFileName, nulmark)) { /* Check if destination file already exists */ 285f34808e4ae183d049e5e13949941d44876fdb90cYann Collet f = fopen( dstFileName, "rb" ); 286f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (f != NULL) { /* dest exists, prompt for overwrite authorization */ 287f34808e4ae183d049e5e13949941d44876fdb90cYann Collet fclose(f); 288f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (g_displayLevel <= 1) { /* No interaction possible */ 2895b37837e6e872bb57c8c7d07d6d4ff94176b8c59Nick Terrell DISPLAY("%s already exists; not overwritten \n", dstFileName); 290f34808e4ae183d049e5e13949941d44876fdb90cYann Collet return NULL; 291f34808e4ae183d049e5e13949941d44876fdb90cYann Collet } 2925b37837e6e872bb57c8c7d07d6d4ff94176b8c59Nick Terrell DISPLAY("%s already exists; do you wish to overwrite (y/N) ? ", dstFileName); 293f34808e4ae183d049e5e13949941d44876fdb90cYann Collet { int ch = getchar(); 294f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if ((ch!='Y') && (ch!='y')) { 295f34808e4ae183d049e5e13949941d44876fdb90cYann Collet DISPLAY(" not overwritten \n"); 296f34808e4ae183d049e5e13949941d44876fdb90cYann Collet return NULL; 297f34808e4ae183d049e5e13949941d44876fdb90cYann Collet } 298f34808e4ae183d049e5e13949941d44876fdb90cYann Collet while ((ch!=EOF) && (ch!='\n')) ch = getchar(); /* flush rest of input line */ 299f34808e4ae183d049e5e13949941d44876fdb90cYann Collet } } } 300f34808e4ae183d049e5e13949941d44876fdb90cYann Collet f = fopen( dstFileName, "wb" ); 3015b37837e6e872bb57c8c7d07d6d4ff94176b8c59Nick Terrell if (f==NULL) DISPLAYLEVEL(1, "%s: %s\n", dstFileName, strerror(errno)); 30269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. } 30369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 304f34808e4ae183d049e5e13949941d44876fdb90cYann Collet /* sparse file */ 305767a23160b746f3f34e865c5a09bb0a7d4e5bf7cPrzemyslaw Skibinski if (f && g_sparseFileSupport) { SET_SPARSE_FILE_MODE(f); } 30669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 307f34808e4ae183d049e5e13949941d44876fdb90cYann Collet return f; 30869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 30969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 31069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 3116de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet 3126de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet/*************************************** 313d11ac4087254db4b9391039ce862e7305874fe97Yann Collet* Legacy Compression 314d11ac4087254db4b9391039ce862e7305874fe97Yann Collet***************************************/ 3156de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet 3166de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet/* unoptimized version; solves endianess & alignment issues */ 3176de52c2a8c40b7381e364ad87af9e80a60d95229Yann Colletstatic void LZ4IO_writeLE32 (void* p, unsigned value32) 3186de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet{ 319ceec6fa8492a5ff0ed163c96516716a3c2b09461Yann Collet unsigned char* dstPtr = (unsigned char*)p; 3206de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet dstPtr[0] = (unsigned char)value32; 3216de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet dstPtr[1] = (unsigned char)(value32 >> 8); 3226de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet dstPtr[2] = (unsigned char)(value32 >> 16); 3236de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet dstPtr[3] = (unsigned char)(value32 >> 24); 3246de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet} 3256de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet 326b805d581b97be95fcc000134a54aa7c591b3ef09Yann Colletstatic int LZ4IO_LZ4_compress(const char* src, char* dst, int srcSize, int dstSize, int cLevel) 327b805d581b97be95fcc000134a54aa7c591b3ef09Yann Collet{ 328b805d581b97be95fcc000134a54aa7c591b3ef09Yann Collet (void)cLevel; 3291b17bf2ab8cf66dd2b740eca376e2d46f7ad7041Yann Collet return LZ4_compress_fast(src, dst, srcSize, dstSize, 1); 330b805d581b97be95fcc000134a54aa7c591b3ef09Yann Collet} 331b805d581b97be95fcc000134a54aa7c591b3ef09Yann Collet 3326de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet/* LZ4IO_compressFilename_Legacy : 3336de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet * This function is intentionally "hidden" (not published in .h) 3346de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet * It generates compressed streams using the old 'legacy' format */ 335488029ec3b23b1e00a69f1ac3fcdd49d24cb7d3fYann Colletint LZ4IO_compressFilename_Legacy(const char* input_filename, const char* output_filename, int compressionlevel) 33669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 337b805d581b97be95fcc000134a54aa7c591b3ef09Yann Collet int (*compressionFunction)(const char* src, char* dst, int srcSize, int dstSize, int cLevel); 33869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. unsigned long long filesize = 0; 33969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. unsigned long long compressedfilesize = MAGICNUMBER_SIZE; 34069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. char* in_buff; 34169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. char* out_buff; 342f11afafe234ea45a6d80f8b21df1d603ace4e025Yann Collet const int outBuffSize = LZ4_compressBound(LEGACY_BLOCKSIZE); 34369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. FILE* finput; 34469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. FILE* foutput; 345d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet clock_t end; 34669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 3478a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Init */ 348d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet clock_t const start = clock(); 349e05088d0eb500d8d673e081929620e538df3d718Yann Collet if (compressionlevel < 3) compressionFunction = LZ4IO_LZ4_compress; else compressionFunction = LZ4_compress_HC; 3506de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet 351f34808e4ae183d049e5e13949941d44876fdb90cYann Collet finput = LZ4IO_openSrcFile(input_filename); 352f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (finput == NULL) EXM_THROW(20, "%s : open file error ", input_filename); 353f34808e4ae183d049e5e13949941d44876fdb90cYann Collet foutput = LZ4IO_openDstFile(output_filename); 354f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (foutput == NULL) { fclose(finput); EXM_THROW(20, "%s : open file error ", input_filename); } 35569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 3568a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Allocate Memory */ 35769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. in_buff = (char*)malloc(LEGACY_BLOCKSIZE); 358f11afafe234ea45a6d80f8b21df1d603ace4e025Yann Collet out_buff = (char*)malloc(outBuffSize); 35969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. if (!in_buff || !out_buff) EXM_THROW(21, "Allocation error : not enough memory"); 36069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 3618a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Write Archive Header */ 3626de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet LZ4IO_writeLE32(out_buff, LEGACY_MAGICNUMBER); 363d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { size_t const sizeCheck = fwrite(out_buff, 1, MAGICNUMBER_SIZE, foutput); 364d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (sizeCheck!=MAGICNUMBER_SIZE) EXM_THROW(22, "Write error : cannot write header"); } 36569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 3668a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Main Loop */ 367d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet while (1) { 36869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. unsigned int outSize; 3698a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Read Block */ 370c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet size_t const inSize = (int) fread(in_buff, (size_t)1, (size_t)LEGACY_BLOCKSIZE, finput); 371c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet if (inSize == 0) break; 372c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet if (inSize > LEGACY_BLOCKSIZE) EXM_THROW(23, "Read error : wrong fread() size report "); /* should be impossible */ 37369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. filesize += inSize; 37469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 3758a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Compress Block */ 37646b49af37c62225c02098a3150d63a63fb0554aeYann Collet outSize = compressionFunction(in_buff, out_buff+4, (int)inSize, outBuffSize, compressionlevel); 37769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. compressedfilesize += outSize+4; 378f11afafe234ea45a6d80f8b21df1d603ace4e025Yann Collet DISPLAYUPDATE(2, "\rRead : %i MB ==> %.2f%% ", (int)(filesize>>20), (double)compressedfilesize/filesize*100); 37969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 3808a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Write Block */ 3816de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet LZ4IO_writeLE32(out_buff, outSize); 382d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { size_t const sizeCheck = fwrite(out_buff, 1, outSize+4, foutput); 383c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet if (sizeCheck!=(size_t)(outSize+4)) EXM_THROW(24, "Write error : cannot write compressed block"); 384d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet } } 385c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet if (ferror(finput)) EXM_THROW(25, "Error while reading %s ", input_filename); 38669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 3878a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Status */ 38869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. end = clock(); 389d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (end==start) end+=1; /* avoid division by zero (speed) */ 390d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet filesize += !filesize; /* avoid division by zero (ratio) */ 391d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet DISPLAYLEVEL(2, "\r%79s\r", ""); /* blank line */ 39269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. DISPLAYLEVEL(2,"Compressed %llu bytes into %llu bytes ==> %.2f%%\n", 393d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet filesize, compressedfilesize, (double)compressedfilesize / filesize * 100); 394d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { double const seconds = (double)(end - start) / CLOCKS_PER_SEC; 39569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. DISPLAYLEVEL(4,"Done in %.2f s ==> %.2f MB/s\n", seconds, (double)filesize / seconds / 1024 / 1024); 39669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. } 39769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 3988a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Close & Free */ 39969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. free(in_buff); 40069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. free(out_buff); 40169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. fclose(finput); 40269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. fclose(foutput); 40369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 40469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. return 0; 40569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 40669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 40769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 408d11ac4087254db4b9391039ce862e7305874fe97Yann Collet/********************************************* 409d11ac4087254db4b9391039ce862e7305874fe97Yann Collet* Compression using Frame format 410d11ac4087254db4b9391039ce862e7305874fe97Yann Collet*********************************************/ 41169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 412c64200dd85a85d9cc69a6fda682362d851be863bYann Collettypedef struct { 413348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet void* srcBuffer; 414c64200dd85a85d9cc69a6fda682362d851be863bYann Collet size_t srcBufferSize; 415348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet void* dstBuffer; 416c64200dd85a85d9cc69a6fda682362d851be863bYann Collet size_t dstBufferSize; 417c64200dd85a85d9cc69a6fda682362d851be863bYann Collet LZ4F_compressionContext_t ctx; 418348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet} cRess_t; 419c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 420348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Colletstatic cRess_t LZ4IO_createCResources(void) 421348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet{ 422348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet const size_t blockSize = (size_t)LZ4IO_GetBlockSize_FromBlockId (g_blockSizeId); 423348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet cRess_t ress; 424c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 425d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet LZ4F_errorCode_t const errorCode = LZ4F_createCompressionContext(&(ress.ctx), LZ4F_VERSION); 426348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet if (LZ4F_isError(errorCode)) EXM_THROW(30, "Allocation error : can't create LZ4F context : %s", LZ4F_getErrorName(errorCode)); 427348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet 428348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet /* Allocate Memory */ 429348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet ress.srcBuffer = malloc(blockSize); 430348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet ress.srcBufferSize = blockSize; 431e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet ress.dstBufferSize = LZ4F_compressFrameBound(blockSize, NULL); /* cover worst case */ 432348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet ress.dstBuffer = malloc(ress.dstBufferSize); 433348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet if (!ress.srcBuffer || !ress.dstBuffer) EXM_THROW(31, "Allocation error : not enough memory"); 434348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet 435348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet return ress; 436348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet} 437348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet 438348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Colletstatic void LZ4IO_freeCResources(cRess_t ress) 439348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet{ 440348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet free(ress.srcBuffer); 441348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet free(ress.dstBuffer); 442d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { LZ4F_errorCode_t const errorCode = LZ4F_freeCompressionContext(ress.ctx); 443d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (LZ4F_isError(errorCode)) EXM_THROW(38, "Error : can't free LZ4F context resource : %s", LZ4F_getErrorName(errorCode)); } 444348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet} 445348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet 446d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet/* 447d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet * LZ4IO_compressFilename_extRess() 448d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet * result : 0 : compression completed correctly 449d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet * 1 : missing or pb opening srcFileName 450d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet */ 451e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Colletstatic int LZ4IO_compressFilename_extRess(cRess_t ress, const char* srcFileName, const char* dstFileName, int compressionLevel) 45269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 45369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. unsigned long long filesize = 0; 45469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. unsigned long long compressedfilesize = 0; 455348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet FILE* srcFile; 456348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet FILE* dstFile; 457c64200dd85a85d9cc69a6fda682362d851be863bYann Collet void* const srcBuffer = ress.srcBuffer; 458c64200dd85a85d9cc69a6fda682362d851be863bYann Collet void* const dstBuffer = ress.dstBuffer; 459c64200dd85a85d9cc69a6fda682362d851be863bYann Collet const size_t dstBufferSize = ress.dstBufferSize; 460c64200dd85a85d9cc69a6fda682362d851be863bYann Collet const size_t blockSize = (size_t)LZ4IO_GetBlockSize_FromBlockId (g_blockSizeId); 461c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet size_t readSize; 462c64200dd85a85d9cc69a6fda682362d851be863bYann Collet LZ4F_compressionContext_t ctx = ress.ctx; /* just a pointer */ 463ceec6fa8492a5ff0ed163c96516716a3c2b09461Yann Collet LZ4F_preferences_t prefs; 46469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 4658a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Init */ 466f34808e4ae183d049e5e13949941d44876fdb90cYann Collet srcFile = LZ4IO_openSrcFile(srcFileName); 467f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (srcFile == NULL) return 1; 468f34808e4ae183d049e5e13949941d44876fdb90cYann Collet dstFile = LZ4IO_openDstFile(dstFileName); 469f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (dstFile == NULL) { fclose(srcFile); return 1; } 470ceec6fa8492a5ff0ed163c96516716a3c2b09461Yann Collet memset(&prefs, 0, sizeof(prefs)); 47169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 472348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet 4738a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Set compression parameters */ 4746de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet prefs.autoFlush = 1; 475348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet prefs.compressionLevel = compressionLevel; 476081bcca33bba4f6ac3e913b3cf2bc2ba58b6b697Takayuki MATSUOKA prefs.frameInfo.blockMode = (LZ4F_blockMode_t)g_blockIndependence; 477081bcca33bba4f6ac3e913b3cf2bc2ba58b6b697Takayuki MATSUOKA prefs.frameInfo.blockSizeID = (LZ4F_blockSizeID_t)g_blockSizeId; 478081bcca33bba4f6ac3e913b3cf2bc2ba58b6b697Takayuki MATSUOKA prefs.frameInfo.contentChecksumFlag = (LZ4F_contentChecksum_t)g_streamChecksum; 479d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (g_contentSizeFlag) { 480ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski U64 const fileSize = UTIL_getFileSize(srcFileName); 481d5da787c1bd92a22c87b6428321668548155995fYann Collet prefs.frameInfo.contentSize = fileSize; /* == 0 if input == stdin */ 48290c0104c4eaf8f06932990aacf07e60dd21685b9Yann Collet if (fileSize==0) 483d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet DISPLAYLEVEL(3, "Warning : cannot determine input content size \n"); 4847f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet } 4856de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet 4868a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* read first block */ 487e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet readSize = fread(srcBuffer, (size_t)1, blockSize, srcFile); 48800c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (ferror(srcFile)) EXM_THROW(30, "Error reading %s ", srcFileName); 4896de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet filesize += readSize; 49069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 491e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet /* single-block file */ 492d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (readSize < blockSize) { 493e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet /* Compress in single pass */ 494d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet size_t const cSize = LZ4F_compressFrame(dstBuffer, dstBufferSize, srcBuffer, readSize, &prefs); 49500c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (LZ4F_isError(cSize)) EXM_THROW(31, "Compression failed : %s", LZ4F_getErrorName(cSize)); 496d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet compressedfilesize = cSize; 4972ed9dcc900a8a662a52d11968baf27f61a9bedd3Yann Collet DISPLAYUPDATE(2, "\rRead : %u MB ==> %.2f%% ", 4982ed9dcc900a8a662a52d11968baf27f61a9bedd3Yann Collet (unsigned)(filesize>>20), (double)compressedfilesize/(filesize+!filesize)*100); /* avoid division by zero */ 49969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 5008a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Write Block */ 501d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { size_t const sizeCheck = fwrite(dstBuffer, 1, cSize, dstFile); 50200c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (sizeCheck!=cSize) EXM_THROW(32, "Write error : cannot write compressed block"); 503d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet } } 50469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 505e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet else 506e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet 507e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet /* multiple-blocks file */ 508e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet { 509e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet /* Write Archive Header */ 510c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet size_t headerSize = LZ4F_compressBegin(ctx, dstBuffer, dstBufferSize, &prefs); 51100c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (LZ4F_isError(headerSize)) EXM_THROW(33, "File header generation failed : %s", LZ4F_getErrorName(headerSize)); 512d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { size_t const sizeCheck = fwrite(dstBuffer, 1, headerSize, dstFile); 51300c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (sizeCheck!=headerSize) EXM_THROW(34, "Write error : cannot write header"); } 514e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet compressedfilesize += headerSize; 515e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet 516e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet /* Main Loop */ 517d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet while (readSize>0) { 518e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet size_t outSize; 519e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet 520e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet /* Compress Block */ 521e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet outSize = LZ4F_compressUpdate(ctx, dstBuffer, dstBufferSize, srcBuffer, readSize, NULL); 52200c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (LZ4F_isError(outSize)) EXM_THROW(35, "Compression failed : %s", LZ4F_getErrorName(outSize)); 523e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet compressedfilesize += outSize; 524e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet DISPLAYUPDATE(2, "\rRead : %u MB ==> %.2f%% ", (unsigned)(filesize>>20), (double)compressedfilesize/filesize*100); 525e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet 526e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet /* Write Block */ 527d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { size_t const sizeCheck = fwrite(dstBuffer, 1, outSize, dstFile); 52800c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (sizeCheck!=outSize) EXM_THROW(36, "Write error : cannot write compressed block"); } 529e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet 530e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet /* Read next block */ 531e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet readSize = fread(srcBuffer, (size_t)1, (size_t)blockSize, srcFile); 532e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet filesize += readSize; 533e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet } 53400c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (ferror(srcFile)) EXM_THROW(37, "Error reading %s ", srcFileName); 535e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet 536e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet /* End of Stream mark */ 537e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet headerSize = LZ4F_compressEnd(ctx, dstBuffer, dstBufferSize, NULL); 53800c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (LZ4F_isError(headerSize)) EXM_THROW(38, "End of file generation failed : %s", LZ4F_getErrorName(headerSize)); 5396de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet 540d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { size_t const sizeCheck = fwrite(dstBuffer, 1, headerSize, dstFile); 54100c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (sizeCheck!=headerSize) EXM_THROW(39, "Write error : cannot write end of stream"); } 542e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet compressedfilesize += headerSize; 543e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet } 54469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 545348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet /* Release files */ 546348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet fclose (srcFile); 547348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet fclose (dstFile); 548348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet 54998be008479486f60b0a98289eee2f57c28650964Przemyslaw Skibinski /* Copy owner, file permissions and modification time */ 550ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski { stat_t statbuf; 551ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski if (strcmp (srcFileName, stdinmark) && strcmp (dstFileName, stdoutmark) && UTIL_getFileStat(srcFileName, &statbuf)) 552ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski UTIL_setFileStat(dstFileName, &statbuf); 553ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski } 554ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski 55500c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (g_removeSrcFile) { if (remove(srcFileName)) EXM_THROW(40, "Remove error : %s: %s", srcFileName, strerror(errno)); } /* remove source file : --rm */ 55698be008479486f60b0a98289eee2f57c28650964Przemyslaw Skibinski 5578a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Final Status */ 55869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. DISPLAYLEVEL(2, "\r%79s\r", ""); 559d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet DISPLAYLEVEL(2, "Compressed %llu bytes into %llu bytes ==> %.2f%%\n", 560d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet filesize, compressedfilesize, (double)compressedfilesize/(filesize + !filesize)*100); /* avoid division by zero */ 56169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 56269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. return 0; 56369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 56469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 56569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 566348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Colletint LZ4IO_compressFilename(const char* srcFileName, const char* dstFileName, int compressionLevel) 567488029ec3b23b1e00a69f1ac3fcdd49d24cb7d3fYann Collet{ 568d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet clock_t const start = clock(); 569d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet cRess_t const ress = LZ4IO_createCResources(); 570c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 571d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet int const issueWithSrcFile = LZ4IO_compressFilename_extRess(ress, srcFileName, dstFileName, compressionLevel); 572c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 573348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet /* Free resources */ 574348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet LZ4IO_freeCResources(ress); 575c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 576c64200dd85a85d9cc69a6fda682362d851be863bYann Collet /* Final Status */ 577d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { clock_t const end = clock(); 578d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet double const seconds = (double)(end - start) / CLOCKS_PER_SEC; 579c64200dd85a85d9cc69a6fda682362d851be863bYann Collet DISPLAYLEVEL(4, "Completed in %.2f sec \n", seconds); 580488029ec3b23b1e00a69f1ac3fcdd49d24cb7d3fYann Collet } 581c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 582348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet return issueWithSrcFile; 583488029ec3b23b1e00a69f1ac3fcdd49d24cb7d3fYann Collet} 584488029ec3b23b1e00a69f1ac3fcdd49d24cb7d3fYann Collet 585c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 586c64200dd85a85d9cc69a6fda682362d851be863bYann Collet#define FNSPACE 30 587c64200dd85a85d9cc69a6fda682362d851be863bYann Colletint LZ4IO_compressMultipleFilenames(const char** inFileNamesTable, int ifntSize, const char* suffix, int compressionLevel) 5880169502b49dfa5eb8878f5c85be3270012266fc3Kyle J Harper{ 5890169502b49dfa5eb8878f5c85be3270012266fc3Kyle J Harper int i; 590d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet int missed_files = 0; 591d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet char* dstFileName = (char*)malloc(FNSPACE); 5920169502b49dfa5eb8878f5c85be3270012266fc3Kyle J Harper size_t ofnSize = FNSPACE; 593cc2412401400fbacd7530b8dcc4af0b0d7c734ceYann Collet const size_t suffixSize = strlen(suffix); 594d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet cRess_t const ress = LZ4IO_createCResources(); 595c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 596de0cf5de640eb56775f44c0f4c7c7a065e00447cPrzemyslaw Skibinski if (dstFileName == NULL) return ifntSize; /* not enough memory */ 597de0cf5de640eb56775f44c0f4c7c7a065e00447cPrzemyslaw Skibinski 598c64200dd85a85d9cc69a6fda682362d851be863bYann Collet /* loop on each file */ 599d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet for (i=0; i<ifntSize; i++) { 600d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet size_t const ifnSize = strlen(inFileNamesTable[i]); 6011833be1cf0e545f8b24bb4a786e274a9e419e280Przemyslaw Skibinski if (ofnSize <= ifnSize+suffixSize+1) { free(dstFileName); ofnSize = ifnSize + 20; dstFileName = (char*)malloc(ofnSize); if (dstFileName==NULL) { LZ4IO_freeCResources(ress); return ifntSize; } } 602d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet strcpy(dstFileName, inFileNamesTable[i]); 603d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet strcat(dstFileName, suffix); 604c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 605d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet missed_files += LZ4IO_compressFilename_extRess(ress, inFileNamesTable[i], dstFileName, compressionLevel); 6060169502b49dfa5eb8878f5c85be3270012266fc3Kyle J Harper } 607c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 608c64200dd85a85d9cc69a6fda682362d851be863bYann Collet /* Close & Free */ 609348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet LZ4IO_freeCResources(ress); 610d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet free(dstFileName); 611c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 612d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet return missed_files; 6130169502b49dfa5eb8878f5c85be3270012266fc3Kyle J Harper} 614488029ec3b23b1e00a69f1ac3fcdd49d24cb7d3fYann Collet 615c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 61669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* ********************************************************************* */ 617488029ec3b23b1e00a69f1ac3fcdd49d24cb7d3fYann Collet/* ********************** LZ4 file-stream Decompression **************** */ 61869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* ********************************************************************* */ 61969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 6206de52c2a8c40b7381e364ad87af9e80a60d95229Yann Colletstatic unsigned LZ4IO_readLE32 (const void* s) 6216de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet{ 622d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet const unsigned char* const srcPtr = (const unsigned char*)s; 6236de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet unsigned value32 = srcPtr[0]; 6246de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet value32 += (srcPtr[1]<<8); 6256de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet value32 += (srcPtr[2]<<16); 626c64200dd85a85d9cc69a6fda682362d851be863bYann Collet value32 += ((unsigned)srcPtr[3])<<24; 6276de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet return value32; 6286de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet} 6296de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet 6301abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet#define sizeT sizeof(size_t) 6311abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet#define maskT (sizeT - 1) 6321abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet 633113b150f0aeb3512b2850a65a824ad87f605187eYann Colletstatic unsigned LZ4IO_fwriteSparse(FILE* file, const void* buffer, size_t bufferSize, unsigned storedSkips) 634113b150f0aeb3512b2850a65a824ad87f605187eYann Collet{ 6351c3e633c48766c58df949887297dc5838170a33fYann Collet const size_t* const bufferT = (const size_t*)buffer; /* Buffer is supposed malloc'ed, hence aligned on size_t */ 6361c3e633c48766c58df949887297dc5838170a33fYann Collet const size_t* ptrT = bufferT; 6371abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet size_t bufferSizeT = bufferSize / sizeT; 6381c3e633c48766c58df949887297dc5838170a33fYann Collet const size_t* const bufferTEnd = bufferT + bufferSizeT; 639113b150f0aeb3512b2850a65a824ad87f605187eYann Collet static const size_t segmentSizeT = (32 KB) / sizeT; 640113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 641d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (!g_sparseFileSupport) { /* normal write */ 642d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet size_t const sizeCheck = fwrite(buffer, 1, bufferSize, file); 64358b5aadb1fc5d937e81c8f33e0e8290f2097c6bbYann Collet if (sizeCheck != bufferSize) EXM_THROW(70, "Write error : cannot write decoded block"); 644113b150f0aeb3512b2850a65a824ad87f605187eYann Collet return 0; 645113b150f0aeb3512b2850a65a824ad87f605187eYann Collet } 646113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 647113b150f0aeb3512b2850a65a824ad87f605187eYann Collet /* avoid int overflow */ 648d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (storedSkips > 1 GB) { 649d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet int const seekResult = fseek(file, 1 GB, SEEK_CUR); 65058b5aadb1fc5d937e81c8f33e0e8290f2097c6bbYann Collet if (seekResult != 0) EXM_THROW(71, "1 GB skip error (sparse file support)"); 651113b150f0aeb3512b2850a65a824ad87f605187eYann Collet storedSkips -= 1 GB; 652113b150f0aeb3512b2850a65a824ad87f605187eYann Collet } 653113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 654d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet while (ptrT < bufferTEnd) { 655113b150f0aeb3512b2850a65a824ad87f605187eYann Collet size_t seg0SizeT = segmentSizeT; 656113b150f0aeb3512b2850a65a824ad87f605187eYann Collet size_t nb0T; 657113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 658113b150f0aeb3512b2850a65a824ad87f605187eYann Collet /* count leading zeros */ 659113b150f0aeb3512b2850a65a824ad87f605187eYann Collet if (seg0SizeT > bufferSizeT) seg0SizeT = bufferSizeT; 660113b150f0aeb3512b2850a65a824ad87f605187eYann Collet bufferSizeT -= seg0SizeT; 661113b150f0aeb3512b2850a65a824ad87f605187eYann Collet for (nb0T=0; (nb0T < seg0SizeT) && (ptrT[nb0T] == 0); nb0T++) ; 662113b150f0aeb3512b2850a65a824ad87f605187eYann Collet storedSkips += (unsigned)(nb0T * sizeT); 663113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 664d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (nb0T != seg0SizeT) { /* not all 0s */ 665d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet int const seekResult = fseek(file, storedSkips, SEEK_CUR); 666acae59a73969f436f95ed31130efe0ee9f7b3e48Yann Collet if (seekResult) EXM_THROW(72, "Sparse skip error ; try --no-sparse"); 667113b150f0aeb3512b2850a65a824ad87f605187eYann Collet storedSkips = 0; 668113b150f0aeb3512b2850a65a824ad87f605187eYann Collet seg0SizeT -= nb0T; 669113b150f0aeb3512b2850a65a824ad87f605187eYann Collet ptrT += nb0T; 670d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { size_t const sizeCheck = fwrite(ptrT, sizeT, seg0SizeT, file); 671d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (sizeCheck != seg0SizeT) EXM_THROW(73, "Write error : cannot write decoded block"); 672d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet } } 673113b150f0aeb3512b2850a65a824ad87f605187eYann Collet ptrT += seg0SizeT; 674113b150f0aeb3512b2850a65a824ad87f605187eYann Collet } 675113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 676d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (bufferSize & maskT) { /* size not multiple of sizeT : implies end of block */ 6771c3e633c48766c58df949887297dc5838170a33fYann Collet const char* const restStart = (const char*)bufferTEnd; 678113b150f0aeb3512b2850a65a824ad87f605187eYann Collet const char* restPtr = restStart; 679d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet size_t const restSize = bufferSize & maskT; 680113b150f0aeb3512b2850a65a824ad87f605187eYann Collet const char* const restEnd = restStart + restSize; 681113b150f0aeb3512b2850a65a824ad87f605187eYann Collet for (; (restPtr < restEnd) && (*restPtr == 0); restPtr++) ; 682113b150f0aeb3512b2850a65a824ad87f605187eYann Collet storedSkips += (unsigned) (restPtr - restStart); 683d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (restPtr != restEnd) { 684d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet int const seekResult = fseek(file, storedSkips, SEEK_CUR); 685acae59a73969f436f95ed31130efe0ee9f7b3e48Yann Collet if (seekResult) EXM_THROW(74, "Sparse skip error ; try --no-sparse"); 686113b150f0aeb3512b2850a65a824ad87f605187eYann Collet storedSkips = 0; 687d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { size_t const sizeCheck = fwrite(restPtr, 1, restEnd - restPtr, file); 688d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (sizeCheck != (size_t)(restEnd - restPtr)) EXM_THROW(75, "Write error : cannot write decoded end of block"); 689d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet } } 690113b150f0aeb3512b2850a65a824ad87f605187eYann Collet } 691113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 692113b150f0aeb3512b2850a65a824ad87f605187eYann Collet return storedSkips; 693113b150f0aeb3512b2850a65a824ad87f605187eYann Collet} 694113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 695113b150f0aeb3512b2850a65a824ad87f605187eYann Colletstatic void LZ4IO_fwriteSparseEnd(FILE* file, unsigned storedSkips) 696113b150f0aeb3512b2850a65a824ad87f605187eYann Collet{ 697f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (storedSkips>0) { /* implies g_sparseFileSupport>0 */ 698d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet int const seekResult = fseek(file, storedSkips-1, SEEK_CUR); 699113b150f0aeb3512b2850a65a824ad87f605187eYann Collet if (seekResult != 0) EXM_THROW(69, "Final skip error (sparse file)\n"); 700d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { const char lastZeroByte[1] = { 0 }; 701d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet size_t const sizeCheck = fwrite(lastZeroByte, 1, 1, file); 702d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (sizeCheck != 1) EXM_THROW(69, "Write error : cannot write last zero\n"); 703d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet } } 704113b150f0aeb3512b2850a65a824ad87f605187eYann Collet} 705113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 706113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 70762ed15319570d80690915f0d0dba0dc2e9478631Yann Colletstatic unsigned g_magicRead = 0; 708113b150f0aeb3512b2850a65a824ad87f605187eYann Colletstatic unsigned long long LZ4IO_decodeLegacyStream(FILE* finput, FILE* foutput) 70969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 71069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. unsigned long long filesize = 0; 71169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. char* in_buff; 71269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. char* out_buff; 713113b150f0aeb3512b2850a65a824ad87f605187eYann Collet unsigned storedSkips = 0; 71469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 7158a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Allocate Memory */ 71669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. in_buff = (char*)malloc(LZ4_compressBound(LEGACY_BLOCKSIZE)); 71769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. out_buff = (char*)malloc(LEGACY_BLOCKSIZE); 71869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. if (!in_buff || !out_buff) EXM_THROW(51, "Allocation error : not enough memory"); 71969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 7208a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Main Loop */ 721d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet while (1) { 72269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. int decodeSize; 723c5decf7562a3b4065922ae6460b7785eb91366f8Yann Collet unsigned int blockSize; 72469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 7258a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Block Size */ 7261abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet { size_t const sizeCheck = fread(in_buff, 1, 4, finput); 7271abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet if (sizeCheck == 0) break; /* Nothing to read : file read is completed */ 7281abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet if (sizeCheck != 4) EXM_THROW(52, "Read error : cannot access block size "); } 7291abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet blockSize = LZ4IO_readLE32(in_buff); /* Convert to Little Endian */ 7301abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet if (blockSize > LZ4_COMPRESSBOUND(LEGACY_BLOCKSIZE)) { 731d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet /* Cannot read next block : maybe new stream ? */ 73262ed15319570d80690915f0d0dba0dc2e9478631Yann Collet g_magicRead = blockSize; 73369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. break; 73469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. } 73569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 7368a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Read Block */ 737f17302769055ad0c4b2e10e3de544f6593865e89Yann Collet { size_t const sizeCheck = fread(in_buff, 1, blockSize, finput); 738f17302769055ad0c4b2e10e3de544f6593865e89Yann Collet if (sizeCheck!=blockSize) EXM_THROW(52, "Read error : cannot access compressed block !"); } 73969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 7408a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Decode Block */ 74169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. decodeSize = LZ4_decompress_safe(in_buff, out_buff, blockSize, LEGACY_BLOCKSIZE); 74245b0642bf54718d2b57dd61cb606b154afc0ab26Yann Collet if (decodeSize < 0) EXM_THROW(53, "Decoding Failed ! Corrupted input detected !"); 74369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. filesize += decodeSize; 74469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 7458a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Write Block */ 746113b150f0aeb3512b2850a65a824ad87f605187eYann Collet storedSkips = LZ4IO_fwriteSparse(foutput, out_buff, decodeSize, storedSkips); 74769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. } 748c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet if (ferror(finput)) EXM_THROW(54, "Read error : ferror"); 74969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 750113b150f0aeb3512b2850a65a824ad87f605187eYann Collet LZ4IO_fwriteSparseEnd(foutput, storedSkips); 751113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 7528a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Free */ 75369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. free(in_buff); 75469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. free(out_buff); 75569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 75669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. return filesize; 75769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 75869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 75969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 760113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 761113b150f0aeb3512b2850a65a824ad87f605187eYann Collettypedef struct { 762113b150f0aeb3512b2850a65a824ad87f605187eYann Collet void* srcBuffer; 763113b150f0aeb3512b2850a65a824ad87f605187eYann Collet size_t srcBufferSize; 764113b150f0aeb3512b2850a65a824ad87f605187eYann Collet void* dstBuffer; 765113b150f0aeb3512b2850a65a824ad87f605187eYann Collet size_t dstBufferSize; 766fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet FILE* dstFile; 767113b150f0aeb3512b2850a65a824ad87f605187eYann Collet LZ4F_decompressionContext_t dCtx; 768a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet} dRess_t; 769113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 770a430b859cf552aa43215fe082e15a95c8bda5d6fYann Colletstatic const size_t LZ4IO_dBufferSize = 64 KB; 771a430b859cf552aa43215fe082e15a95c8bda5d6fYann Colletstatic dRess_t LZ4IO_createDResources(void) 772a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet{ 773a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet dRess_t ress; 774a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 775a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet /* init */ 776d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet LZ4F_errorCode_t const errorCode = LZ4F_createDecompressionContext(&ress.dCtx, LZ4F_VERSION); 777a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet if (LZ4F_isError(errorCode)) EXM_THROW(60, "Can't create LZ4F context : %s", LZ4F_getErrorName(errorCode)); 778a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 779a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet /* Allocate Memory */ 780a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet ress.srcBufferSize = LZ4IO_dBufferSize; 781a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet ress.srcBuffer = malloc(ress.srcBufferSize); 782a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet ress.dstBufferSize = LZ4IO_dBufferSize; 783a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet ress.dstBuffer = malloc(ress.dstBufferSize); 784a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet if (!ress.srcBuffer || !ress.dstBuffer) EXM_THROW(61, "Allocation error : not enough memory"); 785a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 786d2be69b144d6c5fd9a3dcbc4133e93e710cda998Yann Collet ress.dstFile = NULL; 787a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet return ress; 788a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet} 789a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 790a430b859cf552aa43215fe082e15a95c8bda5d6fYann Colletstatic void LZ4IO_freeDResources(dRess_t ress) 791a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet{ 792a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet LZ4F_errorCode_t errorCode = LZ4F_freeDecompressionContext(ress.dCtx); 793a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet if (LZ4F_isError(errorCode)) EXM_THROW(69, "Error : can't free LZ4F context resource : %s", LZ4F_getErrorName(errorCode)); 794a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet free(ress.srcBuffer); 795a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet free(ress.dstBuffer); 796a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet} 797a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 798a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 799a430b859cf552aa43215fe082e15a95c8bda5d6fYann Colletstatic unsigned long long LZ4IO_decompressLZ4F(dRess_t ress, FILE* srcFile, FILE* dstFile) 80069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 80169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. unsigned long long filesize = 0; 802197982ec6cf449734f78d849ed4a845e075b2cf4Yann Collet LZ4F_errorCode_t nextToLoad; 80345a357fd1704e9c6d2d8037277bda62e8c86308eYann Collet unsigned storedSkips = 0; 804d517d609d95bdbab665a6ddb6e018c450d1e5ae6Yann Collet 805d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet /* Init feed with magic number (already consumed from FILE* sFile) */ 806d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { size_t inSize = MAGICNUMBER_SIZE; 807113b150f0aeb3512b2850a65a824ad87f605187eYann Collet size_t outSize= 0; 808113b150f0aeb3512b2850a65a824ad87f605187eYann Collet LZ4IO_writeLE32(ress.srcBuffer, LZ4IO_MAGICNUMBER); 809197982ec6cf449734f78d849ed4a845e075b2cf4Yann Collet nextToLoad = LZ4F_decompress(ress.dCtx, ress.dstBuffer, &outSize, ress.srcBuffer, &inSize, NULL); 810197982ec6cf449734f78d849ed4a845e075b2cf4Yann Collet if (LZ4F_isError(nextToLoad)) EXM_THROW(62, "Header error : %s", LZ4F_getErrorName(nextToLoad)); 8117f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet } 81269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 8137f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet /* Main Loop */ 814d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet for (;nextToLoad;) { 8157f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet size_t readSize; 8167f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet size_t pos = 0; 817197982ec6cf449734f78d849ed4a845e075b2cf4Yann Collet size_t decodedBytes = ress.dstBufferSize; 81869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 8197f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet /* Read input */ 820cbcdd88ccb97632015cf3732b46f8800e62e337bYann Collet if (nextToLoad > ress.srcBufferSize) nextToLoad = ress.srcBufferSize; 821cbcdd88ccb97632015cf3732b46f8800e62e337bYann Collet readSize = fread(ress.srcBuffer, 1, nextToLoad, srcFile); 822d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (!readSize) break; /* reached end of file or stream */ 8237f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet 824d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet while ((pos < readSize) || (decodedBytes == ress.dstBufferSize)) { /* still to read, or still to flush */ 8257f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet /* Decode Input (at least partially) */ 8267f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet size_t remaining = readSize - pos; 827197982ec6cf449734f78d849ed4a845e075b2cf4Yann Collet decodedBytes = ress.dstBufferSize; 828197982ec6cf449734f78d849ed4a845e075b2cf4Yann Collet nextToLoad = LZ4F_decompress(ress.dCtx, ress.dstBuffer, &decodedBytes, (char*)(ress.srcBuffer)+pos, &remaining, NULL); 829197982ec6cf449734f78d849ed4a845e075b2cf4Yann Collet if (LZ4F_isError(nextToLoad)) EXM_THROW(66, "Decompression error : %s", LZ4F_getErrorName(nextToLoad)); 8307f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet pos += remaining; 8317f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet 832d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet /* Write Block */ 833d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (decodedBytes) { 834f094f531441140f10fd461ba769f49d10f5cd581Yann Collet if (!g_testMode) 835f094f531441140f10fd461ba769f49d10f5cd581Yann Collet storedSkips = LZ4IO_fwriteSparse(dstFile, ress.dstBuffer, decodedBytes, storedSkips); 8367f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet filesize += decodedBytes; 83790c0104c4eaf8f06932990aacf07e60dd21685b9Yann Collet DISPLAYUPDATE(2, "\rDecompressed : %u MB ", (unsigned)(filesize>>20)); 83845a357fd1704e9c6d2d8037277bda62e8c86308eYann Collet } 83926065c3f47381c6ebe56ea114015b3c2b1c2a615Yann Collet 84026065c3f47381c6ebe56ea114015b3c2b1c2a615Yann Collet if (!nextToLoad) break; 84112ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet } 84245a357fd1704e9c6d2d8037277bda62e8c86308eYann Collet } 843c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet /* can be out because readSize == 0, which could be an fread() error */ 844c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet if (ferror(srcFile)) EXM_THROW(67, "Read error"); 84545a357fd1704e9c6d2d8037277bda62e8c86308eYann Collet 8461b95d60c66bfc80b77066f929263cf3aac412434Yann Collet if (!g_testMode) LZ4IO_fwriteSparseEnd(dstFile, storedSkips); 847c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet if (nextToLoad!=0) EXM_THROW(68, "Unfinished stream"); 848197982ec6cf449734f78d849ed4a845e075b2cf4Yann Collet 84969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. return filesize; 85069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 85169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 85269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 8531098d897a0c410306f0ac547c4b92e02922f8ddbYann Collet#define PTSIZE (64 KB) 8541098d897a0c410306f0ac547c4b92e02922f8ddbYann Collet#define PTSIZET (PTSIZE / sizeof(size_t)) 855a430b859cf552aa43215fe082e15a95c8bda5d6fYann Colletstatic unsigned long long LZ4IO_passThrough(FILE* finput, FILE* foutput, unsigned char MNstore[MAGICNUMBER_SIZE]) 856e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet{ 8571098d897a0c410306f0ac547c4b92e02922f8ddbYann Collet size_t buffer[PTSIZET]; 858a38cbf9f62a9d7200086b9965745ad7330cac259Yann Collet size_t readBytes = 1; 859e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet unsigned long long total = MAGICNUMBER_SIZE; 860113b150f0aeb3512b2850a65a824ad87f605187eYann Collet unsigned storedSkips = 0; 861e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet 862d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet size_t const sizeCheck = fwrite(MNstore, 1, MAGICNUMBER_SIZE, foutput); 863a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet if (sizeCheck != MAGICNUMBER_SIZE) EXM_THROW(50, "Pass-through write error"); 864e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet 865a38cbf9f62a9d7200086b9965745ad7330cac259Yann Collet while (readBytes) { 866a38cbf9f62a9d7200086b9965745ad7330cac259Yann Collet readBytes = fread(buffer, 1, PTSIZE, finput); 867a38cbf9f62a9d7200086b9965745ad7330cac259Yann Collet total += readBytes; 868a38cbf9f62a9d7200086b9965745ad7330cac259Yann Collet storedSkips = LZ4IO_fwriteSparse(foutput, buffer, readBytes, storedSkips); 869e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet } 870c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet if (ferror(finput)) EXM_THROW(51, "Read Error") 871e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet 872113b150f0aeb3512b2850a65a824ad87f605187eYann Collet LZ4IO_fwriteSparseEnd(foutput, storedSkips); 873e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet return total; 874e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet} 875e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet 876e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet 877d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet/** Safely handle cases when (unsigned)offset > LONG_MAX */ 878d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Colletstatic int fseek_u32(FILE *fp, unsigned offset, int where) 879d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet{ 880d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet const unsigned stepMax = 1U << 30; 881d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet int errorNb = 0; 882d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet 883d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (where != SEEK_CUR) return -1; /* Only allows SEEK_CUR */ 884d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet while (offset > 0) { 885d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet unsigned s = offset; 886d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (s > stepMax) s = stepMax; 887d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet errorNb = fseek(fp, (long) s, SEEK_CUR); 888d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (errorNb != 0) break; 889d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet offset -= s; 890d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet } 891d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet return errorNb; 892d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet} 893d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet 89489d8b98d0dd896dccf6964fa3c6bb6ae6a2349b0Yann Collet#define ENDOFSTREAM ((unsigned long long)-1) 895a430b859cf552aa43215fe082e15a95c8bda5d6fYann Colletstatic unsigned long long selectDecoder(dRess_t ress, FILE* finput, FILE* foutput) 89669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 897a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet unsigned char MNstore[MAGICNUMBER_SIZE]; 898d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet unsigned magicNumber; 899e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet static unsigned nbCalls = 0; 900e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet 901e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet /* init */ 902e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet nbCalls++; 90369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 9048a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Check Archive Header */ 905d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (g_magicRead) { /* magic number already read from finput (see legacy frame)*/ 90662ed15319570d80690915f0d0dba0dc2e9478631Yann Collet magicNumber = g_magicRead; 90762ed15319570d80690915f0d0dba0dc2e9478631Yann Collet g_magicRead = 0; 908d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet } else { 909d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet size_t const nbReadBytes = fread(MNstore, 1, MAGICNUMBER_SIZE, finput); 910fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet if (nbReadBytes==0) { nbCalls = 0; return ENDOFSTREAM; } /* EOF */ 91162ed15319570d80690915f0d0dba0dc2e9478631Yann Collet if (nbReadBytes != MAGICNUMBER_SIZE) EXM_THROW(40, "Unrecognized header : Magic Number unreadable"); 912a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet magicNumber = LZ4IO_readLE32(MNstore); /* Little Endian format */ 91362ed15319570d80690915f0d0dba0dc2e9478631Yann Collet } 9147d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet if (LZ4IO_isSkippableMagicNumber(magicNumber)) magicNumber = LZ4IO_SKIPPABLE0; /* fold skippable magic numbers */ 91569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 91669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. switch(magicNumber) 91769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. { 9187d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet case LZ4IO_MAGICNUMBER: 919a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet return LZ4IO_decompressLZ4F(ress, finput, foutput); 92069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. case LEGACY_MAGICNUMBER: 92169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. DISPLAYLEVEL(4, "Detected : Legacy format \n"); 922113b150f0aeb3512b2850a65a824ad87f605187eYann Collet return LZ4IO_decodeLegacyStream(finput, foutput); 9237d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet case LZ4IO_SKIPPABLE0: 92469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. DISPLAYLEVEL(4, "Skipping detected skippable area \n"); 925d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { size_t const nbReadBytes = fread(MNstore, 1, 4, finput); 926d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (nbReadBytes != 4) EXM_THROW(42, "Stream error : skippable size unreadable"); } 927d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { unsigned const size = LZ4IO_readLE32(MNstore); /* Little Endian format */ 928d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet int const errorNb = fseek_u32(finput, size, SEEK_CUR); 929d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (errorNb != 0) EXM_THROW(43, "Stream error : cannot skip skippable area"); } 930d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet return 0; 931d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet EXTENDED_FORMAT; /* macro extension for custom formats */ 93269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. default: 933d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (nbCalls == 1) { /* just started */ 934fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet if (!g_testMode && g_overwrite) { 935fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet nbCalls = 0; 936a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet return LZ4IO_passThrough(finput, foutput, MNstore); 937fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet } 938e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet EXM_THROW(44,"Unrecognized header : file cannot be decoded"); /* Wrong magic number at the beginning of 1st stream */ 939e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet } 940d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet DISPLAYLEVEL(2, "Stream followed by undecodable data\n"); 94189d8b98d0dd896dccf6964fa3c6bb6ae6a2349b0Yann Collet return ENDOFSTREAM; 94269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. } 94369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 94469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 94569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 946fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Colletstatic int LZ4IO_decompressSrcFile(dRess_t ress, const char* input_filename, const char* output_filename) 94769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 948fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet FILE* const foutput = ress.dstFile; 94969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. unsigned long long filesize = 0, decodedSize=0; 95069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. FILE* finput; 95169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 9528a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Init */ 953f34808e4ae183d049e5e13949941d44876fdb90cYann Collet finput = LZ4IO_openSrcFile(input_filename); 954f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (finput==NULL) return 1; 95569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 9568a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Loop over multiple streams */ 957d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet do { 958a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet decodedSize = selectDecoder(ress, finput, foutput); 95989d8b98d0dd896dccf6964fa3c6bb6ae6a2349b0Yann Collet if (decodedSize != ENDOFSTREAM) 96089d8b98d0dd896dccf6964fa3c6bb6ae6a2349b0Yann Collet filesize += decodedSize; 96189d8b98d0dd896dccf6964fa3c6bb6ae6a2349b0Yann Collet } while (decodedSize != ENDOFSTREAM); 96269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 9638a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Close */ 96469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. fclose(finput); 965fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet 966fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet if (g_removeSrcFile) { if (remove(input_filename)) EXM_THROW(45, "Remove error : %s: %s", input_filename, strerror(errno)); } /* remove source file : --rm */ 967fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet 968fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet /* Final Status */ 969fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet DISPLAYLEVEL(2, "\r%79s\r", ""); 970fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet DISPLAYLEVEL(2, "%-20.20s : decoded %llu bytes \n", input_filename, filesize); 971f34808e4ae183d049e5e13949941d44876fdb90cYann Collet (void)output_filename; 972fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet 973fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet return 0; 974fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet} 975fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet 976fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet 977fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Colletstatic int LZ4IO_decompressDstFile(dRess_t ress, const char* input_filename, const char* output_filename) 978fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet{ 979fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet FILE* foutput; 980fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet 981fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet /* Init */ 982f34808e4ae183d049e5e13949941d44876fdb90cYann Collet foutput = LZ4IO_openDstFile(output_filename); 983f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (foutput==NULL) return 1; /* failure */ 984fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet 985fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet ress.dstFile = foutput; 986fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet LZ4IO_decompressSrcFile(ress, input_filename, output_filename); 987fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet 98869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. fclose(foutput); 98969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 990ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski /* Copy owner, file permissions and modification time */ 991ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski { stat_t statbuf; 992ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski if (strcmp (input_filename, stdinmark) && strcmp (output_filename, stdoutmark) && UTIL_getFileStat(input_filename, &statbuf)) 993ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski UTIL_setFileStat(output_filename, &statbuf); 994ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski } 995ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski 99669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. return 0; 99769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 99869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 999c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 1000a430b859cf552aa43215fe082e15a95c8bda5d6fYann Colletint LZ4IO_decompressFilename(const char* input_filename, const char* output_filename) 1001a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet{ 1002d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet dRess_t const ress = LZ4IO_createDResources(); 1003d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet clock_t const start = clock(); 1004a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 1005fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet int const missingFiles = LZ4IO_decompressDstFile(ress, input_filename, output_filename); 1006a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 1007d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { clock_t const end = clock(); 1008d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet double const seconds = (double)(end - start) / CLOCKS_PER_SEC; 1009a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet DISPLAYLEVEL(4, "Done in %.2f sec \n", seconds); 1010a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet } 1011a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 1012d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet LZ4IO_freeDResources(ress); 1013a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet return missingFiles; 1014a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet} 1015a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 1016a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 1017c64200dd85a85d9cc69a6fda682362d851be863bYann Colletint LZ4IO_decompressMultipleFilenames(const char** inFileNamesTable, int ifntSize, const char* suffix) 1018c64200dd85a85d9cc69a6fda682362d851be863bYann Collet{ 1019c64200dd85a85d9cc69a6fda682362d851be863bYann Collet int i; 1020a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet int skippedFiles = 0; 1021a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet int missingFiles = 0; 1022c64200dd85a85d9cc69a6fda682362d851be863bYann Collet char* outFileName = (char*)malloc(FNSPACE); 1023c64200dd85a85d9cc69a6fda682362d851be863bYann Collet size_t ofnSize = FNSPACE; 1024d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet size_t const suffixSize = strlen(suffix); 1025fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet dRess_t ress = LZ4IO_createDResources(); 1026a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 1027de0cf5de640eb56775f44c0f4c7c7a065e00447cPrzemyslaw Skibinski if (outFileName==NULL) return ifntSize; /* not enough memory */ 1028f34808e4ae183d049e5e13949941d44876fdb90cYann Collet ress.dstFile = LZ4IO_openDstFile(stdoutmark); 1029c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 1030d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet for (i=0; i<ifntSize; i++) { 1031d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet size_t const ifnSize = strlen(inFileNamesTable[i]); 1032d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet const char* const suffixPtr = inFileNamesTable[i] + ifnSize - suffixSize; 1033fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet if (!strcmp(suffix, stdoutmark)) { 1034fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet missingFiles += LZ4IO_decompressSrcFile(ress, inFileNamesTable[i], stdoutmark); 1035fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet continue; 1036fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet } 1037de0cf5de640eb56775f44c0f4c7c7a065e00447cPrzemyslaw Skibinski if (ofnSize <= ifnSize-suffixSize+1) { free(outFileName); ofnSize = ifnSize + 20; outFileName = (char*)malloc(ofnSize); if (outFileName==NULL) return ifntSize; } 1038d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (ifnSize <= suffixSize || strcmp(suffixPtr, suffix) != 0) { 1039bce2eeb9dfbca883003f21681e21df657fac90c4Yann Collet DISPLAYLEVEL(1, "File extension doesn't match expected LZ4_EXTENSION (%4s); will not process file: %s\n", suffix, inFileNamesTable[i]); 1040a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet skippedFiles++; 1041c64200dd85a85d9cc69a6fda682362d851be863bYann Collet continue; 1042c64200dd85a85d9cc69a6fda682362d851be863bYann Collet } 1043c64200dd85a85d9cc69a6fda682362d851be863bYann Collet memcpy(outFileName, inFileNamesTable[i], ifnSize - suffixSize); 1044c64200dd85a85d9cc69a6fda682362d851be863bYann Collet outFileName[ifnSize-suffixSize] = '\0'; 1045fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet missingFiles += LZ4IO_decompressDstFile(ress, inFileNamesTable[i], outFileName); 1046c64200dd85a85d9cc69a6fda682362d851be863bYann Collet } 1047a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 1048a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet LZ4IO_freeDResources(ress); 1049c64200dd85a85d9cc69a6fda682362d851be863bYann Collet free(outFileName); 1050a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet return missingFiles + skippedFiles; 1051c64200dd85a85d9cc69a6fda682362d851be863bYann Collet} 1052