summaryrefslogtreecommitdiffstats
path: root/main.cc
diff options
context:
space:
mode:
authorDaniel Baumann <mail@daniel-baumann.ch>2015-11-07 15:18:57 +0000
committerDaniel Baumann <mail@daniel-baumann.ch>2015-11-07 15:18:57 +0000
commit46446038e7d97bb60f516919a3936dd668ddfd54 (patch)
tree44ba8b8c194a34bb5e3a5c0cd8a3ddeb19f0a53d /main.cc
parentAdding debian version 0.5-1. (diff)
downloadplzip-46446038e7d97bb60f516919a3936dd668ddfd54.tar.xz
plzip-46446038e7d97bb60f516919a3936dd668ddfd54.zip
Merging upstream version 0.6.
Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
Diffstat (limited to 'main.cc')
-rw-r--r--main.cc118
1 files changed, 72 insertions, 46 deletions
diff --git a/main.cc b/main.cc
index dc21a9a..17ec3ee 100644
--- a/main.cc
+++ b/main.cc
@@ -34,20 +34,20 @@
#include <string>
#include <vector>
#include <fcntl.h>
+#include <inttypes.h>
#include <pthread.h>
-#include <stdint.h>
#include <unistd.h>
#include <utime.h>
#include <sys/stat.h>
#include <lzlib.h>
-#if CHAR_BIT != 8
-# error "Environments where CHAR_BIT != 8 are not supported."
-#endif
-
#include "arg_parser.h"
#include "plzip.h"
+#if CHAR_BIT != 8
+#error "Environments where CHAR_BIT != 8 are not supported."
+#endif
+
#ifndef LLONG_MAX
#define LLONG_MAX 0x7FFFFFFFFFFFFFFFLL
#endif
@@ -77,7 +77,7 @@ struct { const char * from; const char * to; } const known_extensions[] = {
{ ".tlz", ".tar" },
{ 0, 0 } };
-struct lzma_options
+struct Lzma_options
{
int dictionary_size; // 4KiB..512MiB
int match_len_limit; // 5..273
@@ -87,6 +87,7 @@ enum Mode { m_compress = 0, m_decompress, m_test };
std::string output_filename;
int outfd = -1;
+mode_t outfd_mode = S_IRUSR | S_IWUSR;
bool delete_output_on_interrupt = false;
pthread_t main_thread;
pid_t main_thread_pid;
@@ -99,7 +100,6 @@ void show_help() throw()
std::printf( "\nOptions:\n" );
std::printf( " -h, --help display this help and exit\n" );
std::printf( " -V, --version output version information and exit\n" );
-// std::printf( " -b, --member-size=<n> set member size limit in bytes\n" );
std::printf( " -B, --data-size=<n> set input data block size in bytes\n" );
std::printf( " -c, --stdout send output to standard output\n" );
std::printf( " -d, --decompress decompress\n" );
@@ -110,7 +110,6 @@ void show_help() throw()
std::printf( " -o, --output=<file> if reading stdin, place the output into <file>\n" );
std::printf( " -q, --quiet suppress all messages\n" );
std::printf( " -s, --dictionary-size=<n> set dictionary size limit in bytes [8MiB]\n" );
-// std::printf( " -S, --volume-size=<n> set volume size limit in bytes\n" );
std::printf( " -t, --test test compressed file integrity\n" );
std::printf( " -v, --verbose be verbose (a 2nd -v gives more)\n" );
std::printf( " -1 .. -9 set compression level [default 6]\n" );
@@ -141,7 +140,31 @@ void show_version() throw()
}
-long long getnum( const char * ptr, const int bs = 0,
+const char * format_num( long long num, long long limit = 9999,
+ const int set_prefix = 0 ) throw()
+ {
+ const char * const si_prefix[8] =
+ { "k", "M", "G", "T", "P", "E", "Z", "Y" };
+ const char * const binary_prefix[8] =
+ { "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" };
+ static bool si = false;
+ static char buf[16];
+
+ if( set_prefix ) si = ( set_prefix > 0 );
+ const int factor = ( si ) ? 1000 : 1024;
+ const char * const *prefix = ( si ) ? si_prefix : binary_prefix;
+ const char *p = "";
+ limit = std::max( 999LL, std::min( 999999LL, limit ) );
+
+ for( int i = 0; i < 8 && ( llabs( num ) > limit ||
+ ( llabs( num ) >= factor && num % factor == 0 ) ); ++i )
+ { num /= factor; p = prefix[i]; }
+ snprintf( buf, sizeof buf, "%lld %s", num, p );
+ return buf;
+ }
+
+
+long long getnum( const char * const ptr, const int bs = 0,
const long long llimit = LLONG_MIN + 1,
const long long ulimit = LLONG_MAX ) throw()
{
@@ -199,7 +222,7 @@ long long getnum( const char * ptr, const int bs = 0,
}
-int get_dict_size( const char * arg ) throw()
+int get_dict_size( const char * const arg ) throw()
{
char *tail;
int bits = std::strtol( arg, &tail, 0 );
@@ -223,7 +246,7 @@ int extension_index( const std::string & name ) throw()
}
-int open_instream( const std::string & name, struct stat * in_statsp,
+int open_instream( const std::string & name, struct stat * const in_statsp,
const Mode program_mode, const int eindex,
const bool force, const bool to_stdout ) throw()
{
@@ -293,13 +316,10 @@ void set_d_outname( const std::string & name, const int i ) throw()
bool open_outstream( const bool force ) throw()
{
- if( force )
- outfd = open( output_filename.c_str(),
- O_CREAT | O_TRUNC | O_WRONLY | o_binary,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH );
- else outfd = open( output_filename.c_str(),
- O_CREAT | O_EXCL | O_WRONLY | o_binary,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH );
+ int flags = O_CREAT | O_WRONLY | o_binary;
+ if( force ) flags |= O_TRUNC; else flags |= O_EXCL;
+
+ outfd = open( output_filename.c_str(), flags, outfd_mode );
if( outfd < 0 )
{
if( errno == EEXIST ) outfd = -2; else outfd = -1;
@@ -393,11 +413,11 @@ void set_signals( const bool to_file ) throw()
{
if( to_file )
{
- signal( SIGHUP, signal_handler );
- signal( SIGINT, signal_handler );
- signal( SIGTERM, signal_handler );
+ std::signal( SIGHUP, signal_handler );
+ std::signal( SIGINT, signal_handler );
+ std::signal( SIGTERM, signal_handler );
}
- signal( SIGUSR1, signal_handler );
+ std::signal( SIGUSR1, signal_handler );
}
} // end namespace
@@ -406,6 +426,12 @@ void set_signals( const bool to_file ) throw()
int verbosity = 0;
+// This can be called from any thread, main thread or sub-threads alike, since
+// they all call common helper functions that call fatal() in case of an error.
+//
+void fatal() { signal_handler( SIGUSR1 ); }
+
+
void Pretty_print::operator()( const char * const msg ) const throw()
{
if( verbosity >= 0 )
@@ -423,7 +449,7 @@ void Pretty_print::operator()( const char * const msg ) const throw()
}
-void show_error( const char * msg, const int errcode, const bool help ) throw()
+void show_error( const char * const msg, const int errcode, const bool help ) throw()
{
if( verbosity >= 0 )
{
@@ -439,7 +465,7 @@ void show_error( const char * msg, const int errcode, const bool help ) throw()
}
-void internal_error( const char * msg )
+void internal_error( const char * const msg )
{
std::string s( "internal error: " ); s += msg;
show_error( s.c_str() );
@@ -447,16 +473,10 @@ void internal_error( const char * msg )
}
-// This can be called from any thread, main thread or sub-threads alike, since
-// they all call common helper functions that call fatal() in case of an error.
-//
-void fatal() { signal_handler( SIGUSR1 ); }
-
-
// Returns the number of bytes really read.
// If (returned value < size) and (errno == 0), means EOF was reached.
//
-int readblock( const int fd, uint8_t * buf, const int size ) throw()
+int readblock( const int fd, uint8_t * const buf, const int size ) throw()
{
int rest = size;
errno = 0;
@@ -475,7 +495,7 @@ int readblock( const int fd, uint8_t * buf, const int size ) throw()
// Returns the number of bytes really written.
// If (returned value < size), it is always an error.
//
-int writeblock( const int fd, const uint8_t * buf, const int size ) throw()
+int writeblock( const int fd, const uint8_t * const buf, const int size ) throw()
{
int rest = size;
errno = 0;
@@ -490,22 +510,23 @@ int writeblock( const int fd, const uint8_t * buf, const int size ) throw()
}
-int main( const int argc, const char * argv[] )
+int main( const int argc, const char * const argv[] )
{
// Mapping from gzip/bzip2 style 1..9 compression modes
// to the corresponding LZMA compression modes.
- const lzma_options option_mapping[] =
+ const Lzma_options option_mapping[] =
{
+ { 1 << 16, 5 }, // -0
{ 1 << 20, 10 }, // -1
- { 1 << 20, 12 }, // -2
- { 1 << 20, 17 }, // -3
- { 1 << 21, 26 }, // -4
+ { 3 << 19, 12 }, // -2
+ { 1 << 21, 17 }, // -3
+ { 3 << 20, 26 }, // -4
{ 1 << 22, 44 }, // -5
{ 1 << 23, 80 }, // -6
{ 1 << 24, 108 }, // -7
- { 1 << 24, 163 }, // -8
+ { 3 << 23, 163 }, // -8
{ 1 << 25, 273 } }; // -9
- lzma_options encoder_options = option_mapping[5]; // default = "-6"
+ Lzma_options encoder_options = option_mapping[6]; // default = "-6"
int data_size = 0;
int debug_level = 0;
int infd = -1;
@@ -533,6 +554,7 @@ int main( const int argc, const char * argv[] )
const Arg_parser::Option options[] =
{
+ { '0', 0, Arg_parser::no },
{ '1', "fast", Arg_parser::no },
{ '2', 0, Arg_parser::no },
{ '3', 0, Arg_parser::no },
@@ -546,6 +568,7 @@ int main( const int argc, const char * argv[] )
{ 'B', "data-size", Arg_parser::yes },
{ 'c', "stdout", Arg_parser::no },
{ 'd', "decompress", Arg_parser::no },
+ { 'e', "extreme", Arg_parser::no },
{ 'D', "debug", Arg_parser::yes },
{ 'f', "force", Arg_parser::no },
{ 'h', "help", Arg_parser::no },
@@ -570,20 +593,19 @@ int main( const int argc, const char * argv[] )
{
const int code = parser.code( argind );
if( !code ) break; // no more options
- const char * arg = parser.argument( argind ).c_str();
+ const char * const arg = parser.argument( argind ).c_str();
switch( code )
{
- case '1': case '2': case '3':
- case '4': case '5': case '6':
- case '7': case '8': case '9':
- encoder_options = option_mapping[code-'1']; break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ encoder_options = option_mapping[code-'0']; break;
case 'b': break;
case 'B': data_size = getnum( arg, 0, 2 * LZ_min_dictionary_size(),
2 * LZ_max_dictionary_size() ); break;
case 'c': to_stdout = true; break;
case 'd': program_mode = m_decompress; break;
- case 'D': debug_level = getnum( arg, 0, 0, 3 );
- break;
+ case 'D': debug_level = getnum( arg, 0, 0, 3 ); break;
+ case 'e': break;
case 'f': force = true; break;
case 'h': show_help(); return 0;
case 'k': keep_input_files = true; break;
@@ -605,6 +627,8 @@ int main( const int argc, const char * argv[] )
if( data_size <= 0 )
data_size = 2 * std::max( 65536, encoder_options.dictionary_size );
+ else if( data_size < encoder_options.dictionary_size )
+ encoder_options.dictionary_size = std::max( data_size, LZ_min_dictionary_size() );
if( num_workers <= 0 )
{
@@ -648,6 +672,7 @@ int main( const int argc, const char * argv[] )
if( program_mode == m_compress )
set_c_outname( default_output_filename );
else output_filename = default_output_filename;
+ outfd_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
if( !open_outstream( force ) )
{
if( outfd == -1 && retval < 1 ) retval = 1;
@@ -672,6 +697,7 @@ int main( const int argc, const char * argv[] )
if( program_mode == m_compress )
set_c_outname( input_filename );
else set_d_outname( input_filename, eindex );
+ outfd_mode = S_IRUSR | S_IWUSR;
if( !open_outstream( force ) )
{
if( outfd == -1 && retval < 1 ) retval = 1;