summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2022-01-09 05:52:40 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2022-01-09 05:53:03 +0000
commit882d8d8da4a8b4a332458c4f01b03d81c2c08c78 (patch)
treed7acd130c7201183b14adfa8e095e79eb1f49bbe
parentReleasing debian version 0.21-3. (diff)
downloadtarlz-882d8d8da4a8b4a332458c4f01b03d81c2c08c78.tar.xz
tarlz-882d8d8da4a8b4a332458c4f01b03d81c2c08c78.zip
Merging upstream version 0.22.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
-rw-r--r--ChangeLog14
-rw-r--r--INSTALL4
-rw-r--r--Makefile.in3
-rw-r--r--NEWS25
-rw-r--r--README2
-rw-r--r--archive_reader.cc10
-rw-r--r--archive_reader.h2
-rw-r--r--arg_parser.cc15
-rw-r--r--arg_parser.h23
-rw-r--r--common.cc10
-rw-r--r--common_decode.cc2
-rw-r--r--compress.cc9
-rwxr-xr-xconfigure11
-rw-r--r--create.cc8
-rw-r--r--create.h4
-rw-r--r--create_lz.cc5
-rw-r--r--decode.cc2
-rw-r--r--decode_lz.cc2
-rw-r--r--delete.cc2
-rw-r--r--delete_lz.cc2
-rw-r--r--doc/tarlz.16
-rw-r--r--doc/tarlz.info83
-rw-r--r--doc/tarlz.texi54
-rw-r--r--exclude.cc2
-rw-r--r--extended.cc6
-rw-r--r--lzip_index.cc2
-rw-r--r--lzip_index.h2
-rw-r--r--main.cc154
-rw-r--r--tarlz.h6
-rwxr-xr-xtestsuite/check.sh19
30 files changed, 307 insertions, 182 deletions
diff --git a/ChangeLog b/ChangeLog
index 34e5f12..8f23ad6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2022-01-05 Antonio Diaz Diaz <antonio@gnu.org>
+
+ * Version 0.22 released.
+ * main.cc (getnum): Show option name and valid range if error.
+ (check_lib): Check that LZ_API_VERSION and LZ_version_string match.
+ (main): Report an error if -o is used with any operation except -z.
+ * Set variable LIBS from configure.
+
2021-06-14 Antonio Diaz Diaz <antonio@gnu.org>
* Version 0.21 released.
@@ -130,13 +138,13 @@
* Option '--ignore-crc' replaced with '--missing-crc'.
* create.cc (add_member): Test that uid, gid, mtime, devmajor
and devminor are in ustar range.
- * configure: Accept appending to CXXFLAGS, 'CXXFLAGS+=OPTIONS'.
+ * configure: Accept appending to CXXFLAGS; 'CXXFLAGS+=OPTIONS'.
* Makefile.in: Use tarlz in target 'dist'.
2018-09-29 Antonio Diaz Diaz <antonio@gnu.org>
* Version 0.5 released.
- * Implement simplified posix pax format.
+ * Implement simplified POSIX pax format.
* Implement CRC32-C (Castagnoli) of the extended header data.
* New option '--ignore-crc'.
* Add missing #includes for major, minor and makedev.
@@ -174,7 +182,7 @@
* Version 0.1 released.
-Copyright (C) 2013-2021 Antonio Diaz Diaz.
+Copyright (C) 2013-2022 Antonio Diaz Diaz.
This file is a collection of facts, and thus it is not copyrightable,
but just in case, you have unlimited permission to copy, distribute, and
diff --git a/INSTALL b/INSTALL
index 2590d7e..507c1e5 100644
--- a/INSTALL
+++ b/INSTALL
@@ -2,7 +2,7 @@ Requirements
------------
You will need a C++11 compiler and the compression library lzlib installed.
(gcc 3.3.6 or newer is recommended).
-I use gcc 6.1.0 and 4.1.2, but the code should compile with any standards
+I use gcc 6.1.0 and 3.3.6, but the code should compile with any standards
compliant compiler.
Lzlib must be version 1.12 or newer.
@@ -70,7 +70,7 @@ After running 'configure', you can run 'make' and 'make install' as
explained above.
-Copyright (C) 2013-2021 Antonio Diaz Diaz.
+Copyright (C) 2013-2022 Antonio Diaz Diaz.
This file is free documentation: you have unlimited permission to copy,
distribute, and modify it.
diff --git a/Makefile.in b/Makefile.in
index 6a10c03..7506a17 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -4,7 +4,6 @@ INSTALL = install
INSTALL_PROGRAM = $(INSTALL) -m 755
INSTALL_DATA = $(INSTALL) -m 644
INSTALL_DIR = $(INSTALL) -d -m 755
-LIBS = -llz -lpthread
SHELL = /bin/sh
CAN_RUN_INSTALLINFO = $(SHELL) -c "install-info --version" > /dev/null 2>&1
@@ -22,7 +21,7 @@ objs = arg_parser.o lzip_index.o archive_reader.o common.o common_decode.o \
all : $(progname)
$(progname) : $(objs)
- $(CXX) $(LDFLAGS) $(CXXFLAGS) -o $@ $(objs) $(LIBS)
+ $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $(objs) $(LIBS)
main.o : main.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROGVERSION=\"$(pkgversion)\" -c -o $@ $<
diff --git a/NEWS b/NEWS
index e6dcaf1..7616e6c 100644
--- a/NEWS
+++ b/NEWS
@@ -1,22 +1,11 @@
-Changes in version 0.21:
+Changes in version 0.22:
-Lzlib 1.12 or newer is now required to compile and run tarlz.
+In case of error in a numerical argument to a command line option, tarlz
+now shows the name of the option and the range of valid values.
-Members without name are now skipped when decoding except when listing. This
-allows the reliable detection of certain format violations during parallel
-extraction with more than two threads. (Thanks to Florian Schmaus for
-reporting the problem).
+'--check-lib' now checks that LZ_API_VERSION and LZ_version_string match.
-The new option '-z, --compress', which compresses existing POSIX tar
-archives aligning the lzip members to the tar members with choice of
-granularity, has been added. Existing compressed archives are not
-overwritten.
+Tarlz now reports an error and exits with status 1 if '-o, --output' is used
+with any operation other than '-z, --compress'.
-The new option '-o, --output', which writes the compressed output to a file,
-has been added. Currently '--output' only works with '--compress'.
-
-The new option '--warn-newer', which warns during archive creation if any
-file being archived has a modification time newer than the archive creation
-time, has been added.
-
-A failure in the '--diff' test of the testsuite on OS/2 has been fixed.
+The variable LIBS can now be set from configure.
diff --git a/README b/README
index 046cf54..55734d4 100644
--- a/README
+++ b/README
@@ -87,7 +87,7 @@ tar.lz
+===============+=================================================+========+
-Copyright (C) 2013-2021 Antonio Diaz Diaz.
+Copyright (C) 2013-2022 Antonio Diaz Diaz.
This file is free documentation: you have unlimited permission to copy,
distribute, and modify it.
diff --git a/archive_reader.cc b/archive_reader.cc
index 5e0862e..a146156 100644
--- a/archive_reader.cc
+++ b/archive_reader.cc
@@ -1,5 +1,5 @@
/* Tarlz - Archiver with multimember lzip compression
- Copyright (C) 2013-2021 Antonio Diaz Diaz.
+ Copyright (C) 2013-2022 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
@@ -30,8 +30,8 @@
namespace {
-/* Returns the number of bytes really read.
- If (returned value < size) and (errno == 0), means EOF was reached.
+/* Return the number of bytes really read.
+ If (value returned < size) and (errno == 0), means EOF was reached.
*/
int preadblock( const int fd, uint8_t * const buf, const int size,
const long long pos )
@@ -50,8 +50,8 @@ int preadblock( const int fd, uint8_t * const buf, const int size,
}
-/* Returns the number of bytes really written.
- If (returned value < size), it is always an error.
+/* Return the number of bytes really written.
+ If (value returned < size), it is always an error.
*//*
int pwriteblock( const int fd, const uint8_t * const buf, const int size,
const long long pos )
diff --git a/archive_reader.h b/archive_reader.h
index bbd5bcb..1b16f1c 100644
--- a/archive_reader.h
+++ b/archive_reader.h
@@ -1,5 +1,5 @@
/* Tarlz - Archiver with multimember lzip compression
- Copyright (C) 2013-2021 Antonio Diaz Diaz.
+ Copyright (C) 2013-2022 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
diff --git a/arg_parser.cc b/arg_parser.cc
index 2e40a13..59998ac 100644
--- a/arg_parser.cc
+++ b/arg_parser.cc
@@ -1,5 +1,5 @@
/* Arg_parser - POSIX/GNU command line argument parser. (C++ version)
- Copyright (C) 2006-2021 Antonio Diaz Diaz.
+ Copyright (C) 2006-2022 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided
@@ -35,9 +35,10 @@ bool Arg_parser::parse_long_option( const char * const opt, const char * const a
// Test all long options for either exact match or abbreviated matches.
for( int i = 0; options[i].code != 0; ++i )
- if( options[i].name && std::strncmp( options[i].name, &opt[2], len ) == 0 )
+ if( options[i].long_name &&
+ std::strncmp( options[i].long_name, &opt[2], len ) == 0 )
{
- if( std::strlen( options[i].name ) == len ) // Exact match found
+ if( std::strlen( options[i].long_name ) == len ) // Exact match found
{ index = i; exact = true; break; }
else if( index < 0 ) index = i; // First nonexact match found
else if( options[index].code != options[i].code ||
@@ -58,19 +59,19 @@ bool Arg_parser::parse_long_option( const char * const opt, const char * const a
}
++argind;
- data.push_back( Record( options[index].code ) );
+ data.push_back( Record( options[index].code, options[index].long_name ) );
if( opt[len+2] ) // '--<long_option>=<argument>' syntax
{
if( options[index].has_arg == no )
{
- error_ = "option '--"; error_ += options[index].name;
+ error_ = "option '--"; error_ += options[index].long_name;
error_ += "' doesn't allow an argument";
return false;
}
if( options[index].has_arg == yes && !opt[len+3] )
{
- error_ = "option '--"; error_ += options[index].name;
+ error_ = "option '--"; error_ += options[index].long_name;
error_ += "' requires an argument";
return false;
}
@@ -82,7 +83,7 @@ bool Arg_parser::parse_long_option( const char * const opt, const char * const a
{
if( !arg || !arg[0] )
{
- error_ = "option '--"; error_ += options[index].name;
+ error_ = "option '--"; error_ += options[index].long_name;
error_ += "' requires an argument";
return false;
}
diff --git a/arg_parser.h b/arg_parser.h
index 5629b90..e854838 100644
--- a/arg_parser.h
+++ b/arg_parser.h
@@ -1,5 +1,5 @@
/* Arg_parser - POSIX/GNU command line argument parser. (C++ version)
- Copyright (C) 2006-2021 Antonio Diaz Diaz.
+ Copyright (C) 2006-2022 Antonio Diaz Diaz.
This library is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided
@@ -23,9 +23,9 @@
In case of error, 'error' returns a non-empty error message.
'options' is an array of 'struct Option' terminated by an element
- containing a code which is zero. A null name means a short-only
- option. A code value outside the unsigned char range means a
- long-only option.
+ containing a code which is zero. A null long_name means a short-only
+ option. A code value outside the unsigned char range means a long-only
+ option.
Arg_parser normally makes it appear as if all the option arguments
were specified before all the non-option arguments for the purposes
@@ -48,7 +48,7 @@ public:
struct Option
{
int code; // Short option letter or code ( code != 0 )
- const char * name; // Long option name (maybe null)
+ const char * long_name; // Long option name (maybe null)
Has_arg has_arg;
};
@@ -56,8 +56,12 @@ private:
struct Record
{
int code;
+ std::string parsed_name;
std::string argument;
- explicit Record( const int c ) : code( c ) {}
+ explicit Record( const unsigned char c )
+ : code( c ), parsed_name( "-" ) { parsed_name += c; }
+ Record( const int c, const char * const long_name )
+ : code( c ), parsed_name( "--" ) { parsed_name += long_name; }
explicit Record( const char * const arg ) : code( 0 ), argument( arg ) {}
};
@@ -91,6 +95,13 @@ public:
else return 0;
}
+ // Full name of the option parsed (short or long).
+ const std::string & parsed_name( const int i ) const
+ {
+ if( i >= 0 && i < arguments() ) return data[i].parsed_name;
+ else return empty_arg;
+ }
+
const std::string & argument( const int i ) const
{
if( i >= 0 && i < arguments() ) return data[i].argument;
diff --git a/common.cc b/common.cc
index a493e11..444280d 100644
--- a/common.cc
+++ b/common.cc
@@ -1,5 +1,5 @@
/* Tarlz - Archiver with multimember lzip compression
- Copyright (C) 2013-2021 Antonio Diaz Diaz.
+ Copyright (C) 2013-2022 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
@@ -108,8 +108,8 @@ unsigned long long parse_octal( const uint8_t * const ptr, const int size )
}
-/* Returns the number of bytes really read.
- If (returned value < size) and (errno == 0), means EOF was reached.
+/* Return the number of bytes really read.
+ If (value returned < size) and (errno == 0), means EOF was reached.
*/
int readblock( const int fd, uint8_t * const buf, const int size )
{
@@ -127,8 +127,8 @@ int readblock( const int fd, uint8_t * const buf, const int size )
}
-/* Returns the number of bytes really written.
- If (returned value < size), it is always an error.
+/* Return the number of bytes really written.
+ If (value returned < size), it is always an error.
*/
int writeblock( const int fd, const uint8_t * const buf, const int size )
{
diff --git a/common_decode.cc b/common_decode.cc
index 595fd7b..a030428 100644
--- a/common_decode.cc
+++ b/common_decode.cc
@@ -1,5 +1,5 @@
/* Tarlz - Archiver with multimember lzip compression
- Copyright (C) 2013-2021 Antonio Diaz Diaz.
+ Copyright (C) 2013-2022 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
diff --git a/compress.cc b/compress.cc
index e26814b..ad3f151 100644
--- a/compress.cc
+++ b/compress.cc
@@ -1,5 +1,5 @@
/* Tarlz - Archiver with multimember lzip compression
- Copyright (C) 2013-2021 Antonio Diaz Diaz.
+ Copyright (C) 2013-2022 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
@@ -122,10 +122,6 @@ void close_and_set_permissions( const struct stat * const in_statsp )
}
-inline void set_retval( int & retval, const int new_val )
- { if( retval < new_val ) retval = new_val; }
-
-
bool archive_write( const uint8_t * const buf, const long long size,
LZ_Encoder * const encoder )
{
@@ -318,9 +314,6 @@ int compress_archive( const Cl_options & cl_opts,
int compress( Cl_options & cl_opts )
{
- if( !cl_opts.archive_name.empty() )
- { show_file_error( cl_opts.archive_name.c_str(),
- "Option '-f' is incompatible with '--compress'." ); return 1; }
if( cl_opts.num_files > 1 && cl_opts.output_filename.size() )
{ show_file_error( cl_opts.output_filename.c_str(),
"Only can compress one archive when using '-o'." ); return 1; }
diff --git a/configure b/configure
index 42e0532..39abe55 100755
--- a/configure
+++ b/configure
@@ -1,12 +1,12 @@
#! /bin/sh
# configure script for Tarlz - Archiver with multimember lzip compression
-# Copyright (C) 2013-2021 Antonio Diaz Diaz.
+# Copyright (C) 2013-2022 Antonio Diaz Diaz.
#
# This configure script is free software: you have unlimited permission
# to copy, distribute, and modify it.
pkgname=tarlz
-pkgversion=0.21
+pkgversion=0.22
progname=tarlz
srctrigger=doc/${pkgname}.texi
@@ -24,6 +24,7 @@ CXX=g++
CPPFLAGS=
CXXFLAGS='-Wall -W -O2'
LDFLAGS=
+LIBS='-llz -lpthread'
# checking whether we are using GNU C++.
/bin/sh -c "${CXX} --version" > /dev/null 2>&1 || { CXX=c++ ; CXXFLAGS=-O2 ; }
@@ -69,6 +70,7 @@ while [ $# != 0 ] ; do
echo " CXXFLAGS=OPTIONS command line options for the C++ compiler [${CXXFLAGS}]"
echo " CXXFLAGS+=OPTIONS append options to the current value of CXXFLAGS"
echo " LDFLAGS=OPTIONS command line options for the linker [${LDFLAGS}]"
+ echo " LIBS=OPTIONS libraries to pass to the linker [${LIBS}]"
echo
exit 0 ;;
--version | -V)
@@ -96,6 +98,7 @@ while [ $# != 0 ] ; do
CXXFLAGS=*) CXXFLAGS=${optarg} ;;
CXXFLAGS+=*) CXXFLAGS="${CXXFLAGS} ${optarg}" ;;
LDFLAGS=*) LDFLAGS=${optarg} ;;
+ LIBS=*) LIBS="${optarg} ${LIBS}" ;;
--*)
echo "configure: WARNING: unrecognized option: '${option}'" 1>&2 ;;
@@ -164,10 +167,11 @@ echo "CXX = ${CXX}"
echo "CPPFLAGS = ${CPPFLAGS}"
echo "CXXFLAGS = ${CXXFLAGS}"
echo "LDFLAGS = ${LDFLAGS}"
+echo "LIBS = ${LIBS}"
rm -f Makefile
cat > Makefile << EOF
# Makefile for Tarlz - Archiver with multimember lzip compression
-# Copyright (C) 2013-2021 Antonio Diaz Diaz.
+# Copyright (C) 2013-2022 Antonio Diaz Diaz.
# This file was generated automatically by configure. Don't edit.
#
# This Makefile is free software: you have unlimited permission
@@ -187,6 +191,7 @@ CXX = ${CXX}
CPPFLAGS = ${CPPFLAGS}
CXXFLAGS = ${CXXFLAGS}
LDFLAGS = ${LDFLAGS}
+LIBS = ${LIBS}
EOF
cat "${srcdir}/Makefile.in" >> Makefile
diff --git a/create.cc b/create.cc
index 327f494..54ce7c3 100644
--- a/create.cc
+++ b/create.cc
@@ -1,5 +1,5 @@
/* Tarlz - Archiver with multimember lzip compression
- Copyright (C) 2013-2021 Antonio Diaz Diaz.
+ Copyright (C) 2013-2022 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
@@ -394,12 +394,13 @@ const char * remove_leading_dotslash( const char * const filename,
}
+// set file_size != 0 only for regular files
bool fill_headers( const char * const filename, Extended & extended,
Tar_header header, long long & file_size, const int flag )
{
struct stat st;
if( hstat( filename, &st, gcl_opts->dereference ) != 0 )
- { show_file_error( filename, "Can't stat input file", errno );
+ { show_file_error( filename, cant_stat, errno );
set_error_status( 1 ); return false; }
if( archive_attrs.is_the_archive( st ) )
{ show_file_error( archive_namep, "File is the archive; not dumped." );
@@ -717,8 +718,7 @@ int encode( Cl_options & cl_opts )
if( Exclude::excluded( filename ) ) continue; // skip excluded files
struct stat st;
if( lstat( filename, &st ) != 0 ) // filename from command line
- { show_file_error( filename, "Can't stat input file", errno );
- set_error_status( 1 ); }
+ { show_file_error( filename, cant_stat, errno ); set_error_status( 1 ); }
else if( ( retval = nftw( filename, add_member, 16,
cl_opts.dereference ? 0 : FTW_PHYS ) ) != 0 )
break; // write error
diff --git a/create.h b/create.h
index b536f3e..ea616e2 100644
--- a/create.h
+++ b/create.h
@@ -1,5 +1,5 @@
/* Tarlz - Archiver with multimember lzip compression
- Copyright (C) 2013-2021 Antonio Diaz Diaz.
+ Copyright (C) 2013-2022 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
@@ -43,3 +43,5 @@ public:
};
extern Archive_attrs archive_attrs;
+
+const char * const cant_stat = "Can't stat input file";
diff --git a/create_lz.cc b/create_lz.cc
index f942809..67a6f7a 100644
--- a/create_lz.cc
+++ b/create_lz.cc
@@ -1,5 +1,5 @@
/* Tarlz - Archiver with multimember lzip compression
- Copyright (C) 2013-2021 Antonio Diaz Diaz.
+ Copyright (C) 2013-2022 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
@@ -316,8 +316,7 @@ extern "C" void * grouper( void * arg )
if( Exclude::excluded( filename ) ) continue; // skip excluded files
struct stat st;
if( lstat( filename, &st ) != 0 ) // filename from command line
- { show_file_error( filename, "Can't stat input file", errno );
- set_error_status( 1 ); }
+ { show_file_error( filename, cant_stat, errno ); set_error_status( 1 ); }
else if( nftw( filename, add_member_lz, 16,
cl_opts.dereference ? 0 : FTW_PHYS ) != 0 )
exit_fail_mt(); // write error or OOM
diff --git a/decode.cc b/decode.cc
index 6c7d0ff..18e7c4b 100644
--- a/decode.cc
+++ b/decode.cc
@@ -1,5 +1,5 @@
/* Tarlz - Archiver with multimember lzip compression
- Copyright (C) 2013-2021 Antonio Diaz Diaz.
+ Copyright (C) 2013-2022 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
diff --git a/decode_lz.cc b/decode_lz.cc
index 2bbb000..a941ace 100644
--- a/decode_lz.cc
+++ b/decode_lz.cc
@@ -1,5 +1,5 @@
/* Tarlz - Archiver with multimember lzip compression
- Copyright (C) 2013-2021 Antonio Diaz Diaz.
+ Copyright (C) 2013-2022 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
diff --git a/delete.cc b/delete.cc
index 9347888..08d44fb 100644
--- a/delete.cc
+++ b/delete.cc
@@ -1,5 +1,5 @@
/* Tarlz - Archiver with multimember lzip compression
- Copyright (C) 2013-2021 Antonio Diaz Diaz.
+ Copyright (C) 2013-2022 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
diff --git a/delete_lz.cc b/delete_lz.cc
index b6667fd..9b2b34f 100644
--- a/delete_lz.cc
+++ b/delete_lz.cc
@@ -1,5 +1,5 @@
/* Tarlz - Archiver with multimember lzip compression
- Copyright (C) 2013-2021 Antonio Diaz Diaz.
+ Copyright (C) 2013-2022 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
diff --git a/doc/tarlz.1 b/doc/tarlz.1
index 4df1fa1..d7cc093 100644
--- a/doc/tarlz.1
+++ b/doc/tarlz.1
@@ -1,5 +1,5 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.16.
-.TH TARLZ "1" "June 2021" "tarlz 0.21" "User Commands"
+.TH TARLZ "1" "January 2022" "tarlz 0.22" "User Commands"
.SH NAME
tarlz \- creates tar archives with multimember lzip compression
.SH SYNOPSIS
@@ -150,8 +150,8 @@ Report bugs to lzip\-bug@nongnu.org
.br
Tarlz home page: http://www.nongnu.org/lzip/tarlz.html
.SH COPYRIGHT
-Copyright \(co 2021 Antonio Diaz Diaz.
-Using lzlib 1.12
+Copyright \(co 2022 Antonio Diaz Diaz.
+Using lzlib 1.13\-rc1
License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>
.br
This is free software: you are free to change and redistribute it.
diff --git a/doc/tarlz.info b/doc/tarlz.info
index c797f0b..79661cc 100644
--- a/doc/tarlz.info
+++ b/doc/tarlz.info
@@ -11,7 +11,7 @@ File: tarlz.info, Node: Top, Next: Introduction, Up: (dir)
Tarlz Manual
************
-This manual is for Tarlz (version 0.21, 14 June 2021).
+This manual is for Tarlz (version 0.22, 5 January 2022).
* Menu:
@@ -28,7 +28,7 @@ This manual is for Tarlz (version 0.21, 14 June 2021).
* Concept index:: Index of concepts
- Copyright (C) 2013-2021 Antonio Diaz Diaz.
+ Copyright (C) 2013-2022 Antonio Diaz Diaz.
This manual is free documentation: you have unlimited permission to copy,
distribute, and modify it.
@@ -101,8 +101,9 @@ The format for running tarlz is:
tarlz [OPTIONS] [FILES]
-All operations except '--concatenate' operate on whole trees if any FILE is
-a directory. Tarlz overwrites output files without warning.
+All operations except '--concatenate' and '--compress' operate on whole
+trees if any FILE is a directory. All operations except '--compress'
+overwrite output files without warning.
On archive creation or appending tarlz archives the files specified, but
removes from member names any leading and trailing slashes and any file name
@@ -432,12 +433,14 @@ to '-1 --solid'.
'--check-lib'
Compare the version of lzlib used to compile tarlz with the version
- actually being used and exit. Report any differences found. Exit with
- error status 1 if differences are found. A mismatch may indicate that
- lzlib is not correctly installed or that a different version of lzlib
- has been installed after compiling tarlz. 'tarlz -v --check-lib' shows
- the version of lzlib being used and the value of 'LZ_API_VERSION' (if
- defined). *Note Library version: (lzlib)Library version.
+ actually being used at run time and exit. Report any differences
+ found. Exit with error status 1 if differences are found. A mismatch
+ may indicate that lzlib is not correctly installed or that a different
+ version of lzlib has been installed after compiling tarlz. Exit with
+ error status 2 if LZ_API_VERSION and LZ_version_string don't match.
+ 'tarlz -v --check-lib' shows the version of lzlib being used and the
+ value of LZ_API_VERSION (if defined). *Note Library version:
+ (lzlib)Library version.
'--warn-newer'
During archive creation, warn if any file being archived has a
@@ -594,10 +597,10 @@ space, equal-sign, and newline.
representing the CRC <value> itself. The <value> is represented as 8
hexadecimal digits in big endian order, '22 GNU.crc32=00000000\n'. The
keyword of the CRC record is protected by the CRC to guarante that
- corruption is always detected (except in case of CRC collision). A CRC
- was chosen because a checksum is too weak for a potentially large list
- of variable sized records. A checksum can't detect simple errors like
- the swapping of two bytes.
+ corruption is always detected when using '--missing-crc' (except in
+ case of CRC collision). A CRC was chosen because a checksum is too
+ weak for a potentially large list of variable sized records. A
+ checksum can't detect simple errors like the swapping of two bytes.
At verbosity level 1 or higher tarlz prints a diagnostic for each unknown
@@ -844,16 +847,16 @@ workers. The workers compress the metadata received from the grouper along
with the file data read from the file system. The muxer collects processed
packets from the workers, and writes them to the archive.
-,--------,
+.--------.
| data|---> to each worker below
-| | ,------------,
+| | .------------.
| file | ,-->| worker 0 |--,
| system | | `------------' |
-| | ,---------, | ,------------, | ,-------, ,---------,
+| | .---------. | .------------. | .-------. .---------.
|metadata|--->| grouper |-+-->| worker 1 |--+-->| muxer |-->| archive |
`--------' `---------' | `------------' | `-------' `---------'
| ... |
- | ,------------, |
+ | .------------. |
`-->| worker N-1 |--'
`------------'
@@ -864,17 +867,17 @@ worker may access files in the file system either to read them (diff) or
write them (extract). As in plzip, each worker reads members directly from
the archive.
-,--------,
+.--------.
| file |<---> data to/from each worker below
| system |
-`--------' ,------------,
+`--------' .------------.
,-->| worker 0 |--,
| `------------' |
-,---------, | ,------------, | ,-------, ,--------,
+.---------. | .------------. | .-------. .--------.
| archive |-+-->| worker 1 |--+-->| muxer |-->| stdout |
`---------' | `------------' | `-------' | stderr |
| ... | `--------'
- | ,------------, |
+ | .------------. |
`-->| worker N-1 |--'
`------------'
@@ -956,7 +959,7 @@ example listing the Silesia corpus on a dual core machine:
On the other hand, multi-threaded '--list' won't detect corruption in
the tar member data because it only decodes the part of each lzip member
corresponding to the tar member header. This is another reason why the tar
-headers must provide its own integrity checking.
+headers must provide their own integrity checking.
7.1 Limitations of multi-threaded extraction
@@ -1101,7 +1104,7 @@ eternity, if not longer.
If you find a bug in tarlz, please send electronic mail to
<lzip-bug@nongnu.org>. Include the version number, which you can find by
-running 'tarlz --version'.
+running 'tarlz --version' and 'tarlz -v --check-lib'.

File: tarlz.info, Node: Concept index, Prev: Problems, Up: Top
@@ -1131,22 +1134,22 @@ Concept index

Tag Table:
Node: Top223
-Node: Introduction1212
-Node: Invoking tarlz4020
-Ref: --data-size6389
-Ref: --bsolid16341
-Node: Portable character set21079
-Node: File format21874
-Ref: key_crc3226799
-Node: Amendments to pax format32400
-Ref: crc3233064
-Ref: flawed-compat34375
-Node: Program design37176
-Node: Multi-threaded decoding41101
-Node: Minimum archive sizes45590
-Node: Examples47728
-Node: Problems49744
-Node: Concept index50272
+Node: Introduction1214
+Node: Invoking tarlz4022
+Ref: --data-size6436
+Ref: --bsolid16388
+Node: Portable character set21224
+Node: File format22019
+Ref: key_crc3226944
+Node: Amendments to pax format32572
+Ref: crc3233236
+Ref: flawed-compat34547
+Node: Program design37348
+Node: Multi-threaded decoding41273
+Node: Minimum archive sizes45764
+Node: Examples47902
+Node: Problems49918
+Node: Concept index50473

End Tag Table
diff --git a/doc/tarlz.texi b/doc/tarlz.texi
index f451e5a..bfa6d9d 100644
--- a/doc/tarlz.texi
+++ b/doc/tarlz.texi
@@ -6,8 +6,8 @@
@finalout
@c %**end of header
-@set UPDATED 14 June 2021
-@set VERSION 0.21
+@set UPDATED 5 January 2022
+@set VERSION 0.22
@dircategory Data Compression
@direntry
@@ -50,7 +50,7 @@ This manual is for Tarlz (version @value{VERSION}, @value{UPDATED}).
@end menu
@sp 1
-Copyright @copyright{} 2013-2021 Antonio Diaz Diaz.
+Copyright @copyright{} 2013-2022 Antonio Diaz Diaz.
This manual is free documentation: you have unlimited permission to copy,
distribute, and modify it.
@@ -137,8 +137,9 @@ tarlz [@var{options}] [@var{files}]
@end example
@noindent
-All operations except @samp{--concatenate} operate on whole trees if any
-@var{file} is a directory. Tarlz overwrites output files without warning.
+All operations except @samp{--concatenate} and @samp{--compress} operate on
+whole trees if any @var{file} is a directory. All operations except
+@samp{--compress} overwrite output files without warning.
On archive creation or appending tarlz archives the files specified, but
removes from member names any leading and trailing slashes and any file name
@@ -467,12 +468,13 @@ values range from 1 to 1024. The default value is 64.
@item --check-lib
Compare the
@uref{http://www.nongnu.org/lzip/manual/lzlib_manual.html#Library-version,,version of lzlib}
-used to compile tarlz with the version actually being used and exit. Report
-any differences found. Exit with error status 1 if differences are found. A
-mismatch may indicate that lzlib is not correctly installed or that a
-different version of lzlib has been installed after compiling tarlz.
-@w{@samp{tarlz -v --check-lib}} shows the version of lzlib being used and
-the value of @samp{LZ_API_VERSION} (if defined).
+used to compile tarlz with the version actually being used at run time and
+exit. Report any differences found. Exit with error status 1 if differences
+are found. A mismatch may indicate that lzlib is not correctly installed or
+that a different version of lzlib has been installed after compiling tarlz.
+Exit with error status 2 if LZ_API_VERSION and LZ_version_string don't
+match. @w{@samp{tarlz -v --check-lib}} shows the version of lzlib being used
+and the value of LZ_API_VERSION (if defined).
@ifnothtml
@xref{Library version,,,lzlib}.
@end ifnothtml
@@ -671,10 +673,11 @@ CRC32-C (Castagnoli) of the extended header data excluding the 8 bytes
representing the CRC <value> itself. The <value> is represented as 8
hexadecimal digits in big endian order,
@w{@samp{22 GNU.crc32=00000000\n}}. The keyword of the CRC record is
-protected by the CRC to guarante that corruption is always detected
-(except in case of CRC collision). A CRC was chosen because a checksum
-is too weak for a potentially large list of variable sized records. A
-checksum can't detect simple errors like the swapping of two bytes.
+protected by the CRC to guarante that corruption is always detected when
+using @samp{--missing-crc} (except in case of CRC collision). A CRC was
+chosen because a checksum is too weak for a potentially large list of
+variable sized records. A checksum can't detect simple errors like the
+swapping of two bytes.
@end table
@@ -926,16 +929,16 @@ with the file data read from the file system. The muxer collects processed
packets from the workers, and writes them to the archive.
@verbatim
-,--------,
+.--------.
| data|---> to each worker below
-| | ,------------,
+| | .------------.
| file | ,-->| worker 0 |--,
| system | | `------------' |
-| | ,---------, | ,------------, | ,-------, ,---------,
+| | .---------. | .------------. | .-------. .---------.
|metadata|--->| grouper |-+-->| worker 1 |--+-->| muxer |-->| archive |
`--------' `---------' | `------------' | `-------' `---------'
| ... |
- | ,------------, |
+ | .------------. |
`-->| worker N-1 |--'
`------------'
@end verbatim
@@ -947,17 +950,17 @@ access files in the file system either to read them (diff) or write them
(extract). As in plzip, each worker reads members directly from the archive.
@verbatim
-,--------,
+.--------.
| file |<---> data to/from each worker below
| system |
-`--------' ,------------,
+`--------' .------------.
,-->| worker 0 |--,
| `------------' |
-,---------, | ,------------, | ,-------, ,--------,
+.---------. | .------------. | .-------. .--------.
| archive |-+-->| worker 1 |--+-->| muxer |-->| stdout |
`---------' | `------------' | `-------' | stderr |
| ... | `--------'
- | ,------------, |
+ | .------------. |
`-->| worker N-1 |--'
`------------'
@end verbatim
@@ -1041,7 +1044,7 @@ time tarlz -tf silesia.tar.lz (0.020s)
On the other hand, multi-threaded @samp{--list} won't detect corruption in
the tar member data because it only decodes the part of each lzip member
corresponding to the tar member header. This is another reason why the tar
-headers must provide its own integrity checking.
+headers must provide their own integrity checking.
@sp 1
@section Limitations of multi-threaded extraction
@@ -1212,7 +1215,8 @@ for all eternity, if not longer.
If you find a bug in tarlz, please send electronic mail to
@email{lzip-bug@@nongnu.org}. Include the version number, which you can
-find by running @w{@samp{tarlz --version}}.
+find by running @w{@samp{tarlz --version}} and
+@w{@samp{tarlz -v --check-lib}}.
@node Concept index
diff --git a/exclude.cc b/exclude.cc
index e52e6d8..876e04f 100644
--- a/exclude.cc
+++ b/exclude.cc
@@ -1,5 +1,5 @@
/* Tarlz - Archiver with multimember lzip compression
- Copyright (C) 2013-2021 Antonio Diaz Diaz.
+ Copyright (C) 2013-2022 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
diff --git a/extended.cc b/extended.cc
index ad65eb7..721634a 100644
--- a/extended.cc
+++ b/extended.cc
@@ -1,5 +1,5 @@
/* Tarlz - Archiver with multimember lzip compression
- Copyright (C) 2013-2021 Antonio Diaz Diaz.
+ Copyright (C) 2013-2022 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
@@ -159,7 +159,7 @@ void Extended::unknown_keyword( const char * const buf,
}
-// Returns the extended block size, or -1 if error.
+// Return the size of the extended block, or -1 if error.
long long Extended::format_block( Resizable_buffer & rbuf ) const
{
if( empty() ) return 0; // no extended data
@@ -295,7 +295,7 @@ void Extended::fill_from_ustar( const Tar_header header )
}
-/* Returns file size from record or from ustar header, and resets file_size_.
+/* Return file size from record or from ustar header, and reset file_size_.
Used for fast parsing of headers in uncompressed archives.
*/
long long Extended::get_file_size_and_reset( const Tar_header header )
diff --git a/lzip_index.cc b/lzip_index.cc
index ae14771..baf4513 100644
--- a/lzip_index.cc
+++ b/lzip_index.cc
@@ -1,5 +1,5 @@
/* Tarlz - Archiver with multimember lzip compression
- Copyright (C) 2013-2021 Antonio Diaz Diaz.
+ Copyright (C) 2013-2022 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
diff --git a/lzip_index.h b/lzip_index.h
index f47792f..dd6ad67 100644
--- a/lzip_index.h
+++ b/lzip_index.h
@@ -1,5 +1,5 @@
/* Tarlz - Archiver with multimember lzip compression
- Copyright (C) 2013-2021 Antonio Diaz Diaz.
+ Copyright (C) 2013-2022 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
diff --git a/main.cc b/main.cc
index 38bcf63..e04d37d 100644
--- a/main.cc
+++ b/main.cc
@@ -1,5 +1,5 @@
/* Tarlz - Archiver with multimember lzip compression
- Copyright (C) 2013-2021 Antonio Diaz Diaz.
+ Copyright (C) 2013-2022 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
@@ -56,7 +56,7 @@ const char * const program_name = "tarlz";
namespace {
-const char * const program_year = "2021";
+const char * const program_year = "2022";
const char * invocation_name = program_name; // default value
@@ -146,17 +146,44 @@ void show_version()
}
+int check_lzlib_ver() // <major>.<minor> or <major>.<minor>[a-z.-]*
+ {
+#if defined LZ_API_VERSION && LZ_API_VERSION >= 1012
+ const unsigned char * p = (unsigned char *)LZ_version_string;
+ unsigned major = 0, minor = 0;
+ while( major < 100000 && isdigit( *p ) )
+ { major *= 10; major += *p - '0'; ++p; }
+ if( *p == '.' ) ++p;
+ else
+out: { show_error( "Invalid LZ_version_string in lzlib.h" ); return 2; }
+ while( minor < 100 && isdigit( *p ) )
+ { minor *= 10; minor += *p - '0'; ++p; }
+ if( *p && *p != '-' && *p != '.' && !std::islower( *p ) ) goto out;
+ const unsigned version = major * 1000 + minor;
+ if( LZ_API_VERSION != version )
+ {
+ if( verbosity >= 0 )
+ std::fprintf( stderr, "%s: Version mismatch in lzlib.h: "
+ "LZ_API_VERSION = %u, should be %u.\n",
+ program_name, LZ_API_VERSION, version );
+ return 2;
+ }
+#endif
+ return 0;
+ }
+
+
int check_lib()
{
- bool warning = false;
+ int retval = check_lzlib_ver();
if( std::strcmp( LZ_version_string, LZ_version() ) != 0 )
- { warning = true;
+ { set_retval( retval, 1 );
if( verbosity >= 0 )
std::printf( "warning: LZ_version_string != LZ_version() (%s vs %s)\n",
LZ_version_string, LZ_version() ); }
#if defined LZ_API_VERSION && LZ_API_VERSION >= 1012
if( LZ_API_VERSION != LZ_api_version() )
- { warning = true;
+ { set_retval( retval, 1 );
if( verbosity >= 0 )
std::printf( "warning: LZ_API_VERSION != LZ_api_version() (%u vs %u)\n",
LZ_API_VERSION, LZ_api_version() ); }
@@ -173,20 +200,54 @@ int check_lib()
"Using an unknown LZ_API_VERSION\n", LZ_API_VERSION );
#endif
}
- return warning;
+ return retval;
+ }
+
+
+// separate large numbers >= 100_000 in groups of 3 digits using '_'
+const char * format_num3( unsigned long long num )
+ {
+ const char * const si_prefix = "kMGTPEZY";
+ const char * const binary_prefix = "KMGTPEZY";
+ enum { buffers = 8, bufsize = 4 * sizeof (long long) };
+ 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
+ char prefix = 0; // try binary first, then si
+ for( int i = 0; i < 8 && num >= 1024 && num % 1024 == 0; ++i )
+ { num /= 1024; prefix = binary_prefix[i]; }
+ if( prefix ) *(--p) = 'i';
+ else
+ for( int i = 0; i < 8 && num >= 1000 && num % 1000 == 0; ++i )
+ { num /= 1000; prefix = si_prefix[i]; }
+ if( prefix ) *(--p) = prefix;
+ const bool split = num >= 100000;
+
+ for( int i = 0; ; )
+ {
+ *(--p) = num % 10 + '0'; num /= 10; if( num == 0 ) break;
+ if( split && ++i >= 3 ) { i = 0; *(--p) = '_'; }
+ }
+ return p;
}
-unsigned long long getnum( const char * const ptr,
+unsigned long long getnum( const char * const arg,
+ const char * const option_name,
const unsigned long long llimit,
const unsigned long long ulimit )
{
char * tail;
errno = 0;
- unsigned long long result = strtoull( ptr, &tail, 0 );
- if( tail == ptr )
+ unsigned long long result = strtoull( arg, &tail, 0 );
+ if( tail == arg )
{
- show_error( "Bad or missing numerical argument.", 0, true );
+ if( verbosity >= 0 )
+ std::fprintf( stderr, "%s: Bad or missing numerical argument in "
+ "option '%s'.\n", program_name, option_name );
std::exit( 1 );
}
@@ -208,7 +269,9 @@ unsigned long long getnum( const char * const ptr,
}
if( exponent <= 0 )
{
- show_error( "Bad multiplier in numerical argument.", 0, true );
+ if( verbosity >= 0 )
+ std::fprintf( stderr, "%s: Bad multiplier in numerical argument of "
+ "option '%s'.\n", program_name, option_name );
std::exit( 1 );
}
for( int i = 0; i < exponent; ++i )
@@ -220,7 +283,10 @@ unsigned long long getnum( const char * const ptr,
if( !errno && ( result < llimit || result > ulimit ) ) errno = ERANGE;
if( errno )
{
- show_error( "Numerical argument out of limits." );
+ if( verbosity >= 0 )
+ std::fprintf( stderr, "%s: Numerical argument out of limits [%s,%s] "
+ "in option '%s'.\n", program_name, format_num3( llimit ),
+ format_num3( ulimit ), option_name );
std::exit( 1 );
}
return result;
@@ -249,10 +315,10 @@ void set_mode( Program_mode & program_mode, const Program_mode new_mode )
}
-void set_mtime( long long & mtime, const char * arg )
+void set_mtime( long long & mtime, const char * arg, const char * const pn )
{
if( *arg == '@' )
- { mtime = getnum( arg + 1, 0, ( 1ULL << 33 ) - 1 ); return; }
+ { mtime = getnum( arg + 1, pn, 0, ( 1ULL << 33 ) - 1 ); return; }
else if( *arg == '.' || *arg == '/' )
{
struct stat st;
@@ -276,22 +342,22 @@ void set_mtime( long long & mtime, const char * arg )
}
-void set_owner( int & owner, const char * const arg )
+void set_owner( int & 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, 0, INT_MAX );
+ 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 ); }
}
-void set_group( int & group, const char * const arg )
+void set_group( int & 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, 0, INT_MAX );
+ 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 ); }
}
@@ -308,7 +374,12 @@ int open_instream( const std::string & name )
{
const int infd = open( name.c_str(), O_RDONLY | O_BINARY );
if( infd < 0 )
- show_file_error( name.c_str(), "Can't open for reading", errno );
+ { show_file_error( name.c_str(), "Can't open for reading", errno );
+ 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." );
+ close( infd ); return -1; }
return infd;
}
@@ -460,6 +531,9 @@ int main( const int argc, const char * const argv[] )
if( max_workers < 1 || max_workers > INT_MAX / (int)sizeof (pthread_t) )
max_workers = INT_MAX / sizeof (pthread_t);
+ const char * f_pn = 0;
+ const char * o_pn = 0;
+ const char * z_pn = 0;
for( int argind = 0; argind < parser.arguments(); ++argind )
{
const int code = parser.code( argind );
@@ -470,6 +544,7 @@ int main( const int argc, const char * const argv[] )
if( parser.argument( argind ) != "-" ) cl_opts.filenames_given = true;
++cl_opts.num_files; continue;
}
+ const char * const pn = parser.parsed_name( argind ).c_str();
const std::string & sarg = parser.argument( argind );
const char * const arg = sarg.c_str();
switch( code )
@@ -478,16 +553,16 @@ int main( const int argc, const char * const argv[] )
case '5': case '6': case '7': case '8': case '9':
cl_opts.level = code - '0'; break;
case 'A': set_mode( cl_opts.program_mode, m_concatenate ); break;
- case 'B': cl_opts.data_size = getnum( arg, min_data_size, max_data_size );
- break;
+ case 'B': cl_opts.data_size =
+ getnum( arg, pn, min_data_size, max_data_size ); break;
case 'c': set_mode( cl_opts.program_mode, m_create ); break;
case 'C': break; // skip chdir
case 'd': set_mode( cl_opts.program_mode, m_diff ); break;
- case 'f': set_archive_name( cl_opts.archive_name, sarg ); break;
+ case 'f': set_archive_name( cl_opts.archive_name, sarg ); f_pn = pn; break;
case 'h': cl_opts.dereference = true; break;
case 'H': break; // ignore format
- case 'n': cl_opts.num_workers = getnum( arg, 0, max_workers ); break;
- case 'o': cl_opts.output_filename = sarg; break;
+ case 'n': cl_opts.num_workers = getnum( arg, pn, 0, max_workers ); break;
+ case 'o': cl_opts.output_filename = sarg; o_pn = pn; break;
case 'p': cl_opts.preserve_permissions = true; break;
case 'q': verbosity = -1; break;
case 'r': set_mode( cl_opts.program_mode, m_append ); break;
@@ -495,25 +570,25 @@ int main( const int argc, const char * const argv[] )
case 'v': if( verbosity < 4 ) ++verbosity; break;
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 ); break;
- case opt_ano: set_owner( cl_opts.owner, "root" );
- set_group( cl_opts.group, "root" ); 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_aso: cl_opts.solidity = asolid; break;
case opt_bso: cl_opts.solidity = bsolid; break;
case opt_crc: cl_opts.missing_crc = true; break;
case opt_chk: return check_lib();
- case opt_dbg: cl_opts.debug_level = getnum( arg, 0, 3 ); break;
+ case opt_dbg: cl_opts.debug_level = getnum( arg, pn, 0, 3 ); break;
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 ); break;
+ case opt_grp: set_group( cl_opts.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 ); break;
+ case opt_mti: set_mtime( cl_opts.mtime, arg, pn ); break;
case opt_nso: cl_opts.solidity = no_solid; break;
- case opt_out: cl_opts.out_slots = getnum( arg, 1, 1024 ); break;
- case opt_own: set_owner( cl_opts.owner, arg ); 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_per: cl_opts.permissive = true; break;
case opt_sol: cl_opts.solidity = solid; break;
case opt_un: cl_opts.level = -1; break;
@@ -522,6 +597,21 @@ 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( verbosity >= 0 )
+ std::fprintf( stderr, "%s: Option '%s' can only be used with "
+ "'-z, --compress'.\n", program_name, o_pn );
+ return 1;
+ }
+ if( cl_opts.program_mode == m_compress && f_pn )
+ {
+ if( verbosity >= 0 )
+ std::fprintf( stderr, "%s: Option '%s' can't be used with '%s'.\n",
+ program_name, f_pn, z_pn );
+ return 1;
+ }
+
#if !defined LZ_API_VERSION || LZ_API_VERSION < 1012 // compile-time test
#error "lzlib 1.12 or newer needed."
#endif
diff --git a/tarlz.h b/tarlz.h
index 3323e60..19c913a 100644
--- a/tarlz.h
+++ b/tarlz.h
@@ -1,5 +1,5 @@
/* Tarlz - Archiver with multimember lzip compression
- Copyright (C) 2013-2021 Antonio Diaz Diaz.
+ Copyright (C) 2013-2022 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
@@ -201,6 +201,7 @@ public:
void update_byte( uint32_t & crc, const uint8_t byte ) const
{ crc = data[(crc^byte)&0xFF] ^ ( crc >> 8 ); }
+ // about as fast as it is possible without messing with endianness
void update_buf( uint32_t & crc, const uint8_t * const buffer,
const int size ) const
{
@@ -392,6 +393,9 @@ struct Cl_options // command line options
};
+inline void set_retval( int & retval, const int new_val )
+ { if( retval < new_val ) retval = new_val; }
+
const char * const bad_magic_msg = "Bad magic number (file not in lzip format).";
const char * const bad_dict_msg = "Invalid dictionary size in member header.";
const char * const corrupt_mm_msg = "Corrupt header in multimember file.";
diff --git a/testsuite/check.sh b/testsuite/check.sh
index 25b7055..56aafdb 100755
--- a/testsuite/check.sh
+++ b/testsuite/check.sh
@@ -1,6 +1,6 @@
#! /bin/sh
# check script for Tarlz - Archiver with multimember lzip compression
-# Copyright (C) 2013-2021 Antonio Diaz Diaz.
+# Copyright (C) 2013-2022 Antonio Diaz Diaz.
#
# This script is free software: you have unlimited permission
# to copy, distribute, and modify it.
@@ -115,6 +115,7 @@ cyg_symlink() { [ ${lwarnc} = 0 ] &&
# test3_bad3.tar.lz because their headers are intact.
"${TARLZ}" --check-lib # just print warning
+[ $? != 2 ] || test_failed $LINENO # unless bad lzlib.h
printf "testing tarlz-%s..." "$2"
"${TARLZ}" -q -tf "${in}"
@@ -158,6 +159,8 @@ touch empty.tar.lz empty.tlz # list an empty lz file
"${TARLZ}" -q -tf empty.tlz
[ $? = 2 ] || test_failed $LINENO
rm -f empty.tar.lz empty.tlz || framework_failure
+"${TARLZ}" -q -cd # test mixed operations
+[ $? = 1 ] || test_failed $LINENO
"${TARLZ}" -q -cr
[ $? = 1 ] || test_failed $LINENO
"${TARLZ}" -q -ct
@@ -168,6 +171,14 @@ rm -f empty.tar.lz empty.tlz || framework_failure
[ $? = 1 ] || test_failed $LINENO
"${TARLZ}" -q -ctx
[ $? = 1 ] || test_failed $LINENO
+for i in A c d r t x -delete ; do # test -o with operations other than -z
+ "${TARLZ}" -q -$i -o -
+ [ $? = 1 ] || test_failed $LINENO $i
+done
+"${TARLZ}" -q -z -f -
+[ $? = 1 ] || test_failed $LINENO
+"${TARLZ}" -q -z .
+[ $? = 1 ] || test_failed $LINENO
"${TARLZ}" -q -tf "${in_tar_lz}" ""
[ $? = 1 ] || test_failed $LINENO
"${TARLZ}" --help > /dev/null || test_failed $LINENO
@@ -1059,6 +1070,12 @@ rm -f out3z.tar.lz || framework_failure
[ $? = 1 ] || test_failed $LINENO
cmp out outz.tar.lz || test_failed $LINENO
cmp out3 out3z.tar.lz || test_failed $LINENO
+if [ "${ln_works}" = yes ] ; then
+ ln -s outz.tar loutz.tar || framework_failure
+ "${TARLZ}" -0 -z loutz.tar || test_failed $LINENO
+ cmp loutz.tar.lz outz.tar.lz || test_failed $LINENO
+ rm -f loutz.tar.lz loutz.tar || framework_failure
+fi
rm -f out out3 outz.tar.lz out3z.tar.lz || framework_failure
#
for i in --solid --no-solid ; do