From 321b4b38cb22eb640619cebcb1230c604b2e9297 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 24 Sep 2022 03:57:46 +0200 Subject: Adding upstream version 0.23. Signed-off-by: Daniel Baumann --- common_decode.cc | 67 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 29 deletions(-) (limited to 'common_decode.cc') diff --git a/common_decode.cc b/common_decode.cc index a030428..835687f 100644 --- a/common_decode.cc +++ b/common_decode.cc @@ -68,7 +68,8 @@ void format_mode_string( const Tar_header header, char buf[mode_string_size] ) } -int format_user_group_string( const Tar_header header, +int format_user_group_string( const Extended & extended, + const Tar_header header, char buf[group_string_size] ) { int len; @@ -76,11 +77,8 @@ int format_user_group_string( const Tar_header header, len = snprintf( buf, group_string_size, " %.32s/%.32s", header + uname_o, header + gname_o ); else - { - const unsigned uid = parse_octal( header + uid_o, uid_l ); - const unsigned gid = parse_octal( header + gid_o, gid_l ); - len = snprintf( buf, group_string_size, " %u/%u", uid, gid ); - } + len = snprintf( buf, group_string_size, " %llu/%llu", + extended.get_uid(), extended.get_gid() ); return len; } @@ -122,32 +120,41 @@ bool format_member_name( const Extended & extended, const Tar_header header, { format_mode_string( header, rbuf() ); const int group_string_len = - format_user_group_string( header, rbuf() + mode_string_size ); + format_user_group_string( extended, header, rbuf() + mode_string_size ); int offset = mode_string_size + group_string_len; - const time_t mtime = parse_octal( header + mtime_o, mtime_l ); // 33 bits - struct tm tms; - const struct tm * tm = localtime_r( &mtime, &tms ); - if( !tm ) - { time_t z = 0; tm = localtime_r( &z, &tms ); if( !tm ) tm = &tms; } + const time_t mtime = extended.mtime().sec(); + struct tm t; + if( !localtime_r( &mtime, &t ) ) // if local time fails + { time_t z = 0; if( !gmtime_r( &z, &t ) ) // use the UTC epoch + { t.tm_year = 70; t.tm_mon = t.tm_hour = t.tm_min = 0; t.tm_mday = 1; } } const Typeflag typeflag = (Typeflag)header[typeflag_o]; const bool islink = ( typeflag == tf_link || typeflag == tf_symlink ); const char * const link_string = !islink ? "" : ( ( typeflag == tf_link ) ? " link to " : " -> " ); + // print "user/group size" in a field of width 19 with 8 or more for size if( typeflag == tf_chardev || typeflag == tf_blockdev ) - offset += snprintf( rbuf() + offset, rbuf.size() - offset, " %5u,%u", - (unsigned)parse_octal( header + devmajor_o, devmajor_l ), - (unsigned)parse_octal( header + devminor_o, devminor_l ) ); + { + const unsigned devmajor = parse_octal( header + devmajor_o, devmajor_l ); + const unsigned devminor = parse_octal( header + devminor_o, devminor_l ); + const int width = std::max( 1, + std::max( 8, 19 - group_string_len ) - 1 - decimal_digits( devminor ) ); + offset += snprintf( rbuf() + offset, rbuf.size() - offset, " %*u,%u", + width, devmajor, devminor ); + } else - offset += snprintf( rbuf() + offset, rbuf.size() - offset, " %9llu", - extended.file_size() ); + { + const int width = std::max( 8, 19 - group_string_len ); + offset += snprintf( rbuf() + offset, rbuf.size() - offset, " %*llu", + width, extended.file_size() ); + } for( int i = 0; i < 2; ++i ) // resize rbuf if not large enough { const int len = snprintf( rbuf() + offset, rbuf.size() - offset, " %4d-%02u-%02u %02u:%02u %s%s%s\n", - 1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, - tm->tm_hour, tm->tm_min, extended.path().c_str(), - link_string, islink ? extended.linkpath().c_str() : "" ); - if( (int)rbuf.size() > len + offset ) break; + 1900 + t.tm_year, 1 + t.tm_mon, t.tm_mday, t.tm_hour, + t.tm_min, extended.path().c_str(), link_string, + islink ? extended.linkpath().c_str() : "" ); + if( len + offset < (int)rbuf.size() ) break; if( !rbuf.resize( len + offset + 1 ) ) return false; } } @@ -180,16 +187,18 @@ bool check_skip_filename( const Cl_options & cl_opts, const char * const filename ) { if( Exclude::excluded( filename ) ) return true; // skip excluded files - bool skip = cl_opts.num_files > 0; - if( skip ) + bool skip = cl_opts.num_files > 0; // if no files specified, skip nothing + if( skip ) // else skip all but the files (or trees) specified for( int i = 0; i < cl_opts.parser.arguments(); ++i ) if( nonempty_arg( cl_opts.parser, i ) ) { - const char * const name = - remove_leading_dotslash( cl_opts.parser.argument( i ).c_str() ); + std::string removed_prefix; + const char * const name = remove_leading_dotslash( + cl_opts.parser.argument( i ).c_str(), &removed_prefix ); if( compare_prefix_dir( name, filename ) || compare_tslash( name, filename ) ) - { skip = false; name_pending[i] = false; break; } + { print_removed_prefix( removed_prefix ); + skip = false; name_pending[i] = false; break; } } return skip; } @@ -224,10 +233,10 @@ bool make_path( const std::string & name ) { const std::string partial( name, 0, index ); struct stat st; - if( stat( partial.c_str(), &st ) == 0 ) - { if( !S_ISDIR( st.st_mode ) ) return false; } + if( lstat( partial.c_str(), &st ) == 0 ) + { if( !S_ISDIR( st.st_mode ) ) { errno = ENOTDIR; return false; } } else if( mkdir( partial.c_str(), mode ) != 0 && errno != EEXIST ) - return false; + return false; // if EEXIST, another thread or process created the dir } } return true; -- cgit v1.2.3