diff options
Diffstat (limited to '')
-rw-r--r-- | zutils.cc | 175 |
1 files changed, 43 insertions, 132 deletions
@@ -27,14 +27,51 @@ #include <unistd.h> #include <sys/wait.h> -#include "zutils.h" #include "rc.h" +#include "zutils.h" -const char * invocation_name = 0; -const char * util_name = program_name; +namespace { -int verbosity = 0; +// first magic byte must be different among formats +enum { bzip2_magic_size = 3, + gzip_magic_size = 2, + lzip_magic_size = 4, + xz_magic_size = 5 }; +const uint8_t bzip2_magic[bzip2_magic_size] = + { 0x42, 0x5A, 0x68 }; // "BZh" +const uint8_t gzip_magic[gzip_magic_size] = + { 0x1F, 0x8B }; +const uint8_t lzip_magic[lzip_magic_size] = + { 0x4C, 0x5A, 0x49, 0x50 }; // "LZIP" +const uint8_t xz_magic[xz_magic_size] = + { 0xFD, 0x37, 0x7A, 0x58, 0x5A }; // 0xFD, "7zXZ" + + +// Returns -1 if child not terminated, 2 in case of error, or +// exit status of child process 'pid'. +// +int child_status( const pid_t pid, const char * const name ) + { + int status; + while( true ) + { + const int tmp = waitpid( pid, &status, WNOHANG ); + if( tmp == -1 && errno != EINTR ) + { + if( verbosity >= 0 ) + std::fprintf( stderr, "%s: Error checking status of '%s': %s.\n", + program_name, name, std::strerror( errno ) ); + _exit( 2 ); + } + if( tmp == 0 ) return -1; // child not terminated + if( tmp == pid ) break; // child terminated + } + if( WIFEXITED( status ) ) return WEXITSTATUS( status ); + return 2; + } + +} // end namespace int parse_format_type( const std::string & arg ) @@ -152,7 +189,7 @@ bool set_data_feeder( int * const infdp, Children & children, int format_index ) !feed_data( old_infd, fda[1], magic_data, magic_size ) ) _exit( 2 ); if( close( fda[1] ) != 0 ) - { show_close_error( "data feeder" ); _exit( 2 ); } + { show_close_error(); _exit( 2 ); } _exit( 0 ); } if( pid < 0 ) // parent @@ -201,7 +238,7 @@ bool set_data_feeder( int * const infdp, Children & children, int format_index ) !feed_data( old_infd, fda[1], magic_data, magic_size ) ) _exit( 2 ); if( close( fda[1] ) != 0 ) - { show_close_error( "data feeder" ); _exit( 2 ); } + { show_close_error(); _exit( 2 ); } _exit( 0 ); } if( pid < 0 ) // parent @@ -214,84 +251,6 @@ bool set_data_feeder( int * const infdp, Children & children, int format_index ) } -void show_help_addr() - { - std::printf( "\nReport bugs to zutils-bug@nongnu.org\n" - "Zutils home page: http://www.nongnu.org/zutils/zutils.html\n" ); - } - - -void show_version( const char * const Util_name ) - { - if( !Util_name || !Util_name[0] ) - std::printf( "%s %s\n", Program_name, PROGVERSION ); - else - std::printf( "%s (%s) %s\n", Util_name, 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" - "There is NO WARRANTY, to the extent permitted by law.\n" ); - } - - -void show_error( const char * const msg, const int errcode, const bool help ) - { - if( verbosity >= 0 ) - { - if( msg && msg[0] ) - { - std::fprintf( stderr, "%s: %s", util_name, msg ); - if( errcode > 0 ) - std::fprintf( stderr, ": %s", std::strerror( errcode ) ); - std::fprintf( stderr, "\n" ); - } - if( help ) - std::fprintf( stderr, "Try '%s --help' for more information.\n", - invocation_name ); - } - } - - -void show_error2( const char * const msg, const char * const name ) - { - if( verbosity >= 0 ) - std::fprintf( stderr, "%s: %s '%s': %s.\n", - util_name, msg, name, std::strerror( errno ) ); - } - - -void show_close_error( const char * const prog_name ) - { - if( verbosity >= 0 ) - std::fprintf( stderr, "%s: Can't close output of %s: %s.\n", - util_name, prog_name, std::strerror( errno ) ); - } - - -void show_exec_error( const char * const prog_name ) - { - if( verbosity >= 0 ) - std::fprintf( stderr, "%s: Can't exec '%s': %s.\n", - util_name, prog_name, std::strerror( errno ) ); - } - - -void show_fork_error( const char * const prog_name ) - { - if( verbosity >= 0 ) - std::fprintf( stderr, "%s: Can't fork '%s': %s.\n", - util_name, prog_name, std::strerror( errno ) ); - } - - -void internal_error( const char * const msg ) - { - if( verbosity >= 0 ) - std::fprintf( stderr, "%s: internal error: %s.\n", util_name, msg ); - std::exit( 3 ); - } - - int test_format( const int infd, const uint8_t ** const magic_datap, int * const magic_sizep ) { @@ -335,51 +294,3 @@ int test_format( const int infd, const uint8_t ** const magic_datap, *magic_datap = buf; *magic_sizep = i; return -1; } - - -int wait_for_child( const pid_t pid, const char * const name, - const int eretval, const bool isgzxz ) - { - int status; - while( waitpid( pid, &status, 0 ) == -1 ) - { - if( errno != EINTR ) - { - if( verbosity >= 0 ) - std::fprintf( stderr, "%s: Error waiting termination of '%s': %s.\n", - util_name, name, std::strerror( errno ) ); - _exit( eretval ); - } - } - - if( WIFEXITED( status ) ) - { - const int tmp = WEXITSTATUS( status ); - if( isgzxz && eretval == 1 && tmp == 1 ) return 2; // for ztest - return tmp; - } - return eretval; - } - - -int child_status( const pid_t pid, const char * const name, - const int eretval ) - { - int status; - while( true ) - { - const int tmp = waitpid( pid, &status, WNOHANG ); - if( tmp == -1 && errno != EINTR ) - { - if( verbosity >= 0 ) - std::fprintf( stderr, "%s: Error checking status of '%s': %s.\n", - util_name, name, std::strerror( errno ) ); - _exit( eretval ); - } - if( tmp == 0 ) return -1; // child not terminated - if( tmp == pid ) break; // child terminated - } - - if( WIFEXITED( status ) ) return WEXITSTATUS( status ); - return eretval; - } |