Merging upstream version 0.11.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
3b818501c2
commit
5db1949a73
18 changed files with 1504 additions and 654 deletions
75
extract.cc
75
extract.cc
|
@ -44,7 +44,6 @@
|
|||
namespace {
|
||||
|
||||
Resizable_buffer grbuf( initial_line_length );
|
||||
int gretval = 0;
|
||||
bool has_lz_ext; // global var for archive_read
|
||||
|
||||
void skip_warn( const bool reset = false ) // avoid duplicate warnings
|
||||
|
@ -118,16 +117,14 @@ int archive_read( const int infd, uint8_t * const buf, const int size,
|
|||
if( !islz && !istar && !iseof ) // corrupt or invalid format
|
||||
{
|
||||
show_error( "This does not look like a POSIX tar archive." );
|
||||
if( has_lz_ext ) islz = true;
|
||||
if( verbosity >= 2 && !islz && rd == size )
|
||||
std::fprintf( stderr, "ustar chksum = %07o\n", ustar_chksum( buf ) );
|
||||
if( has_lz_ext && rd >= min_member_size ) islz = true;
|
||||
if( !islz ) return 1;
|
||||
}
|
||||
if( !islz ) // uncompressed
|
||||
{ if( rd == size ) return 0; fatal = true; return 2; }
|
||||
decoder = LZ_decompress_open(); // compressed
|
||||
if( !decoder || LZ_decompress_errno( decoder ) != LZ_ok )
|
||||
{ show_error( "Not enough memory." );
|
||||
{ show_error( mem_msg );
|
||||
LZ_decompress_close( decoder ); fatal = true; return 2; }
|
||||
if( LZ_decompress_write( decoder, buf, rd ) != rd )
|
||||
internal_error( "library error (LZ_decompress_write)." );
|
||||
|
@ -154,7 +151,7 @@ int archive_read( const int infd, uint8_t * const buf, const int size,
|
|||
{
|
||||
if( LZ_decompress_sync_to_member( decoder ) < 0 )
|
||||
internal_error( "library error (LZ_decompress_sync_to_member)." );
|
||||
skip_warn(); gretval = 2; return 1;
|
||||
skip_warn(); set_error_status( 2 ); return 1;
|
||||
}
|
||||
if( rd == 0 && LZ_decompress_finished( decoder ) == 1 )
|
||||
{ LZ_decompress_close( decoder );
|
||||
|
@ -271,8 +268,8 @@ void format_member_name( const Extended & extended, const Tar_header header,
|
|||
extended.file_size(), 1900 + tm->tm_year, 1 + tm->tm_mon,
|
||||
tm->tm_mday, tm->tm_hour, tm->tm_min, extended.path().c_str(),
|
||||
link_string, !islink ? "" : extended.linkpath().c_str() );
|
||||
if( (int)rbuf.size() > len + offset ) break;
|
||||
else rbuf.resize( len + offset + 1 );
|
||||
if( (int)rbuf.size() > len + offset || !rbuf.resize( len + offset + 1 ) )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -458,25 +455,6 @@ int extract_member( const int infd, const Extended & extended,
|
|||
|
||||
} // end namespace
|
||||
|
||||
// Removes any amount of leading "./" and '/' strings.
|
||||
const char * remove_leading_slash( const char * const filename )
|
||||
{
|
||||
static bool first_post = true;
|
||||
const char * p = filename;
|
||||
|
||||
while( *p == '/' || ( *p == '.' && p[1] == '/' ) ) ++p;
|
||||
if( p != filename && first_post )
|
||||
{
|
||||
first_post = false;
|
||||
std::string msg( "Removing leading '" );
|
||||
msg.append( filename, p - filename );
|
||||
msg += "' from member names.";
|
||||
show_error( msg.c_str() );
|
||||
}
|
||||
if( *p == 0 ) p = ".";
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
// return true if dir is a parent directory of name
|
||||
bool compare_prefix_dir( const char * const dir, const char * const name )
|
||||
|
@ -587,19 +565,21 @@ int decode( const std::string & archive_name, const Arg_parser & parser,
|
|||
{ show_file_error( dir, "Error changing working directory", errno );
|
||||
return 1; }
|
||||
}
|
||||
if( !code ) name_pending[i] = true;
|
||||
if( !code && parser.argument( i ).size() ) name_pending[i] = true;
|
||||
}
|
||||
|
||||
if( listing && num_workers > 0 ) // multi-threaded --list
|
||||
// multi-threaded --list is faster even with 1 thread and 1 file in archive
|
||||
if( listing && num_workers > 0 )
|
||||
{
|
||||
const Lzip_index lzip_index( infd, true, false );
|
||||
const Lzip_index lzip_index( infd, true, false ); // only regular files
|
||||
const long members = lzip_index.members();
|
||||
if( lzip_index.retval() == 0 && ( members >= 3 ||
|
||||
( members >= 2 && lzip_index.dblock( members - 1 ).size() > 1024 ) ) )
|
||||
{ //show_file_error( archive_name.c_str(), "Is compressed seekable" );
|
||||
return list_lz( parser, name_pending, lzip_index, filenames,
|
||||
debug_level, infd, std::min( (long)num_workers, members ),
|
||||
missing_crc, permissive ); }
|
||||
if( lzip_index.retval() == 0 && members >= 2 ) // one file + eof
|
||||
{
|
||||
// show_file_error( archive_name.c_str(), "Is compressed seekable" );
|
||||
return list_lz( parser, name_pending, lzip_index, filenames, debug_level,
|
||||
infd, std::min( (long)num_workers, members ),
|
||||
missing_crc, permissive );
|
||||
}
|
||||
lseek( infd, 0, SEEK_SET );
|
||||
}
|
||||
|
||||
|
@ -619,7 +599,9 @@ int decode( const std::string & archive_name, const Arg_parser & parser,
|
|||
if( ret != 0 || !verify_ustar_chksum( header ) )
|
||||
{
|
||||
if( ret == 0 && block_is_zero( header, header_size ) ) break; // EOF
|
||||
skip_warn(); gretval = 2; continue;
|
||||
if( verbosity >= 2 )
|
||||
std::fprintf( stderr, "ustar chksum = %07o\n", ustar_chksum( header ) );
|
||||
skip_warn(); set_error_status( 2 ); continue;
|
||||
}
|
||||
skip_warn( true ); // reset warning
|
||||
|
||||
|
@ -632,7 +614,7 @@ int decode( const std::string & archive_name, const Arg_parser & parser,
|
|||
Extended dummy; // global headers are parsed and ignored
|
||||
if( !parse_records( infd, dummy, header, true ) )
|
||||
{ show_error( "Error in global extended records. Skipping to next header." );
|
||||
gretval = 2; }
|
||||
set_error_status( 2 ); }
|
||||
continue;
|
||||
}
|
||||
if( typeflag == tf_extended )
|
||||
|
@ -642,7 +624,7 @@ int decode( const std::string & archive_name, const Arg_parser & parser,
|
|||
/*" Use --permissive.", 0, true*/ ); return 2; }
|
||||
if( !parse_records( infd, extended, header, permissive ) )
|
||||
{ show_error( "Error in extended records. Skipping to next header." );
|
||||
extended.reset(); gretval = 2; }
|
||||
extended.reset(); set_error_status( 2 ); }
|
||||
else if( !extended.crc_present() && missing_crc )
|
||||
{ show_error( "Missing CRC in extended records.", 0, true ); return 2; }
|
||||
prev_extended = true;
|
||||
|
@ -674,17 +656,17 @@ int decode( const std::string & archive_name, const Arg_parser & parser,
|
|||
{ stored_name[len] = header[name_o+i]; ++len; }
|
||||
while( len > 0 && stored_name[len-1] == '/' ) --len; // trailing '/'
|
||||
stored_name[len] = 0;
|
||||
extended.path( remove_leading_slash( stored_name ) );
|
||||
extended.path( remove_leading_dotslash( stored_name ) );
|
||||
}
|
||||
const char * const filename = extended.path().c_str();
|
||||
|
||||
bool skip = filenames > 0;
|
||||
if( skip )
|
||||
for( int i = 0; i < parser.arguments(); ++i )
|
||||
if( parser.code( i ) == 0 )
|
||||
if( !parser.code( i ) && parser.argument( i ).size() )
|
||||
{
|
||||
const char * const name =
|
||||
remove_leading_slash( parser.argument( i ).c_str() );
|
||||
remove_leading_dotslash( parser.argument( i ).c_str() );
|
||||
if( compare_prefix_dir( name, filename ) ||
|
||||
compare_tslash( name, filename ) )
|
||||
{ skip = false; name_pending[i] = false; break; }
|
||||
|
@ -705,13 +687,10 @@ int decode( const std::string & archive_name, const Arg_parser & parser,
|
|||
}
|
||||
|
||||
for( int i = 0; i < parser.arguments(); ++i )
|
||||
if( parser.code( i ) == 0 && name_pending[i] )
|
||||
if( !parser.code( i ) && parser.argument( i ).size() && name_pending[i] )
|
||||
{
|
||||
show_file_error( parser.argument( i ).c_str(), "Not found in archive." );
|
||||
if( gretval < 1 ) gretval = 1;
|
||||
set_error_status( 1 );
|
||||
}
|
||||
if( !retval && gretval )
|
||||
{ show_error( "Exiting with failure status due to previous errors." );
|
||||
retval = gretval; }
|
||||
return retval;
|
||||
return final_exit_status( retval );
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue