diff options
Diffstat (limited to 'zupdate.cc')
-rw-r--r-- | zupdate.cc | 103 |
1 files changed, 44 insertions, 59 deletions
@@ -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; } |