Merging upstream version 0.11.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
3b818501c2
commit
5db1949a73
18 changed files with 1504 additions and 654 deletions
68
list_lz.cc
68
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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue