1
0
Fork 0

Merging upstream version 0.11.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-17 21:12:14 +01:00
parent 3b818501c2
commit 5db1949a73
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
18 changed files with 1504 additions and 654 deletions

View file

@ -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;