Merging upstream version 0.22.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
62c16efd2b
commit
61a463b53b
30 changed files with 307 additions and 182 deletions
14
ChangeLog
14
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
|
||||
|
|
4
INSTALL
4
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.
|
||||
|
|
|
@ -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 $@ $<
|
||||
|
|
25
NEWS
25
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.
|
||||
|
|
2
README
2
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.
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
23
arg_parser.h
23
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;
|
||||
|
|
10
common.cc
10
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 )
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
|
|
11
configure
vendored
11
configure
vendored
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
4
create.h
4
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";
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
154
main.cc
154
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;
|
||||
}
|
||||
|
||||
|
||||
unsigned long long getnum( const char * const ptr,
|
||||
// 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 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
|
||||
|
|
6
tarlz.h
6
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.";
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue