1
0
Fork 0

Adding upstream version 0.17.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-17 21:15:00 +01:00
parent bb26c2917c
commit 739f200278
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
29 changed files with 2935 additions and 2272 deletions

View file

@ -1,18 +1,18 @@
/* Tarlz - Archiver with multimember lzip compression
Copyright (C) 2013-2019 Antonio Diaz Diaz.
/* Tarlz - Archiver with multimember lzip compression
Copyright (C) 2013-2020 Antonio Diaz Diaz.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _FILE_OFFSET_BITS 64
@ -39,9 +39,10 @@
namespace {
const Cl_options * gcl_opts = 0; // local vars needed by add_member_lz
enum { max_packet_size = 1 << 20 };
class Packet_courier;
Packet_courier * courierp = 0; // local vars needed by add_member_lz
Packet_courier * courierp = 0;
unsigned long long partial_data_size = 0; // size of current block
@ -156,7 +157,7 @@ public:
If filename.empty() (end of lzip member token), move to next queue. */
void receive_packet( const Ipacket * const ipacket )
{
if( ipacket->filename.size() )
if( !ipacket->filename.empty() )
slot_tally.get_slot(); // wait for a free slot
xlock( &imutex );
ipacket_queues[receive_worker_id].push( ipacket );
@ -184,7 +185,7 @@ public:
}
xunlock( &imutex );
if( ipacket )
{ if( ipacket->filename.size() ) slot_tally.leave_slot(); }
{ if( !ipacket->filename.empty() ) slot_tally.leave_slot(); }
else
{
// notify muxer when last worker exits
@ -270,13 +271,13 @@ int add_member_lz( const char * const filename, const struct stat *,
if( !fill_headers( filename, *extended, header, file_size, flag ) )
{ delete[] header; delete extended; return 0; }
if( solidity == bsolid &&
if( gcl_opts->solidity == bsolid &&
block_is_full( *extended, file_size, partial_data_size ) )
courierp->receive_packet( new Ipacket ); // end of group
courierp->receive_packet( new Ipacket( filename, file_size, extended, header ) );
if( solidity == no_solid ) // one tar member per group
if( gcl_opts->solidity == no_solid ) // one tar member per group
courierp->receive_packet( new Ipacket );
if( verbosity >= 1 ) std::fprintf( stderr, "%s\n", filename );
return 0;
@ -285,31 +286,30 @@ int add_member_lz( const char * const filename, const struct stat *,
struct Grouper_arg
{
const Cl_options * cl_opts;
Packet_courier * courier;
const Arg_parser * parser;
bool dereference;
};
/* Package metadata of the files to be archived and pass them to the
courier for distribution to workers. */
courier for distribution to workers.
*/
extern "C" void * grouper( void * arg )
{
const Grouper_arg & tmp = *(const Grouper_arg *)arg;
const Cl_options & cl_opts = *tmp.cl_opts;
Packet_courier & courier = *tmp.courier;
const Arg_parser & parser = *tmp.parser;
const bool dereference = tmp.dereference;
for( int i = 0; i < parser.arguments(); ++i ) // parse command line
for( int i = 0; i < cl_opts.parser.arguments(); ++i ) // parse command line
{
const int code = parser.code( i );
const std::string & arg = parser.argument( i );
const int code = cl_opts.parser.code( i );
const std::string & arg = cl_opts.parser.argument( i );
const char * filename = arg.c_str();
if( code == 'C' && chdir( filename ) != 0 )
{ show_file_error( filename, "Error changing working directory", errno );
cleanup_and_fail(); }
if( code ) continue; // skip options
if( parser.argument( i ).empty() ) continue; // skip empty names
if( cl_opts.parser.argument( i ).empty() ) continue; // skip empty names
std::string deslashed; // arg without trailing slashes
unsigned len = arg.size();
while( len > 1 && arg[len-1] == '/' ) --len;
@ -321,13 +321,13 @@ extern "C" void * grouper( void * arg )
{ show_file_error( filename, "Can't stat input file", errno );
set_error_status( 1 ); }
else if( nftw( filename, add_member_lz, 16,
dereference ? 0 : FTW_PHYS ) != 0 )
cleanup_and_fail(); // write error or oom
else if( solidity == dsolid ) // end of group
cl_opts.dereference ? 0 : FTW_PHYS ) != 0 )
cleanup_and_fail(); // write error or OOM
else if( cl_opts.solidity == dsolid ) // end of group
courier.receive_packet( new Ipacket );
}
if( solidity == bsolid && partial_data_size ) // finish last block
if( cl_opts.solidity == bsolid && partial_data_size ) // finish last block
{ partial_data_size = 0; courierp->receive_packet( new Ipacket ); }
courier.finish(); // no more packets to send
return 0;
@ -336,7 +336,8 @@ extern "C" void * grouper( void * arg )
/* Writes ibuf to encoder. To minimize dictionary size, it does not read
from encoder until encoder's input buffer is full or finish is true.
Sends opacket to courier and allocates new obuf each time obuf is full. */
Sends opacket to courier and allocates new obuf each time obuf is full.
*/
void loop_encode( const uint8_t * const ibuf, const int isize,
uint8_t * & obuf, int & opos, Packet_courier & courier,
LZ_Encoder * const encoder, const int worker_id,
@ -395,7 +396,8 @@ struct Worker_arg
/* Get ipackets from courier, compress headers and file data, and give the
opackets produced to courier. */
opackets produced to courier.
*/
extern "C" void * cworker( void * arg )
{
const Worker_arg & tmp = *(const Worker_arg *)arg;
@ -502,7 +504,8 @@ extern "C" void * cworker( void * arg )
/* Get from courier the processed and sorted packets, and write
their contents to the output archive. */
their contents to the output archive.
*/
void muxer( Packet_courier & courier, const int outfd )
{
while( true )
@ -521,24 +524,24 @@ void muxer( Packet_courier & courier, const int outfd )
// init the courier, then start the grouper and the workers and call the muxer
int encode_lz( const char * const archive_namep, const Arg_parser & parser,
int encode_lz( const Cl_options & cl_opts, const char * const archive_namep,
const int dictionary_size, const int match_len_limit,
const int num_workers, const int outfd, const int out_slots,
const int debug_level, const bool dereference )
const int outfd )
{
const int in_slots = 65536; // max small files (<=512B) in 64 MiB
const int num_workers = cl_opts.num_workers;
const int total_in_slots = ( INT_MAX / num_workers >= in_slots ) ?
num_workers * in_slots : INT_MAX;
gcl_opts = &cl_opts;
/* If an error happens after any threads have been started, exit must be
called before courier goes out of scope. */
Packet_courier courier( num_workers, total_in_slots, out_slots );
Packet_courier courier( num_workers, total_in_slots, cl_opts.out_slots );
courierp = &courier; // needed by add_member_lz
Grouper_arg grouper_arg;
grouper_arg.cl_opts = &cl_opts;
grouper_arg.courier = &courier;
grouper_arg.parser = &parser;
grouper_arg.dereference = dereference;
pthread_t grouper_thread;
int errcode = pthread_create( &grouper_thread, 0, grouper, &grouper_arg );
@ -582,7 +585,7 @@ int encode_lz( const char * const archive_namep, const Arg_parser & parser,
{ show_file_error( archive_namep, "Error closing archive", errno );
retval = 1; }
if( debug_level & 1 )
if( cl_opts.debug_level & 1 )
std::fprintf( stderr,
"any worker tried to consume from grouper %8u times\n"
"any worker had to wait %8u times\n"