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. 3369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 34f084b653835940c749d4fc92a610e861a6644aa2Przemyslaw Skibinski/*-************************************ 35f084b653835940c749d4fc92a610e861a6644aa2Przemyslaw Skibinski* Compiler options 36f084b653835940c749d4fc92a610e861a6644aa2Przemyslaw Skibinski**************************************/ 37f084b653835940c749d4fc92a610e861a6644aa2Przemyslaw Skibinski#ifdef _MSC_VER /* Visual Studio */ 38f084b653835940c749d4fc92a610e861a6644aa2Przemyslaw Skibinski# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ 39f084b653835940c749d4fc92a610e861a6644aa2Przemyslaw Skibinski#endif 40973bc79740f571c2b6700cab16a319df9aed2a05Przemyslaw Skibinski#if defined(__MINGW32__) && !defined(_POSIX_SOURCE) 41973bc79740f571c2b6700cab16a319df9aed2a05Przemyslaw Skibinski# define _POSIX_SOURCE 1 /* disable %llu warnings with MinGW on Windows */ 42973bc79740f571c2b6700cab16a319df9aed2a05Przemyslaw Skibinski#endif 43973bc79740f571c2b6700cab16a319df9aed2a05Przemyslaw Skibinski 44f084b653835940c749d4fc92a610e861a6644aa2Przemyslaw Skibinski 45d11ac4087254db4b9391039ce862e7305874fe97Yann Collet/***************************** 468a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet* Includes 478a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet*****************************/ 48e6af952f8495de3a9e3cabb9a21e0ba4d7d28ff0Przemyslaw Skibinski#include "platform.h" /* Large File Support, SET_BINARY_MODE, SET_SPARSE_FILE_MODE, PLATFORM_POSIX_VERSION, __64BIT__ */ 496adf05d1ed83053b8bb1f762494d2c10fdd8ac1dPrzemyslaw Skibinski#include "util.h" /* UTIL_getFileStat, UTIL_setFileStat */ 50c64200dd85a85d9cc69a6fda682362d851be863bYann Collet#include <stdio.h> /* fprintf, fopen, fread, stdin, stdout, fflush, getchar */ 517f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet#include <stdlib.h> /* malloc, free */ 52fea95c156761ee10d32a4f12105ebd90c67d4f47Przemyslaw Skibinski#include <string.h> /* strerror, strcmp, strlen */ 537f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet#include <time.h> /* clock */ 547f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet#include <sys/types.h> /* stat64 */ 557f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet#include <sys/stat.h> /* stat64 */ 5669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#include "lz4io.h" 578b8e5efefe2dfdfbeb3ebc7591d2c345c34552f5Yann Collet#include "lz4.h" /* still required for legacy format */ 588b8e5efefe2dfdfbeb3ebc7591d2c345c34552f5Yann Collet#include "lz4hc.h" /* still required for legacy format */ 596de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet#include "lz4frame.h" 6069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 6158124506358648b05477698e9136d7f651f11e01Przemyslaw Skibinski 622fd7eb554a17ce4815c60b29a226130e0ea448d6Przemyslaw Skibinski/* ************************************** 632fd7eb554a17ce4815c60b29a226130e0ea448d6Przemyslaw Skibinski* Compiler Options 642fd7eb554a17ce4815c60b29a226130e0ea448d6Przemyslaw Skibinski****************************************/ 652fd7eb554a17ce4815c60b29a226130e0ea448d6Przemyslaw Skibinski#if defined(_MSC_VER) && (_MSC_VER >= 1400) /* Avoid MSVC fseek()'s 2GiB barrier */ 662fd7eb554a17ce4815c60b29a226130e0ea448d6Przemyslaw Skibinski# define fseek _fseeki64 672fd7eb554a17ce4815c60b29a226130e0ea448d6Przemyslaw Skibinski#endif 685f0cc8e2d0dc473185ebac61b03fb6a4262797fbPrzemyslaw Skibinski#if !defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L) /* No point defining Large file for 64 bit */ 695f0cc8e2d0dc473185ebac61b03fb6a4262797fbPrzemyslaw Skibinski# define fseek fseeko 705f0cc8e2d0dc473185ebac61b03fb6a4262797fbPrzemyslaw Skibinski#endif 7169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 722fd7eb554a17ce4815c60b29a226130e0ea448d6Przemyslaw Skibinski 73248b761f55b92a34eacbfe2ac5d6f1b94e69d7bfYann Collet/***************************** 748a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet* Constants 758a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet*****************************/ 766de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet#define KB *(1 <<10) 776de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet#define MB *(1 <<20) 7869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define GB *(1U<<30) 7969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 8069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define _1BIT 0x01 8169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define _2BITS 0x03 8269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define _3BITS 0x07 8369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define _4BITS 0x0F 8469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define _8BITS 0xFF 8569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 867d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet#define MAGICNUMBER_SIZE 4 877d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet#define LZ4IO_MAGICNUMBER 0x184D2204 887d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet#define LZ4IO_SKIPPABLE0 0x184D2A50 897d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet#define LZ4IO_SKIPPABLEMASK 0xFFFFFFF0 907d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet#define LEGACY_MAGICNUMBER 0x184C2102 9169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 9269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define CACHELINE 64 9369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define LEGACY_BLOCKSIZE (8 MB) 94d517d609d95bdbab665a6ddb6e018c450d1e5ae6Yann Collet#define MIN_STREAM_BUFSIZE (192 KB) 957d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet#define LZ4IO_BLOCKSIZEID_DEFAULT 7 967d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet 9769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 988a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet/************************************** 998a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet* Macros 100d11ac4087254db4b9391039ce862e7305874fe97Yann Collet**************************************/ 10169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define DISPLAY(...) fprintf(stderr, __VA_ARGS__) 10212ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet#define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); } 10312ab41571ef7fd11b8b2013aa943beae373cef8aYann Colletstatic int g_displayLevel = 0; /* 0 : no display ; 1: errors ; 2 : + result + interaction + warnings ; 3 : + progression; 4 : + information */ 10412ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet 10512ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet#define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \ 10659adfd82d6c00c005a88ef5bdd405204d71d5729Yann Collet if (((clock_t)(g_time - clock()) > refreshRate) || (g_displayLevel>=4)) \ 1076de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet { g_time = clock(); DISPLAY(__VA_ARGS__); \ 108d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (g_displayLevel>=4) fflush(stderr); } } 10959adfd82d6c00c005a88ef5bdd405204d71d5729Yann Colletstatic const clock_t refreshRate = CLOCKS_PER_SEC / 6; 1106de52c2a8c40b7381e364ad87af9e80a60d95229Yann Colletstatic clock_t g_time = 0; 11169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 11269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 1138a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet/************************************** 1148a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet* Local Parameters 115d11ac4087254db4b9391039ce862e7305874fe97Yann Collet**************************************/ 11612ab41571ef7fd11b8b2013aa943beae373cef8aYann Colletstatic int g_overwrite = 1; 117136caa552bdc5657449e540b8becff826b80ade7Nick Terrellstatic int g_testMode = 0; 1187d87d43e619b0296bbe3f1674f10575b3f68c189Yann Colletstatic int g_blockSizeId = LZ4IO_BLOCKSIZEID_DEFAULT; 11912ab41571ef7fd11b8b2013aa943beae373cef8aYann Colletstatic int g_blockChecksum = 0; 12012ab41571ef7fd11b8b2013aa943beae373cef8aYann Colletstatic int g_streamChecksum = 1; 12112ab41571ef7fd11b8b2013aa943beae373cef8aYann Colletstatic int g_blockIndependence = 1; 1229fd4f1f9f780f1be38ad6695d62a9ba2ea426d6dYann Colletstatic int g_sparseFileSupport = 1; 1237f436a1215f11b0fb872c34f088b8b5888d0630dYann Colletstatic int g_contentSizeFlag = 0; 12469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 125c5decf7562a3b4065922ae6460b7785eb91366f8Yann Collet 1268a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet/************************************** 1278a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet* Exceptions 1288a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet***************************************/ 129d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet#ifndef DEBUG 130d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet# define DEBUG 0 131d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet#endif 13269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define DEBUGOUTPUT(...) if (DEBUG) DISPLAY(__VA_ARGS__); 13369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define EXM_THROW(error, ...) \ 13469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ \ 13569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. DEBUGOUTPUT("Error defined at %s, line %i : \n", __FILE__, __LINE__); \ 13669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. DISPLAYLEVEL(1, "Error %i : ", error); \ 13769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. DISPLAYLEVEL(1, __VA_ARGS__); \ 138c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet DISPLAYLEVEL(1, " \n"); \ 13969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. exit(error); \ 14069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 14169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 14269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 1438a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet/************************************** 1448a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet* Version modifiers 1457d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet**************************************/ 14669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define EXTENDED_ARGUMENTS 14769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define EXTENDED_HELP 14869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.#define EXTENDED_FORMAT 149a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet#define DEFAULT_DECOMPRESSOR LZ4IO_decompressLZ4F 15069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 15169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 15269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* ************************************************** */ 15369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* ****************** Parameters ******************** */ 15469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* ************************************************** */ 15569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 15669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* Default setting : overwrite = 1; return : overwrite mode (0/1) */ 15769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.int LZ4IO_setOverwrite(int yes) 15869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 15912ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet g_overwrite = (yes!=0); 16012ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet return g_overwrite; 16169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 16269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 163136caa552bdc5657449e540b8becff826b80ade7Nick Terrell/* Default setting : testMode = 0; return : testMode (0/1) */ 164136caa552bdc5657449e540b8becff826b80ade7Nick Terrellint LZ4IO_setTestMode(int yes) 1653dcafd35d409380182393fdb0d5666f6a64ff841Nick Terrell{ 166136caa552bdc5657449e540b8becff826b80ade7Nick Terrell g_testMode = (yes!=0); 167136caa552bdc5657449e540b8becff826b80ade7Nick Terrell return g_testMode; 1683dcafd35d409380182393fdb0d5666f6a64ff841Nick Terrell} 1693dcafd35d409380182393fdb0d5666f6a64ff841Nick Terrell 17069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* blockSizeID : valid values : 4-5-6-7 */ 171d2be69b144d6c5fd9a3dcbc4133e93e710cda998Yann Colletsize_t LZ4IO_setBlockSizeID(unsigned bsid) 17269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 173d2be69b144d6c5fd9a3dcbc4133e93e710cda998Yann Collet static const size_t blockSizeTable[] = { 64 KB, 256 KB, 1 MB, 4 MB }; 174929badd611544f28ed887c380f55e282a101e6bdYann Collet static const unsigned minBlockSizeID = 4; 175929badd611544f28ed887c380f55e282a101e6bdYann Collet static const unsigned maxBlockSizeID = 7; 176d2be69b144d6c5fd9a3dcbc4133e93e710cda998Yann Collet if ((bsid < minBlockSizeID) || (bsid > maxBlockSizeID)) return 0; 17712ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet g_blockSizeId = bsid; 17812ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet return blockSizeTable[g_blockSizeId-minBlockSizeID]; 17969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 18069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 1816de52c2a8c40b7381e364ad87af9e80a60d95229Yann Colletint LZ4IO_setBlockMode(LZ4IO_blockMode_t blockMode) 18269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 18312ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet g_blockIndependence = (blockMode == LZ4IO_blockIndependent); 18412ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet return g_blockIndependence; 18569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 18669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 18769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* Default setting : no checksum */ 18869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.int LZ4IO_setBlockChecksumMode(int xxhash) 18969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 19012ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet g_blockChecksum = (xxhash != 0); 19112ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet return g_blockChecksum; 19269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 19369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 19469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* Default setting : checksum enabled */ 19569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.int LZ4IO_setStreamChecksumMode(int xxhash) 19669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 19712ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet g_streamChecksum = (xxhash != 0); 19812ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet return g_streamChecksum; 19969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 20069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 20169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* Default setting : 0 (no notification) */ 20269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.int LZ4IO_setNotificationLevel(int level) 20369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 20412ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet g_displayLevel = level; 20512ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet return g_displayLevel; 20612ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet} 20712ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet 20812ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet/* Default setting : 0 (disabled) */ 20912ab41571ef7fd11b8b2013aa943beae373cef8aYann Colletint LZ4IO_setSparseFile(int enable) 21012ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet{ 211e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet g_sparseFileSupport = (enable!=0); 21212ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet return g_sparseFileSupport; 21369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 21469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 2157f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet/* Default setting : 0 (disabled) */ 2167f436a1215f11b0fb872c34f088b8b5888d0630dYann Colletint LZ4IO_setContentSize(int enable) 2177f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet{ 2187f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet g_contentSizeFlag = (enable!=0); 2197f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet return g_contentSizeFlag; 2207f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet} 2217f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet 222ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinskistatic U32 g_removeSrcFile = 0; 223ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinskivoid LZ4IO_setRemoveSrcFile(unsigned flag) { g_removeSrcFile = (flag>0); } 224ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski 2257f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet 22669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 227d11ac4087254db4b9391039ce862e7305874fe97Yann Collet/* ************************************************************************ ** 228d11ac4087254db4b9391039ce862e7305874fe97Yann Collet** ********************** LZ4 File / Pipe compression ********************* ** 229d11ac4087254db4b9391039ce862e7305874fe97Yann Collet** ************************************************************************ */ 23069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 2317d87d43e619b0296bbe3f1674f10575b3f68c189Yann Colletstatic int LZ4IO_GetBlockSize_FromBlockId (int id) { return (1 << (8 + (2 * id))); } 2327d87d43e619b0296bbe3f1674f10575b3f68c189Yann Colletstatic int LZ4IO_isSkippableMagicNumber(unsigned int magic) { return (magic & LZ4IO_SKIPPABLEMASK) == LZ4IO_SKIPPABLE0; } 23369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 23469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 235f34808e4ae183d049e5e13949941d44876fdb90cYann Collet/** LZ4IO_openSrcFile() : 236f34808e4ae183d049e5e13949941d44876fdb90cYann Collet * condition : `dstFileName` must be non-NULL. 237f34808e4ae183d049e5e13949941d44876fdb90cYann Collet * @result : FILE* to `dstFileName`, or NULL if it fails */ 238f34808e4ae183d049e5e13949941d44876fdb90cYann Colletstatic FILE* LZ4IO_openSrcFile(const char* srcFileName) 239f34808e4ae183d049e5e13949941d44876fdb90cYann Collet{ 240f34808e4ae183d049e5e13949941d44876fdb90cYann Collet FILE* f; 24169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 242f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (!strcmp (srcFileName, stdinmark)) { 243f34808e4ae183d049e5e13949941d44876fdb90cYann Collet DISPLAYLEVEL(4,"Using stdin for input\n"); 244f34808e4ae183d049e5e13949941d44876fdb90cYann Collet f = stdin; 245f34808e4ae183d049e5e13949941d44876fdb90cYann Collet SET_BINARY_MODE(stdin); 246f34808e4ae183d049e5e13949941d44876fdb90cYann Collet } else { 247f34808e4ae183d049e5e13949941d44876fdb90cYann Collet f = fopen(srcFileName, "rb"); 2485b37837e6e872bb57c8c7d07d6d4ff94176b8c59Nick Terrell if ( f==NULL ) DISPLAYLEVEL(1, "%s: %s \n", srcFileName, strerror(errno)); 249c64200dd85a85d9cc69a6fda682362d851be863bYann Collet } 250c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 251f34808e4ae183d049e5e13949941d44876fdb90cYann Collet return f; 252f34808e4ae183d049e5e13949941d44876fdb90cYann Collet} 253f34808e4ae183d049e5e13949941d44876fdb90cYann Collet 254f34808e4ae183d049e5e13949941d44876fdb90cYann Collet/** FIO_openDstFile() : 255f34808e4ae183d049e5e13949941d44876fdb90cYann Collet * condition : `dstFileName` must be non-NULL. 256f34808e4ae183d049e5e13949941d44876fdb90cYann Collet * @result : FILE* to `dstFileName`, or NULL if it fails */ 257f34808e4ae183d049e5e13949941d44876fdb90cYann Colletstatic FILE* LZ4IO_openDstFile(const char* dstFileName) 258f34808e4ae183d049e5e13949941d44876fdb90cYann Collet{ 259f34808e4ae183d049e5e13949941d44876fdb90cYann Collet FILE* f; 260fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet 261f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (!strcmp (dstFileName, stdoutmark)) { 262f34808e4ae183d049e5e13949941d44876fdb90cYann Collet DISPLAYLEVEL(4,"Using stdout for output\n"); 263f34808e4ae183d049e5e13949941d44876fdb90cYann Collet f = stdout; 26469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. SET_BINARY_MODE(stdout); 265d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (g_sparseFileSupport==1) { 266acae59a73969f436f95ed31130efe0ee9f7b3e48Yann Collet g_sparseFileSupport = 0; 267acae59a73969f436f95ed31130efe0ee9f7b3e48Yann Collet DISPLAYLEVEL(4, "Sparse File Support is automatically disabled on stdout ; try --sparse \n"); 268acae59a73969f436f95ed31130efe0ee9f7b3e48Yann Collet } 269d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet } else { 270f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (!g_overwrite && strcmp (dstFileName, nulmark)) { /* Check if destination file already exists */ 271f34808e4ae183d049e5e13949941d44876fdb90cYann Collet f = fopen( dstFileName, "rb" ); 272f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (f != NULL) { /* dest exists, prompt for overwrite authorization */ 273f34808e4ae183d049e5e13949941d44876fdb90cYann Collet fclose(f); 274f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (g_displayLevel <= 1) { /* No interaction possible */ 2755b37837e6e872bb57c8c7d07d6d4ff94176b8c59Nick Terrell DISPLAY("%s already exists; not overwritten \n", dstFileName); 276f34808e4ae183d049e5e13949941d44876fdb90cYann Collet return NULL; 277f34808e4ae183d049e5e13949941d44876fdb90cYann Collet } 2785b37837e6e872bb57c8c7d07d6d4ff94176b8c59Nick Terrell DISPLAY("%s already exists; do you wish to overwrite (y/N) ? ", dstFileName); 279f34808e4ae183d049e5e13949941d44876fdb90cYann Collet { int ch = getchar(); 280f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if ((ch!='Y') && (ch!='y')) { 281f34808e4ae183d049e5e13949941d44876fdb90cYann Collet DISPLAY(" not overwritten \n"); 282f34808e4ae183d049e5e13949941d44876fdb90cYann Collet return NULL; 283f34808e4ae183d049e5e13949941d44876fdb90cYann Collet } 284f34808e4ae183d049e5e13949941d44876fdb90cYann Collet while ((ch!=EOF) && (ch!='\n')) ch = getchar(); /* flush rest of input line */ 285f34808e4ae183d049e5e13949941d44876fdb90cYann Collet } } } 286f34808e4ae183d049e5e13949941d44876fdb90cYann Collet f = fopen( dstFileName, "wb" ); 2875b37837e6e872bb57c8c7d07d6d4ff94176b8c59Nick Terrell if (f==NULL) DISPLAYLEVEL(1, "%s: %s\n", dstFileName, strerror(errno)); 28869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. } 28969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 290f34808e4ae183d049e5e13949941d44876fdb90cYann Collet /* sparse file */ 291767a23160b746f3f34e865c5a09bb0a7d4e5bf7cPrzemyslaw Skibinski if (f && g_sparseFileSupport) { SET_SPARSE_FILE_MODE(f); } 29269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 293f34808e4ae183d049e5e13949941d44876fdb90cYann Collet return f; 29469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 29569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 29669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 2976de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet 2986de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet/*************************************** 299d11ac4087254db4b9391039ce862e7305874fe97Yann Collet* Legacy Compression 300d11ac4087254db4b9391039ce862e7305874fe97Yann Collet***************************************/ 3016de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet 3026de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet/* unoptimized version; solves endianess & alignment issues */ 3036de52c2a8c40b7381e364ad87af9e80a60d95229Yann Colletstatic void LZ4IO_writeLE32 (void* p, unsigned value32) 3046de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet{ 305ceec6fa8492a5ff0ed163c96516716a3c2b09461Yann Collet unsigned char* dstPtr = (unsigned char*)p; 3066de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet dstPtr[0] = (unsigned char)value32; 3076de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet dstPtr[1] = (unsigned char)(value32 >> 8); 3086de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet dstPtr[2] = (unsigned char)(value32 >> 16); 3096de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet dstPtr[3] = (unsigned char)(value32 >> 24); 3106de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet} 3116de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet 312b805d581b97be95fcc000134a54aa7c591b3ef09Yann Colletstatic int LZ4IO_LZ4_compress(const char* src, char* dst, int srcSize, int dstSize, int cLevel) 313b805d581b97be95fcc000134a54aa7c591b3ef09Yann Collet{ 314b805d581b97be95fcc000134a54aa7c591b3ef09Yann Collet (void)cLevel; 3151b17bf2ab8cf66dd2b740eca376e2d46f7ad7041Yann Collet return LZ4_compress_fast(src, dst, srcSize, dstSize, 1); 316b805d581b97be95fcc000134a54aa7c591b3ef09Yann Collet} 317b805d581b97be95fcc000134a54aa7c591b3ef09Yann Collet 3186de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet/* LZ4IO_compressFilename_Legacy : 3196de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet * This function is intentionally "hidden" (not published in .h) 3206de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet * It generates compressed streams using the old 'legacy' format */ 321488029ec3b23b1e00a69f1ac3fcdd49d24cb7d3fYann Colletint LZ4IO_compressFilename_Legacy(const char* input_filename, const char* output_filename, int compressionlevel) 32269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 323b805d581b97be95fcc000134a54aa7c591b3ef09Yann Collet int (*compressionFunction)(const char* src, char* dst, int srcSize, int dstSize, int cLevel); 32469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. unsigned long long filesize = 0; 32569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. unsigned long long compressedfilesize = MAGICNUMBER_SIZE; 32669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. char* in_buff; 32769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. char* out_buff; 328f11afafe234ea45a6d80f8b21df1d603ace4e025Yann Collet const int outBuffSize = LZ4_compressBound(LEGACY_BLOCKSIZE); 32969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. FILE* finput; 33069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. FILE* foutput; 331d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet clock_t end; 33269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 3338a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Init */ 334d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet clock_t const start = clock(); 335e05088d0eb500d8d673e081929620e538df3d718Yann Collet if (compressionlevel < 3) compressionFunction = LZ4IO_LZ4_compress; else compressionFunction = LZ4_compress_HC; 3366de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet 337f34808e4ae183d049e5e13949941d44876fdb90cYann Collet finput = LZ4IO_openSrcFile(input_filename); 338f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (finput == NULL) EXM_THROW(20, "%s : open file error ", input_filename); 339f34808e4ae183d049e5e13949941d44876fdb90cYann Collet foutput = LZ4IO_openDstFile(output_filename); 340f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (foutput == NULL) { fclose(finput); EXM_THROW(20, "%s : open file error ", input_filename); } 34169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 3428a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Allocate Memory */ 34369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. in_buff = (char*)malloc(LEGACY_BLOCKSIZE); 344f11afafe234ea45a6d80f8b21df1d603ace4e025Yann Collet out_buff = (char*)malloc(outBuffSize); 34569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. if (!in_buff || !out_buff) EXM_THROW(21, "Allocation error : not enough memory"); 34669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 3478a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Write Archive Header */ 3486de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet LZ4IO_writeLE32(out_buff, LEGACY_MAGICNUMBER); 349d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { size_t const sizeCheck = fwrite(out_buff, 1, MAGICNUMBER_SIZE, foutput); 350d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (sizeCheck!=MAGICNUMBER_SIZE) EXM_THROW(22, "Write error : cannot write header"); } 35169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 3528a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Main Loop */ 353d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet while (1) { 35469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. unsigned int outSize; 3558a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Read Block */ 356c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet size_t const inSize = (int) fread(in_buff, (size_t)1, (size_t)LEGACY_BLOCKSIZE, finput); 357c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet if (inSize == 0) break; 358c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet if (inSize > LEGACY_BLOCKSIZE) EXM_THROW(23, "Read error : wrong fread() size report "); /* should be impossible */ 35969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. filesize += inSize; 36069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 3618a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Compress Block */ 36246b49af37c62225c02098a3150d63a63fb0554aeYann Collet outSize = compressionFunction(in_buff, out_buff+4, (int)inSize, outBuffSize, compressionlevel); 36369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. compressedfilesize += outSize+4; 364f11afafe234ea45a6d80f8b21df1d603ace4e025Yann Collet DISPLAYUPDATE(2, "\rRead : %i MB ==> %.2f%% ", (int)(filesize>>20), (double)compressedfilesize/filesize*100); 36569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 3668a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Write Block */ 3676de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet LZ4IO_writeLE32(out_buff, outSize); 368d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { size_t const sizeCheck = fwrite(out_buff, 1, outSize+4, foutput); 369c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet if (sizeCheck!=(size_t)(outSize+4)) EXM_THROW(24, "Write error : cannot write compressed block"); 370d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet } } 371c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet if (ferror(finput)) EXM_THROW(25, "Error while reading %s ", input_filename); 37269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 3738a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Status */ 37469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. end = clock(); 375d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (end==start) end+=1; /* avoid division by zero (speed) */ 376d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet filesize += !filesize; /* avoid division by zero (ratio) */ 377d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet DISPLAYLEVEL(2, "\r%79s\r", ""); /* blank line */ 37869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. DISPLAYLEVEL(2,"Compressed %llu bytes into %llu bytes ==> %.2f%%\n", 379d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet filesize, compressedfilesize, (double)compressedfilesize / filesize * 100); 380d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { double const seconds = (double)(end - start) / CLOCKS_PER_SEC; 38169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. DISPLAYLEVEL(4,"Done in %.2f s ==> %.2f MB/s\n", seconds, (double)filesize / seconds / 1024 / 1024); 38269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. } 38369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 3848a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Close & Free */ 38569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. free(in_buff); 38669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. free(out_buff); 38769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. fclose(finput); 38869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. fclose(foutput); 38969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 39069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. return 0; 39169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 39269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 39369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 394d11ac4087254db4b9391039ce862e7305874fe97Yann Collet/********************************************* 395d11ac4087254db4b9391039ce862e7305874fe97Yann Collet* Compression using Frame format 396d11ac4087254db4b9391039ce862e7305874fe97Yann Collet*********************************************/ 39769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 398c64200dd85a85d9cc69a6fda682362d851be863bYann Collettypedef struct { 399348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet void* srcBuffer; 400c64200dd85a85d9cc69a6fda682362d851be863bYann Collet size_t srcBufferSize; 401348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet void* dstBuffer; 402c64200dd85a85d9cc69a6fda682362d851be863bYann Collet size_t dstBufferSize; 403c64200dd85a85d9cc69a6fda682362d851be863bYann Collet LZ4F_compressionContext_t ctx; 404348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet} cRess_t; 405c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 406348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Colletstatic cRess_t LZ4IO_createCResources(void) 407348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet{ 408348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet const size_t blockSize = (size_t)LZ4IO_GetBlockSize_FromBlockId (g_blockSizeId); 409348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet cRess_t ress; 410c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 411d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet LZ4F_errorCode_t const errorCode = LZ4F_createCompressionContext(&(ress.ctx), LZ4F_VERSION); 412348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet if (LZ4F_isError(errorCode)) EXM_THROW(30, "Allocation error : can't create LZ4F context : %s", LZ4F_getErrorName(errorCode)); 413348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet 414348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet /* Allocate Memory */ 415348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet ress.srcBuffer = malloc(blockSize); 416348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet ress.srcBufferSize = blockSize; 417e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet ress.dstBufferSize = LZ4F_compressFrameBound(blockSize, NULL); /* cover worst case */ 418348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet ress.dstBuffer = malloc(ress.dstBufferSize); 419348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet if (!ress.srcBuffer || !ress.dstBuffer) EXM_THROW(31, "Allocation error : not enough memory"); 420348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet 421348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet return ress; 422348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet} 423348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet 424348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Colletstatic void LZ4IO_freeCResources(cRess_t ress) 425348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet{ 426348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet free(ress.srcBuffer); 427348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet free(ress.dstBuffer); 428d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { LZ4F_errorCode_t const errorCode = LZ4F_freeCompressionContext(ress.ctx); 429d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (LZ4F_isError(errorCode)) EXM_THROW(38, "Error : can't free LZ4F context resource : %s", LZ4F_getErrorName(errorCode)); } 430348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet} 431348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet 432d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet/* 433d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet * LZ4IO_compressFilename_extRess() 434d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet * result : 0 : compression completed correctly 435d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet * 1 : missing or pb opening srcFileName 436d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet */ 437e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Colletstatic int LZ4IO_compressFilename_extRess(cRess_t ress, const char* srcFileName, const char* dstFileName, int compressionLevel) 43869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 43969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. unsigned long long filesize = 0; 44069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. unsigned long long compressedfilesize = 0; 441348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet FILE* srcFile; 442348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet FILE* dstFile; 443c64200dd85a85d9cc69a6fda682362d851be863bYann Collet void* const srcBuffer = ress.srcBuffer; 444c64200dd85a85d9cc69a6fda682362d851be863bYann Collet void* const dstBuffer = ress.dstBuffer; 445c64200dd85a85d9cc69a6fda682362d851be863bYann Collet const size_t dstBufferSize = ress.dstBufferSize; 446c64200dd85a85d9cc69a6fda682362d851be863bYann Collet const size_t blockSize = (size_t)LZ4IO_GetBlockSize_FromBlockId (g_blockSizeId); 447c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet size_t readSize; 448c64200dd85a85d9cc69a6fda682362d851be863bYann Collet LZ4F_compressionContext_t ctx = ress.ctx; /* just a pointer */ 449ceec6fa8492a5ff0ed163c96516716a3c2b09461Yann Collet LZ4F_preferences_t prefs; 45069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 4518a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Init */ 452f34808e4ae183d049e5e13949941d44876fdb90cYann Collet srcFile = LZ4IO_openSrcFile(srcFileName); 453f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (srcFile == NULL) return 1; 454f34808e4ae183d049e5e13949941d44876fdb90cYann Collet dstFile = LZ4IO_openDstFile(dstFileName); 455f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (dstFile == NULL) { fclose(srcFile); return 1; } 456ceec6fa8492a5ff0ed163c96516716a3c2b09461Yann Collet memset(&prefs, 0, sizeof(prefs)); 45769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 458348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet 4598a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Set compression parameters */ 4606de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet prefs.autoFlush = 1; 461348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet prefs.compressionLevel = compressionLevel; 462081bcca33bba4f6ac3e913b3cf2bc2ba58b6b697Takayuki MATSUOKA prefs.frameInfo.blockMode = (LZ4F_blockMode_t)g_blockIndependence; 463081bcca33bba4f6ac3e913b3cf2bc2ba58b6b697Takayuki MATSUOKA prefs.frameInfo.blockSizeID = (LZ4F_blockSizeID_t)g_blockSizeId; 464081bcca33bba4f6ac3e913b3cf2bc2ba58b6b697Takayuki MATSUOKA prefs.frameInfo.contentChecksumFlag = (LZ4F_contentChecksum_t)g_streamChecksum; 465d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (g_contentSizeFlag) { 466ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski U64 const fileSize = UTIL_getFileSize(srcFileName); 467d5da787c1bd92a22c87b6428321668548155995fYann Collet prefs.frameInfo.contentSize = fileSize; /* == 0 if input == stdin */ 46890c0104c4eaf8f06932990aacf07e60dd21685b9Yann Collet if (fileSize==0) 469d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet DISPLAYLEVEL(3, "Warning : cannot determine input content size \n"); 4707f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet } 4716de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet 4728a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* read first block */ 473e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet readSize = fread(srcBuffer, (size_t)1, blockSize, srcFile); 47400c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (ferror(srcFile)) EXM_THROW(30, "Error reading %s ", srcFileName); 4756de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet filesize += readSize; 47669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 477e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet /* single-block file */ 478d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (readSize < blockSize) { 479e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet /* Compress in single pass */ 480d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet size_t const cSize = LZ4F_compressFrame(dstBuffer, dstBufferSize, srcBuffer, readSize, &prefs); 48100c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (LZ4F_isError(cSize)) EXM_THROW(31, "Compression failed : %s", LZ4F_getErrorName(cSize)); 482d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet compressedfilesize = cSize; 4832ed9dcc900a8a662a52d11968baf27f61a9bedd3Yann Collet DISPLAYUPDATE(2, "\rRead : %u MB ==> %.2f%% ", 4842ed9dcc900a8a662a52d11968baf27f61a9bedd3Yann Collet (unsigned)(filesize>>20), (double)compressedfilesize/(filesize+!filesize)*100); /* avoid division by zero */ 48569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 4868a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Write Block */ 487d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { size_t const sizeCheck = fwrite(dstBuffer, 1, cSize, dstFile); 48800c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (sizeCheck!=cSize) EXM_THROW(32, "Write error : cannot write compressed block"); 489d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet } } 49069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 491e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet else 492e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet 493e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet /* multiple-blocks file */ 494e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet { 495e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet /* Write Archive Header */ 496c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet size_t headerSize = LZ4F_compressBegin(ctx, dstBuffer, dstBufferSize, &prefs); 49700c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (LZ4F_isError(headerSize)) EXM_THROW(33, "File header generation failed : %s", LZ4F_getErrorName(headerSize)); 498d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { size_t const sizeCheck = fwrite(dstBuffer, 1, headerSize, dstFile); 49900c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (sizeCheck!=headerSize) EXM_THROW(34, "Write error : cannot write header"); } 500e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet compressedfilesize += headerSize; 501e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet 502e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet /* Main Loop */ 503d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet while (readSize>0) { 504e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet size_t outSize; 505e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet 506e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet /* Compress Block */ 507e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet outSize = LZ4F_compressUpdate(ctx, dstBuffer, dstBufferSize, srcBuffer, readSize, NULL); 50800c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (LZ4F_isError(outSize)) EXM_THROW(35, "Compression failed : %s", LZ4F_getErrorName(outSize)); 509e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet compressedfilesize += outSize; 510e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet DISPLAYUPDATE(2, "\rRead : %u MB ==> %.2f%% ", (unsigned)(filesize>>20), (double)compressedfilesize/filesize*100); 511e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet 512e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet /* Write Block */ 513d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { size_t const sizeCheck = fwrite(dstBuffer, 1, outSize, dstFile); 51400c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (sizeCheck!=outSize) EXM_THROW(36, "Write error : cannot write compressed block"); } 515e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet 516e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet /* Read next block */ 517e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet readSize = fread(srcBuffer, (size_t)1, (size_t)blockSize, srcFile); 518e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet filesize += readSize; 519e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet } 52000c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (ferror(srcFile)) EXM_THROW(37, "Error reading %s ", srcFileName); 521e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet 522e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet /* End of Stream mark */ 523e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet headerSize = LZ4F_compressEnd(ctx, dstBuffer, dstBufferSize, NULL); 52400c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (LZ4F_isError(headerSize)) EXM_THROW(38, "End of file generation failed : %s", LZ4F_getErrorName(headerSize)); 5256de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet 526d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { size_t const sizeCheck = fwrite(dstBuffer, 1, headerSize, dstFile); 52700c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (sizeCheck!=headerSize) EXM_THROW(39, "Write error : cannot write end of stream"); } 528e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet compressedfilesize += headerSize; 529e328d41ef4124870c31cba1fe1f4eed282b8e53eYann Collet } 53069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 531348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet /* Release files */ 532348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet fclose (srcFile); 533348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet fclose (dstFile); 534348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet 53598be008479486f60b0a98289eee2f57c28650964Przemyslaw Skibinski /* Copy owner, file permissions and modification time */ 536ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski { stat_t statbuf; 537ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski if (strcmp (srcFileName, stdinmark) && strcmp (dstFileName, stdoutmark) && UTIL_getFileStat(srcFileName, &statbuf)) 538ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski UTIL_setFileStat(dstFileName, &statbuf); 539ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski } 540ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski 54100c6370ad2419ea1906cf876013fef44df9c5af0Yann Collet if (g_removeSrcFile) { if (remove(srcFileName)) EXM_THROW(40, "Remove error : %s: %s", srcFileName, strerror(errno)); } /* remove source file : --rm */ 54298be008479486f60b0a98289eee2f57c28650964Przemyslaw Skibinski 5438a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Final Status */ 54469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. DISPLAYLEVEL(2, "\r%79s\r", ""); 545d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet DISPLAYLEVEL(2, "Compressed %llu bytes into %llu bytes ==> %.2f%%\n", 546d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet filesize, compressedfilesize, (double)compressedfilesize/(filesize + !filesize)*100); /* avoid division by zero */ 54769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 54869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. return 0; 54969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 55069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 55169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 552348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Colletint LZ4IO_compressFilename(const char* srcFileName, const char* dstFileName, int compressionLevel) 553488029ec3b23b1e00a69f1ac3fcdd49d24cb7d3fYann Collet{ 554d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet clock_t const start = clock(); 555d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet cRess_t const ress = LZ4IO_createCResources(); 556c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 557d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet int const issueWithSrcFile = LZ4IO_compressFilename_extRess(ress, srcFileName, dstFileName, compressionLevel); 558c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 559348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet /* Free resources */ 560348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet LZ4IO_freeCResources(ress); 561c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 562c64200dd85a85d9cc69a6fda682362d851be863bYann Collet /* Final Status */ 563d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { clock_t const end = clock(); 564d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet double const seconds = (double)(end - start) / CLOCKS_PER_SEC; 565c64200dd85a85d9cc69a6fda682362d851be863bYann Collet DISPLAYLEVEL(4, "Completed in %.2f sec \n", seconds); 566488029ec3b23b1e00a69f1ac3fcdd49d24cb7d3fYann Collet } 567c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 568348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet return issueWithSrcFile; 569488029ec3b23b1e00a69f1ac3fcdd49d24cb7d3fYann Collet} 570488029ec3b23b1e00a69f1ac3fcdd49d24cb7d3fYann Collet 571c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 572c64200dd85a85d9cc69a6fda682362d851be863bYann Collet#define FNSPACE 30 573c64200dd85a85d9cc69a6fda682362d851be863bYann Colletint LZ4IO_compressMultipleFilenames(const char** inFileNamesTable, int ifntSize, const char* suffix, int compressionLevel) 5740169502b49dfa5eb8878f5c85be3270012266fc3Kyle J Harper{ 5750169502b49dfa5eb8878f5c85be3270012266fc3Kyle J Harper int i; 576d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet int missed_files = 0; 577d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet char* dstFileName = (char*)malloc(FNSPACE); 5780169502b49dfa5eb8878f5c85be3270012266fc3Kyle J Harper size_t ofnSize = FNSPACE; 579cc2412401400fbacd7530b8dcc4af0b0d7c734ceYann Collet const size_t suffixSize = strlen(suffix); 5801289038240ab81aee4cc70ef071da907ccfdfcdePrzemyslaw Skibinski cRess_t ress; 581c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 582de0cf5de640eb56775f44c0f4c7c7a065e00447cPrzemyslaw Skibinski if (dstFileName == NULL) return ifntSize; /* not enough memory */ 5831289038240ab81aee4cc70ef071da907ccfdfcdePrzemyslaw Skibinski ress = LZ4IO_createCResources(); 584de0cf5de640eb56775f44c0f4c7c7a065e00447cPrzemyslaw Skibinski 585c64200dd85a85d9cc69a6fda682362d851be863bYann Collet /* loop on each file */ 586d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet for (i=0; i<ifntSize; i++) { 587d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet size_t const ifnSize = strlen(inFileNamesTable[i]); 5881833be1cf0e545f8b24bb4a786e274a9e419e280Przemyslaw Skibinski if (ofnSize <= ifnSize+suffixSize+1) { free(dstFileName); ofnSize = ifnSize + 20; dstFileName = (char*)malloc(ofnSize); if (dstFileName==NULL) { LZ4IO_freeCResources(ress); return ifntSize; } } 589d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet strcpy(dstFileName, inFileNamesTable[i]); 590d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet strcat(dstFileName, suffix); 591c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 592d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet missed_files += LZ4IO_compressFilename_extRess(ress, inFileNamesTable[i], dstFileName, compressionLevel); 5930169502b49dfa5eb8878f5c85be3270012266fc3Kyle J Harper } 594c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 595c64200dd85a85d9cc69a6fda682362d851be863bYann Collet /* Close & Free */ 596348f5099e42c23393ec9c8e6b403f4bca99bbb41Yann Collet LZ4IO_freeCResources(ress); 597d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet free(dstFileName); 598c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 599d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet return missed_files; 6000169502b49dfa5eb8878f5c85be3270012266fc3Kyle J Harper} 601488029ec3b23b1e00a69f1ac3fcdd49d24cb7d3fYann Collet 602c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 60369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* ********************************************************************* */ 604488029ec3b23b1e00a69f1ac3fcdd49d24cb7d3fYann Collet/* ********************** LZ4 file-stream Decompression **************** */ 60569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* ********************************************************************* */ 60669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 6076de52c2a8c40b7381e364ad87af9e80a60d95229Yann Colletstatic unsigned LZ4IO_readLE32 (const void* s) 6086de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet{ 609d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet const unsigned char* const srcPtr = (const unsigned char*)s; 6106de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet unsigned value32 = srcPtr[0]; 6116de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet value32 += (srcPtr[1]<<8); 6126de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet value32 += (srcPtr[2]<<16); 613c64200dd85a85d9cc69a6fda682362d851be863bYann Collet value32 += ((unsigned)srcPtr[3])<<24; 6146de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet return value32; 6156de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet} 6166de52c2a8c40b7381e364ad87af9e80a60d95229Yann Collet 6171abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet#define sizeT sizeof(size_t) 6181abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet#define maskT (sizeT - 1) 6191abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet 620113b150f0aeb3512b2850a65a824ad87f605187eYann Colletstatic unsigned LZ4IO_fwriteSparse(FILE* file, const void* buffer, size_t bufferSize, unsigned storedSkips) 621113b150f0aeb3512b2850a65a824ad87f605187eYann Collet{ 6221c3e633c48766c58df949887297dc5838170a33fYann Collet const size_t* const bufferT = (const size_t*)buffer; /* Buffer is supposed malloc'ed, hence aligned on size_t */ 6231c3e633c48766c58df949887297dc5838170a33fYann Collet const size_t* ptrT = bufferT; 6241abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet size_t bufferSizeT = bufferSize / sizeT; 6251c3e633c48766c58df949887297dc5838170a33fYann Collet const size_t* const bufferTEnd = bufferT + bufferSizeT; 626113b150f0aeb3512b2850a65a824ad87f605187eYann Collet static const size_t segmentSizeT = (32 KB) / sizeT; 627113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 628d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (!g_sparseFileSupport) { /* normal write */ 629d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet size_t const sizeCheck = fwrite(buffer, 1, bufferSize, file); 63058b5aadb1fc5d937e81c8f33e0e8290f2097c6bbYann Collet if (sizeCheck != bufferSize) EXM_THROW(70, "Write error : cannot write decoded block"); 631113b150f0aeb3512b2850a65a824ad87f605187eYann Collet return 0; 632113b150f0aeb3512b2850a65a824ad87f605187eYann Collet } 633113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 634113b150f0aeb3512b2850a65a824ad87f605187eYann Collet /* avoid int overflow */ 635d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (storedSkips > 1 GB) { 636d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet int const seekResult = fseek(file, 1 GB, SEEK_CUR); 63758b5aadb1fc5d937e81c8f33e0e8290f2097c6bbYann Collet if (seekResult != 0) EXM_THROW(71, "1 GB skip error (sparse file support)"); 638113b150f0aeb3512b2850a65a824ad87f605187eYann Collet storedSkips -= 1 GB; 639113b150f0aeb3512b2850a65a824ad87f605187eYann Collet } 640113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 641d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet while (ptrT < bufferTEnd) { 642113b150f0aeb3512b2850a65a824ad87f605187eYann Collet size_t seg0SizeT = segmentSizeT; 643113b150f0aeb3512b2850a65a824ad87f605187eYann Collet size_t nb0T; 644113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 645113b150f0aeb3512b2850a65a824ad87f605187eYann Collet /* count leading zeros */ 646113b150f0aeb3512b2850a65a824ad87f605187eYann Collet if (seg0SizeT > bufferSizeT) seg0SizeT = bufferSizeT; 647113b150f0aeb3512b2850a65a824ad87f605187eYann Collet bufferSizeT -= seg0SizeT; 648113b150f0aeb3512b2850a65a824ad87f605187eYann Collet for (nb0T=0; (nb0T < seg0SizeT) && (ptrT[nb0T] == 0); nb0T++) ; 649113b150f0aeb3512b2850a65a824ad87f605187eYann Collet storedSkips += (unsigned)(nb0T * sizeT); 650113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 651d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (nb0T != seg0SizeT) { /* not all 0s */ 652f084b653835940c749d4fc92a610e861a6644aa2Przemyslaw Skibinski errno = 0; 653f084b653835940c749d4fc92a610e861a6644aa2Przemyslaw Skibinski { int const seekResult = fseek(file, storedSkips, SEEK_CUR); 654f084b653835940c749d4fc92a610e861a6644aa2Przemyslaw Skibinski if (seekResult) EXM_THROW(72, "Sparse skip error(%d): %s ; try --no-sparse", (int)errno, strerror(errno)); 655f084b653835940c749d4fc92a610e861a6644aa2Przemyslaw Skibinski } 656113b150f0aeb3512b2850a65a824ad87f605187eYann Collet storedSkips = 0; 657113b150f0aeb3512b2850a65a824ad87f605187eYann Collet seg0SizeT -= nb0T; 658113b150f0aeb3512b2850a65a824ad87f605187eYann Collet ptrT += nb0T; 659d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { size_t const sizeCheck = fwrite(ptrT, sizeT, seg0SizeT, file); 660d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (sizeCheck != seg0SizeT) EXM_THROW(73, "Write error : cannot write decoded block"); 661d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet } } 662113b150f0aeb3512b2850a65a824ad87f605187eYann Collet ptrT += seg0SizeT; 663113b150f0aeb3512b2850a65a824ad87f605187eYann Collet } 664113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 665d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (bufferSize & maskT) { /* size not multiple of sizeT : implies end of block */ 6661c3e633c48766c58df949887297dc5838170a33fYann Collet const char* const restStart = (const char*)bufferTEnd; 667113b150f0aeb3512b2850a65a824ad87f605187eYann Collet const char* restPtr = restStart; 668d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet size_t const restSize = bufferSize & maskT; 669113b150f0aeb3512b2850a65a824ad87f605187eYann Collet const char* const restEnd = restStart + restSize; 670113b150f0aeb3512b2850a65a824ad87f605187eYann Collet for (; (restPtr < restEnd) && (*restPtr == 0); restPtr++) ; 671113b150f0aeb3512b2850a65a824ad87f605187eYann Collet storedSkips += (unsigned) (restPtr - restStart); 672d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (restPtr != restEnd) { 673d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet int const seekResult = fseek(file, storedSkips, SEEK_CUR); 674acae59a73969f436f95ed31130efe0ee9f7b3e48Yann Collet if (seekResult) EXM_THROW(74, "Sparse skip error ; try --no-sparse"); 675113b150f0aeb3512b2850a65a824ad87f605187eYann Collet storedSkips = 0; 676d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { size_t const sizeCheck = fwrite(restPtr, 1, restEnd - restPtr, file); 677d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (sizeCheck != (size_t)(restEnd - restPtr)) EXM_THROW(75, "Write error : cannot write decoded end of block"); 678d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet } } 679113b150f0aeb3512b2850a65a824ad87f605187eYann Collet } 680113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 681113b150f0aeb3512b2850a65a824ad87f605187eYann Collet return storedSkips; 682113b150f0aeb3512b2850a65a824ad87f605187eYann Collet} 683113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 684113b150f0aeb3512b2850a65a824ad87f605187eYann Colletstatic void LZ4IO_fwriteSparseEnd(FILE* file, unsigned storedSkips) 685113b150f0aeb3512b2850a65a824ad87f605187eYann Collet{ 686f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (storedSkips>0) { /* implies g_sparseFileSupport>0 */ 687d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet int const seekResult = fseek(file, storedSkips-1, SEEK_CUR); 688113b150f0aeb3512b2850a65a824ad87f605187eYann Collet if (seekResult != 0) EXM_THROW(69, "Final skip error (sparse file)\n"); 689d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { const char lastZeroByte[1] = { 0 }; 690d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet size_t const sizeCheck = fwrite(lastZeroByte, 1, 1, file); 691d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (sizeCheck != 1) EXM_THROW(69, "Write error : cannot write last zero\n"); 692d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet } } 693113b150f0aeb3512b2850a65a824ad87f605187eYann Collet} 694113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 695113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 69662ed15319570d80690915f0d0dba0dc2e9478631Yann Colletstatic unsigned g_magicRead = 0; 697113b150f0aeb3512b2850a65a824ad87f605187eYann Colletstatic unsigned long long LZ4IO_decodeLegacyStream(FILE* finput, FILE* foutput) 69869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 69969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. unsigned long long filesize = 0; 70069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. char* in_buff; 70169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. char* out_buff; 702113b150f0aeb3512b2850a65a824ad87f605187eYann Collet unsigned storedSkips = 0; 70369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 7048a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Allocate Memory */ 70569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. in_buff = (char*)malloc(LZ4_compressBound(LEGACY_BLOCKSIZE)); 70669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. out_buff = (char*)malloc(LEGACY_BLOCKSIZE); 70769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. if (!in_buff || !out_buff) EXM_THROW(51, "Allocation error : not enough memory"); 70869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 7098a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Main Loop */ 710d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet while (1) { 71169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. int decodeSize; 712c5decf7562a3b4065922ae6460b7785eb91366f8Yann Collet unsigned int blockSize; 71369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 7148a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Block Size */ 7151abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet { size_t const sizeCheck = fread(in_buff, 1, 4, finput); 7161abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet if (sizeCheck == 0) break; /* Nothing to read : file read is completed */ 7171abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet if (sizeCheck != 4) EXM_THROW(52, "Read error : cannot access block size "); } 7181abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet blockSize = LZ4IO_readLE32(in_buff); /* Convert to Little Endian */ 7191abecbc33c8ec5b84d2623dcbe73136aeb99db37Yann Collet if (blockSize > LZ4_COMPRESSBOUND(LEGACY_BLOCKSIZE)) { 720d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet /* Cannot read next block : maybe new stream ? */ 72162ed15319570d80690915f0d0dba0dc2e9478631Yann Collet g_magicRead = blockSize; 72269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. break; 72369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. } 72469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 7258a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Read Block */ 726f17302769055ad0c4b2e10e3de544f6593865e89Yann Collet { size_t const sizeCheck = fread(in_buff, 1, blockSize, finput); 727f17302769055ad0c4b2e10e3de544f6593865e89Yann Collet if (sizeCheck!=blockSize) EXM_THROW(52, "Read error : cannot access compressed block !"); } 72869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 7298a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Decode Block */ 73069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. decodeSize = LZ4_decompress_safe(in_buff, out_buff, blockSize, LEGACY_BLOCKSIZE); 73145b0642bf54718d2b57dd61cb606b154afc0ab26Yann Collet if (decodeSize < 0) EXM_THROW(53, "Decoding Failed ! Corrupted input detected !"); 73269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. filesize += decodeSize; 73369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 7348a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Write Block */ 735113b150f0aeb3512b2850a65a824ad87f605187eYann Collet storedSkips = LZ4IO_fwriteSparse(foutput, out_buff, decodeSize, storedSkips); 73669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. } 737c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet if (ferror(finput)) EXM_THROW(54, "Read error : ferror"); 73869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 739113b150f0aeb3512b2850a65a824ad87f605187eYann Collet LZ4IO_fwriteSparseEnd(foutput, storedSkips); 740113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 7418a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Free */ 74269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. free(in_buff); 74369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. free(out_buff); 74469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 74569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. return filesize; 74669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 74769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 74869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 749113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 750113b150f0aeb3512b2850a65a824ad87f605187eYann Collettypedef struct { 751113b150f0aeb3512b2850a65a824ad87f605187eYann Collet void* srcBuffer; 752113b150f0aeb3512b2850a65a824ad87f605187eYann Collet size_t srcBufferSize; 753113b150f0aeb3512b2850a65a824ad87f605187eYann Collet void* dstBuffer; 754113b150f0aeb3512b2850a65a824ad87f605187eYann Collet size_t dstBufferSize; 755fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet FILE* dstFile; 756113b150f0aeb3512b2850a65a824ad87f605187eYann Collet LZ4F_decompressionContext_t dCtx; 757a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet} dRess_t; 758113b150f0aeb3512b2850a65a824ad87f605187eYann Collet 759a430b859cf552aa43215fe082e15a95c8bda5d6fYann Colletstatic const size_t LZ4IO_dBufferSize = 64 KB; 760a430b859cf552aa43215fe082e15a95c8bda5d6fYann Colletstatic dRess_t LZ4IO_createDResources(void) 761a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet{ 762a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet dRess_t ress; 763a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 764a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet /* init */ 765d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet LZ4F_errorCode_t const errorCode = LZ4F_createDecompressionContext(&ress.dCtx, LZ4F_VERSION); 766a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet if (LZ4F_isError(errorCode)) EXM_THROW(60, "Can't create LZ4F context : %s", LZ4F_getErrorName(errorCode)); 767a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 768a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet /* Allocate Memory */ 769a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet ress.srcBufferSize = LZ4IO_dBufferSize; 770a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet ress.srcBuffer = malloc(ress.srcBufferSize); 771a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet ress.dstBufferSize = LZ4IO_dBufferSize; 772a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet ress.dstBuffer = malloc(ress.dstBufferSize); 773a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet if (!ress.srcBuffer || !ress.dstBuffer) EXM_THROW(61, "Allocation error : not enough memory"); 774a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 775d2be69b144d6c5fd9a3dcbc4133e93e710cda998Yann Collet ress.dstFile = NULL; 776a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet return ress; 777a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet} 778a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 779a430b859cf552aa43215fe082e15a95c8bda5d6fYann Colletstatic void LZ4IO_freeDResources(dRess_t ress) 780a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet{ 781a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet LZ4F_errorCode_t errorCode = LZ4F_freeDecompressionContext(ress.dCtx); 782a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet if (LZ4F_isError(errorCode)) EXM_THROW(69, "Error : can't free LZ4F context resource : %s", LZ4F_getErrorName(errorCode)); 783a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet free(ress.srcBuffer); 784a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet free(ress.dstBuffer); 785a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet} 786a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 787a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 788a430b859cf552aa43215fe082e15a95c8bda5d6fYann Colletstatic unsigned long long LZ4IO_decompressLZ4F(dRess_t ress, FILE* srcFile, FILE* dstFile) 78969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 79069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. unsigned long long filesize = 0; 791197982ec6cf449734f78d849ed4a845e075b2cf4Yann Collet LZ4F_errorCode_t nextToLoad; 79245a357fd1704e9c6d2d8037277bda62e8c86308eYann Collet unsigned storedSkips = 0; 793d517d609d95bdbab665a6ddb6e018c450d1e5ae6Yann Collet 794d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet /* Init feed with magic number (already consumed from FILE* sFile) */ 795d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { size_t inSize = MAGICNUMBER_SIZE; 796113b150f0aeb3512b2850a65a824ad87f605187eYann Collet size_t outSize= 0; 797113b150f0aeb3512b2850a65a824ad87f605187eYann Collet LZ4IO_writeLE32(ress.srcBuffer, LZ4IO_MAGICNUMBER); 798197982ec6cf449734f78d849ed4a845e075b2cf4Yann Collet nextToLoad = LZ4F_decompress(ress.dCtx, ress.dstBuffer, &outSize, ress.srcBuffer, &inSize, NULL); 799197982ec6cf449734f78d849ed4a845e075b2cf4Yann Collet if (LZ4F_isError(nextToLoad)) EXM_THROW(62, "Header error : %s", LZ4F_getErrorName(nextToLoad)); 8007f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet } 80169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 8027f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet /* Main Loop */ 803d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet for (;nextToLoad;) { 8047f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet size_t readSize; 8057f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet size_t pos = 0; 806197982ec6cf449734f78d849ed4a845e075b2cf4Yann Collet size_t decodedBytes = ress.dstBufferSize; 80769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 8087f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet /* Read input */ 809cbcdd88ccb97632015cf3732b46f8800e62e337bYann Collet if (nextToLoad > ress.srcBufferSize) nextToLoad = ress.srcBufferSize; 810cbcdd88ccb97632015cf3732b46f8800e62e337bYann Collet readSize = fread(ress.srcBuffer, 1, nextToLoad, srcFile); 811d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (!readSize) break; /* reached end of file or stream */ 8127f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet 813d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet while ((pos < readSize) || (decodedBytes == ress.dstBufferSize)) { /* still to read, or still to flush */ 8147f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet /* Decode Input (at least partially) */ 8157f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet size_t remaining = readSize - pos; 816197982ec6cf449734f78d849ed4a845e075b2cf4Yann Collet decodedBytes = ress.dstBufferSize; 817197982ec6cf449734f78d849ed4a845e075b2cf4Yann Collet nextToLoad = LZ4F_decompress(ress.dCtx, ress.dstBuffer, &decodedBytes, (char*)(ress.srcBuffer)+pos, &remaining, NULL); 818197982ec6cf449734f78d849ed4a845e075b2cf4Yann Collet if (LZ4F_isError(nextToLoad)) EXM_THROW(66, "Decompression error : %s", LZ4F_getErrorName(nextToLoad)); 8197f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet pos += remaining; 8207f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet 821d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet /* Write Block */ 822d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (decodedBytes) { 823f094f531441140f10fd461ba769f49d10f5cd581Yann Collet if (!g_testMode) 824f094f531441140f10fd461ba769f49d10f5cd581Yann Collet storedSkips = LZ4IO_fwriteSparse(dstFile, ress.dstBuffer, decodedBytes, storedSkips); 8257f436a1215f11b0fb872c34f088b8b5888d0630dYann Collet filesize += decodedBytes; 82690c0104c4eaf8f06932990aacf07e60dd21685b9Yann Collet DISPLAYUPDATE(2, "\rDecompressed : %u MB ", (unsigned)(filesize>>20)); 82745a357fd1704e9c6d2d8037277bda62e8c86308eYann Collet } 82826065c3f47381c6ebe56ea114015b3c2b1c2a615Yann Collet 82926065c3f47381c6ebe56ea114015b3c2b1c2a615Yann Collet if (!nextToLoad) break; 83012ab41571ef7fd11b8b2013aa943beae373cef8aYann Collet } 83145a357fd1704e9c6d2d8037277bda62e8c86308eYann Collet } 832c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet /* can be out because readSize == 0, which could be an fread() error */ 833c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet if (ferror(srcFile)) EXM_THROW(67, "Read error"); 83445a357fd1704e9c6d2d8037277bda62e8c86308eYann Collet 8351b95d60c66bfc80b77066f929263cf3aac412434Yann Collet if (!g_testMode) LZ4IO_fwriteSparseEnd(dstFile, storedSkips); 836c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet if (nextToLoad!=0) EXM_THROW(68, "Unfinished stream"); 837197982ec6cf449734f78d849ed4a845e075b2cf4Yann Collet 83869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. return filesize; 83969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 84069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 84169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 8421098d897a0c410306f0ac547c4b92e02922f8ddbYann Collet#define PTSIZE (64 KB) 8431098d897a0c410306f0ac547c4b92e02922f8ddbYann Collet#define PTSIZET (PTSIZE / sizeof(size_t)) 844a430b859cf552aa43215fe082e15a95c8bda5d6fYann Colletstatic unsigned long long LZ4IO_passThrough(FILE* finput, FILE* foutput, unsigned char MNstore[MAGICNUMBER_SIZE]) 845e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet{ 8461098d897a0c410306f0ac547c4b92e02922f8ddbYann Collet size_t buffer[PTSIZET]; 847a38cbf9f62a9d7200086b9965745ad7330cac259Yann Collet size_t readBytes = 1; 848e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet unsigned long long total = MAGICNUMBER_SIZE; 849113b150f0aeb3512b2850a65a824ad87f605187eYann Collet unsigned storedSkips = 0; 850e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet 851d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet size_t const sizeCheck = fwrite(MNstore, 1, MAGICNUMBER_SIZE, foutput); 852a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet if (sizeCheck != MAGICNUMBER_SIZE) EXM_THROW(50, "Pass-through write error"); 853e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet 854a38cbf9f62a9d7200086b9965745ad7330cac259Yann Collet while (readBytes) { 855a38cbf9f62a9d7200086b9965745ad7330cac259Yann Collet readBytes = fread(buffer, 1, PTSIZE, finput); 856a38cbf9f62a9d7200086b9965745ad7330cac259Yann Collet total += readBytes; 857a38cbf9f62a9d7200086b9965745ad7330cac259Yann Collet storedSkips = LZ4IO_fwriteSparse(foutput, buffer, readBytes, storedSkips); 858e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet } 859c66108ceb2b51f452511ecb38ad157e7d3d73269Yann Collet if (ferror(finput)) EXM_THROW(51, "Read Error") 860e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet 861113b150f0aeb3512b2850a65a824ad87f605187eYann Collet LZ4IO_fwriteSparseEnd(foutput, storedSkips); 862e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet return total; 863e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet} 864e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet 865e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet 866d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet/** Safely handle cases when (unsigned)offset > LONG_MAX */ 867d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Colletstatic int fseek_u32(FILE *fp, unsigned offset, int where) 868d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet{ 869d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet const unsigned stepMax = 1U << 30; 870d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet int errorNb = 0; 871d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet 872d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (where != SEEK_CUR) return -1; /* Only allows SEEK_CUR */ 873d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet while (offset > 0) { 874d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet unsigned s = offset; 875d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (s > stepMax) s = stepMax; 876d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet errorNb = fseek(fp, (long) s, SEEK_CUR); 877d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (errorNb != 0) break; 878d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet offset -= s; 879d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet } 880d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet return errorNb; 881d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet} 882d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet 88389d8b98d0dd896dccf6964fa3c6bb6ae6a2349b0Yann Collet#define ENDOFSTREAM ((unsigned long long)-1) 884a430b859cf552aa43215fe082e15a95c8bda5d6fYann Colletstatic unsigned long long selectDecoder(dRess_t ress, FILE* finput, FILE* foutput) 88569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 886a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet unsigned char MNstore[MAGICNUMBER_SIZE]; 887d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet unsigned magicNumber; 888e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet static unsigned nbCalls = 0; 889e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet 890e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet /* init */ 891e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet nbCalls++; 89269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 8938a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Check Archive Header */ 894d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (g_magicRead) { /* magic number already read from finput (see legacy frame)*/ 89562ed15319570d80690915f0d0dba0dc2e9478631Yann Collet magicNumber = g_magicRead; 89662ed15319570d80690915f0d0dba0dc2e9478631Yann Collet g_magicRead = 0; 897d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet } else { 898d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet size_t const nbReadBytes = fread(MNstore, 1, MAGICNUMBER_SIZE, finput); 899fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet if (nbReadBytes==0) { nbCalls = 0; return ENDOFSTREAM; } /* EOF */ 90062ed15319570d80690915f0d0dba0dc2e9478631Yann Collet if (nbReadBytes != MAGICNUMBER_SIZE) EXM_THROW(40, "Unrecognized header : Magic Number unreadable"); 901a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet magicNumber = LZ4IO_readLE32(MNstore); /* Little Endian format */ 90262ed15319570d80690915f0d0dba0dc2e9478631Yann Collet } 9037d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet if (LZ4IO_isSkippableMagicNumber(magicNumber)) magicNumber = LZ4IO_SKIPPABLE0; /* fold skippable magic numbers */ 90469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 90569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. switch(magicNumber) 90669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. { 9077d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet case LZ4IO_MAGICNUMBER: 908a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet return LZ4IO_decompressLZ4F(ress, finput, foutput); 90969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. case LEGACY_MAGICNUMBER: 91069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. DISPLAYLEVEL(4, "Detected : Legacy format \n"); 911113b150f0aeb3512b2850a65a824ad87f605187eYann Collet return LZ4IO_decodeLegacyStream(finput, foutput); 9127d87d43e619b0296bbe3f1674f10575b3f68c189Yann Collet case LZ4IO_SKIPPABLE0: 91369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. DISPLAYLEVEL(4, "Skipping detected skippable area \n"); 914d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { size_t const nbReadBytes = fread(MNstore, 1, 4, finput); 915d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (nbReadBytes != 4) EXM_THROW(42, "Stream error : skippable size unreadable"); } 916d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { unsigned const size = LZ4IO_readLE32(MNstore); /* Little Endian format */ 917d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet int const errorNb = fseek_u32(finput, size, SEEK_CUR); 918d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (errorNb != 0) EXM_THROW(43, "Stream error : cannot skip skippable area"); } 919d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet return 0; 920d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet EXTENDED_FORMAT; /* macro extension for custom formats */ 92169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. default: 922d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (nbCalls == 1) { /* just started */ 923fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet if (!g_testMode && g_overwrite) { 924fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet nbCalls = 0; 925a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet return LZ4IO_passThrough(finput, foutput, MNstore); 926fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet } 927e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet EXM_THROW(44,"Unrecognized header : file cannot be decoded"); /* Wrong magic number at the beginning of 1st stream */ 928e7fb4d151d104764e5e8f988c679fdff8807683eYann Collet } 929d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet DISPLAYLEVEL(2, "Stream followed by undecodable data\n"); 93089d8b98d0dd896dccf6964fa3c6bb6ae6a2349b0Yann Collet return ENDOFSTREAM; 93169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. } 93269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 93369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 93469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 935fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Colletstatic int LZ4IO_decompressSrcFile(dRess_t ress, const char* input_filename, const char* output_filename) 93669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{ 937fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet FILE* const foutput = ress.dstFile; 93869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. unsigned long long filesize = 0, decodedSize=0; 93969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. FILE* finput; 94069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 9418a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Init */ 942f34808e4ae183d049e5e13949941d44876fdb90cYann Collet finput = LZ4IO_openSrcFile(input_filename); 943f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (finput==NULL) return 1; 94469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 9458a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Loop over multiple streams */ 946d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet do { 947a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet decodedSize = selectDecoder(ress, finput, foutput); 94889d8b98d0dd896dccf6964fa3c6bb6ae6a2349b0Yann Collet if (decodedSize != ENDOFSTREAM) 94989d8b98d0dd896dccf6964fa3c6bb6ae6a2349b0Yann Collet filesize += decodedSize; 95089d8b98d0dd896dccf6964fa3c6bb6ae6a2349b0Yann Collet } while (decodedSize != ENDOFSTREAM); 95169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 9528a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet /* Close */ 95369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. fclose(finput); 954fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet 955fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet if (g_removeSrcFile) { if (remove(input_filename)) EXM_THROW(45, "Remove error : %s: %s", input_filename, strerror(errno)); } /* remove source file : --rm */ 956fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet 957fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet /* Final Status */ 958fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet DISPLAYLEVEL(2, "\r%79s\r", ""); 959fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet DISPLAYLEVEL(2, "%-20.20s : decoded %llu bytes \n", input_filename, filesize); 960f34808e4ae183d049e5e13949941d44876fdb90cYann Collet (void)output_filename; 961fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet 962fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet return 0; 963fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet} 964fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet 965fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet 966fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Colletstatic int LZ4IO_decompressDstFile(dRess_t ress, const char* input_filename, const char* output_filename) 967fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet{ 968fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet FILE* foutput; 969fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet 970fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet /* Init */ 971f34808e4ae183d049e5e13949941d44876fdb90cYann Collet foutput = LZ4IO_openDstFile(output_filename); 972f34808e4ae183d049e5e13949941d44876fdb90cYann Collet if (foutput==NULL) return 1; /* failure */ 973fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet 974fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet ress.dstFile = foutput; 975fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet LZ4IO_decompressSrcFile(ress, input_filename, output_filename); 976fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet 97769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. fclose(foutput); 97869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 979ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski /* Copy owner, file permissions and modification time */ 980ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski { stat_t statbuf; 981ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski if (strcmp (input_filename, stdinmark) && strcmp (output_filename, stdoutmark) && UTIL_getFileStat(input_filename, &statbuf)) 982ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski UTIL_setFileStat(output_filename, &statbuf); 983ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski } 984ef54f9f9dd5d69ab69a085f25adaf4ce4533fe5cPrzemyslaw Skibinski 98569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. return 0; 98669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.} 98769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet. 988c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 989a430b859cf552aa43215fe082e15a95c8bda5d6fYann Colletint LZ4IO_decompressFilename(const char* input_filename, const char* output_filename) 990a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet{ 991d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet dRess_t const ress = LZ4IO_createDResources(); 992d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet clock_t const start = clock(); 993a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 994fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet int const missingFiles = LZ4IO_decompressDstFile(ress, input_filename, output_filename); 995a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 996d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet { clock_t const end = clock(); 997d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet double const seconds = (double)(end - start) / CLOCKS_PER_SEC; 998a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet DISPLAYLEVEL(4, "Done in %.2f sec \n", seconds); 999a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet } 1000a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 1001d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet LZ4IO_freeDResources(ress); 1002a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet return missingFiles; 1003a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet} 1004a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 1005a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 1006c64200dd85a85d9cc69a6fda682362d851be863bYann Colletint LZ4IO_decompressMultipleFilenames(const char** inFileNamesTable, int ifntSize, const char* suffix) 1007c64200dd85a85d9cc69a6fda682362d851be863bYann Collet{ 1008c64200dd85a85d9cc69a6fda682362d851be863bYann Collet int i; 1009a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet int skippedFiles = 0; 1010a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet int missingFiles = 0; 1011c64200dd85a85d9cc69a6fda682362d851be863bYann Collet char* outFileName = (char*)malloc(FNSPACE); 1012c64200dd85a85d9cc69a6fda682362d851be863bYann Collet size_t ofnSize = FNSPACE; 1013d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet size_t const suffixSize = strlen(suffix); 1014fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet dRess_t ress = LZ4IO_createDResources(); 1015a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 1016de0cf5de640eb56775f44c0f4c7c7a065e00447cPrzemyslaw Skibinski if (outFileName==NULL) return ifntSize; /* not enough memory */ 1017f34808e4ae183d049e5e13949941d44876fdb90cYann Collet ress.dstFile = LZ4IO_openDstFile(stdoutmark); 1018c64200dd85a85d9cc69a6fda682362d851be863bYann Collet 1019d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet for (i=0; i<ifntSize; i++) { 1020d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet size_t const ifnSize = strlen(inFileNamesTable[i]); 1021d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet const char* const suffixPtr = inFileNamesTable[i] + ifnSize - suffixSize; 1022fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet if (!strcmp(suffix, stdoutmark)) { 1023fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet missingFiles += LZ4IO_decompressSrcFile(ress, inFileNamesTable[i], stdoutmark); 1024fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet continue; 1025fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet } 1026de0cf5de640eb56775f44c0f4c7c7a065e00447cPrzemyslaw Skibinski if (ofnSize <= ifnSize-suffixSize+1) { free(outFileName); ofnSize = ifnSize + 20; outFileName = (char*)malloc(ofnSize); if (outFileName==NULL) return ifntSize; } 1027d05ca2ff6d7ea79ad1426c6cb3f5260ec8af26b9Yann Collet if (ifnSize <= suffixSize || strcmp(suffixPtr, suffix) != 0) { 1028bce2eeb9dfbca883003f21681e21df657fac90c4Yann Collet DISPLAYLEVEL(1, "File extension doesn't match expected LZ4_EXTENSION (%4s); will not process file: %s\n", suffix, inFileNamesTable[i]); 1029a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet skippedFiles++; 1030c64200dd85a85d9cc69a6fda682362d851be863bYann Collet continue; 1031c64200dd85a85d9cc69a6fda682362d851be863bYann Collet } 1032c64200dd85a85d9cc69a6fda682362d851be863bYann Collet memcpy(outFileName, inFileNamesTable[i], ifnSize - suffixSize); 1033c64200dd85a85d9cc69a6fda682362d851be863bYann Collet outFileName[ifnSize-suffixSize] = '\0'; 1034fe48cef50ed6d3585dcd81eae2ae0998172e8cd7Yann Collet missingFiles += LZ4IO_decompressDstFile(ress, inFileNamesTable[i], outFileName); 1035c64200dd85a85d9cc69a6fda682362d851be863bYann Collet } 1036a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet 1037a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet LZ4IO_freeDResources(ress); 1038c64200dd85a85d9cc69a6fda682362d851be863bYann Collet free(outFileName); 1039a430b859cf552aa43215fe082e15a95c8bda5d6fYann Collet return missingFiles + skippedFiles; 1040c64200dd85a85d9cc69a6fda682362d851be863bYann Collet} 1041