diff options
Diffstat (limited to 'create.cc')
-rw-r--r-- | create.cc | 55 |
1 files changed, 31 insertions, 24 deletions
@@ -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 ); } |