summaryrefslogtreecommitdiffstats
path: root/create.cc
diff options
context:
space:
mode:
Diffstat (limited to 'create.cc')
-rw-r--r--create.cc55
1 files changed, 31 insertions, 24 deletions
diff --git a/create.cc b/create.cc
index 0eaa183..cba638a 100644
--- a/create.cc
+++ b/create.cc
@@ -92,15 +92,6 @@ bool option_C_after_relative_filename( const Arg_parser & parser )
}
-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; }
- return true;
- }
-
-
// infd and outfd can refer to the same file if copying to a lower file
// position or if source and destination blocks don't overlap.
// max_size < 0 means no size limit.
@@ -310,6 +301,15 @@ int add_member( const char * const filename, const struct stat *,
} // end namespace
+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; }
+ return true;
+ }
+
+
/* Removes any amount of leading "./" and '/' strings from filename.
Optionally also removes prefixes containing a ".." component. */
const char * remove_leading_dotslash( const char * const filename,
@@ -322,10 +322,7 @@ const char * remove_leading_dotslash( const char * const filename,
if( dotdot )
for( int i = 0; filename[i]; ++i )
- if( filename[i] == '.' && filename[i+1] == '.' &&
- ( i == 0 || filename[i-1] == '/' ) &&
- ( filename[i+2] == 0 || filename[i+2] == '/' ) )
- p = filename + i + 2;
+ if( dotdot_at_i( filename, i ) ) p = filename + i + 2;
while( *p == '/' || ( *p == '.' && p[1] == '/' ) ) ++p;
if( p != filename )
{
@@ -371,8 +368,8 @@ bool fill_headers( const char * const filename, Extended & extended,
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 long long mtime = st.st_mtime; // shut up gcc about time_t
- if( mtime < 0 || mtime >= 1LL << 33 )
+ const unsigned long long 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 );
@@ -388,25 +385,35 @@ bool fill_headers( const char * const filename, Extended & extended,
else if( S_ISLNK( mode ) )
{
typeflag = tf_symlink;
- long len;
+ long len, sz;
if( st.st_size <= linkname_l )
- len = readlink( filename, (char *)header + linkname_o, linkname_l );
+ {
+ len = sz = readlink( filename, (char *)header + linkname_o, linkname_l );
+ while( len > 1 && header[linkname_o+len-1] == '/' ) // trailing '/'
+ { --len; header[linkname_o+len] = 0; }
+ }
else
{
char * const buf = new char[st.st_size+1];
- len = readlink( filename, buf, st.st_size );
- if( len == st.st_size )
- { buf[len] = 0; extended.linkpath( buf ); force_extended_name = true; }
+ len = sz = readlink( filename, buf, st.st_size );
+ if( sz == st.st_size )
+ {
+ while( len > 1 && buf[len-1] == '/' ) --len; // trailing '/'
+ if( len <= linkname_l ) std::memcpy( header + linkname_o, buf, len );
+ else { buf[len] = 0; extended.linkpath( buf );
+ force_extended_name = true; }
+ }
delete[] buf;
}
- if( len != st.st_size )
- { show_file_error( filename, "Error reading link", (len < 0) ? errno : 0 );
+ if( sz != st.st_size )
+ { show_file_error( filename, "Error reading link", (sz < 0) ? errno : 0 );
set_error_status( 1 ); return false; }
}
else if( S_ISCHR( mode ) || S_ISBLK( mode ) )
{
typeflag = S_ISCHR( mode ) ? tf_chardev : tf_blockdev;
- if( major( st.st_rdev ) >= 2 << 20 || minor( st.st_rdev ) >= 2 << 20 )
+ if( (unsigned)major( st.st_rdev ) >= 2 << 20 ||
+ (unsigned)minor( st.st_rdev ) >= 2 << 20 )
{ show_file_error( filename, "devmajor or devminor is larger than 2_097_151." );
set_error_status( 1 ); return false; }
print_octal( header + devmajor_o, devmajor_l - 1, major( st.st_rdev ) );
@@ -593,7 +600,7 @@ int encode( const std::string & archive_name, const Arg_parser & parser,
!option_C_after_relative_filename( parser ) )
{
// show_file_error( archive_namep, "Multi-threaded --create" );
- return encode_lz( archive_namep, parser, dictionary_size,
+ return encode_lz( parser, dictionary_size,
option_mapping[level].match_len_limit, num_workers,
goutfd, debug_level );
}