From 18525b97f1a4b60884962d8fb326e8e85d837686 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 17 Jul 2021 09:43:33 +0200 Subject: Merging upstream version 0.21. Signed-off-by: Daniel Baumann --- create.cc | 84 ++++++++++++++++++--------------------------------------------- 1 file changed, 24 insertions(+), 60 deletions(-) (limited to 'create.cc') diff --git a/create.cc b/create.cc index 32d9abf..327f494 100644 --- a/create.cc +++ b/create.cc @@ -19,14 +19,10 @@ #include #include -#include #include #include -#include -#include -#include #include -#include +#include // for lzlib.h #include #include #if !defined __FreeBSD__ && !defined __OpenBSD__ && !defined __NetBSD__ && \ @@ -38,8 +34,12 @@ #include #include -#include "arg_parser.h" #include "tarlz.h" +#include "arg_parser.h" +#include "create.h" + + +Archive_attrs archive_attrs; // archive attributes at time of creation namespace { @@ -52,28 +52,6 @@ Resizable_buffer grbuf; // extended header + data int goutfd = -1; int error_status = 0; -class File_is_the_archive - { - dev_t archive_dev; - ino_t archive_ino; - bool initialized; - -public: - File_is_the_archive() : initialized( false ) {} - bool init( const int fd ) - { - struct stat st; - if( fstat( fd, &st ) != 0 ) return false; - if( S_ISREG( st.st_mode ) ) - { archive_dev = st.st_dev; archive_ino = st.st_ino; initialized = true; } - return true; - } - bool operator()( const struct stat & st ) const - { - return initialized && archive_dev == st.st_dev && archive_ino == st.st_ino; - } - } file_is_the_archive; - bool option_C_after_relative_filename( const Arg_parser & parser ) { @@ -171,7 +149,7 @@ long long check_uncompressed_appendable( const int fd, const bool remove_eof ) if( edsize <= 0 || edsize >= 1LL << 33 || bufsize >= INT_MAX ) return -1; // overflow or no extended data if( !rbuf.resize( bufsize ) ) return -1; - if( readblock( fd, (uint8_t *)rbuf(), bufsize ) != bufsize ) + if( readblock( fd, rbuf.u8(), bufsize ) != bufsize ) return -1; if( typeflag == tf_extended ) { if( !extended.parse( rbuf(), edsize, false ) ) return -1; @@ -229,7 +207,7 @@ bool write_extended( const Extended & extended ) for( long long pos = 0; pos < ebsize; ) // write extended block to archive { int size = std::min( ebsize - pos, 1LL << 20 ); - if( !archive_write( (const uint8_t *)grbuf() + pos, size ) ) return false; + if( !archive_write( grbuf.u8() + pos, size ) ) return false; pos += size; } return true; @@ -276,8 +254,8 @@ int add_member( const char * const filename, const struct stat *, if( file_size && infd < 0 ) { set_error_status( 1 ); return 0; } if( encoder && gcl_opts->solidity == bsolid && - block_is_full( extended, file_size, partial_data_size ) && - !archive_write( 0, 0 ) ) return 1; + block_is_full( extended.full_size(), file_size, gcl_opts->data_size, + partial_data_size ) && !archive_write( 0, 0 ) ) return 1; if( !write_extended( extended ) || !archive_write( header, header_size ) ) return 1; @@ -312,6 +290,9 @@ int add_member( const char * const filename, const struct stat *, } if( encoder && gcl_opts->solidity == no_solid && !archive_write( 0, 0 ) ) return 1; + if( gcl_opts->warn_newer && archive_attrs.is_newer( filename ) ) + { show_file_error( filename, "File is newer than the archive." ); + set_error_status( 1 ); } if( verbosity >= 1 ) std::fprintf( stderr, "%s\n", filename ); return 0; } @@ -420,7 +401,7 @@ bool fill_headers( const char * const filename, Extended & extended, if( hstat( filename, &st, gcl_opts->dereference ) != 0 ) { show_file_error( filename, "Can't stat input file", errno ); set_error_status( 1 ); return false; } - if( file_is_the_archive( st ) ) + if( archive_attrs.is_the_archive( st ) ) { show_file_error( archive_namep, "File is the archive; not dumped." ); return false; } init_tar_header( header ); @@ -516,13 +497,13 @@ bool fill_headers( const char * const filename, Extended & extended, } -bool block_is_full( const Extended & extended, +bool block_is_full( const long long extended_size, const unsigned long long file_size, + const unsigned long long target_size, unsigned long long & partial_data_size ) { const unsigned long long member_size = // may overflow 'long long' - header_size + extended.full_size() + round_up( file_size ); - const unsigned long long target_size = gcl_opts->data_size; + header_size + extended_size + round_up( file_size ); if( partial_data_size >= target_size || ( partial_data_size >= min_data_size && partial_data_size + member_size / 2 > target_size ) ) @@ -550,7 +531,7 @@ int final_exit_status( int retval, const bool show_msg ) return retval; } -unsigned ustar_chksum( const uint8_t * const header ) +unsigned ustar_chksum( const Tar_header header ) { unsigned chksum = chksum_l * 0x20; // treat chksum field as spaces for( int i = 0; i < chksum_o; ++i ) chksum += header[i]; @@ -559,7 +540,7 @@ unsigned ustar_chksum( const uint8_t * const header ) } -bool verify_ustar_chksum( const uint8_t * const header ) +bool verify_ustar_chksum( const Tar_header header ) { return ( verify_ustar_magic( header ) && ustar_chksum( header ) == parse_octal( header + chksum_o, chksum_l ) ); } @@ -575,14 +556,14 @@ bool has_lz_ext( const std::string & name ) int concatenate( const Cl_options & cl_opts ) { - if( cl_opts.filenames <= 0 ) + if( cl_opts.num_files <= 0 ) { if( verbosity >= 1 ) show_error( "Nothing to concatenate." ); return 0; } const bool to_stdout = cl_opts.archive_name.empty(); archive_namep = to_stdout ? "(stdout)" : cl_opts.archive_name.c_str(); const int outfd = to_stdout ? STDOUT_FILENO : open_outstream( cl_opts.archive_name, false ); if( outfd < 0 ) return 1; - if( !to_stdout && !file_is_the_archive.init( outfd ) ) + if( !to_stdout && !archive_attrs.init( outfd ) ) { show_file_error( archive_namep, "Can't stat", errno ); return 1; } int compressed; // tri-state bool if( to_stdout ) compressed = -1; // unknown @@ -613,7 +594,7 @@ int concatenate( const Cl_options & cl_opts ) const int infd = open_instream( filename ); if( infd < 0 ) { retval = 1; break; } struct stat st; - if( !to_stdout && fstat( infd, &st ) == 0 && file_is_the_archive( st ) ) + if( !to_stdout && fstat( infd, &st ) == 0 && archive_attrs.is_the_archive( st ) ) { show_file_error( filename, "File is the archive; not concatenated." ); close( infd ); continue; } long long size; @@ -649,23 +630,6 @@ int concatenate( const Cl_options & cl_opts ) int encode( Cl_options & cl_opts ) { - struct Lzma_options - { - int dictionary_size; // 4 KiB .. 512 MiB - int match_len_limit; // 5 .. 273 - }; - const Lzma_options option_mapping[] = - { - { 65535, 16 }, // -0 - { 1 << 20, 5 }, // -1 - { 3 << 19, 6 }, // -2 - { 1 << 21, 8 }, // -3 - { 3 << 20, 12 }, // -4 - { 1 << 22, 20 }, // -5 - { 1 << 23, 36 }, // -6 - { 1 << 24, 68 }, // -7 - { 3 << 23, 132 }, // -8 - { 1 << 25, 273 } }; // -9 const bool compressed = ( cl_opts.level >= 0 && cl_opts.level <= 9 ); const bool to_stdout = cl_opts.archive_name.empty(); archive_namep = to_stdout ? "(stdout)" : cl_opts.archive_name.c_str(); @@ -676,7 +640,7 @@ int encode( Cl_options & cl_opts ) "Uncompressed mode incompatible with .lz extension." ); return 2; } const bool append = cl_opts.program_mode == m_append; - if( cl_opts.filenames <= 0 ) + if( cl_opts.num_files <= 0 ) { if( !append && !to_stdout ) // create archive { show_error( "Cowardly refusing to create an empty archive.", 0, true ); @@ -701,7 +665,7 @@ int encode( Cl_options & cl_opts ) "This does not look like an appendable tar archive." ); return 2; } } - if( !file_is_the_archive.init( goutfd ) ) + if( !archive_attrs.init( goutfd ) ) { show_file_error( archive_namep, "Can't stat", errno ); return 1; } if( compressed ) -- cgit v1.2.3