1
0
Fork 0

Adding upstream version 1.7.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-23 19:21:39 +01:00
parent f87096b5dd
commit 29d0941b98
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
17 changed files with 298 additions and 190 deletions

View file

@ -1,3 +1,13 @@
2016-05-16 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.7 released.
* main.c: Added new option '-a, --trailing-error'.
* main.c (main): Delete '--output' file if infd is a terminal.
* main.c (main): Don't use stdin more than once.
* configure: Avoid warning on some shells when testing for gcc.
* testsuite/check.sh: A POSIX shell is required to run the tests.
* testsuite/check.sh: Don't check error messages.
2015-05-26 Antonio Diaz Diaz <antonio@gnu.org> 2015-05-26 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.6 released. * Version 1.6 released.
@ -7,7 +17,7 @@
2013-09-14 Antonio Diaz Diaz <antonio@gnu.org> 2013-09-14 Antonio Diaz Diaz <antonio@gnu.org>
* Version 1.5 released. * Version 1.5 released.
* main.c (show_header): Do not show header version in lzip mode. * main.c (show_header): Don't show header version in lzip mode.
* Minor fixes. * Minor fixes.
2013-05-27 Antonio Diaz Diaz <antonio@gnu.org> 2013-05-27 Antonio Diaz Diaz <antonio@gnu.org>
@ -57,7 +67,7 @@
* Using LZMA SDK 9.10 (public domain) from Igor Pavlov. * Using LZMA SDK 9.10 (public domain) from Igor Pavlov.
Copyright (C) 2010-2015 Antonio Diaz Diaz. Copyright (C) 2010-2016 Antonio Diaz Diaz.
This file is a collection of facts, and thus it is not copyrightable, This file is a collection of facts, and thus it is not copyrightable,
but just in case, you have unlimited permission to copy, distribute and but just in case, you have unlimited permission to copy, distribute and

View file

@ -1,7 +1,7 @@
Requirements Requirements
------------ ------------
You will need a C compiler. You will need a C compiler.
I use gcc 4.9.1 and 4.1.2, but the code should compile with any I use gcc 5.3.0 and 4.1.2, but the code should compile with any
standards compliant compiler. standards compliant compiler.
Gcc is available at http://gcc.gnu.org. Gcc is available at http://gcc.gnu.org.
@ -61,7 +61,7 @@ After running 'configure', you can run 'make' and 'make install' as
explained above. explained above.
Copyright (C) 2010-2015 Antonio Diaz Diaz. Copyright (C) 2010-2016 Antonio Diaz Diaz.
This file is free documentation: you have unlimited permission to copy, This file is free documentation: you have unlimited permission to copy,
distribute and modify it. distribute and modify it.

View file

@ -4,6 +4,7 @@
#define _FILE_OFFSET_BITS 64 #define _FILE_OFFSET_BITS 64
#include <errno.h> #include <errno.h>
#include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>

View file

@ -4,6 +4,7 @@
#define _FILE_OFFSET_BITS 64 #define _FILE_OFFSET_BITS 64
#include <errno.h> #include <errno.h>
#include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>

View file

@ -3,6 +3,7 @@
#define _FILE_OFFSET_BITS 64 #define _FILE_OFFSET_BITS 64
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -1371,7 +1372,7 @@ static void LZe_full_flush(CLzmaEnc *p, uint32_t posState)
unsigned long long in_size = p->nowPos64; unsigned long long in_size = p->nowPos64;
unsigned long long out_size = p->rc.processed + Fh_size + Ft_size; unsigned long long out_size = p->rc.processed + Fh_size + Ft_size;
if( in_size <= 0 || out_size <= 0 ) if( in_size <= 0 || out_size <= 0 )
fprintf( stderr, " no data compressed.\n" ); fputs( " no data compressed.\n", stderr );
else else
fprintf( stderr, "%6.3f:1, %6.3f bits/byte, " fprintf( stderr, "%6.3f:1, %6.3f bits/byte, "
"%5.2f%% saved, %llu in, %llu out.\n", "%5.2f%% saved, %llu in, %llu out.\n",

View file

@ -5,6 +5,7 @@ INSTALL_PROGRAM = $(INSTALL) -m 755
INSTALL_DATA = $(INSTALL) -m 644 INSTALL_DATA = $(INSTALL) -m 644
INSTALL_DIR = $(INSTALL) -d -m 755 INSTALL_DIR = $(INSTALL) -d -m 755
SHELL = /bin/sh SHELL = /bin/sh
CAN_RUN_INSTALLINFO = $(SHELL) -c "install-info --version" > /dev/null 2>&1
objs = carg_parser.o LzFind.o LzmaEnc.o LzmaDec.o main.o objs = carg_parser.o LzFind.o LzmaEnc.o LzmaDec.o main.o
@ -68,7 +69,9 @@ install-info :
if [ ! -d "$(DESTDIR)$(infodir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(infodir)" ; fi if [ ! -d "$(DESTDIR)$(infodir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(infodir)" ; fi
-rm -f "$(DESTDIR)$(infodir)/$(pkgname).info"* -rm -f "$(DESTDIR)$(infodir)/$(pkgname).info"*
$(INSTALL_DATA) $(VPATH)/doc/$(pkgname).info "$(DESTDIR)$(infodir)/$(pkgname).info" $(INSTALL_DATA) $(VPATH)/doc/$(pkgname).info "$(DESTDIR)$(infodir)/$(pkgname).info"
-install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$(pkgname).info" -if $(CAN_RUN_INSTALLINFO) ; then \
install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$(pkgname).info" ; \
fi
install-info-compress : install-info install-info-compress : install-info
lzip -v -9 "$(DESTDIR)$(infodir)/$(pkgname).info" lzip -v -9 "$(DESTDIR)$(infodir)/$(pkgname).info"
@ -91,7 +94,9 @@ uninstall-bin :
-rm -f "$(DESTDIR)$(bindir)/$(progname)" -rm -f "$(DESTDIR)$(bindir)/$(progname)"
uninstall-info : uninstall-info :
-install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$(pkgname).info" -if $(CAN_RUN_INSTALLINFO) ; then \
install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$(pkgname).info" ; \
fi
-rm -f "$(DESTDIR)$(infodir)/$(pkgname).info"* -rm -f "$(DESTDIR)$(infodir)/$(pkgname).info"*
uninstall-man : uninstall-man :

15
NEWS
View file

@ -1,8 +1,11 @@
Changes in version 1.6: Changes in version 1.7:
Copying of file dates, permissions, and ownership now behaves like "cp -p". The option "-a, --trailing-error", which makes pdlzip exit with error
(If the user ID or the group ID can't be duplicated, the file permission status 2 if any remaining input is detected after decompressing the last
bits S_ISUID and S_ISGID are cleared). member, has been added.
The targets "install-compress", "install-strip-compress" and When decompressing, the file specified with the '--output' option is now
"install-man-compress" have been added to the Makefile. deleted if the input is a terminal.
A harmless check failure on Windows, caused by the failed comparison of
a message in text mode, has been fixed.

13
README
View file

@ -5,8 +5,9 @@ the one of lzip, bzip2 or gzip.
Pdlzip uses the lzip file format; the files produced by pdlzip are Pdlzip uses the lzip file format; the files produced by pdlzip are
(hope)fully compatible with lzip-1.4 or newer. Pdlzip is in fact a (hope)fully compatible with lzip-1.4 or newer. Pdlzip is in fact a
"public domain" version of the lzip data compressor, intended for those permissively licensed implementation of the lzip data compressor,
who can't distribute (or even use) GPL licensed Free Software. intended for those who can't distribute (or even use) GPL licensed Free
Software. (The name of pdlzip comes from "public domain lzip").
The lzip file format is designed for data sharing and long-term The lzip file format is designed for data sharing and long-term
archiving, taking into account both data integrity and decoder archiving, taking into account both data integrity and decoder
@ -34,8 +35,10 @@ the help of lziprecover, losing an entire archive just because of a
corrupt byte near the beginning is a thing of the past. corrupt byte near the beginning is a thing of the past.
Pdlzip is also able to decompress legacy lzma-alone (.lzma) files. Pdlzip is also able to decompress legacy lzma-alone (.lzma) files.
Lzma-alone is a very bad format. If you keep any lzma-alone files, it is Lzma-alone is a very bad format; it is essentially a raw LZMA stream.
advisable to recompress them to lzip format. If you keep any lzma-alone files, it is advisable to recompress them to
lzip format. Lziprecover can convert lzma-alone files to lzip format
without recompressing.
Pdlzip is written in C. Pdlzip is written in C.
@ -49,7 +52,7 @@ users of the most non-free platforms can share lzip files with everybody
else. else.
Copyright (C) 2010-2015 Antonio Diaz Diaz. Copyright (C) 2010-2016 Antonio Diaz Diaz.
This file is free documentation: you have unlimited permission to copy, This file is free documentation: you have unlimited permission to copy,
distribute and modify it. distribute and modify it.

View file

@ -1,5 +1,5 @@
/* Arg_parser - POSIX/GNU command line argument parser. (C version) /* Arg_parser - POSIX/GNU command line argument parser. (C version)
Copyright (C) 2006-2015 Antonio Diaz Diaz. Copyright (C) 2006-2016 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided binary forms, with or without modification, are permitted provided

View file

@ -1,5 +1,5 @@
/* Arg_parser - POSIX/GNU command line argument parser. (C version) /* Arg_parser - POSIX/GNU command line argument parser. (C version)
Copyright (C) 2006-2015 Antonio Diaz Diaz. Copyright (C) 2006-2016 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided binary forms, with or without modification, are permitted provided

14
configure vendored
View file

@ -1,12 +1,12 @@
#! /bin/sh #! /bin/sh
# configure script for Pdlzip - LZMA lossless data compressor # configure script for Pdlzip - LZMA lossless data compressor
# Copyright (C) 2010-2015 Antonio Diaz Diaz. # Copyright (C) 2010-2016 Antonio Diaz Diaz.
# #
# This configure script is free software: you have unlimited permission # This configure script is free software: you have unlimited permission
# to copy, distribute and modify it. # to copy, distribute and modify it.
pkgname=pdlzip pkgname=pdlzip
pkgversion=1.6 pkgversion=1.7
progname=pdlzip progname=pdlzip
srctrigger=doc/${progname}.1 srctrigger=doc/${progname}.1
@ -26,8 +26,8 @@ CFLAGS='-Wall -W -O2'
LDFLAGS= LDFLAGS=
# checking whether we are using GNU C. # checking whether we are using GNU C.
${CC} --version > /dev/null 2>&1 if /bin/sh -c "${CC} --version" > /dev/null 2>&1 ; then true
if [ $? != 0 ] ; then else
CC=cc CC=cc
CFLAGS='-W -O2' CFLAGS='-W -O2'
fi fi
@ -139,7 +139,7 @@ if [ -z "${no_create}" ] ; then
rm -f config.status rm -f config.status
cat > config.status << EOF cat > config.status << EOF
#! /bin/sh #! /bin/sh
# This file was generated automatically by configure. Do not edit. # This file was generated automatically by configure. Don't edit.
# Run this file to recreate the current configuration. # Run this file to recreate the current configuration.
# #
# This script is free software: you have unlimited permission # This script is free software: you have unlimited permission
@ -165,8 +165,8 @@ echo "LDFLAGS = ${LDFLAGS}"
rm -f Makefile rm -f Makefile
cat > Makefile << EOF cat > Makefile << EOF
# Makefile for Pdlzip - LZMA lossless data compressor # Makefile for Pdlzip - LZMA lossless data compressor
# Copyright (C) 2010-2015 Antonio Diaz Diaz. # Copyright (C) 2010-2016 Antonio Diaz Diaz.
# This file was generated automatically by configure. Do not edit. # This file was generated automatically by configure. Don't edit.
# #
# This Makefile is free software: you have unlimited permission # This Makefile is free software: you have unlimited permission
# to copy, distribute and modify it. # to copy, distribute and modify it.

View file

@ -1,15 +1,18 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1.
.TH PDLZIP "1" "May 2015" "pdlzip 1.6" "User Commands" .TH PDLZIP "1" "May 2016" "pdlzip 1.7" "User Commands"
.SH NAME .SH NAME
pdlzip \- reduces the size of files pdlzip \- reduces the size of files
.SH SYNOPSIS .SH SYNOPSIS
.B pdlzip .B pdlzip
[\fI\,options\/\fR] [\fI\,files\/\fR] [\fI\,options\/\fR] [\fI\,files\/\fR]
.SH DESCRIPTION .SH DESCRIPTION
Pdlzip \- A "public domain" version of the lzip data compressor Pdlzip \- A permissively licensed implementation of the lzip data
also able to decompress legacy lzma\-alone (.lzma) files. compressor also able to decompress legacy lzma\-alone (.lzma) files.
Lzma\-alone is a very bad format. If you keep any lzma\-alone files, it is .PP
advisable to recompress them to lzip format. Lzma\-alone is a very bad format; it is essentially a raw LZMA stream.
If you keep any lzma\-alone files, it is advisable to recompress them to
lzip format. Lziprecover can convert lzma\-alone files to lzip format
without recompressing.
.SH OPTIONS .SH OPTIONS
.TP .TP
\fB\-h\fR, \fB\-\-help\fR \fB\-h\fR, \fB\-\-help\fR
@ -18,8 +21,11 @@ display this help and exit
\fB\-V\fR, \fB\-\-version\fR \fB\-V\fR, \fB\-\-version\fR
output version information and exit output version information and exit
.TP .TP
\fB\-a\fR, \fB\-\-trailing\-error\fR
exit with error status if trailing data
.TP
\fB\-c\fR, \fB\-\-stdout\fR \fB\-c\fR, \fB\-\-stdout\fR
send output to standard output write to standard output, keep input files
.TP .TP
\fB\-d\fR, \fB\-\-decompress\fR \fB\-d\fR, \fB\-\-decompress\fR
decompress decompress
@ -37,7 +43,7 @@ keep (don't delete) input files
set match length limit in bytes [36] set match length limit in bytes [36]
.TP .TP
\fB\-o\fR, \fB\-\-output=\fR<file> \fB\-o\fR, \fB\-\-output=\fR<file>
if reading stdin, place the output into <file> if reading standard input, write to <file>
.TP .TP
\fB\-q\fR, \fB\-\-quiet\fR \fB\-q\fR, \fB\-\-quiet\fR
suppress all messages suppress all messages
@ -60,13 +66,16 @@ alias for \fB\-1\fR
\fB\-\-best\fR \fB\-\-best\fR
alias for \fB\-9\fR alias for \fB\-9\fR
.PP .PP
If no file names are given, pdlzip compresses or decompresses If no file names are given, or if a file is '\-', pdlzip compresses or
from standard input to standard output. decompresses from standard input to standard output.
Numbers may be followed by a multiplier: k = kB = 10^3 = 1000, Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,
Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc... Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...
Dictionary sizes 12 to 27 are interpreted as powers of two, meaning 2^12
to 2^27 bytes.
.PP
The bidimensional parameter space of LZMA can't be mapped to a linear The bidimensional parameter space of LZMA can't be mapped to a linear
scale optimal for all files. If your files are large, very repetitive, scale optimal for all files. If your files are large, very repetitive,
etc, you may need to use the \fB\-\-match\-length\fR and \fB\-\-dictionary\-size\fR etc, you may need to use the \fB\-\-dictionary\-size\fR and \fB\-\-match\-length\fR
options directly to achieve optimal performance. For example, \fB\-9m64\fR options directly to achieve optimal performance. For example, \fB\-9m64\fR
usually compresses executables more (and faster) than \fB\-9\fR. usually compresses executables more (and faster) than \fB\-9\fR.
.PP .PP
@ -79,7 +88,7 @@ Report bugs to lzip\-bug@nongnu.org
.br .br
Pdlzip home page: http://www.nongnu.org/lzip/pdlzip.html Pdlzip home page: http://www.nongnu.org/lzip/pdlzip.html
.SH COPYRIGHT .SH COPYRIGHT
Copyright \(co 2015 Antonio Diaz Diaz. Copyright \(co 2016 Antonio Diaz Diaz.
Public Domain 2009 Igor Pavlov. Public Domain 2009 Igor Pavlov.
License 2\-clause BSD. License 2\-clause BSD.
.br .br

50
lzip.h
View file

@ -1,5 +1,5 @@
/* Pdlzip - LZMA lossless data compressor /* Pdlzip - LZMA lossless data compressor
Copyright (C) 2010-2015 Antonio Diaz Diaz. Copyright (C) 2010-2016 Antonio Diaz Diaz.
This program is free software. Redistribution and use in source and This program is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided binary forms, with or without modification, are permitted provided
@ -17,11 +17,6 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/ */
#ifndef __cplusplus
enum Bool { false = 0, true = 1 };
typedef enum Bool bool;
#endif
#ifndef max #ifndef max
#define max(x,y) ((x) >= (y) ? (x) : (y)) #define max(x,y) ((x) >= (y) ? (x) : (y))
#endif #endif
@ -34,9 +29,10 @@ typedef int State;
enum { enum {
min_dictionary_bits = 12, min_dictionary_bits = 12,
min_dictionary_size = 1 << min_dictionary_bits, min_dictionary_size = 1 << min_dictionary_bits,
max_dictionary_bits = 29, max_dictionary_bits = 27, /* kDicLogSizeMaxCompress */
max_dictionary_size = 1 << max_dictionary_bits, max_dictionary_size = 1 << max_dictionary_bits,
literal_context_bits = 3, literal_context_bits = 3,
literal_pos_state_bits = 0, /* not used */
pos_state_bits = 2, pos_state_bits = 2,
len_low_bits = 3, len_low_bits = 3,
@ -61,7 +57,8 @@ struct Pretty_print
}; };
static inline void Pp_init( struct Pretty_print * const pp, static inline void Pp_init( struct Pretty_print * const pp,
const char * const filenames[], const int num_filenames ) const char * const filenames[],
const int num_filenames, const int verbosity )
{ {
unsigned stdin_name_len; unsigned stdin_name_len;
int i; int i;
@ -71,6 +68,7 @@ static inline void Pp_init( struct Pretty_print * const pp,
pp->first_post = false; pp->first_post = false;
stdin_name_len = strlen( pp->stdin_name ); stdin_name_len = strlen( pp->stdin_name );
if( verbosity <= 0 ) return;
for( i = 0; i < num_filenames; ++i ) for( i = 0; i < num_filenames; ++i )
{ {
const char * const s = filenames[i]; const char * const s = filenames[i];
@ -121,6 +119,11 @@ static inline void CRC32_update_buf( uint32_t * const crc,
} }
static inline bool isvalid_ds( const unsigned dictionary_size )
{ return ( dictionary_size >= min_dictionary_size &&
dictionary_size <= max_dictionary_size ); }
static inline int real_bits( unsigned value ) static inline int real_bits( unsigned value )
{ {
int bits = 0; int bits = 0;
@ -142,6 +145,14 @@ static inline void Fh_set_magic( File_header data )
static inline bool Fh_verify_magic( const File_header data ) static inline bool Fh_verify_magic( const File_header data )
{ return ( memcmp( data, magic_string, 4 ) == 0 ); } { return ( memcmp( data, magic_string, 4 ) == 0 ); }
/* detect truncated header */
static inline bool Fh_verify_prefix( const File_header data, const int size )
{
int i; for( i = 0; i < size && i < 4; ++i )
if( data[i] != magic_string[i] ) return false;
return ( size > 0 );
}
static inline uint8_t Fh_version( const File_header data ) static inline uint8_t Fh_version( const File_header data )
{ return data[4]; } { return data[4]; }
@ -158,21 +169,18 @@ static inline unsigned Fh_get_dictionary_size( const File_header data )
static inline bool Fh_set_dictionary_size( File_header data, const unsigned sz ) static inline bool Fh_set_dictionary_size( File_header data, const unsigned sz )
{ {
if( sz >= min_dictionary_size && sz <= max_dictionary_size ) if( !isvalid_ds( sz ) ) return false;
data[5] = real_bits( sz - 1 );
if( sz > min_dictionary_size )
{ {
data[5] = real_bits( sz - 1 ); const unsigned base_size = 1 << data[5];
if( sz > min_dictionary_size ) const unsigned fraction = base_size / 16;
{ int i;
const unsigned base_size = 1 << data[5]; for( i = 7; i >= 1; --i )
const unsigned fraction = base_size / 16; if( base_size - ( i * fraction ) >= sz )
int i; { data[5] |= ( i << 5 ); break; }
for( i = 7; i >= 1; --i )
if( base_size - ( i * fraction ) >= sz )
{ data[5] |= ( i << 5 ); break; }
}
return true;
} }
return false; return true;
} }

225
main.c
View file

@ -1,6 +1,6 @@
/* Pdlzip - LZMA lossless data compressor /* Pdlzip - LZMA lossless data compressor
2009-08-14 : Igor Pavlov : Public domain 2009-08-14 : Igor Pavlov : Public domain
Copyright (C) 2010-2015 Antonio Diaz Diaz. Copyright (C) 2010-2016 Antonio Diaz Diaz.
This program is free software. Redistribution and use in source and This program is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided binary forms, with or without modification, are permitted provided
@ -30,6 +30,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <limits.h> #include <limits.h>
#include <signal.h> #include <signal.h>
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -65,10 +66,11 @@
#error "Environments where CHAR_BIT != 8 are not supported." #error "Environments where CHAR_BIT != 8 are not supported."
#endif #endif
int verbosity = 0;
const char * const Program_name = "Pdlzip"; const char * const Program_name = "Pdlzip";
const char * const program_name = "pdlzip"; const char * const program_name = "pdlzip";
const char * const program_year = "2015"; const char * const program_year = "2016";
const char * invocation_name = 0; const char * invocation_name = 0;
struct { const char * from; const char * to; } const known_extensions[] = { struct { const char * from; const char * to; } const known_extensions[] = {
@ -87,30 +89,29 @@ enum Mode { m_compress, m_decompress, m_test };
char * output_filename = 0; char * output_filename = 0;
int outfd = -1; int outfd = -1;
int verbosity = 0;
const mode_t usr_rw = S_IRUSR | S_IWUSR;
const mode_t all_rw = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
mode_t outfd_mode = S_IRUSR | S_IWUSR;
bool delete_output_on_interrupt = false; bool delete_output_on_interrupt = false;
static void show_help( void ) static void show_help( void )
{ {
printf( "%s - A \"public domain\" version of the lzip data compressor\n", Program_name ); printf( "%s - A permissively licensed implementation of the lzip data\n", Program_name );
printf( "also able to decompress legacy lzma-alone (.lzma) files.\n" printf( "compressor also able to decompress legacy lzma-alone (.lzma) files.\n"
"Lzma-alone is a very bad format. If you keep any lzma-alone files, it is\n" "\nLzma-alone is a very bad format; it is essentially a raw LZMA stream.\n"
"advisable to recompress them to lzip format.\n" "If you keep any lzma-alone files, it is advisable to recompress them to\n"
"lzip format. Lziprecover can convert lzma-alone files to lzip format\n"
"without recompressing.\n"
"\nUsage: %s [options] [files]\n", invocation_name ); "\nUsage: %s [options] [files]\n", invocation_name );
printf( "\nOptions:\n" printf( "\nOptions:\n"
" -h, --help display this help and exit\n" " -h, --help display this help and exit\n"
" -V, --version output version information and exit\n" " -V, --version output version information and exit\n"
" -c, --stdout send output to standard output\n" " -a, --trailing-error exit with error status if trailing data\n"
" -c, --stdout write to standard output, keep input files\n"
" -d, --decompress decompress\n" " -d, --decompress decompress\n"
" -f, --force overwrite existing output files\n" " -f, --force overwrite existing output files\n"
" -F, --recompress force re-compression of compressed files\n" " -F, --recompress force re-compression of compressed files\n"
" -k, --keep keep (don't delete) input files\n" " -k, --keep keep (don't delete) input files\n"
" -m, --match-length=<bytes> set match length limit in bytes [36]\n" " -m, --match-length=<bytes> set match length limit in bytes [36]\n"
" -o, --output=<file> if reading stdin, place the output into <file>\n" " -o, --output=<file> if reading standard input, write to <file>\n"
" -q, --quiet suppress all messages\n" " -q, --quiet suppress all messages\n"
" -s, --dictionary-size=<bytes> set dictionary size limit in bytes [8 MiB]\n" " -s, --dictionary-size=<bytes> set dictionary size limit in bytes [8 MiB]\n"
" -t, --test test compressed file integrity\n" " -t, --test test compressed file integrity\n"
@ -118,13 +119,15 @@ static void show_help( void )
" -1 .. -9 set compression level [default 6]\n" " -1 .. -9 set compression level [default 6]\n"
" --fast alias for -1\n" " --fast alias for -1\n"
" --best alias for -9\n" " --best alias for -9\n"
"If no file names are given, pdlzip compresses or decompresses\n" "If no file names are given, or if a file is '-', pdlzip compresses or\n"
"from standard input to standard output.\n" "decompresses from standard input to standard output.\n"
"Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n" "Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n"
"Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\n" "Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\n"
"The bidimensional parameter space of LZMA can't be mapped to a linear\n" "Dictionary sizes 12 to 27 are interpreted as powers of two, meaning 2^12\n"
"to 2^27 bytes.\n"
"\nThe bidimensional parameter space of LZMA can't be mapped to a linear\n"
"scale optimal for all files. If your files are large, very repetitive,\n" "scale optimal for all files. If your files are large, very repetitive,\n"
"etc, you may need to use the --match-length and --dictionary-size\n" "etc, you may need to use the --dictionary-size and --match-length\n"
"options directly to achieve optimal performance. For example, -9m64\n" "options directly to achieve optimal performance. For example, -9m64\n"
"usually compresses executables more (and faster) than -9.\n" "usually compresses executables more (and faster) than -9.\n"
"\nExit status: 0 for a normal exit, 1 for environmental problems (file\n" "\nExit status: 0 for a normal exit, 1 for environmental problems (file\n"
@ -149,18 +152,21 @@ static void show_version( void )
static void show_header( const unsigned dictionary_size ) static void show_header( const unsigned dictionary_size )
{ {
const char * const prefix[8] = if( verbosity >= 3 )
{ "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" }; {
enum { factor = 1024 }; const char * const prefix[8] =
const char * p = ""; { "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" };
const char * np = " "; enum { factor = 1024 };
unsigned num = dictionary_size, i; const char * p = "";
bool exact = ( num % factor == 0 ); const char * np = " ";
unsigned num = dictionary_size, i;
bool exact = ( num % factor == 0 );
for( i = 0; i < 8 && ( num > 9999 || ( exact && num >= factor ) ); ++i ) for( i = 0; i < 8 && ( num > 9999 || ( exact && num >= factor ) ); ++i )
{ num /= factor; if( num % factor != 0 ) exact = false; { num /= factor; if( num % factor != 0 ) exact = false;
p = prefix[i]; np = ""; } p = prefix[i]; np = ""; }
fprintf( stderr, "dictionary size %s%4u %sB. ", np, num, p ); fprintf( stderr, "dictionary size %s%4u %sB. ", np, num, p );
}
} }
@ -180,12 +186,11 @@ static unsigned long getnum( const char * const ptr,
if( !errno && tail[0] ) if( !errno && tail[0] )
{ {
int factor = ( tail[1] == 'i' ) ? 1024 : 1000; const int factor = ( tail[1] == 'i' ) ? 1024 : 1000;
int exponent = 0, i; int exponent = 0; /* 0 = bad multiplier */
bool bad_multiplier = false; int i;
switch( tail[0] ) switch( tail[0] )
{ {
case ' ': break;
case 'Y': exponent = 8; break; case 'Y': exponent = 8; break;
case 'Z': exponent = 7; break; case 'Z': exponent = 7; break;
case 'E': exponent = 6; break; case 'E': exponent = 6; break;
@ -193,13 +198,10 @@ static unsigned long getnum( const char * const ptr,
case 'T': exponent = 4; break; case 'T': exponent = 4; break;
case 'G': exponent = 3; break; case 'G': exponent = 3; break;
case 'M': exponent = 2; break; case 'M': exponent = 2; break;
case 'K': if( factor == 1024 ) exponent = 1; else bad_multiplier = true; case 'K': if( factor == 1024 ) exponent = 1; break;
break; case 'k': if( factor == 1000 ) exponent = 1; break;
case 'k': if( factor == 1000 ) exponent = 1; else bad_multiplier = true;
break;
default : bad_multiplier = true;
} }
if( bad_multiplier ) if( exponent <= 0 )
{ {
show_error( "Bad multiplier in numerical argument.", 0, true ); show_error( "Bad multiplier in numerical argument.", 0, true );
exit( 1 ); exit( 1 );
@ -264,7 +266,7 @@ static int open_instream( const char * const name, struct stat * const in_statsp
if( infd < 0 ) if( infd < 0 )
{ {
if( verbosity >= 0 ) if( verbosity >= 0 )
fprintf( stderr, "%s: Can't open input file '%s': %s.\n", fprintf( stderr, "%s: Can't open input file '%s': %s\n",
program_name, name, strerror( errno ) ); program_name, name, strerror( errno ) );
} }
else else
@ -274,14 +276,14 @@ static int open_instream( const char * const name, struct stat * const in_statsp
const bool can_read = ( i == 0 && const bool can_read = ( i == 0 &&
( S_ISBLK( mode ) || S_ISCHR( mode ) || ( S_ISBLK( mode ) || S_ISCHR( mode ) ||
S_ISFIFO( mode ) || S_ISSOCK( mode ) ) ); S_ISFIFO( mode ) || S_ISSOCK( mode ) ) );
const bool no_ofile = to_stdout || program_mode == m_test; const bool no_ofile = ( to_stdout || program_mode == m_test );
if( i != 0 || ( !S_ISREG( mode ) && ( !can_read || !no_ofile ) ) ) if( i != 0 || ( !S_ISREG( mode ) && ( !can_read || !no_ofile ) ) )
{ {
if( verbosity >= 0 ) if( verbosity >= 0 )
fprintf( stderr, "%s: Input file '%s' is not a regular file%s.\n", fprintf( stderr, "%s: Input file '%s' is not a regular file%s.\n",
program_name, name, program_name, name,
( can_read && !no_ofile ) ? ( can_read && !no_ofile ) ?
" and '--stdout' was not specified" : "" ); ",\n and '--stdout' was not specified" : "" );
close( infd ); close( infd );
infd = -1; infd = -1;
} }
@ -334,24 +336,28 @@ static void set_d_outname( const char * const name, const int i )
strcpy( output_filename, name ); strcpy( output_filename, name );
strcat( output_filename, ".out" ); strcat( output_filename, ".out" );
if( verbosity >= 1 ) if( verbosity >= 1 )
fprintf( stderr, "%s: Can't guess original name for '%s' -- using '%s'.\n", fprintf( stderr, "%s: Can't guess original name for '%s' -- using '%s'\n",
program_name, name, output_filename ); program_name, name, output_filename );
} }
static bool open_outstream( const bool force ) static bool open_outstream( const bool force, const bool from_stdin )
{ {
const mode_t usr_rw = S_IRUSR | S_IWUSR;
const mode_t all_rw = usr_rw | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
const mode_t outfd_mode = from_stdin ? all_rw : usr_rw;
int flags = O_CREAT | O_WRONLY | O_BINARY; int flags = O_CREAT | O_WRONLY | O_BINARY;
if( force ) flags |= O_TRUNC; else flags |= O_EXCL; if( force ) flags |= O_TRUNC; else flags |= O_EXCL;
outfd = open( output_filename, flags, outfd_mode ); outfd = open( output_filename, flags, outfd_mode );
if( outfd < 0 && verbosity >= 0 ) if( outfd >= 0 ) delete_output_on_interrupt = true;
else if( verbosity >= 0 )
{ {
if( errno == EEXIST ) if( errno == EEXIST )
fprintf( stderr, "%s: Output file '%s' already exists, skipping.\n", fprintf( stderr, "%s: Output file '%s' already exists, skipping.\n",
program_name, output_filename ); program_name, output_filename );
else else
fprintf( stderr, "%s: Can't create output file '%s': %s.\n", fprintf( stderr, "%s: Can't create output file '%s': %s\n",
program_name, output_filename, strerror( errno ) ); program_name, output_filename, strerror( errno ) );
} }
return ( outfd >= 0 ); return ( outfd >= 0 );
@ -406,7 +412,11 @@ static void close_and_set_permissions( const struct stat * const in_statsp )
fchmod( outfd, mode & ~( S_ISUID | S_ISGID | S_ISVTX ) ) != 0 ) fchmod( outfd, mode & ~( S_ISUID | S_ISGID | S_ISVTX ) ) != 0 )
warning = true; warning = true;
} }
if( close( outfd ) != 0 ) cleanup_and_fail( 1 ); if( close( outfd ) != 0 )
{
show_error( "Error closing output file", errno, false );
cleanup_and_fail( 1 );
}
outfd = -1; outfd = -1;
delete_output_on_interrupt = false; delete_output_on_interrupt = false;
if( in_statsp ) if( in_statsp )
@ -444,7 +454,7 @@ static int compress( const struct Lzma_options * const encoder_options,
} }
if( writeblock( outfd, header, Fh_size ) != Fh_size ) if( writeblock( outfd, header, Fh_size ) != Fh_size )
{ show_error( "Can not write output file", errno, false ); retval = 1; } { show_error( "Can't write output file", errno, false ); retval = 1; }
else else
if( LzmaEnc_Encode( encoder ) != 0 ) if( LzmaEnc_Encode( encoder ) != 0 )
{ Pp_show_msg( pp, "Encoder error." ); retval = 1; } { Pp_show_msg( pp, "Encoder error." ); retval = 1; }
@ -516,7 +526,7 @@ static int lzma_decode( uint64_t unpackSize, CLzmaDec *decoder, const int infd,
unpackSize -= outProcessed; unpackSize -= outProcessed;
if( outfd >= 0 && writeblock( outfd, outBuf, outPos ) != outPos ) if( outfd >= 0 && writeblock( outfd, outBuf, outPos ) != outPos )
{ show_error( "Can not write output file", errno, false ); return 1; } { show_error( "Can't write output file", errno, false ); return 1; }
total_out += outPos; total_out += outPos;
outPos = 0; outPos = 0;
@ -527,13 +537,18 @@ static int lzma_decode( uint64_t unpackSize, CLzmaDec *decoder, const int infd,
if( ( thereIsSize && unpackSize != 0 ) || if( ( thereIsSize && unpackSize != 0 ) ||
( !thereIsSize && status != LZMA_STATUS_FINISHED_WITH_MARK ) ) ( !thereIsSize && status != LZMA_STATUS_FINISHED_WITH_MARK ) )
{ show_error( "Data error.", 0, false ); return 2; } { show_error( "Data error.", 0, false ); return 2; }
if( verbosity >= 2 ) if( verbosity >= 2 && total_out > 0 && total_in > 0 )
{ fprintf( stderr, "lzma-alone, " ); show_header( decoder->dicBufSize ); } fprintf( stderr, "%6.3f:1, %6.3f bits/byte, %5.2f%% saved. ",
if( verbosity >= 3 ) (double)total_out / total_in,
( 8.0 * total_in ) / total_out,
100.0 * ( 1.0 - ( (double)total_in / total_out ) ) );
if( verbosity >= 4 )
fprintf( stderr, "uncompressed size %9llu, compressed size %8llu. ", fprintf( stderr, "uncompressed size %9llu, compressed size %8llu. ",
total_out, total_in ); total_out, total_in );
if( verbosity >= 2 )
fputs( "lzma-alone, ", stderr );
if( verbosity >= 1 ) if( verbosity >= 1 )
fprintf( stderr, testing ? "(apparently) ok\n" : "(apparently) done\n" ); fputs( testing ? "(apparently) ok\n" : "(apparently) done\n", stderr );
return 0; return 0;
} }
} }
@ -569,7 +584,7 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, uint8_t inBuf[],
outPos += outProcessed; outPos += outProcessed;
if( outfd >= 0 && writeblock( outfd, outBuf, outPos ) != outPos ) if( outfd >= 0 && writeblock( outfd, outBuf, outPos ) != outPos )
{ show_error( "Can not write output file", errno, false ); return 1; } { show_error( "Can't write output file", errno, false ); return 1; }
CRC32_update_buf( &crc, outBuf, outPos ); CRC32_update_buf( &crc, outBuf, outPos );
total_out += outPos; total_out += outPos;
@ -598,25 +613,26 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, uint8_t inBuf[],
for( i = 0; i < Ft_size; ++i ) for( i = 0; i < Ft_size; ++i )
trailer[i] = inBuf[(*inPos)++]; trailer[i] = inBuf[(*inPos)++];
total_in += Ft_size; total_in += Ft_size;
if( Ft_get_data_crc( trailer ) != ( crc ^ 0xFFFFFFFFU ) ) crc ^= 0xFFFFFFFFU;
if( Ft_get_data_crc( trailer ) != crc )
{ {
error = true; error = true;
if( verbosity >= 0 ) if( verbosity >= 0 )
fprintf( stderr, "CRC mismatch; trailer says %08X, data crc is %08X.\n", fprintf( stderr, "CRC mismatch; trailer says %08X, data crc is %08X\n",
Ft_get_data_crc( trailer ), crc ^ 0xFFFFFFFFU ); Ft_get_data_crc( trailer ), crc );
} }
if( Ft_get_data_size( trailer ) != total_out ) if( Ft_get_data_size( trailer ) != total_out )
{ {
error = true; error = true;
if( verbosity >= 0 ) if( verbosity >= 0 )
fprintf( stderr, "Data size mismatch; trailer says %llu, data size is %llu (0x%llX).\n", fprintf( stderr, "Data size mismatch; trailer says %llu, data size is %llu (0x%llX)\n",
Ft_get_data_size( trailer ), total_out, total_out ); Ft_get_data_size( trailer ), total_out, total_out );
} }
if( Ft_get_member_size( trailer ) != total_in ) if( Ft_get_member_size( trailer ) != total_in )
{ {
error = true; error = true;
if( verbosity >= 0 ) if( verbosity >= 0 )
fprintf( stderr, "Member size mismatch; trailer says %llu, member size is %llu (0x%llX).\n", fprintf( stderr, "Member size mismatch; trailer says %llu, member size is %llu (0x%llX)\n",
Ft_get_member_size( trailer ), total_in, total_in ); Ft_get_member_size( trailer ), total_in, total_in );
} }
if( !error && verbosity >= 2 && total_out > 0 && total_in > 0 ) if( !error && verbosity >= 2 && total_out > 0 && total_in > 0 )
@ -626,8 +642,7 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, uint8_t inBuf[],
100.0 * ( 1.0 - ( (double)total_in / total_out ) ) ); 100.0 * ( 1.0 - ( (double)total_in / total_out ) ) );
if( !error && verbosity >= 4 ) if( !error && verbosity >= 4 )
fprintf( stderr, "data CRC %08X, data size %9llu, member size %8llu. ", fprintf( stderr, "data CRC %08X, data size %9llu, member size %8llu. ",
Ft_get_data_crc( trailer ), crc, total_out, total_in );
Ft_get_data_size( trailer ), Ft_get_member_size( trailer ) );
if( error ) return 2; if( error ) return 2;
return 0; return 0;
} }
@ -636,7 +651,7 @@ static int lzip_decode( CLzmaDec *decoder, const int infd, uint8_t inBuf[],
static int decompress( const int infd, struct Pretty_print * const pp, static int decompress( const int infd, struct Pretty_print * const pp,
const bool testing ) const bool ignore_trailing, const bool testing )
{ {
uint64_t unpackSize = 0; uint64_t unpackSize = 0;
CLzmaDec decoder; CLzmaDec decoder;
@ -649,31 +664,43 @@ static int decompress( const int infd, struct Pretty_print * const pp,
for( first_member = true; ; first_member = false ) for( first_member = true; ; first_member = false )
{ {
int i; int i, size;
unsigned dictionary_size = 0; unsigned dictionary_size;
File_header header; File_header header;
if( inSize - inPos < lzma_header_size && if( inSize - inPos < lzma_header_size &&
!read_inbuf( infd, inBuf, &inPos, &inSize ) ) return 1; !read_inbuf( infd, inBuf, &inPos, &inSize ) ) return 1;
if( inSize - inPos <= Fh_size ) /* End Of File */ size = inSize - inPos;
for( i = 0; i < size && i < Fh_size; ++i )
raw_props[i] = header[i] = inBuf[inPos++];
if( size <= Fh_size ) /* End Of File */
{ {
if( first_member ) if( first_member || Fh_verify_prefix( header, size ) )
{ Pp_show_msg( pp, "File ends unexpectedly at member header." ); { Pp_show_msg( pp, "File ends unexpectedly at member header." );
retval = 2; } retval = 2; }
break; break;
} }
for( i = 0; i < Fh_size; ++i ) raw_props[i] = header[i] = inBuf[inPos++];
if( !Fh_verify_magic( header ) ) if( !Fh_verify_magic( header ) )
{ {
if( !first_member ) break; /* trailing garbage */ if( !first_member )
{
if( !ignore_trailing )
{ Pp_show_msg( pp, "Trailing data not allowed." ); retval = 2; }
break;
}
if( inSize - inPos >= lzma_header_size - Fh_size ) /* try lzma-alone */ if( inSize - inPos >= lzma_header_size - Fh_size ) /* try lzma-alone */
{ {
for( i = Fh_size; i < lzma_header_size; ++i ) for( i = Fh_size; i < lzma_header_size; ++i )
raw_props[i] = inBuf[inPos++]; raw_props[i] = inBuf[inPos++];
for( i = 0; i < 8; ++i )
unpackSize += (uint64_t)raw_props[LZMA_PROPS_SIZE+i] << (i * 8);
if( ( raw_props[12] == 0 || raw_props[12] == 0xFF ) && if( ( raw_props[12] == 0 || raw_props[12] == 0xFF ) &&
raw_props[12] == raw_props[11] && raw_props[0] < (9 * 5 * 5) ) raw_props[12] == raw_props[11] && raw_props[0] < (9 * 5 * 5) )
{
lzip_mode = false; lzip_mode = false;
dictionary_size = 0;
for( i = 4; i >= 1; --i )
{ dictionary_size <<= 8; dictionary_size += raw_props[i]; }
for( i = 7; i >= 0; --i )
{ unpackSize <<= 8; unpackSize += raw_props[LZMA_PROPS_SIZE+i]; }
}
} }
if( lzip_mode ) if( lzip_mode )
{ {
@ -693,8 +720,7 @@ static int decompress( const int infd, struct Pretty_print * const pp,
retval = 2; break; retval = 2; break;
} }
dictionary_size = Fh_get_dictionary_size( header ); dictionary_size = Fh_get_dictionary_size( header );
if( dictionary_size < min_dictionary_size || if( !isvalid_ds( dictionary_size ) )
dictionary_size > max_dictionary_size )
{ Pp_show_msg( pp, "Invalid dictionary size in member header." ); { Pp_show_msg( pp, "Invalid dictionary size in member header." );
retval = 2; break; } retval = 2; break; }
@ -704,14 +730,10 @@ static int decompress( const int infd, struct Pretty_print * const pp,
} }
if( verbosity >= 2 || ( verbosity == 1 && first_member ) ) if( verbosity >= 2 || ( verbosity == 1 && first_member ) )
{ Pp_show_msg( pp, 0 ); { Pp_show_msg( pp, 0 ); show_header( dictionary_size ); }
if( lzip_mode && verbosity >= 3 ) show_header( dictionary_size ); }
if( !LzmaDec_Init( &decoder, raw_props ) ) if( !LzmaDec_Init( &decoder, raw_props ) )
{ { Pp_show_msg( pp, "Not enough memory." ); return 1; }
show_error( "Not enough memory.", 0, false );
cleanup_and_fail( 1 );
}
if( lzip_mode ) if( lzip_mode )
retval = lzip_decode( &decoder, infd, inBuf, &inPos, &inSize ); retval = lzip_decode( &decoder, infd, inBuf, &inPos, &inSize );
else else
@ -720,10 +742,10 @@ static int decompress( const int infd, struct Pretty_print * const pp,
LzmaDec_Free(&decoder); LzmaDec_Free(&decoder);
if( retval != 0 || !lzip_mode ) break; if( retval != 0 || !lzip_mode ) break;
if( verbosity >= 2 ) if( verbosity >= 2 )
{ fprintf( stderr, testing ? "ok\n" : "done\n" ); Pp_reset( pp ); } { fputs( testing ? "ok\n" : "done\n", stderr ); Pp_reset( pp ); }
} }
if( lzip_mode && verbosity == 1 && retval == 0 ) if( lzip_mode && verbosity == 1 && retval == 0 )
fprintf( stderr, testing ? "ok\n" : "done\n" ); fputs( testing ? "ok\n" : "done\n", stderr );
return retval; return retval;
} }
@ -753,11 +775,11 @@ void Pp_show_msg( struct Pretty_print * const pp, const char * const msg )
{ {
if( pp->first_post ) if( pp->first_post )
{ {
int i, len; unsigned i;
pp->first_post = false; pp->first_post = false;
fprintf( stderr, " %s: ", pp->name ); fprintf( stderr, " %s: ", pp->name );
len = pp->longest_name - strlen( pp->name ); for( i = strlen( pp->name ); i < pp->longest_name; ++i )
for( i = 0; i < len; ++i ) fprintf( stderr, " " ); fputc( ' ', stderr );
if( !msg ) fflush( stderr ); if( !msg ) fflush( stderr );
} }
if( msg ) fprintf( stderr, "%s\n", msg ); if( msg ) fprintf( stderr, "%s\n", msg );
@ -804,18 +826,16 @@ int writeblock( const int fd, const uint8_t * const buf, const int size )
void show_error( const char * const msg, const int errcode, const bool help ) void show_error( const char * const msg, const int errcode, const bool help )
{ {
if( verbosity >= 0 ) if( verbosity < 0 ) return;
if( msg && msg[0] )
{ {
if( msg && msg[0] ) fprintf( stderr, "%s: %s", program_name, msg );
{ if( errcode > 0 ) fprintf( stderr, ": %s", strerror( errcode ) );
fprintf( stderr, "%s: %s", program_name, msg ); fputc( '\n', stderr );
if( errcode > 0 ) fprintf( stderr, ": %s.", strerror( errcode ) );
fprintf( stderr, "\n" );
}
if( help )
fprintf( stderr, "Try '%s --help' for more information.\n",
invocation_name );
} }
if( help )
fprintf( stderr, "Try '%s --help' for more information.\n",
invocation_name );
} }
@ -855,7 +875,9 @@ int main( const int argc, const char * const argv[] )
int i; int i;
bool filenames_given = false; bool filenames_given = false;
bool force = false; bool force = false;
bool ignore_trailing = true;
bool keep_input_files = false; bool keep_input_files = false;
bool stdin_used = false;
bool recompress = false; bool recompress = false;
bool to_stdout = false; bool to_stdout = false;
struct Pretty_print pp; struct Pretty_print pp;
@ -872,6 +894,7 @@ int main( const int argc, const char * const argv[] )
{ '7', 0, ap_no }, { '7', 0, ap_no },
{ '8', 0, ap_no }, { '8', 0, ap_no },
{ '9', "best", ap_no }, { '9', "best", ap_no },
{ 'a', "trailing-error", ap_no },
{ 'b', "member-size", ap_yes }, { 'b', "member-size", ap_yes },
{ 'c', "stdout", ap_no }, { 'c', "stdout", ap_no },
{ 'd', "decompress", ap_no }, { 'd', "decompress", ap_no },
@ -910,6 +933,7 @@ int main( const int argc, const char * const argv[] )
case '0': case '1': case '2': case '3': case '4': case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': case '5': case '6': case '7': case '8': case '9':
encoder_options = option_mapping[code-'0']; break; encoder_options = option_mapping[code-'0']; break;
case 'a': ignore_trailing = false; break;
case 'b': break; case 'b': break;
case 'c': to_stdout = true; break; case 'c': to_stdout = true; break;
case 'd': program_mode = m_decompress; break; case 'd': program_mode = m_decompress; break;
@ -954,7 +978,7 @@ int main( const int argc, const char * const argv[] )
( filenames_given || default_output_filename[0] ) ) ( filenames_given || default_output_filename[0] ) )
set_signals(); set_signals();
Pp_init( &pp, filenames, num_filenames ); Pp_init( &pp, filenames, num_filenames, verbosity );
output_filename = resize_buffer( output_filename, 1 ); output_filename = resize_buffer( output_filename, 1 );
for( i = 0; i < num_filenames; ++i ) for( i = 0; i < num_filenames; ++i )
@ -966,6 +990,7 @@ int main( const int argc, const char * const argv[] )
if( !filenames[i][0] || strcmp( filenames[i], "-" ) == 0 ) if( !filenames[i][0] || strcmp( filenames[i], "-" ) == 0 )
{ {
if( stdin_used ) continue; else stdin_used = true;
input_filename = ""; input_filename = "";
infd = STDIN_FILENO; infd = STDIN_FILENO;
if( program_mode != m_test ) if( program_mode != m_test )
@ -982,8 +1007,7 @@ int main( const int argc, const char * const argv[] )
strlen( default_output_filename ) + 1 ); strlen( default_output_filename ) + 1 );
strcpy( output_filename, default_output_filename ); strcpy( output_filename, default_output_filename );
} }
outfd_mode = all_rw; if( !open_outstream( force, true ) )
if( !open_outstream( force ) )
{ {
if( retval < 1 ) retval = 1; if( retval < 1 ) retval = 1;
close( infd ); infd = -1; close( infd ); infd = -1;
@ -1007,8 +1031,7 @@ int main( const int argc, const char * const argv[] )
if( program_mode == m_compress ) if( program_mode == m_compress )
set_c_outname( input_filename ); set_c_outname( input_filename );
else set_d_outname( input_filename, eindex ); else set_d_outname( input_filename, eindex );
outfd_mode = usr_rw; if( !open_outstream( force, false ) )
if( !open_outstream( force ) )
{ {
if( retval < 1 ) retval = 1; if( retval < 1 ) retval = 1;
close( infd ); infd = -1; close( infd ); infd = -1;
@ -1018,16 +1041,18 @@ int main( const int argc, const char * const argv[] )
} }
} }
if( !check_tty( infd, program_mode ) ) return 1; if( !check_tty( infd, program_mode ) )
{
if( retval < 1 ) retval = 1;
cleanup_and_fail( retval );
}
if( output_filename[0] && !to_stdout && program_mode != m_test )
delete_output_on_interrupt = true;
in_statsp = input_filename[0] ? &in_stats : 0; in_statsp = input_filename[0] ? &in_stats : 0;
Pp_set_name( &pp, input_filename ); Pp_set_name( &pp, input_filename );
if( program_mode == m_compress ) if( program_mode == m_compress )
tmp = compress( &encoder_options, infd, &pp ); tmp = compress( &encoder_options, infd, &pp );
else else
tmp = decompress( infd, &pp, program_mode == m_test ); tmp = decompress( infd, &pp, ignore_trailing, program_mode == m_test );
if( tmp > retval ) retval = tmp; if( tmp > retval ) retval = tmp;
if( tmp && program_mode != m_test ) cleanup_and_fail( retval ); if( tmp && program_mode != m_test ) cleanup_and_fail( retval );

View file

@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# check script for Pdlzip - LZMA lossless data compressor # check script for Pdlzip - LZMA lossless data compressor
# Copyright (C) 2010-2015 Antonio Diaz Diaz. # Copyright (C) 2010-2016 Antonio Diaz Diaz.
# #
# This script is free software: you have unlimited permission # This script is free software: you have unlimited permission
# to copy, distribute and modify it. # to copy, distribute and modify it.
@ -17,9 +17,16 @@ if [ ! -f "${LZIP}" ] || [ ! -x "${LZIP}" ] ; then
exit 1 exit 1
fi fi
if [ -e "${LZIP}" ] 2> /dev/null ; then true
else
echo "$0: a POSIX shell is required to run the tests"
echo "Try bash -c \"$0 $1 $2\""
exit 1
fi
if [ -d tmp ] ; then rm -rf tmp ; fi if [ -d tmp ] ; then rm -rf tmp ; fi
mkdir tmp mkdir tmp
cd "${objdir}"/tmp cd "${objdir}"/tmp || framework_failure
cat "${testdir}"/test.txt > in || framework_failure cat "${testdir}"/test.txt > in || framework_failure
in_lz="${testdir}"/test.txt.lz in_lz="${testdir}"/test.txt.lz
@ -27,25 +34,22 @@ fail=0
printf "testing pdlzip-%s..." "$2" printf "testing pdlzip-%s..." "$2"
"${LZIP}" -cqm4 in > /dev/null "${LZIP}" -fkqm4 in
if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi
"${LZIP}" -cqm274 in > /dev/null "${LZIP}" -fkqm274 in
if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi
"${LZIP}" -cqs-1 in > /dev/null "${LZIP}" -fkqs-1 in
if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi
"${LZIP}" -cqs0 in > /dev/null "${LZIP}" -fkqs0 in
if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi
"${LZIP}" -cqs4095 in > /dev/null "${LZIP}" -fkqs4095 in
if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi
"${LZIP}" -cqs513MiB in > /dev/null "${LZIP}" -fkqs513MiB in
if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi if [ $? = 1 ] && [ ! -e in.lz ] ; then printf . ; else printf - ; fail=1 ; fi
printf " in: Bad magic number (file not in lzip format).\n" > msg "${LZIP}" -tq in
"${LZIP}" -t in 2> out if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
if [ $? = 2 ] && cmp out msg ; then printf . ; else printf - ; fail=1 ; fi "${LZIP}" -tq < in
printf " (stdin): Bad magic number (file not in lzip format).\n" > msg if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
"${LZIP}" -t < in 2> out
if [ $? = 2 ] && cmp out msg ; then printf . ; else printf - ; fail=1 ; fi
rm -f out msg
"${LZIP}" -cdq in "${LZIP}" -cdq in
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
"${LZIP}" -cdq < in "${LZIP}" -cdq < in
@ -55,47 +59,85 @@ if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
dd if="${in_lz}" bs=1 count=20 2> /dev/null | "${LZIP}" -tq dd if="${in_lz}" bs=1 count=20 2> /dev/null | "${LZIP}" -tq
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
"${LZIP}" -t "${in_lz}" || fail=1 printf "\ntesting decompression..."
"${LZIP}" -t "${in_lz}"
if [ $? = 0 ] ; then printf . ; else printf - ; fail=1 ; fi
"${LZIP}" -cd "${in_lz}" > copy || fail=1 "${LZIP}" -cd "${in_lz}" > copy || fail=1
cmp in copy || fail=1 cmp in copy || fail=1
printf . printf .
"${LZIP}" -t "${testdir}"/test.txt.lzma || fail=1 "${LZIP}" -t "${testdir}"/test.txt.lzma
if [ $? = 0 ] ; then printf . ; else printf - ; fail=1 ; fi
"${LZIP}" -cd "${testdir}"/test.txt.lzma > copy || fail=1 "${LZIP}" -cd "${testdir}"/test.txt.lzma > copy || fail=1
cmp in copy || fail=1 cmp in copy || fail=1
printf . printf .
rm -f copy
cat "${in_lz}" > copy.lz || framework_failure cat "${in_lz}" > copy.lz || framework_failure
printf "to be overwritten" > copy || framework_failure "${LZIP}" -dk copy.lz || fail=1
"${LZIP}" -df copy.lz || fail=1
cmp in copy || fail=1 cmp in copy || fail=1
printf . printf "to be overwritten" > copy || framework_failure
"${LZIP}" -dq copy.lz
if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi
"${LZIP}" -df copy.lz
if [ $? = 0 ] && [ ! -e copy.lz ] && cmp in copy ; then
printf . ; else printf - ; fail=1 ; fi
printf "to be overwritten" > copy || framework_failure printf "to be overwritten" > copy || framework_failure
"${LZIP}" -df -o copy < "${in_lz}" || fail=1 "${LZIP}" -df -o copy < "${in_lz}" || fail=1
cmp in copy || fail=1 cmp in copy || fail=1
printf . printf .
rm -f copy
"${LZIP}" -s16 < in > anyothername || fail=1 "${LZIP}" -s16 < in > anyothername || fail=1
"${LZIP}" -d anyothername || fail=1 "${LZIP}" -d -o copy - anyothername - < "${in_lz}"
cmp in anyothername.out || fail=1 if [ $? = 0 ] && cmp in copy && cmp in anyothername.out ; then
printf . printf . ; else printf - ; fail=1 ; fi
rm -f copy anyothername.out
"${LZIP}" -tq in "${in_lz}"
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
"${LZIP}" -tq foo.lz "${in_lz}"
if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi
"${LZIP}" -cdq in "${in_lz}" > copy
if [ $? = 2 ] && cat copy in | cmp in - ; then printf . ; else printf - ; fail=1 ; fi
"${LZIP}" -cdq foo.lz "${in_lz}" > copy
if [ $? = 1 ] && cmp in copy ; then printf . ; else printf - ; fail=1 ; fi
rm -f copy
cat "${in_lz}" > copy.lz || framework_failure
"${LZIP}" -dq in copy.lz
if [ $? = 2 ] && [ -e copy.lz ] && [ ! -e copy ] && [ ! -e in.out ] ; then
printf . ; else printf - ; fail=1 ; fi
"${LZIP}" -dq foo.lz copy.lz
if [ $? = 1 ] && [ ! -e copy.lz ] && [ ! -e foo ] && cmp in copy ; then
printf . ; else printf - ; fail=1 ; fi
cat in in > in2 || framework_failure cat in in > in2 || framework_failure
"${LZIP}" -s16 -o copy2 < in2 || fail=1 "${LZIP}" -s16 -o copy2 < in2 || fail=1
"${LZIP}" -t copy2.lz || fail=1 "${LZIP}" -t copy2.lz || fail=1
printf .
"${LZIP}" -cd copy2.lz > copy2 || fail=1 "${LZIP}" -cd copy2.lz > copy2 || fail=1
cmp in2 copy2 || fail=1 cmp in2 copy2 || fail=1
printf . printf .
printf "garbage" >> copy2.lz || framework_failure printf "garbage" >> copy2.lz || framework_failure
rm -f copy2
"${LZIP}" -atq copy2.lz
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
"${LZIP}" -atq < copy2.lz
if [ $? = 2 ] ; then printf . ; else printf - ; fail=1 ; fi
"${LZIP}" -adkq copy2.lz
if [ $? = 2 ] && [ ! -e copy2 ] ; then printf . ; else printf - ; fail=1 ; fi
"${LZIP}" -adkq -o copy2 < copy2.lz
if [ $? = 2 ] && [ ! -e copy2 ] ; then printf . ; else printf - ; fail=1 ; fi
printf "to be overwritten" > copy2 || framework_failure printf "to be overwritten" > copy2 || framework_failure
"${LZIP}" -df copy2.lz || fail=1 "${LZIP}" -df copy2.lz || fail=1
cmp in2 copy2 || fail=1 cmp in2 copy2 || fail=1
printf . printf .
"${LZIP}" -cfq "${in_lz}" > out printf "\ntesting compression..."
"${LZIP}" -cfq "${in_lz}" > out # /dev/null is a tty on OS/2
if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi if [ $? = 1 ] ; then printf . ; else printf - ; fail=1 ; fi
"${LZIP}" -cF -s16 "${in_lz}" > out || fail=1 "${LZIP}" -cF -s16 "${in_lz}" > out || fail=1
"${LZIP}" -cd out | "${LZIP}" -d > copy || fail=1 "${LZIP}" -cd out | "${LZIP}" -d > copy || fail=1

Binary file not shown.

Binary file not shown.