diff options
Diffstat (limited to '')
-rw-r--r-- | create.cc | 55 |
1 files changed, 27 insertions, 28 deletions
@@ -1,5 +1,5 @@ /* Tarlz - Archiver with multimember lzip compression - Copyright (C) 2013-2018 Antonio Diaz Diaz. + Copyright (C) 2013-2019 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 @@ -46,7 +46,7 @@ const CRC32C crc32c; int cl_owner = -1; // global vars needed by add_member int cl_group = -1; -int cl_solid = 0; // 1 = dsolid, 2 = asolid, 3 = solid +Solidity solidity = no_solid; namespace { @@ -110,7 +110,7 @@ bool check_appendable( const int fd, const bool remove_eof ) if( rd == 0 && errno == 0 ) return true; // append to empty archive if( rd < min_member_size || ( rd != bufsize && errno ) ) return false; const Lzip_header * const p = (const Lzip_header *)buf; // shut up gcc - if( !p->verify_magic() ) return false; + if( !p->verify_magic() || !p->verify_version() ) return false; LZ_Decoder * decoder = LZ_decompress_open(); // decompress first header if( !decoder || LZ_decompress_errno( decoder ) != LZ_ok || LZ_decompress_write( decoder, buf, rd ) != rd || @@ -133,8 +133,8 @@ bool check_appendable( const int fd, const bool remove_eof ) Lzip_header header; if( seek_read( fd, header.data, Lzip_header::size, end - member_size ) != Lzip_header::size ) return false; - if( !header.verify_magic() || !isvalid_ds( header.dictionary_size() ) ) - return false; + if( !header.verify_magic() || !header.verify_version() || + !isvalid_ds( header.dictionary_size() ) ) return false; const unsigned long long data_size = trailer.data_size(); if( data_size < header_size || data_size > 32256 ) return false; @@ -218,7 +218,7 @@ void print_hex( char * const buf, int size, unsigned long long num ) while( --size >= 0 ) { buf[size] = xdigit( num & 0x0F ); num >>= 4; } } -void print_octal( char * const buf, int size, unsigned long long num ) +void print_octal( uint8_t * const buf, int size, unsigned long long num ) { while( --size >= 0 ) { buf[size] = '0' + ( num % 8 ); num /= 8; } } @@ -230,13 +230,14 @@ unsigned decimal_digits( unsigned long long value ) return digits; } -unsigned long long record_size( const unsigned keyword_size, - const unsigned long long value_size ) +int record_size( const unsigned keyword_size, const unsigned long value_size ) { // size = ' ' + keyword + '=' + value + '\n' - const unsigned long long size = 1 + keyword_size + 1 + value_size + 1; + unsigned long long size = 1 + keyword_size + 1 + value_size + 1; const unsigned d1 = decimal_digits( size ); - return decimal_digits( d1 + size ) + size; + size += decimal_digits( d1 + size ); + if( size >= INT_MAX ) size = 0; // overflows snprintf size + return size; } bool write_extended( const Extended & extended ) @@ -274,9 +275,8 @@ bool write_extended( const Extended & extended ) init_tar_header( header ); header[typeflag_o] = tf_extended; // fill only required fields print_octal( header + size_o, size_l - 1, edsize ); - print_octal( header + chksum_o, chksum_l - 1, - ustar_chksum( (const uint8_t *)header ) ); - if( !archive_write( (const uint8_t *)header, header_size ) ) goto error; + print_octal( header + chksum_o, chksum_l - 1, ustar_chksum( header ) ); + if( !archive_write( header, header_size ) ) goto error; for( pos = 0; pos < bufsize; ) // write extended records to archive { int size = std::min( bufsize - pos, 1ULL << 20 ); @@ -387,7 +387,7 @@ int add_member( const char * const filename, const struct stat *, typeflag = tf_symlink; long len; if( st.st_size <= linkname_l ) - len = readlink( filename, header + linkname_o, linkname_l ); + len = readlink( filename, (char *)header + linkname_o, linkname_l ); else { char * const buf = new char[st.st_size+1]; @@ -414,20 +414,19 @@ int add_member( const char * const filename, const struct stat *, header[typeflag_o] = typeflag; const struct passwd * const pw = getpwuid( uid ); if( pw && pw->pw_name ) - std::strncpy( header + uname_o, pw->pw_name, uname_l - 1 ); + std::strncpy( (char *)header + uname_o, pw->pw_name, uname_l - 1 ); const struct group * const gr = getgrgid( gid ); if( gr && gr->gr_name ) - std::strncpy( header + gname_o, gr->gr_name, gname_l - 1 ); + std::strncpy( (char *)header + gname_o, gr->gr_name, gname_l - 1 ); if( file_size >= 1ULL << 33 ) extended.size = file_size; else print_octal( header + size_o, size_l - 1, file_size ); - print_octal( header + chksum_o, chksum_l - 1, - ustar_chksum( (const uint8_t *)header ) ); + print_octal( header + chksum_o, chksum_l - 1, ustar_chksum( header ) ); const int infd = file_size ? open_instream( filename ) : -1; if( file_size && infd < 0 ) { gretval = 1; return 0; } if( !extended.empty() && !write_extended( extended ) ) { show_error( "Error writing extended header", errno ); return 1; } - if( !archive_write( (const uint8_t *)header, header_size ) ) + if( !archive_write( header, header_size ) ) { show_error( "Error writing ustar header", errno ); return 1; } if( file_size ) { @@ -460,7 +459,7 @@ int add_member( const char * const filename, const struct stat *, if( close( infd ) != 0 ) { show_file_error( filename, "Error closing file", errno ); return 1; } } - if( encoder && cl_solid == 0 && !archive_write( 0, 0 ) ) // flush encoder + if( encoder && solidity == no_solid && !archive_write( 0, 0 ) ) { show_error( "Error flushing encoder", errno ); return 1; } if( verbosity >= 1 ) std::fprintf( stderr, "%s\n", filename ); return 0; @@ -469,18 +468,18 @@ int add_member( const char * const filename, const struct stat *, } // end namespace -unsigned ustar_chksum( const uint8_t * const buf ) +unsigned ustar_chksum( const uint8_t * const header ) { unsigned chksum = chksum_l * 0x20; // treat chksum field as spaces - for( int i = 0; i < chksum_o; ++i ) chksum += buf[i]; - for( int i = chksum_o + chksum_l; i < header_size; ++i ) chksum += buf[i]; + for( int i = 0; i < chksum_o; ++i ) chksum += header[i]; + for( int i = chksum_o + chksum_l; i < header_size; ++i ) chksum += header[i]; return chksum; } -bool verify_ustar_chksum( const uint8_t * const buf ) - { return ( verify_ustar_magic( buf ) && - ustar_chksum( buf ) == strtoul( (const char *)buf + chksum_o, 0, 8 ) ); } +bool verify_ustar_chksum( const uint8_t * const header ) + { return ( verify_ustar_magic( header ) && + ustar_chksum( header ) == parse_octal( header + chksum_o, chksum_l ) ); } int concatenate( const std::string & archive_name, const Arg_parser & parser, @@ -611,7 +610,7 @@ int encode( const std::string & archive_name, const Arg_parser & parser, if( gretval < 1 ) gretval = 1; } else if( ( retval = nftw( filename, add_member, 16, FTW_PHYS ) ) != 0 ) break; // write error - else if( encoder && cl_solid == 1 && !archive_write( 0, 0 ) ) // flush encoder + else if( encoder && solidity == dsolid && !archive_write( 0, 0 ) ) { show_error( "Error flushing encoder", errno ); retval = 1; } } @@ -620,7 +619,7 @@ int encode( const std::string & archive_name, const Arg_parser & parser, enum { bufsize = 2 * header_size }; uint8_t buf[bufsize]; std::memset( buf, 0, bufsize ); - if( encoder && cl_solid == 2 && !archive_write( 0, 0 ) ) // flush encoder + if( encoder && solidity == asolid && !archive_write( 0, 0 ) ) { show_error( "Error flushing encoder", errno ); retval = 1; } else if( !archive_write( buf, bufsize ) || ( encoder && !archive_write( 0, 0 ) ) ) // flush encoder |