Adding upstream version 1.24.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
b5b27e635c
commit
5ed044e6c7
35 changed files with 910 additions and 848 deletions
13
ChangeLog
13
ChangeLog
|
@ -1,14 +1,19 @@
|
||||||
2023-06-14 Antonio Diaz Diaz <antonio@gnu.org>
|
2024-01-20 Antonio Diaz Diaz <antonio@gnu.org>
|
||||||
|
|
||||||
* Version 1.24-pre1 released.
|
* Version 1.24 released.
|
||||||
* New options '--empty-error', '--marking-error', '--clear-marking'.
|
* New options '--empty-error', '--marking-error', '--clear-marking'.
|
||||||
* dump_remove.cc, main.cc: Accept 'empty' in --dump, --remove, --strip.
|
* dump_remove.cc, main.cc: Accept 'empty' in --dump, --remove, --strip.
|
||||||
* main.cc: Rename '--repair' to '--byte-repair'.
|
* main.cc: Rename '--repair' to '--byte-repair'.
|
||||||
Rename '--debug-repair' to '--debug-byte-repair'.
|
Rename '--debug-repair' to '--debug-byte-repair'.
|
||||||
|
Reformat file diagnostics as 'PROGRAM: FILE: MESSAGE'.
|
||||||
(show_option_error): New function showing argument and option name.
|
(show_option_error): New function showing argument and option name.
|
||||||
|
(main): Make -o preserve date/mode/owner if 1 input file.
|
||||||
|
(open_outstream): Create missing intermediate directories.
|
||||||
* lzip.h: Rename verify_* to check_*.
|
* lzip.h: Rename verify_* to check_*.
|
||||||
* unzcrash.cc: Rename '--no-verify' to '--no-check'.
|
|
||||||
* repair.cc: Rename to byte_repair.cc.
|
* repair.cc: Rename to byte_repair.cc.
|
||||||
|
* unzcrash.cc: Rename '--no-verify' to '--no-check'.
|
||||||
|
* configure, Makefile.in: New variable 'MAKEINFO'.
|
||||||
|
* Makefile.in: Remove target 'install-as-lzip'; -e needs a real lzip.
|
||||||
* testsuite: New test files test_3m.txt.lz.md5, fox6_mark.lz.
|
* testsuite: New test files test_3m.txt.lz.md5, fox6_mark.lz.
|
||||||
|
|
||||||
2022-01-21 Antonio Diaz Diaz <antonio@gnu.org>
|
2022-01-21 Antonio Diaz Diaz <antonio@gnu.org>
|
||||||
|
@ -239,7 +244,7 @@
|
||||||
* unzcrash.cc: Test all 1-byte errors.
|
* unzcrash.cc: Test all 1-byte errors.
|
||||||
|
|
||||||
|
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 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
|
||||||
|
|
9
INSTALL
9
INSTALL
|
@ -49,7 +49,8 @@ extracted from the archive.
|
||||||
make LZIP_NAME=clzip check
|
make LZIP_NAME=clzip check
|
||||||
|
|
||||||
5. Type 'make install' to install the program and any data files and
|
5. Type 'make install' to install the program and any data files and
|
||||||
documentation.
|
documentation. You need root privileges to install into a prefix owned
|
||||||
|
by root.
|
||||||
|
|
||||||
Or type 'make install-compress', which additionally compresses the
|
Or type 'make install-compress', which additionally compresses the
|
||||||
info manual and the man page after installation.
|
info manual and the man page after installation.
|
||||||
|
@ -59,10 +60,6 @@ extracted from the archive.
|
||||||
typing 'make install-bin', 'make install-info', or 'make install-man'
|
typing 'make install-bin', 'make install-info', or 'make install-man'
|
||||||
respectively.
|
respectively.
|
||||||
|
|
||||||
Instead of 'make install', you can type 'make install-as-lzip' to
|
|
||||||
install the program and any data files and documentation, and link
|
|
||||||
the program to the name 'lzip'.
|
|
||||||
|
|
||||||
|
|
||||||
Another way
|
Another way
|
||||||
-----------
|
-----------
|
||||||
|
@ -81,7 +78,7 @@ After running 'configure', you can run 'make' and 'make install' as
|
||||||
explained above.
|
explained above.
|
||||||
|
|
||||||
|
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 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.
|
||||||
|
|
10
Makefile.in
10
Makefile.in
|
@ -16,7 +16,6 @@ unzobjs = arg_parser.o unzcrash.o
|
||||||
.PHONY : all install install-bin install-info install-man \
|
.PHONY : all install install-bin install-info install-man \
|
||||||
install-strip install-compress install-strip-compress \
|
install-strip install-compress install-strip-compress \
|
||||||
install-bin-strip install-info-compress install-man-compress \
|
install-bin-strip install-info-compress install-man-compress \
|
||||||
install-as-lzip \
|
|
||||||
uninstall uninstall-bin uninstall-info uninstall-man \
|
uninstall uninstall-bin uninstall-info uninstall-man \
|
||||||
doc info man check dist clean distclean
|
doc info man check dist clean distclean
|
||||||
|
|
||||||
|
@ -37,6 +36,10 @@ unzcrash.o : unzcrash.cc
|
||||||
%.o : %.cc
|
%.o : %.cc
|
||||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
# prevent 'make' from trying to remake source files
|
||||||
|
$(VPATH)/configure $(VPATH)/Makefile.in $(VPATH)/doc/$(pkgname).texi : ;
|
||||||
|
%.h %.cc : ;
|
||||||
|
|
||||||
$(objs) : Makefile
|
$(objs) : Makefile
|
||||||
alone_to_lz.o : lzip.h common.h mtester.h
|
alone_to_lz.o : lzip.h common.h mtester.h
|
||||||
arg_parser.o : arg_parser.h
|
arg_parser.o : arg_parser.h
|
||||||
|
@ -56,7 +59,6 @@ reproduce.o : lzip.h common.h md5.h mtester.h lzip_index.h
|
||||||
split.o : lzip.h common.h lzip_index.h
|
split.o : lzip.h common.h lzip_index.h
|
||||||
unzcrash.o : Makefile arg_parser.h common.h main_common.cc
|
unzcrash.o : Makefile arg_parser.h common.h main_common.cc
|
||||||
|
|
||||||
|
|
||||||
doc : info man
|
doc : info man
|
||||||
|
|
||||||
info : $(VPATH)/doc/$(pkgname).info
|
info : $(VPATH)/doc/$(pkgname).info
|
||||||
|
@ -106,10 +108,6 @@ install-man :
|
||||||
install-man-compress : install-man
|
install-man-compress : install-man
|
||||||
lzip -v -9 "$(DESTDIR)$(mandir)/man1/$(progname).1"
|
lzip -v -9 "$(DESTDIR)$(mandir)/man1/$(progname).1"
|
||||||
|
|
||||||
install-as-lzip : install
|
|
||||||
-rm -f "$(DESTDIR)$(bindir)/lzip"
|
|
||||||
cd "$(DESTDIR)$(bindir)" && ln -s $(progname) lzip
|
|
||||||
|
|
||||||
uninstall : uninstall-man uninstall-info uninstall-bin
|
uninstall : uninstall-man uninstall-info uninstall-bin
|
||||||
|
|
||||||
uninstall-bin :
|
uninstall-bin :
|
||||||
|
|
19
NEWS
19
NEWS
|
@ -9,14 +9,27 @@ byte is non-zero in any member, has been added.
|
||||||
The option '--clear-marking', which sets to zero the first LZMA byte of each
|
The option '--clear-marking', which sets to zero the first LZMA byte of each
|
||||||
member, has been added.
|
member, has been added.
|
||||||
|
|
||||||
The keyword 'empty' is now recognized in the argument of --dump, --remove,
|
The keyword 'empty' is now recognized in the argument of '--dump',
|
||||||
and --strip.
|
'--remove', and '--strip'.
|
||||||
|
|
||||||
The option '--repair' has been renamed to '--byte-repair'.
|
The option '--repair' has been renamed to '--byte-repair'.
|
||||||
|
|
||||||
The option '--debug-repair' has been renamed to '--debug-byte-repair'.
|
The option '--debug-repair' has been renamed to '--debug-byte-repair'.
|
||||||
|
|
||||||
Diagnostics caused by invalid arguments to command line options now show the
|
File diagnostics have been reformatted as 'PROGRAM: FILE: MESSAGE'.
|
||||||
|
|
||||||
|
Diagnostics caused by invalid arguments to command-line options now show the
|
||||||
argument and the name of the option.
|
argument and the name of the option.
|
||||||
|
|
||||||
|
The option '-o, --output' now preserves dates, permissions, and ownership of
|
||||||
|
the file, when decompressing exactly one file.
|
||||||
|
|
||||||
|
The option '-o, --output' now creates missing intermediate directories when
|
||||||
|
writing to a file.
|
||||||
|
|
||||||
The option '--no-verify' of unzcrash has been renamed to '--no-check'.
|
The option '--no-verify' of unzcrash has been renamed to '--no-check'.
|
||||||
|
|
||||||
|
The variable MAKEINFO has been added to configure and Makefile.in.
|
||||||
|
|
||||||
|
The makefile target 'install-as-lzip' has been removed because '--reproduce'
|
||||||
|
needs a lzip compressor (not just a decompressor) named 'lzip' by default.
|
||||||
|
|
7
README
7
README
|
@ -84,11 +84,10 @@ Julian Seward's bzip2. Type 'make unzcrash' in the lziprecover source
|
||||||
directory to build it. Then try 'unzcrash --help'.
|
directory to build it. Then try 'unzcrash --help'.
|
||||||
|
|
||||||
|
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 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.
|
||||||
|
|
||||||
The file Makefile.in is a data file used by configure to produce the
|
The file Makefile.in is a data file used by configure to produce the Makefile.
|
||||||
Makefile. It has the same copyright owner and permissions that configure
|
It has the same copyright owner and permissions that configure itself.
|
||||||
itself.
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Lziprecover - Data recovery tool for the lzip format
|
/* Lziprecover - Data recovery tool for the lzip format
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -130,7 +130,7 @@ int alone_to_lz( const int infd, const Pretty_print & pp )
|
||||||
header.dictionary_size( dictionary_size );
|
header.dictionary_size( dictionary_size );
|
||||||
}
|
}
|
||||||
Lzip_trailer & trailer =
|
Lzip_trailer & trailer =
|
||||||
*(Lzip_trailer *)( buffer + file_size - Lzip_trailer::size );
|
*(Lzip_trailer *)( buffer + file_size - trailer.size );
|
||||||
trailer.data_crc( mtester.crc() );
|
trailer.data_crc( mtester.crc() );
|
||||||
trailer.data_size( mtester.data_position() );
|
trailer.data_size( mtester.data_position() );
|
||||||
trailer.member_size( mtester.member_position() );
|
trailer.member_size( mtester.member_position() );
|
||||||
|
|
|
@ -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-2023 Antonio Diaz Diaz.
|
Copyright (C) 2006-2024 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
|
||||||
|
|
|
@ -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-2023 Antonio Diaz Diaz.
|
Copyright (C) 2006-2024 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
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Lziprecover - Data recovery tool for the lzip format
|
/* Lziprecover - Data recovery tool for the lzip format
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -64,7 +64,7 @@ int repair_dictionary_size( uint8_t * const mbuffer, const long msize )
|
||||||
Lzip_header & header = *(Lzip_header *)mbuffer;
|
Lzip_header & header = *(Lzip_header *)mbuffer;
|
||||||
unsigned dictionary_size = header.dictionary_size();
|
unsigned dictionary_size = header.dictionary_size();
|
||||||
const Lzip_trailer & trailer =
|
const Lzip_trailer & trailer =
|
||||||
*(const Lzip_trailer *)( mbuffer + msize - Lzip_trailer::size );
|
*(const Lzip_trailer *)( mbuffer + msize - trailer.size );
|
||||||
const unsigned long long data_size = trailer.data_size();
|
const unsigned long long data_size = trailer.data_size();
|
||||||
const bool valid_ds = isvalid_ds( dictionary_size );
|
const bool valid_ds = isvalid_ds( dictionary_size );
|
||||||
if( valid_ds && dictionary_size >= data_size ) return 0; // can't be bad
|
if( valid_ds && dictionary_size >= data_size ) return 0; // can't be bad
|
||||||
|
@ -195,8 +195,9 @@ int byte_repair( const std::string & input_filename,
|
||||||
{ show_file_error( filename, lzip_index.error().c_str() );
|
{ show_file_error( filename, lzip_index.error().c_str() );
|
||||||
return lzip_index.retval(); }
|
return lzip_index.retval(); }
|
||||||
|
|
||||||
output_filename = default_output_filename.empty() ?
|
const bool to_file = default_output_filename.size();
|
||||||
insert_fixed( input_filename ) : default_output_filename;
|
output_filename =
|
||||||
|
to_file ? default_output_filename : insert_fixed( input_filename );
|
||||||
if( !force && output_file_exists() ) return 1;
|
if( !force && output_file_exists() ) return 1;
|
||||||
outfd = -1;
|
outfd = -1;
|
||||||
for( long i = 0; i < lzip_index.members(); ++i )
|
for( long i = 0; i < lzip_index.members(); ++i )
|
||||||
|
@ -226,10 +227,10 @@ int byte_repair( const std::string & input_filename,
|
||||||
{
|
{
|
||||||
pos = repair_dictionary_size( mbuffer, msize );
|
pos = repair_dictionary_size( mbuffer, msize );
|
||||||
if( pos == 0 )
|
if( pos == 0 )
|
||||||
pos = repair_member( mbuffer, mpos, msize, Lzip_header::size + 1,
|
pos = repair_member( mbuffer, mpos, msize, header.size + 1,
|
||||||
Lzip_header::size + 6, dictionary_size, terminator );
|
header.size + 6, dictionary_size, terminator );
|
||||||
if( pos == 0 )
|
if( pos == 0 )
|
||||||
pos = repair_member( mbuffer, mpos, msize, Lzip_header::size + 7,
|
pos = repair_member( mbuffer, mpos, msize, header.size + 7,
|
||||||
failure_pos, dictionary_size, terminator );
|
failure_pos, dictionary_size, terminator );
|
||||||
print_pending_newline( terminator );
|
print_pending_newline( terminator );
|
||||||
}
|
}
|
||||||
|
@ -241,7 +242,7 @@ int byte_repair( const std::string & input_filename,
|
||||||
{
|
{
|
||||||
if( !safe_seek( infd, 0, filename ) ) return 1;
|
if( !safe_seek( infd, 0, filename ) ) return 1;
|
||||||
set_signal_handler();
|
set_signal_handler();
|
||||||
if( !open_outstream( true, true ) ) return 1;
|
if( !open_outstream( true, true, false, true, to_file ) ) return 1;
|
||||||
if( !copy_file( infd, outfd ) ) // copy whole file
|
if( !copy_file( infd, outfd ) ) // copy whole file
|
||||||
cleanup_and_fail( 1 );
|
cleanup_and_fail( 1 );
|
||||||
}
|
}
|
||||||
|
@ -263,7 +264,7 @@ int byte_repair( const std::string & input_filename,
|
||||||
std::fputs( "Input file has no errors. Recovery is not needed.\n", stdout );
|
std::fputs( "Input file has no errors. Recovery is not needed.\n", stdout );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if( close_outstream( &in_stats ) != 0 ) return 1;
|
if( !close_outstream( &in_stats ) ) return 1;
|
||||||
if( verbosity >= 1 )
|
if( verbosity >= 1 )
|
||||||
std::fputs( "Copy of input file repaired successfully.\n", stdout );
|
std::fputs( "Copy of input file repaired successfully.\n", stdout );
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -416,10 +417,10 @@ int debug_byte_repair( const char * const input_filename,
|
||||||
if( failure_pos >= msize ) failure_pos = msize - 1;
|
if( failure_pos >= msize ) failure_pos = msize - 1;
|
||||||
long pos = repair_dictionary_size( mbuffer, msize );
|
long pos = repair_dictionary_size( mbuffer, msize );
|
||||||
if( pos == 0 )
|
if( pos == 0 )
|
||||||
pos = repair_member( mbuffer, mpos, msize, Lzip_header::size + 1,
|
pos = repair_member( mbuffer, mpos, msize, header.size + 1,
|
||||||
Lzip_header::size + 6, dictionary_size, terminator );
|
header.size + 6, dictionary_size, terminator );
|
||||||
if( pos == 0 )
|
if( pos == 0 )
|
||||||
pos = repair_member( mbuffer, mpos, msize, Lzip_header::size + 7,
|
pos = repair_member( mbuffer, mpos, msize, header.size + 7,
|
||||||
failure_pos, dictionary_size, terminator );
|
failure_pos, dictionary_size, terminator );
|
||||||
print_pending_newline( terminator );
|
print_pending_newline( terminator );
|
||||||
delete[] mbuffer;
|
delete[] mbuffer;
|
||||||
|
@ -512,7 +513,7 @@ int debug_decompress( const char * const input_filename,
|
||||||
std::fputc( '\n', stdout );
|
std::fputc( '\n', stdout );
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = std::max( retval, close_outstream( &in_stats ) );
|
if( !close_outstream( &in_stats ) && retval == 0 ) retval = 1;
|
||||||
if( verbosity >= 1 && show_packets && retval == 0 )
|
if( verbosity >= 1 && show_packets && retval == 0 )
|
||||||
std::fputs( "Done.\n", stdout );
|
std::fputs( "Done.\n", stdout );
|
||||||
return retval;
|
return retval;
|
||||||
|
|
2
common.h
2
common.h
|
@ -1,5 +1,5 @@
|
||||||
/* Lziprecover - Data recovery tool for the lzip format
|
/* Lziprecover - Data recovery tool for the lzip format
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
18
configure
vendored
18
configure
vendored
|
@ -1,12 +1,12 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# configure script for Lziprecover - Data recovery tool for the lzip format
|
# configure script for Lziprecover - Data recovery tool for the lzip format
|
||||||
# Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
# Copyright (C) 2009-2024 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=lziprecover
|
pkgname=lziprecover
|
||||||
pkgversion=1.24-pre1
|
pkgversion=1.24
|
||||||
progname=lziprecover
|
progname=lziprecover
|
||||||
srctrigger=doc/${pkgname}.texi
|
srctrigger=doc/${pkgname}.texi
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ while [ $# != 0 ] ; do
|
||||||
|
|
||||||
# Split out the argument for options that take them
|
# Split out the argument for options that take them
|
||||||
case ${option} in
|
case ${option} in
|
||||||
*=*) optarg="`echo "${option}" | sed -e 's,^[^=]*=,,;s,/$,,'`" ;;
|
*=*) optarg=`echo "${option}" | sed -e 's,^[^=]*=,,;s,/$,,'` ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Process the options
|
# Process the options
|
||||||
|
@ -66,10 +66,10 @@ while [ $# != 0 ] ; do
|
||||||
echo " --infodir=DIR info files directory [${infodir}]"
|
echo " --infodir=DIR info files directory [${infodir}]"
|
||||||
echo " --mandir=DIR man pages directory [${mandir}]"
|
echo " --mandir=DIR man pages directory [${mandir}]"
|
||||||
echo " CXX=COMPILER C++ compiler to use [${CXX}]"
|
echo " CXX=COMPILER C++ compiler to use [${CXX}]"
|
||||||
echo " CPPFLAGS=OPTIONS command line options for the preprocessor [${CPPFLAGS}]"
|
echo " CPPFLAGS=OPTIONS command-line options for the preprocessor [${CPPFLAGS}]"
|
||||||
echo " CXXFLAGS=OPTIONS command line options for the C++ compiler [${CXXFLAGS}]"
|
echo " CXXFLAGS=OPTIONS command-line options for the C++ compiler [${CXXFLAGS}]"
|
||||||
echo " CXXFLAGS+=OPTIONS append options to the current value of CXXFLAGS"
|
echo " CXXFLAGS+=OPTIONS append options to the current value of CXXFLAGS"
|
||||||
echo " LDFLAGS=OPTIONS command line options for the linker [${LDFLAGS}]"
|
echo " LDFLAGS=OPTIONS command-line options for the linker [${LDFLAGS}]"
|
||||||
echo " MAKEINFO=NAME makeinfo program to use [${MAKEINFO}]"
|
echo " MAKEINFO=NAME makeinfo program to use [${MAKEINFO}]"
|
||||||
echo
|
echo
|
||||||
exit 0 ;;
|
exit 0 ;;
|
||||||
|
@ -125,7 +125,7 @@ if [ -z "${srcdir}" ] ; then
|
||||||
if [ ! -r "${srcdir}/${srctrigger}" ] ; then srcdir=.. ; fi
|
if [ ! -r "${srcdir}/${srctrigger}" ] ; then srcdir=.. ; fi
|
||||||
if [ ! -r "${srcdir}/${srctrigger}" ] ; then
|
if [ ! -r "${srcdir}/${srctrigger}" ] ; then
|
||||||
## the sed command below emulates the dirname command
|
## the sed command below emulates the dirname command
|
||||||
srcdir="`echo "$0" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`"
|
srcdir=`echo "$0" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ if [ -z "${no_create}" ] ; then
|
||||||
# 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.
|
||||||
|
|
||||||
exec /bin/sh $0 ${args} --no-create
|
exec /bin/sh "$0" ${args} --no-create
|
||||||
EOF
|
EOF
|
||||||
chmod +x config.status
|
chmod +x config.status
|
||||||
fi
|
fi
|
||||||
|
@ -171,7 +171,7 @@ echo "MAKEINFO = ${MAKEINFO}"
|
||||||
rm -f Makefile
|
rm -f Makefile
|
||||||
cat > Makefile << EOF
|
cat > Makefile << EOF
|
||||||
# Makefile for Lziprecover - Data recovery tool for the lzip format
|
# Makefile for Lziprecover - Data recovery tool for the lzip format
|
||||||
# Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
# Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
# This file was generated automatically by configure. Don't 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
|
||||||
|
|
52
decoder.cc
52
decoder.cc
|
@ -1,5 +1,5 @@
|
||||||
/* Lziprecover - Data recovery tool for the lzip format
|
/* Lziprecover - Data recovery tool for the lzip format
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -112,21 +112,17 @@ int LZ_decoder::check_trailer( const Pretty_print & pp,
|
||||||
const bool ignore_empty ) const
|
const bool ignore_empty ) const
|
||||||
{
|
{
|
||||||
Lzip_trailer trailer;
|
Lzip_trailer trailer;
|
||||||
int size = rdec.read_data( trailer.data, Lzip_trailer::size );
|
int size = rdec.read_data( trailer.data, trailer.size );
|
||||||
const unsigned long long data_size = data_position();
|
|
||||||
const unsigned long long member_size = rdec.member_position();
|
|
||||||
bool error = false;
|
bool error = false;
|
||||||
|
|
||||||
if( size < Lzip_trailer::size )
|
if( size < trailer.size )
|
||||||
{
|
{
|
||||||
error = true;
|
error = true;
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
{
|
{ pp();
|
||||||
pp();
|
std::fprintf( stderr, "Trailer truncated at trailer position %d;"
|
||||||
std::fprintf( stderr, "Trailer truncated at trailer position %d;"
|
" some checks may fail.\n", size ); }
|
||||||
" some checks may fail.\n", size );
|
while( size < trailer.size ) trailer.data[size++] = 0;
|
||||||
}
|
|
||||||
while( size < Lzip_trailer::size ) trailer.data[size++] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned td_crc = trailer.data_crc();
|
const unsigned td_crc = trailer.data_crc();
|
||||||
|
@ -134,33 +130,29 @@ int LZ_decoder::check_trailer( const Pretty_print & pp,
|
||||||
{
|
{
|
||||||
error = true;
|
error = true;
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
{
|
{ pp();
|
||||||
pp();
|
std::fprintf( stderr, "CRC mismatch; stored %08X, computed %08X\n",
|
||||||
std::fprintf( stderr, "CRC mismatch; stored %08X, computed %08X\n",
|
td_crc, crc() ); }
|
||||||
td_crc, crc() );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
const unsigned long long data_size = data_position();
|
||||||
const unsigned long long td_size = trailer.data_size();
|
const unsigned long long td_size = trailer.data_size();
|
||||||
if( td_size != data_size )
|
if( td_size != data_size )
|
||||||
{
|
{
|
||||||
error = true;
|
error = true;
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
{
|
{ pp();
|
||||||
pp();
|
std::fprintf( stderr, "Data size mismatch; stored %llu (0x%llX), computed %llu (0x%llX)\n",
|
||||||
std::fprintf( stderr, "Data size mismatch; stored %llu (0x%llX), computed %llu (0x%llX)\n",
|
td_size, td_size, data_size, data_size ); }
|
||||||
td_size, td_size, data_size, data_size );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
const unsigned long long member_size = rdec.member_position();
|
||||||
const unsigned long long tm_size = trailer.member_size();
|
const unsigned long long tm_size = trailer.member_size();
|
||||||
if( tm_size != member_size )
|
if( tm_size != member_size )
|
||||||
{
|
{
|
||||||
error = true;
|
error = true;
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
{
|
{ pp();
|
||||||
pp();
|
std::fprintf( stderr, "Member size mismatch; stored %llu (0x%llX), computed %llu (0x%llX)\n",
|
||||||
std::fprintf( stderr, "Member size mismatch; stored %llu (0x%llX), computed %llu (0x%llX)\n",
|
tm_size, tm_size, member_size, member_size ); }
|
||||||
tm_size, tm_size, member_size, member_size );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if( error ) return 3;
|
if( error ) return 3;
|
||||||
if( !ignore_empty && data_size == 0 ) return 5;
|
if( !ignore_empty && data_size == 0 ) return 5;
|
||||||
|
@ -190,8 +182,8 @@ int LZ_decoder::check_trailer( const Pretty_print & pp,
|
||||||
/* Return value: 0 = OK, 1 = decoder error, 2 = unexpected EOF,
|
/* Return value: 0 = OK, 1 = decoder error, 2 = unexpected EOF,
|
||||||
3 = trailer error, 4 = unknown marker found,
|
3 = trailer error, 4 = unknown marker found,
|
||||||
5 = empty member found, 6 = marked member found. */
|
5 = empty member found, 6 = marked member found. */
|
||||||
int LZ_decoder::decode_member( const Pretty_print & pp,
|
int LZ_decoder::decode_member( const Cl_options & cl_opts,
|
||||||
const bool ignore_empty, const bool ignore_marking )
|
const Pretty_print & pp )
|
||||||
{
|
{
|
||||||
Bit_model bm_literal[1<<literal_context_bits][0x300];
|
Bit_model bm_literal[1<<literal_context_bits][0x300];
|
||||||
Bit_model bm_match[State::states][pos_states];
|
Bit_model bm_match[State::states][pos_states];
|
||||||
|
@ -211,7 +203,7 @@ int LZ_decoder::decode_member( const Pretty_print & pp,
|
||||||
unsigned rep3 = 0;
|
unsigned rep3 = 0;
|
||||||
State state;
|
State state;
|
||||||
|
|
||||||
if( !rdec.load( ignore_marking ) ) return 6;
|
if( !rdec.load( cl_opts.ignore_marking ) ) return 6;
|
||||||
while( !rdec.finished() )
|
while( !rdec.finished() )
|
||||||
{
|
{
|
||||||
const int pos_state = data_position() & pos_state_mask;
|
const int pos_state = data_position() & pos_state_mask;
|
||||||
|
@ -275,7 +267,7 @@ int LZ_decoder::decode_member( const Pretty_print & pp,
|
||||||
rdec.normalize();
|
rdec.normalize();
|
||||||
flush_data();
|
flush_data();
|
||||||
if( len == min_match_len ) // End Of Stream marker
|
if( len == min_match_len ) // End Of Stream marker
|
||||||
return check_trailer( pp, ignore_empty );
|
return check_trailer( pp, cl_opts.ignore_empty );
|
||||||
if( len == min_match_len + 1 ) // Sync Flush marker
|
if( len == min_match_len + 1 ) // Sync Flush marker
|
||||||
{ rdec.load(); continue; }
|
{ rdec.load(); continue; }
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
|
|
11
decoder.h
11
decoder.h
|
@ -1,5 +1,5 @@
|
||||||
/* Lziprecover - Data recovery tool for the lzip format
|
/* Lziprecover - Data recovery tool for the lzip format
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -81,7 +81,7 @@ public:
|
||||||
int read_header_carefully( Lzip_header & header, const bool ignore_errors )
|
int read_header_carefully( Lzip_header & header, const bool ignore_errors )
|
||||||
{
|
{
|
||||||
int sz = 0;
|
int sz = 0;
|
||||||
while( sz < Lzip_header::size && !finished() )
|
while( sz < header.size && !finished() )
|
||||||
{
|
{
|
||||||
header.data[sz] = buffer[pos];
|
header.data[sz] = buffer[pos];
|
||||||
if( ignore_errors &&
|
if( ignore_errors &&
|
||||||
|
@ -100,7 +100,7 @@ public:
|
||||||
if( buffer[pos] != lzip_magic[0] ) { ++pos; continue; }
|
if( buffer[pos] != lzip_magic[0] ) { ++pos; continue; }
|
||||||
reset_member_position();
|
reset_member_position();
|
||||||
Lzip_header h;
|
Lzip_header h;
|
||||||
if( read_header_carefully( h, true ) == Lzip_header::size )
|
if( read_header_carefully( h, true ) == header.size )
|
||||||
{ header = h; return true; }
|
{ header = h; return true; }
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -381,6 +381,7 @@ public:
|
||||||
unsigned crc() const { return crc_ ^ 0xFFFFFFFFU; }
|
unsigned crc() const { return crc_ ^ 0xFFFFFFFFU; }
|
||||||
unsigned long long data_position() const { return partial_data_pos + pos; }
|
unsigned long long data_position() const { return partial_data_pos + pos; }
|
||||||
|
|
||||||
int decode_member( const Pretty_print & pp, const bool ignore_empty = true,
|
int decode_member( const Cl_options & cl_opts, const Pretty_print & pp );
|
||||||
const bool ignore_marking = true );
|
int decode_member()
|
||||||
|
{ return decode_member( Cl_options(), Pretty_print( "" ) ); }
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.2.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.2.
|
||||||
.TH LZIPRECOVER "1" "June 2023" "lziprecover 1.24-pre1" "User Commands"
|
.TH LZIPRECOVER "1" "January 2024" "lziprecover 1.24" "User Commands"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
lziprecover \- recovers data from damaged lzip files
|
lziprecover \- recovers data from damaged lzip files
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
@ -75,7 +75,7 @@ keep (don't delete) input files
|
||||||
print (un)compressed file sizes
|
print (un)compressed file sizes
|
||||||
.TP
|
.TP
|
||||||
\fB\-m\fR, \fB\-\-merge\fR
|
\fB\-m\fR, \fB\-\-merge\fR
|
||||||
correct errors in file using several copies
|
repair errors in file using several copies
|
||||||
.TP
|
.TP
|
||||||
\fB\-o\fR, \fB\-\-output=\fR<file>
|
\fB\-o\fR, \fB\-\-output=\fR<file>
|
||||||
place the output into <file>
|
place the output into <file>
|
||||||
|
@ -125,7 +125,7 @@ To extract all the files from archive 'foo.tar.lz', use the commands
|
||||||
\&'tar \fB\-xf\fR foo.tar.lz' or 'lziprecover \fB\-cd\fR foo.tar.lz | tar \fB\-xf\fR \-'.
|
\&'tar \fB\-xf\fR foo.tar.lz' or 'lziprecover \fB\-cd\fR foo.tar.lz | tar \fB\-xf\fR \-'.
|
||||||
.PP
|
.PP
|
||||||
Exit status: 0 for a normal exit, 1 for environmental problems
|
Exit status: 0 for a normal exit, 1 for environmental problems
|
||||||
(file not found, invalid command line options, I/O errors, etc), 2 to
|
(file not found, invalid command\-line options, I/O errors, etc), 2 to
|
||||||
indicate a corrupt or invalid input file, 3 for an internal consistency
|
indicate a corrupt or invalid input file, 3 for an internal consistency
|
||||||
error (e.g., bug) which caused lziprecover to panic.
|
error (e.g., bug) which caused lziprecover to panic.
|
||||||
.SH "REPORTING BUGS"
|
.SH "REPORTING BUGS"
|
||||||
|
@ -133,7 +133,7 @@ Report bugs to lzip\-bug@nongnu.org
|
||||||
.br
|
.br
|
||||||
Lziprecover home page: http://www.nongnu.org/lzip/lziprecover.html
|
Lziprecover home page: http://www.nongnu.org/lzip/lziprecover.html
|
||||||
.SH COPYRIGHT
|
.SH COPYRIGHT
|
||||||
Copyright \(co 2023 Antonio Diaz Diaz.
|
Copyright \(co 2024 Antonio Diaz Diaz.
|
||||||
License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>
|
License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>
|
||||||
.br
|
.br
|
||||||
This is free software: you are free to change and redistribute it.
|
This is free software: you are free to change and redistribute it.
|
||||||
|
|
|
@ -12,12 +12,12 @@ File: lziprecover.info, Node: Top, Next: Introduction, Up: (dir)
|
||||||
Lziprecover Manual
|
Lziprecover Manual
|
||||||
******************
|
******************
|
||||||
|
|
||||||
This manual is for Lziprecover (version 1.24-pre1, 14 June 2023).
|
This manual is for Lziprecover (version 1.24, 20 January 2024).
|
||||||
|
|
||||||
* Menu:
|
* Menu:
|
||||||
|
|
||||||
* Introduction:: Purpose and features of lziprecover
|
* Introduction:: Purpose and features of lziprecover
|
||||||
* Invoking lziprecover:: Command line interface
|
* Invoking lziprecover:: Command-line interface
|
||||||
* Data safety:: Protecting data from accidental loss
|
* Data safety:: Protecting data from accidental loss
|
||||||
* Repairing one byte:: Fixing bit flips and similar errors
|
* Repairing one byte:: Fixing bit flips and similar errors
|
||||||
* Merging files:: Fixing several damaged copies
|
* Merging files:: Fixing several damaged copies
|
||||||
|
@ -32,7 +32,7 @@ This manual is for Lziprecover (version 1.24-pre1, 14 June 2023).
|
||||||
* Concept index:: Index of concepts
|
* Concept index:: Index of concepts
|
||||||
|
|
||||||
|
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This manual is free documentation: you have unlimited permission to copy,
|
This manual is free documentation: you have unlimited permission to copy,
|
||||||
distribute, and modify it.
|
distribute, and modify it.
|
||||||
|
@ -211,12 +211,12 @@ to prepend './' to any file name beginning with a hyphen, or use '--'.
|
||||||
'--reproduce'
|
'--reproduce'
|
||||||
Try to recover a missing (zeroed) sector in FILE using a reference
|
Try to recover a missing (zeroed) sector in FILE using a reference
|
||||||
file and the same version of lzip that created FILE. If successful, a
|
file and the same version of lzip that created FILE. If successful, a
|
||||||
repaired copy is written to the file 'FILE_fixed.lz'. FILE is not
|
repaired copy is written to the file FILE_fixed.lz. FILE is not
|
||||||
modified at all. The exit status is 0 if the member containing the
|
modified at all. The exit status is 0 if the member containing the
|
||||||
zeroed sector could be repaired, 2 otherwise. Note that
|
zeroed sector could be repaired, 2 otherwise. Note that FILE_fixed.lz
|
||||||
'FILE_fixed.lz' may still contain errors in the members following the
|
may still contain errors in the members following the one repaired.
|
||||||
one repaired. *Note Reproducing one sector::, for a complete
|
*Note Reproducing one sector::, for a complete description of the
|
||||||
description of the reproduce mode.
|
reproduce mode.
|
||||||
|
|
||||||
'--lzip-level=DIGIT|a|m[LENGTH]'
|
'--lzip-level=DIGIT|a|m[LENGTH]'
|
||||||
Try only the given compression level or match length limit when
|
Try only the given compression level or match length limit when
|
||||||
|
@ -273,7 +273,7 @@ to prepend './' to any file name beginning with a hyphen, or use '--'.
|
||||||
file numbers produced by '--split'.
|
file numbers produced by '--split'.
|
||||||
|
|
||||||
If any file is damaged, does not exist, can't be opened, or is not
|
If any file is damaged, does not exist, can't be opened, or is not
|
||||||
regular, the final exit status will be > 0. '-lq' can be used to check
|
regular, the final exit status is > 0. '-lq' can be used to check
|
||||||
quickly (without decompressing) the structural integrity of the files
|
quickly (without decompressing) the structural integrity of the files
|
||||||
specified. (Use '--test' to check the data integrity). '-alq'
|
specified. (Use '--test' to check the data integrity). '-alq'
|
||||||
additionally checks that none of the files specified contain trailing
|
additionally checks that none of the files specified contain trailing
|
||||||
|
@ -283,21 +283,21 @@ to prepend './' to any file name beginning with a hyphen, or use '--'.
|
||||||
'--merge'
|
'--merge'
|
||||||
Try to produce a correct file by merging the good parts of two or more
|
Try to produce a correct file by merging the good parts of two or more
|
||||||
damaged copies. If successful, a repaired copy is written to the file
|
damaged copies. If successful, a repaired copy is written to the file
|
||||||
'FILE_fixed.lz'. The exit status is 0 if a correct file could be
|
FILE_fixed.lz. The exit status is 0 if a correct file could be
|
||||||
produced, 2 otherwise. *Note Merging files::, for a complete
|
produced, 2 otherwise. *Note Merging files::, for a complete
|
||||||
description of the merge mode.
|
description of the merge mode.
|
||||||
|
|
||||||
'-o FILE'
|
'-o FILE'
|
||||||
'--output=FILE'
|
'--output=FILE'
|
||||||
Place the output into FILE instead of into 'FILE_fixed.lz'. If
|
Place the repaired output into FILE instead of into FILE_fixed.lz. If
|
||||||
splitting, the names of the files produced are in the form
|
splitting, the names of the files produced are in the form
|
||||||
'rec01FILE', 'rec02FILE', etc.
|
'rec01FILE', 'rec02FILE', etc.
|
||||||
|
|
||||||
If decompressing, or converting lzma-alone files, and '-c' has not been
|
If '-c' has not been also specified, write the (de)compressed output
|
||||||
also specified, write the decompressed or converted output to FILE;
|
to FILE, automatically creating any missing parent directories; keep
|
||||||
keep input files unchanged. This option (or '-c') is needed when
|
input files unchanged. This option (or '-c') is needed when reading
|
||||||
reading from a named pipe (fifo) or from a device. '-o -' is
|
from a named pipe (fifo) or from a device. '-o -' is equivalent to
|
||||||
equivalent to '-c'. '-o' has no effect when testing or listing.
|
'-c'. '-o' has no effect when testing or listing.
|
||||||
|
|
||||||
'-q'
|
'-q'
|
||||||
'--quiet'
|
'--quiet'
|
||||||
|
@ -307,7 +307,7 @@ to prepend './' to any file name beginning with a hyphen, or use '--'.
|
||||||
'--byte-repair'
|
'--byte-repair'
|
||||||
Try to repair a FILE with small errors (up to one single-byte error
|
Try to repair a FILE with small errors (up to one single-byte error
|
||||||
per member). If successful, a repaired copy is written to the file
|
per member). If successful, a repaired copy is written to the file
|
||||||
'FILE_fixed.lz'. FILE is not modified at all. The exit status is 0 if
|
FILE_fixed.lz. FILE is not modified at all. The exit status is 0 if
|
||||||
the file could be repaired, 2 otherwise. *Note Repairing one byte::,
|
the file could be repaired, 2 otherwise. *Note Repairing one byte::,
|
||||||
for a complete description of the repair mode.
|
for a complete description of the repair mode.
|
||||||
|
|
||||||
|
@ -491,12 +491,12 @@ to prepend './' to any file name beginning with a hyphen, or use '--'.
|
||||||
With argument '1', test 1-bit errors in the LZMA stream of the
|
With argument '1', test 1-bit errors in the LZMA stream of the
|
||||||
compressed input FILE like the command
|
compressed input FILE like the command
|
||||||
'unzcrash -b1 -p7 -s-20 'lzip -t' FILE' but in memory, and therefore
|
'unzcrash -b1 -p7 -s-20 'lzip -t' FILE' but in memory, and therefore
|
||||||
much faster. *Note Unzcrash::. This option tests all the members
|
much faster (30 to 50 times faster). *Note Unzcrash::. This option
|
||||||
independently in a multimember file, skipping headers and trailers. If
|
tests all the members independently in a multimember file, skipping
|
||||||
a decompression succeeds, the decompressed output is compared with the
|
headers and trailers. If a decompression succeeds, the decompressed
|
||||||
decompressed output of the original FILE using MD5 digests. FILE must
|
output is compared with the decompressed output of the original FILE
|
||||||
not contain errors and must decompress correctly for the comparisons to
|
using MD5 digests. FILE must not contain errors and must decompress
|
||||||
work.
|
correctly for the comparisons to work.
|
||||||
|
|
||||||
With argument 'B', test zeroed sectors (blocks of bytes) in the LZMA
|
With argument 'B', test zeroed sectors (blocks of bytes) in the LZMA
|
||||||
stream of the compressed input FILE like the command
|
stream of the compressed input FILE like the command
|
||||||
|
@ -517,8 +517,8 @@ to prepend './' to any file name beginning with a hyphen, or use '--'.
|
||||||
'--debug-decompress=POSITION,VALUE'
|
'--debug-decompress=POSITION,VALUE'
|
||||||
Load the compressed FILE into memory, set the byte at POSITION to
|
Load the compressed FILE into memory, set the byte at POSITION to
|
||||||
VALUE, and decompress the modified compressed data to standard output.
|
VALUE, and decompress the modified compressed data to standard output.
|
||||||
If the damaged member is decompressed fully (just fails with a CRC
|
If the damaged member can be decompressed to the end (just fails with
|
||||||
mismatch), the members following it are also decompressed.
|
a CRC mismatch), the members following it are also decompressed.
|
||||||
|
|
||||||
'-X[POSITION,VALUE]'
|
'-X[POSITION,VALUE]'
|
||||||
'--show-packets[=POSITION,VALUE]'
|
'--show-packets[=POSITION,VALUE]'
|
||||||
|
@ -564,7 +564,7 @@ Q quettabyte (10^30) | Qi quebibyte (2^100)
|
||||||
|
|
||||||
|
|
||||||
Exit status: 0 for a normal exit, 1 for environmental problems (file not
|
Exit status: 0 for a normal exit, 1 for environmental problems (file not
|
||||||
found, invalid command line options, I/O errors, etc), 2 to indicate a
|
found, invalid command-line options, I/O errors, etc), 2 to indicate a
|
||||||
corrupt or invalid input file, 3 for an internal consistency error (e.g.,
|
corrupt or invalid input file, 3 for an internal consistency error (e.g.,
|
||||||
bug) which caused lziprecover to panic.
|
bug) which caused lziprecover to panic.
|
||||||
|
|
||||||
|
@ -574,7 +574,7 @@ File: lziprecover.info, Node: Data safety, Next: Repairing one byte, Prev: In
|
||||||
3 Protecting data from accidental loss
|
3 Protecting data from accidental loss
|
||||||
**************************************
|
**************************************
|
||||||
|
|
||||||
It is a fact of life that sometimes data will become corrupt. Software has
|
It is a fact of life that sometimes data becomes corrupt. Software has
|
||||||
errors. Hardware may misbehave or fail. RAM may be struck by a cosmic ray.
|
errors. Hardware may misbehave or fail. RAM may be struck by a cosmic ray.
|
||||||
This is why a safe enough integrity checking is needed in compressed
|
This is why a safe enough integrity checking is needed in compressed
|
||||||
formats, and the reason why a data recovery tool is sometimes needed.
|
formats, and the reason why a data recovery tool is sometimes needed.
|
||||||
|
@ -690,9 +690,9 @@ File: lziprecover.info, Node: Repairing one byte, Next: Merging files, Prev:
|
||||||
|
|
||||||
Lziprecover can repair perfectly most files with small errors (up to one
|
Lziprecover can repair perfectly most files with small errors (up to one
|
||||||
single-byte error per member), without the need of any extra redundance at
|
single-byte error per member), without the need of any extra redundance at
|
||||||
all. If the reparation is successful, the repaired file will be identical
|
all. If the reparation is successful, the repaired file is identical bit for
|
||||||
bit for bit to the original. This makes lzip files resistant to bit flip,
|
bit to the original. This makes lzip files resistant to bit flip, one of the
|
||||||
one of the most common forms of data corruption.
|
most common forms of data corruption.
|
||||||
|
|
||||||
The file is repaired in memory. Therefore, enough virtual memory
|
The file is repaired in memory. Therefore, enough virtual memory
|
||||||
(RAM + swap) to contain the largest damaged member is required.
|
(RAM + swap) to contain the largest damaged member is required.
|
||||||
|
@ -730,23 +730,23 @@ File: lziprecover.info, Node: Merging files, Next: Reproducing one sector, Pr
|
||||||
***************
|
***************
|
||||||
|
|
||||||
If you have several copies of a file but all of them are too damaged to
|
If you have several copies of a file but all of them are too damaged to
|
||||||
repair them (*note Repairing one byte::), lziprecover can try to produce a
|
repair them individually (*note Repairing one byte::), lziprecover can try
|
||||||
correct file by merging the good parts of the damaged copies.
|
to produce a correct file by merging the good parts of the damaged copies.
|
||||||
|
|
||||||
The merge may succeed even if some copies of the file have all the
|
The merge may succeed even if some copies of the file have all the
|
||||||
headers and trailers damaged, as long as there is at least one copy of
|
headers and trailers damaged, as long as there is at least one copy of
|
||||||
every header and trailer intact, even if they are in different copies of
|
every header and trailer intact, even if they are in different copies of
|
||||||
the file.
|
the file.
|
||||||
|
|
||||||
The merge will fail if the damaged areas overlap (at least one byte is
|
The merge fails if the damaged areas overlap (at least one byte is
|
||||||
damaged in all copies), or are adjacent and the boundary can't be
|
damaged in all copies), or are adjacent and the boundary can't be
|
||||||
determined, or if the copies have too many damaged areas.
|
determined, or if the copies have too many damaged areas.
|
||||||
|
|
||||||
All the copies to be merged must have the same size. If any of them is
|
All the copies to be merged must have the same size. If any of them is
|
||||||
larger or smaller than it should, either because it has been truncated or
|
larger or smaller than it should, either because it has been truncated or
|
||||||
because it got some garbage data appended at the end, it can be brought to
|
because it got some garbage data appended at the end, it can be brought to
|
||||||
the correct size with the following command before merging it with the
|
the correct size with the following command before merging it with the other
|
||||||
other copies:
|
copies:
|
||||||
|
|
||||||
ddrescue -s<correct_size> -x<correct_size> file.lz correct_size_file.lz
|
ddrescue -s<correct_size> -x<correct_size> file.lz correct_size_file.lz
|
||||||
|
|
||||||
|
@ -1009,8 +1009,8 @@ the tar archiver and the lzip compressor.
|
||||||
Tarlz creates tar archives using a simplified and safer variant of the
|
Tarlz creates tar archives using a simplified and safer variant of the
|
||||||
POSIX pax format compressed in lzip format, keeping the alignment between
|
POSIX pax format compressed in lzip format, keeping the alignment between
|
||||||
tar members and lzip members. The resulting multimember tar.lz archive is
|
tar members and lzip members. The resulting multimember tar.lz archive is
|
||||||
fully backward compatible with standard tar tools like GNU tar, which treat
|
backward compatible with standard tar tools like GNU tar, which treat it
|
||||||
it like any other tar.lz archive. *Note tarlz manual: (tarlz)Top, and *note
|
like any other tar.lz archive. *Note tarlz manual: (tarlz)Top, and *note
|
||||||
lzip manual: (lzip)Top.
|
lzip manual: (lzip)Top.
|
||||||
|
|
||||||
Multimember tar.lz archives have some safety advantages over solidly
|
Multimember tar.lz archives have some safety advantages over solidly
|
||||||
|
@ -1113,7 +1113,7 @@ when there is no longer anything to take away.
|
||||||
represents a variable number of bytes.
|
represents a variable number of bytes.
|
||||||
|
|
||||||
|
|
||||||
A lzip file consists of a series of independent "members" (compressed
|
A lzip file consists of one or more independent "members" (compressed
|
||||||
data sets). The members simply appear one after another in the file, with no
|
data sets). The members simply appear one after another in the file, with no
|
||||||
additional information before, between, or after them. Each member can
|
additional information before, between, or after them. Each member can
|
||||||
encode in compressed form up to 16 EiB - 1 byte of uncompressed data. The
|
encode in compressed form up to 16 EiB - 1 byte of uncompressed data. The
|
||||||
|
@ -1180,7 +1180,7 @@ member. Such trailing data may be:
|
||||||
the file has not been truncated), a cryptographically secure hash, a
|
the file has not been truncated), a cryptographically secure hash, a
|
||||||
description of file contents, etc. It is safe to append any amount of
|
description of file contents, etc. It is safe to append any amount of
|
||||||
text to a lzip file as long as none of the first four bytes of the
|
text to a lzip file as long as none of the first four bytes of the
|
||||||
text match the corresponding byte in the string "LZIP", and the text
|
text matches the corresponding byte in the string "LZIP", and the text
|
||||||
does not contain any zero bytes (null characters). Nonzero bytes and
|
does not contain any zero bytes (null characters). Nonzero bytes and
|
||||||
zero bytes can't be safely mixed in trailing data.
|
zero bytes can't be safely mixed in trailing data.
|
||||||
|
|
||||||
|
@ -1198,7 +1198,7 @@ member. Such trailing data may be:
|
||||||
discriminate trailing data from a corrupt header has a Hamming
|
discriminate trailing data from a corrupt header has a Hamming
|
||||||
distance (HD) of 3, and the 3 bit flips must happen in different magic
|
distance (HD) of 3, and the 3 bit flips must happen in different magic
|
||||||
bytes for the test to fail. In any case, the option '--trailing-error'
|
bytes for the test to fail. In any case, the option '--trailing-error'
|
||||||
guarantees that any corrupt header will be detected.
|
guarantees that any corrupt header is detected.
|
||||||
|
|
||||||
Trailing data are in no way part of the lzip file format, but tools
|
Trailing data are in no way part of the lzip file format, but tools
|
||||||
reading lzip files are expected to behave as correctly and usefully as
|
reading lzip files are expected to behave as correctly and usefully as
|
||||||
|
@ -1305,7 +1305,9 @@ File: lziprecover.info, Node: Unzcrash, Next: Problems, Prev: Examples, Up:
|
||||||
12 Testing the robustness of decompressors
|
12 Testing the robustness of decompressors
|
||||||
******************************************
|
******************************************
|
||||||
|
|
||||||
The lziprecover package also includes unzcrash, a program written to test
|
*Note --unzcrash::, for a faster way of testing the robustness of lzip.
|
||||||
|
|
||||||
|
The lziprecover package also includes unzcrash, a program written to test
|
||||||
robustness to decompression of corrupted data, inspired by unzcrash.c from
|
robustness to decompression of corrupted data, inspired by unzcrash.c from
|
||||||
Julian Seward's bzip2. Type 'make unzcrash' in the lziprecover source
|
Julian Seward's bzip2. Type 'make unzcrash' in the lziprecover source
|
||||||
directory to build it.
|
directory to build it.
|
||||||
|
@ -1332,7 +1334,7 @@ the first non-option argument, and then writes the file specified in the
|
||||||
second non-option argument to the standard input of the subprocess,
|
second non-option argument to the standard input of the subprocess,
|
||||||
modifying the corresponding byte each time. Therefore unzcrash can be used
|
modifying the corresponding byte each time. Therefore unzcrash can be used
|
||||||
to test any decompressor (not only lzip), or even other decoder programs
|
to test any decompressor (not only lzip), or even other decoder programs
|
||||||
having a suitable command line syntax.
|
having a suitable command-line syntax.
|
||||||
|
|
||||||
If the decompressor returns with zero status, unzcrash compares the
|
If the decompressor returns with zero status, unzcrash compares the
|
||||||
output of the decompressor for the original and corrupt files. If the
|
output of the decompressor for the original and corrupt files. If the
|
||||||
|
@ -1345,9 +1347,9 @@ latter case, please, report any false negative as a bug.
|
||||||
In order to compare the outputs, unzcrash needs a 'zcmp' program able to
|
In order to compare the outputs, unzcrash needs a 'zcmp' program able to
|
||||||
understand the format being tested. For example the 'zcmp' provided by
|
understand the format being tested. For example the 'zcmp' provided by
|
||||||
zutils. If the 'zcmp' program used does not understand the format being
|
zutils. If the 'zcmp' program used does not understand the format being
|
||||||
tested, all the comparisons will fail because the compressed files will be
|
tested, all the comparisons fail because the compressed files are compared
|
||||||
compared without being decompressed first. Use '--zcmp=false' to disable
|
without being decompressed first. Use '--zcmp=false' to disable comparisons.
|
||||||
comparisons. *Note Zcmp: (zutils)Zcmp.
|
*Note Zcmp: (zutils)Zcmp.
|
||||||
|
|
||||||
The format for running unzcrash is:
|
The format for running unzcrash is:
|
||||||
|
|
||||||
|
@ -1395,8 +1397,8 @@ tested must decompress it correctly for the comparisons to work.
|
||||||
Test one byte, block, or truncation size every N bytes. If '--delta'
|
Test one byte, block, or truncation size every N bytes. If '--delta'
|
||||||
is not specified, unzcrash tests all the bytes, non-overlapping
|
is not specified, unzcrash tests all the bytes, non-overlapping
|
||||||
blocks, or truncation sizes. Values of N smaller than the block size
|
blocks, or truncation sizes. Values of N smaller than the block size
|
||||||
will result in overlapping blocks. (Which is convenient for testing
|
result in overlapping blocks. (Which is convenient for testing because
|
||||||
because there are usually too few non-overlapping blocks in a file).
|
there are usually too few non-overlapping blocks in a file).
|
||||||
|
|
||||||
'-e POSITION,VALUE'
|
'-e POSITION,VALUE'
|
||||||
'--set-byte=POSITION,VALUE'
|
'--set-byte=POSITION,VALUE'
|
||||||
|
@ -1447,7 +1449,7 @@ tested must decompress it correctly for the comparisons to work.
|
||||||
|
|
||||||
|
|
||||||
Exit status: 0 for a normal exit, 1 for environmental problems (file not
|
Exit status: 0 for a normal exit, 1 for environmental problems (file not
|
||||||
found, invalid command line options, I/O errors, etc), 2 to indicate a
|
found, invalid command-line options, I/O errors, etc), 2 to indicate a
|
||||||
corrupt or invalid input file, 3 for an internal consistency error (e.g.,
|
corrupt or invalid input file, 3 for an internal consistency error (e.g.,
|
||||||
bug) which caused unzcrash to panic.
|
bug) which caused unzcrash to panic.
|
||||||
|
|
||||||
|
@ -1499,31 +1501,32 @@ Concept index
|
||||||
|
|
||||||
Tag Table:
|
Tag Table:
|
||||||
Node: Top226
|
Node: Top226
|
||||||
Node: Introduction1408
|
Node: Introduction1406
|
||||||
Node: Invoking lziprecover5414
|
Node: Invoking lziprecover5412
|
||||||
Ref: --trailing-error6361
|
Ref: --trailing-error6359
|
||||||
Ref: range-format8793
|
Ref: range-format8791
|
||||||
Ref: --reproduce9128
|
Ref: --reproduce9126
|
||||||
Ref: --byte-repair13424
|
Ref: --byte-repair13411
|
||||||
Node: Data safety27441
|
Ref: --unzcrash23209
|
||||||
Node: Merging with a backup29429
|
Node: Data safety27459
|
||||||
Node: Reproducing a mailbox30692
|
Node: Merging with a backup29443
|
||||||
Node: Repairing one byte33146
|
Node: Reproducing a mailbox30706
|
||||||
Node: Merging files35211
|
Node: Repairing one byte33160
|
||||||
Ref: performance-of-merge36381
|
Node: Merging files35220
|
||||||
Ref: ddrescue-example37990
|
Ref: performance-of-merge36399
|
||||||
Node: Reproducing one sector39277
|
Ref: ddrescue-example38008
|
||||||
Ref: performance-of-reproduce43163
|
Node: Reproducing one sector39295
|
||||||
Ref: ddrescue-example245837
|
Ref: performance-of-reproduce43181
|
||||||
Node: Tarlz48257
|
Ref: ddrescue-example245855
|
||||||
Node: File names51921
|
Node: Tarlz48275
|
||||||
Node: File format52383
|
Node: File names51933
|
||||||
Node: Trailing data55070
|
Node: File format52395
|
||||||
Node: Examples58388
|
Node: Trailing data55082
|
||||||
Ref: concat-example58963
|
Node: Examples58397
|
||||||
Node: Unzcrash60355
|
Ref: concat-example58972
|
||||||
Node: Problems66633
|
Node: Unzcrash60364
|
||||||
Node: Concept index67185
|
Node: Problems66704
|
||||||
|
Node: Concept index67256
|
||||||
|
|
||||||
End Tag Table
|
End Tag Table
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
@finalout
|
@finalout
|
||||||
@c %**end of header
|
@c %**end of header
|
||||||
|
|
||||||
@set UPDATED 14 June 2023
|
@set UPDATED 20 January 2024
|
||||||
@set VERSION 1.24-pre1
|
@set VERSION 1.24
|
||||||
|
|
||||||
@dircategory Compression
|
@dircategory Compression
|
||||||
@direntry
|
@direntry
|
||||||
|
@ -37,7 +37,7 @@ This manual is for Lziprecover (version @value{VERSION}, @value{UPDATED}).
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* Introduction:: Purpose and features of lziprecover
|
* Introduction:: Purpose and features of lziprecover
|
||||||
* Invoking lziprecover:: Command line interface
|
* Invoking lziprecover:: Command-line interface
|
||||||
* Data safety:: Protecting data from accidental loss
|
* Data safety:: Protecting data from accidental loss
|
||||||
* Repairing one byte:: Fixing bit flips and similar errors
|
* Repairing one byte:: Fixing bit flips and similar errors
|
||||||
* Merging files:: Fixing several damaged copies
|
* Merging files:: Fixing several damaged copies
|
||||||
|
@ -53,7 +53,7 @@ This manual is for Lziprecover (version @value{VERSION}, @value{UPDATED}).
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
@sp 1
|
@sp 1
|
||||||
Copyright @copyright{} 2009-2023 Antonio Diaz Diaz.
|
Copyright @copyright{} 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This manual is free documentation: you have unlimited permission to copy,
|
This manual is free documentation: you have unlimited permission to copy,
|
||||||
distribute, and modify it.
|
distribute, and modify it.
|
||||||
|
@ -254,12 +254,12 @@ unless the option @option{--output} is used.
|
||||||
@itemx --reproduce
|
@itemx --reproduce
|
||||||
Try to recover a missing (zeroed) sector in @var{file} using a reference
|
Try to recover a missing (zeroed) sector in @var{file} using a reference
|
||||||
file and the same version of lzip that created @var{file}. If successful, a
|
file and the same version of lzip that created @var{file}. If successful, a
|
||||||
repaired copy is written to the file @samp{@var{file}_fixed.lz}. @var{file}
|
repaired copy is written to the file @var{file}_fixed.lz. @var{file} is not
|
||||||
is not modified at all. The exit status is 0 if the member containing the
|
modified at all. The exit status is 0 if the member containing the zeroed
|
||||||
zeroed sector could be repaired, 2 otherwise. Note that
|
sector could be repaired, 2 otherwise. Note that @var{file}_fixed.lz may
|
||||||
@samp{@var{file}_fixed.lz} may still contain errors in the members following
|
still contain errors in the members following the one repaired.
|
||||||
the one repaired. @xref{Reproducing one sector}, for a complete description
|
@xref{Reproducing one sector}, for a complete description of the reproduce
|
||||||
of the reproduce mode.
|
mode.
|
||||||
|
|
||||||
@item --lzip-level=@var{digit}|a|m[@var{length}]
|
@item --lzip-level=@var{digit}|a|m[@var{length}]
|
||||||
Try only the given compression level or match length limit when reproducing
|
Try only the given compression level or match length limit when reproducing
|
||||||
|
@ -315,30 +315,30 @@ are ignored, and with @option{-ivv}, gaps between members are shown. The
|
||||||
member numbers shown coincide with the file numbers produced by @option{--split}.
|
member numbers shown coincide with the file numbers produced by @option{--split}.
|
||||||
|
|
||||||
If any file is damaged, does not exist, can't be opened, or is not regular,
|
If any file is damaged, does not exist, can't be opened, or is not regular,
|
||||||
the final exit status will be @w{> 0}. @option{-lq} can be used to check
|
the final exit status is @w{> 0}. @option{-lq} can be used to check quickly
|
||||||
quickly (without decompressing) the structural integrity of the files
|
(without decompressing) the structural integrity of the files specified.
|
||||||
specified. (Use @option{--test} to check the data integrity). @option{-alq}
|
(Use @option{--test} to check the data integrity). @option{-alq}
|
||||||
additionally checks that none of the files specified contain trailing data.
|
additionally checks that none of the files specified contain trailing data.
|
||||||
|
|
||||||
@item -m
|
@item -m
|
||||||
@itemx --merge
|
@itemx --merge
|
||||||
Try to produce a correct file by merging the good parts of two or more
|
Try to produce a correct file by merging the good parts of two or more
|
||||||
damaged copies. If successful, a repaired copy is written to the file
|
damaged copies. If successful, a repaired copy is written to the file
|
||||||
@samp{@var{file}_fixed.lz}. The exit status is 0 if a correct file could
|
@var{file}_fixed.lz. The exit status is 0 if a correct file could be
|
||||||
be produced, 2 otherwise. @xref{Merging files}, for a complete
|
produced, 2 otherwise. @xref{Merging files}, for a complete description of
|
||||||
description of the merge mode.
|
the merge mode.
|
||||||
|
|
||||||
@item -o @var{file}
|
@item -o @var{file}
|
||||||
@itemx --output=@var{file}
|
@itemx --output=@var{file}
|
||||||
Place the output into @var{file} instead of into @samp{@var{file}_fixed.lz}.
|
Place the repaired output into @var{file} instead of into
|
||||||
If splitting, the names of the files produced are in the form
|
@var{file}_fixed.lz. If splitting, the names of the files produced are in
|
||||||
@samp{rec01@var{file}}, @samp{rec02@var{file}}, etc.
|
the form @samp{rec01@var{file}}, @samp{rec02@var{file}}, etc.
|
||||||
|
|
||||||
If decompressing, or converting lzma-alone files, and @option{-c} has not been
|
If @option{-c} has not been also specified, write the (de)compressed output
|
||||||
also specified, write the decompressed or converted output to @var{file};
|
to @var{file}, automatically creating any missing parent directories; keep
|
||||||
keep input files unchanged. This option (or @option{-c}) is needed when
|
input files unchanged. This option (or @option{-c}) is needed when reading
|
||||||
reading from a named pipe (fifo) or from a device. @w{@samp{-o -}} is
|
from a named pipe (fifo) or from a device. @w{@option{-o -}} is equivalent
|
||||||
equivalent to @option{-c}. @option{-o} has no effect when testing or listing.
|
to @option{-c}. @option{-o} has no effect when testing or listing.
|
||||||
|
|
||||||
@item -q
|
@item -q
|
||||||
@itemx --quiet
|
@itemx --quiet
|
||||||
|
@ -349,9 +349,9 @@ Quiet operation. Suppress all messages.
|
||||||
@itemx --byte-repair
|
@itemx --byte-repair
|
||||||
Try to repair a @var{file} with small errors (up to one single-byte error
|
Try to repair a @var{file} with small errors (up to one single-byte error
|
||||||
per member). If successful, a repaired copy is written to the file
|
per member). If successful, a repaired copy is written to the file
|
||||||
@samp{@var{file}_fixed.lz}. @var{file} is not modified at all. The exit
|
@var{file}_fixed.lz. @var{file} is not modified at all. The exit status is 0
|
||||||
status is 0 if the file could be repaired, 2 otherwise. @xref{Repairing one
|
if the file could be repaired, 2 otherwise. @xref{Repairing one byte}, for a
|
||||||
byte}, for a complete description of the repair mode.
|
complete description of the repair mode.
|
||||||
|
|
||||||
@item -s
|
@item -s
|
||||||
@itemx --split
|
@itemx --split
|
||||||
|
@ -522,17 +522,18 @@ specified, print the frequency of repeated sequences of all possible byte
|
||||||
values. Print cumulative data for all the files, followed by the name of the
|
values. Print cumulative data for all the files, followed by the name of the
|
||||||
first file with the longest sequence.
|
first file with the longest sequence.
|
||||||
|
|
||||||
|
@anchor{--unzcrash}
|
||||||
@item -U 1|B@var{size}
|
@item -U 1|B@var{size}
|
||||||
@itemx --unzcrash=1|B@var{size}
|
@itemx --unzcrash=1|B@var{size}
|
||||||
With argument @samp{1}, test 1-bit errors in the LZMA stream of the
|
With argument @samp{1}, test 1-bit errors in the LZMA stream of the
|
||||||
compressed input @var{file} like the command
|
compressed input @var{file} like the command
|
||||||
@w{@samp{unzcrash -b1 -p7 -s-20 'lzip -t' @var{file}}} but in memory, and
|
@w{@samp{unzcrash -b1 -p7 -s-20 'lzip -t' @var{file}}} but in memory, and
|
||||||
therefore much faster. @xref{Unzcrash}. This option tests all the members
|
therefore much faster (30 to 50 times faster). @xref{Unzcrash}. This option
|
||||||
independently in a multimember file, skipping headers and trailers. If a
|
tests all the members independently in a multimember file, skipping headers
|
||||||
decompression succeeds, the decompressed output is compared with the
|
and trailers. If a decompression succeeds, the decompressed output is
|
||||||
decompressed output of the original @var{file} using MD5 digests. @var{file}
|
compared with the decompressed output of the original @var{file} using MD5
|
||||||
must not contain errors and must decompress correctly for the comparisons to
|
digests. @var{file} must not contain errors and must decompress correctly
|
||||||
work.
|
for the comparisons to work.
|
||||||
|
|
||||||
With argument @samp{B}, test zeroed sectors (blocks of bytes) in the LZMA
|
With argument @samp{B}, test zeroed sectors (blocks of bytes) in the LZMA
|
||||||
stream of the compressed input @var{file} like the command
|
stream of the compressed input @var{file} like the command
|
||||||
|
@ -553,8 +554,8 @@ block for zeroed blocks.
|
||||||
@itemx --debug-decompress=@var{position},@var{value}
|
@itemx --debug-decompress=@var{position},@var{value}
|
||||||
Load the compressed @var{file} into memory, set the byte at @var{position}
|
Load the compressed @var{file} into memory, set the byte at @var{position}
|
||||||
to @var{value}, and decompress the modified compressed data to standard
|
to @var{value}, and decompress the modified compressed data to standard
|
||||||
output. If the damaged member is decompressed fully (just fails with a CRC
|
output. If the damaged member can be decompressed to the end (just fails
|
||||||
mismatch), the members following it are also decompressed.
|
with a CRC mismatch), the members following it are also decompressed.
|
||||||
|
|
||||||
@item -X[@var{position},@var{value}]
|
@item -X[@var{position},@var{value}]
|
||||||
@itemx --show-packets[=@var{position},@var{value}]
|
@itemx --show-packets[=@var{position},@var{value}]
|
||||||
|
@ -603,7 +604,7 @@ Table of SI and binary prefixes (unit multipliers):
|
||||||
|
|
||||||
@sp 1
|
@sp 1
|
||||||
Exit status: 0 for a normal exit, 1 for environmental problems
|
Exit status: 0 for a normal exit, 1 for environmental problems
|
||||||
(file not found, invalid command line options, I/O errors, etc), 2 to
|
(file not found, invalid command-line options, I/O errors, etc), 2 to
|
||||||
indicate a corrupt or invalid input file, 3 for an internal consistency
|
indicate a corrupt or invalid input file, 3 for an internal consistency
|
||||||
error (e.g., bug) which caused lziprecover to panic.
|
error (e.g., bug) which caused lziprecover to panic.
|
||||||
|
|
||||||
|
@ -612,7 +613,7 @@ error (e.g., bug) which caused lziprecover to panic.
|
||||||
@chapter Protecting data from accidental loss
|
@chapter Protecting data from accidental loss
|
||||||
@cindex data safety
|
@cindex data safety
|
||||||
|
|
||||||
It is a fact of life that sometimes data will become corrupt. Software has
|
It is a fact of life that sometimes data becomes corrupt. Software has
|
||||||
errors. Hardware may misbehave or fail. RAM may be struck by a cosmic ray.
|
errors. Hardware may misbehave or fail. RAM may be struck by a cosmic ray.
|
||||||
This is why a safe enough integrity checking is needed in compressed
|
This is why a safe enough integrity checking is needed in compressed
|
||||||
formats, and the reason why a data recovery tool is sometimes needed.
|
formats, and the reason why a data recovery tool is sometimes needed.
|
||||||
|
@ -725,10 +726,10 @@ identical backups (@pxref{performance-of-merge}).
|
||||||
@cindex repairing one byte
|
@cindex repairing one byte
|
||||||
|
|
||||||
Lziprecover can repair perfectly most files with small errors (up to one
|
Lziprecover can repair perfectly most files with small errors (up to one
|
||||||
single-byte error per member), without the need of any extra redundance
|
single-byte error per member), without the need of any extra redundance at
|
||||||
at all. If the reparation is successful, the repaired file will be
|
all. If the reparation is successful, the repaired file is identical bit for
|
||||||
identical bit for bit to the original. This makes lzip files resistant
|
bit to the original. This makes lzip files resistant to bit flip, one of the
|
||||||
to bit flip, one of the most common forms of data corruption.
|
most common forms of data corruption.
|
||||||
|
|
||||||
The file is repaired in memory. Therefore, enough virtual memory
|
The file is repaired in memory. Therefore, enough virtual memory
|
||||||
@w{(RAM + swap)} to contain the largest damaged member is required.
|
@w{(RAM + swap)} to contain the largest damaged member is required.
|
||||||
|
@ -765,23 +766,22 @@ repairs more efficiently the worst errors.
|
||||||
@cindex merging files
|
@cindex merging files
|
||||||
|
|
||||||
If you have several copies of a file but all of them are too damaged to
|
If you have several copies of a file but all of them are too damaged to
|
||||||
repair them (@pxref{Repairing one byte}), lziprecover can try to produce a
|
repair them individually (@pxref{Repairing one byte}), lziprecover can try
|
||||||
correct file by merging the good parts of the damaged copies.
|
to produce a correct file by merging the good parts of the damaged copies.
|
||||||
|
|
||||||
The merge may succeed even if some copies of the file have all the
|
The merge may succeed even if some copies of the file have all the headers
|
||||||
headers and trailers damaged, as long as there is at least one copy of
|
and trailers damaged, as long as there is at least one copy of every header
|
||||||
every header and trailer intact, even if they are in different copies of
|
and trailer intact, even if they are in different copies of the file.
|
||||||
the file.
|
|
||||||
|
|
||||||
The merge will fail if the damaged areas overlap (at least one byte is
|
The merge fails if the damaged areas overlap (at least one byte is damaged
|
||||||
damaged in all copies), or are adjacent and the boundary can't be
|
in all copies), or are adjacent and the boundary can't be determined, or if
|
||||||
determined, or if the copies have too many damaged areas.
|
the copies have too many damaged areas.
|
||||||
|
|
||||||
All the copies to be merged must have the same size. If any of them is
|
All the copies to be merged must have the same size. If any of them is
|
||||||
larger or smaller than it should, either because it has been truncated
|
larger or smaller than it should, either because it has been truncated or
|
||||||
or because it got some garbage data appended at the end, it can be
|
because it got some garbage data appended at the end, it can be brought to
|
||||||
brought to the correct size with the following command before merging it
|
the correct size with the following command before merging it with the other
|
||||||
with the other copies:
|
copies:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
ddrescue -s<correct_size> -x<correct_size> file.lz correct_size_file.lz
|
ddrescue -s<correct_size> -x<correct_size> file.lz correct_size_file.lz
|
||||||
|
@ -1080,7 +1080,7 @@ archiver and the
|
||||||
|
|
||||||
Tarlz creates tar archives using a simplified and safer variant of the POSIX
|
Tarlz creates tar archives using a simplified and safer variant of the POSIX
|
||||||
pax format compressed in lzip format, keeping the alignment between tar
|
pax format compressed in lzip format, keeping the alignment between tar
|
||||||
members and lzip members. The resulting multimember tar.lz archive is fully
|
members and lzip members. The resulting multimember tar.lz archive is
|
||||||
backward compatible with standard tar tools like GNU tar, which treat it
|
backward compatible with standard tar tools like GNU tar, which treat it
|
||||||
like any other tar.lz archive.
|
like any other tar.lz archive.
|
||||||
@ifnothtml
|
@ifnothtml
|
||||||
|
@ -1199,7 +1199,7 @@ represents one byte; a box like this:
|
||||||
represents a variable number of bytes.
|
represents a variable number of bytes.
|
||||||
|
|
||||||
@sp 1
|
@sp 1
|
||||||
A lzip file consists of a series of independent "members" (compressed data
|
A lzip file consists of one or more independent "members" (compressed data
|
||||||
sets). The members simply appear one after another in the file, with no
|
sets). The members simply appear one after another in the file, with no
|
||||||
additional information before, between, or after them. Each member can
|
additional information before, between, or after them. Each member can
|
||||||
encode in compressed form up to @w{16 EiB - 1 byte} of uncompressed data.
|
encode in compressed form up to @w{16 EiB - 1 byte} of uncompressed data.
|
||||||
|
@ -1277,7 +1277,7 @@ padding zero bytes to a lzip file.
|
||||||
Useful data added by the user; an "End Of File" string (to check that the
|
Useful data added by the user; an "End Of File" string (to check that the
|
||||||
file has not been truncated), a cryptographically secure hash, a description
|
file has not been truncated), a cryptographically secure hash, a description
|
||||||
of file contents, etc. It is safe to append any amount of text to a lzip
|
of file contents, etc. It is safe to append any amount of text to a lzip
|
||||||
file as long as none of the first four bytes of the text match the
|
file as long as none of the first four bytes of the text matches the
|
||||||
corresponding byte in the string "LZIP", and the text does not contain any
|
corresponding byte in the string "LZIP", and the text does not contain any
|
||||||
zero bytes (null characters). Nonzero bytes and zero bytes can't be safely
|
zero bytes (null characters). Nonzero bytes and zero bytes can't be safely
|
||||||
mixed in trailing data.
|
mixed in trailing data.
|
||||||
|
@ -1299,7 +1299,7 @@ the noise level. Additionally, the test used by lziprecover to discriminate
|
||||||
trailing data from a corrupt header has a Hamming distance (HD) of 3,
|
trailing data from a corrupt header has a Hamming distance (HD) of 3,
|
||||||
and the 3 bit flips must happen in different magic bytes for the test to
|
and the 3 bit flips must happen in different magic bytes for the test to
|
||||||
fail. In any case, the option @option{--trailing-error} guarantees that
|
fail. In any case, the option @option{--trailing-error} guarantees that
|
||||||
any corrupt header will be detected.
|
any corrupt header is detected.
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
Trailing data are in no way part of the lzip file format, but tools
|
Trailing data are in no way part of the lzip file format, but tools
|
||||||
|
@ -1435,6 +1435,8 @@ lziprecover -tv rec*file.lz
|
||||||
@chapter Testing the robustness of decompressors
|
@chapter Testing the robustness of decompressors
|
||||||
@cindex unzcrash
|
@cindex unzcrash
|
||||||
|
|
||||||
|
@xref{--unzcrash}, for a faster way of testing the robustness of lzip.
|
||||||
|
|
||||||
The lziprecover package also includes unzcrash, a program written to test
|
The lziprecover package also includes unzcrash, a program written to test
|
||||||
robustness to decompression of corrupted data, inspired by unzcrash.c from
|
robustness to decompression of corrupted data, inspired by unzcrash.c from
|
||||||
Julian Seward's bzip2. Type @samp{make unzcrash} in the lziprecover source
|
Julian Seward's bzip2. Type @samp{make unzcrash} in the lziprecover source
|
||||||
|
@ -1462,7 +1464,7 @@ first non-option argument, and then writes the file specified in the second
|
||||||
non-option argument to the standard input of the subprocess, modifying the
|
non-option argument to the standard input of the subprocess, modifying the
|
||||||
corresponding byte each time. Therefore unzcrash can be used to test any
|
corresponding byte each time. Therefore unzcrash can be used to test any
|
||||||
decompressor (not only lzip), or even other decoder programs having a
|
decompressor (not only lzip), or even other decoder programs having a
|
||||||
suitable command line syntax.
|
suitable command-line syntax.
|
||||||
|
|
||||||
If the decompressor returns with zero status, unzcrash compares the output
|
If the decompressor returns with zero status, unzcrash compares the output
|
||||||
of the decompressor for the original and corrupt files. If the outputs
|
of the decompressor for the original and corrupt files. If the outputs
|
||||||
|
@ -1476,9 +1478,8 @@ In order to compare the outputs, unzcrash needs a @samp{zcmp} program able
|
||||||
to understand the format being tested. For example the @samp{zcmp} provided
|
to understand the format being tested. For example the @samp{zcmp} provided
|
||||||
by @uref{http://www.nongnu.org/zutils/manual/zutils_manual.html#Zcmp,,zutils}.
|
by @uref{http://www.nongnu.org/zutils/manual/zutils_manual.html#Zcmp,,zutils}.
|
||||||
If the @samp{zcmp} program used does not understand the format being tested,
|
If the @samp{zcmp} program used does not understand the format being tested,
|
||||||
all the comparisons will fail because the compressed files will be compared
|
all the comparisons fail because the compressed files are compared without
|
||||||
without being decompressed first. Use @option{--zcmp=false} to disable
|
being decompressed first. Use @option{--zcmp=false} to disable comparisons.
|
||||||
comparisons.
|
|
||||||
@ifnothtml
|
@ifnothtml
|
||||||
@xref{Zcmp,,,zutils}.
|
@xref{Zcmp,,,zutils}.
|
||||||
@end ifnothtml
|
@end ifnothtml
|
||||||
|
@ -1535,7 +1536,7 @@ with the option @option{--delta}.
|
||||||
Test one byte, block, or truncation size every @var{n} bytes. If
|
Test one byte, block, or truncation size every @var{n} bytes. If
|
||||||
@option{--delta} is not specified, unzcrash tests all the bytes,
|
@option{--delta} is not specified, unzcrash tests all the bytes,
|
||||||
non-overlapping blocks, or truncation sizes. Values of @var{n} smaller than
|
non-overlapping blocks, or truncation sizes. Values of @var{n} smaller than
|
||||||
the block size will result in overlapping blocks. (Which is convenient for
|
the block size result in overlapping blocks. (Which is convenient for
|
||||||
testing because there are usually too few non-overlapping blocks in a file).
|
testing because there are usually too few non-overlapping blocks in a file).
|
||||||
|
|
||||||
@item -e @var{position},@var{value}
|
@item -e @var{position},@var{value}
|
||||||
|
@ -1588,7 +1589,7 @@ unzcrash and zcmp to use the same decompressor with a command like
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
Exit status: 0 for a normal exit, 1 for environmental problems
|
Exit status: 0 for a normal exit, 1 for environmental problems
|
||||||
(file not found, invalid command line options, I/O errors, etc), 2 to
|
(file not found, invalid command-line options, I/O errors, etc), 2 to
|
||||||
indicate a corrupt or invalid input file, 3 for an internal consistency
|
indicate a corrupt or invalid input file, 3 for an internal consistency
|
||||||
error (e.g., bug) which caused unzcrash to panic.
|
error (e.g., bug) which caused unzcrash to panic.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Lziprecover - Data recovery tool for the lzip format
|
/* Lziprecover - Data recovery tool for the lzip format
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -32,6 +32,9 @@
|
||||||
#include "lzip_index.h"
|
#include "lzip_index.h"
|
||||||
|
|
||||||
|
|
||||||
|
const char * const pdate_msg = "warning: can't preserve file date";
|
||||||
|
|
||||||
|
|
||||||
/* If strip is false, dump to outfd members/gaps/tdata in member_list.
|
/* If strip is false, dump to outfd members/gaps/tdata in member_list.
|
||||||
If strip is true, dump to outfd members/gaps/tdata not in member_list. */
|
If strip is true, dump to outfd members/gaps/tdata not in member_list. */
|
||||||
int dump_members( const std::vector< std::string > & filenames,
|
int dump_members( const std::vector< std::string > & filenames,
|
||||||
|
@ -134,7 +137,7 @@ int dump_members( const std::vector< std::string > & filenames,
|
||||||
else if( trailing_size > 0 ) { stripped_tsize += trailing_size; ++tfiles; }
|
else if( trailing_size > 0 ) { stripped_tsize += trailing_size; ++tfiles; }
|
||||||
close( infd );
|
close( infd );
|
||||||
}
|
}
|
||||||
if( close_outstream( 0 ) != 0 ) set_retval( retval, 1 );
|
if( !close_outstream( 0 ) ) set_retval( retval, 1 );
|
||||||
if( verbosity >= 1 )
|
if( verbosity >= 1 )
|
||||||
{
|
{
|
||||||
if( !strip )
|
if( !strip )
|
||||||
|
@ -275,7 +278,8 @@ int remove_members( const std::vector< std::string > & filenames,
|
||||||
struct utimbuf t;
|
struct utimbuf t;
|
||||||
t.actime = in_stats.st_atime;
|
t.actime = in_stats.st_atime;
|
||||||
t.modtime = in_stats.st_mtime;
|
t.modtime = in_stats.st_mtime;
|
||||||
utime( filename, &t );
|
if( utime( filename, &t ) != 0 && verbosity >= 1 )
|
||||||
|
show_file_error( filename, pdate_msg, errno );
|
||||||
}
|
}
|
||||||
if( verbosity >= 1 )
|
if( verbosity >= 1 )
|
||||||
{
|
{
|
||||||
|
@ -320,7 +324,7 @@ int clear_marking( const std::vector< std::string > & filenames,
|
||||||
uint8_t header_buf[bufsize];
|
uint8_t header_buf[bufsize];
|
||||||
const uint8_t * const p = header_buf; // keep gcc 6.1.0 quiet
|
const uint8_t * const p = header_buf; // keep gcc 6.1.0 quiet
|
||||||
const Lzip_header & header = *(const Lzip_header *)p;
|
const Lzip_header & header = *(const Lzip_header *)p;
|
||||||
uint8_t * const mark = header_buf + Lzip_header::size;
|
uint8_t * const mark = header_buf + header.size;
|
||||||
bool write_attempted = false;
|
bool write_attempted = false;
|
||||||
for( long j = 0; j < lzip_index.members(); ++j ) // clear the members
|
for( long j = 0; j < lzip_index.members(); ++j ) // clear the members
|
||||||
{
|
{
|
||||||
|
@ -333,7 +337,7 @@ int clear_marking( const std::vector< std::string > & filenames,
|
||||||
set_retval( retval, 2 ); break; }
|
set_retval( retval, 2 ); break; }
|
||||||
if( *mark == 0 ) continue;
|
if( *mark == 0 ) continue;
|
||||||
*mark = 0; write_attempted = true;
|
*mark = 0; write_attempted = true;
|
||||||
if( seek_write( fd, mark, 1, mb.pos() + Lzip_header::size ) != 1 )
|
if( seek_write( fd, mark, 1, mb.pos() + header.size ) != 1 )
|
||||||
{ show_file_error( filename, "Error writing to file", errno );
|
{ show_file_error( filename, "Error writing to file", errno );
|
||||||
set_retval( retval, 1 ); break; }
|
set_retval( retval, 1 ); break; }
|
||||||
++cleared_members;
|
++cleared_members;
|
||||||
|
@ -348,7 +352,8 @@ int clear_marking( const std::vector< std::string > & filenames,
|
||||||
struct utimbuf t;
|
struct utimbuf t;
|
||||||
t.actime = in_stats.st_atime;
|
t.actime = in_stats.st_atime;
|
||||||
t.modtime = in_stats.st_mtime;
|
t.modtime = in_stats.st_mtime;
|
||||||
utime( filename, &t );
|
if( utime( filename, &t ) != 0 && verbosity >= 1 )
|
||||||
|
show_file_error( filename, pdate_msg, errno );
|
||||||
++files;
|
++files;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
list.cc
2
list.cc
|
@ -1,5 +1,5 @@
|
||||||
/* Lziprecover - Data recovery tool for the lzip format
|
/* Lziprecover - Data recovery tool for the lzip format
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Lziprecover - Data recovery tool for the lzip format
|
/* Lziprecover - Data recovery tool for the lzip format
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
10
lzip.h
10
lzip.h
|
@ -1,5 +1,5 @@
|
||||||
/* Lziprecover - Data recovery tool for the lzip format
|
/* Lziprecover - Data recovery tool for the lzip format
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -309,7 +309,7 @@ struct Lzip_trailer
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct Cl_options // command line options
|
struct Cl_options // command-line options
|
||||||
{
|
{
|
||||||
bool ignore_empty;
|
bool ignore_empty;
|
||||||
bool ignore_errors;
|
bool ignore_errors;
|
||||||
|
@ -355,7 +355,6 @@ public:
|
||||||
bool overlaps( const long long pos, const long long size ) const
|
bool overlaps( const long long pos, const long long size ) const
|
||||||
{ return pos_ < pos + size && pos < end(); }
|
{ return pos_ < pos + size && pos < end(); }
|
||||||
|
|
||||||
void shift( Block & b ) { ++size_; ++b.pos_; --b.size_; }
|
|
||||||
Block split( const long long pos );
|
Block split( const long long pos );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -479,12 +478,13 @@ int open_instream( const char * const name, struct stat * const in_statsp,
|
||||||
int open_truncable_stream( const char * const name,
|
int open_truncable_stream( const char * const name,
|
||||||
struct stat * const in_statsp );
|
struct stat * const in_statsp );
|
||||||
bool open_outstream( const bool force, const bool protect,
|
bool open_outstream( const bool force, const bool protect,
|
||||||
const bool rw = false, const bool skipping = true );
|
const bool rw = false, const bool skipping = true,
|
||||||
|
const bool to_file = false );
|
||||||
bool output_file_exists();
|
bool output_file_exists();
|
||||||
void cleanup_and_fail( const int retval );
|
void cleanup_and_fail( const int retval );
|
||||||
bool check_tty_out();
|
bool check_tty_out();
|
||||||
void set_signal_handler();
|
void set_signal_handler();
|
||||||
int close_outstream( const struct stat * const in_statsp );
|
bool close_outstream( const struct stat * const in_statsp );
|
||||||
std::string insert_fixed( std::string name );
|
std::string insert_fixed( std::string name );
|
||||||
void show_2file_error( const char * const msg1, const char * const name1,
|
void show_2file_error( const char * const msg1, const char * const name1,
|
||||||
const char * const name2, const char * const msg2 );
|
const char * const name2, const char * const msg2 );
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Lziprecover - Data recovery tool for the lzip format
|
/* Lziprecover - Data recovery tool for the lzip format
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -39,17 +39,16 @@ int seek_read( const int fd, uint8_t * const buf, const int size,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Lzip_index::check_header_error( const Lzip_header & header,
|
bool Lzip_index::check_header( const Lzip_header & header,
|
||||||
const bool first, const bool ignore_bad_ds )
|
const bool ignore_bad_ds )
|
||||||
{
|
{
|
||||||
if( !header.check_magic() )
|
if( !header.check_magic() )
|
||||||
{ error_ = bad_magic_msg; retval_ = 2; if( first ) bad_magic_ = true;
|
{ error_ = bad_magic_msg; retval_ = 2; return false; }
|
||||||
return true; }
|
|
||||||
if( !header.check_version() )
|
if( !header.check_version() )
|
||||||
{ error_ = bad_version( header.version() ); retval_ = 2; return true; }
|
{ error_ = bad_version( header.version() ); retval_ = 2; return false; }
|
||||||
if( !ignore_bad_ds && !isvalid_ds( header.dictionary_size() ) )
|
if( !ignore_bad_ds && !isvalid_ds( header.dictionary_size() ) )
|
||||||
{ error_ = bad_dict_msg; retval_ = 2; return true; }
|
{ error_ = bad_dict_msg; retval_ = 2; return false; }
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lzip_index::set_errno_error( const char * const msg )
|
void Lzip_index::set_errno_error( const char * const msg )
|
||||||
|
@ -70,7 +69,7 @@ void Lzip_index::set_num_error( const char * const msg, unsigned long long num )
|
||||||
bool Lzip_index::read_header( const int fd, Lzip_header & header,
|
bool Lzip_index::read_header( const int fd, Lzip_header & header,
|
||||||
const long long pos, const bool ignore_marking )
|
const long long pos, const bool ignore_marking )
|
||||||
{
|
{
|
||||||
if( seek_read( fd, header.data, Lzip_header::size, pos ) != Lzip_header::size )
|
if( seek_read( fd, header.data, header.size, pos ) != header.size )
|
||||||
{ set_errno_error( "Error reading member header: " ); return false; }
|
{ set_errno_error( "Error reading member header: " ); return false; }
|
||||||
uint8_t byte;
|
uint8_t byte;
|
||||||
if( !ignore_marking && readblock( fd, &byte, 1 ) == 1 && byte != 0 )
|
if( !ignore_marking && readblock( fd, &byte, 1 ) == 1 && byte != 0 )
|
||||||
|
@ -81,8 +80,8 @@ bool Lzip_index::read_header( const int fd, Lzip_header & header,
|
||||||
bool Lzip_index::read_trailer( const int fd, Lzip_trailer & trailer,
|
bool Lzip_index::read_trailer( const int fd, Lzip_trailer & trailer,
|
||||||
const long long pos )
|
const long long pos )
|
||||||
{
|
{
|
||||||
if( seek_read( fd, trailer.data, Lzip_trailer::size,
|
if( seek_read( fd, trailer.data, trailer.size, pos - trailer.size ) !=
|
||||||
pos - Lzip_trailer::size ) != Lzip_trailer::size )
|
trailer.size )
|
||||||
{ set_errno_error( "Error reading member trailer: " ); return false; }
|
{ set_errno_error( "Error reading member trailer: " ); return false; }
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -118,24 +117,23 @@ bool Lzip_index::skip_gap( const int fd, unsigned long long & pos,
|
||||||
if( buffer[i-1] <= max_msb ) // most significant byte of member_size
|
if( buffer[i-1] <= max_msb ) // most significant byte of member_size
|
||||||
{
|
{
|
||||||
const Lzip_trailer & trailer =
|
const Lzip_trailer & trailer =
|
||||||
*(const Lzip_trailer *)( buffer + i - Lzip_trailer::size );
|
*(const Lzip_trailer *)( buffer + i - trailer.size );
|
||||||
const unsigned long long member_size = trailer.member_size();
|
const unsigned long long member_size = trailer.member_size();
|
||||||
if( member_size == 0 ) // skip trailing zeros
|
if( member_size == 0 ) // skip trailing zeros
|
||||||
{ while( i > Lzip_trailer::size && buffer[i-9] == 0 ) --i; continue; }
|
{ while( i > trailer.size && buffer[i-9] == 0 ) --i; continue; }
|
||||||
if( member_size > ipos + i || !trailer.check_consistency() )
|
if( member_size > ipos + i || !trailer.check_consistency() ) continue;
|
||||||
continue;
|
|
||||||
Lzip_header header;
|
Lzip_header header;
|
||||||
if( !read_header( fd, header, ipos + i - member_size,
|
if( !read_header( fd, header, ipos + i - member_size,
|
||||||
cl_opts.ignore_marking ) ) return false;
|
cl_opts.ignore_marking ) ) return false;
|
||||||
if( !header.check( ignore_bad_ds ) ) continue;
|
if( !header.check( ignore_bad_ds ) ) continue;
|
||||||
const Lzip_header & header2 = *(const Lzip_header *)( buffer + i );
|
const Lzip_header & header2 = *(const Lzip_header *)( buffer + i );
|
||||||
const bool full_h2 = bsize - i >= Lzip_header::size;
|
const bool full_h2 = bsize - i >= header.size;
|
||||||
if( header2.check_prefix( bsize - i ) ) // next header
|
if( header2.check_prefix( bsize - i ) ) // next header
|
||||||
{
|
{
|
||||||
if( !ignore_gaps && member_vector.empty() ) // last member
|
if( !ignore_gaps && member_vector.empty() ) // last member
|
||||||
{
|
{
|
||||||
if( !full_h2 ) error_ = "Last member in input file is truncated.";
|
if( !full_h2 ) error_ = "Last member in input file is truncated.";
|
||||||
else if( !check_header_error( header2, false, ignore_bad_ds ) )
|
else if( check_header( header2, ignore_bad_ds ) )
|
||||||
error_ = "Last member in input file is truncated or corrupt.";
|
error_ = "Last member in input file is truncated or corrupt.";
|
||||||
retval_ = 2; return false;
|
retval_ = 2; return false;
|
||||||
}
|
}
|
||||||
|
@ -154,15 +152,15 @@ bool Lzip_index::skip_gap( const int fd, unsigned long long & pos,
|
||||||
if( !cl_opts.ignore_trailing )
|
if( !cl_opts.ignore_trailing )
|
||||||
{ error_ = trailing_msg; retval_ = 2; return false; }
|
{ error_ = trailing_msg; retval_ = 2; return false; }
|
||||||
}
|
}
|
||||||
pos = ipos + i - member_size;
|
|
||||||
const unsigned long long data_size = trailer.data_size();
|
const unsigned long long data_size = trailer.data_size();
|
||||||
if( !cl_opts.ignore_empty && data_size == 0 )
|
if( !cl_opts.ignore_empty && data_size == 0 )
|
||||||
{ error_ = empty_msg; retval_ = 2; return false; }
|
{ error_ = empty_msg; retval_ = 2; return false; }
|
||||||
|
pos = ipos + i - member_size; // good member
|
||||||
const unsigned dictionary_size = header.dictionary_size();
|
const unsigned dictionary_size = header.dictionary_size();
|
||||||
member_vector.push_back( Member( 0, data_size, pos, member_size,
|
|
||||||
dictionary_size ) );
|
|
||||||
if( dictionary_size_ < dictionary_size )
|
if( dictionary_size_ < dictionary_size )
|
||||||
dictionary_size_ = dictionary_size;
|
dictionary_size_ = dictionary_size;
|
||||||
|
member_vector.push_back( Member( 0, data_size, pos, member_size,
|
||||||
|
dictionary_size ) );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if( ipos == 0 )
|
if( ipos == 0 )
|
||||||
|
@ -190,8 +188,7 @@ bool Lzip_index::skip_gap( const int fd, unsigned long long & pos,
|
||||||
Lzip_index::Lzip_index( const int infd, const Cl_options & cl_opts,
|
Lzip_index::Lzip_index( const int infd, const Cl_options & cl_opts,
|
||||||
const bool ignore_bad_ds, const bool ignore_gaps,
|
const bool ignore_bad_ds, const bool ignore_gaps,
|
||||||
const long long max_pos )
|
const long long max_pos )
|
||||||
: insize( lseek( infd, 0, SEEK_END ) ), retval_( 0 ),
|
: insize( lseek( infd, 0, SEEK_END ) ), retval_( 0 ), dictionary_size_( 0 )
|
||||||
dictionary_size_( 0 ), bad_magic_( false )
|
|
||||||
{
|
{
|
||||||
if( insize < 0 )
|
if( insize < 0 )
|
||||||
{ set_errno_error( "Input file is not seekable: " ); return; }
|
{ set_errno_error( "Input file is not seekable: " ); return; }
|
||||||
|
@ -202,8 +199,8 @@ Lzip_index::Lzip_index( const int infd, const Cl_options & cl_opts,
|
||||||
retval_ = 2; return; }
|
retval_ = 2; return; }
|
||||||
|
|
||||||
Lzip_header header;
|
Lzip_header header;
|
||||||
if( !read_header( infd, header, 0, cl_opts.ignore_marking ) ) return;
|
if( !read_header( infd, header, 0, cl_opts.ignore_marking ) ||
|
||||||
if( check_header_error( header, true, ignore_bad_ds ) ) return;
|
!check_header( header, ignore_bad_ds ) ) return;
|
||||||
|
|
||||||
// pos always points to a header or to ( EOF || max_pos )
|
// pos always points to a header or to ( EOF || max_pos )
|
||||||
unsigned long long pos = ( max_pos > 0 ) ? max_pos : insize;
|
unsigned long long pos = ( max_pos > 0 ) ? max_pos : insize;
|
||||||
|
@ -220,8 +217,7 @@ Lzip_index::Lzip_index( const int infd, const Cl_options & cl_opts,
|
||||||
if( ignore_gaps || member_vector.empty() )
|
if( ignore_gaps || member_vector.empty() )
|
||||||
{ if( skip_gap( infd, pos, cl_opts, ignore_bad_ds, ignore_gaps ) )
|
{ if( skip_gap( infd, pos, cl_opts, ignore_bad_ds, ignore_gaps ) )
|
||||||
continue; else return; }
|
continue; else return; }
|
||||||
set_num_error( "Bad trailer at pos ", pos - Lzip_trailer::size );
|
set_num_error( "Bad trailer at pos ", pos - trailer.size ); break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if( !read_header( infd, header, pos - member_size, cl_opts.ignore_marking ) )
|
if( !read_header( infd, header, pos - member_size, cl_opts.ignore_marking ) )
|
||||||
break;
|
break;
|
||||||
|
@ -230,18 +226,17 @@ Lzip_index::Lzip_index( const int infd, const Cl_options & cl_opts,
|
||||||
if( ignore_gaps || member_vector.empty() )
|
if( ignore_gaps || member_vector.empty() )
|
||||||
{ if( skip_gap( infd, pos, cl_opts, ignore_bad_ds, ignore_gaps ) )
|
{ if( skip_gap( infd, pos, cl_opts, ignore_bad_ds, ignore_gaps ) )
|
||||||
continue; else return; }
|
continue; else return; }
|
||||||
set_num_error( "Bad header at pos ", pos - member_size );
|
set_num_error( "Bad header at pos ", pos - member_size ); break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
pos -= member_size;
|
|
||||||
const unsigned long long data_size = trailer.data_size();
|
const unsigned long long data_size = trailer.data_size();
|
||||||
if( !cl_opts.ignore_empty && data_size == 0 )
|
if( !cl_opts.ignore_empty && data_size == 0 )
|
||||||
{ error_ = empty_msg; retval_ = 2; break; }
|
{ error_ = empty_msg; retval_ = 2; break; }
|
||||||
|
pos -= member_size; // good member
|
||||||
const unsigned dictionary_size = header.dictionary_size();
|
const unsigned dictionary_size = header.dictionary_size();
|
||||||
member_vector.push_back( Member( 0, data_size, pos, member_size,
|
|
||||||
dictionary_size ) );
|
|
||||||
if( dictionary_size_ < dictionary_size )
|
if( dictionary_size_ < dictionary_size )
|
||||||
dictionary_size_ = dictionary_size;
|
dictionary_size_ = dictionary_size;
|
||||||
|
member_vector.push_back( Member( 0, data_size, pos, member_size,
|
||||||
|
dictionary_size ) );
|
||||||
}
|
}
|
||||||
// block at pos == 0 must be a member unless shorter than min_member_size
|
// block at pos == 0 must be a member unless shorter than min_member_size
|
||||||
if( pos >= min_member_size || ( pos != 0 && !ignore_gaps ) ||
|
if( pos >= min_member_size || ( pos != 0 && !ignore_gaps ) ||
|
||||||
|
@ -272,8 +267,7 @@ Lzip_index::Lzip_index( const int infd, const Cl_options & cl_opts,
|
||||||
// All files in 'infd_vector' must be at least 'fsize' bytes long.
|
// All files in 'infd_vector' must be at least 'fsize' bytes long.
|
||||||
Lzip_index::Lzip_index( const std::vector< int > & infd_vector,
|
Lzip_index::Lzip_index( const std::vector< int > & infd_vector,
|
||||||
const long long fsize )
|
const long long fsize )
|
||||||
: insize( fsize ), retval_( 0 ),
|
: insize( fsize ), retval_( 0 ), dictionary_size_( 0 ) // DS not used
|
||||||
dictionary_size_( 0 ), bad_magic_( false ) // DS not used
|
|
||||||
{
|
{
|
||||||
if( insize < 0 )
|
if( insize < 0 )
|
||||||
{ set_errno_error( "Input file is not seekable: " ); return; }
|
{ set_errno_error( "Input file is not seekable: " ); return; }
|
||||||
|
@ -322,7 +316,7 @@ Lzip_index::Lzip_index( const std::vector< int > & infd_vector,
|
||||||
}
|
}
|
||||||
if( member_vector.empty() && insize > pos )
|
if( member_vector.empty() && insize > pos )
|
||||||
{
|
{
|
||||||
const int size = std::min( (long long)Lzip_header::size, insize - pos );
|
const int size = std::min( (long long)header.size, insize - pos );
|
||||||
for( int i = 0; i < files; ++i )
|
for( int i = 0; i < files; ++i )
|
||||||
{
|
{
|
||||||
const int infd = infd_vector[i];
|
const int infd = infd_vector[i];
|
||||||
|
@ -339,7 +333,7 @@ Lzip_index::Lzip_index( const std::vector< int > & infd_vector,
|
||||||
member_size, 0 ) );
|
member_size, 0 ) );
|
||||||
}
|
}
|
||||||
error:
|
error:
|
||||||
if( pos != 0 || member_vector.empty() )
|
if( pos != 0 || member_vector.empty() || retval_ != 0 )
|
||||||
{
|
{
|
||||||
member_vector.clear();
|
member_vector.clear();
|
||||||
if( retval_ == 0 ) { error_ = "Can't create file index."; retval_ = 2; }
|
if( retval_ == 0 ) { error_ = "Can't create file index."; retval_ = 2; }
|
||||||
|
|
10
lzip_index.h
10
lzip_index.h
|
@ -1,5 +1,5 @@
|
||||||
/* Lziprecover - Data recovery tool for the lzip format
|
/* Lziprecover - Data recovery tool for the lzip format
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -39,10 +39,8 @@ class Lzip_index
|
||||||
long long insize;
|
long long insize;
|
||||||
int retval_;
|
int retval_;
|
||||||
unsigned dictionary_size_; // largest dictionary size in the file
|
unsigned dictionary_size_; // largest dictionary size in the file
|
||||||
bool bad_magic_; // bad magic in first header
|
|
||||||
|
|
||||||
bool check_header_error( const Lzip_header & header, const bool first,
|
bool check_header( const Lzip_header & header, const bool ignore_bad_ds );
|
||||||
const bool ignore_bad_ds );
|
|
||||||
void set_errno_error( const char * const msg );
|
void set_errno_error( const char * const msg );
|
||||||
void set_num_error( const char * const msg, unsigned long long num );
|
void set_num_error( const char * const msg, unsigned long long num );
|
||||||
bool read_header( const int fd, Lzip_header & header, const long long pos,
|
bool read_header( const int fd, Lzip_header & header, const long long pos,
|
||||||
|
@ -55,8 +53,7 @@ class Lzip_index
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Lzip_index()
|
Lzip_index()
|
||||||
: error_( "No index" ), insize( 0 ), retval_( 2 ),
|
: error_( "No index" ), insize( 0 ), retval_( 2 ), dictionary_size_( 0 ) {}
|
||||||
dictionary_size_( 0 ), bad_magic_( false ) {}
|
|
||||||
Lzip_index( const int infd, const Cl_options & cl_opts,
|
Lzip_index( const int infd, const Cl_options & cl_opts,
|
||||||
const bool ignore_bad_ds = false, const bool ignore_gaps = false,
|
const bool ignore_bad_ds = false, const bool ignore_gaps = false,
|
||||||
const long long max_pos = 0 );
|
const long long max_pos = 0 );
|
||||||
|
@ -67,7 +64,6 @@ public:
|
||||||
const std::string & error() const { return error_; }
|
const std::string & error() const { return error_; }
|
||||||
int retval() const { return retval_; }
|
int retval() const { return retval_; }
|
||||||
unsigned dictionary_size() const { return dictionary_size_; }
|
unsigned dictionary_size() const { return dictionary_size_; }
|
||||||
bool bad_magic() const { return bad_magic_; }
|
|
||||||
|
|
||||||
bool operator==( const Lzip_index & li ) const
|
bool operator==( const Lzip_index & li ) const
|
||||||
{
|
{
|
||||||
|
|
137
main.cc
137
main.cc
|
@ -1,5 +1,5 @@
|
||||||
/* Lziprecover - Data recovery tool for the lzip format
|
/* Lziprecover - Data recovery tool for the lzip format
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
Exit status: 0 for a normal exit, 1 for environmental problems
|
Exit status: 0 for a normal exit, 1 for environmental problems
|
||||||
(file not found, invalid command line options, I/O errors, etc), 2 to
|
(file not found, invalid command-line options, I/O errors, etc), 2 to
|
||||||
indicate a corrupt or invalid input file, 3 for an internal consistency
|
indicate a corrupt or invalid input file, 3 for an internal consistency
|
||||||
error (e.g., bug) which caused lziprecover to panic.
|
error (e.g., bug) which caused lziprecover to panic.
|
||||||
*/
|
*/
|
||||||
|
@ -76,7 +76,7 @@
|
||||||
#error "Environments where 'size_t' is narrower than 'long' are not supported."
|
#error "Environments where 'size_t' is narrower than 'long' are not supported."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool fits_in_size_t( const unsigned long long size )
|
bool fits_in_size_t( const unsigned long long size ) // fits also in long
|
||||||
{ return ( sizeof (long) <= sizeof (size_t) && size <= LONG_MAX ) ||
|
{ return ( sizeof (long) <= sizeof (size_t) && size <= LONG_MAX ) ||
|
||||||
( sizeof (int) <= sizeof (size_t) && size <= INT_MAX ); }
|
( sizeof (int) <= sizeof (size_t) && size <= INT_MAX ); }
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ void show_help()
|
||||||
" -i, --ignore-errors ignore some errors in -d, -D, -l, -t, --dump\n"
|
" -i, --ignore-errors ignore some errors in -d, -D, -l, -t, --dump\n"
|
||||||
" -k, --keep keep (don't delete) input files\n"
|
" -k, --keep keep (don't delete) input files\n"
|
||||||
" -l, --list print (un)compressed file sizes\n"
|
" -l, --list print (un)compressed file sizes\n"
|
||||||
" -m, --merge correct errors in file using several copies\n"
|
" -m, --merge repair errors in file using several copies\n"
|
||||||
" -o, --output=<file> place the output into <file>\n"
|
" -o, --output=<file> place the output into <file>\n"
|
||||||
" -q, --quiet suppress all messages\n"
|
" -q, --quiet suppress all messages\n"
|
||||||
" -R, --byte-repair try to repair a corrupt byte in file\n"
|
" -R, --byte-repair try to repair a corrupt byte in file\n"
|
||||||
|
@ -174,7 +174,7 @@ void show_help()
|
||||||
"\nTo extract all the files from archive 'foo.tar.lz', use the commands\n"
|
"\nTo extract all the files from archive 'foo.tar.lz', use the commands\n"
|
||||||
"'tar -xf foo.tar.lz' or 'lziprecover -cd foo.tar.lz | tar -xf -'.\n"
|
"'tar -xf foo.tar.lz' or 'lziprecover -cd foo.tar.lz | tar -xf -'.\n"
|
||||||
"\nExit status: 0 for a normal exit, 1 for environmental problems\n"
|
"\nExit status: 0 for a normal exit, 1 for environmental problems\n"
|
||||||
"(file not found, invalid command line options, I/O errors, etc), 2 to\n"
|
"(file not found, invalid command-line options, I/O errors, etc), 2 to\n"
|
||||||
"indicate a corrupt or invalid input file, 3 for an internal consistency\n"
|
"indicate a corrupt or invalid input file, 3 for an internal consistency\n"
|
||||||
"error (e.g., bug) which caused lziprecover to panic.\n"
|
"error (e.g., bug) which caused lziprecover to panic.\n"
|
||||||
"\nReport bugs to lzip-bug@nongnu.org\n"
|
"\nReport bugs to lzip-bug@nongnu.org\n"
|
||||||
|
@ -207,15 +207,15 @@ const char * bad_version( const unsigned version )
|
||||||
|
|
||||||
const char * format_ds( const unsigned dictionary_size )
|
const char * format_ds( const unsigned dictionary_size )
|
||||||
{
|
{
|
||||||
enum { bufsize = 16, factor = 1024 };
|
enum { bufsize = 16, factor = 1024, n = 3 };
|
||||||
static char buf[bufsize];
|
static char buf[bufsize];
|
||||||
const char * const prefix[3] = { "Ki", "Mi", "Gi" };
|
const char * const prefix[n] = { "Ki", "Mi", "Gi" };
|
||||||
const char * p = "";
|
const char * p = "";
|
||||||
const char * np = " ";
|
const char * np = " ";
|
||||||
unsigned num = dictionary_size;
|
unsigned num = dictionary_size;
|
||||||
bool exact = ( num % factor == 0 );
|
bool exact = ( num % factor == 0 );
|
||||||
|
|
||||||
for( int i = 0; i < 3 && ( num > 9999 || ( exact && num >= factor ) ); ++i )
|
for( int i = 0; i < n && ( 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 = ""; }
|
||||||
snprintf( buf, bufsize, "%s%4u %sB", np, num, p );
|
snprintf( buf, bufsize, "%s%4u %sB", np, num, p );
|
||||||
|
@ -280,7 +280,6 @@ next:
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Recognized formats: <digit> 'a' m[<match_length>]
|
// Recognized formats: <digit> 'a' m[<match_length>]
|
||||||
//
|
|
||||||
int parse_lzip_level( const char * const arg, const char * const option_name )
|
int parse_lzip_level( const char * const arg, const char * const option_name )
|
||||||
{
|
{
|
||||||
if( *arg == 'a' || std::isdigit( *(const unsigned char *)arg ) ) return *arg;
|
if( *arg == 'a' || std::isdigit( *(const unsigned char *)arg ) ) return *arg;
|
||||||
|
@ -408,7 +407,7 @@ void set_d_outname( const std::string & name, const int eindex )
|
||||||
}
|
}
|
||||||
output_filename = name; output_filename += ".out";
|
output_filename = name; output_filename += ".out";
|
||||||
if( verbosity >= 1 )
|
if( verbosity >= 1 )
|
||||||
std::fprintf( stderr, "%s: Can't guess original name for '%s' -- using '%s'\n",
|
std::fprintf( stderr, "%s: %s: Can't guess original name -- using '%s'\n",
|
||||||
program_name, name.c_str(), output_filename.c_str() );
|
program_name, name.c_str(), output_filename.c_str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,9 +429,9 @@ int open_instream( const char * const name, struct stat * const in_statsp,
|
||||||
if( i != 0 || ( !S_ISREG( mode ) && ( !can_read || one_to_one ) ) )
|
if( i != 0 || ( !S_ISREG( mode ) && ( !can_read || one_to_one ) ) )
|
||||||
{
|
{
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
std::fprintf( stderr, "%s: Input file '%s' is not a regular file%s.\n",
|
std::fprintf( stderr, "%s: %s: Input file is not a regular file%s.\n",
|
||||||
program_name, name, ( can_read && one_to_one ) ?
|
program_name, name, ( can_read && one_to_one ) ?
|
||||||
",\n and neither '-c' nor '-o' were specified" : "" );
|
",\n and neither '-c' nor '-o' were specified" : "" );
|
||||||
close( infd );
|
close( infd );
|
||||||
infd = -1;
|
infd = -1;
|
||||||
}
|
}
|
||||||
|
@ -457,9 +456,41 @@ int open_truncable_stream( const char * const name,
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool make_dirs( const std::string & name )
|
||||||
|
{
|
||||||
|
int i = name.size();
|
||||||
|
while( i > 0 && name[i-1] != '/' ) --i; // remove last component
|
||||||
|
while( i > 0 && name[i-1] == '/' ) --i; // remove slash(es)
|
||||||
|
const int dirsize = i; // size of dirname without trailing slash(es)
|
||||||
|
|
||||||
|
for( i = 0; i < dirsize; ) // if dirsize == 0, dirname is '/' or empty
|
||||||
|
{
|
||||||
|
while( i < dirsize && name[i] == '/' ) ++i;
|
||||||
|
const int first = i;
|
||||||
|
while( i < dirsize && name[i] != '/' ) ++i;
|
||||||
|
if( first < i )
|
||||||
|
{
|
||||||
|
const std::string partial( name, 0, i );
|
||||||
|
const mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
|
||||||
|
struct stat st;
|
||||||
|
if( stat( partial.c_str(), &st ) == 0 )
|
||||||
|
{ if( !S_ISDIR( st.st_mode ) ) { errno = ENOTDIR; return false; } }
|
||||||
|
else if( mkdir( partial.c_str(), mode ) != 0 && errno != EEXIST )
|
||||||
|
return false; // if EEXIST, another process created the dir
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * const force_msg =
|
||||||
|
"Output file already exists. Use '--force' to overwrite it.";
|
||||||
|
|
||||||
|
} // end namespace
|
||||||
|
|
||||||
bool open_outstream( const bool force, const bool protect,
|
bool open_outstream( const bool force, const bool protect,
|
||||||
const bool rw, const bool skipping )
|
const bool rw, const bool skipping, const bool to_file )
|
||||||
{
|
{
|
||||||
const mode_t usr_rw = S_IRUSR | S_IWUSR;
|
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 all_rw = usr_rw | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
|
||||||
|
@ -467,19 +498,21 @@ bool open_outstream( const bool force, const bool protect,
|
||||||
int flags = O_CREAT | ( rw ? O_RDWR : O_WRONLY ) | O_BINARY;
|
int flags = O_CREAT | ( rw ? O_RDWR : 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.c_str(), flags, outfd_mode );
|
outfd = -1;
|
||||||
if( outfd >= 0 ) delete_output_on_interrupt = true;
|
if( output_filename.size() &&
|
||||||
else if( verbosity >= 0 )
|
output_filename[output_filename.size()-1] == '/' ) errno = EISDIR;
|
||||||
{
|
else {
|
||||||
|
if( ( !protect || to_file ) && !make_dirs( output_filename ) )
|
||||||
|
{ show_file_error( output_filename.c_str(),
|
||||||
|
"Error creating intermediate directory", errno ); return false; }
|
||||||
|
outfd = open( output_filename.c_str(), flags, outfd_mode );
|
||||||
|
if( outfd >= 0 ) { delete_output_on_interrupt = true; return true; }
|
||||||
if( errno == EEXIST )
|
if( errno == EEXIST )
|
||||||
std::fprintf( stderr, "%s: Output file '%s' already exists%s.\n",
|
{ show_file_error( output_filename.c_str(), skipping ?
|
||||||
program_name, output_filename.c_str(), skipping ?
|
"Output file already exists, skipping." : force_msg ); return false; }
|
||||||
", skipping" : ". Use '--force' to overwrite it" );
|
|
||||||
else
|
|
||||||
std::fprintf( stderr, "%s: Can't create output file '%s': %s\n",
|
|
||||||
program_name, output_filename.c_str(), std::strerror( errno ) );
|
|
||||||
}
|
}
|
||||||
return ( outfd >= 0 );
|
show_file_error( output_filename.c_str(), "Can't create output file", errno );
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -487,13 +520,7 @@ bool output_file_exists()
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if( stat( output_filename.c_str(), &st ) == 0 )
|
if( stat( output_filename.c_str(), &st ) == 0 )
|
||||||
{
|
{ show_file_error( output_filename.c_str(), force_msg ); return true; }
|
||||||
if( verbosity >= 0 )
|
|
||||||
std::fprintf( stderr, "%s: Output file '%s' already exists."
|
|
||||||
" Use '--force' to overwrite it.\n",
|
|
||||||
program_name, output_filename.c_str() );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,12 +539,11 @@ void cleanup_and_fail( const int retval )
|
||||||
if( delete_output_on_interrupt )
|
if( delete_output_on_interrupt )
|
||||||
{
|
{
|
||||||
delete_output_on_interrupt = false;
|
delete_output_on_interrupt = false;
|
||||||
if( verbosity >= 0 )
|
show_file_error( output_filename.c_str(),
|
||||||
std::fprintf( stderr, "%s: Deleting output file '%s', if it exists.\n",
|
"Deleting output file, if it exists." );
|
||||||
program_name, output_filename.c_str() );
|
|
||||||
if( outfd >= 0 ) { close( outfd ); outfd = -1; }
|
if( outfd >= 0 ) { close( outfd ); outfd = -1; }
|
||||||
if( std::remove( output_filename.c_str() ) != 0 && errno != ENOENT )
|
if( std::remove( output_filename.c_str() ) != 0 && errno != ENOENT )
|
||||||
show_error( "WARNING: deletion of output file (apparently) failed." );
|
show_error( "warning: deletion of output file failed", errno );
|
||||||
}
|
}
|
||||||
std::exit( retval );
|
std::exit( retval );
|
||||||
}
|
}
|
||||||
|
@ -565,7 +591,7 @@ void close_and_set_permissions( const struct stat * const in_statsp )
|
||||||
if( in_statsp )
|
if( in_statsp )
|
||||||
{
|
{
|
||||||
const mode_t mode = in_statsp->st_mode;
|
const mode_t mode = in_statsp->st_mode;
|
||||||
// fchown will in many cases return with EPERM, which can be safely ignored.
|
// fchown in many cases returns with EPERM, which can be safely ignored.
|
||||||
if( fchown( outfd, in_statsp->st_uid, in_statsp->st_gid ) == 0 )
|
if( fchown( outfd, in_statsp->st_uid, in_statsp->st_gid ) == 0 )
|
||||||
{ if( fchmod( outfd, mode ) != 0 ) warning = true; }
|
{ if( fchmod( outfd, mode ) != 0 ) warning = true; }
|
||||||
else
|
else
|
||||||
|
@ -574,10 +600,8 @@ void close_and_set_permissions( const struct stat * const in_statsp )
|
||||||
warning = true;
|
warning = true;
|
||||||
}
|
}
|
||||||
if( close( outfd ) != 0 )
|
if( close( outfd ) != 0 )
|
||||||
{
|
{ show_file_error( output_filename.c_str(), "Error closing output file",
|
||||||
show_error( "Error closing output file", errno );
|
errno ); cleanup_and_fail( 1 ); }
|
||||||
cleanup_and_fail( 1 );
|
|
||||||
}
|
|
||||||
outfd = -1;
|
outfd = -1;
|
||||||
delete_output_on_interrupt = false;
|
delete_output_on_interrupt = false;
|
||||||
if( in_statsp )
|
if( in_statsp )
|
||||||
|
@ -588,7 +612,8 @@ void close_and_set_permissions( const struct stat * const in_statsp )
|
||||||
if( utime( output_filename.c_str(), &t ) != 0 ) warning = true;
|
if( utime( output_filename.c_str(), &t ) != 0 ) warning = true;
|
||||||
}
|
}
|
||||||
if( warning && verbosity >= 1 )
|
if( warning && verbosity >= 1 )
|
||||||
show_error( "Can't change output file attributes." );
|
show_file_error( output_filename.c_str(),
|
||||||
|
"warning: can't change output file attributes", errno );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -622,7 +647,7 @@ bool show_trailing_data( const uint8_t * const data, const int size,
|
||||||
pp( msg.c_str() );
|
pp( msg.c_str() );
|
||||||
if( ignore_trailing == 0 ) show_file_error( pp.name(), trailing_msg );
|
if( ignore_trailing == 0 ) show_file_error( pp.name(), trailing_msg );
|
||||||
}
|
}
|
||||||
return ( ignore_trailing > 0 );
|
return ignore_trailing > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -640,7 +665,7 @@ int decompress( const unsigned long long cfile_size, const int infd,
|
||||||
rdec.reset_member_position();
|
rdec.reset_member_position();
|
||||||
const int size = rdec.read_header_carefully( header, cl_opts.ignore_errors );
|
const int size = rdec.read_header_carefully( header, cl_opts.ignore_errors );
|
||||||
if( rdec.finished() || // End Of File
|
if( rdec.finished() || // End Of File
|
||||||
( size < Lzip_header::size && !rdec.find_header( header ) ) )
|
( size < header.size && !rdec.find_header( header ) ) )
|
||||||
{
|
{
|
||||||
if( first_member )
|
if( first_member )
|
||||||
{ show_file_error( pp.name(), "File ends unexpectedly at member header." );
|
{ show_file_error( pp.name(), "File ends unexpectedly at member header." );
|
||||||
|
@ -675,8 +700,7 @@ int decompress( const unsigned long long cfile_size, const int infd,
|
||||||
|
|
||||||
LZ_decoder decoder( rdec, dictionary_size, outfd );
|
LZ_decoder decoder( rdec, dictionary_size, outfd );
|
||||||
show_dprogress( cfile_size, partial_file_pos, &rdec, &pp ); // init
|
show_dprogress( cfile_size, partial_file_pos, &rdec, &pp ); // init
|
||||||
const int result =
|
const int result = decoder.decode_member( cl_opts, pp );
|
||||||
decoder.decode_member( pp, cl_opts.ignore_empty, cl_opts.ignore_marking );
|
|
||||||
partial_file_pos += rdec.member_position();
|
partial_file_pos += rdec.member_position();
|
||||||
if( result != 0 )
|
if( result != 0 )
|
||||||
{
|
{
|
||||||
|
@ -705,14 +729,13 @@ int decompress( const unsigned long long cfile_size, const int infd,
|
||||||
|
|
||||||
void set_signal_handler() { set_signals( signal_handler ); }
|
void set_signal_handler() { set_signals( signal_handler ); }
|
||||||
|
|
||||||
int close_outstream( const struct stat * const in_statsp )
|
bool close_outstream( const struct stat * const in_statsp )
|
||||||
{
|
{
|
||||||
if( delete_output_on_interrupt )
|
if( delete_output_on_interrupt ) close_and_set_permissions( in_statsp );
|
||||||
close_and_set_permissions( in_statsp );
|
|
||||||
if( outfd >= 0 && close( outfd ) != 0 )
|
if( outfd >= 0 && close( outfd ) != 0 )
|
||||||
{ show_error( "Error closing stdout", errno ); return 1; }
|
{ show_error( "Error closing stdout", errno ); return false; }
|
||||||
outfd = -1;
|
outfd = -1;
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -783,7 +806,7 @@ int main( const int argc, const char * const argv[] )
|
||||||
// '0'..'9' = level, 'a' = all levels
|
// '0'..'9' = level, 'a' = all levels
|
||||||
// -5..-273 = match length, -1 = all lengths
|
// -5..-273 = match length, -1 = all lengths
|
||||||
int repeated_byte = -1; // 0 to 255, or -1 for all values
|
int repeated_byte = -1; // 0 to 255, or -1 for all values
|
||||||
Cl_options cl_opts; // command line options
|
Cl_options cl_opts; // command-line options
|
||||||
bool force = false;
|
bool force = false;
|
||||||
bool keep_input_files = false;
|
bool keep_input_files = false;
|
||||||
bool to_stdout = false;
|
bool to_stdout = false;
|
||||||
|
@ -825,14 +848,14 @@ int main( const int argc, const char * const argv[] )
|
||||||
{ opt_cm, "clear-marking", Arg_parser::no },
|
{ opt_cm, "clear-marking", Arg_parser::no },
|
||||||
{ opt_du, "dump", Arg_parser::yes },
|
{ opt_du, "dump", Arg_parser::yes },
|
||||||
{ opt_eer, "empty-error", Arg_parser::no },
|
{ opt_eer, "empty-error", Arg_parser::no },
|
||||||
{ opt_mer, "marking-error", Arg_parser::no },
|
|
||||||
{ opt_lt, "loose-trailing", Arg_parser::no },
|
{ opt_lt, "loose-trailing", Arg_parser::no },
|
||||||
{ opt_lzl, "lzip-level", Arg_parser::yes },
|
{ opt_lzl, "lzip-level", Arg_parser::yes },
|
||||||
{ opt_lzn, "lzip-name", Arg_parser::yes },
|
{ opt_lzn, "lzip-name", Arg_parser::yes },
|
||||||
|
{ opt_mer, "marking-error", Arg_parser::no },
|
||||||
{ opt_ref, "reference-file", Arg_parser::yes },
|
{ opt_ref, "reference-file", Arg_parser::yes },
|
||||||
{ opt_rem, "remove", Arg_parser::yes },
|
{ opt_rem, "remove", Arg_parser::yes },
|
||||||
{ opt_st, "strip", Arg_parser::yes },
|
{ opt_st, "strip", Arg_parser::yes },
|
||||||
{ 0 , 0, Arg_parser::no } };
|
{ 0, 0, Arg_parser::no } };
|
||||||
|
|
||||||
const Arg_parser parser( argc, argv, options );
|
const Arg_parser parser( argc, argv, options );
|
||||||
if( parser.error().size() ) // bad option
|
if( parser.error().size() ) // bad option
|
||||||
|
@ -898,7 +921,7 @@ int main( const int argc, const char * const argv[] )
|
||||||
member_list.parse_ml( arg, pn, cl_opts ); break;
|
member_list.parse_ml( arg, pn, cl_opts ); break;
|
||||||
case opt_st: set_mode( program_mode, m_strip );
|
case opt_st: set_mode( program_mode, m_strip );
|
||||||
member_list.parse_ml( arg, pn, cl_opts ); break;
|
member_list.parse_ml( arg, pn, cl_opts ); break;
|
||||||
default : internal_error( "uncaught option." );
|
default: internal_error( "uncaught option." );
|
||||||
}
|
}
|
||||||
} // end process options
|
} // end process options
|
||||||
|
|
||||||
|
@ -1020,11 +1043,11 @@ int main( const int argc, const char * const argv[] )
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
const bool one_to_one = !to_stdout && program_mode != m_test && !to_file;
|
const bool one_to_one = !to_stdout && program_mode != m_test && !to_file;
|
||||||
bool stdin_used = false;
|
bool stdin_used = false;
|
||||||
|
struct stat in_stats;
|
||||||
for( unsigned i = 0; i < filenames.size(); ++i )
|
for( unsigned i = 0; i < filenames.size(); ++i )
|
||||||
{
|
{
|
||||||
std::string input_filename;
|
std::string input_filename;
|
||||||
int infd;
|
int infd;
|
||||||
struct stat in_stats;
|
|
||||||
|
|
||||||
pp.set_name( filenames[i] );
|
pp.set_name( filenames[i] );
|
||||||
if( filenames[i] == "-" )
|
if( filenames[i] == "-" )
|
||||||
|
@ -1087,7 +1110,9 @@ int main( const int argc, const char * const argv[] )
|
||||||
( program_mode != m_decompress || !cl_opts.ignore_errors ) )
|
( program_mode != m_decompress || !cl_opts.ignore_errors ) )
|
||||||
std::remove( input_filename.c_str() );
|
std::remove( input_filename.c_str() );
|
||||||
}
|
}
|
||||||
if( delete_output_on_interrupt ) close_and_set_permissions( 0 ); // -o
|
if( delete_output_on_interrupt ) // -o
|
||||||
|
close_and_set_permissions( ( retval == 0 && !stdin_used &&
|
||||||
|
filenames_given && filenames.size() == 1 ) ? &in_stats : 0 );
|
||||||
else if( outfd >= 0 && close( outfd ) != 0 ) // -c
|
else if( outfd >= 0 && close( outfd ) != 0 ) // -c
|
||||||
{
|
{
|
||||||
show_error( "Error closing stdout", errno );
|
show_error( "Error closing stdout", errno );
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Lziprecover - Data recovery tool for the lzip format
|
/* Lziprecover - Data recovery tool for the lzip format
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const char * const program_year = "2023";
|
const char * const program_year = "2024";
|
||||||
|
|
||||||
void show_version()
|
void show_version()
|
||||||
{
|
{
|
||||||
|
@ -32,9 +32,9 @@ void show_version()
|
||||||
// separate numbers of 5 or more digits in groups of 3 digits using '_'
|
// separate numbers of 5 or more digits in groups of 3 digits using '_'
|
||||||
const char * format_num3( long long num )
|
const char * format_num3( long long num )
|
||||||
{
|
{
|
||||||
const char * const si_prefix = "kMGTPEZY";
|
enum { buffers = 8, bufsize = 4 * sizeof num, n = 10 };
|
||||||
const char * const binary_prefix = "KMGTPEZY";
|
const char * const si_prefix = "kMGTPEZYRQ";
|
||||||
enum { buffers = 8, bufsize = 4 * sizeof num };
|
const char * const binary_prefix = "KMGTPEZYRQ";
|
||||||
static char buffer[buffers][bufsize]; // circle of static buffers for printf
|
static char buffer[buffers][bufsize]; // circle of static buffers for printf
|
||||||
static int current = 0;
|
static int current = 0;
|
||||||
|
|
||||||
|
@ -42,19 +42,22 @@ const char * format_num3( long long num )
|
||||||
char * p = buf + bufsize - 1; // fill the buffer backwards
|
char * p = buf + bufsize - 1; // fill the buffer backwards
|
||||||
*p = 0; // terminator
|
*p = 0; // terminator
|
||||||
const bool negative = num < 0;
|
const bool negative = num < 0;
|
||||||
char prefix = 0; // try binary first, then si
|
if( num > 1024 || num < -1024 )
|
||||||
for( int i = 0; i < 8 && num != 0 && ( num / 1024 ) * 1024 == num; ++i )
|
{
|
||||||
{ num /= 1024; prefix = binary_prefix[i]; }
|
char prefix = 0; // try binary first, then si
|
||||||
if( prefix ) *(--p) = 'i';
|
for( int i = 0; i < n && num != 0 && num % 1024 == 0; ++i )
|
||||||
else
|
{ num /= 1024; prefix = binary_prefix[i]; }
|
||||||
for( int i = 0; i < 8 && num != 0 && ( num / 1000 ) * 1000 == num; ++i )
|
if( prefix ) *(--p) = 'i';
|
||||||
{ num /= 1000; prefix = si_prefix[i]; }
|
else
|
||||||
if( prefix ) *(--p) = prefix;
|
for( int i = 0; i < n && num != 0 && num % 1000 == 0; ++i )
|
||||||
|
{ num /= 1000; prefix = si_prefix[i]; }
|
||||||
|
if( prefix ) *(--p) = prefix;
|
||||||
|
}
|
||||||
const bool split = num >= 10000 || num <= -10000;
|
const bool split = num >= 10000 || num <= -10000;
|
||||||
|
|
||||||
for( int i = 0; ; )
|
for( int i = 0; ; )
|
||||||
{
|
{
|
||||||
long long onum = num; num /= 10;
|
const long long onum = num; num /= 10;
|
||||||
*(--p) = llabs( onum - ( 10 * num ) ) + '0'; if( num == 0 ) break;
|
*(--p) = llabs( onum - ( 10 * num ) ) + '0'; if( num == 0 ) break;
|
||||||
if( split && ++i >= 3 ) { i = 0; *(--p) = '_'; }
|
if( split && ++i >= 3 ) { i = 0; *(--p) = '_'; }
|
||||||
}
|
}
|
||||||
|
@ -72,8 +75,7 @@ void show_option_error( const char * const arg, const char * const msg,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Recognized formats: <num>[YZEPTGM][i][Bs], <num>k[Bs], <num>Ki[Bs]
|
// Recognized formats: <num>k[Bs], <num>Ki[Bs], <num>[MGTPEZYRQ][i][Bs]
|
||||||
//
|
|
||||||
long long getnum( const char * const arg, const char * const option_name,
|
long long getnum( const char * const arg, const char * const option_name,
|
||||||
const int hardbs, const long long llimit = LLONG_MIN,
|
const int hardbs, const long long llimit = LLONG_MIN,
|
||||||
const long long ulimit = LLONG_MAX,
|
const long long ulimit = LLONG_MAX,
|
||||||
|
@ -107,7 +109,7 @@ long long getnum( const char * const arg, const char * const option_name,
|
||||||
case 'k': if( tail[0] != 'i' ) exponent = 1; break;
|
case 'k': if( tail[0] != 'i' ) exponent = 1; break;
|
||||||
case 'B':
|
case 'B':
|
||||||
case 's': usuf = *p; exponent = 0; break;
|
case 's': usuf = *p; exponent = 0; break;
|
||||||
default : if( tailp ) { tail = p; exponent = 0; }
|
default: if( tailp ) { tail = p; exponent = 0; }
|
||||||
}
|
}
|
||||||
if( exponent > 1 && tail[0] == 'i' ) { ++tail; factor = 1024; }
|
if( exponent > 1 && tail[0] == 'i' ) { ++tail; factor = 1024; }
|
||||||
if( exponent > 0 && usuf == 0 && ( tail[0] == 'B' || tail[0] == 's' ) )
|
if( exponent > 0 && usuf == 0 && ( tail[0] == 'B' || tail[0] == 's' ) )
|
||||||
|
|
2
md5.cc
2
md5.cc
|
@ -1,6 +1,6 @@
|
||||||
/* Functions to compute MD5 message digest of memory blocks according to the
|
/* Functions to compute MD5 message digest of memory blocks according to the
|
||||||
definition of MD5 in RFC 1321 from April 1992.
|
definition of MD5 in RFC 1321 from April 1992.
|
||||||
Copyright (C) 2020-2023 Antonio Diaz Diaz.
|
Copyright (C) 2020-2024 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
|
||||||
|
|
2
md5.h
2
md5.h
|
@ -1,6 +1,6 @@
|
||||||
/* Functions to compute MD5 message digest of memory blocks according to the
|
/* Functions to compute MD5 message digest of memory blocks according to the
|
||||||
definition of MD5 in RFC 1321 from April 1992.
|
definition of MD5 in RFC 1321 from April 1992.
|
||||||
Copyright (C) 2020-2023 Antonio Diaz Diaz.
|
Copyright (C) 2020-2024 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
|
||||||
|
|
16
merge.cc
16
merge.cc
|
@ -1,5 +1,5 @@
|
||||||
/* Lziprecover - Data recovery tool for the lzip format
|
/* Lziprecover - Data recovery tool for the lzip format
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -549,7 +549,7 @@ int test_member_from_file( const int infd, const unsigned long long msize,
|
||||||
{
|
{
|
||||||
Range_decoder rdec( infd );
|
Range_decoder rdec( infd );
|
||||||
Lzip_header header;
|
Lzip_header header;
|
||||||
rdec.read_data( header.data, Lzip_header::size );
|
rdec.read_data( header.data, header.size );
|
||||||
const unsigned dictionary_size = header.dictionary_size();
|
const unsigned dictionary_size = header.dictionary_size();
|
||||||
bool done = false;
|
bool done = false;
|
||||||
if( !rdec.finished() && header.check_magic() &&
|
if( !rdec.finished() && header.check_magic() &&
|
||||||
|
@ -558,8 +558,7 @@ int test_member_from_file( const int infd, const unsigned long long msize,
|
||||||
LZ_decoder decoder( rdec, dictionary_size, -1 );
|
LZ_decoder decoder( rdec, dictionary_size, -1 );
|
||||||
const int saved_verbosity = verbosity;
|
const int saved_verbosity = verbosity;
|
||||||
verbosity = -1; // suppress all messages
|
verbosity = -1; // suppress all messages
|
||||||
Pretty_print dummy_pp( "" );
|
done = decoder.decode_member() == 0;
|
||||||
done = ( decoder.decode_member( dummy_pp ) == 0 );
|
|
||||||
verbosity = saved_verbosity; // restore verbosity level
|
verbosity = saved_verbosity; // restore verbosity level
|
||||||
if( done && rdec.member_position() == msize ) return 0;
|
if( done && rdec.member_position() == msize ) return 0;
|
||||||
}
|
}
|
||||||
|
@ -582,10 +581,11 @@ int merge_files( const std::vector< std::string > & filenames,
|
||||||
if( retval >= 0 ) return retval;
|
if( retval >= 0 ) return retval;
|
||||||
if( !safe_seek( infd_vector[0], 0, filenames[0].c_str() ) ) return 1;
|
if( !safe_seek( infd_vector[0], 0, filenames[0].c_str() ) ) return 1;
|
||||||
|
|
||||||
output_filename = default_output_filename.empty() ?
|
const bool to_file = default_output_filename.size();
|
||||||
insert_fixed( filenames[0] ) : default_output_filename;
|
output_filename =
|
||||||
|
to_file ? default_output_filename : insert_fixed( filenames[0] );
|
||||||
set_signal_handler();
|
set_signal_handler();
|
||||||
if( !open_outstream( force, true, true, false ) ) return 1;
|
if( !open_outstream( force, true, true, false, to_file ) ) return 1;
|
||||||
if( !copy_file( infd_vector[0], outfd ) ) // copy whole file
|
if( !copy_file( infd_vector[0], outfd ) ) // copy whole file
|
||||||
cleanup_and_fail( 1 );
|
cleanup_and_fail( 1 );
|
||||||
|
|
||||||
|
@ -651,7 +651,7 @@ int merge_files( const std::vector< std::string > & filenames,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( close_outstream( &in_stats ) != 0 ) return 1;
|
if( !close_outstream( &in_stats ) ) return 1;
|
||||||
if( verbosity >= 1 )
|
if( verbosity >= 1 )
|
||||||
std::fputs( "Input files merged successfully.\n", stdout );
|
std::fputs( "Input files merged successfully.\n", stdout );
|
||||||
return 0;
|
return 0;
|
||||||
|
|
10
mtester.cc
10
mtester.cc
|
@ -1,5 +1,5 @@
|
||||||
/* Lziprecover - Data recovery tool for the lzip format
|
/* Lziprecover - Data recovery tool for the lzip format
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -102,8 +102,6 @@ bool LZ_mtester::check_trailer( FILE * const f, unsigned long long byte_pos )
|
||||||
std::fputs( "Can't get trailer.\n", f ); }
|
std::fputs( "Can't get trailer.\n", f ); }
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const unsigned long long data_size = data_position();
|
|
||||||
const unsigned long member_size = rdec.member_position();
|
|
||||||
bool error = false;
|
bool error = false;
|
||||||
|
|
||||||
const unsigned td_crc = trailer->data_crc();
|
const unsigned td_crc = trailer->data_crc();
|
||||||
|
@ -116,6 +114,7 @@ bool LZ_mtester::check_trailer( FILE * const f, unsigned long long byte_pos )
|
||||||
std::fprintf( f, "CRC mismatch; stored %08X, computed %08X\n",
|
std::fprintf( f, "CRC mismatch; stored %08X, computed %08X\n",
|
||||||
td_crc, crc() ); }
|
td_crc, crc() ); }
|
||||||
}
|
}
|
||||||
|
const unsigned long long data_size = data_position();
|
||||||
const unsigned long long td_size = trailer->data_size();
|
const unsigned long long td_size = trailer->data_size();
|
||||||
if( td_size != data_size )
|
if( td_size != data_size )
|
||||||
{
|
{
|
||||||
|
@ -126,6 +125,7 @@ bool LZ_mtester::check_trailer( FILE * const f, unsigned long long byte_pos )
|
||||||
std::fprintf( f, "Data size mismatch; stored %llu (0x%llX), computed %llu (0x%llX)\n",
|
std::fprintf( f, "Data size mismatch; stored %llu (0x%llX), computed %llu (0x%llX)\n",
|
||||||
td_size, td_size, data_size, data_size ); }
|
td_size, td_size, data_size, data_size ); }
|
||||||
}
|
}
|
||||||
|
const unsigned long member_size = rdec.member_position();
|
||||||
const unsigned long long tm_size = trailer->member_size();
|
const unsigned long long tm_size = trailer->member_size();
|
||||||
if( tm_size != member_size )
|
if( tm_size != member_size )
|
||||||
{
|
{
|
||||||
|
@ -350,9 +350,7 @@ int LZ_mtester::debug_decode_member( const long long dpos, const long long mpos,
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
if( len == min_match_len + 1 ) // Sync Flush marker
|
if( len == min_match_len + 1 ) // Sync Flush marker
|
||||||
{
|
{ rdec.load(); continue; }
|
||||||
rdec.load(); continue;
|
|
||||||
}
|
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Lziprecover - Data recovery tool for the lzip format
|
/* Lziprecover - Data recovery tool for the lzip format
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Lziprecover - Data recovery tool for the lzip format
|
/* Lziprecover - Data recovery tool for the lzip format
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
35
range_dec.cc
35
range_dec.cc
|
@ -1,5 +1,5 @@
|
||||||
/* Lziprecover - Data recovery tool for the lzip format
|
/* Lziprecover - Data recovery tool for the lzip format
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -35,14 +35,13 @@
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
bool decompress_member( const int infd, const Pretty_print & pp,
|
bool decompress_member( const int infd, const Cl_options & cl_opts,
|
||||||
const unsigned long long mpos,
|
const Pretty_print & pp, const unsigned long long mpos,
|
||||||
const unsigned long long outskip,
|
const unsigned long long outskip, const unsigned long long outend )
|
||||||
const unsigned long long outend )
|
|
||||||
{
|
{
|
||||||
Range_decoder rdec( infd );
|
Range_decoder rdec( infd );
|
||||||
Lzip_header header;
|
Lzip_header header;
|
||||||
rdec.read_data( header.data, Lzip_header::size );
|
rdec.read_data( header.data, header.size );
|
||||||
if( rdec.finished() ) // End Of File
|
if( rdec.finished() ) // End Of File
|
||||||
{ pp( "File ends unexpectedly at member header." ); return false; }
|
{ pp( "File ends unexpectedly at member header." ); return false; }
|
||||||
if( !header.check_magic() ) { pp( bad_magic_msg ); return false; }
|
if( !header.check_magic() ) { pp( bad_magic_msg ); return false; }
|
||||||
|
@ -54,7 +53,7 @@ bool decompress_member( const int infd, const Pretty_print & pp,
|
||||||
if( verbosity >= 2 ) pp();
|
if( verbosity >= 2 ) pp();
|
||||||
|
|
||||||
LZ_decoder decoder( rdec, dictionary_size, outfd, outskip, outend );
|
LZ_decoder decoder( rdec, dictionary_size, outfd, outskip, outend );
|
||||||
const int result = decoder.decode_member( pp );
|
const int result = decoder.decode_member( cl_opts, pp );
|
||||||
if( result != 0 )
|
if( result != 0 )
|
||||||
{
|
{
|
||||||
if( verbosity >= 0 && result <= 2 )
|
if( verbosity >= 0 && result <= 2 )
|
||||||
|
@ -86,23 +85,23 @@ const char * format_num( unsigned long long num,
|
||||||
unsigned long long limit,
|
unsigned long long limit,
|
||||||
const int set_prefix )
|
const int set_prefix )
|
||||||
{
|
{
|
||||||
const char * const si_prefix[8] =
|
enum { buffers = 8, bufsize = 32, n = 10 };
|
||||||
{ "k", "M", "G", "T", "P", "E", "Z", "Y" };
|
const char * const si_prefix[n] =
|
||||||
const char * const binary_prefix[8] =
|
{ "k", "M", "G", "T", "P", "E", "Z", "Y", "R", "Q" };
|
||||||
{ "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" };
|
const char * const binary_prefix[n] =
|
||||||
enum { buffers = 8, bufsize = 32 };
|
{ "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi", "Ri", "Qi" };
|
||||||
static char buffer[buffers][bufsize]; // circle of static buffers for printf
|
static char buffer[buffers][bufsize]; // circle of static buffers for printf
|
||||||
static int current = 0;
|
static int current = 0;
|
||||||
static bool si = true;
|
static bool si = true;
|
||||||
|
|
||||||
if( set_prefix ) si = ( set_prefix > 0 );
|
if( set_prefix ) si = ( set_prefix > 0 );
|
||||||
unsigned long long den = 1;
|
unsigned long long den = 1;
|
||||||
const unsigned factor = ( si ? 1000 : 1024 );
|
const unsigned factor = si ? 1000 : 1024;
|
||||||
char * const buf = buffer[current++]; current %= buffers;
|
char * const buf = buffer[current++]; current %= buffers;
|
||||||
const char * const * prefix = ( si ? si_prefix : binary_prefix );
|
const char * const * prefix = si ? si_prefix : binary_prefix;
|
||||||
const char * p = "";
|
const char * p = "";
|
||||||
|
|
||||||
for( int i = 0; i < 8 && num / den >= factor && den * factor > den; ++i )
|
for( int i = 0; i < n && num / den >= factor && den * factor > den; ++i )
|
||||||
{ if( num / den <= limit && num % ( den * factor ) != 0 ) break;
|
{ if( num / den <= limit && num % ( den * factor ) != 0 ) break;
|
||||||
den *= factor; p = prefix[i]; }
|
den *= factor; p = prefix[i]; }
|
||||||
if( num % den == 0 )
|
if( num % den == 0 )
|
||||||
|
@ -150,7 +149,7 @@ int range_decompress( const std::string & input_filename,
|
||||||
{
|
{
|
||||||
output_filename = default_output_filename;
|
output_filename = default_output_filename;
|
||||||
set_signal_handler();
|
set_signal_handler();
|
||||||
if( !open_outstream( force, true, false, false ) ) return 1;
|
if( !open_outstream( force, true, false, false, true ) ) return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( verbosity >= 1 )
|
if( verbosity >= 1 )
|
||||||
|
@ -172,7 +171,7 @@ int range_decompress( const std::string & input_filename,
|
||||||
const long long outend = std::min( db.size(), range.end() - db.pos() );
|
const long long outend = std::min( db.size(), range.end() - db.pos() );
|
||||||
const long long mpos = lzip_index.mblock( i ).pos();
|
const long long mpos = lzip_index.mblock( i ).pos();
|
||||||
if( !safe_seek( infd, mpos, filename ) ) cleanup_and_fail( 1 );
|
if( !safe_seek( infd, mpos, filename ) ) cleanup_and_fail( 1 );
|
||||||
if( !decompress_member( infd, pp, mpos, outskip, outend ) )
|
if( !decompress_member( infd, cl_opts, pp, mpos, outskip, outend ) )
|
||||||
{ if( cl_opts.ignore_errors ) error = true; else cleanup_and_fail( 2 ); }
|
{ if( cl_opts.ignore_errors ) error = true; else cleanup_and_fail( 2 ); }
|
||||||
pp.reset();
|
pp.reset();
|
||||||
}
|
}
|
||||||
|
@ -180,7 +179,7 @@ int range_decompress( const std::string & input_filename,
|
||||||
if( close( infd ) != 0 )
|
if( close( infd ) != 0 )
|
||||||
{ show_file_error( filename, "Error closing input file", errno );
|
{ show_file_error( filename, "Error closing input file", errno );
|
||||||
cleanup_and_fail( 1 ); }
|
cleanup_and_fail( 1 ); }
|
||||||
if( close_outstream( &in_stats ) != 0 ) cleanup_and_fail( 1 );
|
if( !close_outstream( &in_stats ) ) cleanup_and_fail( 1 );
|
||||||
if( verbosity >= 2 && !error )
|
if( verbosity >= 2 && !error )
|
||||||
std::fputs( "Byte range decompressed successfully.\n", stderr );
|
std::fputs( "Byte range decompressed successfully.\n", stderr );
|
||||||
return 0; // either no error or ignored
|
return 0; // either no error or ignored
|
||||||
|
|
11
reproduce.cc
11
reproduce.cc
|
@ -1,5 +1,5 @@
|
||||||
/* Lziprecover - Data recovery tool for the lzip format
|
/* Lziprecover - Data recovery tool for the lzip format
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -532,8 +532,9 @@ int reproduce_file( const std::string & input_filename,
|
||||||
{ show_file_error( filename, lzip_index.error().c_str() );
|
{ show_file_error( filename, lzip_index.error().c_str() );
|
||||||
return lzip_index.retval(); }
|
return lzip_index.retval(); }
|
||||||
|
|
||||||
output_filename = default_output_filename.empty() ?
|
const bool to_file = default_output_filename.size();
|
||||||
insert_fixed( input_filename ) : default_output_filename;
|
output_filename =
|
||||||
|
to_file ? default_output_filename : insert_fixed( input_filename );
|
||||||
if( !force && output_file_exists() ) return 1;
|
if( !force && output_file_exists() ) return 1;
|
||||||
outfd = -1;
|
outfd = -1;
|
||||||
int errors = 0;
|
int errors = 0;
|
||||||
|
@ -593,7 +594,7 @@ int reproduce_file( const std::string & input_filename,
|
||||||
{
|
{
|
||||||
if( !safe_seek( infd, 0, filename ) ) return 1;
|
if( !safe_seek( infd, 0, filename ) ) return 1;
|
||||||
set_signal_handler();
|
set_signal_handler();
|
||||||
if( !open_outstream( true, true ) ) return 1;
|
if( !open_outstream( true, true, false, true, to_file ) ) return 1;
|
||||||
if( !copy_file( infd, outfd ) ) // copy whole file
|
if( !copy_file( infd, outfd ) ) // copy whole file
|
||||||
cleanup_and_fail( 1 );
|
cleanup_and_fail( 1 );
|
||||||
}
|
}
|
||||||
|
@ -619,7 +620,7 @@ int reproduce_file( const std::string & input_filename,
|
||||||
filename );
|
filename );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if( close_outstream( &in_stats ) != 0 ) return 1;
|
if( !close_outstream( &in_stats ) ) return 1;
|
||||||
if( verbosity >= 0 )
|
if( verbosity >= 0 )
|
||||||
{
|
{
|
||||||
if( errors > 1 )
|
if( errors > 1 )
|
||||||
|
|
33
split.cc
33
split.cc
|
@ -1,5 +1,5 @@
|
||||||
/* Lziprecover - Data recovery tool for the lzip format
|
/* Lziprecover - Data recovery tool for the lzip format
|
||||||
Copyright (C) 2009-2023 Antonio Diaz Diaz.
|
Copyright (C) 2009-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -34,16 +34,17 @@
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void first_filename( const std::string & input_filename,
|
bool first_filename( const std::string & input_filename,
|
||||||
const std::string & default_output_filename,
|
const std::string & default_output_filename,
|
||||||
const int max_digits )
|
const int max_digits )
|
||||||
{
|
{
|
||||||
output_filename = default_output_filename.empty() ?
|
const bool to_file = default_output_filename.size();
|
||||||
input_filename : default_output_filename;
|
output_filename = to_file ? default_output_filename : input_filename;
|
||||||
int b = output_filename.size();
|
int b = output_filename.size();
|
||||||
while( b > 0 && output_filename[b-1] != '/' ) --b;
|
while( b > 0 && output_filename[b-1] != '/' ) --b;
|
||||||
output_filename.insert( b, "rec1" );
|
output_filename.insert( b, "rec1" );
|
||||||
if( max_digits > 1 ) output_filename.insert( b + 3, max_digits - 1, '0' );
|
if( max_digits > 1 ) output_filename.insert( b + 3, max_digits - 1, '0' );
|
||||||
|
return to_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,7 +109,8 @@ int split_file( const std::string & input_filename,
|
||||||
if( !safe_seek( infd, 0, filename ) ) return 1;
|
if( !safe_seek( infd, 0, filename ) ) return 1;
|
||||||
int max_digits = 1;
|
int max_digits = 1;
|
||||||
for( long i = lzip_index.blocks( true ); i >= 10; i /= 10 ) ++max_digits;
|
for( long i = lzip_index.blocks( true ); i >= 10; i /= 10 ) ++max_digits;
|
||||||
first_filename( input_filename, default_output_filename, max_digits );
|
bool to_file = // if true, create intermediate dirs
|
||||||
|
first_filename( input_filename, default_output_filename, max_digits );
|
||||||
|
|
||||||
long long stream_pos = 0; // first pos not yet written to file
|
long long stream_pos = 0; // first pos not yet written to file
|
||||||
set_signal_handler();
|
set_signal_handler();
|
||||||
|
@ -117,26 +119,23 @@ int split_file( const std::string & input_filename,
|
||||||
const Block & mb = lzip_index.mblock( i );
|
const Block & mb = lzip_index.mblock( i );
|
||||||
if( mb.pos() > stream_pos ) // gap
|
if( mb.pos() > stream_pos ) // gap
|
||||||
{
|
{
|
||||||
if( !open_outstream( force, true, false, false ) ) return 1;
|
if( !open_outstream( force, true, false, false, to_file ) ) return 1;
|
||||||
if( !copy_file( infd, outfd, mb.pos() - stream_pos ) ||
|
if( !copy_file( infd, outfd, mb.pos() - stream_pos ) ||
|
||||||
close_outstream( &in_stats ) != 0 )
|
!close_outstream( &in_stats ) ) cleanup_and_fail( 1 );
|
||||||
cleanup_and_fail( 1 );
|
next_filename( max_digits ); to_file = false;
|
||||||
next_filename( max_digits );
|
|
||||||
}
|
}
|
||||||
if( !open_outstream( force, true, false, false ) ) return 1; // member
|
if( !open_outstream( force, true, false, false, to_file ) ) return 1; // member
|
||||||
if( !copy_file( infd, outfd, mb.size() ) ||
|
if( !copy_file( infd, outfd, mb.size() ) ||
|
||||||
close_outstream( &in_stats ) != 0 )
|
!close_outstream( &in_stats ) ) cleanup_and_fail( 1 );
|
||||||
cleanup_and_fail( 1 );
|
next_filename( max_digits ); to_file = false;
|
||||||
next_filename( max_digits );
|
|
||||||
stream_pos = mb.end();
|
stream_pos = mb.end();
|
||||||
}
|
}
|
||||||
if( lzip_index.file_size() > stream_pos ) // trailing data
|
if( lzip_index.file_size() > stream_pos ) // trailing data
|
||||||
{
|
{
|
||||||
if( !open_outstream( force, true, false, false ) ) return 1;
|
if( !open_outstream( force, true, false, false, to_file ) ) return 1;
|
||||||
if( !copy_file( infd, outfd, lzip_index.file_size() - stream_pos ) ||
|
if( !copy_file( infd, outfd, lzip_index.file_size() - stream_pos ) ||
|
||||||
close_outstream( &in_stats ) != 0 )
|
!close_outstream( &in_stats ) ) cleanup_and_fail( 1 );
|
||||||
cleanup_and_fail( 1 );
|
next_filename( max_digits ); to_file = false;
|
||||||
next_filename( max_digits );
|
|
||||||
}
|
}
|
||||||
close( infd );
|
close( infd );
|
||||||
return 0;
|
return 0;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
||||||
/* Unzcrash - Tests robustness of decompressors to corrupted data.
|
/* Unzcrash - Tests robustness of decompressors to corrupted data.
|
||||||
Inspired by unzcrash.c from Julian Seward's bzip2.
|
Inspired by unzcrash.c from Julian Seward's bzip2.
|
||||||
Copyright (C) 2008-2023 Antonio Diaz Diaz.
|
Copyright (C) 2008-2024 Antonio Diaz Diaz.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
Exit status: 0 for a normal exit, 1 for environmental problems
|
Exit status: 0 for a normal exit, 1 for environmental problems
|
||||||
(file not found, invalid command line options, I/O errors, etc), 2 to
|
(file not found, invalid command-line options, I/O errors, etc), 2 to
|
||||||
indicate a corrupt or invalid input file, 3 for an internal consistency
|
indicate a corrupt or invalid input file, 3 for an internal consistency
|
||||||
error (e.g., bug) which caused unzcrash to panic.
|
error (e.g., bug) which caused unzcrash to panic.
|
||||||
*/
|
*/
|
||||||
|
@ -102,7 +102,7 @@ void show_help()
|
||||||
"A negative position is relative to the end of file.\n"
|
"A negative position is relative to the end of file.\n"
|
||||||
"A negative size is relative to the rest of the file.\n"
|
"A negative size is relative to the rest of the file.\n"
|
||||||
"\nExit status: 0 for a normal exit, 1 for environmental problems\n"
|
"\nExit status: 0 for a normal exit, 1 for environmental problems\n"
|
||||||
"(file not found, invalid command line options, I/O errors, etc), 2 to\n"
|
"(file not found, invalid command-line options, I/O errors, etc), 2 to\n"
|
||||||
"indicate a corrupt or invalid input file, 3 for an internal consistency\n"
|
"indicate a corrupt or invalid input file, 3 for an internal consistency\n"
|
||||||
"error (e.g., bug) which caused unzcrash to panic.\n"
|
"error (e.g., bug) which caused unzcrash to panic.\n"
|
||||||
"\nReport bugs to lzip-bug@nongnu.org\n"
|
"\nReport bugs to lzip-bug@nongnu.org\n"
|
||||||
|
@ -412,7 +412,7 @@ int main( const int argc, const char * const argv[] )
|
||||||
case 'v': if( verbosity < 4 ) ++verbosity; break;
|
case 'v': if( verbosity < 4 ) ++verbosity; break;
|
||||||
case 'V': show_version(); return 0;
|
case 'V': show_version(); return 0;
|
||||||
case 'z': zcmp_program = arg; break;
|
case 'z': zcmp_program = arg; break;
|
||||||
default : internal_error( "uncaught option." );
|
default: internal_error( "uncaught option." );
|
||||||
}
|
}
|
||||||
} // end process options
|
} // end process options
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue