Merging upstream version 0.10.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e076fdd679
commit
060c1457b6
21 changed files with 633 additions and 443 deletions
133
extract.cc
133
extract.cc
|
@ -37,7 +37,6 @@
|
|||
#include <lzlib.h>
|
||||
|
||||
#include "arg_parser.h"
|
||||
#include "lzip.h"
|
||||
#include "lzip_index.h"
|
||||
#include "tarlz.h"
|
||||
|
||||
|
@ -268,19 +267,19 @@ void format_member_name( const Extended & extended, const Tar_header header,
|
|||
for( int i = 0; i < 2; ++i )
|
||||
{
|
||||
const int len = snprintf( rbuf() + offset, rbuf.size() - offset,
|
||||
" %9llu %4d-%02u-%02u %02u:%02u %s%s%s\n",
|
||||
extended.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() );
|
||||
" %9llu %4d-%02u-%02u %02u:%02u %s%s%s\n",
|
||||
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 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( rbuf.size() < extended.path.size() + 2 )
|
||||
rbuf.resize( extended.path.size() + 2 );
|
||||
snprintf( rbuf(), rbuf.size(), "%s\n", extended.path.c_str() );
|
||||
if( rbuf.size() < extended.path().size() + 2 )
|
||||
rbuf.resize( extended.path().size() + 2 );
|
||||
snprintf( rbuf(), rbuf.size(), "%s\n", extended.path().c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -303,8 +302,8 @@ int list_member( const int infd, const Extended & extended,
|
|||
|
||||
const unsigned bufsize = 32 * header_size;
|
||||
uint8_t buf[bufsize];
|
||||
unsigned long long rest = extended.size;
|
||||
const int rem = extended.size % header_size;
|
||||
unsigned long long rest = extended.file_size();
|
||||
const int rem = rest % header_size;
|
||||
const int padding = rem ? header_size - rem : 0;
|
||||
while( rest > 0 )
|
||||
{
|
||||
|
@ -331,7 +330,7 @@ bool contains_dotdot( const char * const filename )
|
|||
int extract_member( const int infd, const Extended & extended,
|
||||
const Tar_header header, const bool keep_damaged )
|
||||
{
|
||||
const char * const filename = extended.path.c_str();
|
||||
const char * const filename = extended.path().c_str();
|
||||
if( contains_dotdot( filename ) )
|
||||
{
|
||||
show_file_error( filename, "Contains a '..' component, skipping." );
|
||||
|
@ -357,7 +356,7 @@ int extract_member( const int infd, const Extended & extended,
|
|||
case tf_link:
|
||||
case tf_symlink:
|
||||
{
|
||||
const char * const linkname = extended.linkpath.c_str();
|
||||
const char * const linkname = extended.linkpath().c_str();
|
||||
/* if( contains_dotdot( linkname ) )
|
||||
{
|
||||
show_file_error( filename,
|
||||
|
@ -421,8 +420,8 @@ int extract_member( const int infd, const Extended & extended,
|
|||
|
||||
const unsigned bufsize = 32 * header_size;
|
||||
uint8_t buf[bufsize];
|
||||
unsigned long long rest = extended.size;
|
||||
const int rem = extended.size % header_size;
|
||||
unsigned long long rest = extended.file_size();
|
||||
const int rem = rest % header_size;
|
||||
const int padding = rem ? header_size - rem : 0;
|
||||
while( rest > 0 )
|
||||
{
|
||||
|
@ -501,42 +500,6 @@ bool compare_tslash( const char * const name1, const char * const name2 )
|
|||
|
||||
namespace {
|
||||
|
||||
unsigned long long parse_decimal( const char * const ptr,
|
||||
const char ** const tailp,
|
||||
const unsigned long long size )
|
||||
{
|
||||
unsigned long long result = 0;
|
||||
unsigned long long i = 0;
|
||||
while( i < size && std::isspace( ptr[i] ) ) ++i;
|
||||
if( !std::isdigit( (unsigned char)ptr[i] ) )
|
||||
{ if( tailp ) *tailp = ptr; return 0; }
|
||||
for( ; i < size && std::isdigit( (unsigned char)ptr[i] ); ++i )
|
||||
{
|
||||
const unsigned long long prev = result;
|
||||
result *= 10; result += ptr[i] - '0';
|
||||
if( result < prev || result > LLONG_MAX ) // overflow
|
||||
{ if( tailp ) *tailp = ptr; return 0; }
|
||||
}
|
||||
if( tailp ) *tailp = ptr + i;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
uint32_t parse_record_crc( const char * const ptr )
|
||||
{
|
||||
uint32_t crc = 0;
|
||||
for( int i = 0; i < 8; ++i )
|
||||
{
|
||||
crc <<= 4;
|
||||
if( ptr[i] >= '0' && ptr[i] <= '9' ) crc += ptr[i] - '0';
|
||||
else if( ptr[i] >= 'A' && ptr[i] <= 'F' ) crc += ptr[i] + 10 - 'A';
|
||||
else if( ptr[i] >= 'a' && ptr[i] <= 'f' ) crc += ptr[i] + 10 - 'a';
|
||||
else { crc = 0; break; } // invalid digit in crc string
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
bool parse_records( const int infd, Extended & extended,
|
||||
const Tar_header header, const bool permissive )
|
||||
{
|
||||
|
@ -602,48 +565,6 @@ unsigned long long parse_octal( const uint8_t * const ptr, const int size )
|
|||
}
|
||||
|
||||
|
||||
bool Extended::parse( const char * const buf, const unsigned long long edsize,
|
||||
const bool permissive )
|
||||
{
|
||||
for( unsigned long long pos = 0; pos < edsize; ) // parse records
|
||||
{
|
||||
const char * tail;
|
||||
const unsigned long long rsize =
|
||||
parse_decimal( buf + pos, &tail, edsize - pos );
|
||||
if( rsize == 0 || rsize > edsize - pos || tail[0] != ' ' ||
|
||||
buf[pos+rsize-1] != '\n' ) return false;
|
||||
++tail; // point to keyword
|
||||
// rest = length of (keyword + '=' + value) without the final newline
|
||||
const unsigned long long rest = ( buf + ( pos + rsize - 1 ) ) - tail;
|
||||
if( rest > 5 && std::memcmp( tail, "path=", 5 ) == 0 )
|
||||
{ if( path.size() && !permissive ) return false;
|
||||
path.assign( tail + 5, rest - 5 ); }
|
||||
else if( rest > 9 && std::memcmp( tail, "linkpath=", 9 ) == 0 )
|
||||
{ if( linkpath.size() && !permissive ) return false;
|
||||
linkpath.assign( tail + 9, rest - 9 ); }
|
||||
else if( rest > 5 && std::memcmp( tail, "size=", 5 ) == 0 )
|
||||
{
|
||||
if( size != 0 && !permissive ) return false;
|
||||
size = parse_decimal( tail + 5, &tail, rest - 5 );
|
||||
// parse error or size fits in ustar header
|
||||
if( size < 1ULL << 33 || tail != buf + ( pos + rsize - 1 ) ) return false;
|
||||
}
|
||||
else if( rest > 10 && std::memcmp( tail, "GNU.crc32=", 10 ) == 0 )
|
||||
{
|
||||
if( crc_present && !permissive ) return false;
|
||||
if( rsize != 22 ) return false;
|
||||
const uint32_t stored_crc = parse_record_crc( tail + 10 );
|
||||
const uint32_t computed_crc =
|
||||
crc32c.windowed_crc( (const uint8_t *)buf, pos + rsize - 9, edsize );
|
||||
crc_present = true;
|
||||
if( stored_crc != computed_crc ) return false;
|
||||
}
|
||||
pos += rsize;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int decode( const std::string & archive_name, const Arg_parser & parser,
|
||||
const int filenames, const int num_workers, const int debug_level,
|
||||
const bool keep_damaged, const bool listing, const bool missing_crc,
|
||||
|
@ -722,23 +643,27 @@ int decode( const std::string & archive_name, const Arg_parser & parser,
|
|||
if( !parse_records( infd, extended, header, permissive ) )
|
||||
{ show_error( "Error in extended records. Skipping to next header." );
|
||||
extended.reset(); gretval = 2; }
|
||||
else if( !extended.crc_present && missing_crc )
|
||||
else if( !extended.crc_present() && missing_crc )
|
||||
{ show_error( "Missing CRC in extended records.", 0, true ); return 2; }
|
||||
prev_extended = true;
|
||||
continue;
|
||||
}
|
||||
prev_extended = false;
|
||||
|
||||
if( extended.linkpath.empty() ) // copy linkpath from ustar header
|
||||
if( extended.linkpath().empty() ) // copy linkpath from ustar header
|
||||
{
|
||||
for( int i = 0; i < linkname_l && header[linkname_o+i]; ++i )
|
||||
extended.linkpath += header[linkname_o+i];
|
||||
while( extended.linkpath.size() > 1 && // trailing '/'
|
||||
extended.linkpath[extended.linkpath.size()-1] == '/' )
|
||||
extended.linkpath.resize( extended.linkpath.size() - 1 );
|
||||
int len = 0;
|
||||
while( len < linkname_l && header[linkname_o+len] ) ++len;
|
||||
while( len > 1 && header[linkname_o+len-1] == '/' ) --len; // trailing '/'
|
||||
if( len > 0 )
|
||||
{
|
||||
const uint8_t c = header[linkname_o+len]; header[linkname_o+len] = 0;
|
||||
extended.linkpath( (const char *)header + linkname_o );
|
||||
header[linkname_o+len] = c;
|
||||
}
|
||||
}
|
||||
|
||||
if( extended.path.empty() ) // copy path from ustar header
|
||||
if( extended.path().empty() ) // copy path from ustar header
|
||||
{
|
||||
char stored_name[prefix_l+1+name_l+1];
|
||||
int len = 0;
|
||||
|
@ -749,9 +674,9 @@ 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_slash( stored_name ) );
|
||||
}
|
||||
const char * const filename = extended.path.c_str();
|
||||
const char * const filename = extended.path().c_str();
|
||||
|
||||
bool skip = filenames > 0;
|
||||
if( skip )
|
||||
|
@ -765,9 +690,9 @@ int decode( const std::string & archive_name, const Arg_parser & parser,
|
|||
{ skip = false; name_pending[i] = false; break; }
|
||||
}
|
||||
|
||||
if( extended.size == 0 &&
|
||||
if( extended.file_size() == 0 &&
|
||||
( typeflag == tf_regular || typeflag == tf_hiperf ) )
|
||||
extended.size = parse_octal( header + size_o, size_l );
|
||||
extended.file_size( parse_octal( header + size_o, size_l ) );
|
||||
|
||||
if( listing || skip )
|
||||
retval = list_member( infd, extended, header, skip );
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue