Adding upstream version 0.24.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
9a8733dd3b
commit
4f5d0de2b2
33 changed files with 905 additions and 882 deletions
102
decode.cc
102
decode.cc
|
@ -1,5 +1,5 @@
|
|||
/* Tarlz - Archiver with multimember lzip compression
|
||||
Copyright (C) 2013-2022 Antonio Diaz Diaz.
|
||||
Copyright (C) 2013-2023 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
|
||||
|
@ -21,7 +21,7 @@
|
|||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h> // for lzlib.h
|
||||
#include <unistd.h>
|
||||
#include <utime.h>
|
||||
|
@ -246,9 +246,37 @@ void format_file_diff( std::string & ostr, const char * const filename,
|
|||
{ if( verbosity >= 0 )
|
||||
{ ostr += filename; ostr += ": "; ostr += msg; ostr += '\n'; } }
|
||||
|
||||
|
||||
bool option_C_present( const Arg_parser & parser )
|
||||
{
|
||||
for( int i = 0; i < parser.arguments(); ++i )
|
||||
if( parser.code( i ) == 'C' ) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool option_C_after_filename( const Arg_parser & parser )
|
||||
{
|
||||
for( int i = 0; i < parser.arguments(); ++i )
|
||||
if( nonempty_arg( parser, i ) )
|
||||
while( ++i < parser.arguments() )
|
||||
if( parser.code( i ) == 'C' ) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
|
||||
|
||||
mode_t get_umask()
|
||||
{
|
||||
static mode_t mask = 0; // read once, cache the result
|
||||
static bool first_call = true;
|
||||
if( first_call ) { first_call = false; mask = umask( 0 ); umask( mask );
|
||||
mask &= S_IRWXU | S_IRWXG | S_IRWXO; }
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
bool compare_file_type( std::string & estr, std::string & ostr,
|
||||
const Cl_options & cl_opts,
|
||||
const Extended & extended, const Tar_header header )
|
||||
|
@ -380,32 +408,37 @@ int decode( const Cl_options & cl_opts )
|
|||
const Archive_descriptor ad( cl_opts.archive_name );
|
||||
if( ad.infd < 0 ) return 1;
|
||||
|
||||
// Execute -C options and mark filenames to be compared, extracted or listed.
|
||||
// name_pending is of type char instead of bool to allow concurrent update.
|
||||
std::vector< char > name_pending( cl_opts.parser.arguments(), false );
|
||||
for( int i = 0; i < cl_opts.parser.arguments(); ++i )
|
||||
{
|
||||
const int code = cl_opts.parser.code( i );
|
||||
if( code == 'C' && cl_opts.program_mode != m_list )
|
||||
const bool c_present = option_C_present( cl_opts.parser ) &&
|
||||
cl_opts.program_mode != m_list;
|
||||
const bool c_after_name = c_present &&
|
||||
option_C_after_filename( cl_opts.parser );
|
||||
// save current working directory for sequential decoding
|
||||
const int chdir_fd = c_after_name ? open( ".", O_RDONLY | O_DIRECTORY ) : -1;
|
||||
if( c_after_name && chdir_fd < 0 )
|
||||
{ show_error( "Can't save current working directory", errno ); return 1; }
|
||||
if( c_present && !c_after_name ) // execute all -C options
|
||||
for( int i = 0; i < cl_opts.parser.arguments(); ++i )
|
||||
{
|
||||
if( cl_opts.parser.code( i ) != 'C' ) continue;
|
||||
const char * const dir = cl_opts.parser.argument( i ).c_str();
|
||||
if( chdir( dir ) != 0 )
|
||||
{ show_file_error( dir, chdir_msg, errno ); return 1; }
|
||||
}
|
||||
if( !code && cl_opts.parser.argument( i ).size() &&
|
||||
/* Mark filenames to be compared, extracted or listed.
|
||||
name_pending is of type char instead of bool to allow concurrent update. */
|
||||
std::vector< char > name_pending( cl_opts.parser.arguments(), false );
|
||||
for( int i = 0; i < cl_opts.parser.arguments(); ++i )
|
||||
if( nonempty_arg( cl_opts.parser, i ) && // skip opts, empty names
|
||||
!Exclude::excluded( cl_opts.parser.argument( i ).c_str() ) )
|
||||
name_pending[i] = true;
|
||||
}
|
||||
|
||||
// multi-threaded --list is faster even with 1 thread and 1 file in archive
|
||||
// but multi-threaded --diff and --extract probably need at least 2 of each
|
||||
if( ( cl_opts.program_mode == m_diff || cl_opts.program_mode == m_list ||
|
||||
cl_opts.program_mode == m_extract ) && cl_opts.num_workers > 0 &&
|
||||
ad.indexed && ad.lzip_index.members() >= 2 ) // one file + EOA
|
||||
{
|
||||
// show_file_error( ad.namep, "Is compressed seekable" );
|
||||
/* multi-threaded --list is faster even with 1 thread and 1 file in archive
|
||||
but multi-threaded --diff and --extract probably need at least 2 of each.
|
||||
CWD is not per-thread; multi-threaded decode can't be used if a
|
||||
-C option appears after a file name in the command line. */
|
||||
if( cl_opts.num_workers > 0 && !c_after_name && ad.indexed &&
|
||||
ad.lzip_index.members() >= 2 ) // 2 lzip members may be 1 file + EOA
|
||||
return decode_lz( cl_opts, ad, name_pending );
|
||||
}
|
||||
|
||||
Archive_reader ar( ad ); // serial reader
|
||||
Extended extended; // metadata from extended records
|
||||
|
@ -416,7 +449,7 @@ int decode( const Cl_options & cl_opts )
|
|||
Tar_header header;
|
||||
const int ret = ar.read( header, header_size );
|
||||
if( ret != 0 ) { read_error( ar ); if( ar.fatal() ) { retval = ret; break; } }
|
||||
if( ret != 0 || !verify_ustar_chksum( header ) ) // error or EOA
|
||||
if( ret != 0 || !check_ustar_chksum( header ) ) // error or EOA
|
||||
{
|
||||
if( ret == 0 && block_is_zero( header, header_size ) ) // EOA
|
||||
{
|
||||
|
@ -461,20 +494,23 @@ int decode( const Cl_options & cl_opts )
|
|||
|
||||
extended.fill_from_ustar( header ); // copy metadata from header
|
||||
|
||||
// members without name are skipped except when listing
|
||||
if( check_skip_filename( cl_opts, name_pending, extended.path().c_str() ) )
|
||||
retval = skip_member( ar, extended, typeflag );
|
||||
else
|
||||
{
|
||||
print_removed_prefix( extended.removed_prefix );
|
||||
if( cl_opts.program_mode == m_list )
|
||||
retval = list_member( ar, extended, header );
|
||||
else if( extended.path().empty() )
|
||||
retval = skip_member( ar, extended, typeflag );
|
||||
else if( cl_opts.program_mode == m_diff )
|
||||
retval = compare_member( cl_opts, ar, extended, header );
|
||||
else retval = extract_member( cl_opts, ar, extended, header );
|
||||
try {
|
||||
// members without name are skipped except when listing
|
||||
if( check_skip_filename( cl_opts, name_pending, extended.path().c_str(),
|
||||
chdir_fd ) ) retval = skip_member( ar, extended, typeflag );
|
||||
else
|
||||
{
|
||||
print_removed_prefix( extended.removed_prefix );
|
||||
if( cl_opts.program_mode == m_list )
|
||||
retval = list_member( ar, extended, header );
|
||||
else if( extended.path().empty() )
|
||||
retval = skip_member( ar, extended, typeflag );
|
||||
else if( cl_opts.program_mode == m_diff )
|
||||
retval = compare_member( cl_opts, ar, extended, header );
|
||||
else retval = extract_member( cl_opts, ar, extended, header );
|
||||
}
|
||||
}
|
||||
catch( Chdir_error & ) { retval = 1; }
|
||||
extended.reset();
|
||||
if( retval )
|
||||
{ show_error( "Error is not recoverable: exiting now." ); break; }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue