summaryrefslogtreecommitdiffstats
path: root/list_lz.cc
diff options
context:
space:
mode:
Diffstat (limited to 'list_lz.cc')
-rw-r--r--list_lz.cc68
1 files changed, 27 insertions, 41 deletions
diff --git a/list_lz.cc b/list_lz.cc
index 79d500c..23b6e7c 100644
--- a/list_lz.cc
+++ b/list_lz.cc
@@ -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;