Merging upstream version 1.13~rc1.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
f40403d840
commit
95e3ee3bd3
29 changed files with 472 additions and 517 deletions
58
zupdate.cc
58
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
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue