From cb1387c92038634c063ee06a24e249b87525f519 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Tue, 23 Jan 2024 06:08:19 +0100 Subject: Merging upstream version 0.25. Signed-off-by: Daniel Baumann --- tarlz.h | 121 ++++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 60 insertions(+), 61 deletions(-) (limited to 'tarlz.h') diff --git a/tarlz.h b/tarlz.h index 2da81dd..16ae6e0 100644 --- a/tarlz.h +++ b/tarlz.h @@ -1,5 +1,5 @@ /* Tarlz - Archiver with multimember lzip compression - Copyright (C) 2013-2022 Antonio Diaz Diaz. + Copyright (C) 2013-2024 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 @@ -16,14 +16,15 @@ */ #include +#include #include #include #include #include -#include #define max_file_size ( LLONG_MAX - header_size ) -enum { header_size = 512 }; +enum { header_size = 512, + max_edata_size = ( INT_MAX / header_size - 2 ) * header_size }; typedef uint8_t Tar_header[header_size]; enum Offsets { @@ -46,7 +47,7 @@ enum Typeflag { const uint8_t ustar_magic[magic_l] = { 0x75, 0x73, 0x74, 0x61, 0x72, 0 }; // "ustar\0" -inline bool verify_ustar_magic( const Tar_header header ) +inline bool check_ustar_magic( const Tar_header header ) { return std::memcmp( header + magic_o, ustar_magic, magic_l ) == 0; } inline void init_tar_header( Tar_header header ) // set magic and version @@ -154,7 +155,7 @@ public: unsigned decimal_size() const; unsigned print( char * const buf ) const; bool parse( const char * const ptr, const char ** const tailp, - const long long size ); + const int size ); }; @@ -167,12 +168,12 @@ class Extended // stores metadata from/for extended records 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 - mutable long long padded_edsize_; // edsize rounded up - mutable long long full_size_; // header + padded edsize - mutable long long linkpath_recsize_; - mutable long long path_recsize_; + // cached sizes; if full_size_ <= -4 they must be recalculated + mutable int edsize_; // extended data size + mutable int padded_edsize_; // edsize rounded up + mutable int full_size_; // header + padded edsize + mutable int linkpath_recsize_; + mutable int path_recsize_; mutable int file_size_recsize_; mutable int uid_recsize_; mutable int gid_recsize_; @@ -183,8 +184,7 @@ class Extended // stores metadata from/for extended records mutable bool crc_present_; void calculate_sizes() const; - void unknown_keyword( const char * const buf, - const unsigned long long size ) const; + void unknown_keyword( const char * const buf, const int size ) const; public: static const std::string crc_record; @@ -205,11 +205,6 @@ public: atime_recsize_ = 0; mtime_recsize_ = 0; crc_present_ = false; removed_prefix.clear(); } - bool empty() const - { 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_; } @@ -219,23 +214,26 @@ public: 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; + void linkpath( const char * const lp ) { linkpath_ = lp; full_size_ = -4; } + void path( const char * const p ) { path_ = p; full_size_ = -4; } + void file_size( const long long fs ) { full_size_ = -4; 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; } + { if( id >= 0 ) { uid_ = id; full_size_ = -4; } 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; } + { if( id >= 0 ) { gid_ = id; full_size_ = -4; } return id >= 0; } + void set_atime( const long long s ) { atime_.set( s ); full_size_ = -4; } + void set_mtime( const long long s ) { mtime_.set( s ); full_size_ = -4; } - long long full_size() const - { if( full_size_ < 0 ) calculate_sizes(); return full_size_; } + /* Return the size of the extended block, or 0 if empty. + Return -1 if error, -2 if out of memory, -3 if block too long. */ + int full_size() const + { if( full_size_ <= -4 ) calculate_sizes(); return full_size_; } + int format_block( Resizable_buffer & rbuf ) const; + const char * full_size_error() const; bool crc_present() const { return crc_present_; } - long long format_block( Resizable_buffer & rbuf ) const; - bool parse( const char * const buf, const unsigned long long edsize, + bool parse( const char * const buf, const int edsize, const bool permissive ); void fill_from_ustar( const Tar_header header ); }; @@ -337,17 +335,17 @@ struct Lzip_header // 4 version // 5 coded dictionary size - bool verify_magic() const + bool check_magic() const { return ( std::memcmp( data, lzip_magic, 4 ) == 0 ); } - bool verify_prefix( const int sz ) const // detect (truncated) header + bool check_prefix( const int sz ) const // detect (truncated) header { for( int i = 0; i < sz && i < 4; ++i ) if( data[i] != lzip_magic[i] ) return false; return ( sz > 0 ); } - bool verify_corrupt() const // detect corrupt header + bool check_corrupt() const // detect corrupt header { int matches = 0; for( int i = 0; i < 4; ++i ) @@ -356,7 +354,7 @@ struct Lzip_header } uint8_t version() const { return data[4]; } - bool verify_version() const { return ( data[4] == 1 ); } + bool check_version() const { return ( data[4] == 1 ); } unsigned dictionary_size() const { @@ -366,8 +364,8 @@ struct Lzip_header return sz; } - bool verify() const - { return verify_magic() && verify_version() && + bool check() const + { return check_magic() && check_version() && isvalid_ds( dictionary_size() ); } }; @@ -400,7 +398,7 @@ struct Lzip_trailer return tmp; } - bool verify_consistency() const // check internal consistency + bool check_consistency() const // check internal consistency { const unsigned crc = data_crc(); const unsigned long long dsize = data_size(); @@ -421,7 +419,7 @@ enum Program_mode { m_none, m_append, m_compress, m_concatenate, m_create, enum Solidity { no_solid, bsolid, dsolid, asolid, solid }; class Arg_parser; -struct Cl_options // command line options +struct Cl_options // command-line options { const Arg_parser & parser; std::string archive_name; @@ -440,8 +438,10 @@ struct Cl_options // command line options bool dereference; bool filenames_given; bool ignore_ids; + bool ignore_metadata; bool ignore_overflow; bool keep_damaged; + bool level_set; // compression level set in command line bool missing_crc; bool mtime_set; bool permissive; @@ -452,10 +452,15 @@ struct Cl_options // command line options : 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 ) {} + filenames_given( false ), ignore_ids( false ), ignore_metadata( false ), + ignore_overflow( false ), keep_damaged( false ), level_set( false ), + missing_crc( false ), mtime_set( false ), permissive( false ), + preserve_permissions( false ), warn_newer( false ) {} + + void set_level( const int l ) { level = l; level_set = true; } + int compressed() const; // tri-state bool with error (-2) + bool uncompressed() const { return level < 0 || level > 9; } bool to_stdout() const { return output_filename == "-"; } }; @@ -465,7 +470,6 @@ inline void set_retval( int & retval, const int 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."; -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."; @@ -486,21 +490,12 @@ 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"; +const char * const intdir_msg = "Failed to create intermediate directory"; // defined in common.cc -void xinit_mutex( pthread_mutex_t * const mutex ); -void xinit_cond( pthread_cond_t * const cond ); -void xdestroy_mutex( pthread_mutex_t * const mutex ); -void xdestroy_cond( pthread_cond_t * const cond ); -void xlock( pthread_mutex_t * const mutex ); -void xunlock( pthread_mutex_t * const mutex ); -void xwait( pthread_cond_t * const cond, pthread_mutex_t * const mutex ); -void xsignal( pthread_cond_t * const cond ); -void xbroadcast( pthread_cond_t * const cond ); unsigned long long parse_octal( const uint8_t * const ptr, const int size ); int readblock( const int fd, uint8_t * const buf, const int size ); int writeblock( const int fd, const uint8_t * const buf, const int size ); -bool nonempty_arg( const Arg_parser & parser, const int i ); // defined in common_decode.cc bool block_is_zero( const uint8_t * const buf, const int size ); @@ -510,11 +505,19 @@ bool show_member_name( const Extended & extended, const Tar_header header, const int vlevel, Resizable_buffer & rbuf ); bool check_skip_filename( const Cl_options & cl_opts, std::vector< char > & name_pending, - const char * const filename ); -mode_t get_umask(); -bool make_path( const std::string & name ); + const char * const filename, const int chdir_fd = -1 ); +bool make_dirs( const std::string & name ); + +// defined in common_mutex.cc +void exit_fail_mt( const int retval = 1 ); // terminate the program +bool print_removed_prefix( const std::string & prefix, + std::string * const msgp = 0 ); +void set_error_status( const int retval ); +int final_exit_status( int retval, const bool show_msg = true ); // defined in compress.cc +void show_atpos_error( const char * const filename, const long long pos, + const bool isarchive ); int compress( const Cl_options & cl_opts ); // defined in create.cc @@ -524,18 +527,14 @@ bool writeblock_wrapper( const int outfd, const uint8_t * const buffer, bool write_eoa_records( const int outfd, const bool compressed ); const char * remove_leading_dotslash( const char * const filename, 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, +bool block_is_full( const int extended_size, const unsigned long long file_size, const unsigned long long target_size, unsigned long long & partial_data_size ); -void set_error_status( const int retval ); -int final_exit_status( int retval, const bool show_msg = true ); unsigned ustar_chksum( const Tar_header header ); -bool verify_ustar_chksum( const Tar_header header ); +bool check_ustar_chksum( const Tar_header header ); bool has_lz_ext( const std::string & name ); int concatenate( const Cl_options & cl_opts ); int encode( const Cl_options & cl_opts ); @@ -591,10 +590,10 @@ extern const char * const program_name; struct stat; int hstat( const char * const filename, struct stat * const st, const bool dereference ); +bool nonempty_arg( const Arg_parser & parser, const int i ); int open_instream( const std::string & name ); int open_outstream( const std::string & name, const bool create = true, Resizable_buffer * const rbufp = 0, const bool force = 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, -- cgit v1.2.3