2010-03-29 01:07:08 +02:00
|
|
|
/*
|
|
|
|
|
Copyright (C) Andrew Tridgell 1998-2003,
|
2010-10-31 05:09:05 +01:00
|
|
|
Con Kolivas 2006-2010
|
2010-03-29 01:07:08 +02:00
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
*/
|
|
|
|
|
/* lrzip compression - main program */
|
|
|
|
|
#include "rzip.h"
|
|
|
|
|
|
|
|
|
|
struct rzip_control control;
|
|
|
|
|
|
|
|
|
|
static void usage(void)
|
|
|
|
|
{
|
2010-11-04 11:14:55 +01:00
|
|
|
print_output("lrzip version %d.%d.%d\n", LRZIP_MAJOR_VERSION, LRZIP_MINOR_VERSION, LRZIP_MINOR_SUBVERSION);
|
2010-11-01 01:18:58 +01:00
|
|
|
print_output("Copyright (C) Con Kolivas 2006-2010\n\n");
|
|
|
|
|
print_output("Based on rzip ");
|
|
|
|
|
print_output("Copyright (C) Andrew Tridgell 1998-2003\n");
|
|
|
|
|
print_output("usage: lrzip [options] <file...>\n");
|
|
|
|
|
print_output(" Options:\n");
|
2010-11-04 11:14:55 +01:00
|
|
|
print_output(" -w size maximum compression window in hundreds of MB\n");
|
2010-11-01 01:18:58 +01:00
|
|
|
print_output(" default chosen by heuristic dependent on ram and chosen compression\n");
|
|
|
|
|
print_output(" -d decompress\n");
|
|
|
|
|
print_output(" -o filename specify the output file name and/or path\n");
|
|
|
|
|
print_output(" -O directory specify the output directory when -o is not used\n");
|
|
|
|
|
print_output(" -S suffix specify compressed suffix (default '.lrz')\n");
|
|
|
|
|
print_output(" -f force overwrite of any existing files\n");
|
|
|
|
|
print_output(" -D delete existing files\n");
|
|
|
|
|
print_output(" -P don't set permissions on output file - may leave it world-readable\n");
|
|
|
|
|
print_output(" -q don't show compression progress\n");
|
2010-11-04 11:14:55 +01:00
|
|
|
print_output(" -L level set lzma/bzip2/gzip compression level (1-9, default 9)\n");
|
2010-11-01 01:18:58 +01:00
|
|
|
print_output(" -n no backend compression - prepare for other compressor\n");
|
|
|
|
|
print_output(" -l lzo compression (ultra fast)\n");
|
|
|
|
|
print_output(" -b bzip2 compression\n");
|
|
|
|
|
print_output(" -g gzip compression using zlib\n");
|
|
|
|
|
print_output(" -z zpaq compression (best, extreme compression, extremely slow)\n");
|
2010-11-04 11:14:55 +01:00
|
|
|
print_output(" -M Maximum window (all available ram)\n");
|
|
|
|
|
print_output(" -U Use unlimited window size beyond ramsize (100x slower)\n");
|
2010-11-01 01:18:58 +01:00
|
|
|
print_output(" -T value Compression threshold with LZO test. (0 (nil) - 10 (high), default 1)\n");
|
|
|
|
|
print_output(" -N value Set nice value to value (default 19)\n");
|
|
|
|
|
print_output(" -v[v] Increase verbosity\n");
|
|
|
|
|
print_output(" -V show version\n");
|
|
|
|
|
print_output(" -t test compressed file integrity\n");
|
|
|
|
|
print_output(" -i show compressed file information\n");
|
|
|
|
|
print_output("\nIf no filenames or \"-\" is specified, stdin/out will be used.\n");
|
2010-03-29 01:07:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void write_magic(int fd_in, int fd_out)
|
|
|
|
|
{
|
|
|
|
|
struct stat st;
|
|
|
|
|
char magic[24];
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
memset(magic, 0, sizeof(magic));
|
|
|
|
|
strcpy(magic, "LRZI");
|
|
|
|
|
magic[4] = LRZIP_MAJOR_VERSION;
|
|
|
|
|
magic[5] = LRZIP_MINOR_VERSION;
|
|
|
|
|
|
|
|
|
|
if (fstat(fd_in, &st) != 0)
|
|
|
|
|
fatal("bad magic file descriptor!?\n");
|
|
|
|
|
|
2010-11-01 09:18:20 +01:00
|
|
|
memcpy(&magic[6], &control.st_size, 8);
|
2010-03-29 01:07:08 +02:00
|
|
|
|
|
|
|
|
/* save LZMA compression flags */
|
2010-11-01 09:59:27 +01:00
|
|
|
if (LZMA_COMPRESS) {
|
2010-03-29 01:07:08 +02:00
|
|
|
for (i = 0; i < 5; i++)
|
|
|
|
|
magic[i + 16] = (char)control.lzma_properties[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lseek(fd_out, 0, SEEK_SET) != 0)
|
|
|
|
|
fatal("Failed to seek to BOF to write Magic Header\n");
|
|
|
|
|
|
|
|
|
|
if (write(fd_out, magic, sizeof(magic)) != sizeof(magic))
|
|
|
|
|
fatal("Failed to write magic header\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void read_magic(int fd_in, i64 *expected_size)
|
|
|
|
|
{
|
|
|
|
|
char magic[24];
|
2010-10-31 05:17:04 +01:00
|
|
|
uint32_t v;
|
2010-03-29 01:07:08 +02:00
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (read(fd_in, magic, sizeof(magic)) != sizeof(magic))
|
|
|
|
|
fatal("Failed to read magic header\n");
|
|
|
|
|
|
|
|
|
|
*expected_size = 0;
|
|
|
|
|
|
|
|
|
|
if (strncmp(magic, "LRZI", 4) != 0) {
|
|
|
|
|
fatal("Not an lrzip file\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memcpy(&control.major_version, &magic[4], 1);
|
|
|
|
|
memcpy(&control.minor_version, &magic[5], 1);
|
|
|
|
|
|
|
|
|
|
/* Support the convoluted way we described size in versions < 0.40 */
|
|
|
|
|
if (control.major_version == 0 && control.minor_version < 4) {
|
|
|
|
|
memcpy(&v, &magic[6], 4);
|
|
|
|
|
*expected_size = ntohl(v);
|
|
|
|
|
memcpy(&v, &magic[10], 4);
|
|
|
|
|
*expected_size |= ((i64)ntohl(v)) << 32;
|
|
|
|
|
} else
|
|
|
|
|
memcpy(expected_size, &magic[6], 8);
|
|
|
|
|
|
|
|
|
|
/* restore LZMA compression flags only if stored */
|
|
|
|
|
if ((int) magic[16]) {
|
|
|
|
|
for (i = 0; i < 5; i++)
|
|
|
|
|
control.lzma_properties[i] = magic[i + 16];
|
|
|
|
|
}
|
2010-10-31 18:53:53 +01:00
|
|
|
print_verbose("Detected lrzip version %d.%d file.\n", control.major_version, control.minor_version);
|
2010-03-29 01:07:08 +02:00
|
|
|
if (control.major_version > LRZIP_MAJOR_VERSION ||
|
2010-10-31 18:53:53 +01:00
|
|
|
(control.major_version == LRZIP_MAJOR_VERSION && control.minor_version > LRZIP_MINOR_VERSION))
|
|
|
|
|
print_output("Attempting to work with file produced by newer lrzip version %d.%d file.\n", control.major_version, control.minor_version);
|
2010-03-29 01:07:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* preserve ownership and permissions where possible */
|
|
|
|
|
static void preserve_perms(int fd_in, int fd_out)
|
|
|
|
|
{
|
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
|
|
if (fstat(fd_in, &st) != 0)
|
|
|
|
|
fatal("Failed to fstat input file\n");
|
|
|
|
|
if (fchmod(fd_out, (st.st_mode & 0777)) != 0)
|
|
|
|
|
fatal("Failed to set permissions on %s\n", control.outfile);
|
|
|
|
|
|
|
|
|
|
/* chown fail is not fatal */
|
|
|
|
|
fchown(fd_out, st.st_uid, st.st_gid);
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-02 01:14:00 +01:00
|
|
|
/* Open a temporary outputfile to emulate stdout */
|
2010-03-29 01:07:08 +02:00
|
|
|
static int open_tmpoutfile(void)
|
|
|
|
|
{
|
|
|
|
|
int fd_out;
|
|
|
|
|
|
2010-10-31 18:53:53 +01:00
|
|
|
if (STDOUT)
|
|
|
|
|
print_verbose("Outputting to stdout.\n");
|
2010-05-22 01:10:25 +02:00
|
|
|
control.outfile = realloc(NULL, 16);
|
|
|
|
|
strcpy(control.outfile, "lrzipout.XXXXXX");
|
2010-03-29 01:07:08 +02:00
|
|
|
if (!control.outfile)
|
|
|
|
|
fatal("Failed to allocate outfile name\n");
|
|
|
|
|
|
|
|
|
|
fd_out = mkstemp(control.outfile);
|
2010-05-19 15:31:11 +02:00
|
|
|
if (fd_out == -1)
|
2010-03-29 01:07:08 +02:00
|
|
|
fatal("Failed to create out tmpfile: %s\n", strerror(errno));
|
|
|
|
|
return fd_out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Dump temporary outputfile to perform stdout */
|
|
|
|
|
static void dump_tmpoutfile(int fd_out)
|
|
|
|
|
{
|
|
|
|
|
FILE *tmpoutfp;
|
|
|
|
|
int tmpchar;
|
|
|
|
|
|
2010-10-31 18:53:53 +01:00
|
|
|
print_progress("Dumping to stdout.\n");
|
2010-03-29 01:07:08 +02:00
|
|
|
/* flush anything not yet in the temporary file */
|
2010-11-01 01:18:58 +01:00
|
|
|
fsync(fd_out);
|
2010-03-29 01:07:08 +02:00
|
|
|
tmpoutfp = fdopen(fd_out, "r");
|
|
|
|
|
if (tmpoutfp == NULL)
|
|
|
|
|
fatal("Failed to fdopen out tmpfile: %s\n", strerror(errno));
|
|
|
|
|
rewind(tmpoutfp);
|
|
|
|
|
|
|
|
|
|
while ((tmpchar = fgetc(tmpoutfp)) != EOF)
|
|
|
|
|
putchar(tmpchar);
|
|
|
|
|
|
2010-04-25 08:26:00 +02:00
|
|
|
fflush(control.msgout);
|
2010-03-29 01:07:08 +02:00
|
|
|
}
|
|
|
|
|
|
2010-11-01 11:37:55 +01:00
|
|
|
/* Open a temporary inputfile to perform stdin decompression */
|
|
|
|
|
static int open_tmpinfile(void)
|
|
|
|
|
{
|
|
|
|
|
int fd_in;
|
|
|
|
|
|
|
|
|
|
control.infile = malloc(15);
|
|
|
|
|
strcpy(control.infile, "lrzipin.XXXXXX");
|
|
|
|
|
if (!control.infile)
|
|
|
|
|
fatal("Failed to allocate infile name\n");
|
|
|
|
|
|
|
|
|
|
fd_in = mkstemp(control.infile);
|
|
|
|
|
if (fd_in == -1)
|
|
|
|
|
fatal("Failed to create in tmpfile: %s\n", strerror(errno));
|
|
|
|
|
return fd_in;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Read data from stdin into temporary inputfile */
|
|
|
|
|
static void read_tmpinfile(int fd_in)
|
|
|
|
|
{
|
|
|
|
|
FILE *tmpinfp;
|
|
|
|
|
int tmpchar;
|
|
|
|
|
|
|
|
|
|
if (control.flags & FLAG_SHOW_PROGRESS)
|
|
|
|
|
fprintf(control.msgout, "Copying from stdin.\n");
|
|
|
|
|
tmpinfp = fdopen(fd_in, "w+");
|
|
|
|
|
if (tmpinfp == NULL)
|
|
|
|
|
fatal("Failed to fdopen in tmpfile: %s\n", strerror(errno));
|
|
|
|
|
|
|
|
|
|
while ((tmpchar = getchar()) != EOF)
|
|
|
|
|
fputc(tmpchar, tmpinfp);
|
|
|
|
|
|
|
|
|
|
fflush(tmpinfp);
|
|
|
|
|
rewind(tmpinfp);
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-29 01:07:08 +02:00
|
|
|
/*
|
|
|
|
|
decompress one file from the command line
|
|
|
|
|
*/
|
|
|
|
|
static void decompress_file(void)
|
|
|
|
|
{
|
2010-10-31 05:17:04 +01:00
|
|
|
char *tmp, *tmpoutfile, *infilecopy = NULL;
|
2010-03-29 01:07:08 +02:00
|
|
|
int fd_in, fd_out = -1, fd_hist = -1;
|
|
|
|
|
i64 expected_size;
|
|
|
|
|
|
2010-10-31 18:53:53 +01:00
|
|
|
if (!STDIN) {
|
2010-03-29 01:07:08 +02:00
|
|
|
if ((tmp = strrchr(control.infile, '.')) && strcmp(tmp,control.suffix)) {
|
|
|
|
|
/* make sure infile has an extension. If not, add it
|
|
|
|
|
* because manipulations may be made to input filename, set local ptr
|
|
|
|
|
*/
|
|
|
|
|
infilecopy = malloc(strlen(control.infile) + strlen(control.suffix) + 1);
|
|
|
|
|
if (infilecopy == NULL)
|
|
|
|
|
fatal("Failed to allocate memory for infile suffix\n");
|
|
|
|
|
else {
|
|
|
|
|
strcpy(infilecopy, control.infile);
|
|
|
|
|
strcat(infilecopy, control.suffix);
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
infilecopy = strdup(control.infile);
|
|
|
|
|
/* regardless, infilecopy has the input filename */
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-31 18:53:53 +01:00
|
|
|
if (!STDOUT && !TEST_ONLY) {
|
2010-03-29 01:07:08 +02:00
|
|
|
/* if output name already set, use it */
|
|
|
|
|
if (control.outname) {
|
|
|
|
|
control.outfile = strdup(control.outname);
|
|
|
|
|
} else {
|
|
|
|
|
/* default output name from infilecopy
|
|
|
|
|
* test if outdir specified. If so, strip path from filename of
|
|
|
|
|
* infilecopy, then remove suffix.
|
|
|
|
|
*/
|
|
|
|
|
if (control.outdir && (tmp = strrchr(infilecopy, '/')))
|
|
|
|
|
tmpoutfile = strdup(tmp + 1);
|
|
|
|
|
else
|
|
|
|
|
tmpoutfile = strdup(infilecopy);
|
|
|
|
|
|
|
|
|
|
/* remove suffix to make outfile name */
|
|
|
|
|
if ((tmp = strrchr(tmpoutfile, '.')) && !strcmp(tmp, control.suffix))
|
|
|
|
|
*tmp='\0';
|
|
|
|
|
|
|
|
|
|
control.outfile = malloc((control.outdir == NULL? 0: strlen(control.outdir)) + strlen(tmpoutfile) + 1);
|
|
|
|
|
if (!control.outfile)
|
|
|
|
|
fatal("Failed to allocate outfile name\n");
|
|
|
|
|
|
|
|
|
|
if (control.outdir) { /* prepend control.outdir */
|
|
|
|
|
strcpy(control.outfile, control.outdir);
|
|
|
|
|
strcat(control.outfile, tmpoutfile);
|
|
|
|
|
} else
|
|
|
|
|
strcpy(control.outfile, tmpoutfile);
|
|
|
|
|
free(tmpoutfile);
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-31 18:53:53 +01:00
|
|
|
if (!STDOUT)
|
|
|
|
|
print_progress("Output filename is: %s...Decompressing...\n", control.outfile);
|
2010-03-29 01:07:08 +02:00
|
|
|
}
|
|
|
|
|
|
2010-10-31 18:53:53 +01:00
|
|
|
if (STDIN) {
|
2010-11-01 11:37:55 +01:00
|
|
|
fd_in = open_tmpinfile();
|
|
|
|
|
read_tmpinfile(fd_in);
|
2010-03-29 01:07:08 +02:00
|
|
|
} else {
|
|
|
|
|
fd_in = open(infilecopy, O_RDONLY);
|
|
|
|
|
if (fd_in == -1) {
|
|
|
|
|
fatal("Failed to open %s: %s\n",
|
|
|
|
|
infilecopy,
|
|
|
|
|
strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-31 18:53:53 +01:00
|
|
|
if (!(TEST_ONLY | STDOUT)) {
|
|
|
|
|
if (FORCE_REPLACE)
|
2010-03-29 01:07:08 +02:00
|
|
|
fd_out = open(control.outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
|
|
|
|
else
|
|
|
|
|
fd_out = open(control.outfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
|
|
|
|
|
if (fd_out == -1)
|
|
|
|
|
fatal("Failed to create %s: %s\n", control.outfile, strerror(errno));
|
|
|
|
|
|
2010-10-31 18:53:53 +01:00
|
|
|
if (!NO_SET_PERMS)
|
2010-03-29 01:07:08 +02:00
|
|
|
preserve_perms(fd_in, fd_out);
|
2010-11-02 00:52:21 +01:00
|
|
|
} else
|
|
|
|
|
fd_out = open_tmpoutfile();
|
2010-03-29 01:07:08 +02:00
|
|
|
|
2010-11-02 00:52:21 +01:00
|
|
|
fd_hist = open(control.outfile, O_RDONLY);
|
2010-11-02 03:50:15 +01:00
|
|
|
if (fd_hist == -1)
|
|
|
|
|
fatal("Failed to open history file %s\n", control.outfile);
|
|
|
|
|
|
2010-03-29 01:07:08 +02:00
|
|
|
read_magic(fd_in, &expected_size);
|
2010-10-31 18:53:53 +01:00
|
|
|
print_progress("Decompressing...");
|
2010-03-29 01:07:08 +02:00
|
|
|
|
|
|
|
|
runzip_fd(fd_in, fd_out, fd_hist, expected_size);
|
|
|
|
|
|
2010-11-02 00:52:21 +01:00
|
|
|
if (STDOUT)
|
|
|
|
|
dump_tmpoutfile(fd_out);
|
|
|
|
|
|
2010-03-29 01:07:08 +02:00
|
|
|
/* if we get here, no fatal errors during decompression */
|
2010-10-31 18:53:53 +01:00
|
|
|
print_progress("\r");
|
|
|
|
|
if (!(STDOUT | TEST_ONLY))
|
|
|
|
|
print_output("Output filename is: %s: ", control.outfile);
|
|
|
|
|
print_progress("[OK] - %lld bytes \n", expected_size);
|
2010-03-29 01:07:08 +02:00
|
|
|
|
2010-11-02 00:52:21 +01:00
|
|
|
if (close(fd_hist) != 0 || close(fd_out) != 0)
|
|
|
|
|
fatal("Failed to close files\n");
|
|
|
|
|
|
|
|
|
|
if (TEST_ONLY | STDOUT) {
|
|
|
|
|
/* Delete temporary files generated for testing or faking stdout */
|
|
|
|
|
if (unlink(control.outfile) != 0)
|
|
|
|
|
fatal("Failed to unlink tmpfile: %s\n", strerror(errno));
|
2010-03-29 01:07:08 +02:00
|
|
|
}
|
|
|
|
|
|
2010-11-01 11:37:55 +01:00
|
|
|
close(fd_in);
|
2010-03-29 01:07:08 +02:00
|
|
|
|
2010-11-01 11:37:55 +01:00
|
|
|
if (!(KEEP_FILES | TEST_ONLY) || STDIN) {
|
2010-03-29 01:07:08 +02:00
|
|
|
if (unlink(control.infile) != 0)
|
|
|
|
|
fatal("Failed to unlink %s: %s\n", infilecopy, strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(control.outfile);
|
|
|
|
|
free(infilecopy);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void get_fileinfo(void)
|
|
|
|
|
{
|
|
|
|
|
int fd_in, ctype = 0;
|
2010-10-31 05:17:04 +01:00
|
|
|
long double cratio;
|
2010-03-29 01:07:08 +02:00
|
|
|
i64 expected_size;
|
|
|
|
|
i64 infile_size;
|
2010-10-31 05:17:04 +01:00
|
|
|
struct stat st;
|
2010-03-29 01:07:08 +02:00
|
|
|
int seekspot;
|
|
|
|
|
|
|
|
|
|
char *tmp, *infilecopy = NULL;
|
|
|
|
|
|
2010-10-31 18:53:53 +01:00
|
|
|
if (!STDIN) {
|
2010-03-29 01:07:08 +02:00
|
|
|
if ((tmp = strrchr(control.infile, '.')) && strcmp(tmp,control.suffix)) {
|
|
|
|
|
infilecopy = malloc(strlen(control.infile) + strlen(control.suffix) + 1);
|
|
|
|
|
if (infilecopy == NULL)
|
|
|
|
|
fatal("Failed to allocate memory for infile suffix\n");
|
|
|
|
|
else {
|
|
|
|
|
strcpy(infilecopy, control.infile);
|
|
|
|
|
strcat(infilecopy, control.suffix);
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
infilecopy = strdup(control.infile);
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-01 06:45:48 +01:00
|
|
|
if (STDIN)
|
|
|
|
|
fd_in = 0;
|
|
|
|
|
else {
|
2010-03-29 01:07:08 +02:00
|
|
|
fd_in = open(infilecopy, O_RDONLY);
|
|
|
|
|
if (fd_in == -1)
|
|
|
|
|
fatal("Failed to open %s: %s\n", infilecopy, strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get file size */
|
|
|
|
|
if (fstat(fd_in, &st) != 0)
|
|
|
|
|
fatal("bad magic file descriptor!?\n");
|
|
|
|
|
memcpy(&infile_size, &st.st_size, 8);
|
|
|
|
|
|
|
|
|
|
/* Get decompressed size */
|
|
|
|
|
read_magic(fd_in, &expected_size);
|
|
|
|
|
|
|
|
|
|
/* Version < 0.4 had different file format */
|
|
|
|
|
if (control.major_version == 0 && control.minor_version < 4)
|
|
|
|
|
seekspot = 50;
|
|
|
|
|
else
|
|
|
|
|
seekspot = 74;
|
|
|
|
|
if (lseek(fd_in, seekspot, SEEK_SET) == -1)
|
|
|
|
|
fatal("Failed to lseek in get_fileinfo: %s\n", strerror(errno));
|
|
|
|
|
|
|
|
|
|
/* Read the compression type of the first block. It's possible that
|
|
|
|
|
not all blocks are compressed so this may not be accurate.
|
|
|
|
|
*/
|
|
|
|
|
read(fd_in, &ctype, 1);
|
|
|
|
|
|
|
|
|
|
cratio = (long double)expected_size / (long double)infile_size;
|
|
|
|
|
|
2010-10-31 18:53:53 +01:00
|
|
|
print_output("%s:\nlrzip version: %d.%d file\n", infilecopy, control.major_version, control.minor_version);
|
|
|
|
|
print_output("Compression: ");
|
2010-03-29 01:07:08 +02:00
|
|
|
if (ctype == CTYPE_NONE)
|
2010-11-01 01:18:58 +01:00
|
|
|
print_output("rzip alone\n");
|
2010-03-29 01:07:08 +02:00
|
|
|
else if (ctype == CTYPE_BZIP2)
|
2010-11-01 01:18:58 +01:00
|
|
|
print_output("rzip + bzip2\n");
|
2010-03-29 01:07:08 +02:00
|
|
|
else if (ctype == CTYPE_LZO)
|
2010-11-01 01:18:58 +01:00
|
|
|
print_output("rzip + lzo\n");
|
2010-03-29 01:07:08 +02:00
|
|
|
else if (ctype == CTYPE_LZMA)
|
2010-11-01 01:18:58 +01:00
|
|
|
print_output("rzip + lzma\n");
|
2010-03-29 01:07:08 +02:00
|
|
|
else if (ctype == CTYPE_GZIP)
|
2010-11-01 01:18:58 +01:00
|
|
|
print_output("rzip + gzip\n");
|
2010-03-29 01:07:08 +02:00
|
|
|
else if (ctype == CTYPE_ZPAQ)
|
2010-11-01 01:18:58 +01:00
|
|
|
print_output("rzip + zpaq\n");
|
2010-10-31 18:53:53 +01:00
|
|
|
print_output("Decompressed file size: %llu\n", expected_size);
|
|
|
|
|
print_output("Compressed file size: %llu\n", infile_size);
|
|
|
|
|
print_output("Compression ratio: %.3Lf\n", cratio);
|
2010-03-29 01:07:08 +02:00
|
|
|
|
2010-10-31 18:53:53 +01:00
|
|
|
if (STDIN) {
|
2010-03-29 01:07:08 +02:00
|
|
|
if (unlink(control.infile) != 0)
|
|
|
|
|
fatal("Failed to unlink %s: %s\n", infilecopy, strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(control.outfile);
|
|
|
|
|
free(infilecopy);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
compress one file from the command line
|
|
|
|
|
*/
|
|
|
|
|
static void compress_file(void)
|
|
|
|
|
{
|
|
|
|
|
const char *tmp, *tmpinfile; /* we're just using this as a proxy for control.infile.
|
|
|
|
|
* Spares a compiler warning
|
|
|
|
|
*/
|
2010-10-31 05:17:04 +01:00
|
|
|
int fd_in, fd_out;
|
2010-03-29 01:07:08 +02:00
|
|
|
char header[24];
|
|
|
|
|
|
|
|
|
|
memset(header, 0, sizeof(header));
|
|
|
|
|
|
2010-10-31 18:53:53 +01:00
|
|
|
if (!STDIN) {
|
2010-03-29 01:07:08 +02:00
|
|
|
/* is extension at end of infile? */
|
|
|
|
|
if ((tmp = strrchr(control.infile, '.')) && !strcmp(tmp, control.suffix)) {
|
2010-10-31 18:53:53 +01:00
|
|
|
print_output("%s: already has %s suffix. Skipping...\n", control.infile, control.suffix);
|
2010-03-29 01:07:08 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fd_in = open(control.infile, O_RDONLY);
|
|
|
|
|
if (fd_in == -1)
|
|
|
|
|
fatal("Failed to open %s: %s\n", control.infile, strerror(errno));
|
2010-11-01 06:45:48 +01:00
|
|
|
} else
|
|
|
|
|
fd_in = 0;
|
2010-03-29 01:07:08 +02:00
|
|
|
|
2010-10-31 18:53:53 +01:00
|
|
|
if (!STDOUT) {
|
2010-03-29 01:07:08 +02:00
|
|
|
if (control.outname) {
|
|
|
|
|
/* check if outname has control.suffix */
|
|
|
|
|
if (*(control.suffix) == '\0') /* suffix is empty string */
|
|
|
|
|
control.outfile = strdup(control.outname);
|
|
|
|
|
else if ((tmp=strrchr(control.outname, '.')) && strcmp(tmp, control.suffix)) {
|
|
|
|
|
control.outfile = malloc(strlen(control.outname) + strlen(control.suffix) + 1);
|
|
|
|
|
if (!control.outfile)
|
|
|
|
|
fatal("Failed to allocate outfile name\n");
|
|
|
|
|
strcpy(control.outfile, control.outname);
|
|
|
|
|
strcat(control.outfile, control.suffix);
|
2010-11-01 01:18:58 +01:00
|
|
|
print_output("Suffix added to %s.\nFull pathname is: %s\n", control.outname, control.outfile);
|
2010-03-29 01:07:08 +02:00
|
|
|
} else /* no, already has suffix */
|
|
|
|
|
control.outfile = strdup(control.outname);
|
|
|
|
|
} else {
|
|
|
|
|
/* default output name from control.infile
|
|
|
|
|
* test if outdir specified. If so, strip path from filename of
|
|
|
|
|
* control.infile
|
|
|
|
|
*/
|
|
|
|
|
if (control.outdir && (tmp = strrchr(control.infile, '/')))
|
|
|
|
|
tmpinfile = tmp + 1;
|
|
|
|
|
else
|
|
|
|
|
tmpinfile = control.infile;
|
|
|
|
|
|
|
|
|
|
control.outfile = malloc((control.outdir == NULL? 0: strlen(control.outdir)) + strlen(tmpinfile) + strlen(control.suffix) + 1);
|
|
|
|
|
if (!control.outfile)
|
|
|
|
|
fatal("Failed to allocate outfile name\n");
|
|
|
|
|
|
|
|
|
|
if (control.outdir) { /* prepend control.outdir */
|
|
|
|
|
strcpy(control.outfile, control.outdir);
|
|
|
|
|
strcat(control.outfile, tmpinfile);
|
|
|
|
|
} else
|
|
|
|
|
strcpy(control.outfile, tmpinfile);
|
|
|
|
|
strcat(control.outfile, control.suffix);
|
2010-10-31 18:53:53 +01:00
|
|
|
print_progress("Output filename is: %s\n", control.outfile);
|
2010-03-29 01:07:08 +02:00
|
|
|
}
|
|
|
|
|
|
2010-10-31 18:53:53 +01:00
|
|
|
if (FORCE_REPLACE)
|
2010-03-29 01:07:08 +02:00
|
|
|
fd_out = open(control.outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
|
|
|
|
else
|
|
|
|
|
fd_out = open(control.outfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
|
|
|
|
|
if (fd_out == -1)
|
|
|
|
|
fatal("Failed to create %s: %s\n", control.outfile, strerror(errno));
|
|
|
|
|
} else
|
|
|
|
|
fd_out = open_tmpoutfile();
|
|
|
|
|
|
2010-10-31 18:53:53 +01:00
|
|
|
if (!NO_SET_PERMS)
|
2010-03-29 01:07:08 +02:00
|
|
|
preserve_perms(fd_in, fd_out);
|
|
|
|
|
|
|
|
|
|
/* write zeroes to 24 bytes at beginning of file */
|
|
|
|
|
if (write(fd_out, header, sizeof(header)) != sizeof(header))
|
|
|
|
|
fatal("Cannot write file header\n");
|
|
|
|
|
|
|
|
|
|
rzip_fd(fd_in, fd_out);
|
|
|
|
|
|
|
|
|
|
/* write magic at end b/c lzma does not tell us properties until it is done */
|
|
|
|
|
write_magic(fd_in, fd_out);
|
|
|
|
|
|
2010-10-31 18:53:53 +01:00
|
|
|
if (STDOUT)
|
2010-03-29 01:07:08 +02:00
|
|
|
dump_tmpoutfile(fd_out);
|
|
|
|
|
|
|
|
|
|
if (close(fd_in) != 0 || close(fd_out) != 0)
|
|
|
|
|
fatal("Failed to close files\n");
|
|
|
|
|
|
2010-10-31 18:53:53 +01:00
|
|
|
if (STDOUT) {
|
2010-03-29 01:07:08 +02:00
|
|
|
/* Delete temporary files generated for testing or faking stdout */
|
|
|
|
|
if (unlink(control.outfile) != 0)
|
|
|
|
|
fatal("Failed to unlink tmpfile: %s\n", strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-01 06:45:48 +01:00
|
|
|
if (!KEEP_FILES) {
|
2010-03-29 01:07:08 +02:00
|
|
|
if (unlink(control.infile) != 0)
|
|
|
|
|
fatal("Failed to unlink %s: %s\n", control.infile, strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(control.outfile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2010-11-04 11:14:55 +01:00
|
|
|
* Returns ram size in bytes on linux/darwin.
|
2010-03-29 01:07:08 +02:00
|
|
|
*/
|
|
|
|
|
#ifdef __APPLE__
|
|
|
|
|
static i64 get_ram(void)
|
|
|
|
|
{
|
|
|
|
|
int mib[2];
|
|
|
|
|
size_t len;
|
|
|
|
|
i64 *p, ramsize;
|
|
|
|
|
|
|
|
|
|
mib[0] = CTL_HW;
|
|
|
|
|
mib[1] = HW_MEMSIZE;
|
|
|
|
|
sysctl(mib, 2, NULL, &len, NULL, 0);
|
|
|
|
|
p = malloc(len);
|
|
|
|
|
sysctl(mib, 2, p, &len, NULL, 0);
|
2010-11-04 11:14:55 +01:00
|
|
|
ramsize = *p
|
2010-03-29 01:07:08 +02:00
|
|
|
|
|
|
|
|
return ramsize;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
static i64 get_ram(void)
|
|
|
|
|
{
|
2010-11-04 11:14:55 +01:00
|
|
|
return (i64)sysconf(_SC_PHYS_PAGES) * (i64)sysconf(_SC_PAGE_SIZE);
|
2010-03-29 01:07:08 +02:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
|
{
|
|
|
|
|
struct timeval start_time, end_time;
|
|
|
|
|
struct sigaction handler;
|
|
|
|
|
double seconds,total_time; // for timers
|
2010-11-04 11:14:55 +01:00
|
|
|
int c, i;
|
2010-10-31 05:17:04 +01:00
|
|
|
int hours,minutes;
|
|
|
|
|
extern int optind;
|
2010-03-29 01:07:08 +02:00
|
|
|
char *eptr; /* for environment */
|
|
|
|
|
|
|
|
|
|
memset(&control, 0, sizeof(control));
|
|
|
|
|
|
2010-04-25 08:26:00 +02:00
|
|
|
control.msgout = stderr;
|
2010-03-29 01:07:08 +02:00
|
|
|
control.flags = FLAG_SHOW_PROGRESS | FLAG_KEEP_FILES;
|
|
|
|
|
control.suffix = ".lrz";
|
|
|
|
|
control.outdir = NULL;
|
|
|
|
|
|
2010-11-02 01:14:00 +01:00
|
|
|
if (strstr(argv[0], "lrunzip"))
|
2010-03-29 01:07:08 +02:00
|
|
|
control.flags |= FLAG_DECOMPRESS;
|
|
|
|
|
|
2010-11-04 11:14:55 +01:00
|
|
|
control.compression_level = 9;
|
|
|
|
|
control.ramsize = get_ram();
|
2010-03-29 01:07:08 +02:00
|
|
|
control.window = 0;
|
|
|
|
|
control.threshold = 1.0; /* default lzo test compression threshold (level 1) with LZMA compression */
|
|
|
|
|
/* for testing single CPU */
|
|
|
|
|
#ifndef NOTHREAD
|
|
|
|
|
control.threads = sysconf(_SC_NPROCESSORS_ONLN); /* get CPUs for LZMA */
|
|
|
|
|
#else
|
|
|
|
|
control.threads = 1;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
control.nice_val = 19;
|
|
|
|
|
|
|
|
|
|
/* generate crc table */
|
|
|
|
|
CrcGenerateTable();
|
|
|
|
|
|
|
|
|
|
/* Get Preloaded Defaults from lrzip.conf
|
|
|
|
|
* Look in ., $HOME/.lrzip/, /etc/lrzip.
|
|
|
|
|
* If LRZIP=NOCONFIG is set, then ignore config
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
eptr = getenv("LRZIP");
|
|
|
|
|
if (eptr == NULL)
|
|
|
|
|
read_config(&control);
|
|
|
|
|
else if (!strstr(eptr,"NOCONFIG"))
|
|
|
|
|
read_config(&control);
|
|
|
|
|
|
2010-11-04 11:14:55 +01:00
|
|
|
while ((c = getopt(argc, argv, "L:hdS:tVvDfqo:w:nlbMUO:T:N:gPzi")) != -1) {
|
2010-03-29 01:07:08 +02:00
|
|
|
switch (c) {
|
|
|
|
|
case 'L':
|
|
|
|
|
control.compression_level = atoi(optarg);
|
|
|
|
|
if (control.compression_level < 1 || control.compression_level > 9)
|
|
|
|
|
fatal("Invalid compression level (must be 1-9)\n");
|
|
|
|
|
break;
|
|
|
|
|
case 'w':
|
|
|
|
|
control.window = atol(optarg);
|
|
|
|
|
break;
|
|
|
|
|
case 'd':
|
|
|
|
|
control.flags |= FLAG_DECOMPRESS;
|
|
|
|
|
break;
|
|
|
|
|
case 'S':
|
|
|
|
|
control.suffix = optarg;
|
|
|
|
|
break;
|
|
|
|
|
case 'o':
|
|
|
|
|
if (control.outdir)
|
|
|
|
|
fatal("Cannot have -o and -O together\n");
|
|
|
|
|
control.outname = optarg;
|
|
|
|
|
break;
|
|
|
|
|
case 'f':
|
|
|
|
|
control.flags |= FLAG_FORCE_REPLACE;
|
|
|
|
|
break;
|
|
|
|
|
case 'D':
|
|
|
|
|
control.flags &= ~FLAG_KEEP_FILES;
|
|
|
|
|
break;
|
|
|
|
|
case 't':
|
|
|
|
|
if (control.outname)
|
|
|
|
|
fatal("Cannot specify an output file name when just testing.\n");
|
2010-10-31 18:53:53 +01:00
|
|
|
if (!KEEP_FILES)
|
2010-03-29 01:07:08 +02:00
|
|
|
fatal("Doubt that you want to delete a file when just testing.\n");
|
|
|
|
|
control.flags |= FLAG_TEST_ONLY;
|
|
|
|
|
break;
|
|
|
|
|
case 'v':
|
|
|
|
|
/* set verbosity flag */
|
|
|
|
|
if (!(control.flags & FLAG_VERBOSITY) && !(control.flags & FLAG_VERBOSITY_MAX))
|
|
|
|
|
control.flags |= FLAG_VERBOSITY;
|
|
|
|
|
else if ((control.flags & FLAG_VERBOSITY)) {
|
|
|
|
|
control.flags &= ~FLAG_VERBOSITY;
|
|
|
|
|
control.flags |= FLAG_VERBOSITY_MAX;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'q':
|
|
|
|
|
control.flags &= ~FLAG_SHOW_PROGRESS;
|
|
|
|
|
break;
|
|
|
|
|
case 'V':
|
2010-11-04 14:16:18 +01:00
|
|
|
print_output("lrzip version %d.%d.%d\n",
|
2010-03-29 01:07:08 +02:00
|
|
|
LRZIP_MAJOR_VERSION, LRZIP_MINOR_VERSION, LRZIP_MINOR_SUBVERSION);
|
|
|
|
|
exit(0);
|
|
|
|
|
break;
|
|
|
|
|
case 'l':
|
|
|
|
|
if (control.flags & FLAG_NOT_LZMA)
|
|
|
|
|
fatal("Can only use one of -l, -b, -g, -z or -n\n");
|
|
|
|
|
control.flags |= FLAG_LZO_COMPRESS;
|
|
|
|
|
break;
|
|
|
|
|
case 'b':
|
|
|
|
|
if (control.flags & FLAG_NOT_LZMA)
|
|
|
|
|
fatal("Can only use one of -l, -b, -g, -z or -n\n");
|
|
|
|
|
control.flags |= FLAG_BZIP2_COMPRESS;
|
|
|
|
|
break;
|
|
|
|
|
case 'n':
|
|
|
|
|
if (control.flags & FLAG_NOT_LZMA)
|
|
|
|
|
fatal("Can only use one of -l, -b, -g, -z or -n\n");
|
|
|
|
|
control.flags |= FLAG_NO_COMPRESS;
|
|
|
|
|
break;
|
|
|
|
|
case 'M':
|
2010-11-04 11:14:55 +01:00
|
|
|
control.flags |= FLAG_MAXRAM;
|
|
|
|
|
break;
|
|
|
|
|
case 'U':
|
|
|
|
|
control.flags |= FLAG_UNLIMITED;
|
2010-03-29 01:07:08 +02:00
|
|
|
break;
|
|
|
|
|
case 'O':
|
|
|
|
|
if (control.outname) /* can't mix -o and -O */
|
|
|
|
|
fatal("Cannot have options -o and -O together\n");
|
|
|
|
|
control.outdir = malloc(strlen(optarg) + 2);
|
|
|
|
|
if (control.outdir == NULL)
|
|
|
|
|
fatal("Failed to allocate for outdir\n");
|
|
|
|
|
strcpy(control.outdir,optarg);
|
|
|
|
|
if (strcmp(optarg+strlen(optarg) - 1, "/")) /* need a trailing slash */
|
|
|
|
|
strcat(control.outdir, "/");
|
|
|
|
|
break;
|
|
|
|
|
case 'T':
|
|
|
|
|
/* invert argument, a threshold of 1 means that the compressed result can be
|
|
|
|
|
* 90%-100% of the sample size
|
|
|
|
|
*/
|
|
|
|
|
control.threshold = atoi(optarg);
|
|
|
|
|
if (control.threshold < 0 || control.threshold > 10)
|
|
|
|
|
fatal("Threshold value must be between 0 and 10\n");
|
|
|
|
|
control.threshold = 1.05 - control.threshold / 20;
|
|
|
|
|
break;
|
|
|
|
|
case 'N':
|
|
|
|
|
control.nice_val = atoi(optarg);
|
|
|
|
|
if (control.nice_val < -20 || control.nice_val > 19)
|
|
|
|
|
fatal("Invalid nice value (must be -20..19)\n");
|
|
|
|
|
break;
|
|
|
|
|
case 'g':
|
|
|
|
|
if (control.flags & FLAG_NOT_LZMA)
|
|
|
|
|
fatal("Can only use one of -l, -b, -g, -z or -n\n");
|
|
|
|
|
control.flags |= FLAG_ZLIB_COMPRESS;
|
|
|
|
|
break;
|
|
|
|
|
case 'P':
|
|
|
|
|
control.flags |= FLAG_NO_SET_PERMS;
|
|
|
|
|
break;
|
|
|
|
|
case 'z':
|
|
|
|
|
if (control.flags & FLAG_NOT_LZMA)
|
|
|
|
|
fatal("Can only use one of -l, -b, -g, -z or -n\n");
|
|
|
|
|
control.flags |= FLAG_ZPAQ_COMPRESS;
|
|
|
|
|
break;
|
|
|
|
|
case 'i':
|
|
|
|
|
control.flags |= FLAG_INFO;
|
|
|
|
|
break;
|
|
|
|
|
case 'h':
|
|
|
|
|
usage();
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
argc -= optind;
|
|
|
|
|
argv += optind;
|
|
|
|
|
|
|
|
|
|
if (control.outname && argc > 1)
|
|
|
|
|
fatal("Cannot specify output filename with more than 1 file\n");
|
|
|
|
|
|
2010-10-31 18:53:53 +01:00
|
|
|
if (VERBOSE && !SHOW_PROGRESS) {
|
|
|
|
|
print_err("Cannot have -v and -q options. -v wins.\n");
|
2010-03-29 01:07:08 +02:00
|
|
|
control.flags |= FLAG_SHOW_PROGRESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (argc < 1)
|
|
|
|
|
control.flags |= FLAG_STDIN;
|
|
|
|
|
|
2010-11-04 11:14:55 +01:00
|
|
|
#if 0
|
2010-11-01 12:55:59 +01:00
|
|
|
/* malloc limited to 2GB on 32bit */
|
|
|
|
|
if (sizeof(long) == 4 && control.window > 20) {
|
|
|
|
|
control.window = 20;
|
|
|
|
|
print_verbose("Limiting control window to 2GB due to 32bit limitations.\n");
|
|
|
|
|
}
|
2010-11-04 11:14:55 +01:00
|
|
|
#endif
|
2010-11-01 12:55:59 +01:00
|
|
|
|
2010-03-29 01:07:08 +02:00
|
|
|
/* OK, if verbosity set, print summary of options selected */
|
2010-10-31 18:53:53 +01:00
|
|
|
if (VERBOSE && !INFO) {
|
|
|
|
|
print_err("The following options are in effect for this %s.\n",
|
2010-11-01 01:18:58 +01:00
|
|
|
DECOMPRESS ? "DECOMPRESSION" : "COMPRESSION");
|
2010-11-01 09:59:27 +01:00
|
|
|
if (LZMA_COMPRESS)
|
2010-10-31 18:53:53 +01:00
|
|
|
print_err("Threading is %s. Number of CPUs detected: %lu\n", control.threads > 1? "ENABLED" : "DISABLED",
|
2010-03-29 01:07:08 +02:00
|
|
|
control.threads);
|
2010-10-31 18:53:53 +01:00
|
|
|
print_err("Nice Value: %d\n", control.nice_val);
|
2010-11-01 01:18:58 +01:00
|
|
|
if (SHOW_PROGRESS)
|
2010-10-31 18:53:53 +01:00
|
|
|
print_err("Show Progress\n");
|
2010-11-01 01:18:58 +01:00
|
|
|
if (VERBOSITY)
|
2010-10-31 18:53:53 +01:00
|
|
|
print_err("Verbose\n");
|
2010-11-01 01:18:58 +01:00
|
|
|
else if (MAX_VERBOSE)
|
2010-10-31 18:53:53 +01:00
|
|
|
print_err("Max Verbosity\n");
|
2010-11-01 01:18:58 +01:00
|
|
|
if (FORCE_REPLACE)
|
2010-10-31 18:53:53 +01:00
|
|
|
print_err("Overwrite Files\n");
|
2010-11-01 01:18:58 +01:00
|
|
|
if (!KEEP_FILES)
|
2010-10-31 18:53:53 +01:00
|
|
|
print_err("Remove input files on completion\n");
|
2010-03-29 01:07:08 +02:00
|
|
|
if (control.outdir)
|
2010-10-31 18:53:53 +01:00
|
|
|
print_err("Output Directory Specified: %s\n", control.outdir);
|
2010-03-29 01:07:08 +02:00
|
|
|
else if (control.outname)
|
2010-10-31 18:53:53 +01:00
|
|
|
print_err("Output Filename Specified: %s\n", control.outname);
|
2010-11-01 01:18:58 +01:00
|
|
|
if (TEST_ONLY)
|
2010-10-31 18:53:53 +01:00
|
|
|
print_err("Test file integrity\n");
|
2010-11-01 09:59:27 +01:00
|
|
|
|
2010-03-29 01:07:08 +02:00
|
|
|
/* show compression options */
|
2010-11-01 01:18:58 +01:00
|
|
|
if (!DECOMPRESS) {
|
2010-10-31 18:53:53 +01:00
|
|
|
print_err("Compression mode is: ");
|
2010-11-01 09:59:27 +01:00
|
|
|
if (LZMA_COMPRESS)
|
2010-10-31 18:53:53 +01:00
|
|
|
print_err("LZMA. LZO Test Compression Threshold: %.f\n",
|
2010-03-29 01:07:08 +02:00
|
|
|
(control.threshold < 1.05 ? 21 - control.threshold * 20 : 0));
|
2010-11-01 01:18:58 +01:00
|
|
|
else if (LZO_COMPRESS)
|
2010-10-31 18:53:53 +01:00
|
|
|
print_err("LZO\n");
|
2010-11-01 01:18:58 +01:00
|
|
|
else if (BZIP2_COMPRESS)
|
2010-10-31 18:53:53 +01:00
|
|
|
print_err("BZIP2. LZO Test Compression Threshold: %.f\n",
|
2010-03-29 01:07:08 +02:00
|
|
|
(control.threshold < 1.05 ? 21 - control.threshold * 20 : 0));
|
2010-11-01 01:18:58 +01:00
|
|
|
else if (ZLIB_COMPRESS)
|
2010-10-31 18:53:53 +01:00
|
|
|
print_err("GZIP\n");
|
2010-11-01 01:18:58 +01:00
|
|
|
else if (ZPAQ_COMPRESS)
|
2010-10-31 18:53:53 +01:00
|
|
|
print_err("ZPAQ. LZO Test Compression Threshold: %.f\n",
|
2010-03-29 01:07:08 +02:00
|
|
|
(control.threshold < 1.05 ? 21 - control.threshold * 20 : 0));
|
2010-11-01 01:18:58 +01:00
|
|
|
else if (NO_COMPRESS)
|
2010-10-31 18:53:53 +01:00
|
|
|
print_err("RZIP\n");
|
2010-11-04 11:14:55 +01:00
|
|
|
if (control.window) {
|
|
|
|
|
print_verbose("Compression Window: %lld = %lldMB\n", control.window, control.window * 100ull);
|
|
|
|
|
print_verbose("Compression Level: %d\n", control.compression_level);
|
|
|
|
|
}
|
2010-03-29 01:07:08 +02:00
|
|
|
}
|
2010-10-31 18:53:53 +01:00
|
|
|
print_err("\n");
|
2010-03-29 01:07:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (setpriority(PRIO_PROCESS, 0, control.nice_val) == -1)
|
|
|
|
|
fatal("Unable to set nice value\n");
|
|
|
|
|
|
|
|
|
|
/* One extra iteration for the case of no parameters means we will default to stdin/out */
|
|
|
|
|
for (i = 0; i <= argc; i++) {
|
|
|
|
|
if (i < argc)
|
|
|
|
|
control.infile = argv[i];
|
2010-10-31 18:53:53 +01:00
|
|
|
else if (!(i == 0 && STDIN))
|
2010-03-29 01:07:08 +02:00
|
|
|
break;
|
|
|
|
|
if (control.infile && (strcmp(control.infile, "-") == 0))
|
|
|
|
|
control.flags |= FLAG_STDIN;
|
|
|
|
|
|
2010-04-25 08:26:00 +02:00
|
|
|
if (control.outname && (strcmp(control.outname, "-") == 0)) {
|
2010-03-29 01:07:08 +02:00
|
|
|
control.flags |= FLAG_STDOUT;
|
2010-04-25 08:26:00 +02:00
|
|
|
control.msgout = stderr;
|
|
|
|
|
}
|
2010-03-29 01:07:08 +02:00
|
|
|
|
|
|
|
|
/* If we're using stdin and no output filename, use stdout */
|
2010-10-31 18:53:53 +01:00
|
|
|
if (STDIN && !control.outname) {
|
2010-03-29 01:07:08 +02:00
|
|
|
control.flags |= FLAG_STDOUT;
|
2010-04-25 08:26:00 +02:00
|
|
|
control.msgout = stderr;
|
|
|
|
|
}
|
2010-03-29 01:07:08 +02:00
|
|
|
|
2010-10-31 18:53:53 +01:00
|
|
|
if (!STDOUT)
|
2010-04-25 08:26:00 +02:00
|
|
|
control.msgout = stdout;
|
2010-03-29 01:07:08 +02:00
|
|
|
/* Implement signal handler only once flags are set */
|
|
|
|
|
handler.sa_handler = &sighandler;
|
|
|
|
|
sigaction(SIGTERM, &handler, 0);
|
|
|
|
|
sigaction(SIGINT, &handler, 0);
|
|
|
|
|
|
|
|
|
|
gettimeofday(&start_time, NULL);
|
|
|
|
|
|
|
|
|
|
if (control.flags & (FLAG_DECOMPRESS | FLAG_TEST_ONLY))
|
|
|
|
|
decompress_file();
|
2010-10-31 18:53:53 +01:00
|
|
|
else if (INFO)
|
2010-03-29 01:07:08 +02:00
|
|
|
get_fileinfo();
|
|
|
|
|
else
|
|
|
|
|
compress_file();
|
|
|
|
|
|
|
|
|
|
/* compute total time */
|
|
|
|
|
gettimeofday(&end_time, NULL);
|
|
|
|
|
total_time = (end_time.tv_sec + (double)end_time.tv_usec / 1000000) -
|
|
|
|
|
(start_time.tv_sec + (double)start_time.tv_usec / 1000000);
|
|
|
|
|
hours = (int)total_time / 3600;
|
|
|
|
|
minutes = (int)(total_time - hours * 3600) / 60;
|
|
|
|
|
seconds = total_time - hours * 60 - minutes * 60;
|
2010-10-31 18:53:53 +01:00
|
|
|
if (!INFO)
|
|
|
|
|
print_progress("Total time: %02d:%02d:%06.3f\n", hours, minutes, seconds);
|
2010-03-29 01:07:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|