1
0
Fork 0

Adding upstream version 0.6.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-24 04:57:56 +01:00
parent 557010b363
commit c2bdc739f1
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
14 changed files with 207 additions and 172 deletions

146
main.cc
View file

@ -134,6 +134,7 @@ void show_help() throw()
// std::printf( " -d, --decompress decompress\n" );
// std::printf( " -f, --force overwrite existing output files\n" );
// std::printf( " -k, --keep keep (don't delete) input files\n" );
std::printf( " -m, --magic=<type> output magic bytes for given file type\n" );
// std::printf( " -o, --output=<file> if reading stdin, place the output into <file>\n" );
std::printf( " -q, --quiet suppress all messages\n" );
std::printf( " -t, --test test compressed file type\n" );
@ -492,6 +493,129 @@ int decompress( const int inhandle, const Pretty_print & pp )
}
*/
unsigned char xdigit( const int value ) throw()
{
if( value >= 0 && value <= 9 ) return '0' + value;
if( value >= 10 && value <= 15 ) return 'A' + value - 10;
return 0;
}
int xtoi( const unsigned char ch ) throw()
{
switch( ch )
{
case '0': return 0;
case '1': return 1;
case '2': return 2;
case '3': return 3;
case '4': return 4;
case '5': return 5;
case '6': return 6;
case '7': return 7;
case '8': return 8;
case '9': return 9;
case 'a':
case 'A': return 0x0A;
case 'b':
case 'B': return 0x0B;
case 'c':
case 'C': return 0x0C;
case 'd':
case 'D': return 0x0D;
case 'e':
case 'E': return 0x0E;
case 'f':
case 'F': return 0x0F;
default: return -1;
}
}
bool hex_to_data( const std::string & hex, std::string & data )
{
data.clear();
if( hex.size() == 0 || hex.size() % 2 != 0 ) return false;
for( unsigned int i = 0; 2 * i + 1 < hex.size(); ++i )
{
int uch = xtoi( hex[2*i] );
int lch = xtoi( hex[2*i+1] );
if( uch < 0 || lch < 0 ) return false;
data.push_back( ( uch << 4 ) | lch );
}
return true;
}
int print_magic_type( const std::string & magic_type )
{
std::string data;
if( magic_type == "gzip" ) std::printf( "\x1F\x8B" );
else if( magic_type == "bzip2" ) std::printf( "BZh" );
else if( magic_type == "lzip" ) std::printf( "LZIP" );
else if( magic_type == "xz" ) std::printf( "%c7zXZ", '\xFD' );
else if( hex_to_data( magic_type, data ) ) std::printf( data.c_str() );
else return 1;
return 0;
}
int test_stdin_type( const int inhandle, const Pretty_print & pp )
{
unsigned char buf[5];
const char * msg = 0;
int i = 0;
if( readblock( inhandle, (char *)buf, 1 ) == 1 )
{
if( buf[0] == 0x1F )
{
if( readblock( inhandle, (char *)&buf[++i], 1 ) == 1 && buf[i] == 0x8B )
msg = "gzip";
}
else if( buf[0] == 'B' )
{
if( readblock( inhandle, (char *)&buf[++i], 1 ) == 1 && buf[i] == 'Z' &&
readblock( inhandle, (char *)&buf[++i], 1 ) == 1 && buf[i] == 'h' )
msg = "bzip2";
}
else if( buf[0] == 'L' )
{
if( readblock( inhandle, (char *)&buf[++i], 1 ) == 1 && buf[i] == 'Z' &&
readblock( inhandle, (char *)&buf[++i], 1 ) == 1 && buf[i] == 'I' &&
readblock( inhandle, (char *)&buf[++i], 1 ) == 1 && buf[i] == 'P' )
msg = "lzip";
}
else if( buf[0] == 0xFD )
{
if( readblock( inhandle, (char *)&buf[++i], 1 ) == 1 && buf[i] == '7' &&
readblock( inhandle, (char *)&buf[++i], 1 ) == 1 && buf[i] == 'z' &&
readblock( inhandle, (char *)&buf[++i], 1 ) == 1 && buf[i] == 'X' &&
readblock( inhandle, (char *)&buf[++i], 1 ) == 1 && buf[i] == 'Z' )
msg = "xz";
}
}
const int retval = ( msg ? 0 : 1 );
if( verbosity >= 0 )
{
if( verbosity >= 1 ) pp();
if( !msg )
{
char hexmsg[(2*sizeof buf)+1];
for( int j = 0; j <= i; ++j )
{
hexmsg[2*j] = xdigit( buf[j] >> 4 );
hexmsg[2*j+1] = xdigit( buf[j] & 0x0F );
}
hexmsg[2*i+2] = 0;
msg = hexmsg;
}
std::printf( "%s\n", msg );
}
return retval;
}
int test_type( const int inhandle, const Pretty_print & pp )
{
unsigned char buf[5];
@ -505,7 +629,7 @@ int test_type( const int inhandle, const Pretty_print & pp )
msg = "bzip2";
else if( buf[0] == 'L' && buf[1] == 'Z' && buf[2] == 'I' && buf[3] == 'P' )
msg = "lzip";
else if( buf[1] == '7' && buf[2] == 'z' && buf[3] == 'X' && buf[4] == 'Z' )
else if( buf[0] == 0xFD && buf[1] == '7' && buf[2] == 'z' && buf[3] == 'X' && buf[4] == 'Z' )
msg = "xz";
}
const int retval = ( msg ? 0 : 1 );
@ -546,6 +670,7 @@ int main( const int argc, const char * argv[] )
std::string input_filename;
std::string default_output_filename;
std::vector< std::string > filenames;
std::string magic_type;
invocation_name = argv[0];
const Arg_parser::Option options[] =
@ -555,6 +680,7 @@ int main( const int argc, const char * argv[] )
{ 'f', "force", Arg_parser::no },
{ 'h', "help", Arg_parser::no },
{ 'k', "keep", Arg_parser::no },
{ 'm', "magic", Arg_parser::yes },
{ 'o', "output", Arg_parser::yes },
{ 'q', "quiet", Arg_parser::no },
{ 't', "test", Arg_parser::no },
@ -571,7 +697,7 @@ int main( const int argc, const char * argv[] )
{
const int code = parser.code( argind );
if( !code ) break; // no more options
const char * arg = parser.argument( argind ).c_str();
const std::string & arg = parser.argument( argind );
switch( code )
{
case 'c': to_stdout = true; break;
@ -579,6 +705,7 @@ int main( const int argc, const char * argv[] )
case 'f': force = true; break;
case 'h': show_help(); return 0;
case 'k': keep_input_files = true; break;
case 'm': magic_type = arg; break;
case 'o': default_output_filename = arg; break;
case 'q': verbosity = -1; break;
case 't': program_mode = m_test; break;
@ -588,6 +715,8 @@ int main( const int argc, const char * argv[] )
}
}
if( magic_type.size() ) return print_magic_type( magic_type );
bool filenames_given = false;
for( ; argind < parser.arguments(); ++argind )
{
@ -669,19 +798,22 @@ int main( const int argc, const char * argv[] )
case m_decompress:
/*tmp = decompress( inhandle, pp );*/ break;
case m_test:
tmp = test_type( inhandle, pp ); break;
if( inhandle == STDIN_FILENO )
tmp = test_stdin_type( inhandle, pp );
else tmp = test_type( inhandle, pp );
break;
}
if( tmp > retval ) retval = tmp;
if( tmp && program_mode != m_test ) cleanup_and_fail( retval );
/*
if( delete_output_on_interrupt )
close_and_set_permissions( in_statsp, &retval );
// if( delete_output_on_interrupt )
// close_and_set_permissions( in_statsp, &retval );
if( input_filename.size() )
{
close( inhandle ); inhandle = -1;
if( !keep_input_files && !to_stdout && program_mode != m_test )
std::remove( input_filename.c_str() );
}*/
}
}
if( outhandle >= 0 ) close( outhandle );
return retval;