diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-09-21 06:58:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-09-21 06:58:44 +0000 |
commit | dbbdc02b322480ee799107d2cfa317533008e6c8 (patch) | |
tree | a22c11b459ba27df42ea3427d8b48f7873110104 /common_decode.cc | |
parent | Adding upstream version 0.23. (diff) | |
download | tarlz-upstream/0.24.tar.xz tarlz-upstream/0.24.zip |
Adding upstream version 0.24.upstream/0.24
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | common_decode.cc | 63 |
1 files changed, 38 insertions, 25 deletions
diff --git a/common_decode.cc b/common_decode.cc index 835687f..99956ff 100644 --- a/common_decode.cc +++ b/common_decode.cc @@ -1,5 +1,5 @@ /* Tarlz - Archiver with multimember lzip compression - Copyright (C) 2013-2022 Antonio Diaz Diaz. + Copyright (C) 2013-2023 Antonio Diaz Diaz. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,12 +19,13 @@ #include <cerrno> #include <cstdio> -#include <cstdlib> #include <ctime> +#include <unistd.h> #include <sys/stat.h> #include "tarlz.h" #include "arg_parser.h" +#include "decode.h" namespace { @@ -125,7 +126,7 @@ bool format_member_name( const Extended & extended, const Tar_header header, 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 + { time_t z = 0; if( !gmtime_r( &z, &t ) ) // use UTC, the 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 ); @@ -184,36 +185,48 @@ bool show_member_name( const Extended & extended, const Tar_header header, bool check_skip_filename( const Cl_options & cl_opts, std::vector< char > & name_pending, - const char * const filename ) + const char * const filename, const int chdir_fd ) { + static int c_idx = -1; // parser index of last -C executed if( Exclude::excluded( filename ) ) return true; // skip excluded files - 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 ) ) + if( cl_opts.num_files <= 0 ) return false; // no files specified, no skip + bool skip = true; // else skip all but the files (or trees) specified + bool chdir_pending = false; + + for( int i = 0; i < cl_opts.parser.arguments(); ++i ) + { + if( cl_opts.parser.code( i ) == 'C' ) { chdir_pending = true; continue; } + if( !nonempty_arg( cl_opts.parser, i ) ) continue; // skip opts, empty names + 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 ) ) + { + print_removed_prefix( removed_prefix ); + skip = false; name_pending[i] = false; + if( chdir_pending && chdir_fd >= 0 ) { - 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 ) ) - { print_removed_prefix( removed_prefix ); - skip = false; name_pending[i] = false; break; } + if( c_idx > i ) + { if( fchdir( chdir_fd ) != 0 ) + { show_error( "Error changing to initial working directory", errno ); + throw Chdir_error(); } c_idx = -1; } + for( int j = c_idx + 1; j < i; ++j ) + { + if( cl_opts.parser.code( j ) != 'C' ) continue; + const char * const dir = cl_opts.parser.argument( j ).c_str(); + if( chdir( dir ) != 0 ) + { show_file_error( dir, chdir_msg, errno ); throw Chdir_error(); } + c_idx = j; + } } + break; + } + } return skip; } -mode_t get_umask() - { - static mode_t mask = 0; // read once, cache the result - static bool first_call = true; - if( first_call ) { first_call = false; mask = umask( 0 ); umask( mask ); - mask &= S_IRWXU | S_IRWXG | S_IRWXO; } - return mask; - } - - bool make_path( const std::string & name ) { const mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; |