1
0
Fork 0

Merging upstream version 0.8.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-17 21:10:01 +01:00
parent c7152715b0
commit d91c44b5bd
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
28 changed files with 2668 additions and 574 deletions

121
main.cc
View file

@ -40,6 +40,7 @@
#if defined(__OS2__)
#include <io.h>
#endif
#include <lzlib.h>
#include "arg_parser.h"
#include "tarlz.h"
@ -56,21 +57,33 @@ int verbosity = 0;
namespace {
const char * const Program_name = "Tarlz";
const char * const program_name = "tarlz";
const char * const program_year = "2018";
const char * invocation_name = 0;
enum Mode { m_none, m_append, m_create, m_extract, m_list };
enum Mode { m_none, m_append, m_concatenate, m_create, m_extract, m_list };
void show_help()
{
std::printf( "%s - Archiver with multimember lzip compression.\n", Program_name );
std::printf( "\nUsage: %s [options] [files]\n", invocation_name );
std::printf( "Tarlz is a small and simple implementation of the tar archiver. By default\n"
"tarlz creates, lists and extracts archives in a simplified posix pax format\n"
"compressed with lzip on a per file basis. Each tar member is compressed in\n"
"its own lzip member, as well as the end-of-file blocks. This method is fully\n"
"backward compatible with standard tar tools like GNU tar, which treat the\n"
"resulting multimember tar.lz archive like any other tar.lz archive. Tarlz\n"
"can append files to the end of such compressed archives.\n"
"\nThe tarlz file format is a safe posix-style backup format. In case of\n"
"corruption, tarlz can extract all the undamaged members from the tar.lz\n"
"archive, skipping over the damaged members, just like the standard\n"
"(uncompressed) tar. Moreover, the option '--keep-damaged' can be used to\n"
"recover as much data as possible from each damaged member, and lziprecover\n"
"can be used to recover some of the damaged members.\n"
"\nUsage: %s [options] [files]\n", invocation_name );
std::printf( "\nOptions:\n"
" -h, --help display this help and exit\n"
" -V, --version output version information and exit\n"
" -A, --concatenate append tar.lz archives to the end of an archive\n"
" -c, --create create a new archive\n"
" -C, --directory=<dir> change to directory <dir>\n"
" -f, --file=<archive> use archive file <archive>\n"
@ -82,10 +95,15 @@ void show_help()
" -0 .. -9 set compression level [default 6]\n"
" --asolid create solidly compressed appendable archive\n"
" --dsolid create per-directory compressed archive\n"
" --no-solid create per-file compressed archive (default)\n"
" --solid create solidly compressed archive\n"
" --group=<group> use <group> name/id for added files\n"
" --owner=<owner> use <owner> name/id for added files\n"
" --uncompressed don't compress the created archive\n"
" --anonymous equivalent to '--owner=root --group=root'\n"
" --owner=<owner> use <owner> name/ID for files added\n"
" --group=<group> use <group> name/ID for files added\n"
" --keep-damaged don't delete partially extracted files\n"
" --missing-crc exit with error status if missing extended CRC\n"
// " --permissive allow repeated extended headers and records\n"
" --uncompressed don't compress the archive created\n"
"\nExit status: 0 for a normal exit, 1 for environmental problems (file\n"
"not found, invalid flags, I/O errors, etc), 2 to indicate a corrupt or\n"
"invalid input file, 3 for an internal consistency error (eg, bug) which\n"
@ -99,6 +117,7 @@ void show_version()
{
std::printf( "%s %s\n", program_name, PROGVERSION );
std::printf( "Copyright (C) %s Antonio Diaz Diaz.\n", program_year );
std::printf( "Using lzlib %s\n", LZ_version() );
std::printf( "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n" );
@ -280,39 +299,53 @@ int main( const int argc, const char * const argv[] )
std::string archive_name;
Mode program_mode = m_none;
int level = 6; // compression level, < 0 = uncompressed
bool keep_damaged = false;
bool missing_crc = false;
bool permissive = false;
invocation_name = argv[0];
enum { opt_aso = 256, opt_dso, opt_grp, opt_own, opt_sol, opt_un };
if( LZ_version()[0] < '1' )
{ show_error( "Bad library version. At least lzlib 1.0 is required." );
return 1; }
enum { opt_ano = 256, opt_aso, opt_crc, opt_dso, opt_grp, opt_kd, opt_nso,
opt_own, opt_per, opt_sol, opt_un };
const Arg_parser::Option options[] =
{
{ '0', 0, Arg_parser::no },
{ '1', 0, Arg_parser::no },
{ '2', 0, Arg_parser::no },
{ '3', 0, Arg_parser::no },
{ '4', 0, Arg_parser::no },
{ '5', 0, Arg_parser::no },
{ '6', 0, Arg_parser::no },
{ '7', 0, Arg_parser::no },
{ '8', 0, Arg_parser::no },
{ '9', 0, Arg_parser::no },
{ 'c', "create", Arg_parser::no },
{ 'C', "directory", Arg_parser::yes },
{ 'f', "file", Arg_parser::yes },
{ 'h', "help", Arg_parser::no },
{ 'H', "format", Arg_parser::yes },
{ 'q', "quiet", Arg_parser::no },
{ 'r', "append", Arg_parser::no },
{ 't', "list", Arg_parser::no },
{ 'v', "verbose", Arg_parser::no },
{ 'V', "version", Arg_parser::no },
{ 'x', "extract", Arg_parser::no },
{ opt_aso, "asolid", Arg_parser::no },
{ opt_dso, "dsolid", Arg_parser::no },
{ opt_grp, "group", Arg_parser::yes },
{ opt_own, "owner", Arg_parser::yes },
{ opt_sol, "solid", Arg_parser::no },
{ opt_un, "uncompressed", Arg_parser::no },
{ 0 , 0, Arg_parser::no } };
{ '0', 0, Arg_parser::no },
{ '1', 0, Arg_parser::no },
{ '2', 0, Arg_parser::no },
{ '3', 0, Arg_parser::no },
{ '4', 0, Arg_parser::no },
{ '5', 0, Arg_parser::no },
{ '6', 0, Arg_parser::no },
{ '7', 0, Arg_parser::no },
{ '8', 0, Arg_parser::no },
{ '9', 0, Arg_parser::no },
{ 'A', "concatenate", Arg_parser::no },
{ 'c', "create", Arg_parser::no },
{ 'C', "directory", Arg_parser::yes },
{ 'f', "file", Arg_parser::yes },
{ 'h', "help", Arg_parser::no },
{ 'H', "format", Arg_parser::yes },
{ 'q', "quiet", Arg_parser::no },
{ 'r', "append", Arg_parser::no },
{ 't', "list", Arg_parser::no },
{ 'v', "verbose", Arg_parser::no },
{ 'V', "version", Arg_parser::no },
{ 'x', "extract", Arg_parser::no },
{ opt_ano, "anonymous", Arg_parser::no },
{ opt_aso, "asolid", Arg_parser::no },
{ opt_dso, "dsolid", Arg_parser::no },
{ opt_grp, "group", Arg_parser::yes },
{ opt_kd, "keep-damaged", Arg_parser::no },
{ opt_crc, "missing-crc", Arg_parser::no },
{ opt_nso, "no-solid", Arg_parser::no },
{ opt_own, "owner", Arg_parser::yes },
{ opt_per, "permissive", Arg_parser::no },
{ opt_sol, "solid", Arg_parser::no },
{ opt_un, "uncompressed", Arg_parser::no },
{ 0 , 0, Arg_parser::no } };
const Arg_parser parser( argc, argv, options, true );
if( parser.error().size() ) // bad option
@ -330,6 +363,7 @@ int main( const int argc, const char * const argv[] )
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
level = code - '0'; break;
case 'A': set_mode( program_mode, m_concatenate ); break;
case 'c': set_mode( program_mode, m_create ); break;
case 'C': break; // skip chdir
case 'f': if( sarg != "-" ) archive_name = sarg; break;
@ -341,12 +375,17 @@ 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( program_mode, m_extract ); break;
case opt_ano: set_owner( "root" ); set_group( "root" ); break;
case opt_aso: cl_solid = 2; break;
case opt_crc: missing_crc = true; break;
case opt_dso: cl_solid = 1; break;
case opt_grp: set_group( arg ); break;
case opt_kd: keep_damaged = true; break;
case opt_nso: cl_solid = 0; break;
case opt_own: set_owner( arg ); break;
case opt_per: permissive = true; break;
case opt_sol: cl_solid = 3; break;
case opt_un: level = -1; break;
case opt_un: level = -1; break;
default : internal_error( "uncaught option" );
}
} // end process options
@ -358,12 +397,14 @@ int main( const int argc, const char * const argv[] )
switch( program_mode )
{
case m_none: show_error( "Missing operation.", 0, true ); return 2;
case m_none: show_error( "Missing operation.", 0, true ); return 2;
case m_append:
case m_create: return encode( archive_name, parser, filenames, level,
program_mode == m_append );
case m_concatenate: return concatenate( archive_name, parser, filenames );
case m_extract:
case m_list:
return decode( archive_name, parser, filenames, program_mode == m_list );
case m_list: return decode( archive_name, parser, filenames,
keep_damaged, program_mode == m_list,
missing_crc, permissive );
}
}