diff options
Diffstat (limited to 'extended.cc')
-rw-r--r-- | extended.cc | 78 |
1 files changed, 59 insertions, 19 deletions
diff --git a/extended.cc b/extended.cc index 5440de7..5931be2 100644 --- a/extended.cc +++ b/extended.cc @@ -86,23 +86,6 @@ uint32_t parse_record_crc( const char * const ptr ) return crc; } -} // end namespace - - -const std::string Extended::crc_record( "22 GNU.crc32=00000000\n" ); - -void Extended::calculate_sizes() const - { - linkpath_recsize_ = linkpath_.size() ? record_size( 8, linkpath_.size() ) : 0; - path_recsize_ = path_.size() ? record_size( 4, path_.size() ) : 0; - file_size_recsize_ = - ( file_size_ > 0 ) ? record_size( 4, decimal_digits( file_size_ ) ) : 0; - edsize_ = linkpath_recsize_ + path_recsize_ + file_size_recsize_ + - crc_record.size(); - padded_edsize_ = round_up( edsize_ ); - full_size_ = header_size + padded_edsize_; - } - unsigned char xdigit( const unsigned value ) { @@ -144,6 +127,23 @@ bool print_record( char * const buf, const int size, return pos == size; } +} // end namespace + + +const std::string Extended::crc_record( "22 GNU.crc32=00000000\n" ); + +void Extended::calculate_sizes() const + { + linkpath_recsize_ = linkpath_.size() ? record_size( 8, linkpath_.size() ) : 0; + path_recsize_ = path_.size() ? record_size( 4, path_.size() ) : 0; + file_size_recsize_ = + ( file_size_ > 0 ) ? record_size( 4, decimal_digits( file_size_ ) ) : 0; + edsize_ = linkpath_recsize_ + path_recsize_ + file_size_recsize_ + + crc_record.size(); + padded_edsize_ = round_up( edsize_ ); + full_size_ = header_size + padded_edsize_; + } + // Returns the extended block size, or -1 if error. long long Extended::format_block( Resizable_buffer & rbuf ) const @@ -206,8 +206,12 @@ bool Extended::parse( const char * const buf, const unsigned long long edsize, path_.assign( remove_leading_dotslash( path_.c_str() ) ); } else if( rest > 9 && std::memcmp( tail, "linkpath=", 9 ) == 0 ) - { if( linkpath_.size() && !permissive ) return false; - linkpath_.assign( tail + 9, rest - 9 ); } + { + if( linkpath_.size() && !permissive ) return false; + unsigned long long len = rest - 9; + while( len > 1 && tail[9+len-1] == '/' ) --len; // trailing '/' + linkpath_.assign( tail + 9, len ); + } else if( rest > 5 && std::memcmp( tail, "size=", 5 ) == 0 ) { if( file_size_ != 0 && !permissive ) return false; @@ -235,3 +239,39 @@ bool Extended::parse( const char * const buf, const unsigned long long edsize, } return true; } + + +// if needed, copy linkpath, path and file_size from ustar header +void Extended::fill_from_ustar( const Tar_header header ) + { + if( linkpath_.empty() ) // copy linkpath from ustar header + { + 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 ) + { + linkpath_.assign( (const char *)header + linkname_o, len ); + full_size_ = -1; + } + } + + if( path_.empty() ) // copy path from ustar header + { + char stored_name[prefix_l+1+name_l+1]; + int len = 0; + while( len < prefix_l && header[prefix_o+len] ) + { stored_name[len] = header[prefix_o+len]; ++len; } + if( len && header[name_o] ) stored_name[len++] = '/'; + for( int i = 0; i < name_l && header[name_o+i]; ++i ) + { stored_name[len] = header[name_o+i]; ++len; } + while( len > 0 && stored_name[len-1] == '/' ) --len; // trailing '/' + stored_name[len] = 0; + path( remove_leading_dotslash( stored_name ) ); + } + + const Typeflag typeflag = (Typeflag)header[typeflag_o]; + if( file_size_ == 0 && // copy file_size from ustar header + ( typeflag == tf_regular || typeflag == tf_hiperf ) ) + file_size( parse_octal( header + size_o, size_l ) ); + } |