1
0
Fork 0

Merging upstream version 1.13~rc1.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-24 06:03:46 +01:00
parent f40403d840
commit 95e3ee3bd3
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
29 changed files with 472 additions and 517 deletions

View file

@ -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