From b95f39dfdb659097af23465ec2a533a254fd4ac5 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Tue, 23 Jan 2024 06:54:09 +0100 Subject: Adding upstream version 1.13~rc1. Signed-off-by: Daniel Baumann --- zupdate.cc | 58 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 28 insertions(+), 30 deletions(-) (limited to 'zupdate.cc') diff --git a/zupdate.cc b/zupdate.cc index 6497a5e..15d91d6 100644 --- a/zupdate.cc +++ b/zupdate.cc @@ -57,15 +57,15 @@ void show_help() "other files are ignored. Compressed files are decompressed and then\n" "recompressed on the fly; no temporary files are created. The lzip format\n" "is chosen as destination because it is the most appropriate for\n" - "long-term data archiving.\n" + "long-term archiving.\n" "\nIf no files are specified, recursive searches examine the current\n" "working directory, and nonrecursive searches do nothing.\n" - "\nIf the lzip compressed version of a file already exists, the file is\n" - "skipped unless the option '--force' is given. In this case, if the\n" - "comparison with the existing lzip version fails, an error is returned\n" - "and the original file is not deleted. The operation of zupdate is meant\n" - "to be safe and not cause any data loss. Therefore, existing lzip\n" - "compressed files are never overwritten nor deleted.\n" + "\nIf the lzip-compressed version of a file already exists, the file is skipped\n" + "unless the option '--force' is given. In this case, if the comparison with\n" + "the existing lzip version fails, an error is returned and the original file\n" + "is not deleted. The operation of zupdate is meant to be safe and not cause\n" + "any data loss. Therefore, existing lzip-compressed files are never\n" + "overwritten nor deleted.\n" "\nThe names of the original files must have one of the following extensions:\n" "\n'.bz2', '.gz', '.xz', '.zst', or '.Z', which are recompressed to '.lz'.\n" "\n'.tbz', '.tbz2', '.tgz', '.txz', or '.tzst', which are recompressed to '.tlz'.\n" @@ -73,7 +73,7 @@ void show_help() "\nExit status is 0 if all the compressed files were successfully recompressed\n" "(if needed), compared, and deleted (if requested). 1 if a non-fatal error\n" "occurred (file not found or not regular, or has invalid format, or can't be\n" - "deleted). 2 if a fatal error occurred (invalid command line options,\n" + "deleted). 2 if a fatal error occurred (invalid command-line options,\n" "compressor can't be run, or comparison fails).\n" "\nOptions:\n" " -h, --help display this help and exit\n" @@ -120,28 +120,28 @@ void extract_srcdir_name( const std::string & name, std::string & srcdir ) bool make_dirs( const std::string & name ) { static std::string cached_dirname; - unsigned dirsize = name.size(); // size of dirname without last slash - - for( unsigned i = name.size(); i > 0; --i ) - if( name[i-1] == '/' ) { dirsize = i - 1; break; } - if( dirsize >= name.size() ) return true; // no dirname - if( dirsize == 0 ) return true; // dirname is '/' + unsigned i = name.size(); + while( i > 0 && name[i-1] != '/' ) --i; // remove last component + while( i > 0 && name[i-1] == '/' ) --i; // remove slash(es) + if( i == 0 ) return true; // dirname is '/' or empty + const unsigned dirsize = i; // size of dirname without trailing slash(es) if( cached_dirname.size() == dirsize && cached_dirname.compare( 0, dirsize, name ) == 0 ) return true; - for( unsigned i = 0; i < dirsize; ) + for( i = 0; i < dirsize; ) { while( i < dirsize && name[i] == '/' ) ++i; const unsigned first = i; while( i < dirsize && name[i] != '/' ) ++i; if( first < i ) { - std::string partial( name, 0, i ); + const std::string partial( name, 0, i ); + const mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; struct stat st; if( stat( partial.c_str(), &st ) == 0 ) - { if( !S_ISDIR( st.st_mode ) ) return false; } - else if( mkdir( partial.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | - S_IXOTH ) != 0 && errno != EEXIST ) return false; + { if( !S_ISDIR( st.st_mode ) ) { errno = ENOTDIR; return false; } } + else if( mkdir( partial.c_str(), mode ) != 0 && errno != EEXIST ) + return false; // if EEXIST, another process created the dir } } cached_dirname.assign( name, 0, dirsize ); @@ -168,7 +168,7 @@ void set_permissions( const char * const rname, const struct stat & in_stats ) { bool warning = false; const mode_t mode = in_stats.st_mode; - // chown will in many cases return with EPERM, which can be safely ignored. + // chown in many cases returns with EPERM, which can be safely ignored. if( chown( rname, in_stats.st_uid, in_stats.st_gid ) == 0 ) { if( chmod( rname, mode ) != 0 ) warning = true; } else @@ -180,7 +180,8 @@ void set_permissions( const char * const rname, const struct stat & in_stats ) t.modtime = in_stats.st_mtime; if( utime( rname, &t ) != 0 ) warning = true; if( warning && verbosity >= 2 ) - show_file_error( rname, "Can't change output file attributes.", errno ); + show_file_error( rname, + "warning: can't change output file attributes", errno ); } @@ -204,7 +205,7 @@ int zupdate_file( const std::string & name, const char * const lzip_name, if( format_index == fmt_lz ) { if( verbosity >= 2 ) - std::fprintf( stderr, "%s: Input file '%s' already has '%s' suffix.\n", + std::fprintf( stderr, "%s: %s: Input file already has '%s' suffix.\n", program_name, name.c_str(), extension_from( eindex ) ); return 0; // ignore this file } @@ -227,8 +228,7 @@ int zupdate_file( const std::string & name, const char * const lzip_name, if( !compressor_name ) { if( verbosity >= 2 ) - std::fprintf( stderr, "%s: Unknown extension in file name '%s' -- ignored.\n", - program_name, name.c_str() ); + show_file_error( name.c_str(), "Unknown extension in file name -- ignored." ); return 0; // ignore this file } @@ -247,9 +247,7 @@ int zupdate_file( const std::string & name, const char * const lzip_name, const bool lz_lz_exists = ( stat( rname2.c_str(), &st ) == 0 ); if( lz_exists && !force ) { - if( verbosity >= 0 ) - std::fprintf( stderr, "%s: Output file '%s' already exists, skipping.\n", - program_name, rname.c_str() ); + show_file_error( rname.c_str(), "Output file already exists, skipping." ); return -1; } @@ -283,8 +281,8 @@ int zupdate_file( const std::string & name, const char * const lzip_name, if( verbosity >= 1 ) std::fprintf( stderr, "Recompressing file '%s'\n", name.c_str() ); if( destdir.size() && !make_dirs( rname ) ) - { show_file_error( rname.c_str(), "Error creating intermediate directory." ); - return 2; } + { show_file_error( rname.c_str(), + "Error creating intermediate directory", errno ); return 2; } int fda[2]; // pipe between decompressor and compressor if( pipe( fda ) < 0 ) { show_error( "Can't create pipe", errno ); return 2; } @@ -465,7 +463,7 @@ int main( const int argc, const char * const argv[] ) case lz_opt: parse_compressor( arg, pn, fmt_lz, 1 ); break; case xz_opt: parse_compressor( arg, pn, fmt_xz, 1 ); break; case zst_opt: parse_compressor( arg, pn, fmt_zst, 1 ); break; - default : internal_error( "uncaught option." ); + default: internal_error( "uncaught option." ); } } // end process options -- cgit v1.2.3