1
0
Fork 0

Adding upstream version 0.2.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-24 03:23:29 +01:00
parent 63d771d1a1
commit e748b84dff
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
21 changed files with 1267 additions and 2163 deletions

475
main.cc
View file

@ -1,6 +1,6 @@
/* Plzip - A parallel version of the lzip data compressor
Copyright (C) 2009 Laszlo Ersek.
Copyright (C) 2009 Antonio Diaz Diaz.
Copyright (C) 2009, 2010 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
@ -29,14 +29,14 @@
#include <cerrno>
#include <climits>
#include <csignal>
#include <cstdarg> /* va_list */
#include <cstdarg>
#include <cstddef>
#include <cstdio> /* flockfile() */
#include <cstdio>
#include <cstdlib>
#include <cstring> /* strerror() */
#include <cstring>
#include <string>
#include <vector>
#include <fcntl.h> /* open() */
#include <fcntl.h>
#include <stdint.h>
#include <pthread.h>
#include <unistd.h>
@ -63,8 +63,6 @@
#endif
void internal_error( const char * msg );
int readblock( const int fd, char * buf, const int size ) throw();
int writeblock( const int fd, const char * buf, const int size ) throw();
namespace {
@ -72,7 +70,7 @@ namespace {
const char * invocation_name = 0;
const char * const Program_name = "Plzip";
const char * const program_name = "plzip";
const char * const program_year = "2009";
const char * const program_year = "2010";
struct { const char * from; const char * to; } const known_extensions[] = {
{ ".lz", "" },
@ -89,7 +87,6 @@ enum Mode { m_compress = 0, m_decompress, m_test };
std::string output_filename;
int outhandle = -1;
int verbosity = 0;
bool delete_output_on_interrupt = false;
class Pretty_print
@ -137,13 +134,13 @@ void show_help() throw()
// std::printf( " -b, --member-size=<n> set member size limit in bytes\n" );
std::printf( " -c, --stdout send output to standard output\n" );
std::printf( " -d, --decompress decompress\n" );
// std::printf( " -f, --force overwrite existing output files\n" );
// std::printf( " -k, --keep keep (don't delete) input files\n" );
// std::printf( " -m, --match-length=<n> set match length limit in bytes [80]\n" );
std::printf( " -f, --force overwrite existing output files\n" );
std::printf( " -k, --keep keep (don't delete) input files\n" );
std::printf( " -m, --match-length=<n> set match length limit in bytes [80]\n" );
std::printf( " -n, --threads=<n> set the number of (de)compression threads\n" );
// std::printf( " -o, --output=<file> if reading stdin, place the output into <file>\n" );
std::printf( " -o, --output=<file> if reading stdin, place the output into <file>\n" );
std::printf( " -q, --quiet suppress all messages\n" );
// std::printf( " -s, --dictionary-size=<n> set dictionary size limit in bytes [8MiB]\n" );
std::printf( " -s, --dictionary-size=<n> set dictionary size limit in bytes [8MiB]\n" );
// std::printf( " -S, --volume-size=<n> set volume size limit in bytes\n" );
std::printf( " -t, --test test compressed file integrity\n" );
std::printf( " -v, --verbose be verbose (a 2nd -v gives more)\n" );
@ -159,7 +156,7 @@ void show_help() throw()
std::printf( "Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n" );
std::printf( "Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\n" );
std::printf( "\nReport bugs to lzip-bug@nongnu.org\n" );
std::printf( "Lzip home page: http://www.nongnu.org/lzip/lzip.html\n" );
std::printf( "Plzip home page: http://www.nongnu.org/lzip/plzip.html\n" );
}
@ -209,7 +206,7 @@ long long getnum( const char * ptr, const int bs = 0,
break;
case 'k': if( factor == 1000 ) exponent = 1; else bad_multiplier = true;
break;
default: bad_multiplier = true;
default : bad_multiplier = true;
}
if( bad_multiplier )
{
@ -236,9 +233,10 @@ int get_dict_size( const char * arg ) throw()
{
char *tail;
int bits = std::strtol( arg, &tail, 0 );
if( bits >= min_dictionary_bits && bits <= max_dictionary_bits && *tail == 0 )
if( bits >= LZ_min_dictionary_bits() &&
bits <= LZ_max_dictionary_bits() && *tail == 0 )
return ( 1 << bits );
return getnum( arg, 0, min_dictionary_size, max_dictionary_size );
return getnum( arg, 0, LZ_min_dictionary_size(), LZ_max_dictionary_size() );
}
@ -380,75 +378,59 @@ void cleanup_and_fail( const int retval ) throw()
// Set permissions, owner and times.
void close_and_set_permissions( const struct stat * in_statsp, int * retvalp )
void close_and_set_permissions( const struct stat * const in_statsp )
{
int tmp = 0;
bool error = false;
if( in_statsp )
{
if( fchmod( outhandle, in_statsp->st_mode ) != 0 ) tmp = 1;
if( !tmp ) (void)fchown( outhandle, in_statsp->st_uid, in_statsp->st_gid );
if( fchmod( outhandle, in_statsp->st_mode ) != 0 ) error = true;
else (void)fchown( outhandle, in_statsp->st_uid, in_statsp->st_gid );
// fchown will in many cases return with EPERM, which can be safely ignored.
}
if( close( outhandle ) == 0 ) outhandle = -1;
else cleanup_and_fail( 1 );
delete_output_on_interrupt = false;
if( !in_statsp ) return;
if( !tmp )
if( !error )
{
struct utimbuf t;
t.actime = in_statsp->st_atime;
t.modtime = in_statsp->st_mtime;
if( utime( output_filename.c_str(), &t ) != 0 ) tmp = 1;
if( utime( output_filename.c_str(), &t ) != 0 ) error = true;
}
if( tmp )
if( error )
{
if( tmp > *retvalp ) *retvalp = tmp;
show_error( "I can't change output file attributes." );
cleanup_and_fail( *retvalp );
cleanup_and_fail( 1 );
}
}
int decompress( const int inhandle, const Pretty_print & pp,
const bool testing )
int do_decompress( LZ_Decoder * const decoder, const int inhandle,
const Pretty_print & pp, const bool testing )
{
void * decoder = LZ_decompress_open();
if( !decoder || LZ_decompress_errno( decoder ) != LZ_ok )
{
LZ_decompress_close( decoder );
pp( "not enough memory. Find a machine with more memory" );
return 1;
}
if( verbosity >= 1 ) pp();
const int in_buffer_size = 65536, out_buffer_size = 8 * in_buffer_size;
uint8_t in_buffer[in_buffer_size], out_buffer[out_buffer_size];
int in_pos = 0, in_stream_pos = 0;
bool finished = false;
if( verbosity >= 1 ) pp();
while( true )
{
int in_size = 0;
if( !finished )
int in_size = std::min( LZ_decompress_write_size( decoder ), in_buffer_size );
if( in_size > 0 )
{
if( in_stream_pos == 0 )
in_stream_pos = readblock( inhandle, (char *)in_buffer, in_buffer_size );
if( in_pos < in_stream_pos )
{
in_size = LZ_decompress_write( decoder, in_buffer + in_pos, in_stream_pos - in_pos );
in_pos += in_size;
}
if( in_pos >= in_stream_pos )
{
if( in_stream_pos < in_buffer_size )
{ finished = true; LZ_decompress_finish( decoder ); }
in_stream_pos = 0; in_pos = 0;
}
const int max_in_size = in_size;
in_size = readblock( inhandle, (char *)in_buffer, max_in_size );
if( in_size != max_in_size && errno )
{ pp(); show_error( "read error", errno ); return 1; }
if( in_size == 0 ) LZ_decompress_finish( decoder );
else if( in_size != LZ_decompress_write( decoder, in_buffer, in_size ) )
internal_error( "library error (LZ_decompress_write)" );
}
int out_size = LZ_decompress_read( decoder, out_buffer, out_buffer_size );
// std::fprintf( stderr, "%5d in_size, %6d out_size.\n", in_size, out_size );
if( out_size < 0 )
{
const LZ_errno lz_errno = LZ_decompress_errno( decoder );
const LZ_Errno lz_errno = LZ_decompress_errno( decoder );
if( lz_errno == LZ_header_error )
{
if( LZ_decompress_total_out_size( decoder ) > 0 )
@ -461,15 +443,18 @@ int decompress( const int inhandle, const Pretty_print & pp,
pp( "not enough memory. Find a machine with more memory" );
return 1;
}
pp();
if( lz_errno == LZ_unexpected_eof )
{
if( verbosity >= 0 )
{ pp();
std::fprintf( stderr, "file ends unexpectedly at pos %lld\n",
LZ_decompress_total_in_size( decoder ) ); }
std::fprintf( stderr, "file ends unexpectedly at pos %lld\n",
LZ_decompress_total_in_size( decoder ) );
return 2;
}
pp(); show_error( "read error", errno ); return 1;
if( verbosity >= 0 )
std::fprintf( stderr, "LZ_decompress_read error: %s.\n",
LZ_strerror( LZ_decompress_errno( decoder ) ) );
return 1;
}
else if( out_size > 0 && outhandle >= 0 )
{
@ -478,17 +463,33 @@ int decompress( const int inhandle, const Pretty_print & pp,
{ pp(); show_error( "write error", errno ); return 1; }
}
if( LZ_decompress_finished( decoder ) == 1 ) break;
if( finished && in_size == 0 && out_size == 0 )
if( in_size == 0 && out_size == 0 )
internal_error( "library error (LZ_decompress_read)" );
}
if( verbosity >= 1 )
{ if( testing ) std::fprintf( stderr, "ok\n" );
else std::fprintf( stderr, "done\n" ); }
LZ_decompress_close( decoder );
return 0;
}
int decompress( const int inhandle, const Pretty_print & pp,
const bool testing )
{
LZ_Decoder * const decoder = LZ_decompress_open();
int retval;
if( !decoder || LZ_decompress_errno( decoder ) != LZ_ok )
{
pp( "not enough memory" );
retval = 1;
}
else retval = do_decompress( decoder, inhandle, pp, testing );
LZ_decompress_close( decoder );
return retval;
}
extern "C" void signal_handler( int ) throw()
{
show_error( "Control-C or similar caught, quitting." );
@ -506,6 +507,9 @@ void set_signals() throw()
} // end namespace
int verbosity = 0;
void Pretty_print::operator()( const char * const msg ) const throw()
{
if( verbosity >= 0 )
@ -523,6 +527,30 @@ void Pretty_print::operator()( const char * const msg ) const throw()
}
void show_error( const char * msg, const int errcode, const bool help ) throw()
{
if( verbosity >= 0 )
{
if( msg && msg[0] != 0 )
{
std::fprintf( stderr, "%s: %s", program_name, msg );
if( errcode > 0 ) std::fprintf( stderr, ": %s", std::strerror( errcode ) );
std::fprintf( stderr, "\n" );
}
if( help && invocation_name && invocation_name[0] != 0 )
std::fprintf( stderr, "Try `%s --help' for more information.\n", invocation_name );
}
}
void internal_error( const char * msg )
{
std::string s( "internal error: " ); s += msg;
show_error( s.c_str() );
std::exit( 3 );
}
/* Private stuff needed by fatal(). */
static pthread_t main_thread;
@ -530,25 +558,21 @@ static pid_t pid;
/* Public utility variables and functions. */
void *(*mallocf)(size_t size);
void (*freef)(void *ptr);
/*
This can be called from any thread, main thread or sub-threads alike, since
they all call common helper functions that call fatal() in case of an error.
*/
void
fatal(void)
void fatal()
{
if( pthread_equal(pthread_self(), main_thread) )
cleanup_and_fail( 1 );
else
{
if (0 == kill(pid, SIGUSR1))
if( 0 == kill(pid, SIGUSR1) )
pthread_exit(0);
}
_exit(EXIT_FAILURE);
_exit( 1 );
}
@ -572,67 +596,51 @@ fail(const char *fmt, int err, ...)
}
void *
xalloc(size_t size)
{
void *ret = (*mallocf)(size);
if (0 == ret) {
fail("(*mallocf)()", errno);
}
return ret;
}
void
xinit(Cond *cond)
{
int ret;
pthread_mutexattr_t attr;
ret = pthread_mutexattr_init(&attr);
if (0 != ret) {
int ret = pthread_mutexattr_init(&attr);
if( ret != 0 ) {
fail("pthread_mutexattr_init()", ret);
}
ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
if (0 != ret) {
if( ret != 0 ) {
fail("pthread_mutexattr_settype()", ret);
}
ret = pthread_mutex_init(&cond->lock, &attr);
if (0 != ret) {
if( ret != 0 ) {
fail("pthread_mutex_init()", ret);
}
ret = pthread_mutexattr_destroy(&attr);
if (0 != ret) {
if( ret != 0 ) {
fail("pthread_mutexattr_destroy()", ret);
}
ret = pthread_cond_init(&cond->cond, 0);
if (0 != ret) {
if( ret != 0 ) {
fail("pthread_cond_init()", ret);
}
cond->ccount = 0lu;
cond->wcount = 0lu;
cond->ccount = 0;
cond->wcount = 0;
}
void
xdestroy(Cond *cond)
{
int ret;
ret = pthread_cond_destroy(&cond->cond);
if (0 != ret) {
int ret = pthread_cond_destroy(&cond->cond);
if( ret != 0 ) {
fail("pthread_cond_destroy()", ret);
}
ret = pthread_mutex_destroy(&cond->lock);
if (0 != ret) {
if( ret != 0 ) {
fail("pthread_mutex_destroy()", ret);
}
}
@ -641,10 +649,8 @@ xdestroy(Cond *cond)
void
xlock(Cond *cond)
{
int ret;
ret = pthread_mutex_lock(&cond->lock);
if (0 != ret) {
int ret = pthread_mutex_lock(&cond->lock);
if( ret != 0 ) {
fail("pthread_mutex_lock()", ret);
}
}
@ -661,10 +667,8 @@ xlock_pred(Cond *cond)
void
xunlock(Cond *cond)
{
int ret;
ret = pthread_mutex_unlock(&cond->lock);
if (0 != ret) {
int ret = pthread_mutex_unlock(&cond->lock);
if( ret != 0 ) {
fail("pthread_mutex_unlock()", ret);
}
}
@ -673,11 +677,9 @@ xunlock(Cond *cond)
void
xwait(Cond *cond)
{
int ret;
++cond->wcount;
ret = pthread_cond_wait(&cond->cond, &cond->lock);
if (0 != ret) {
int ret = pthread_cond_wait(&cond->cond, &cond->lock);
if( ret != 0 ) {
fail("pthread_cond_wait()", ret);
}
++cond->ccount;
@ -687,10 +689,8 @@ xwait(Cond *cond)
void
xsignal(Cond *cond)
{
int ret;
ret = pthread_cond_signal(&cond->cond);
if (0 != ret) {
int ret = pthread_cond_signal(&cond->cond);
if( ret != 0 ) {
fail("pthread_cond_signal()", ret);
}
}
@ -699,10 +699,8 @@ xsignal(Cond *cond)
void
xbroadcast(Cond *cond)
{
int ret;
ret = pthread_cond_broadcast(&cond->cond);
if (0 != ret) {
int ret = pthread_cond_broadcast(&cond->cond);
if( ret != 0 ) {
fail("pthread_cond_broadcast()", ret);
}
}
@ -711,10 +709,8 @@ xbroadcast(Cond *cond)
void
xcreate(pthread_t *thread, void *(*routine)(void *), void *arg)
{
int ret;
ret = pthread_create(thread, 0, routine, arg);
if (0 != ret) {
int ret = pthread_create(thread, 0, routine, arg);
if( ret != 0 ) {
fail("pthread_create()", ret);
}
}
@ -723,10 +719,8 @@ xcreate(pthread_t *thread, void *(*routine)(void *), void *arg)
void
xjoin(pthread_t thread)
{
int ret;
ret = pthread_join(thread, 0);
if (0 != ret) {
int ret = pthread_join(thread, 0);
if( ret != 0 ) {
fail("pthread_join()", ret);
}
}
@ -735,7 +729,7 @@ xjoin(pthread_t thread)
void
xraise(int sig)
{
if (-1 == kill(pid, sig)) {
if( -1 == kill(pid, sig) ) {
fail("kill()", errno);
}
}
@ -743,59 +737,11 @@ xraise(int sig)
/* Private stuff part 2. */
struct Opts
{
unsigned num_worker; /* Start this many worker threads. */
unsigned clidx; /* Compression level index in [0u .. 8u]. */
int print_cctrs; /* Print condition variable counters. */
};
/* Backlog factor for all workers together. */
static const unsigned blf = 3u;
/* Separator characters in environment variable values. No escaping. */
static const char envsep[] = " \t";
static void *
trace_malloc(size_t size)
{
void *ret;
int save_errno = 0;
ret = malloc(size);
if (0 == ret) {
save_errno = errno;
}
if (0 > fprintf(stderr, "%lu: malloc(%lu) == %p\n", (long unsigned)pid,
(long unsigned)size, ret)
) {
fatal();
}
if (0 == ret) {
errno = save_errno;
}
return ret;
}
static void
trace_free(void *ptr)
{
if (0 > fprintf(stderr, "%lu: free(%p)\n", (long unsigned)pid, ptr)) {
fatal();
}
free(ptr);
}
static void
xsigemptyset(sigset_t *set)
{
if (-1 == sigemptyset(set)) {
if( -1 == sigemptyset(set) ) {
fail("sigemptyset()", errno);
}
}
@ -804,7 +750,7 @@ xsigemptyset(sigset_t *set)
static void
xsigaddset(sigset_t *set, int signo)
{
if (-1 == sigaddset(set, signo)) {
if( -1 == sigaddset(set, signo) ) {
fail("sigaddset()", errno);
}
}
@ -813,10 +759,8 @@ xsigaddset(sigset_t *set, int signo)
static void
xsigmask(int how, const sigset_t *set, sigset_t *oset)
{
int ret;
ret = pthread_sigmask(how, set, oset);
if (0 != ret) {
int ret = pthread_sigmask(how, set, oset);
if( ret != 0 ) {
fail("pthread_sigmask()", ret);
}
}
@ -831,54 +775,35 @@ xsigaction(int sig, void (*handler)(int))
xsigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (-1 == sigaction(sig, &act, 0)) {
if( -1 == sigaction(sig, &act, 0) ) {
fail("sigaction()", errno);
}
}
enum caught_sig
{
CS_INT = 1,
CS_TERM,
CS_USR1,
CS_USR2
};
enum Caught_sig { CS_INT = 1, CS_TERM, CS_USR1, CS_USR2 };
static volatile sig_atomic_t caught_sig;
static void
sighandler(int sig)
{
extern "C" void sighandler( int sig )
{
/* sig_atomic_t is nowhere required to be able to hold signal values. */
switch (sig) {
case SIGINT:
caught_sig = CS_INT;
break;
case SIGTERM:
caught_sig = CS_TERM;
break;
case SIGUSR1:
caught_sig = CS_USR1;
break;
case SIGUSR2:
caught_sig = CS_USR2;
break;
default:
assert(0);
switch( sig )
{
case SIGINT : caught_sig = CS_INT; break;
case SIGTERM: caught_sig = CS_TERM; break;
case SIGUSR1: caught_sig = CS_USR1; break;
case SIGUSR2: caught_sig = CS_USR2; break;
default: internal_error( "caught signal not in set" );
}
}
}
static void
process( const Opts *opts, unsigned num_slot,
int infd, int outfd, const Pretty_print & pp, const sigset_t *unblocked )
{
static void compress( const lzma_options & encoder_options, const int num_workers,
int debug_level, int num_slots, int infd, int outfd,
const Pretty_print & pp, const sigset_t *unblocked )
{
/*
We could wait for signals with either sigwait() or sigsuspend(). SUSv2
states about sigwait() that its effect on signal actions is unspecified.
@ -896,18 +821,19 @@ process( const Opts *opts, unsigned num_slot,
13-OCT-2009 lacos
*/
Plzip_arg muxer_arg;
pthread_t muxer;
if( verbosity >= 1 ) pp();
if( verbosity >= 1 ) pp( "" );
muxer_arg.num_worker = opts->num_worker;
muxer_arg.num_slot = num_slot;
muxer_arg.clidx = opts->clidx;
muxer_arg.print_cctrs = opts->print_cctrs;
Muxer_arg muxer_arg;
muxer_arg.dictionary_size = encoder_options.dictionary_size;
muxer_arg.match_len_limit = encoder_options.match_len_limit;
muxer_arg.num_workers = num_workers;
muxer_arg.num_slots = num_slots;
muxer_arg.debug_level = debug_level;
muxer_arg.infd = infd;
muxer_arg.outfd = outfd;
xcreate(&muxer, plzip_wrap, &muxer_arg);
pthread_t muxer_thread;
xcreate(&muxer_thread, muxer, &muxer_arg);
/* Unblock signals, wait for them, then block them again. */
{
@ -915,7 +841,7 @@ process( const Opts *opts, unsigned num_slot,
assert(-1 == ret && EINTR == errno);
}
switch (caught_sig) {
switch( caught_sig ) {
case CS_INT:
case CS_TERM: // FIXME remove output file
{
@ -951,16 +877,16 @@ process( const Opts *opts, unsigned num_slot,
assert(0);
}
xjoin(muxer);
}
xjoin(muxer_thread);
}
static void
sigs_mod(int block_n_catch, sigset_t *oset)
{
{
void (*handler)(int);
if (block_n_catch) {
if( block_n_catch ) {
sigset_t mask;
xsigemptyset(&mask);
@ -981,33 +907,9 @@ sigs_mod(int block_n_catch, sigset_t *oset)
xsigaction(SIGUSR1, handler);
xsigaction(SIGUSR2, handler);
if (!block_n_catch) {
if( !block_n_catch ) {
xsigmask(SIG_SETMASK, oset, 0);
}
}
void show_error( const char * msg, const int errcode, const bool help ) throw()
{
if( verbosity >= 0 )
{
if( msg && msg[0] != 0 )
{
std::fprintf( stderr, "%s: %s", program_name, msg );
if( errcode > 0 ) std::fprintf( stderr, ": %s", std::strerror( errcode ) );
std::fprintf( stderr, "\n" );
}
if( help && invocation_name && invocation_name[0] != 0 )
std::fprintf( stderr, "Try `%s --help' for more information.\n", invocation_name );
}
}
void internal_error( const char * msg )
{
std::string s( "internal error: " ); s += msg;
show_error( s.c_str() );
std::exit( 3 );
}
@ -1050,7 +952,6 @@ int writeblock( const int fd, const char * buf, const int size ) throw()
int main( const int argc, const char * argv[] )
{
Opts opts;
// Mapping from gzip/bzip2 style 1..9 compression modes
// to the corresponding LZMA compression modes.
const lzma_options option_mapping[] =
@ -1065,7 +966,9 @@ int main( const int argc, const char * argv[] )
{ 1 << 24, 163 }, // -8
{ 1 << 25, 273 } }; // -9
lzma_options encoder_options = option_mapping[5]; // default = "-6"
int debug_level = 0;
int inhandle = -1;
int num_workers = 0; // Start this many worker threads
Mode program_mode = m_compress;
bool force = false;
bool keep_input_files = false;
@ -1081,30 +984,15 @@ int main( const int argc, const char * argv[] )
main_thread = pthread_self();
pid = getpid();
mallocf = malloc;
freef = free;
xsigaction(SIGPIPE, SIG_IGN);
xsigaction(SIGXFSZ, SIG_IGN);
/* Effectuate option defaults. */
long max_worker = sysconf(_SC_THREAD_THREADS_MAX);
if (-1L == max_worker) {
max_worker = LONG_MAX;
}
if (UINT_MAX < (long unsigned)max_worker) {
max_worker = UINT_MAX;
}
if (UINT_MAX / blf < (unsigned)max_worker) {
max_worker = UINT_MAX / blf;
}
if ((size_t)-1 / sizeof(pthread_t) < (unsigned)max_worker) {
max_worker = (size_t)-1 / sizeof(pthread_t);
}
opts.num_worker = 0u;
opts.clidx = 5u;
opts.print_cctrs = 0;
const int slots_per_worker = 2;
long max_workers = sysconf( _SC_THREAD_THREADS_MAX );
if( max_workers < 1 || max_workers > INT_MAX / slots_per_worker )
max_workers = INT_MAX / slots_per_worker;
if( max_workers > INT_MAX / (int)sizeof( pthread_t ) )
max_workers = INT_MAX / sizeof( pthread_t );
const Arg_parser::Option options[] =
{
@ -1150,25 +1038,24 @@ int main( const int argc, const char * argv[] )
case '1': case '2': case '3':
case '4': case '5': case '6':
case '7': case '8': case '9':
opts.clidx = code - '1';
encoder_options = option_mapping[code-'1']; break;
case 'b': break;
case 'c': to_stdout = true; break;
case 'd': program_mode = m_decompress; break;
case 'D': { int debug_level = getnum( arg, 0, 0, 3 );
if( debug_level & 1 ) opts.print_cctrs = 1;
if( debug_level & 2 )
{ mallocf = trace_malloc; freef = trace_free; } }
case 'D': debug_level = getnum( arg, 0, 0, 3 );
break;
case 'f': force = true; break;
case 'h': show_help(); return 0;
case 'k': keep_input_files = true; break;
case 'm': encoder_options.match_len_limit =
getnum( arg, 0, 5, 273 ); break;
getnum( arg, 0, LZ_min_match_len_limit(),
LZ_max_match_len_limit() ); break;
case 'o': default_output_filename = arg; break;
case 'n': opts.num_worker = getnum( arg, 0, 1, max_worker ); break;
case 'n': num_workers = getnum( arg, 0, 1, max_workers ); break;
case 'q': verbosity = -1; break;
case 's': encoder_options.dictionary_size = get_dict_size( arg );
break;
case 'S': break;
case 't': program_mode = m_test; break;
case 'v': if( verbosity < 4 ) ++verbosity; break;
case 'V': show_version(); return 0;
@ -1176,23 +1063,13 @@ int main( const int argc, const char * argv[] )
}
}
if( opts.num_worker <= 0 )
if( num_workers <= 0 )
{
#ifdef _SC_NPROCESSORS_ONLN
long num_online = sysconf( _SC_NPROCESSORS_ONLN );
if( num_online <= 0 )
{
show_error( "number of online processors unavailable.", 0, true );
fatal();
}
opts.num_worker = std::min( num_online, max_worker );
#else
show_error( "number of (de)compression threads not set.", 0, true );
fatal();
#endif
if( num_online <= 0 ) num_online = 2;
num_workers = std::min( num_online, max_workers );
}
assert(UINT_MAX / blf >= opts.num_worker);
unsigned num_slot = opts.num_worker * blf;
const int num_slots = num_workers * slots_per_worker;
bool filenames_given = false;
for( ; argind < parser.arguments(); ++argind )
@ -1265,14 +1142,14 @@ int main( const int argc, const char * argv[] )
if( output_filename.size() && !to_stdout && program_mode != m_test )
delete_output_on_interrupt = true;
const struct stat * in_statsp = input_filename.size() ? &in_stats : 0;
const struct stat * const in_statsp = input_filename.size() ? &in_stats : 0;
pp.set_name( input_filename );
int tmp = 0;
if( program_mode == m_compress )
{
sigset_t unblocked;
sigs_mod(1, &unblocked);
process( &opts, num_slot, inhandle, outhandle, pp, &unblocked );
compress( encoder_options, num_workers, debug_level, num_slots, inhandle, outhandle, pp, &unblocked );
sigs_mod(0, &unblocked);
}
else
@ -1281,7 +1158,7 @@ int main( const int argc, const char * argv[] )
if( tmp && program_mode != m_test ) cleanup_and_fail( retval );
if( delete_output_on_interrupt )
close_and_set_permissions( in_statsp, &retval );
close_and_set_permissions( in_statsp );
if( input_filename.size() )
{
close( inhandle ); inhandle = -1;