1
0
Fork 0

Adding upstream version 0.23.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-17 21:17:35 +01:00
parent 22f7f3575c
commit 9a8733dd3b
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
39 changed files with 2213 additions and 1444 deletions

136
tarlz.h
View file

@ -57,7 +57,7 @@ inline void init_tar_header( Tar_header header ) // set magic and version
}
inline void print_octal( uint8_t * const buf, int size, unsigned long long num )
{ while( --size >= 0 ) { buf[size] = '0' + ( num % 8 ); num /= 8; } }
{ while( --size >= 0 ) { buf[size] = num % 8 + '0'; num /= 8; } }
// Round "size" to the next multiple of header size (512).
@ -70,6 +70,14 @@ inline unsigned long long round_up( const unsigned long long size )
}
inline int decimal_digits( unsigned long long value )
{
int digits = 1;
while( value >= 10 ) { value /= 10; ++digits; }
return digits;
}
inline bool dotdot_at_i( const char * const filename, const int i )
{
return ( filename[i] == '.' && filename[i+1] == '.' &&
@ -119,12 +127,45 @@ public:
};
class Extended // stores metadata from/for extended records
inline bool uid_in_ustar_range( const long long uid ) // also for gid
{ return uid >= 0 && uid < 1 << 21; }
inline bool time_in_ustar_range( const long long seconds )
{ return seconds >= 0 && seconds < 1LL << 33; }
/* The sign of the seconds field applies to the whole time value.
A nanoseconds value out of range means an invalid time. */
class Etime // time since (or before) the epoch
{
long long sec_;
int nsec_; // range [0, 999_999_999]
public:
Etime() : sec_( 0 ), nsec_( -1 ) {}
void reset() { sec_ = 0; nsec_ = -1; }
void set( const long long s ) { sec_ = s; nsec_ = 0; }
long long sec() const { return sec_; }
int nsec() const { return nsec_; }
bool isvalid() const { return nsec_ >= 0 && nsec_ <= 999999999; }
bool out_of_ustar_range() const
{ return isvalid() && !time_in_ustar_range( sec_ ); }
unsigned decimal_size() const;
unsigned print( char * const buf ) const;
bool parse( const char * const ptr, const char ** const tailp,
const long long size );
};
class Extended // stores metadata from/for extended records
{
static std::vector< std::string > unknown_keywords; // already diagnosed
std::string linkpath_; // these are the real metadata
std::string path_;
long long file_size_; // >= 0 && <= max_file_size
long long uid_, gid_; // may not fit in unsigned int
Etime atime_, mtime_;
// cached sizes; if full_size_ < 0 they must be recalculated
mutable long long edsize_; // extended data size
@ -133,6 +174,10 @@ class Extended // stores metadata from/for extended records
mutable long long linkpath_recsize_;
mutable long long path_recsize_;
mutable int file_size_recsize_;
mutable int uid_recsize_;
mutable int gid_recsize_;
mutable int atime_recsize_;
mutable int mtime_recsize_;
// true if CRC present in parsed or formatted records
mutable bool crc_present_;
@ -143,29 +188,47 @@ class Extended // stores metadata from/for extended records
public:
static const std::string crc_record;
std::string removed_prefix;
Extended()
: file_size_( 0 ), edsize_( 0 ), padded_edsize_( 0 ), full_size_( 0 ),
linkpath_recsize_( 0 ), path_recsize_( 0 ), file_size_recsize_( 0 ),
: file_size_( 0 ), uid_( -1 ), gid_( -1 ), edsize_( 0 ),
padded_edsize_( 0 ), full_size_( 0 ), linkpath_recsize_( 0 ),
path_recsize_( 0 ), file_size_recsize_( 0 ), uid_recsize_( 0 ),
gid_recsize_( 0 ), atime_recsize_( 0 ), mtime_recsize_( 0 ),
crc_present_( false ) {}
void reset()
{ linkpath_.clear(); path_.clear(); file_size_ = 0; edsize_ = 0;
padded_edsize_ = 0; full_size_ = 0; linkpath_recsize_ = 0;
path_recsize_ = 0; file_size_recsize_ = 0; crc_present_ = false; }
{ linkpath_.clear(); path_.clear(); file_size_ = 0; uid_ = -1; gid_ = -1;
atime_.reset(); mtime_.reset(); edsize_ = 0; padded_edsize_ = 0;
full_size_ = 0; linkpath_recsize_ = 0; path_recsize_ = 0;
file_size_recsize_ = 0; uid_recsize_ = 0; gid_recsize_ = 0;
atime_recsize_ = 0; mtime_recsize_ = 0; crc_present_ = false;
removed_prefix.clear(); }
bool empty() const
{ return linkpath_.empty() && path_.empty() && file_size_ == 0; }
{ return linkpath_.empty() && path_.empty() && file_size_ == 0 &&
uid_ < 0 && gid_ < 0 &&
!atime_.out_of_ustar_range() && !mtime_.out_of_ustar_range(); }
const std::string & linkpath() const { return linkpath_; }
const std::string & path() const { return path_; }
long long file_size() const { return file_size_; }
long long get_file_size_and_reset( const Tar_header header );
long long get_uid() const { return uid_; }
long long get_gid() const { return gid_; }
const Etime & atime() const { return atime_; }
const Etime & mtime() const { return mtime_; }
void linkpath( const char * const lp ) { linkpath_ = lp; full_size_ = -1; }
void path( const char * const p ) { path_ = p; full_size_ = -1; }
void file_size( const long long fs ) { full_size_ = -1;
file_size_ = ( fs >= 0 && fs <= max_file_size ) ? fs : 0; }
bool set_uid( const long long id )
{ if( id >= 0 ) { uid_ = id; full_size_ = -1; } return id >= 0; }
bool set_gid( const long long id )
{ if( id >= 0 ) { gid_ = id; full_size_ = -1; } return id >= 0; }
void set_atime( const long long s ) { atime_.set( s ); full_size_ = -1; }
void set_mtime( const long long s ) { mtime_.set( s ); full_size_ = -1; }
long long full_size() const
{ if( full_size_ < 0 ) calculate_sizes(); return full_size_; }
@ -269,10 +332,10 @@ const uint8_t lzip_magic[4] = { 0x4C, 0x5A, 0x49, 0x50 }; // "LZIP"
struct Lzip_header
{
uint8_t data[6]; // 0-3 magic bytes
enum { size = 6 };
uint8_t data[size]; // 0-3 magic bytes
// 4 version
// 5 coded dictionary size
enum { size = 6 };
bool verify_magic() const
{ return ( std::memcmp( data, lzip_magic, 4 ) == 0 ); }
@ -283,6 +346,7 @@ struct Lzip_header
if( data[i] != lzip_magic[i] ) return false;
return ( sz > 0 );
}
bool verify_corrupt() const // detect corrupt header
{
int matches = 0;
@ -310,10 +374,10 @@ struct Lzip_header
struct Lzip_trailer
{
uint8_t data[20]; // 0-3 CRC32 of the uncompressed data
enum { size = 20 };
uint8_t data[size]; // 0-3 CRC32 of the uncompressed data
// 4-11 size of the uncompressed data
// 12-19 member size including header and trailer
enum { size = 20 };
unsigned data_crc() const
{
@ -356,12 +420,15 @@ enum Program_mode { m_none, m_append, m_compress, m_concatenate, m_create,
m_delete, m_diff, m_extract, m_list };
enum Solidity { no_solid, bsolid, dsolid, asolid, solid };
class Arg_parser;
struct Cl_options // command line options
{
const Arg_parser & parser;
std::string archive_name;
std::string output_filename;
long long mtime;
long long uid;
long long gid;
Program_mode program_mode;
Solidity solidity;
int data_size;
@ -370,29 +437,28 @@ struct Cl_options // command line options
int num_files;
int num_workers; // start this many worker threads
int out_slots;
int owner;
int group;
bool dereference;
bool filenames_given;
bool ignore_ids;
bool ignore_overflow;
bool keep_damaged;
bool missing_crc;
bool mtime_set;
bool permissive;
bool preserve_permissions;
bool warn_newer;
Cl_options( const Arg_parser & ap )
: parser( ap ), mtime( -1 ), program_mode( m_none ), solidity( bsolid ),
data_size( 0 ), debug_level( 0 ), level( 6 ), num_files( 0 ),
num_workers( -1 ), out_slots( 64 ), owner( -1 ), group( -1 ),
dereference( false ), filenames_given( false ), ignore_ids( false ),
keep_damaged( false ), missing_crc( false ), permissive( false ),
preserve_permissions( false ), warn_newer( false ) {}
: parser( ap ), mtime( 0 ), uid( -1 ), gid( -1 ), program_mode( m_none ),
solidity( bsolid ), data_size( 0 ), debug_level( 0 ), level( 6 ),
num_files( 0 ), num_workers( -1 ), out_slots( 64 ), dereference( false ),
filenames_given( false ), ignore_ids( false ), ignore_overflow( false ),
keep_damaged( false ), missing_crc( false ), mtime_set( false ),
permissive( false ), preserve_permissions( false ), warn_newer( false ) {}
bool to_stdout() const { return output_filename == "-"; }
};
inline void set_retval( int & retval, const int new_val )
{ if( retval < new_val ) retval = new_val; }
@ -403,15 +469,23 @@ const char * const trailing_msg = "Trailing data not allowed.";
const char * const bad_hdr_msg = "Corrupt or invalid tar header.";
const char * const gblrec_msg = "Error in global extended records.";
const char * const extrec_msg = "Error in extended records.";
const char * const mcrc_msg = "Missing CRC in extended records.";
const char * const miscrc_msg = "Missing CRC in extended records.";
const char * const misrec_msg = "Missing extended records.";
const char * const longrec_msg = "Extended records are too long.";
const char * const end_msg = "Archive ends unexpectedly.";
const char * const mem_msg = "Not enough memory.";
const char * const mem_msg2 = "Not enough memory. Try a lower compression level.";
const char * const fv_msg1 = "Format violation: extended header followed by EOF blocks.";
const char * const fv_msg1 = "Format violation: extended header followed by EOA blocks.";
const char * const fv_msg2 = "Format violation: extended header followed by global header.";
const char * const fv_msg3 = "Format violation: consecutive extended headers found.";
const char * const posix_msg = "This does not look like a POSIX tar archive.";
const char * const posix_lz_msg = "This does not look like a POSIX tar.lz archive.";
const char * const eclosa_msg = "Error closing archive";
const char * const eclosf_msg = "Error closing file";
const char * const nfound_msg = "Not found in archive.";
const char * const seek_msg = "Seek error";
const char * const werr_msg = "Write error";
const char * const chdir_msg = "Error changing working directory";
// defined in common.cc
void xinit_mutex( pthread_mutex_t * const mutex );
@ -441,15 +515,17 @@ mode_t get_umask();
bool make_path( const std::string & name );
// defined in compress.cc
int compress( Cl_options & cl_opts );
int compress( const Cl_options & cl_opts );
// defined in create.cc
bool copy_file( const int infd, const int outfd, const long long max_size = -1 );
bool writeblock_wrapper( const int outfd, const uint8_t * const buffer,
const int size );
bool write_eof_records( const int outfd, const bool compressed );
bool write_eoa_records( const int outfd, const bool compressed );
const char * remove_leading_dotslash( const char * const filename,
const bool dotdot = false );
std::string * const removed_prefixp, const bool dotdot = false );
bool print_removed_prefix( const std::string & prefix,
std::string * const msgp = 0 );
bool fill_headers( const char * const filename, Extended & extended,
Tar_header header, long long & file_size, const int flag );
bool block_is_full( const long long extended_size,
@ -462,11 +538,10 @@ unsigned ustar_chksum( const Tar_header header );
bool verify_ustar_chksum( const Tar_header header );
bool has_lz_ext( const std::string & name );
int concatenate( const Cl_options & cl_opts );
int encode( Cl_options & cl_opts );
int encode( const Cl_options & cl_opts );
// defined in create_lz.cc
int encode_lz( const Cl_options & cl_opts, const char * const archive_namep,
const int dictionary_size, const int match_len_limit,
const int outfd );
// defined in decode.cc
@ -522,8 +597,13 @@ int open_outstream( const std::string & name, const bool create = true,
void exit_fail_mt( const int retval = 1 ); // terminate the program
void show_error( const char * const msg, const int errcode = 0,
const bool help = false );
bool format_error( Resizable_buffer & rbuf, const int errcode,
const char * const format, ... );
void print_error( const int errcode, const char * const format, ... );
void format_file_error( std::string & estr, const char * const filename,
const char * const msg, const int errcode = 0 );
bool format_file_error( Resizable_buffer & rbuf, const char * const filename,
const char * const msg, const int errcode = 0 );
void show_file_error( const char * const filename, const char * const msg,
const int errcode = 0 );
void internal_error( const char * const msg );