1
0
Fork 0

Merging upstream version 1.2~pre3.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-24 05:45:59 +01:00
parent 388270afb8
commit 57a593e0b1
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
32 changed files with 1172 additions and 1035 deletions

View file

@ -37,24 +37,18 @@
#endif
#include "arg_parser.h"
#include "zutils.h"
#include "rc.h"
#if CHAR_BIT != 8
#error "Environments where CHAR_BIT != 8 are not supported."
#ifndef O_BINARY
#define O_BINARY 0
#endif
namespace {
#ifdef O_BINARY
const int o_binary = O_BINARY;
#else
const int o_binary = 0;
#endif
#include "recursive.cc"
void show_zupdate_help()
void show_help()
{
std::printf( "Zupdate recompresses files from bzip2, gzip, and xz formats to lzip format.\n"
"The originals are compared with the new files and then deleted.\n"
@ -77,6 +71,7 @@ void show_zupdate_help()
" -h, --help display this help and exit\n"
" -V, --version output version information and exit\n"
" -f, --force do not skip a file even if the .lz exists\n"
" -k, --keep keep (don't delete) input files\n"
" -l, --lzip-verbose pass a -v option to the lzip compressor\n"
" -N, --no-rcfile don't read runtime configuration file\n"
" -q, --quiet suppress all messages\n"
@ -97,10 +92,10 @@ int cant_execute( const std::string & command, const int status )
{
if( WIFEXITED( status ) )
std::fprintf( stderr, "%s: Error executing '%s'. Exit status = %d.\n",
util_name, command.c_str(), WEXITSTATUS( status ) );
program_name, command.c_str(), WEXITSTATUS( status ) );
else
std::fprintf( stderr, "%s: Can't execute '%s'.\n",
util_name, command.c_str() );
program_name, command.c_str() );
}
return 1;
}
@ -136,11 +131,13 @@ struct { const char * from; const char * to; int format_index; } const
{ ".txz", ".tar", fmt_xz },
{ 0, 0, -1 } };
int disable_xz = -1; // tri-state bool
// Returns 0 for success, -1 for file skipped, 1 for error.
int zupdate_file( const std::string & name, const char * const lzip_name,
const std::vector< std::string > & lzip_args2,
const bool force )
const bool force, const bool keep_input_files )
{
int format_index = -1;
std::string dname; // decompressed_name
@ -158,7 +155,7 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
{
if( verbosity >= 2 )
std::fprintf( stderr, "%s: Input file '%s' already has '%s' suffix.\n",
util_name, name.c_str(), known_extensions[i].from );
program_name, name.c_str(), known_extensions[i].from );
return 0; // ignore this file
}
break;
@ -169,7 +166,7 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
{
if( verbosity >= 2 )
std::fprintf( stderr, "%s: Unknown extension in file name '%s' -- ignored.\n",
util_name, name.c_str() );
program_name, name.c_str() );
return 0; // ignore this file
}
@ -178,14 +175,14 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
{
if( verbosity >= 0 )
std::fprintf( stderr, "%s: Can't stat input file '%s': %s.\n",
util_name, name.c_str(), std::strerror( errno ) );
program_name, name.c_str(), std::strerror( errno ) );
return 1;
}
if( !S_ISREG( in_stats.st_mode ) )
{
if( verbosity >= 0 )
std::fprintf( stderr, "%s: Input file '%s' is not a regular file.\n",
util_name, name.c_str() );
program_name, name.c_str() );
return 1;
}
@ -196,10 +193,20 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
{
if( verbosity >= 0 )
std::fprintf( stderr, "%s: Output file '%s' already exists, skipping.\n",
util_name, rname.c_str() );
program_name, rname.c_str() );
return -1;
}
if( format_index == fmt_xz )
{
if( disable_xz < 0 )
{
std::string command( compressor_name ); command += " -V > /dev/null";
disable_xz = ( std::system( command.c_str() ) != 0 );
}
if( disable_xz ) return 0; // ignore this file if no xz installed
}
if( !lz_exists ) // recompress
{
if( verbosity >= 1 )
@ -280,11 +287,11 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
return cant_execute( zcmp_command, status ); }
}
if( std::remove( name.c_str() ) != 0 && errno != ENOENT )
if( !keep_input_files && std::remove( name.c_str() ) != 0 && errno != ENOENT )
{
if( verbosity >= 0 )
std::fprintf( stderr, "%s: Can't delete input file '%s': %s.\n",
util_name, name.c_str(), std::strerror( errno ) );
program_name, name.c_str(), std::strerror( errno ) );
return 1;
}
return 0;
@ -300,9 +307,10 @@ int main( const int argc, const char * const argv[] )
std::list< std::string > filenames;
std::vector< std::string > lzip_args2; // args to lzip, maybe empty
bool force = false;
bool keep_input_files = false;
bool recursive = false;
invocation_name = argv[0];
util_name = "zupdate";
program_name = "zupdate";
const Arg_parser::Option options[] =
{
@ -318,6 +326,7 @@ int main( const int argc, const char * const argv[] )
{ '9', 0, Arg_parser::no },
{ 'f', "force", Arg_parser::no },
{ 'h', "help", Arg_parser::no },
{ 'k', "keep", Arg_parser::no },
{ 'l', "lzip-verbose", Arg_parser::no },
{ 'N', "no-rcfile", Arg_parser::no },
{ 'q', "quiet", Arg_parser::no },
@ -342,23 +351,24 @@ int main( const int argc, const char * const argv[] )
const int code = parser.code( argind );
if( !code ) break; // no more options
const char * const arg = parser.argument( argind ).c_str();
switch( code ) // common options
switch( code )
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
lzip_args2.push_back( "-" ); lzip_args2.back() += code; break;
case 'f': force = true; break;
case 'h': show_zupdate_help(); return 0;
case 'h': show_help(); return 0;
case 'k': keep_input_files = true; break;
case 'l': lzip_args2.push_back( "-v" ); break;
case 'N': continue;
case 'N': break;
case 'q': verbosity = -1; lzip_args2.push_back( "-q" ); break;
case 'r': recursive = true; break;
case 'v': if( verbosity < 4 ) ++verbosity; break;
case 'V': show_version( "Zupdate" ); return 0;
case bz2_opt: parse_compressor( arg, fmt_bz2, 1 ); continue;
case gz_opt: parse_compressor( arg, fmt_gz, 1 ); continue;
case lz_opt: parse_compressor( arg, fmt_lz, 1 ); continue;
case xz_opt: parse_compressor( arg, fmt_xz, 1 ); continue;
case bz2_opt: parse_compressor( arg, fmt_bz2, 1 ); break;
case gz_opt: parse_compressor( arg, fmt_gz, 1 ); break;
case lz_opt: parse_compressor( arg, fmt_lz, 1 ); break;
case xz_opt: parse_compressor( arg, fmt_xz, 1 ); break;
default : internal_error( "uncaught option" );
}
} // end process options
@ -376,40 +386,15 @@ int main( const int argc, const char * const argv[] )
filenames.push_back( parser.argument( argind ) );
int retval = 0;
while( !filenames.empty() )
bool error = false;
while( next_filename( filenames, input_filename, error, recursive, true ) )
{
input_filename = filenames.front();
filenames.pop_front();
if( !input_filename.size() || input_filename == "-" ) continue;
if( recursive )
{
struct stat st;
if( stat( input_filename.c_str(), &st ) == 0 && S_ISDIR( st.st_mode ) )
{
DIR * const dirp = opendir( input_filename.c_str() );
if( !dirp )
{
show_error2( "Can't open directory", input_filename.c_str() );
if( retval < 1 ) retval = 1; continue;
}
std::list< std::string > tmp_list;
while( true )
{
const struct dirent * const entryp = readdir( dirp );
if( !entryp ) { closedir( dirp ); break; }
std::string tmp_name( entryp->d_name );
if( tmp_name != "." && tmp_name != ".." )
tmp_list.push_back( input_filename + "/" + tmp_name );
}
filenames.splice( filenames.begin(), tmp_list );
continue;
}
}
int tmp = zupdate_file( input_filename, lzip_name, lzip_args2, force );
if( tmp < 0 && retval < 1 ) retval = 1;
int tmp = zupdate_file( input_filename, lzip_name, lzip_args2, force,
keep_input_files );
if( tmp < 0 ) error = true;
if( tmp > retval ) retval = tmp;
if( tmp > 0 ) break;
}
if( error && retval == 0 ) retval = 1;
return retval;
}