summaryrefslogtreecommitdiffstats
path: root/zupdate.cc
diff options
context:
space:
mode:
Diffstat (limited to 'zupdate.cc')
-rw-r--r--zupdate.cc75
1 files changed, 44 insertions, 31 deletions
diff --git a/zupdate.cc b/zupdate.cc
index dec65f4..cc0ffde 100644
--- a/zupdate.cc
+++ b/zupdate.cc
@@ -1,18 +1,18 @@
-/* Zupdate - recompress bzip2, gzip, xz files to lzip format
- Copyright (C) 2013-2019 Antonio Diaz Diaz.
+/* Zupdate - recompress bzip2, gzip, xz files to lzip format
+ Copyright (C) 2013-2020 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
- the Free Software Foundation, either version 2 of the License, or
- (at your option) any later version.
+ 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
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _FILE_OFFSET_BITS 64
@@ -51,7 +51,7 @@ namespace {
void show_help()
{
- std::printf( "Zupdate recompresses files from bzip2, gzip, and xz formats to lzip\n"
+ std::printf( "zupdate recompresses files from bzip2, gzip, and xz formats to lzip\n"
"format. Each original is compared with the new file and then deleted.\n"
"Only regular files with standard file name extensions are recompressed,\n"
"other files are ignored. Compressed files are decompressed and then\n"
@@ -61,21 +61,23 @@ void show_help()
"\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 '--force' option is given. In this case, if the\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 produce any data loss. Therefore, existing lzip\n"
+ "to be safe and not cause any data loss. Therefore, existing lzip\n"
"compressed files are never overwritten nor deleted.\n"
+ "\nThe names of the original files must have one of the following extensions:\n"
+ "'.bz2', '.gz', and '.xz' are recompressed to '.lz'.\n"
+ "'.tbz', '.tbz2', '.tgz', and '.txz' are recompressed to '.tlz'.\n"
"\nUsage: zupdate [options] [files]\n"
- "\nExit status is 0 if all the compressed files were successfully\n"
- "recompressed (if needed), compared and deleted (if requested). Non-zero\n"
- "otherwise.\n"
+ "\nExit status is 0 if all the compressed files were successfully recompressed\n"
+ "(if needed), compared, and deleted (if requested). Non-zero otherwise.\n"
"\nOptions:\n"
" -h, --help display this help and exit\n"
" -V, --version output version information and exit\n"
" -f, --force don't skip a file even if the .lz exists\n"
" -k, --keep keep (don't delete) input files\n"
- " -l, --lzip-verbose pass a -v option to the lzip compressor\n"
+ " -l, --lzip-verbose pass one option -v to the lzip compressor\n"
" -M, --format=<list> process only the formats in <list>\n"
" -N, --no-rcfile don't read runtime configuration file\n"
" -q, --quiet suppress all messages\n"
@@ -106,7 +108,7 @@ int cant_execute( const std::string & command, const int status )
}
- // Set permissions, owner and times.
+// Set permissions, owner, and times.
void set_permissions( const char * const rname, const struct stat & in_stats )
{
bool warning = false;
@@ -135,7 +137,7 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
{
static int disable_xz = -1; // tri-state bool
int format_index = -1;
- std::string dname; // decompressed_name
+ std::string rname; // recompressed name
const int eindex = extension_index( name ); // search extension
if( eindex >= 0 )
@@ -148,8 +150,9 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
program_name, name.c_str(), extension_from( eindex ) );
return 0; // ignore this file
}
- dname.assign( name, 0, name.size() - std::strlen( extension_from( eindex ) ) );
- dname += extension_to( eindex );
+ rname.assign( name, 0, name.size() - std::strlen( extension_from( eindex ) ) );
+ rname += ( std::strcmp( extension_to( eindex ), ".tar" ) == 0 ) ?
+ ".tlz" : ".lz"; // keep combined extension
}
const char * const compressor_name = get_compressor_name( format_index );
if( !compressor_name )
@@ -176,9 +179,11 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
return 1;
}
- struct stat st;
- std::string rname( dname ); rname += ".lz"; // recompressed_name
+ struct stat st; // not used
+ const std::string rname2( rname + ".lz" ); // produced by lzip < 1.20
const bool lz_exists = ( stat( rname.c_str(), &st ) == 0 );
+ // don't modify an existing 'rname.lz'
+ const bool lz_lz_exists = ( stat( rname2.c_str(), &st ) == 0 );
if( lz_exists && !force )
{
if( verbosity >= 0 )
@@ -245,7 +250,7 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
for( int i = 0; i < size; ++i ) argv[i+2] = lzip_args[i].c_str();
for( int i = 0; i < size2; ++i ) argv[i+size+2] = lzip_args2[i].c_str();
argv[size+size2+2] = "-o";
- argv[size+size2+3] = dname.c_str();
+ argv[size+size2+3] = rname.c_str();
argv[size+size2+4] = 0;
execvp( argv[0], (char **)argv );
}
@@ -258,7 +263,14 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
close( fda[0] ); close( fda[1] );
int retval = wait_for_child( pid, compressor_name );
int retval2 = wait_for_child( pid2, lzip_name );
- if( retval || retval2 ) { std::remove( rname.c_str() ); return 1; }
+ if( retval || retval2 )
+ { if( !lz_lz_exists ) std::remove( rname2.c_str() ); // lzip < 1.20
+ std::remove( rname.c_str() ); return 1; }
+ if( stat( rname.c_str(), &st ) != 0 &&
+ ( lz_lz_exists || stat( rname2.c_str(), &st ) != 0 ||
+ std::rename( rname2.c_str(), rname.c_str() ) != 0 ) )
+ { show_file_error( rname.c_str(), "Error renaming output file", errno );
+ return 1; } // lzip < 1.11
set_permissions( rname.c_str(), in_stats );
}
@@ -268,11 +280,12 @@ int zupdate_file( const std::string & name, const char * const lzip_name,
std::string zcmp_command( invocation_name );
unsigned i = zcmp_command.size();
while( i > 0 && zcmp_command[i-1] != '/' ) --i;
- zcmp_command.resize( i );
- zcmp_command += "zcmp "; // ${bindir}zcmp
+ zcmp_command.resize( i ); zcmp_command.insert( 0U, 1, '\'' );
+ zcmp_command += "zcmp' "; // '[dir/]zcmp'
if( no_rcfile ) zcmp_command += "-N ";
if( verbosity < 0 ) zcmp_command += "-q ";
- zcmp_command += name; zcmp_command += ' '; zcmp_command += rname;
+ zcmp_command += '\''; zcmp_command += name;
+ zcmp_command += "' '"; zcmp_command += rname; zcmp_command += '\'';
int status = std::system( zcmp_command.c_str() );
if( status != 0 )
{ if( !lz_exists ) std::remove( rname.c_str() );
@@ -301,8 +314,8 @@ int main( const int argc, const char * const argv[] )
bool force = false;
bool keep_input_files = false;
bool no_rcfile = false;
- invocation_name = argv[0];
program_name = "zupdate";
+ invocation_name = ( argc > 0 ) ? argv[0] : program_name;
const Arg_parser::Option options[] =
{