1
0
Fork 0

Merging upstream version 1.16~pre1.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-21 11:19:58 +01:00
parent c9bda4fdd7
commit 6a54533419
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
23 changed files with 520 additions and 446 deletions

94
main.cc
View file

@ -1,5 +1,5 @@
/* Lziprecover - Data recovery tool for lzip files
Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 Antonio Diaz Diaz.
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
@ -56,6 +56,10 @@
#include "lzip.h"
#include "decoder.h"
#ifndef O_BINARY
#define O_BINARY 0
#endif
#if CHAR_BIT != 8
#error "Environments where CHAR_BIT != 8 are not supported."
#endif
@ -65,22 +69,16 @@ namespace {
const char * const Program_name = "Lziprecover";
const char * const program_name = "lziprecover";
const char * const program_year = "2013";
const char * const program_year = "2014";
const char * invocation_name = 0;
#ifdef O_BINARY
const int o_binary = O_BINARY;
#else
const int o_binary = 0;
#endif
struct { const char * from; const char * to; } const known_extensions[] = {
{ ".lz", "" },
{ ".tlz", ".tar" },
{ 0, 0 } };
enum Mode { m_none, m_decompress, m_generate, m_list, m_merge, m_range,
m_recover, m_repair, m_split, m_test };
enum Mode { m_none, m_decompress, m_list, m_merge, m_range, m_repair,
m_split, m_test };
std::string output_filename;
int outfd = -1;
@ -102,14 +100,12 @@ void show_help()
" -d, --decompress decompress\n"
" -D, --range-decompress=<range> decompress only a range of bytes (N-M)\n"
" -f, --force overwrite existing output files\n"
// " -g, --generate-recover-file generate a recover file\n"
" -i, --ignore-errors make '--range-decompress' ignore data errors\n"
" -k, --keep keep (don't delete) input files\n"
" -l, --list print total file sizes and ratios\n"
" -m, --merge correct errors in file using several copies\n"
" -o, --output=<file> place the output into <file>\n"
" -q, --quiet suppress all messages\n"
// " -r, --recover correct errors in file using a recover file\n"
" -R, --repair try to repair a small error in file\n"
" -s, --split split multi-member file in single-member files\n"
" -t, --test test compressed file integrity\n"
@ -127,7 +123,7 @@ void show_help()
void show_version()
{
std::printf( "%s %s\n", Program_name, PROGVERSION );
std::printf( "%s %s\n", program_name, PROGVERSION );
std::printf( "Copyright (C) %s Antonio Diaz Diaz.\n", program_year );
std::printf( "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n"
"This is free software: you are free to change and redistribute it.\n"
@ -189,15 +185,15 @@ int extension_index( const std::string & name )
} // end namespace
int open_instream( const std::string & name, struct stat * const in_statsp,
int open_instream( const char * const name, struct stat * const in_statsp,
const bool no_ofile, const bool reg_only )
{
int infd = open( name.c_str(), O_RDONLY | o_binary );
int infd = open( name, O_RDONLY | O_BINARY );
if( infd < 0 )
{
if( verbosity >= 0 )
std::fprintf( stderr, "%s: Can't open input file '%s': %s.\n",
program_name, name.c_str(), std::strerror( errno ) );
program_name, name, std::strerror( errno ) );
}
else
{
@ -210,7 +206,7 @@ int open_instream( const std::string & name, struct stat * const in_statsp,
{
if( verbosity >= 0 )
std::fprintf( stderr, "%s: Input file '%s' is not a regular file%s.\n",
program_name, name.c_str(),
program_name, name,
( can_read && !no_ofile ) ?
" and '--stdout' was not specified" : "" );
close( infd );
@ -243,7 +239,7 @@ void set_d_outname( const std::string & name, const int i )
bool open_outstream( const bool force )
{
int flags = O_CREAT | O_WRONLY | o_binary;
int flags = O_CREAT | O_WRONLY | O_BINARY;
if( force ) flags |= O_TRUNC; else flags |= O_EXCL;
outfd = open( output_filename.c_str(), flags, outfd_mode );
@ -293,10 +289,14 @@ void close_and_set_permissions( const struct stat * const in_statsp )
bool warning = false;
if( in_statsp )
{
const mode_t mode = in_statsp->st_mode;
// fchown will in many cases return with EPERM, which can be safely ignored.
if( ( fchown( outfd, in_statsp->st_uid, in_statsp->st_gid ) != 0 &&
errno != EPERM ) ||
fchmod( outfd, in_statsp->st_mode ) != 0 ) warning = true;
if( fchown( outfd, in_statsp->st_uid, in_statsp->st_gid ) == 0 )
{ if( fchmod( outfd, mode ) != 0 ) warning = true; }
else
if( errno != EPERM ||
fchmod( outfd, mode & ~( S_ISUID | S_ISGID | S_ISVTX ) ) != 0 )
warning = true;
}
if( close( outfd ) != 0 ) cleanup_and_fail( 1 );
outfd = -1;
@ -356,6 +356,7 @@ void show_trailing_garbage( const uint8_t * const data, const int size,
garbage_msg += xdigit( data[i] & 0x0F );
}
}
garbage_msg += '.';
pp( garbage_msg.c_str() );
}
@ -375,7 +376,7 @@ int decompress( const int infd, const Pretty_print & pp, const bool testing )
if( rdec.finished() ) // End Of File
{
if( first_member )
{ pp( "File ends unexpectedly at member header" ); retval = 2; }
{ pp( "File ends unexpectedly at member header." ); retval = 2; }
else if( verbosity >= 4 && size > 0 )
show_trailing_garbage( header.data, size, pp, true );
break;
@ -383,7 +384,7 @@ int decompress( const int infd, const Pretty_print & pp, const bool testing )
if( !header.verify_magic() )
{
if( first_member )
{ pp( "Bad magic number (file not in lzip format)" ); retval = 2; }
{ pp( "Bad magic number (file not in lzip format)." ); retval = 2; }
else if( verbosity >= 4 )
show_trailing_garbage( header.data, size, pp, false );
break;
@ -398,7 +399,7 @@ int decompress( const int infd, const Pretty_print & pp, const bool testing )
}
if( header.dictionary_size() < min_dictionary_size ||
header.dictionary_size() > max_dictionary_size )
{ pp( "Invalid dictionary size in member header" ); retval = 2; break; }
{ pp( "Invalid dictionary size in member header." ); retval = 2; break; }
if( verbosity >= 2 || ( verbosity == 1 && first_member ) )
{ pp(); if( verbosity >= 3 ) show_header( header ); }
@ -412,10 +413,10 @@ int decompress( const int infd, const Pretty_print & pp, const bool testing )
{
pp();
if( result == 2 )
std::fprintf( stderr, "File ends unexpectedly at pos %llu\n",
std::fprintf( stderr, "File ends unexpectedly at pos %llu.\n",
partial_file_pos );
else
std::fprintf( stderr, "Decoder error at pos %llu\n",
std::fprintf( stderr, "Decoder error at pos %llu.\n",
partial_file_pos );
}
retval = 2; break;
@ -424,11 +425,7 @@ int decompress( const int infd, const Pretty_print & pp, const bool testing )
{ std::fprintf( stderr, testing ? "ok\n" : "done\n" ); pp.reset(); }
}
}
catch( std::bad_alloc )
{
pp( "Not enough memory. Find a machine with more memory" );
retval = 1;
}
catch( std::bad_alloc ) { pp( "Not enough memory." ); retval = 1; }
catch( Error e ) { pp(); show_error( e.msg, errno ); retval = 1; }
if( verbosity == 1 && retval == 0 )
std::fprintf( stderr, testing ? "ok\n" : "done\n" );
@ -455,7 +452,7 @@ void set_signals()
int open_outstream_rw( const std::string & output_filename, const bool force )
{
int flags = O_CREAT | O_RDWR | o_binary;
int flags = O_CREAT | O_RDWR | O_BINARY;
if( force ) flags |= O_TRUNC; else flags |= O_EXCL;
int outfd = open( output_filename.c_str(), flags, all_rw );
@ -481,7 +478,7 @@ void show_error( const char * const msg, const int errcode, const bool help )
{
std::fprintf( stderr, "%s: %s", program_name, msg );
if( errcode > 0 )
std::fprintf( stderr, ": %s", std::strerror( errcode ) );
std::fprintf( stderr, ": %s.", std::strerror( errcode ) );
std::fprintf( stderr, "\n" );
}
if( help )
@ -491,10 +488,18 @@ void show_error( const char * const msg, const int errcode, const bool help )
}
void show_error2( const char * const msg1, const char * const name,
const char * const msg2 )
{
if( verbosity >= 0 )
std::fprintf( stderr, "%s: %s '%s' %s\n", program_name, msg1, name, msg2 );
}
void internal_error( const char * const msg )
{
if( verbosity >= 0 )
std::fprintf( stderr, "%s: internal error: %s.\n", program_name, msg );
std::fprintf( stderr, "%s: internal error: %s\n", program_name, msg );
std::exit( 3 );
}
@ -564,7 +569,7 @@ int main( const int argc, const char * const argv[] )
case 't': set_mode( program_mode, m_test ); break;
case 'v': if( verbosity < 4 ) ++verbosity; break;
case 'V': show_version(); return 0;
default : internal_error( "uncaught option" );
default : internal_error( "uncaught option." );
}
} // end process options
@ -588,9 +593,7 @@ int main( const int argc, const char * const argv[] )
switch( program_mode )
{
case m_generate:
case m_recover:
case m_none: internal_error( "invalid operation" ); break;
case m_none: internal_error( "invalid operation." ); break;
case m_decompress: break;
case m_list:
if( filenames.size() < 1 )
@ -599,7 +602,7 @@ int main( const int argc, const char * const argv[] )
case m_merge:
if( filenames.size() < 2 )
{ show_error( "You must specify at least 2 files.", 0, true ); return 1; }
if( !default_output_filename.size() )
if( default_output_filename.empty() )
default_output_filename = insert_fixed( filenames[0] );
return merge_files( filenames, default_output_filename, verbosity, force );
case m_range:
@ -608,9 +611,10 @@ int main( const int argc, const char * const argv[] )
range_string, verbosity, force, ignore, to_stdout );
case m_repair:
one_file( filenames.size() );
if( !default_output_filename.size() )
if( default_output_filename.empty() )
default_output_filename = insert_fixed( filenames[0] );
return repair_file( filenames[0], default_output_filename, verbosity, force );
return repair_file( filenames[0], default_output_filename,
verbosity, force );
case m_split:
one_file( filenames.size() );
return split_file( filenames[0], default_output_filename, verbosity, force );
@ -620,7 +624,7 @@ int main( const int argc, const char * const argv[] )
if( program_mode == m_test )
outfd = -1;
else if( program_mode != m_decompress )
internal_error( "invalid decompressor operation" );
internal_error( "invalid decompressor operation." );
if( filenames.empty() ) filenames.push_back("-");
if( !to_stdout && program_mode != m_test &&
@ -635,13 +639,13 @@ int main( const int argc, const char * const argv[] )
struct stat in_stats;
output_filename.clear();
if( !filenames[i].size() || filenames[i] == "-" )
if( filenames[i].empty() || filenames[i] == "-" )
{
input_filename.clear();
infd = STDIN_FILENO;
if( program_mode != m_test )
{
if( to_stdout || !default_output_filename.size() )
if( to_stdout || default_output_filename.empty() )
outfd = STDOUT_FILENO;
else
{
@ -659,7 +663,7 @@ int main( const int argc, const char * const argv[] )
else
{
input_filename = filenames[i];
infd = open_instream( input_filename, &in_stats,
infd = open_instream( input_filename.c_str(), &in_stats,
to_stdout || program_mode == m_test );
if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; }
if( program_mode != m_test )