diff options
Diffstat (limited to '')
-rw-r--r-- | list_lz.cc | 68 |
1 files changed, 27 insertions, 41 deletions
@@ -75,22 +75,6 @@ int pwriteblock( const int fd, const uint8_t * const buf, const int size, } -namespace { - -// This can be called from any thread, main thread or sub-threads alike, -// since they all call common helper functions that call cleanup_and_fail() -// in case of an error. -// -void cleanup_and_fail( const int retval = 2 ) - { - // only one thread can delete and exit - static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - - pthread_mutex_lock( &mutex ); // ignore errors to avoid loop - std::exit( retval ); - } - - void xinit_mutex( pthread_mutex_t * const mutex ) { const int errcode = pthread_mutex_init( mutex, 0 ); @@ -161,6 +145,8 @@ void xbroadcast( pthread_cond_t * const cond ) } +namespace { + struct Packet // member name and metadata or error message { enum Status { ok, member_done, error }; @@ -262,8 +248,8 @@ public: return true; } - // deliver a packet to muxer - // if packet.status == Packet::member_done, move to next queue + /* Deliver a packet to muxer. + If packet.status == Packet::member_done, move to next queue. */ Packet * deliver_packet() { Packet * opacket = 0; @@ -425,9 +411,9 @@ struct Worker_arg }; - // read lzip members from archive, list their tar members, and - // give the produced packets to courier. -extern "C" void * dworker_l( void * arg ) +/* Read lzip members from archive, list their tar members, and give the + packets produced to courier. */ +extern "C" void * tworker( void * arg ) { const Worker_arg & tmp = *(const Worker_arg *)arg; const Lzip_index & lzip_index = *tmp.lzip_index; @@ -441,12 +427,12 @@ extern "C" void * dworker_l( void * arg ) const int missing_crc = tmp.missing_crc; const bool permissive = tmp.permissive; + Resizable_buffer rbuf( initial_line_length ); LZ_Decoder * const decoder = LZ_decompress_open(); - if( !decoder || LZ_decompress_errno( decoder ) != LZ_ok ) - { show_error( "Not enough memory." ); cleanup_and_fail(); } + if( !rbuf.size() || !decoder || LZ_decompress_errno( decoder ) != LZ_ok ) + { show_error( mem_msg ); cleanup_and_fail(); } const long long cdata_size = lzip_index.cdata_size(); - Resizable_buffer rbuf( initial_line_length ); bool master = false; for( long i = worker_id; !master && i < lzip_index.members(); i += num_workers ) { @@ -498,7 +484,7 @@ extern "C" void * dworker_l( void * arg ) { if( prev_extended ) { show_error( "Format violation: global header after extended header." ); - cleanup_and_fail(); } + cleanup_and_fail( 2 ); } Extended dummy; // global headers are parsed and ignored const int ret = parse_records_lz( decoder, infd, file_pos, member_end, cdata_size, data_pos, dummy, header, &msg, true ); @@ -572,17 +558,17 @@ extern "C" void * dworker_l( void * arg ) { 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; } @@ -602,7 +588,7 @@ extern "C" void * dworker_l( void * arg ) else if( retval > 0 ) { show_error( msg ); show_error( "Error is not recoverable: exiting now." ); - cleanup_and_fail(); } + cleanup_and_fail( 2 ); } } } if( LZ_decompress_close( decoder ) < 0 ) @@ -617,9 +603,9 @@ done: } - // get from courier the processed and sorted packets, and print - // the member lines on stdout or the diagnostics on stderr. -void muxer( Packet_courier & courier ) +/* Get from courier the processed and sorted packets, and print + the member lines on stdout or the diagnostics on stderr. */ +bool muxer( Packet_courier & courier ) { while( true ) { @@ -627,14 +613,15 @@ void muxer( Packet_courier & courier ) if( !opacket ) break; // queue is empty. all workers exited if( opacket->status == Packet::error ) - { show_error( opacket->line.c_str() ); cleanup_and_fail(); } + { show_error( opacket->line.c_str() ); return false; } if( opacket->line.size() ) { std::fputs( opacket->line.c_str(), stdout ); std::fflush( stdout ); } delete opacket; } if( !courier.mastership_granted() ) // no worker found EOF blocks - { show_error( "Archive ends unexpectedly." ); cleanup_and_fail(); } + { show_error( "Archive ends unexpectedly." ); return false; } + return true; } } // end namespace @@ -651,8 +638,7 @@ int list_lz( const Arg_parser & parser, std::vector< char > & name_pending, Worker_arg * worker_args = new( std::nothrow ) Worker_arg[num_workers]; pthread_t * worker_threads = new( std::nothrow ) pthread_t[num_workers]; - if( !worker_args || !worker_threads ) - { show_error( "Not enough memory." ); cleanup_and_fail(); } + if( !worker_args || !worker_threads ) { show_error( mem_msg ); return 1; } for( int i = 0; i < num_workers; ++i ) { worker_args[i].lzip_index = &lzip_index; @@ -666,25 +652,25 @@ int list_lz( const Arg_parser & parser, std::vector< char > & name_pending, worker_args[i].missing_crc = missing_crc; worker_args[i].permissive = permissive; const int errcode = - pthread_create( &worker_threads[i], 0, dworker_l, &worker_args[i] ); + pthread_create( &worker_threads[i], 0, tworker, &worker_args[i] ); if( errcode ) - { show_error( "Can't create worker threads", errcode ); cleanup_and_fail(); } + { show_error( "Can't create worker threads", errcode ); return 1; } } - muxer( courier ); + if( !muxer( courier ) ) return 2; for( int i = num_workers - 1; i >= 0; --i ) { const int errcode = pthread_join( worker_threads[i], 0 ); if( errcode ) - { show_error( "Can't join worker threads", errcode ); cleanup_and_fail(); } + { show_error( "Can't join worker threads", errcode ); return 1; } } delete[] worker_threads; delete[] worker_args; int retval = 0; 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." ); retval = 1; |