summaryrefslogtreecommitdiffstats
path: root/create.cc
diff options
context:
space:
mode:
Diffstat (limited to 'create.cc')
-rw-r--r--create.cc277
1 files changed, 159 insertions, 118 deletions
diff --git a/create.cc b/create.cc
index 54ce7c3..53ba5f5 100644
--- a/create.cc
+++ b/create.cc
@@ -63,11 +63,11 @@ bool option_C_after_relative_filename( const Arg_parser & parser )
}
-/* Check archive type. Return position of EOF blocks or -1 if failure.
- If remove_eof, leave fd file pos at beginning of the EOF blocks.
+/* Check archive type. Return position of EOA blocks or -1 if failure.
+ If remove_eoa, leave fd file pos at beginning of the EOA blocks.
Else, leave fd file pos at 0.
*/
-long long check_appendable( const int fd, const bool remove_eof )
+long long check_compressed_appendable( const int fd, const bool remove_eoa )
{
struct stat st; // fd must be regular
if( fstat( fd, &st ) != 0 || !S_ISREG( st.st_mode ) ) return -1;
@@ -85,24 +85,25 @@ long long check_appendable( const int fd, const bool remove_eof )
LZ_decompress_read( decoder, buf, header_size ) != header_size )
{ LZ_decompress_close( decoder ); return -1; }
LZ_decompress_close( decoder );
- const bool maybe_eof = block_is_zero( buf, header_size );
- if( !verify_ustar_chksum( buf ) && !maybe_eof ) return -1;
+ const bool maybe_eoa = block_is_zero( buf, header_size );
+ if( !verify_ustar_chksum( buf ) && !maybe_eoa ) return -1;
const long long end = lseek( fd, 0, SEEK_END );
if( end < min_member_size ) return -1;
- Lzip_trailer trailer;
+ Lzip_trailer trailer; // read last trailer
if( seek_read( fd, trailer.data, Lzip_trailer::size,
end - Lzip_trailer::size ) != Lzip_trailer::size ) return -1;
const long long member_size = trailer.member_size();
if( member_size < min_member_size || member_size > end ||
- ( maybe_eof && member_size != end ) ) return -1;
+ ( maybe_eoa && member_size != end ) ) return -1; // garbage after EOA?
- Lzip_header header;
+ Lzip_header header; // read last header
if( seek_read( fd, header.data, Lzip_header::size,
end - member_size ) != Lzip_header::size ) return -1;
if( !header.verify_magic() || !header.verify_version() ||
!isvalid_ds( header.dictionary_size() ) ) return -1;
+ // EOA marker in last member must contain between 512 and 32256 zeros alone
const unsigned long long data_size = trailer.data_size();
if( data_size < header_size || data_size > 32256 ) return -1;
const unsigned data_crc = trailer.data_crc();
@@ -112,33 +113,36 @@ long long check_appendable( const int fd, const bool remove_eof )
crc ^= 0xFFFFFFFFU;
if( crc != data_crc ) return -1;
- const long long pos = remove_eof ? end - member_size : 0;
+ const long long pos = remove_eoa ? end - member_size : 0;
if( lseek( fd, pos, SEEK_SET ) != pos ) return -1;
return end - member_size;
}
-/* Skip all tar headers. Return position of EOF blocks or -1 if failure.
- If remove_eof, leave fd file pos at beginning of the EOF blocks.
+/* Skip all tar headers.
+ Return position of EOA blocks, -1 if failure, -2 if out of memory.
+ If remove_eoa, leave fd file pos at beginning of the EOA blocks.
Else, leave fd file pos at 0.
*/
-long long check_uncompressed_appendable( const int fd, const bool remove_eof )
+long long check_uncompressed_appendable( const int fd, const bool remove_eoa )
{
struct stat st; // fd must be regular
if( fstat( fd, &st ) != 0 || !S_ISREG( st.st_mode ) ) return -1;
if( lseek( fd, 0, SEEK_SET ) != 0 ) return -1;
if( st.st_size <= 0 ) return 0; // append to empty archive
- long long eof_pos = 0;
+ long long eoa_pos = 0; // pos of EOA blocks
Extended extended; // metadata from extended records
Resizable_buffer rbuf; // extended records buffer
bool prev_extended = false; // prev header was extended
+ if( !rbuf.size() ) return -2;
+
while( true ) // process one tar header per iteration
{
Tar_header header;
const int rd = readblock( fd, header, header_size );
- if( rd == 0 && errno == 0 ) break; // missing EOF blocks
+ if( rd == 0 && errno == 0 ) break; // missing EOA blocks
if( rd != header_size ) return -1;
- if( !verify_ustar_chksum( header ) ) // maybe EOF
+ if( !verify_ustar_chksum( header ) ) // maybe EOA block
{ if( block_is_zero( header, header_size ) ) break; else return -1; }
const Typeflag typeflag = (Typeflag)header[typeflag_o];
if( typeflag == tf_extended || typeflag == tf_global )
@@ -148,7 +152,7 @@ long long check_uncompressed_appendable( const int fd, const bool remove_eof )
const long long bufsize = round_up( edsize );
if( edsize <= 0 || edsize >= 1LL << 33 || bufsize >= INT_MAX )
return -1; // overflow or no extended data
- if( !rbuf.resize( bufsize ) ) return -1;
+ if( !rbuf.resize( bufsize ) ) return -2;
if( readblock( fd, rbuf.u8(), bufsize ) != bufsize )
return -1;
if( typeflag == tf_extended )
@@ -158,15 +162,15 @@ long long check_uncompressed_appendable( const int fd, const bool remove_eof )
}
prev_extended = false;
- eof_pos = lseek( fd, round_up( extended.get_file_size_and_reset( header ) ),
+ eoa_pos = lseek( fd, round_up( extended.get_file_size_and_reset( header ) ),
SEEK_CUR );
- if( eof_pos <= 0 ) return -1;
+ if( eoa_pos <= 0 ) return -1;
}
if( prev_extended ) return -1;
- const long long pos = remove_eof ? eof_pos : 0;
+ const long long pos = remove_eoa ? eoa_pos : 0;
if( lseek( fd, pos, SEEK_SET ) != pos ) return -1;
- return eof_pos;
+ return eoa_pos;
}
@@ -202,8 +206,9 @@ bool archive_write( const uint8_t * const buf, const int size )
bool write_extended( const Extended & extended )
{
- const long long ebsize = extended.format_block( grbuf );
- if( ebsize < 0 ) return false;
+ const long long ebsize = extended.format_block( grbuf ); // may be 0
+ if( ebsize < 0 )
+ { show_error( ( ebsize == -2 ) ? mem_msg2 : eferec_msg ); return false; }
for( long long pos = 0; pos < ebsize; ) // write extended block to archive
{
int size = std::min( ebsize - pos, 1LL << 20 );
@@ -218,7 +223,8 @@ bool write_extended( const Extended & extended )
bool store_name( const char * const filename, Extended & extended,
Tar_header header, const bool force_extended_name )
{
- const char * const stored_name = remove_leading_dotslash( filename, true );
+ const char * const stored_name =
+ remove_leading_dotslash( filename, &extended.removed_prefix, true );
if( !force_extended_name ) // try storing filename in the ustar header
{
@@ -250,6 +256,7 @@ int add_member( const char * const filename, const struct stat *,
Extended extended; // metadata for extended records
Tar_header header;
if( !fill_headers( filename, extended, header, file_size, flag ) ) return 0;
+ print_removed_prefix( extended.removed_prefix );
const int infd = file_size ? open_instream( filename ) : -1;
if( file_size && infd < 0 ) { set_error_status( 1 ); return 0; }
@@ -286,7 +293,7 @@ int add_member( const char * const filename, const struct stat *,
if( !archive_write( buf, size ) ) { close( infd ); return 1; }
}
if( close( infd ) != 0 )
- { show_file_error( filename, "Error closing file", errno ); return 1; }
+ { show_file_error( filename, eclosf_msg, errno ); return 1; }
}
if( encoder && gcl_opts->solidity == no_solid && !archive_write( 0, 0 ) )
return 1;
@@ -297,6 +304,18 @@ int add_member( const char * const filename, const struct stat *,
return 0;
}
+
+bool check_tty_out( const char * const archive_namep, const int outfd,
+ const bool to_stdout )
+ {
+ if( isatty( outfd ) ) // for example /dev/tty
+ { show_file_error( archive_namep, to_stdout ?
+ "I won't write archive data to a terminal (missing -f option?)" :
+ "I won't write archive data to a terminal." );
+ return false; }
+ return true;
+ }
+
} // end namespace
@@ -335,23 +354,23 @@ bool writeblock_wrapper( const int outfd, const uint8_t * const buffer,
const int size )
{
if( writeblock( outfd, buffer, size ) != size )
- { show_file_error( archive_namep, "Write error", errno ); return false; }
+ { show_file_error( archive_namep, werr_msg, errno ); return false; }
return true;
}
// write End-Of-Archive records
-bool write_eof_records( const int outfd, const bool compressed )
+bool write_eoa_records( const int outfd, const bool compressed )
{
if( compressed )
{
- enum { eof_member_size = 44 };
- const uint8_t eof_member[eof_member_size] = {
+ enum { eoa_member_size = 44 };
+ const uint8_t eoa_member[eoa_member_size] = {
0x4C, 0x5A, 0x49, 0x50, 0x01, 0x0C, 0x00, 0x00, 0x6F, 0xFD, 0xFF, 0xFF,
0xA3, 0xB7, 0x80, 0x0C, 0x82, 0xDB, 0xFF, 0xFF, 0x9F, 0xF0, 0x00, 0x00,
0x2E, 0xAF, 0xB5, 0xEF, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- return writeblock_wrapper( outfd, eof_member, eof_member_size );
+ return writeblock_wrapper( outfd, eoa_member, eoa_member_size );
}
enum { bufsize = 2 * header_size };
uint8_t buf[bufsize];
@@ -360,40 +379,52 @@ bool write_eof_records( const int outfd, const bool compressed )
}
-/* Removes any amount of leading "./" and '/' strings from filename.
- Optionally also removes prefixes containing a ".." component.
+/* Remove any amount of leading "./" and '/' strings from filename.
+ Optionally also remove prefixes containing a ".." component.
+ Return the removed prefix in *removed_prefixp.
*/
const char * remove_leading_dotslash( const char * const filename,
+ std::string * const removed_prefixp,
const bool dotdot )
{
- // prevent two threads from modifying the list of prefixes at the same time
- static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
- static std::vector< std::string > prefixes; // list of prefixes
const char * p = filename;
if( dotdot )
for( int i = 0; filename[i]; ++i )
if( dotdot_at_i( filename, i ) ) p = filename + i + 2;
while( *p == '/' || ( *p == '.' && p[1] == '/' ) ) ++p;
- if( p != filename )
- {
- std::string msg( filename, p - filename );
- unsigned i = 0;
- xlock( &mutex );
- while( i < prefixes.size() && prefixes[i] != msg ) ++i;
- if( i >= prefixes.size() )
- {
- prefixes.push_back( msg );
- msg.insert( 0, "Removing leading '" ); msg += "' from member names.";
- show_error( msg.c_str() );
- }
- xunlock( &mutex );
- }
+ if( p != filename ) removed_prefixp->assign( filename, p - filename );
+ else removed_prefixp->clear(); // no prefix was removed
if( *p == 0 && *filename != 0 ) p = ".";
return p;
}
+/* If msgp is null, print the message, else return the message in *msgp.
+ If prefix is already in the list, print nothing or return empty *msgp.
+ Return true if a message is printed or returned in *msgp. */
+bool print_removed_prefix( const std::string & prefix,
+ std::string * const msgp )
+ {
+ // prevent two threads from modifying the list of prefixes at the same time
+ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+ static std::vector< std::string > prefixes; // list of prefixes
+
+ if( verbosity < 0 || prefix.empty() )
+ { if( msgp ) msgp->clear(); return false; }
+ xlock( &mutex );
+ for( unsigned i = 0; i < prefixes.size(); ++i )
+ if( prefixes[i] == prefix )
+ { xunlock( &mutex ); if( msgp ) msgp->clear(); return false; }
+ prefixes.push_back( prefix );
+ std::string msg( "Removing leading '" ); msg += prefix;
+ msg += "' from member names.";
+ if( msgp ) *msgp = msg; else show_error( msg.c_str() );
+ xunlock( &mutex ); // put here to prevent mixing calls to show_error
+ return true;
+ }
+
+
// set file_size != 0 only for regular files
bool fill_headers( const char * const filename, Extended & extended,
Tar_header header, long long & file_size, const int flag )
@@ -403,7 +434,7 @@ bool fill_headers( const char * const filename, Extended & extended,
{ show_file_error( filename, cant_stat, errno );
set_error_status( 1 ); return false; }
if( archive_attrs.is_the_archive( st ) )
- { show_file_error( archive_namep, "File is the archive; not dumped." );
+ { show_file_error( archive_namep, "Archive can't contain itself; not dumped." );
return false; }
init_tar_header( header );
bool force_extended_name = false;
@@ -412,19 +443,17 @@ bool fill_headers( const char * const filename, Extended & extended,
print_octal( header + mode_o, mode_l - 1,
mode & ( S_ISUID | S_ISGID | S_ISVTX |
S_IRWXU | S_IRWXG | S_IRWXO ) );
- const uid_t uid = (gcl_opts->owner >= 0) ? (uid_t)gcl_opts->owner : st.st_uid;
- const gid_t gid = (gcl_opts->group >= 0) ? (gid_t)gcl_opts->group : st.st_gid;
- if( uid >= 2 << 20 || gid >= 2 << 20 )
- { show_file_error( filename, "uid or gid is larger than 2_097_151." );
- set_error_status( 1 ); return false; }
- print_octal( header + uid_o, uid_l - 1, uid );
- print_octal( header + gid_o, gid_l - 1, gid );
- const unsigned long long mtime = ( gcl_opts->mtime >= 0 ) ? gcl_opts->mtime :
- ( ( st.st_mtime >= 0 ) ? st.st_mtime : 0 );
- if( mtime >= 1ULL << 33 )
- { show_file_error( filename, "mtime is out of ustar range [0, 8_589_934_591]." );
- set_error_status( 1 ); return false; }
- print_octal( header + mtime_o, mtime_l - 1, mtime );
+ const long long uid = ( gcl_opts->uid >= 0 ) ? gcl_opts->uid : st.st_uid;
+ const long long gid = ( gcl_opts->gid >= 0 ) ? gcl_opts->gid : st.st_gid;
+ if( uid_in_ustar_range( uid ) ) print_octal( header + uid_o, uid_l - 1, uid );
+ else if( extended.set_uid( uid ) ) force_extended_name = true;
+ if( uid_in_ustar_range( gid ) ) print_octal( header + gid_o, gid_l - 1, gid );
+ else if( extended.set_gid( gid ) ) force_extended_name = true;
+ const long long mtime = gcl_opts->mtime_set ? gcl_opts->mtime : st.st_mtime;
+ if( time_in_ustar_range( mtime ) )
+ print_octal( header + mtime_o, mtime_l - 1, mtime );
+ else { extended.set_atime( gcl_opts->mtime_set ? mtime : st.st_atime );
+ extended.set_mtime( mtime ); force_extended_name = true; }
Typeflag typeflag;
if( S_ISREG( mode ) ) typeflag = tf_regular;
else if( S_ISDIR( mode ) )
@@ -458,8 +487,16 @@ bool fill_headers( const char * const filename, Extended & extended,
delete[] buf;
}
if( sz != st.st_size )
- { show_file_error( filename, "Error reading link", (sz < 0) ? errno : 0 );
- set_error_status( 1 ); return false; }
+ {
+ if( sz < 0 )
+ show_file_error( filename, "Error reading symbolic link", errno );
+ else
+ show_file_error( filename, "Wrong size reading symbolic link.\n"
+ "Please, send a bug report to the maintainers of your filesystem, "
+ "mentioning\n'wrong st_size of symbolic link'.\nSee "
+ "http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_stat.h.html" );
+ set_error_status( 1 ); return false;
+ }
}
else if( S_ISCHR( mode ) || S_ISBLK( mode ) )
{
@@ -475,18 +512,17 @@ bool fill_headers( const char * const filename, Extended & extended,
else { show_file_error( filename, "Unknown file type." );
set_error_status( 2 ); return false; }
header[typeflag_o] = typeflag;
-// errno = 0;
- const struct passwd * const pw = getpwuid( uid );
- if( pw && pw->pw_name )
- std::strncpy( (char *)header + uname_o, pw->pw_name, uname_l - 1 );
-/* else { show_file_error( filename, "Can't read user name from database", errno );
- set_error_status( 1 ); } */ // numerical only
-// errno = 0;
- const struct group * const gr = getgrgid( gid );
- if( gr && gr->gr_name )
- std::strncpy( (char *)header + gname_o, gr->gr_name, gname_l - 1 );
-/* else { show_file_error( filename, "Can't read group name from database", errno );
- set_error_status( 1 ); } */ // numerical only
+
+ if( uid == (long long)( (uid_t)uid ) ) // get name if uid is in range
+ { const struct passwd * const pw = getpwuid( uid );
+ if( pw && pw->pw_name )
+ std::strncpy( (char *)header + uname_o, pw->pw_name, uname_l - 1 ); }
+
+ if( gid == (long long)( (gid_t)gid ) ) // get name if gid is in range
+ { const struct group * const gr = getgrgid( gid );
+ if( gr && gr->gr_name )
+ std::strncpy( (char *)header + gname_o, gr->gr_name, gname_l - 1 ); }
+
file_size = ( typeflag == tf_regular && st.st_size > 0 &&
st.st_size <= max_file_size ) ? st.st_size : 0;
if( file_size >= 1LL << 33 )
@@ -525,7 +561,7 @@ void set_error_status( const int retval )
int final_exit_status( int retval, const bool show_msg )
{
- if( !retval && error_status )
+ if( retval == 0 && error_status )
{ if( show_msg )
show_error( "Exiting with failure status due to previous errors." );
retval = error_status; }
@@ -564,6 +600,8 @@ int concatenate( const Cl_options & cl_opts )
const int outfd =
to_stdout ? STDOUT_FILENO : open_outstream( cl_opts.archive_name, false );
if( outfd < 0 ) return 1;
+ if( !check_tty_out( archive_namep, outfd, to_stdout ) )
+ { close( outfd ); return 1; }
if( !to_stdout && !archive_attrs.init( outfd ) )
{ show_file_error( archive_namep, "Can't stat", errno ); return 1; }
int compressed; // tri-state bool
@@ -571,22 +609,23 @@ int concatenate( const Cl_options & cl_opts )
else
{
compressed = has_lz_ext( cl_opts.archive_name ); // default value
- long long pos = check_appendable( outfd, true );
+ long long pos = check_compressed_appendable( outfd, true );
if( pos > 0 ) compressed = true;
else if( pos < 0 )
{
pos = check_uncompressed_appendable( outfd, true );
if( pos > 0 ) compressed = false;
+ else if( pos == -2 ) { show_error( mem_msg ); close( outfd ); return 1; }
else if( pos < 0 )
{ show_file_error( archive_namep, compressed ?
"This does not look like an appendable tar.lz archive." :
"This does not look like an appendable tar archive." );
- return 2; }
+ close( outfd ); return 2; }
}
}
int retval = 0;
- bool eof_pending = false;
+ bool eoa_pending = false;
for( int i = 0; i < cl_opts.parser.arguments(); ++i ) // copy archives
{
if( !nonempty_arg( cl_opts.parser, i ) ) continue; // skip opts, empty names
@@ -596,18 +635,21 @@ int concatenate( const Cl_options & cl_opts )
if( infd < 0 ) { retval = 1; break; }
struct stat st;
if( !to_stdout && fstat( infd, &st ) == 0 && archive_attrs.is_the_archive( st ) )
- { show_file_error( filename, "File is the archive; not concatenated." );
+ { show_file_error( filename, "Archive can't contain itself; not concatenated." );
close( infd ); continue; }
long long size;
if( compressed < 0 ) // not initialized yet
{
- if( ( size = check_appendable( infd, false ) ) > 0 ) compressed = true;
+ if( ( size = check_compressed_appendable( infd, false ) ) > 0 )
+ compressed = true;
else if( ( size = check_uncompressed_appendable( infd, false ) ) > 0 )
compressed = false;
- else { size = -1 ; compressed = has_lz_ext( filename ); }
+ else if( size != -2 ) { size = -1 ; compressed = has_lz_ext( filename ); }
}
- else size = compressed ? check_appendable( infd, false ) :
+ else size = compressed ? check_compressed_appendable( infd, false ) :
check_uncompressed_appendable( infd, false );
+ if( size == -2 )
+ { show_error( mem_msg ); close( infd ); retval = 1; break; }
if( size < 0 )
{ show_file_error( filename, compressed ?
"Not an appendable tar.lz archive." :
@@ -615,22 +657,22 @@ int concatenate( const Cl_options & cl_opts )
close( infd ); retval = 2; break; }
if( !copy_file( infd, outfd, size ) || close( infd ) != 0 )
{ show_file_error( filename, "Error copying archive", errno );
- eof_pending = false; retval = 1; break; }
- eof_pending = true;
+ eoa_pending = false; retval = 1; break; }
+ eoa_pending = true;
if( verbosity >= 1 ) std::fprintf( stderr, "%s\n", filename );
}
- if( eof_pending && !write_eof_records( outfd, compressed ) && !retval )
+ if( eoa_pending && !write_eoa_records( outfd, compressed ) && retval == 0 )
retval = 1;
- if( close( outfd ) != 0 && !retval )
- { show_file_error( archive_namep, "Error closing archive", errno );
- retval = 1; }
+ if( close( outfd ) != 0 && retval == 0 )
+ { show_file_error( archive_namep, eclosa_msg, errno ); retval = 1; }
return retval;
}
-int encode( Cl_options & cl_opts )
+int encode( const Cl_options & cl_opts )
{
+ if( !grbuf.size() ) { show_error( mem_msg ); return 1; }
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();
@@ -652,31 +694,33 @@ int encode( Cl_options & cl_opts )
if( to_stdout ) // create/append to stdout
goutfd = STDOUT_FILENO;
- else if( !append ) // create archive
- { if( ( goutfd = open_outstream( cl_opts.archive_name ) ) < 0 ) return 1; }
- else // append to archive
- {
- if( ( goutfd = open_outstream( cl_opts.archive_name, false ) ) < 0 )
+ else // create/append to archive
+ if( ( goutfd = open_outstream( cl_opts.archive_name, !append ) ) < 0 )
return 1;
- if( compressed && check_appendable( goutfd, true ) < 0 )
- { show_file_error( archive_namep,
- "This does not look like an appendable tar.lz archive." ); return 2; }
- if( !compressed && check_uncompressed_appendable( goutfd, true ) < 0 )
+ if( !check_tty_out( archive_namep, goutfd, to_stdout ) )
+ { close( goutfd ); return 1; }
+ if( append && !to_stdout )
+ {
+ if( compressed && check_compressed_appendable( goutfd, true ) < 0 )
{ show_file_error( archive_namep,
- "This does not look like an appendable tar archive." ); return 2; }
+ "This does not look like an appendable tar.lz archive." );
+ close( goutfd ); return 2; }
+ if( !compressed )
+ {
+ const long long pos = check_uncompressed_appendable( goutfd, true );
+ if( pos == -2 ) { show_error( mem_msg ); close( goutfd ); return 1; }
+ if( pos < 0 ) { show_file_error( archive_namep,
+ "This does not look like an appendable tar archive." );
+ close( goutfd ); return 2; }
+ }
}
if( !archive_attrs.init( goutfd ) )
- { show_file_error( archive_namep, "Can't stat", errno ); return 1; }
+ { show_file_error( archive_namep, "Can't stat", errno );
+ close( goutfd ); return 1; }
if( compressed )
{
- const int dictionary_size = option_mapping[cl_opts.level].dictionary_size;
- if( cl_opts.data_size <= 0 )
- {
- if( cl_opts.level == 0 ) cl_opts.data_size = 1 << 20;
- else cl_opts.data_size = 2 * dictionary_size;
- }
/* CWD is not per-thread; multi-threaded --create can't be used if a
-C option appears after a relative filename in the command line. */
if( cl_opts.solidity != asolid && cl_opts.solidity != solid &&
@@ -684,10 +728,9 @@ int encode( Cl_options & cl_opts )
!option_C_after_relative_filename( cl_opts.parser ) )
{
// show_file_error( archive_namep, "Multi-threaded --create" );
- return encode_lz( cl_opts, archive_namep, dictionary_size,
- option_mapping[cl_opts.level].match_len_limit, goutfd );
+ return encode_lz( cl_opts, archive_namep, goutfd );
}
- encoder = LZ_compress_open( dictionary_size,
+ encoder = LZ_compress_open( option_mapping[cl_opts.level].dictionary_size,
option_mapping[cl_opts.level].match_len_limit, LLONG_MAX );
if( !encoder || LZ_compress_errno( encoder ) != LZ_ok )
{
@@ -695,7 +738,7 @@ int encode( Cl_options & cl_opts )
show_error( mem_msg2 );
else
internal_error( "invalid argument to encoder." );
- return 1;
+ close( goutfd ); return 1;
}
}
@@ -706,8 +749,7 @@ int encode( Cl_options & cl_opts )
const std::string & arg = cl_opts.parser.argument( i );
const char * filename = arg.c_str();
if( code == 'C' && chdir( filename ) != 0 )
- { show_file_error( filename, "Error changing working directory", errno );
- retval = 1; break; }
+ { show_file_error( filename, chdir_msg, errno ); retval = 1; break; }
if( code ) continue; // skip options
if( cl_opts.parser.argument( i ).empty() ) continue; // skip empty names
std::string deslashed; // arg without trailing slashes
@@ -726,7 +768,7 @@ int encode( Cl_options & cl_opts )
{ retval = 1; break; }
}
- if( !retval ) // write End-Of-Archive records
+ if( retval == 0 ) // write End-Of-Archive records
{
enum { bufsize = 2 * header_size };
uint8_t buf[bufsize];
@@ -740,8 +782,7 @@ int encode( Cl_options & cl_opts )
}
if( encoder && LZ_compress_close( encoder ) < 0 )
{ show_error( "LZ_compress_close failed." ); retval = 1; }
- if( close( goutfd ) != 0 && !retval )
- { show_file_error( archive_namep, "Error closing archive", errno );
- retval = 1; }
+ if( close( goutfd ) != 0 && retval == 0 )
+ { show_file_error( archive_namep, eclosa_msg, errno ); retval = 1; }
return final_exit_status( retval );
}