Updated : cmake/CMakeLists.txt, by Nobuhiro Iwamatsu

Updated : cmake/pack/CMakeLists.txt, by Dmitry Cherepanov
lz4demo : CLI accept aggregated commands
lz4demo : detect overwrite output
lz4demo : new commands options (-hc, -y)

git-svn-id: https://lz4.googlecode.com/svn/trunk@91 650e7d94-2a16-8b24-b05c-7c0b3f6821cd
This commit is contained in:
yann.collet.73@gmail.com 2013-03-30 21:11:40 +00:00
parent 633c51904e
commit 647baabcef
7 changed files with 390 additions and 323 deletions

View File

@ -83,6 +83,12 @@ if(BUILD_SHARED_LIBS)
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
install(FILES
${SRC_DIR}/lz4.h
${SRC_DIR}/lz4hc.h
DESTINATION include)
endif(BUILD_SHARED_LIBS)

View File

@ -2,7 +2,7 @@ cmake_minimum_required (VERSION 2.8)
PROJECT(LZ4)
############################## CPACK
set(SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../)
set(SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../)
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "LZ4 Packer")
set(CPACK_PACKAGE_VERSION_MAJOR 0)
set(CPACK_PACKAGE_VERSION_MINOR 0)

View File

@ -1,21 +0,0 @@
lz4demo and fuzzer is an open-source demo compression algorithm LZ4 programs
Copyright (C) Yann Collet 2012
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
You can contact the author at :
- LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
- LZ4 source repository : http://code.google.com/p/lz4/

View File

@ -36,6 +36,7 @@
#include <stdio.h> // fgets, sscanf
#include <sys/timeb.h> // timeb
#include "lz4.h"
#include "lz4hc.h"
//**************************************
@ -110,7 +111,7 @@ int FUZ_SecurityTest()
free(input);
free(output);
printf(" Completed (r=%i)\n",r);
printf(" Completed (return = %i < 0)\n",r);
return 0;
}

1
lz4.c
View File

