Adding upstream version 0.23.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
22f7f3575c
commit
9a8733dd3b
39 changed files with 2213 additions and 1444 deletions
255
main.cc
255
main.cc
|
@ -15,16 +15,17 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*
|
||||
Exit status: 0 for a normal exit, 1 for environmental problems (file not
|
||||
found, files differ, invalid flags, I/O errors, etc), 2 to indicate a
|
||||
corrupt or invalid input file, 3 for an internal consistency error
|
||||
(e.g. bug) which caused tarlz to panic.
|
||||
Exit status: 0 for a normal exit, 1 for environmental problems
|
||||
(file not found, files differ, invalid command line options, I/O errors,
|
||||
etc), 2 to indicate a corrupt or invalid input file, 3 for an internal
|
||||
consistency error (e.g., bug) which caused tarlz to panic.
|
||||
*/
|
||||
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
|
@ -81,30 +82,29 @@ void show_help( const long num_online )
|
|||
"(uncompressed) tar. Moreover, the option '--keep-damaged' can be used to\n"
|
||||
"recover as much data as possible from each damaged member, and lziprecover\n"
|
||||
"can be used to recover some of the damaged members.\n"
|
||||
"\nUsage: %s [options] [files]\n", invocation_name );
|
||||
std::printf( "\nOptions:\n"
|
||||
"\nUsage: %s operation [options] [files]\n", invocation_name );
|
||||
std::printf( "\nOperations:\n"
|
||||
" --help display this help and exit\n"
|
||||
" -V, --version output version information and exit\n"
|
||||
" -A, --concatenate append archives to the end of an archive\n"
|
||||
" -B, --data-size=<bytes> set target size of input data blocks [2x8=16 MiB]\n"
|
||||
" -c, --create create a new archive\n"
|
||||
" -C, --directory=<dir> change to directory <dir>\n"
|
||||
" -d, --diff find differences between archive and file system\n"
|
||||
" --ignore-ids ignore differences in owner and group IDs\n"
|
||||
" --delete delete files/directories from an archive\n"
|
||||
" --exclude=<pattern> exclude files matching a shell pattern\n"
|
||||
" -r, --append append files to the end of an archive\n"
|
||||
" -t, --list list the contents of an archive\n"
|
||||
" -x, --extract extract files/directories from an archive\n"
|
||||
" -z, --compress compress existing POSIX tar archives\n"
|
||||
" --check-lib check version of lzlib and exit\n"
|
||||
"\nOptions:\n"
|
||||
" -B, --data-size=<bytes> set target size of input data blocks [2x8=16 MiB]\n"
|
||||
" -C, --directory=<dir> change to directory <dir>\n"
|
||||
" -f, --file=<archive> use archive file <archive>\n"
|
||||
" -h, --dereference follow symlinks; archive the files they point to\n"
|
||||
" --mtime=<date> use <date> as mtime for files added to archive\n"
|
||||
" -n, --threads=<n> set number of (de)compression threads [%ld]\n"
|
||||
" -o, --output=<file> compress to <file>\n"
|
||||
" -p, --preserve-permissions don't subtract the umask on extraction\n"
|
||||
" -q, --quiet suppress all messages\n"
|
||||
" -r, --append append files to the end of an archive\n"
|
||||
" -t, --list list the contents of an archive\n"
|
||||
" -v, --verbose verbosely list files processed\n"
|
||||
" -x, --extract extract files/directories from an archive\n"
|
||||
" -z, --compress compress existing POSIX tar archives\n"
|
||||
" -0 .. -9 set compression level [default 6]\n"
|
||||
" --uncompressed don't compress the archive created\n"
|
||||
" --asolid create solidly compressed appendable archive\n"
|
||||
|
@ -115,10 +115,13 @@ void show_help( const long num_online )
|
|||
" --anonymous equivalent to '--owner=root --group=root'\n"
|
||||
" --owner=<owner> use <owner> name/ID for files added to archive\n"
|
||||
" --group=<group> use <group> name/ID for files added to archive\n"
|
||||
" --exclude=<pattern> exclude files matching a shell pattern\n"
|
||||
" --ignore-ids ignore differences in owner and group IDs\n"
|
||||
" --ignore-overflow ignore mtime overflow differences on 32-bit\n"
|
||||
" --keep-damaged don't delete partially extracted files\n"
|
||||
" --missing-crc exit with error status if missing extended CRC\n"
|
||||
" --mtime=<date> use <date> as mtime for files added to archive\n"
|
||||
" --out-slots=<n> number of 1 MiB output packets buffered [64]\n"
|
||||
" --check-lib compare version of lzlib.h with liblz.{a,so}\n"
|
||||
" --warn-newer warn if any file is newer than the archive\n"
|
||||
/* " --permissive allow repeated extended headers and records\n"*/,
|
||||
num_online );
|
||||
|
@ -126,10 +129,12 @@ void show_help( const long num_online )
|
|||
{
|
||||
std::printf( " --debug=<level> (0-1) print debug statistics to stderr\n" );
|
||||
}
|
||||
std::printf( "\nExit status: 0 for a normal exit, 1 for environmental problems (file not\n"
|
||||
"found, files differ, invalid flags, I/O errors, etc), 2 to indicate a\n"
|
||||
"corrupt or invalid input file, 3 for an internal consistency error (e.g. bug)\n"
|
||||
"which caused tarlz to panic.\n"
|
||||
std::printf( "\nIf no archive is specified, tarlz tries to read it from standard input or\n"
|
||||
"write it to standard output.\n"
|
||||
"\nExit status: 0 for a normal exit, 1 for environmental problems\n"
|
||||
"(file not found, files differ, invalid command line options, I/O errors,\n"
|
||||
"etc), 2 to indicate a corrupt or invalid input file, 3 for an internal\n"
|
||||
"consistency error (e.g., bug) which caused tarlz to panic.\n"
|
||||
"\nReport bugs to lzip-bug@nongnu.org\n"
|
||||
"Tarlz home page: http://www.nongnu.org/lzip/tarlz.html\n" );
|
||||
}
|
||||
|
@ -204,56 +209,63 @@ int check_lib()
|
|||
}
|
||||
|
||||
|
||||
// separate large numbers >= 100_000 in groups of 3 digits using '_'
|
||||
const char * format_num3( unsigned long long num )
|
||||
// separate numbers of 6 or more digits in groups of 3 digits using '_'
|
||||
const char * format_num3( long long num )
|
||||
{
|
||||
const char * const si_prefix = "kMGTPEZY";
|
||||
const char * const binary_prefix = "KMGTPEZY";
|
||||
enum { buffers = 8, bufsize = 4 * sizeof (long long) };
|
||||
enum { buffers = 8, bufsize = 4 * sizeof num };
|
||||
static char buffer[buffers][bufsize]; // circle of static buffers for printf
|
||||
static int current = 0;
|
||||
|
||||
char * const buf = buffer[current++]; current %= buffers;
|
||||
char * p = buf + bufsize - 1; // fill the buffer backwards
|
||||
*p = 0; // terminator
|
||||
const bool negative = num < 0;
|
||||
char prefix = 0; // try binary first, then si
|
||||
for( int i = 0; i < 8 && num >= 1024 && num % 1024 == 0; ++i )
|
||||
for( int i = 0; i < 8 && num != 0 && ( num / 1024 ) * 1024 == num; ++i )
|
||||
{ num /= 1024; prefix = binary_prefix[i]; }
|
||||
if( prefix ) *(--p) = 'i';
|
||||
else
|
||||
for( int i = 0; i < 8 && num >= 1000 && num % 1000 == 0; ++i )
|
||||
for( int i = 0; i < 8 && num != 0 && ( num / 1000 ) * 1000 == num; ++i )
|
||||
{ num /= 1000; prefix = si_prefix[i]; }
|
||||
if( prefix ) *(--p) = prefix;
|
||||
const bool split = num >= 100000;
|
||||
const bool split = num >= 100000 || num <= -100000;
|
||||
|
||||
for( int i = 0; ; )
|
||||
{
|
||||
*(--p) = num % 10 + '0'; num /= 10; if( num == 0 ) break;
|
||||
long long onum = num; num /= 10;
|
||||
*(--p) = llabs( onum - 10 * num ) + '0'; if( num == 0 ) break;
|
||||
if( split && ++i >= 3 ) { i = 0; *(--p) = '_'; }
|
||||
}
|
||||
if( negative ) *(--p) = '-';
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
unsigned long long getnum( const char * const arg,
|
||||
const char * const option_name,
|
||||
const unsigned long long llimit,
|
||||
const unsigned long long ulimit )
|
||||
void show_option_error( const char * const arg, const char * const msg,
|
||||
const char * const option_name )
|
||||
{
|
||||
if( verbosity >= 0 )
|
||||
std::fprintf( stderr, "%s: '%s': %s option '%s'.\n",
|
||||
program_name, arg, msg, option_name );
|
||||
}
|
||||
|
||||
|
||||
long long getnum( const char * const arg, const char * const option_name,
|
||||
const long long llimit = LLONG_MIN,
|
||||
const long long ulimit = LLONG_MAX )
|
||||
{
|
||||
char * tail;
|
||||
errno = 0;
|
||||
unsigned long long result = strtoull( arg, &tail, 0 );
|
||||
long long result = strtoll( arg, &tail, 0 );
|
||||
if( tail == arg )
|
||||
{
|
||||
if( verbosity >= 0 )
|
||||
std::fprintf( stderr, "%s: Bad or missing numerical argument in "
|
||||
"option '%s'.\n", program_name, option_name );
|
||||
std::exit( 1 );
|
||||
}
|
||||
{ show_option_error( arg, "Bad or missing numerical argument in",
|
||||
option_name ); std::exit( 1 ); }
|
||||
|
||||
if( !errno && tail[0] )
|
||||
{
|
||||
const unsigned factor = ( tail[1] == 'i' ) ? 1024 : 1000;
|
||||
const int factor = ( tail[1] == 'i' ) ? 1024 : 1000;
|
||||
int exponent = 0; // 0 = bad multiplier
|
||||
switch( tail[0] )
|
||||
{
|
||||
|
@ -268,15 +280,12 @@ unsigned long long getnum( const char * const arg,
|
|||
case 'k': if( factor == 1000 ) exponent = 1; break;
|
||||
}
|
||||
if( exponent <= 0 )
|
||||
{
|
||||
if( verbosity >= 0 )
|
||||
std::fprintf( stderr, "%s: Bad multiplier in numerical argument of "
|
||||
"option '%s'.\n", program_name, option_name );
|
||||
std::exit( 1 );
|
||||
}
|
||||
{ show_option_error( arg, "Bad multiplier in numerical argument of",
|
||||
option_name ); std::exit( 1 ); }
|
||||
for( int i = 0; i < exponent; ++i )
|
||||
{
|
||||
if( ulimit / factor >= result ) result *= factor;
|
||||
if( ( result >= 0 && LLONG_MAX / factor >= result ) ||
|
||||
( result < 0 && LLONG_MIN / factor <= result ) ) result *= factor;
|
||||
else { errno = ERANGE; break; }
|
||||
}
|
||||
}
|
||||
|
@ -284,8 +293,8 @@ unsigned long long getnum( const char * const arg,
|
|||
if( errno )
|
||||
{
|
||||
if( verbosity >= 0 )
|
||||
std::fprintf( stderr, "%s: Numerical argument out of limits [%s,%s] "
|
||||
"in option '%s'.\n", program_name, format_num3( llimit ),
|
||||
std::fprintf( stderr, "%s: '%s': Value out of limits [%s,%s] in "
|
||||
"option '%s'.\n", program_name, arg, format_num3( llimit ),
|
||||
format_num3( ulimit ), option_name );
|
||||
std::exit( 1 );
|
||||
}
|
||||
|
@ -315,51 +324,61 @@ void set_mode( Program_mode & program_mode, const Program_mode new_mode )
|
|||
}
|
||||
|
||||
|
||||
void set_mtime( long long & mtime, const char * arg, const char * const pn )
|
||||
// parse time as 'long long' even if time_t is 32-bit
|
||||
long long parse_mtime( const char * arg, const char * const pn )
|
||||
{
|
||||
if( *arg == '@' )
|
||||
{ mtime = getnum( arg + 1, pn, 0, ( 1ULL << 33 ) - 1 ); return; }
|
||||
if( *arg == '@' ) return getnum( arg + 1, pn );
|
||||
else if( *arg == '.' || *arg == '/' )
|
||||
{
|
||||
struct stat st;
|
||||
if( stat( arg, &st ) == 0 ) { mtime = st.st_mtime; return; }
|
||||
show_file_error( arg, "Can't stat", errno ); std::exit( 1 );
|
||||
if( stat( arg, &st ) == 0 ) return st.st_mtime;
|
||||
show_file_error( arg, "Can't stat mtime reference file", errno );
|
||||
std::exit( 1 );
|
||||
}
|
||||
else // format 'YYYY-MM-DD HH:MM:SS'
|
||||
else // format '[-]YYYY-MM-DD[[[<separator>HH]:MM]:SS]'
|
||||
{
|
||||
unsigned y, mo, d, h, m, s;
|
||||
const int n = std::sscanf( arg, "%u-%u-%u %u:%u:%u",
|
||||
&y, &mo, &d, &h, &m, &s );
|
||||
if( n == 6 && y >= 1970 && mo >= 1 )
|
||||
long long y; // long long because 2147483648-01-01 overflows int
|
||||
unsigned mo, d, h, m, s;
|
||||
char sep;
|
||||
const int n = std::sscanf( arg, "%lld-%u-%u%c%u:%u:%u",
|
||||
&y, &mo, &d, &sep, &h, &m, &s );
|
||||
if( n >= 3 && n <= 7 && n != 4 && ( n == 3 || sep == ' ' || sep == 'T' ) )
|
||||
{
|
||||
struct tm t;
|
||||
t.tm_year = y - 1900; t.tm_mon = mo - 1; t.tm_mday = d;
|
||||
t.tm_hour = h; t.tm_min = m; t.tm_sec = s; t.tm_isdst = -1;
|
||||
mtime = std::mktime( &t ); if( mtime >= 0 ) return;
|
||||
if( y >= INT_MIN + 1900 && y <= INT_MAX && mo >= 1 && mo <= 12 )
|
||||
{
|
||||
struct tm t;
|
||||
t.tm_year = y - 1900; t.tm_mon = mo - 1; t.tm_mday = d;
|
||||
t.tm_hour = ( n >= 5 ) ? h : 0; t.tm_min = ( n >= 6 ) ? m : 0;
|
||||
t.tm_sec = ( n >= 7 ) ? s : 0; t.tm_isdst = -1;
|
||||
errno = 0;
|
||||
const long long mtime = std::mktime( &t );
|
||||
if( mtime != -1 || errno == 0 ) return mtime; // valid datetime
|
||||
}
|
||||
show_option_error( arg, "Date out of limits in", pn ); std::exit( 1 );
|
||||
}
|
||||
}
|
||||
show_error( "Invalid mtime.", 0, true ); std::exit( 1 );
|
||||
show_option_error( arg, "Unknown date format in", pn ); std::exit( 1 );
|
||||
}
|
||||
|
||||
|
||||
void set_owner( int & owner, const char * const arg, const char * const pn )
|
||||
long long parse_owner( const char * const arg, const char * const pn )
|
||||
{
|
||||
const struct passwd * const pw = getpwnam( arg );
|
||||
if( pw ) owner = pw->pw_uid;
|
||||
else if( std::isdigit( (unsigned char)arg[0] ) )
|
||||
owner = getnum( arg, pn, 0, INT_MAX );
|
||||
else if( std::strcmp( arg, "root" ) == 0 ) owner = 0;
|
||||
else { show_file_error( arg, "Invalid owner" ); std::exit( 1 ); }
|
||||
if( pw ) return pw->pw_uid;
|
||||
if( std::isdigit( (unsigned char)arg[0] ) )
|
||||
return getnum( arg, pn, 0, LLONG_MAX );
|
||||
if( std::strcmp( arg, "root" ) == 0 ) return 0;
|
||||
show_option_error( arg, "Invalid owner in", pn ); std::exit( 1 );
|
||||
}
|
||||
|
||||
void set_group( int & group, const char * const arg, const char * const pn )
|
||||
long long parse_group( const char * const arg, const char * const pn )
|
||||
{
|
||||
const struct group * const gr = getgrnam( arg );
|
||||
if( gr ) group = gr->gr_gid;
|
||||
else if( std::isdigit( (unsigned char)arg[0] ) )
|
||||
group = getnum( arg, pn, 0, INT_MAX );
|
||||
else if( std::strcmp( arg, "root" ) == 0 ) group = 0;
|
||||
else { show_file_error( arg, "Invalid group" ); std::exit( 1 ); }
|
||||
if( gr ) return gr->gr_gid;
|
||||
if( std::isdigit( (unsigned char)arg[0] ) )
|
||||
return getnum( arg, pn, 0, LLONG_MAX );
|
||||
if( std::strcmp( arg, "root" ) == 0 ) return 0;
|
||||
show_option_error( arg, "Invalid group in", pn ); std::exit( 1 );
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
|
@ -378,7 +397,7 @@ int open_instream( const std::string & name )
|
|||
return -1; }
|
||||
struct stat st; // infd must not be a directory
|
||||
if( fstat( infd, &st ) == 0 && S_ISDIR( st.st_mode ) )
|
||||
{ show_file_error( name.c_str(), "Is a directory." );
|
||||
{ show_file_error( name.c_str(), "Can't read. Is a directory." );
|
||||
close( infd ); return -1; }
|
||||
return infd;
|
||||
}
|
||||
|
@ -397,9 +416,7 @@ int open_outstream( const std::string & name, const bool create,
|
|||
const char * msg = !create ? "Error opening file" :
|
||||
( ( errno == EEXIST ) ? "Skipping file" : "Can't create file" );
|
||||
if( !rbufp ) show_file_error( name.c_str(), msg, errno );
|
||||
else
|
||||
snprintf( (*rbufp)(), (*rbufp).size(), "%s: %s: %s\n", name.c_str(),
|
||||
msg, std::strerror( errno ) );
|
||||
else format_file_error( *rbufp, name.c_str(), msg, errno );
|
||||
}
|
||||
return outfd;
|
||||
}
|
||||
|
@ -432,6 +449,41 @@ void show_error( const char * const msg, const int errcode, const bool help )
|
|||
}
|
||||
|
||||
|
||||
bool format_error( Resizable_buffer & rbuf, const int errcode,
|
||||
const char * const format, ... )
|
||||
{
|
||||
if( verbosity < 0 ) { rbuf.resize( 1 ); rbuf()[0] = 0; return false; }
|
||||
va_list args;
|
||||
for( int i = 0; i < 2; ++i ) // resize rbuf if not large enough
|
||||
{
|
||||
int len = snprintf( rbuf(), rbuf.size(), "%s: ", program_name );
|
||||
if( len >= (int)rbuf.size() && !rbuf.resize( len + 1 ) ) break;
|
||||
va_start( args, format );
|
||||
len += vsnprintf( rbuf() + len, rbuf.size() - len, format, args );
|
||||
va_end( args );
|
||||
if( len >= (int)rbuf.size() && !rbuf.resize( len + 1 ) ) break;
|
||||
if( errcode <= 0 ) rbuf()[len++] = '\n';
|
||||
else len += snprintf( rbuf() + len, rbuf.size() - len, ": %s\n",
|
||||
std::strerror( errcode ) );
|
||||
if( len < (int)rbuf.size() || !rbuf.resize( len + 1 ) ) break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void print_error( const int errcode, const char * const format, ... )
|
||||
{
|
||||
if( verbosity < 0 ) return;
|
||||
va_list args;
|
||||
std::fprintf( stderr, "%s: ", program_name );
|
||||
va_start( args, format );
|
||||
std::vfprintf( stderr, format, args );
|
||||
va_end( args );
|
||||
if( errcode <= 0 ) std::fputc( '\n', stderr );
|
||||
else std::fprintf( stderr, ": %s\n", std::strerror( errcode ) );
|
||||
}
|
||||
|
||||
|
||||
void format_file_error( std::string & estr, const char * const filename,
|
||||
const char * const msg, const int errcode )
|
||||
{
|
||||
|
@ -442,6 +494,19 @@ void format_file_error( std::string & estr, const char * const filename,
|
|||
estr += '\n';
|
||||
}
|
||||
|
||||
bool format_file_error( Resizable_buffer & rbuf, const char * const filename,
|
||||
const char * const msg, const int errcode )
|
||||
{
|
||||
if( verbosity < 0 ) { rbuf.resize( 1 ); rbuf()[0] = 0; return false; }
|
||||
for( int i = 0; i < 2; ++i ) // resize rbuf if not large enough
|
||||
{
|
||||
const int len = snprintf( rbuf(), rbuf.size(), "%s: %s: %s%s%s\n",
|
||||
program_name, filename, msg, ( errcode > 0 ) ? ": " : "",
|
||||
( errcode > 0 ) ? std::strerror( errcode ) : "" );
|
||||
if( len < (int)rbuf.size() || !rbuf.resize( len + 1 ) ) break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void show_file_error( const char * const filename, const char * const msg,
|
||||
const int errcode )
|
||||
|
@ -467,7 +532,7 @@ int main( const int argc, const char * const argv[] )
|
|||
|
||||
enum { opt_ano = 256, opt_aso, opt_bso, opt_chk, opt_crc, opt_dbg, opt_del,
|
||||
opt_dso, opt_exc, opt_grp, opt_hlp, opt_id, opt_kd, opt_mti, opt_nso,
|
||||
opt_out, opt_own, opt_per, opt_sol, opt_un, opt_wn };
|
||||
opt_ofl, opt_out, opt_own, opt_per, opt_sol, opt_un, opt_wn };
|
||||
const Arg_parser::Option options[] =
|
||||
{
|
||||
{ '0', 0, Arg_parser::no },
|
||||
|
@ -513,6 +578,7 @@ int main( const int argc, const char * const argv[] )
|
|||
{ opt_crc, "missing-crc", Arg_parser::no },
|
||||
{ opt_mti, "mtime", Arg_parser::yes },
|
||||
{ opt_nso, "no-solid", Arg_parser::no },
|
||||
{ opt_ofl, "ignore-overflow", Arg_parser::no },
|
||||
{ opt_out, "out-slots", Arg_parser::yes },
|
||||
{ opt_own, "owner", Arg_parser::yes },
|
||||
{ opt_per, "permissive", Arg_parser::no },
|
||||
|
@ -571,8 +637,8 @@ int main( const int argc, const char * const argv[] )
|
|||
case 'V': show_version(); return 0;
|
||||
case 'x': set_mode( cl_opts.program_mode, m_extract ); break;
|
||||
case 'z': set_mode( cl_opts.program_mode, m_compress ); z_pn = pn; break;
|
||||
case opt_ano: set_owner( cl_opts.owner, "root", pn );
|
||||
set_group( cl_opts.group, "root", pn ); break;
|
||||
case opt_ano: cl_opts.uid = parse_owner( "root", pn );
|
||||
cl_opts.gid = parse_group( "root", pn ); break;
|
||||
case opt_aso: cl_opts.solidity = asolid; break;
|
||||
case opt_bso: cl_opts.solidity = bsolid; break;
|
||||
case opt_crc: cl_opts.missing_crc = true; break;
|
||||
|
@ -581,14 +647,16 @@ int main( const int argc, const char * const argv[] )
|
|||
case opt_del: set_mode( cl_opts.program_mode, m_delete ); break;
|
||||
case opt_dso: cl_opts.solidity = dsolid; break;
|
||||
case opt_exc: Exclude::add_pattern( sarg ); break;
|
||||
case opt_grp: set_group( cl_opts.group, arg, pn ); break;
|
||||
case opt_grp: cl_opts.gid = parse_group( arg, pn ); break;
|
||||
case opt_hlp: show_help( num_online ); return 0;
|
||||
case opt_id: cl_opts.ignore_ids = true; break;
|
||||
case opt_kd: cl_opts.keep_damaged = true; break;
|
||||
case opt_mti: set_mtime( cl_opts.mtime, arg, pn ); break;
|
||||
case opt_mti: cl_opts.mtime = parse_mtime( arg, pn );
|
||||
cl_opts.mtime_set = true; break;
|
||||
case opt_nso: cl_opts.solidity = no_solid; break;
|
||||
case opt_ofl: cl_opts.ignore_overflow = true; break;
|
||||
case opt_out: cl_opts.out_slots = getnum( arg, pn, 1, 1024 ); break;
|
||||
case opt_own: set_owner( cl_opts.owner, arg, pn ); break;
|
||||
case opt_own: cl_opts.uid = parse_owner( arg, pn ); break;
|
||||
case opt_per: cl_opts.permissive = true; break;
|
||||
case opt_sol: cl_opts.solidity = solid; break;
|
||||
case opt_un: cl_opts.level = -1; break;
|
||||
|
@ -597,7 +665,7 @@ int main( const int argc, const char * const argv[] )
|
|||
}
|
||||
} // end process options
|
||||
|
||||
if( cl_opts.program_mode != m_compress && cl_opts.output_filename.size() )
|
||||
if( cl_opts.program_mode != m_compress && o_pn )
|
||||
{
|
||||
if( verbosity >= 0 )
|
||||
std::fprintf( stderr, "%s: Option '%s' can only be used with "
|
||||
|
@ -611,6 +679,14 @@ int main( const int argc, const char * const argv[] )
|
|||
program_name, f_pn, z_pn );
|
||||
return 1;
|
||||
}
|
||||
if( cl_opts.program_mode == m_compress &&
|
||||
( cl_opts.level < 0 || cl_opts.level > 9 ) )
|
||||
{
|
||||
if( verbosity >= 0 )
|
||||
std::fprintf( stderr, "%s: Option '--uncompressed' can't be used with '%s'.\n",
|
||||
program_name, z_pn );
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if !defined LZ_API_VERSION || LZ_API_VERSION < 1012 // compile-time test
|
||||
#error "lzlib 1.12 or newer needed."
|
||||
|
@ -624,12 +700,17 @@ int main( const int argc, const char * const argv[] )
|
|||
setmode( STDOUT_FILENO, O_BINARY );
|
||||
#endif
|
||||
|
||||
if( cl_opts.data_size <= 0 && cl_opts.level >= 0 && cl_opts.level <= 9 )
|
||||
{
|
||||
if( cl_opts.level == 0 ) cl_opts.data_size = 1 << 20;
|
||||
else cl_opts.data_size = 2 * option_mapping[cl_opts.level].dictionary_size;
|
||||
}
|
||||
if( cl_opts.num_workers < 0 ) // 0 disables multi-threading
|
||||
cl_opts.num_workers = std::min( num_online, max_workers );
|
||||
|
||||
switch( cl_opts.program_mode )
|
||||
{
|
||||
case m_none: show_error( "Missing operation.", 0, true ); return 1;
|
||||
case m_none: show_error( "Missing operation.", 0, true ); return 1;
|
||||
case m_append:
|
||||
case m_create: return encode( cl_opts );
|
||||
case m_compress: return compress( cl_opts );
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue