summaryrefslogtreecommitdiffstats
path: root/create.cc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2021-07-17 07:43:33 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2021-07-17 07:43:33 +0000
commit18525b97f1a4b60884962d8fb326e8e85d837686 (patch)
tree99125a3d130d197d38d03df460e7ec1634784b8f /create.cc
parentReleasing debian version 0.19-2. (diff)
downloadtarlz-18525b97f1a4b60884962d8fb326e8e85d837686.tar.xz
tarlz-18525b97f1a4b60884962d8fb326e8e85d837686.zip
Merging upstream version 0.21.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'create.cc')
-rw-r--r--create.cc84
1 files changed, 24 insertions, 60 deletions
diff --git a/create.cc b/create.cc
index 32d9abf..327f494 100644
--- a/create.cc
+++ b/create.cc
@@ -19,14 +19,10 @@
#include <algorithm>
#include <cerrno>
-#include <climits>
#include <cstdio>
#include <cstdlib>
-#include <cstring>
-#include <string>
-#include <vector>
#include <pthread.h>
-#include <stdint.h>
+#include <stdint.h> // for lzlib.h
#include <unistd.h>
#include <sys/stat.h>
#if !defined __FreeBSD__ && !defined __OpenBSD__ && !defined __NetBSD__ && \
@@ -38,8 +34,12 @@
#include <pwd.h>
#include <lzlib.h>
-#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 )