@ -710,6 +710,7 @@ int LZ4_compress(const char* source,
// are safe against "buffer overflow" attack type.
// They will never write nor read outside of the provided output buffers.
// LZ4_uncompress_unknownOutputSize() also insures that it will never read outside of the input buffer.
// LZ4_uncompress() guarantees that it will never read before source, nor beyond source + LZ4_compressBound(osize)
// A corrupted input will produce an error result, a negative int, indicating the position of the error within input stream.
int LZ4_uncompress(const char* source,

2
lz4.h
View File

@ -66,7 +66,7 @@ LZ4_compress() :
LZ4_uncompress() :
osize : is the output size, therefore the original size
return : the number of bytes read in the source buffer
return : the number of bytes read in the source buffer (in other words, the compressed size)
If the source stream is malformed, the function will stop decoding and return a negative result, indicating the byte position of the faulty instruction
This function never writes outside of provided buffers, and never modifies input buffer.
note : destination buffer must be already allocated.

152
lz4demo.c
View File

@ -102,6 +102,26 @@ static const int one = 1;
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
//**************************************
// Special input/output
//**************************************
#define NULL_INPUT "null"
char stdinmark[] = "stdin";
char stdoutmark[] = "stdout";
#ifdef _WIN32
char nulmark[] = "nul";
#else
char nulmark[] = "/dev/null";
#endif
//**************************************
// I/O Parameters
//**************************************
static int overwrite = 0;
//****************************
// Functions
//****************************
@ -110,12 +130,13 @@ int usage(char* exename)
DISPLAY( "Usage :\n");
DISPLAY( " %s [arg] input output\n", exename);
DISPLAY( "Arguments :\n");
DISPLAY( " -c0: Fast compression (default) \n");
DISPLAY( " -c1: High compression \n");
DISPLAY( " -c0/-c : Fast compression (default) \n");
DISPLAY( " -c1/-hc: High compression \n");
DISPLAY( " -d : decompression \n");
DISPLAY( " -b#: Benchmark files, using # compression level\n");
DISPLAY( " -y : overwrite output \n");
DISPLAY( " -t : check compressed file \n");
DISPLAY( " -h : help (this text)\n");
DISPLAY( " -b# : Benchmark files, using # compression level\n");
DISPLAY( " -H : help (this text)\n");
DISPLAY( "input : can be 'stdin' (pipe) or a filename\n");
DISPLAY( "output : can be 'stdout'(pipe) or a filename or 'null'\n");
return 0;
@ -130,34 +151,52 @@ int badusage(char* exename)
}
int get_fileHandle(char* input_filename, char* output_filename, FILE** pfinput, FILE** pfoutput)
{
char stdinmark[] = "stdin";
char stdoutmark[] = "stdout";
if (!strcmp (input_filename, stdinmark)) {
if (!strcmp (input_filename, stdinmark))
{
DISPLAY( "Using stdin for input\n");
*pfinput = stdin;
#ifdef _WIN32 // Need to set stdin/stdout to binary mode specifically for windows
_setmode( _fileno( stdin ), _O_BINARY );
#endif
} else {
}
else
{
*pfinput = fopen(input_filename, "rb");
}
if (!strcmp (output_filename, stdoutmark)) {
if (!strcmp (output_filename, stdoutmark))
{
DISPLAY( "Using stdout for output\n");
*pfoutput = stdout;
#ifdef _WIN32 // Need to set stdin/stdout to binary mode specifically for windows
_setmode( _fileno( stdout ), _O_BINARY );
#endif
} else {
}
else
{
// Check if destination file already exists
*pfoutput=0;
if (output_filename != nulmark) *pfoutput = fopen( output_filename, "rb" );
if (*pfoutput!=0)
{
char ch;
fclose(*pfoutput);
DISPLAY( "Warning : %s already exists\n", output_filename);
if (!overwrite)
{
DISPLAY( "Overwrite ? (Y/N) : ");
ch = getchar();
if (ch!='Y') { DISPLAY( "Operation aborted : %s already exists\n", output_filename); return 12; }
}
}
*pfoutput = fopen( output_filename, "wb" );
}
if ( *pfinput==0 ) { DISPLAY( "Pb opening %s\n", input_filename); return 2; }
if ( *pfoutput==0) { DISPLAY( "Pb opening %s\n", output_filename); return 3; }
if ( *pfinput==0 ) { DISPLAY( "Pb opening %s\n", input_filename); return 13; }
if ( *pfoutput==0) { DISPLAY( "Pb opening %s\n", output_filename); return 14; }
return 0;
}
@ -194,14 +233,14 @@ int compress_file(char* input_filename, char* output_filename, int compressionle
// Allocate Memory
in_buff = (char*)malloc(CHUNKSIZE);
out_buff = (char*)malloc(LZ4_compressBound(CHUNKSIZE));
if (!in_buff || !out_buff) { DISPLAY("Allocation error : not enough memory\n"); return 8; }
if (!in_buff || !out_buff) { DISPLAY("Allocation error : not enough memory\n"); return 21; }
// Write Archive Header
u32var = ARCHIVE_MAGICNUMBER;
LITTLE_ENDIAN32(u32var);
*(unsigned int*)out_buff = u32var;
sizeCheck = fwrite(out_buff, 1, ARCHIVE_MAGICNUMBER_SIZE, foutput);
if (sizeCheck!=ARCHIVE_MAGICNUMBER_SIZE) { DISPLAY("write error\n"); return 10; }
if (sizeCheck!=ARCHIVE_MAGICNUMBER_SIZE) { DISPLAY("write error\n"); return 22; }
// Main Loop
while (1)
@ -268,13 +307,13 @@ int decode_file(char* input_filename, char* output_filename)
// Allocate Memory
in_buff = (char*)malloc(LZ4_compressBound(CHUNKSIZE));
out_buff = (char*)malloc(CHUNKSIZE);
if (!in_buff || !out_buff) { DISPLAY("Allocation error : not enough memory\n"); return 7; }
if (!in_buff || !out_buff) { DISPLAY("Allocation error : not enough memory\n"); return 31; }
// Check Archive Header
chunkSize = 0;
uselessRet = fread(&chunkSize, 1, ARCHIVE_MAGICNUMBER_SIZE, finput);
LITTLE_ENDIAN32(chunkSize);
if (chunkSize != ARCHIVE_MAGICNUMBER) { DISPLAY("Unrecognized header : file cannot be decoded\n"); return 6; }
if (chunkSize != ARCHIVE_MAGICNUMBER) { DISPLAY("Unrecognized header : file cannot be decoded\n"); return 32; }
// Main Loop
while (1)
@ -291,12 +330,12 @@ int decode_file(char* input_filename, char* output_filename)
// Decode Block
sinkint = LZ4_uncompress_unknownOutputSize(in_buff, out_buff, chunkSize, CHUNKSIZE);
if (sinkint < 0) { DISPLAY("Decoding Failed ! Corrupted input !\n"); return 9; }
if (sinkint < 0) { DISPLAY("Decoding Failed ! Corrupted input !\n"); return 33; }
filesize += sinkint;
// Write Block
sizeCheck = fwrite(out_buff, 1, sinkint, foutput);
if (sizeCheck != (size_t)sinkint) { DISPLAY("write error\n"); return 12; }
if (sizeCheck != (size_t)sinkint) { DISPLAY("write error\n"); return 34; }
}
// Status
@ -327,12 +366,8 @@ int main(int argc, char** argv)
char* exename=argv[0];
char* input_filename=0;
char* output_filename=0;
#ifdef _WIN32
char nulmark[] = "nul";
#else
char nulmark[] = "/dev/null";
#endif
char nullinput[] = "null";
char nullinput[] = NULL_INPUT;
char extension[] = EXTENSION;
// Welcome message
DISPLAY( WELCOME_MESSAGE);
@ -345,34 +380,64 @@ int main(int argc, char** argv)
if(!argument) continue; // Protection if argument empty
// Select command
// Decode command (note : aggregated commands are allowed)
if (argument[0]=='-')
{
while (argument[1]!=0)
{
argument ++;
switch(argument[0])
{
// Display help on usage
if ( argument[0] =='h' ) { usage(exename); return 0; }
case 'H': usage(exename); return 0;
// Compression (default)
if ( argument[0] =='c' ) { if (argument[1] >='0') cLevel=argument[1] - '0'; continue; }
case 'c': if ((argument[1] >='0') && (argument[1] <='1')) { cLevel=argument[1] - '0'; argument++; } break;
case 'h': if (argument[1]=='c') { cLevel=1; argument++; } break;
// Decoding
if ( argument[0] =='d' ) { decode=1; continue; }
case 'd': decode=1; break;
// Bench
if ( argument[0] =='b' ) { bench=1; if (argument[1] >= '0') cLevel=argument[1] - '0'; continue; }
case 'b': bench=1;
if ((argument[1] >='0') && (argument[1] <='1')) { cLevel=argument[1] - '0'; argument++; }
break;
// Modify Block Size (benchmark only)
if ( argument[0] =='B' ) { int B = argument[1] - '0'; int S = 1 << (10 + 2*B); BMK_SetBlocksize(S); continue; }
case 'B':
if ((argument[1] >='0') && (argument[1] <='9'))
{
int B = argument[1] - '0';
int S = 1 << (10 + 2*B); BMK_SetBlocksize(S);
argument++;
}
break;
// Modify Nb Iterations (benchmark only)
if ( argument[0] =='i' ) { int iters = argument[1] - '0'; BMK_SetNbIterations(iters); continue; }
case 'i':
if ((argument[1] >= '0') && (argument[1] <= '9'))
{
int iters = argument[1] - '0';
BMK_SetNbIterations(iters);
argument++;
}
break;
// Pause at the end (benchmark only)
if ( argument[0] =='p' ) { BMK_SetPause(); continue; }
case 'p': BMK_SetPause(); break;
// Test
if ( argument[0] =='t' ) { decode=1; output_filename=nulmark; continue; }
case 't': decode=1; output_filename=nulmark; break;
// Overwrite
case 'y': overwrite=1; break;
// Unrecognised command
default : badusage(exename); return 1;
}
}
continue;
}
// first provided filename is input
@ -392,8 +457,23 @@ int main(int argc, char** argv)
if (bench) return BMK_benchFile(argv+filenamesStart, argc-filenamesStart, cLevel);
// No output filename ==> Error
if (!output_filename) { badusage(exename); return 1; }
// No output filename ==> build one automatically (for compression only)
if (!output_filename)
{
if (!decode)
{
int i=0, l=0;
while (input_filename[l]!=0) l++;
output_filename = (char*)calloc(1,l+5);
for (i=0;i<l;i++) output_filename[i] = input_filename[i];
for (i=l;i<l+4;i++) output_filename[i] = extension[i-l];
}
else
{
badusage(exename);
return 1;
}
}
if (decode) return decode_file(input_filename, output_filename);