summaryrefslogtreecommitdiffstats
path: root/extract.cc
diff options
context:
space:
mode:
Diffstat (limited to 'extract.cc')
-rw-r--r--extract.cc72
1 files changed, 20 insertions, 52 deletions
diff --git a/extract.cc b/extract.cc
index 2307060..04d974a 100644
--- a/extract.cc
+++ b/extract.cc
@@ -373,15 +373,20 @@ int compare_member( const int infd1, const Extended & extended,
}
if( typeflag != tf_symlink )
{
- const time_t mtime = parse_octal( header + mtime_o, mtime_l ); // 33 bits
- if( mtime != st.st_mtime )
- { show_file_diff( filename, "Mod time differs" ); diff = true; }
+ if( typeflag != tf_directory )
+ {
+ const time_t mtime = parse_octal( header + mtime_o, mtime_l ); // 33 bits
+ if( mtime != st.st_mtime )
+ { show_file_diff( filename, "Mod time differs" ); diff = true; }
+ }
if( ( typeflag == tf_regular || typeflag == tf_hiperf ) &&
(off_t)rest != st.st_size ) // don't compare contents
{ show_file_diff( filename, "Size differs" ); size_differs = true; }
if( ( typeflag == tf_chardev || typeflag == tf_blockdev ) &&
- ( parse_octal( header + devmajor_o, devmajor_l ) != major( st.st_rdev ) ||
- parse_octal( header + devminor_o, devminor_l ) != minor( st.st_rdev ) ) )
+ ( parse_octal( header + devmajor_o, devmajor_l ) !=
+ (unsigned)major( st.st_rdev ) ||
+ parse_octal( header + devminor_o, devminor_l ) !=
+ (unsigned)minor( st.st_rdev ) ) )
{ show_file_diff( filename, "Device number differs" ); diff = true; }
}
else
@@ -389,7 +394,12 @@ int compare_member( const int infd1, const Extended & extended,
char * const buf = new char[st.st_size+1];
long len = readlink( filename, buf, st.st_size );
bool e = ( len != st.st_size );
- if( !e ) { buf[len] = 0; if( extended.linkpath() != buf ) e = true; }
+ if( !e )
+ {
+ while( len > 1 && buf[len-1] == '/' ) --len; // trailing '/'
+ buf[len] = 0;
+ if( extended.linkpath() != buf ) e = true;
+ }
delete[] buf;
if( e ) { show_file_diff( filename, "Symlink differs" ); diff = true; }
}
@@ -451,9 +461,7 @@ int list_member( const int infd, const Extended & extended,
bool contains_dotdot( const char * const filename )
{
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] == '/' ) ) return true;
+ if( dotdot_at_i( filename, i ) ) return true;
return false;
}
@@ -763,50 +771,10 @@ int decode( const std::string & archive_name, const Arg_parser & parser,
}
prev_extended = false;
- if( extended.linkpath().empty() ) // copy linkpath from ustar header
- {
- int len = 0;
- while( len < linkname_l && header[linkname_o+len] ) ++len;
- while( len > 1 && header[linkname_o+len-1] == '/' ) --len; // trailing '/'
- if( len > 0 )
- {
- const uint8_t c = header[linkname_o+len]; header[linkname_o+len] = 0;
- extended.linkpath( (const char *)header + linkname_o );
- header[linkname_o+len] = c;
- }
- }
-
- if( extended.path().empty() ) // copy path from ustar header
- {
- char stored_name[prefix_l+1+name_l+1];
- int len = 0;
- while( len < prefix_l && header[prefix_o+len] )
- { stored_name[len] = header[prefix_o+len]; ++len; }
- if( len && header[name_o] ) stored_name[len++] = '/';
- for( int i = 0; i < name_l && header[name_o+i]; ++i )
- { stored_name[len] = header[name_o+i]; ++len; }
- while( len > 0 && stored_name[len-1] == '/' ) --len; // trailing '/'
- stored_name[len] = 0;
- extended.path( remove_leading_dotslash( stored_name ) );
- }
- const char * const filename = extended.path().c_str();
-
- bool skip = filenames > 0;
- if( skip )
- for( int i = 0; i < parser.arguments(); ++i )
- if( !parser.code( i ) && parser.argument( i ).size() )
- {
- const char * const name =
- remove_leading_dotslash( parser.argument( i ).c_str() );
- if( compare_prefix_dir( name, filename ) ||
- compare_tslash( name, filename ) )
- { skip = false; name_pending[i] = false; break; }
- }
-
- if( extended.file_size() == 0 &&
- ( typeflag == tf_regular || typeflag == tf_hiperf ) )
- extended.file_size( parse_octal( header + size_o, size_l ) );
+ extended.fill_from_ustar( header ); // copy metadata from header
+ const bool skip = check_skip_filename( parser, name_pending,
+ extended.path().c_str(), filenames );
if( skip )
retval = skip_member( infd, extended );
else if( program_mode == m_list )