diff options
Diffstat (limited to 'list_lz.cc')
-rw-r--r-- | list_lz.cc | 267 |
1 files changed, 89 insertions, 178 deletions
@@ -36,6 +36,8 @@ #include "tarlz.h" +namespace { + // Returns the number of bytes really read. // If (returned value < size) and (errno == 0), means EOF was reached. // @@ -55,7 +57,7 @@ int preadblock( const int fd, uint8_t * const buf, const int size, return sz; } - +/* // Returns the number of bytes really written. // If (returned value < size), it is always an error. // @@ -73,183 +75,7 @@ int pwriteblock( const int fd, const uint8_t * const buf, const int size, } return sz; } - - -void xinit_mutex( pthread_mutex_t * const mutex ) - { - const int errcode = pthread_mutex_init( mutex, 0 ); - if( errcode ) - { show_error( "pthread_mutex_init", errcode ); cleanup_and_fail(); } - } - -void xinit_cond( pthread_cond_t * const cond ) - { - const int errcode = pthread_cond_init( cond, 0 ); - if( errcode ) - { show_error( "pthread_cond_init", errcode ); cleanup_and_fail(); } - } - - -void xdestroy_mutex( pthread_mutex_t * const mutex ) - { - const int errcode = pthread_mutex_destroy( mutex ); - if( errcode ) - { show_error( "pthread_mutex_destroy", errcode ); cleanup_and_fail(); } - } - -void xdestroy_cond( pthread_cond_t * const cond ) - { - const int errcode = pthread_cond_destroy( cond ); - if( errcode ) - { show_error( "pthread_cond_destroy", errcode ); cleanup_and_fail(); } - } - - -void xlock( pthread_mutex_t * const mutex ) - { - const int errcode = pthread_mutex_lock( mutex ); - if( errcode ) - { show_error( "pthread_mutex_lock", errcode ); cleanup_and_fail(); } - } - - -void xunlock( pthread_mutex_t * const mutex ) - { - const int errcode = pthread_mutex_unlock( mutex ); - if( errcode ) - { show_error( "pthread_mutex_unlock", errcode ); cleanup_and_fail(); } - } - - -void xwait( pthread_cond_t * const cond, pthread_mutex_t * const mutex ) - { - const int errcode = pthread_cond_wait( cond, mutex ); - if( errcode ) - { show_error( "pthread_cond_wait", errcode ); cleanup_and_fail(); } - } - - -void xsignal( pthread_cond_t * const cond ) - { - const int errcode = pthread_cond_signal( cond ); - if( errcode ) - { show_error( "pthread_cond_signal", errcode ); cleanup_and_fail(); } - } - - -void xbroadcast( pthread_cond_t * const cond ) - { - const int errcode = pthread_cond_broadcast( cond ); - if( errcode ) - { show_error( "pthread_cond_broadcast", errcode ); cleanup_and_fail(); } - } - - -bool check_skip_filename( const Arg_parser & parser, - std::vector< char > & name_pending, - const char * const filename, const int filenames ) - { - if( Exclude::excluded( filename ) ) return true; // skip excluded files - bool skip = filenames > 0; - if( skip ) - for( int i = 0; i < parser.arguments(); ++i ) - if( !parser.code( i ) && parser.argument( i ).size() ) - { - const char * const name = - 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; } - } - return skip; - } - - -/* Return value: 0 = OK, 1 = damaged member, 2 = fatal error. */ -int archive_read_lz( LZ_Decoder * const decoder, const int infd, - long long & file_pos, const long long member_end, - const long long cdata_size, uint8_t * const buf, - const int size, const char ** msg ) - { - int sz = 0; - - while( sz < size ) - { - const int rd = LZ_decompress_read( decoder, buf + sz, size - sz ); - if( rd < 0 ) - { *msg = LZ_strerror( LZ_decompress_errno( decoder ) ); return 1; } - if( rd == 0 && LZ_decompress_finished( decoder ) == 1 ) - { *msg = end_msg; return 2; } - sz += rd; - if( sz < size && LZ_decompress_write_size( decoder ) > 0 ) - { - const long long ibuf_size = 16384; // try 65536 - uint8_t ibuf[ibuf_size]; - const long long rest = ( file_pos < member_end ) ? - member_end - file_pos : cdata_size - file_pos; - const int rsize = std::min( LZ_decompress_write_size( decoder ), - (int)std::min( ibuf_size, rest ) ); - if( rsize <= 0 ) LZ_decompress_finish( decoder ); - else - { - const int rd = preadblock( infd, ibuf, rsize, file_pos ); - if( LZ_decompress_write( decoder, ibuf, rd ) != rd ) - internal_error( "library error (LZ_decompress_write)." ); - file_pos += rd; - if( rd < rsize ) - { - LZ_decompress_finish( decoder ); - if( errno ) { *msg = "Error reading archive"; return 2; } - } - } - } - } - return 0; - } - - -int parse_records_lz( LZ_Decoder * const decoder, const int infd, - long long & file_pos, const long long member_end, - const long long cdata_size, long long & data_pos, - Extended & extended, const Tar_header header, - Resizable_buffer & rbuf, const char ** msg, - const bool permissive ) - { - const long long edsize = parse_octal( header + size_o, size_l ); - const long long bufsize = round_up( edsize ); - if( edsize <= 0 || edsize >= 1LL << 33 || bufsize >= INT_MAX ) - return 1; // overflow or no extended data - if( !rbuf.resize( bufsize ) ) return 1; // extended records buffer - int retval = archive_read_lz( decoder, infd, file_pos, member_end, - cdata_size, (uint8_t *)rbuf(), bufsize, msg ); - if( retval == 0 ) - { if( extended.parse( rbuf(), edsize, permissive ) ) data_pos += bufsize; - else retval = 1; } - return retval; - } - - -int skip_member_lz( LZ_Decoder * const decoder, const int infd, - long long & file_pos, const long long member_end, - const long long cdata_size, long long & data_pos, - long long rest, const char ** msg ) - { - const int bufsize = 32 * header_size; - uint8_t buf[bufsize]; - while( rest > 0 ) // skip tar member - { - const int rsize = ( rest >= bufsize ) ? bufsize : rest; - const int ret = archive_read_lz( decoder, infd, file_pos, member_end, - cdata_size, buf, rsize, msg ); - if( ret != 0 ) return ret; - data_pos += rsize; - rest -= rsize; - } - return 0; - } - - -namespace { +*/ struct Packet // member name and metadata or error message { @@ -606,6 +432,91 @@ void muxer( const char * const archive_namep, Packet_courier & courier ) } // end namespace +/* Read 'size' decompressed bytes from the archive. + Return value: 0 = OK, 1 = damaged member, 2 = fatal error. */ +int archive_read_lz( LZ_Decoder * const decoder, const int infd, + long long & file_pos, const long long member_end, + const long long cdata_size, uint8_t * const buf, + const int size, const char ** msg ) + { + int sz = 0; + + while( sz < size ) + { + const int rd = LZ_decompress_read( decoder, buf + sz, size - sz ); + if( rd < 0 ) + { *msg = LZ_strerror( LZ_decompress_errno( decoder ) ); return 1; } + if( rd == 0 && LZ_decompress_finished( decoder ) == 1 ) + { *msg = end_msg; return 2; } + sz += rd; + if( sz < size && LZ_decompress_write_size( decoder ) > 0 ) + { + const long long ibuf_size = 16384; // try 65536 + uint8_t ibuf[ibuf_size]; + const long long rest = ( file_pos < member_end ) ? + member_end - file_pos : cdata_size - file_pos; + const int rsize = std::min( LZ_decompress_write_size( decoder ), + (int)std::min( ibuf_size, rest ) ); + if( rsize <= 0 ) LZ_decompress_finish( decoder ); + else + { + const int rd = preadblock( infd, ibuf, rsize, file_pos ); + if( LZ_decompress_write( decoder, ibuf, rd ) != rd ) + internal_error( "library error (LZ_decompress_write)." ); + file_pos += rd; + if( rd < rsize ) + { + LZ_decompress_finish( decoder ); + if( errno ) { *msg = "Error reading archive"; return 2; } + } + } + } + } + return 0; + } + + +int parse_records_lz( LZ_Decoder * const decoder, const int infd, + long long & file_pos, const long long member_end, + const long long cdata_size, long long & data_pos, + Extended & extended, const Tar_header header, + Resizable_buffer & rbuf, const char ** msg, + const bool permissive ) + { + const long long edsize = parse_octal( header + size_o, size_l ); + const long long bufsize = round_up( edsize ); + if( edsize <= 0 || edsize >= 1LL << 33 || bufsize >= INT_MAX ) + return 1; // overflow or no extended data + if( !rbuf.resize( bufsize ) ) return 1; // extended records buffer + int retval = archive_read_lz( decoder, infd, file_pos, member_end, + cdata_size, (uint8_t *)rbuf(), bufsize, msg ); + if( retval == 0 ) + { if( extended.parse( rbuf(), edsize, permissive ) ) data_pos += bufsize; + else retval = 1; } + return retval; + } + + +int skip_member_lz( LZ_Decoder * const decoder, const int infd, + long long & file_pos, const long long member_end, + const long long cdata_size, long long & data_pos, + long long rest, const char ** msg ) + { + const int bufsize = 32 * header_size; + uint8_t buf[bufsize]; + while( rest > 0 ) // skip tar member + { + const int rsize = ( rest >= bufsize ) ? bufsize : rest; + const int ret = archive_read_lz( decoder, infd, file_pos, member_end, + cdata_size, buf, rsize, msg ); + if( ret != 0 ) return ret; + data_pos += rsize; + rest -= rsize; + } + return 0; + } + + // init the courier, then start the workers and call the muxer. int list_lz( const char * const archive_namep, const Arg_parser & parser, std::vector< char > & name_pending, const Lzip_index & lzip_index, |