mirror of
https://github.com/ckolivas/lrzip.git
synced 2025-12-06 07:12:00 +01:00
giant clusterfuck commit: *add and use alloca/strdupa in some spots *implement return values on almost every function *free() is now a macro which also nulls the freed pointer *when in 'library mode', fatal_exit() will not be called *fatal()/failure() are now macros which add line number and file for logging *all occurrences of fatal/failure in files other than main.c are now wrapped to use a logging callback (if specified) and then return *functions now clean up resources on returning with an error
This commit is contained in:
parent
d7495cee61
commit
6dd20d735b
29
liblrzip.h
29
liblrzip.h
|
|
@ -20,4 +20,33 @@
|
||||||
#ifndef LIBLRZIP_H
|
#ifndef LIBLRZIP_H
|
||||||
#define LIBLRZIP_H
|
#define LIBLRZIP_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef struct Lrzip Lrzip;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LRZIP_MODE_NONE,
|
||||||
|
LRZIP_MODE_DECOMPRESS,
|
||||||
|
LRZIP_MODE_NO_COMPRESS,
|
||||||
|
LRZIP_MODE_LZO_COMPRESS,
|
||||||
|
LRZIP_MODE_BZIP2_COMPRESS,
|
||||||
|
LRZIP_MODE_ZLIB_COMPRESS,
|
||||||
|
LRZIP_MODE_ZPAQ_COMPRESS
|
||||||
|
} Lrzip_Mode;
|
||||||
|
|
||||||
|
typedef void (*Lrzip_Password_Cb)(void *, char **, size_t);
|
||||||
|
|
||||||
|
bool lrzip_init(void);
|
||||||
|
void lrzip_config_env(Lrzip *lr);
|
||||||
|
void lrzip_free(Lrzip *lr);
|
||||||
|
Lrzip *lrzip_new(Lrzip_Mode mode);
|
||||||
|
Lrzip_Mode lrzip_mode_get(Lrzip *lr);
|
||||||
|
char **lrzip_files_get(Lrzip *lr);
|
||||||
|
bool lrzip_file_add(Lrzip *lr, const char *file);
|
||||||
|
bool lrzip_file_del(Lrzip *lr, const char *file);
|
||||||
|
void lrzip_outfile_set(Lrzip *lr, const char *file);
|
||||||
|
const char *lrzip_outfile_get(Lrzip *lr);
|
||||||
|
bool lrzip_run(Lrzip *lr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
345
lrzip.c
345
lrzip.c
|
|
@ -56,6 +56,8 @@
|
||||||
|
|
||||||
#define MAGIC_LEN (24)
|
#define MAGIC_LEN (24)
|
||||||
|
|
||||||
|
static void release_hashes(rzip_control *control);
|
||||||
|
|
||||||
static i64 fdout_seekto(rzip_control *control, i64 pos)
|
static i64 fdout_seekto(rzip_control *control, i64 pos)
|
||||||
{
|
{
|
||||||
if (TMP_OUTBUF) {
|
if (TMP_OUTBUF) {
|
||||||
|
|
@ -100,14 +102,16 @@ inline i64 get_ram(rzip_control *control)
|
||||||
|
|
||||||
/* Workaround for uclibc which doesn't properly support sysconf */
|
/* Workaround for uclibc which doesn't properly support sysconf */
|
||||||
if(!(meminfo = fopen("/proc/meminfo", "r")))
|
if(!(meminfo = fopen("/proc/meminfo", "r")))
|
||||||
fatal(control, "fopen\n");
|
fatal_return(("fopen\n"), -1);
|
||||||
|
|
||||||
while(!feof(meminfo) && !fscanf(meminfo, "MemTotal: %Lu kB", &ramsize)) {
|
while(!feof(meminfo) && !fscanf(meminfo, "MemTotal: %Lu kB", &ramsize)) {
|
||||||
if (unlikely(fgets(aux, sizeof(aux), meminfo) == NULL))
|
if (unlikely(fgets(aux, sizeof(aux), meminfo) == NULL)) {
|
||||||
fatal(control, "Failed to fgets in get_ram\n");
|
fclose(meminfo);
|
||||||
|
fatal_return(("Failed to fgets in get_ram\n"), -1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (fclose(meminfo) == -1)
|
if (fclose(meminfo) == -1)
|
||||||
fatal(control, "fclose");
|
fatal_return(("fclose"), -1);
|
||||||
ramsize *= 1000;
|
ramsize *= 1000;
|
||||||
|
|
||||||
return ramsize;
|
return ramsize;
|
||||||
|
|
@ -130,7 +134,7 @@ i64 nloops(i64 seconds, uchar *b1, uchar *b2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void write_magic(rzip_control *control)
|
bool write_magic(rzip_control *control)
|
||||||
{
|
{
|
||||||
char magic[MAGIC_LEN];
|
char magic[MAGIC_LEN];
|
||||||
|
|
||||||
|
|
@ -168,11 +172,12 @@ void write_magic(rzip_control *control)
|
||||||
magic[22] = 1;
|
magic[22] = 1;
|
||||||
|
|
||||||
if (unlikely(fdout_seekto(control, 0)))
|
if (unlikely(fdout_seekto(control, 0)))
|
||||||
fatal(control, "Failed to seek to BOF to write Magic Header\n");
|
fatal_return(("Failed to seek to BOF to write Magic Header\n"), false);
|
||||||
|
|
||||||
if (unlikely(put_fdout(control, magic, MAGIC_LEN) != MAGIC_LEN))
|
if (unlikely(put_fdout(control, magic, MAGIC_LEN) != MAGIC_LEN))
|
||||||
fatal(control, "Failed to write magic header\n");
|
fatal_return(("Failed to write magic header\n"), false);
|
||||||
control->magic_written = 1;
|
control->magic_written = 1;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline i64 enc_loops(uchar b1, uchar b2)
|
static inline i64 enc_loops(uchar b1, uchar b2)
|
||||||
|
|
@ -180,14 +185,14 @@ static inline i64 enc_loops(uchar b1, uchar b2)
|
||||||
return (i64)b2 << (i64)b1;
|
return (i64)b2 << (i64)b1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_magic(rzip_control *control, char *magic)
|
static bool get_magic(rzip_control *control, char *magic)
|
||||||
{
|
{
|
||||||
int encrypted, md5, i;
|
int encrypted, md5, i;
|
||||||
i64 expected_size;
|
i64 expected_size;
|
||||||
uint32_t v;
|
uint32_t v;
|
||||||
|
|
||||||
if (unlikely(strncmp(magic, "LRZI", 4)))
|
if (unlikely(strncmp(magic, "LRZI", 4)))
|
||||||
failure(control, "Not an lrzip file\n");
|
failure_return(("Not an lrzip file\n"), false);
|
||||||
|
|
||||||
memcpy(&control->major_version, &magic[4], 1);
|
memcpy(&control->major_version, &magic[4], 1);
|
||||||
memcpy(&control->minor_version, &magic[5], 1);
|
memcpy(&control->minor_version, &magic[5], 1);
|
||||||
|
|
@ -230,7 +235,7 @@ static void get_magic(rzip_control *control, char *magic)
|
||||||
if (encrypted == 1)
|
if (encrypted == 1)
|
||||||
control->flags |= FLAG_ENCRYPT;
|
control->flags |= FLAG_ENCRYPT;
|
||||||
else
|
else
|
||||||
failure(control, "Unknown encryption\n");
|
failure_return(("Unknown encryption\n"), false);
|
||||||
/* In encrypted files, the size field is used to store the salt
|
/* In encrypted files, the size field is used to store the salt
|
||||||
* instead and the size is unknown, just like a STDOUT chunked
|
* instead and the size is unknown, just like a STDOUT chunked
|
||||||
* file */
|
* file */
|
||||||
|
|
@ -242,34 +247,37 @@ static void get_magic(rzip_control *control, char *magic)
|
||||||
print_output("Asked to decrypt a non-encrypted archive. Bypassing decryption.\n");
|
print_output("Asked to decrypt a non-encrypted archive. Bypassing decryption.\n");
|
||||||
control->flags &= ~FLAG_ENCRYPT;
|
control->flags &= ~FLAG_ENCRYPT;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_magic(rzip_control *control, int fd_in, i64 *expected_size)
|
bool read_magic(rzip_control *control, int fd_in, i64 *expected_size)
|
||||||
{
|
{
|
||||||
char magic[MAGIC_LEN];
|
char magic[MAGIC_LEN];
|
||||||
|
|
||||||
memset(magic, 0, sizeof(magic));
|
memset(magic, 0, sizeof(magic));
|
||||||
/* Initially read only <v0.6x header */
|
/* Initially read only <v0.6x header */
|
||||||
if (unlikely(read(fd_in, magic, 24) != 24))
|
if (unlikely(read(fd_in, magic, 24) != 24))
|
||||||
fatal(control, "Failed to read magic header\n");
|
fatal_return(("Failed to read magic header\n"), false);
|
||||||
|
|
||||||
get_magic(control, magic);
|
if (unlikely(!get_magic(control, magic))) return false;
|
||||||
*expected_size = control->st_size;
|
*expected_size = control->st_size;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* preserve ownership and permissions where possible */
|
/* preserve ownership and permissions where possible */
|
||||||
void preserve_perms(rzip_control *control, int fd_in, int fd_out)
|
bool preserve_perms(rzip_control *control, int fd_in, int fd_out)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (unlikely(fstat(fd_in, &st)))
|
if (unlikely(fstat(fd_in, &st)))
|
||||||
fatal(control, "Failed to fstat input file\n");
|
fatal_return(("Failed to fstat input file\n"), false);
|
||||||
if (unlikely(fchmod(fd_out, (st.st_mode & 0666))))
|
if (unlikely(fchmod(fd_out, (st.st_mode & 0666))))
|
||||||
print_err("Warning, unable to set permissions on %s\n", control->outfile);
|
print_err("Warning, unable to set permissions on %s\n", control->outfile);
|
||||||
|
|
||||||
/* chown fail is not fatal */
|
/* chown fail is not fatal_return(( */
|
||||||
if (unlikely(fchown(fd_out, st.st_uid, st.st_gid)))
|
if (unlikely(fchown(fd_out, st.st_uid, st.st_gid)))
|
||||||
print_err("Warning, unable to set owner on %s\n", control->outfile);
|
print_err("Warning, unable to set owner on %s\n", control->outfile);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open a temporary outputfile to emulate stdout */
|
/* Open a temporary outputfile to emulate stdout */
|
||||||
|
|
@ -282,24 +290,24 @@ int open_tmpoutfile(rzip_control *control)
|
||||||
if (control->tmpdir) {
|
if (control->tmpdir) {
|
||||||
control->outfile = realloc(NULL, strlen(control->tmpdir) + 16);
|
control->outfile = realloc(NULL, strlen(control->tmpdir) + 16);
|
||||||
if (unlikely(!control->outfile))
|
if (unlikely(!control->outfile))
|
||||||
fatal(control, "Failed to allocate outfile name\n");
|
fatal_return(("Failed to allocate outfile name\n"), -1);
|
||||||
strcpy(control->outfile, control->tmpdir);
|
strcpy(control->outfile, control->tmpdir);
|
||||||
strcat(control->outfile, "lrzipout.XXXXXX");
|
strcat(control->outfile, "lrzipout.XXXXXX");
|
||||||
} else {
|
} else {
|
||||||
control->outfile = realloc(NULL, 16);
|
control->outfile = realloc(NULL, 16);
|
||||||
if (unlikely(!control->outfile))
|
if (unlikely(!control->outfile))
|
||||||
fatal(control, "Failed to allocate outfile name\n");
|
fatal_return(("Failed to allocate outfile name\n"), -1);
|
||||||
strcpy(control->outfile, "lrzipout.XXXXXX");
|
strcpy(control->outfile, "lrzipout.XXXXXX");
|
||||||
}
|
}
|
||||||
|
|
||||||
fd_out = mkstemp(control->outfile);
|
fd_out = mkstemp(control->outfile);
|
||||||
if (unlikely(fd_out == -1))
|
if (unlikely(fd_out == -1))
|
||||||
fatal(control, "Failed to create out tmpfile: %s\n", control->outfile);
|
fatal_return(("Failed to create out tmpfile: %s\n", control->outfile), -1);
|
||||||
register_outfile(control, control->outfile, TEST_ONLY || STDOUT || !KEEP_BROKEN);
|
register_outfile(control, control->outfile, TEST_ONLY || STDOUT || !KEEP_BROKEN);
|
||||||
return fd_out;
|
return fd_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fwrite_stdout(rzip_control *control, void *buf, i64 len)
|
static bool fwrite_stdout(rzip_control *control, void *buf, i64 len)
|
||||||
{
|
{
|
||||||
uchar *offset_buf = buf;
|
uchar *offset_buf = buf;
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
|
@ -313,15 +321,16 @@ static void fwrite_stdout(rzip_control *control, void *buf, i64 len)
|
||||||
ret = len;
|
ret = len;
|
||||||
ret = fwrite(offset_buf, 1, ret, stdout);
|
ret = fwrite(offset_buf, 1, ret, stdout);
|
||||||
if (unlikely(ret <= 0))
|
if (unlikely(ret <= 0))
|
||||||
fatal(control, "Failed to fwrite in fwrite_stdout\n");
|
fatal_return(("Failed to fwrite in fwrite_stdout\n"), false);
|
||||||
len -= ret;
|
len -= ret;
|
||||||
offset_buf += ret;
|
offset_buf += ret;
|
||||||
total += ret;
|
total += ret;
|
||||||
}
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_fdout(rzip_control *control, void *buf, i64 len)
|
bool write_fdout(rzip_control *control, void *buf, i64 len)
|
||||||
{
|
{
|
||||||
uchar *offset_buf = buf;
|
uchar *offset_buf = buf;
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
|
@ -330,27 +339,30 @@ void write_fdout(rzip_control *control, void *buf, i64 len)
|
||||||
ret = MIN(len, one_g);
|
ret = MIN(len, one_g);
|
||||||
ret = write(control->fd_out, offset_buf, (size_t)ret);
|
ret = write(control->fd_out, offset_buf, (size_t)ret);
|
||||||
if (unlikely(ret <= 0))
|
if (unlikely(ret <= 0))
|
||||||
fatal(control, "Failed to write to fd_out in write_fdout\n");
|
fatal_return(("Failed to write to fd_out in write_fdout\n"), false);;
|
||||||
len -= ret;
|
len -= ret;
|
||||||
offset_buf += ret;
|
offset_buf += ret;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void flush_tmpoutbuf(rzip_control *control)
|
bool flush_tmpoutbuf(rzip_control *control)
|
||||||
{
|
{
|
||||||
if (!TEST_ONLY) {
|
if (!TEST_ONLY) {
|
||||||
print_maxverbose("Dumping buffer to physical file.\n");
|
print_maxverbose("Dumping buffer to physical file.\n");
|
||||||
if (STDOUT)
|
if (STDOUT) {
|
||||||
fwrite_stdout(control, control->tmp_outbuf, control->out_len);
|
if (unlikely(!fwrite_stdout(control, control->tmp_outbuf, control->out_len))) return false;
|
||||||
else
|
} else {
|
||||||
write_fdout(control, control->tmp_outbuf, control->out_len);
|
if (unlikely(!write_fdout(control, control->tmp_outbuf, control->out_len))) return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
control->out_relofs += control->out_len;
|
control->out_relofs += control->out_len;
|
||||||
control->out_ofs = control->out_len = 0;
|
control->out_ofs = control->out_len = 0;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dump temporary outputfile to perform stdout */
|
/* Dump temporary outputfile to perform stdout */
|
||||||
void dump_tmpoutfile(rzip_control *control, int fd_out)
|
bool dump_tmpoutfile(rzip_control *control, int fd_out)
|
||||||
{
|
{
|
||||||
FILE *tmpoutfp;
|
FILE *tmpoutfp;
|
||||||
int tmpchar;
|
int tmpchar;
|
||||||
|
|
@ -359,7 +371,7 @@ void dump_tmpoutfile(rzip_control *control, int fd_out)
|
||||||
fsync(fd_out);
|
fsync(fd_out);
|
||||||
tmpoutfp = fdopen(fd_out, "r");
|
tmpoutfp = fdopen(fd_out, "r");
|
||||||
if (unlikely(tmpoutfp == NULL))
|
if (unlikely(tmpoutfp == NULL))
|
||||||
fatal(control, "Failed to fdopen out tmpfile\n");
|
fatal_return(("Failed to fdopen out tmpfile\n"), false);
|
||||||
rewind(tmpoutfp);
|
rewind(tmpoutfp);
|
||||||
|
|
||||||
if (!TEST_ONLY) {
|
if (!TEST_ONLY) {
|
||||||
|
|
@ -371,12 +383,13 @@ void dump_tmpoutfile(rzip_control *control, int fd_out)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(ftruncate(fd_out, 0)))
|
if (unlikely(ftruncate(fd_out, 0)))
|
||||||
fatal(control, "Failed to ftruncate fd_out in dump_tmpoutfile\n");
|
fatal_return(("Failed to ftruncate fd_out in dump_tmpoutfile\n"), false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Used if we're unable to read STDIN into the temporary buffer, shunts data
|
/* Used if we're unable to read STDIN into the temporary buffer, shunts data
|
||||||
* to temporary file */
|
* to temporary file */
|
||||||
void write_fdin(rzip_control *control)
|
bool write_fdin(rzip_control *control)
|
||||||
{
|
{
|
||||||
uchar *offset_buf = control->tmp_inbuf;
|
uchar *offset_buf = control->tmp_inbuf;
|
||||||
i64 len = control->in_len;
|
i64 len = control->in_len;
|
||||||
|
|
@ -386,10 +399,11 @@ void write_fdin(rzip_control *control)
|
||||||
ret = MIN(len, one_g);
|
ret = MIN(len, one_g);
|
||||||
ret = write(control->fd_in, offset_buf, (size_t)ret);
|
ret = write(control->fd_in, offset_buf, (size_t)ret);
|
||||||
if (unlikely(ret <= 0))
|
if (unlikely(ret <= 0))
|
||||||
fatal(control, "Failed to write to fd_in in write_fdin\n");
|
fatal_return(("Failed to write to fd_in in write_fdin\n"), false);
|
||||||
len -= ret;
|
len -= ret;
|
||||||
offset_buf += ret;
|
offset_buf += ret;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open a temporary inputfile to perform stdin decompression */
|
/* Open a temporary inputfile to perform stdin decompression */
|
||||||
|
|
@ -400,28 +414,31 @@ int open_tmpinfile(rzip_control *control)
|
||||||
if (control->tmpdir) {
|
if (control->tmpdir) {
|
||||||
control->infile = malloc(strlen(control->tmpdir) + 15);
|
control->infile = malloc(strlen(control->tmpdir) + 15);
|
||||||
if (unlikely(!control->infile))
|
if (unlikely(!control->infile))
|
||||||
fatal(control, "Failed to allocate infile name\n");
|
fatal_return(("Failed to allocate infile name\n"), -1);
|
||||||
strcpy(control->infile, control->tmpdir);
|
strcpy(control->infile, control->tmpdir);
|
||||||
strcat(control->infile, "lrzipin.XXXXXX");
|
strcat(control->infile, "lrzipin.XXXXXX");
|
||||||
} else {
|
} else {
|
||||||
control->infile = malloc(15);
|
control->infile = malloc(15);
|
||||||
if (unlikely(!control->infile))
|
if (unlikely(!control->infile))
|
||||||
fatal(control, "Failed to allocate infile name\n");
|
fatal_return(("Failed to allocate infile name\n"), -1);
|
||||||
strcpy(control->infile, "lrzipin.XXXXXX");
|
strcpy(control->infile, "lrzipin.XXXXXX");
|
||||||
}
|
}
|
||||||
|
|
||||||
fd_in = mkstemp(control->infile);
|
fd_in = mkstemp(control->infile);
|
||||||
if (unlikely(fd_in == -1))
|
if (unlikely(fd_in == -1))
|
||||||
fatal(control, "Failed to create in tmpfile: %s\n", control->infile);
|
fatal_return(("Failed to create in tmpfile: %s\n", control->infile), -1);
|
||||||
register_infile(control, control->infile, (DECOMPRESS || TEST_ONLY) && STDIN);
|
register_infile(control, control->infile, (DECOMPRESS || TEST_ONLY) && STDIN);
|
||||||
/* Unlink temporary file immediately to minimise chance of files left
|
/* Unlink temporary file immediately to minimise chance of files left
|
||||||
* lying around in cases of failure. */
|
* lying around in cases of failure_return((. */
|
||||||
if (unlikely(unlink(control->infile)))
|
if (unlikely(unlink(control->infile))) {
|
||||||
fatal(control, "Failed to unlink tmpfile: %s\n", control->infile);
|
fatal("Failed to unlink tmpfile: %s\n", control->infile);
|
||||||
|
close(fd_in);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return fd_in;
|
return fd_in;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void read_tmpinmagic(rzip_control *control)
|
static bool read_tmpinmagic(rzip_control *control)
|
||||||
{
|
{
|
||||||
char magic[MAGIC_LEN];
|
char magic[MAGIC_LEN];
|
||||||
int i, tmpchar;
|
int i, tmpchar;
|
||||||
|
|
@ -430,14 +447,14 @@ static void read_tmpinmagic(rzip_control *control)
|
||||||
for (i = 0; i < 24; i++) {
|
for (i = 0; i < 24; i++) {
|
||||||
tmpchar = getchar();
|
tmpchar = getchar();
|
||||||
if (unlikely(tmpchar == EOF))
|
if (unlikely(tmpchar == EOF))
|
||||||
failure(control, "Reached end of file on STDIN prematurely on v05 magic read\n");
|
failure_return(("Reached end of file on STDIN prematurely on v05 magic read\n"), false);
|
||||||
magic[i] = (char)tmpchar;
|
magic[i] = (char)tmpchar;
|
||||||
}
|
}
|
||||||
get_magic(control, magic);
|
return get_magic(control, magic);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read data from stdin into temporary inputfile */
|
/* Read data from stdin into temporary inputfile */
|
||||||
void read_tmpinfile(rzip_control *control, int fd_in)
|
bool read_tmpinfile(rzip_control *control, int fd_in)
|
||||||
{
|
{
|
||||||
FILE *tmpinfp;
|
FILE *tmpinfp;
|
||||||
int tmpchar;
|
int tmpchar;
|
||||||
|
|
@ -446,18 +463,19 @@ void read_tmpinfile(rzip_control *control, int fd_in)
|
||||||
fprintf(control->msgout, "Copying from stdin.\n");
|
fprintf(control->msgout, "Copying from stdin.\n");
|
||||||
tmpinfp = fdopen(fd_in, "w+");
|
tmpinfp = fdopen(fd_in, "w+");
|
||||||
if (unlikely(tmpinfp == NULL))
|
if (unlikely(tmpinfp == NULL))
|
||||||
fatal(control, "Failed to fdopen in tmpfile\n");
|
fatal_return(("Failed to fdopen in tmpfile\n"), false);
|
||||||
|
|
||||||
while ((tmpchar = getchar()) != EOF)
|
while ((tmpchar = getchar()) != EOF)
|
||||||
fputc(tmpchar, tmpinfp);
|
fputc(tmpchar, tmpinfp);
|
||||||
|
|
||||||
fflush(tmpinfp);
|
fflush(tmpinfp);
|
||||||
rewind(tmpinfp);
|
rewind(tmpinfp);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* To perform STDOUT, we allocate a proportion of ram that is then used as
|
/* To perform STDOUT, we allocate a proportion of ram that is then used as
|
||||||
* a pseudo-temporary file */
|
* a pseudo-temporary file */
|
||||||
static void open_tmpoutbuf(rzip_control *control)
|
static bool open_tmpoutbuf(rzip_control *control)
|
||||||
{
|
{
|
||||||
control->flags |= FLAG_TMP_OUTBUF;
|
control->flags |= FLAG_TMP_OUTBUF;
|
||||||
control->out_maxlen = control->maxram;
|
control->out_maxlen = control->maxram;
|
||||||
|
|
@ -465,9 +483,10 @@ static void open_tmpoutbuf(rzip_control *control)
|
||||||
* fall back to a real temporary file */
|
* fall back to a real temporary file */
|
||||||
control->tmp_outbuf = malloc(control->maxram + control->page_size);
|
control->tmp_outbuf = malloc(control->maxram + control->page_size);
|
||||||
if (unlikely(!control->tmp_outbuf))
|
if (unlikely(!control->tmp_outbuf))
|
||||||
fatal(control, "Failed to malloc tmp_outbuf in open_tmpoutbuf\n");
|
fatal_return(("Failed to malloc tmp_outbuf in open_tmpoutbuf\n"), false);
|
||||||
if (!DECOMPRESS && !TEST_ONLY)
|
if (!DECOMPRESS && !TEST_ONLY)
|
||||||
control->out_ofs = control->out_len = MAGIC_LEN;
|
control->out_ofs = control->out_len = MAGIC_LEN;\
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void close_tmpoutbuf(rzip_control *control)
|
void close_tmpoutbuf(rzip_control *control)
|
||||||
|
|
@ -476,13 +495,14 @@ void close_tmpoutbuf(rzip_control *control)
|
||||||
free(control->tmp_outbuf);
|
free(control->tmp_outbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void open_tmpinbuf(rzip_control *control)
|
static bool open_tmpinbuf(rzip_control *control)
|
||||||
{
|
{
|
||||||
control->flags |= FLAG_TMP_INBUF;
|
control->flags |= FLAG_TMP_INBUF;
|
||||||
control->in_maxlen = control->maxram;
|
control->in_maxlen = control->maxram;
|
||||||
control->tmp_inbuf = malloc(control->maxram + control->page_size);
|
control->tmp_inbuf = malloc(control->maxram + control->page_size);
|
||||||
if (unlikely(!control->tmp_inbuf))
|
if (unlikely(!control->tmp_inbuf))
|
||||||
fatal(control, "Failed to malloc tmp_inbuf in open_tmpinbuf\n");
|
fatal_return(("Failed to malloc tmp_inbuf in open_tmpinbuf\n"), false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void clear_tmpinbuf(rzip_control *control)
|
inline void clear_tmpinbuf(rzip_control *control)
|
||||||
|
|
@ -490,12 +510,13 @@ inline void clear_tmpinbuf(rzip_control *control)
|
||||||
control->in_len = control->in_ofs = 0;
|
control->in_len = control->in_ofs = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_tmpinfile(rzip_control *control)
|
bool clear_tmpinfile(rzip_control *control)
|
||||||
{
|
{
|
||||||
if (unlikely(lseek(control->fd_in, 0, SEEK_SET)))
|
if (unlikely(lseek(control->fd_in, 0, SEEK_SET)))
|
||||||
fatal(control, "Failed to lseek on fd_in in clear_tmpinfile\n");
|
fatal_return(("Failed to lseek on fd_in in clear_tmpinfile\n"), false);
|
||||||
if (unlikely(ftruncate(control->fd_in, 0)))
|
if (unlikely(ftruncate(control->fd_in, 0)))
|
||||||
fatal(control, "Failed to truncate fd_in in clear_tmpinfile\n");
|
fatal_return(("Failed to truncate fd_in in clear_tmpinfile\n"), false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void close_tmpinbuf(rzip_control *control)
|
void close_tmpinbuf(rzip_control *control)
|
||||||
|
|
@ -510,7 +531,7 @@ static int get_pass(rzip_control *control, char *s)
|
||||||
|
|
||||||
memset(s, 0, PASS_LEN - SALT_LEN);
|
memset(s, 0, PASS_LEN - SALT_LEN);
|
||||||
if (unlikely(fgets(s, PASS_LEN - SALT_LEN, stdin) == NULL))
|
if (unlikely(fgets(s, PASS_LEN - SALT_LEN, stdin) == NULL))
|
||||||
failure(control, "Failed to retrieve passphrase\n");
|
failure_return(("Failed to retrieve passphrase\n"), -1);
|
||||||
len = strlen(s);
|
len = strlen(s);
|
||||||
if (len > 0 && ('\r' == s[len - 1] || '\n' == s[len - 1]))
|
if (len > 0 && ('\r' == s[len - 1] || '\n' == s[len - 1]))
|
||||||
s[len - 1] = '\0';
|
s[len - 1] = '\0';
|
||||||
|
|
@ -518,11 +539,11 @@ static int get_pass(rzip_control *control, char *s)
|
||||||
s[len - 2] = '\0';
|
s[len - 2] = '\0';
|
||||||
len = strlen(s);
|
len = strlen(s);
|
||||||
if (unlikely(0 == len))
|
if (unlikely(0 == len))
|
||||||
failure(control, "Empty passphrase\n");
|
failure_return(("Empty passphrase\n"), -1);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_hash(rzip_control *control, int make_hash)
|
static bool get_hash(rzip_control *control, int make_hash)
|
||||||
{
|
{
|
||||||
char *passphrase, *testphrase;
|
char *passphrase, *testphrase;
|
||||||
struct termios termios_p;
|
struct termios termios_p;
|
||||||
|
|
@ -531,8 +552,12 @@ static void get_hash(rzip_control *control, int make_hash)
|
||||||
testphrase = calloc(PASS_LEN, 1);
|
testphrase = calloc(PASS_LEN, 1);
|
||||||
control->salt_pass = calloc(PASS_LEN, 1);
|
control->salt_pass = calloc(PASS_LEN, 1);
|
||||||
control->hash = calloc(HASH_LEN, 1);
|
control->hash = calloc(HASH_LEN, 1);
|
||||||
if (unlikely(!passphrase || !testphrase || !control->salt_pass || !control->hash))
|
if (unlikely(!passphrase || !testphrase || !control->salt_pass || !control->hash)) {
|
||||||
fatal(control, "Failed to calloc encrypt buffers in compress_file\n");
|
fatal("Failed to calloc encrypt buffers in compress_file\n");
|
||||||
|
free(testphrase);
|
||||||
|
free(passphrase);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
mlock(passphrase, PASS_LEN);
|
mlock(passphrase, PASS_LEN);
|
||||||
mlock(testphrase, PASS_LEN);
|
mlock(testphrase, PASS_LEN);
|
||||||
mlock(control->salt_pass, PASS_LEN);
|
mlock(control->salt_pass, PASS_LEN);
|
||||||
|
|
@ -540,7 +565,15 @@ static void get_hash(rzip_control *control, int make_hash)
|
||||||
|
|
||||||
if (control->pass_cb) {
|
if (control->pass_cb) {
|
||||||
control->pass_cb(control->pass_data, passphrase, PASS_LEN);
|
control->pass_cb(control->pass_data, passphrase, PASS_LEN);
|
||||||
if (!passphrase[0]) fatal(control, "Supplied password was null!");
|
if (!passphrase[0]) {
|
||||||
|
fatal("Supplied password was null!");
|
||||||
|
munlock(passphrase, PASS_LEN);
|
||||||
|
munlock(testphrase, PASS_LEN);
|
||||||
|
free(testphrase);
|
||||||
|
free(passphrase);
|
||||||
|
release_hashes(control);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Disable stdin echo to screen */
|
/* Disable stdin echo to screen */
|
||||||
tcgetattr(fileno(stdin), &termios_p);
|
tcgetattr(fileno(stdin), &termios_p);
|
||||||
|
|
@ -571,6 +604,7 @@ retry_pass:
|
||||||
munlock(testphrase, PASS_LEN);
|
munlock(testphrase, PASS_LEN);
|
||||||
free(testphrase);
|
free(testphrase);
|
||||||
free(passphrase);
|
free(passphrase);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void release_hashes(rzip_control *control)
|
static void release_hashes(rzip_control *control)
|
||||||
|
|
@ -586,7 +620,7 @@ static void release_hashes(rzip_control *control)
|
||||||
/*
|
/*
|
||||||
decompress one file from the command line
|
decompress one file from the command line
|
||||||
*/
|
*/
|
||||||
void decompress_file(rzip_control *control)
|
bool decompress_file(rzip_control *control)
|
||||||
{
|
{
|
||||||
char *tmp, *tmpoutfile, *infilecopy = NULL;
|
char *tmp, *tmpoutfile, *infilecopy = NULL;
|
||||||
int fd_in, fd_out = -1, fd_hist = -1;
|
int fd_in, fd_out = -1, fd_hist = -1;
|
||||||
|
|
@ -602,15 +636,11 @@ void decompress_file(rzip_control *control)
|
||||||
/* make sure infile has an extension. If not, add it
|
/* make sure infile has an extension. If not, add it
|
||||||
* because manipulations may be made to input filename, set local ptr
|
* because manipulations may be made to input filename, set local ptr
|
||||||
*/
|
*/
|
||||||
infilecopy = malloc(strlen(control->infile) + strlen(control->suffix) + 1);
|
infilecopy = alloca(strlen(control->infile) + strlen(control->suffix) + 1);
|
||||||
if (unlikely(infilecopy == NULL))
|
strcpy(infilecopy, control->infile);
|
||||||
fatal(control, "Failed to allocate memory for infile suffix\n");
|
strcat(infilecopy, control->suffix);
|
||||||
else {
|
|
||||||
strcpy(infilecopy, control->infile);
|
|
||||||
strcat(infilecopy, control->suffix);
|
|
||||||
}
|
|
||||||
} else
|
} else
|
||||||
infilecopy = strdup(control->infile);
|
infilecopy = strdupa(control->infile);
|
||||||
/* regardless, infilecopy has the input filename */
|
/* regardless, infilecopy has the input filename */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -624,9 +654,9 @@ void decompress_file(rzip_control *control)
|
||||||
* infilecopy, then remove suffix.
|
* infilecopy, then remove suffix.
|
||||||
*/
|
*/
|
||||||
if (control->outdir && (tmp = strrchr(infilecopy, '/')))
|
if (control->outdir && (tmp = strrchr(infilecopy, '/')))
|
||||||
tmpoutfile = strdup(tmp + 1);
|
tmpoutfile = strdupa(tmp + 1);
|
||||||
else
|
else
|
||||||
tmpoutfile = strdup(infilecopy);
|
tmpoutfile = strdupa(infilecopy);
|
||||||
|
|
||||||
/* remove suffix to make outfile name */
|
/* remove suffix to make outfile name */
|
||||||
if ((tmp = strrchr(tmpoutfile, '.')) && !strcmp(tmp, control->suffix))
|
if ((tmp = strrchr(tmpoutfile, '.')) && !strcmp(tmp, control->suffix))
|
||||||
|
|
@ -634,14 +664,13 @@ void decompress_file(rzip_control *control)
|
||||||
|
|
||||||
control->outfile = malloc((control->outdir == NULL? 0: strlen(control->outdir)) + strlen(tmpoutfile) + 1);
|
control->outfile = malloc((control->outdir == NULL? 0: strlen(control->outdir)) + strlen(tmpoutfile) + 1);
|
||||||
if (unlikely(!control->outfile))
|
if (unlikely(!control->outfile))
|
||||||
fatal(control, "Failed to allocate outfile name\n");
|
fatal_return(("Failed to allocate outfile name\n"), false);
|
||||||
|
|
||||||
if (control->outdir) { /* prepend control->outdir */
|
if (control->outdir) { /* prepend control->outdir */
|
||||||
strcpy(control->outfile, control->outdir);
|
strcpy(control->outfile, control->outdir);
|
||||||
strcat(control->outfile, tmpoutfile);
|
strcat(control->outfile, tmpoutfile);
|
||||||
} else
|
} else
|
||||||
strcpy(control->outfile, tmpoutfile);
|
strcpy(control->outfile, tmpoutfile);
|
||||||
free(tmpoutfile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!STDOUT)
|
if (!STDOUT)
|
||||||
|
|
@ -650,15 +679,16 @@ void decompress_file(rzip_control *control)
|
||||||
|
|
||||||
if (STDIN) {
|
if (STDIN) {
|
||||||
fd_in = open_tmpinfile(control);
|
fd_in = open_tmpinfile(control);
|
||||||
|
if (unlikely(fd_in == -1)) return false;
|
||||||
read_tmpinmagic(control);
|
read_tmpinmagic(control);
|
||||||
if (ENCRYPT)
|
if (ENCRYPT)
|
||||||
failure(control, "Cannot decompress encrypted file from STDIN\n");
|
failure_return(("Cannot decompress encrypted file from STDIN\n"), false);
|
||||||
expected_size = control->st_size;
|
expected_size = control->st_size;
|
||||||
open_tmpinbuf(control);
|
if (unlikely(!open_tmpinbuf(control))) return false;
|
||||||
} else {
|
} else {
|
||||||
fd_in = open(infilecopy, O_RDONLY);
|
fd_in = open(infilecopy, O_RDONLY);
|
||||||
if (unlikely(fd_in == -1)) {
|
if (unlikely(fd_in == -1)) {
|
||||||
fatal(control, "Failed to open %s\n", infilecopy);
|
fatal_return(("Failed to open %s\n", infilecopy), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
control->fd_in = fd_in;
|
control->fd_in = fd_in;
|
||||||
|
|
@ -667,50 +697,50 @@ void decompress_file(rzip_control *control)
|
||||||
fd_out = open(control->outfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
|
fd_out = open(control->outfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
|
||||||
if (FORCE_REPLACE && (-1 == fd_out) && (EEXIST == errno)) {
|
if (FORCE_REPLACE && (-1 == fd_out) && (EEXIST == errno)) {
|
||||||
if (unlikely(unlink(control->outfile)))
|
if (unlikely(unlink(control->outfile)))
|
||||||
fatal(control, "Failed to unlink an existing file: %s\n", control->outfile);
|
fatal_return(("Failed to unlink an existing file: %s\n", control->outfile), false);
|
||||||
fd_out = open(control->outfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
|
fd_out = open(control->outfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
|
||||||
}
|
}
|
||||||
if (unlikely(fd_out == -1)) {
|
if (unlikely(fd_out == -1)) {
|
||||||
/* We must ensure we don't delete a file that already
|
/* We must ensure we don't delete a file that already
|
||||||
* exists just because we tried to create a new one */
|
* exists just because we tried to create a new one */
|
||||||
control->flags |= FLAG_KEEP_BROKEN;
|
control->flags |= FLAG_KEEP_BROKEN;
|
||||||
fatal(control, "Failed to create %s\n", control->outfile);
|
fatal_return(("Failed to create %s\n", control->outfile), false);
|
||||||
}
|
}
|
||||||
fd_hist = open(control->outfile, O_RDONLY);
|
fd_hist = open(control->outfile, O_RDONLY);
|
||||||
if (unlikely(fd_hist == -1))
|
if (unlikely(fd_hist == -1))
|
||||||
fatal(control, "Failed to open history file %s\n", control->outfile);
|
fatal_return(("Failed to open history file %s\n", control->outfile), false);
|
||||||
|
|
||||||
/* Can't copy permissions from STDIN */
|
/* Can't copy permissions from STDIN */
|
||||||
if (!STDIN)
|
if (!STDIN)
|
||||||
preserve_perms(control, fd_in, fd_out);
|
if (unlikely(!preserve_perms(control, fd_in, fd_out))) return false;
|
||||||
} else {
|
} else {
|
||||||
fd_out = open_tmpoutfile(control);
|
fd_out = open_tmpoutfile(control);
|
||||||
if (unlikely(fd_out == -1))
|
if (unlikely(fd_out == -1))
|
||||||
fatal(control, "Failed to create %s\n", control->outfile);
|
fatal_return(("Failed to create %s\n", control->outfile), false);
|
||||||
fd_hist = open(control->outfile, O_RDONLY);
|
fd_hist = open(control->outfile, O_RDONLY);
|
||||||
if (unlikely(fd_hist == -1))
|
if (unlikely(fd_hist == -1))
|
||||||
fatal(control, "Failed to open history file %s\n", control->outfile);
|
fatal_return(("Failed to open history file %s\n", control->outfile), false);
|
||||||
/* Unlink temporary file as soon as possible */
|
/* Unlink temporary file as soon as possible */
|
||||||
if (unlikely(unlink(control->outfile)))
|
if (unlikely(unlink(control->outfile)))
|
||||||
fatal(control, "Failed to unlink tmpfile: %s\n", control->outfile);
|
fatal_return(("Failed to unlink tmpfile: %s\n", control->outfile), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
open_tmpoutbuf(control);
|
if (unlikely(!open_tmpoutbuf(control))) return false;
|
||||||
|
|
||||||
if (!STDIN)
|
if (!STDIN)
|
||||||
read_magic(control, fd_in, &expected_size);
|
if (unlikely(!read_magic(control, fd_in, &expected_size))) return false;
|
||||||
|
|
||||||
if (!STDOUT) {
|
if (!STDOUT) {
|
||||||
/* Check if there's enough free space on the device chosen to fit the
|
/* Check if there's enough free space on the device chosen to fit the
|
||||||
* decompressed file. */
|
* decompressed file. */
|
||||||
if (unlikely(fstatvfs(fd_out, &fbuf)))
|
if (unlikely(fstatvfs(fd_out, &fbuf)))
|
||||||
fatal(control, "Failed to fstatvfs in decompress_file\n");
|
fatal_return(("Failed to fstatvfs in decompress_file\n"), false);
|
||||||
free_space = (i64)fbuf.f_bsize * (i64)fbuf.f_bavail;
|
free_space = (i64)fbuf.f_bsize * (i64)fbuf.f_bavail;
|
||||||
if (free_space < expected_size) {
|
if (free_space < expected_size) {
|
||||||
if (FORCE_REPLACE)
|
if (FORCE_REPLACE)
|
||||||
print_err("Warning, inadequate free space detected, but attempting to decompress due to -f option being used.\n");
|
print_err("Warning, inadequate free space detected, but attempting to decompress due to -f option being used.\n");
|
||||||
else
|
else
|
||||||
failure(control, "Inadequate free space to decompress file, use -f to override.\n");
|
failure_return(("Inadequate free space to decompress file, use -f to override.\n"), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
control->fd_out = fd_out;
|
control->fd_out = fd_out;
|
||||||
|
|
@ -725,16 +755,16 @@ void decompress_file(rzip_control *control)
|
||||||
print_verbose("being used for integrity testing.\n");
|
print_verbose("being used for integrity testing.\n");
|
||||||
|
|
||||||
if (ENCRYPT)
|
if (ENCRYPT)
|
||||||
get_hash(control, 0);
|
if (unlikely(!get_hash(control, 0))) return false;
|
||||||
|
|
||||||
print_progress("Decompressing...\n");
|
print_progress("Decompressing...\n");
|
||||||
|
|
||||||
runzip_fd(control, fd_in, fd_out, fd_hist, expected_size);
|
if (unlikely(runzip_fd(control, fd_in, fd_out, fd_hist, expected_size) < 0)) return false;
|
||||||
|
|
||||||
if (STDOUT && !TMP_OUTBUF)
|
if (STDOUT && !TMP_OUTBUF)
|
||||||
dump_tmpoutfile(control, fd_out);
|
if (unlikely(!dump_tmpoutfile(control, fd_out))) return false;
|
||||||
|
|
||||||
/* if we get here, no fatal errors during decompression */
|
/* if we get here, no fatal_return(( errors during decompression */
|
||||||
print_progress("\r");
|
print_progress("\r");
|
||||||
if (!(STDOUT | TEST_ONLY))
|
if (!(STDOUT | TEST_ONLY))
|
||||||
print_output("Output filename is: %s: ", control->outfile);
|
print_output("Output filename is: %s: ", control->outfile);
|
||||||
|
|
@ -746,38 +776,38 @@ void decompress_file(rzip_control *control)
|
||||||
print_progress("[OK] \n");
|
print_progress("[OK] \n");
|
||||||
|
|
||||||
if (unlikely(close(fd_hist) || close(fd_out)))
|
if (unlikely(close(fd_hist) || close(fd_out)))
|
||||||
fatal(control, "Failed to close files\n");
|
fatal_return(("Failed to close files\n"), false);
|
||||||
|
|
||||||
close(fd_in);
|
close(fd_in);
|
||||||
|
|
||||||
if (!KEEP_FILES) {
|
if (!KEEP_FILES) {
|
||||||
if (unlikely(unlink(control->infile)))
|
if (unlikely(unlink(control->infile)))
|
||||||
fatal(control, "Failed to unlink %s\n", infilecopy);
|
fatal_return(("Failed to unlink %s\n", infilecopy), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ENCRYPT)
|
if (ENCRYPT)
|
||||||
release_hashes(control);
|
release_hashes(control);
|
||||||
|
|
||||||
free(control->outfile);
|
free(control->outfile);
|
||||||
free(infilecopy);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_header_info(rzip_control *control, int fd_in, uchar *ctype, i64 *c_len,
|
bool get_header_info(rzip_control *control, int fd_in, uchar *ctype, i64 *c_len,
|
||||||
i64 *u_len, i64 *last_head, int chunk_bytes)
|
i64 *u_len, i64 *last_head, int chunk_bytes)
|
||||||
{
|
{
|
||||||
if (unlikely(read(fd_in, ctype, 1) != 1))
|
if (unlikely(read(fd_in, ctype, 1) != 1))
|
||||||
fatal(control, "Failed to read in get_header_info\n");
|
fatal_return(("Failed to read in get_header_info\n"), false);
|
||||||
|
|
||||||
*c_len = *u_len = *last_head = 0;
|
*c_len = *u_len = *last_head = 0;
|
||||||
if (control->major_version == 0 && control->minor_version < 4) {
|
if (control->major_version == 0 && control->minor_version < 4) {
|
||||||
u32 c_len32, u_len32, last_head32;
|
u32 c_len32, u_len32, last_head32;
|
||||||
|
|
||||||
if (unlikely(read(fd_in, &c_len32, 4) != 4))
|
if (unlikely(read(fd_in, &c_len32, 4) != 4))
|
||||||
fatal(control, "Failed to read in get_header_info");
|
fatal_return(("Failed to read in get_header_info"), false);
|
||||||
if (unlikely(read(fd_in, &u_len32, 4) != 4))
|
if (unlikely(read(fd_in, &u_len32, 4) != 4))
|
||||||
fatal(control, "Failed to read in get_header_info");
|
fatal_return(("Failed to read in get_header_info"), false);
|
||||||
if (unlikely(read(fd_in, &last_head32, 4) != 4))
|
if (unlikely(read(fd_in, &last_head32, 4) != 4))
|
||||||
fatal(control, "Failed to read in get_header_info");
|
fatal_return(("Failed to read in get_header_info"), false);
|
||||||
c_len32 = le32toh(c_len32);
|
c_len32 = le32toh(c_len32);
|
||||||
u_len32 = le32toh(u_len32);
|
u_len32 = le32toh(u_len32);
|
||||||
last_head32 = le32toh(last_head32);
|
last_head32 = le32toh(last_head32);
|
||||||
|
|
@ -792,15 +822,16 @@ void get_header_info(rzip_control *control, int fd_in, uchar *ctype, i64 *c_len,
|
||||||
else
|
else
|
||||||
read_len = chunk_bytes;
|
read_len = chunk_bytes;
|
||||||
if (unlikely(read(fd_in, c_len, read_len) != read_len))
|
if (unlikely(read(fd_in, c_len, read_len) != read_len))
|
||||||
fatal(control, "Failed to read in get_header_info");
|
fatal_return(("Failed to read in get_header_info"), false);
|
||||||
if (unlikely(read(fd_in, u_len, read_len) != read_len))
|
if (unlikely(read(fd_in, u_len, read_len) != read_len))
|
||||||
fatal(control, "Failed to read in get_header_info");
|
fatal_return(("Failed to read in get_header_info"), false);
|
||||||
if (unlikely(read(fd_in, last_head, read_len) != read_len))
|
if (unlikely(read(fd_in, last_head, read_len) != read_len))
|
||||||
fatal(control, "Failed to read_i64 in get_header_info");
|
fatal_return(("Failed to read_i64 in get_header_info"), false);
|
||||||
*c_len = le64toh(*c_len);
|
*c_len = le64toh(*c_len);
|
||||||
*u_len = le64toh(*u_len);
|
*u_len = le64toh(*u_len);
|
||||||
*last_head = le64toh(*last_head);
|
*last_head = le64toh(*last_head);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double percentage(i64 num, i64 den)
|
static double percentage(i64 num, i64 den)
|
||||||
|
|
@ -817,7 +848,7 @@ static double percentage(i64 num, i64 den)
|
||||||
return d_num / d_den;
|
return d_num / d_den;
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_fileinfo(rzip_control *control)
|
bool get_fileinfo(rzip_control *control)
|
||||||
{
|
{
|
||||||
i64 u_len, c_len, last_head, utotal = 0, ctotal = 0, ofs = 25, stream_head[2];
|
i64 u_len, c_len, last_head, utotal = 0, ctotal = 0, ofs = 25, stream_head[2];
|
||||||
i64 expected_size, infile_size, chunk_size = 0, chunk_total = 0;
|
i64 expected_size, infile_size, chunk_size = 0, chunk_total = 0;
|
||||||
|
|
@ -835,15 +866,11 @@ void get_fileinfo(rzip_control *control)
|
||||||
stat(control->infile, &fdin_stat);
|
stat(control->infile, &fdin_stat);
|
||||||
if (!S_ISREG(fdin_stat.st_mode) && (tmp = strrchr(control->infile, '.')) &&
|
if (!S_ISREG(fdin_stat.st_mode) && (tmp = strrchr(control->infile, '.')) &&
|
||||||
strcmp(tmp,control->suffix)) {
|
strcmp(tmp,control->suffix)) {
|
||||||
infilecopy = malloc(strlen(control->infile) + strlen(control->suffix) + 1);
|
infilecopy = alloca(strlen(control->infile) + strlen(control->suffix) + 1);
|
||||||
if (unlikely(infilecopy == NULL))
|
strcpy(infilecopy, control->infile);
|
||||||
fatal(control, "Failed to allocate memory for infile suffix\n");
|
strcat(infilecopy, control->suffix);
|
||||||
else {
|
|
||||||
strcpy(infilecopy, control->infile);
|
|
||||||
strcat(infilecopy, control->suffix);
|
|
||||||
}
|
|
||||||
} else
|
} else
|
||||||
infilecopy = strdup(control->infile);
|
infilecopy = strdupa(control->infile);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (STDIN)
|
if (STDIN)
|
||||||
|
|
@ -851,30 +878,31 @@ void get_fileinfo(rzip_control *control)
|
||||||
else {
|
else {
|
||||||
fd_in = open(infilecopy, O_RDONLY);
|
fd_in = open(infilecopy, O_RDONLY);
|
||||||
if (unlikely(fd_in == -1))
|
if (unlikely(fd_in == -1))
|
||||||
fatal(control, "Failed to open %s\n", infilecopy);
|
fatal_return(("Failed to open %s\n", infilecopy), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get file size */
|
/* Get file size */
|
||||||
if (unlikely(fstat(fd_in, &st)))
|
if (unlikely(fstat(fd_in, &st)))
|
||||||
fatal(control, "bad magic file descriptor!?\n");
|
fatal_goto(("bad magic file descriptor!?\n"), error);
|
||||||
infile_size = st.st_size;
|
infile_size = st.st_size;
|
||||||
|
|
||||||
/* Get decompressed size */
|
/* Get decompressed size */
|
||||||
read_magic(control, fd_in, &expected_size);
|
if (unlikely(!read_magic(control, fd_in, &expected_size))) goto error;
|
||||||
|
|
||||||
if (ENCRYPT) {
|
if (ENCRYPT) {
|
||||||
print_output("Encrypted lrzip archive. No further information available\n");
|
print_output("Encrypted lrzip archive. No further information available\n");
|
||||||
|
if (!STDIN) close(fd_in);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (control->major_version == 0 && control->minor_version > 4) {
|
if (control->major_version == 0 && control->minor_version > 4) {
|
||||||
if (unlikely(read(fd_in, &chunk_byte, 1) != 1))
|
if (unlikely(read(fd_in, &chunk_byte, 1) != 1))
|
||||||
fatal(control, "Failed to read chunk_byte in get_fileinfo\n");
|
fatal_goto(("Failed to read chunk_byte in get_fileinfo\n"), error);
|
||||||
if (control->major_version == 0 && control->minor_version > 5) {
|
if (control->major_version == 0 && control->minor_version > 5) {
|
||||||
if (unlikely(read(fd_in, &control->eof, 1) != 1))
|
if (unlikely(read(fd_in, &control->eof, 1) != 1))
|
||||||
fatal(control, "Failed to read eof in get_fileinfo\n");
|
fatal_goto(("Failed to read eof in get_fileinfo\n"), error);
|
||||||
if (unlikely(read(fd_in, &chunk_size, chunk_byte) != chunk_byte))
|
if (unlikely(read(fd_in, &chunk_size, chunk_byte) != chunk_byte))
|
||||||
fatal(control, "Failed to read chunk_size in get_fileinfo\n");
|
fatal_goto(("Failed to read chunk_size in get_fileinfo\n"), error);
|
||||||
chunk_size = le64toh(chunk_size);
|
chunk_size = le64toh(chunk_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -911,8 +939,8 @@ next_chunk:
|
||||||
int block = 1;
|
int block = 1;
|
||||||
|
|
||||||
if (unlikely(lseek(fd_in, stream_head[stream] + ofs, SEEK_SET)) == -1)
|
if (unlikely(lseek(fd_in, stream_head[stream] + ofs, SEEK_SET)) == -1)
|
||||||
fatal(control, "Failed to seek to header data in get_fileinfo\n");
|
fatal_goto(("Failed to seek to header data in get_fileinfo\n"), error);
|
||||||
get_header_info(control, fd_in, &ctype, &c_len, &u_len, &last_head, chunk_byte);
|
if (unlikely(!get_header_info(control, fd_in, &ctype, &c_len, &u_len, &last_head, chunk_byte))) return false;
|
||||||
|
|
||||||
print_verbose("Stream: %d\n", stream);
|
print_verbose("Stream: %d\n", stream);
|
||||||
print_maxverbose("Offset: %lld\n", ofs);
|
print_maxverbose("Offset: %lld\n", ofs);
|
||||||
|
|
@ -921,13 +949,13 @@ next_chunk:
|
||||||
i64 head_off;
|
i64 head_off;
|
||||||
|
|
||||||
if (unlikely(last_head + ofs > infile_size))
|
if (unlikely(last_head + ofs > infile_size))
|
||||||
failure(control, "Offset greater than archive size, likely corrupted/truncated archive.\n");
|
failure_goto(("Offset greater than archive size, likely corrupted/truncated archive.\n"), error);
|
||||||
if (unlikely(head_off = lseek(fd_in, last_head + ofs, SEEK_SET)) == -1)
|
if (unlikely(head_off = lseek(fd_in, last_head + ofs, SEEK_SET)) == -1)
|
||||||
fatal(control, "Failed to seek to header data in get_fileinfo\n");
|
fatal_goto(("Failed to seek to header data in get_fileinfo\n"), error);
|
||||||
get_header_info(control, fd_in, &ctype, &c_len, &u_len,
|
if (unlikely(!get_header_info(control, fd_in, &ctype, &c_len, &u_len,
|
||||||
&last_head, chunk_byte);
|
&last_head, chunk_byte))) return false;
|
||||||
if (unlikely(last_head < 0 || c_len < 0 || u_len < 0))
|
if (unlikely(last_head < 0 || c_len < 0 || u_len < 0))
|
||||||
failure(control, "Entry negative, likely corrupted archive.\n");
|
failure_goto(("Entry negative, likely corrupted archive.\n"), error);
|
||||||
print_verbose("%d\t", block);
|
print_verbose("%d\t", block);
|
||||||
if (ctype == CTYPE_NONE)
|
if (ctype == CTYPE_NONE)
|
||||||
print_verbose("none");
|
print_verbose("none");
|
||||||
|
|
@ -954,20 +982,20 @@ next_chunk:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely((ofs = lseek(fd_in, c_len, SEEK_CUR)) == -1))
|
if (unlikely((ofs = lseek(fd_in, c_len, SEEK_CUR)) == -1))
|
||||||
fatal(control, "Failed to lseek c_len in get_fileinfo\n");
|
fatal_goto(("Failed to lseek c_len in get_fileinfo\n"), error);
|
||||||
|
|
||||||
if (ofs >= infile_size - (HAS_MD5 ? MD5_DIGEST_SIZE : 0))
|
if (ofs >= infile_size - (HAS_MD5 ? MD5_DIGEST_SIZE : 0))
|
||||||
goto done;
|
goto done;
|
||||||
/* Chunk byte entry */
|
/* Chunk byte entry */
|
||||||
if (control->major_version == 0 && control->minor_version > 4) {
|
if (control->major_version == 0 && control->minor_version > 4) {
|
||||||
if (unlikely(read(fd_in, &chunk_byte, 1) != 1))
|
if (unlikely(read(fd_in, &chunk_byte, 1) != 1))
|
||||||
fatal(control, "Failed to read chunk_byte in get_fileinfo\n");
|
fatal_goto(("Failed to read chunk_byte in get_fileinfo\n"), error);
|
||||||
ofs++;
|
ofs++;
|
||||||
if (control->major_version == 0 && control->minor_version > 5) {
|
if (control->major_version == 0 && control->minor_version > 5) {
|
||||||
if (unlikely(read(fd_in, &control->eof, 1) != 1))
|
if (unlikely(read(fd_in, &control->eof, 1) != 1))
|
||||||
fatal(control, "Failed to read eof in get_fileinfo\n");
|
fatal_goto(("Failed to read eof in get_fileinfo\n"), error);
|
||||||
if (unlikely(read(fd_in, &chunk_size, chunk_byte) != chunk_byte))
|
if (unlikely(read(fd_in, &chunk_size, chunk_byte) != chunk_byte))
|
||||||
fatal(control, "Failed to read chunk_size in get_fileinfo\n");
|
fatal_goto(("Failed to read chunk_size in get_fileinfo\n"), error);
|
||||||
chunk_size = le64toh(chunk_size);
|
chunk_size = le64toh(chunk_size);
|
||||||
ofs += 1 + chunk_byte;
|
ofs += 1 + chunk_byte;
|
||||||
header_length = 1 + (chunk_byte * 3);
|
header_length = 1 + (chunk_byte * 3);
|
||||||
|
|
@ -976,7 +1004,7 @@ next_chunk:
|
||||||
goto next_chunk;
|
goto next_chunk;
|
||||||
done:
|
done:
|
||||||
if (unlikely(ofs > infile_size))
|
if (unlikely(ofs > infile_size))
|
||||||
failure(control, "Offset greater than archive size, likely corrupted/truncated archive.\n");
|
failure_goto(("Offset greater than archive size, likely corrupted/truncated archive.\n"), error);
|
||||||
if (chunk_total > expected_size)
|
if (chunk_total > expected_size)
|
||||||
expected_size = chunk_total;
|
expected_size = chunk_total;
|
||||||
print_verbose("Rzip compression: %.1f%% %lld / %lld\n",
|
print_verbose("Rzip compression: %.1f%% %lld / %lld\n",
|
||||||
|
|
@ -1018,9 +1046,9 @@ done:
|
||||||
|
|
||||||
print_output("MD5 used for integrity testing\n");
|
print_output("MD5 used for integrity testing\n");
|
||||||
if (unlikely(lseek(fd_in, -MD5_DIGEST_SIZE, SEEK_END)) == -1)
|
if (unlikely(lseek(fd_in, -MD5_DIGEST_SIZE, SEEK_END)) == -1)
|
||||||
fatal(control, "Failed to seek to md5 data in runzip_fd\n");
|
fatal_goto(("Failed to seek to md5 data in runzip_fd\n"), error);
|
||||||
if (unlikely(read(fd_in, md5_stored, MD5_DIGEST_SIZE) != MD5_DIGEST_SIZE))
|
if (unlikely(read(fd_in, md5_stored, MD5_DIGEST_SIZE) != MD5_DIGEST_SIZE))
|
||||||
fatal(control, "Failed to read md5 data in runzip_fd\n");
|
fatal_goto(("Failed to read md5 data in runzip_fd\n"), error);
|
||||||
print_output("MD5: ");
|
print_output("MD5: ");
|
||||||
for (i = 0; i < MD5_DIGEST_SIZE; i++)
|
for (i = 0; i < MD5_DIGEST_SIZE; i++)
|
||||||
print_output("%02x", md5_stored[i] & 0xFF);
|
print_output("%02x", md5_stored[i] & 0xFF);
|
||||||
|
|
@ -1028,40 +1056,43 @@ done:
|
||||||
} else
|
} else
|
||||||
print_output("CRC32 used for integrity testing\n");
|
print_output("CRC32 used for integrity testing\n");
|
||||||
if (unlikely(close(fd_in)))
|
if (unlikely(close(fd_in)))
|
||||||
fatal(control, "Failed to close fd_in in get_fileinfo\n");
|
fatal_return(("Failed to close fd_in in get_fileinfo\n"), false);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
free(control->outfile);
|
free(control->outfile);
|
||||||
free(infilecopy);
|
return true;
|
||||||
|
error:
|
||||||
|
if (!STDIN) close(fd_in);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
compress one file from the command line
|
compress one file from the command line
|
||||||
*/
|
*/
|
||||||
void compress_file(rzip_control *control)
|
bool compress_file(rzip_control *control)
|
||||||
{
|
{
|
||||||
const char *tmp, *tmpinfile; /* we're just using this as a proxy for control->infile.
|
const char *tmp, *tmpinfile; /* we're just using this as a proxy for control->infile.
|
||||||
* Spares a compiler warning
|
* Spares a compiler warning
|
||||||
*/
|
*/
|
||||||
int fd_in, fd_out = -1;
|
int fd_in = -1, fd_out = -1;
|
||||||
char header[MAGIC_LEN];
|
char header[MAGIC_LEN];
|
||||||
|
|
||||||
if (MD5_RELIABLE)
|
if (MD5_RELIABLE)
|
||||||
control->flags |= FLAG_MD5;
|
control->flags |= FLAG_MD5;
|
||||||
if (ENCRYPT)
|
if (ENCRYPT)
|
||||||
get_hash(control, 1);
|
if (unlikely(!get_hash(control, 1))) return false;
|
||||||
memset(header, 0, sizeof(header));
|
memset(header, 0, sizeof(header));
|
||||||
|
|
||||||
if (!STDIN) {
|
if (!STDIN) {
|
||||||
/* is extension at end of infile? */
|
/* is extension at end of infile? */
|
||||||
if ((tmp = strrchr(control->infile, '.')) && !strcmp(tmp, control->suffix)) {
|
if ((tmp = strrchr(control->infile, '.')) && !strcmp(tmp, control->suffix)) {
|
||||||
print_err("%s: already has %s suffix. Skipping...\n", control->infile, control->suffix);
|
print_err("%s: already has %s suffix. Skipping...\n", control->infile, control->suffix);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd_in = open(control->infile, O_RDONLY);
|
fd_in = open(control->infile, O_RDONLY);
|
||||||
if (unlikely(fd_in == -1))
|
if (unlikely(fd_in == -1))
|
||||||
fatal(control, "Failed to open %s\n", control->infile);
|
fatal_return(("Failed to open %s\n", control->infile), false);
|
||||||
} else
|
} else
|
||||||
fd_in = 0;
|
fd_in = 0;
|
||||||
|
|
||||||
|
|
@ -1073,7 +1104,7 @@ void compress_file(rzip_control *control)
|
||||||
else if ((tmp=strrchr(control->outname, '.')) && strcmp(tmp, control->suffix)) {
|
else if ((tmp=strrchr(control->outname, '.')) && strcmp(tmp, control->suffix)) {
|
||||||
control->outfile = malloc(strlen(control->outname) + strlen(control->suffix) + 1);
|
control->outfile = malloc(strlen(control->outname) + strlen(control->suffix) + 1);
|
||||||
if (unlikely(!control->outfile))
|
if (unlikely(!control->outfile))
|
||||||
fatal(control, "Failed to allocate outfile name\n");
|
fatal_goto(("Failed to allocate outfile name\n"), error);
|
||||||
strcpy(control->outfile, control->outname);
|
strcpy(control->outfile, control->outname);
|
||||||
strcat(control->outfile, control->suffix);
|
strcat(control->outfile, control->suffix);
|
||||||
print_output("Suffix added to %s.\nFull pathname is: %s\n", control->outname, control->outfile);
|
print_output("Suffix added to %s.\nFull pathname is: %s\n", control->outname, control->outfile);
|
||||||
|
|
@ -1091,7 +1122,7 @@ void compress_file(rzip_control *control)
|
||||||
|
|
||||||
control->outfile = malloc((control->outdir == NULL? 0: strlen(control->outdir)) + strlen(tmpinfile) + strlen(control->suffix) + 1);
|
control->outfile = malloc((control->outdir == NULL? 0: strlen(control->outdir)) + strlen(tmpinfile) + strlen(control->suffix) + 1);
|
||||||
if (unlikely(!control->outfile))
|
if (unlikely(!control->outfile))
|
||||||
fatal(control, "Failed to allocate outfile name\n");
|
fatal_goto(("Failed to allocate outfile name\n"), error);
|
||||||
|
|
||||||
if (control->outdir) { /* prepend control->outdir */
|
if (control->outdir) { /* prepend control->outdir */
|
||||||
strcpy(control->outfile, control->outdir);
|
strcpy(control->outfile, control->outdir);
|
||||||
|
|
@ -1105,50 +1136,58 @@ void compress_file(rzip_control *control)
|
||||||
fd_out = open(control->outfile, O_RDWR | O_CREAT | O_EXCL, 0666);
|
fd_out = open(control->outfile, O_RDWR | O_CREAT | O_EXCL, 0666);
|
||||||
if (FORCE_REPLACE && (-1 == fd_out) && (EEXIST == errno)) {
|
if (FORCE_REPLACE && (-1 == fd_out) && (EEXIST == errno)) {
|
||||||
if (unlikely(unlink(control->outfile)))
|
if (unlikely(unlink(control->outfile)))
|
||||||
fatal(control, "Failed to unlink an existing file: %s\n", control->outfile);
|
fatal_goto(("Failed to unlink an existing file: %s\n", control->outfile), error);
|
||||||
fd_out = open(control->outfile, O_RDWR | O_CREAT | O_EXCL, 0666);
|
fd_out = open(control->outfile, O_RDWR | O_CREAT | O_EXCL, 0666);
|
||||||
}
|
}
|
||||||
if (unlikely(fd_out == -1)) {
|
if (unlikely(fd_out == -1)) {
|
||||||
/* We must ensure we don't delete a file that already
|
/* We must ensure we don't delete a file that already
|
||||||
* exists just because we tried to create a new one */
|
* exists just because we tried to create a new one */
|
||||||
control->flags |= FLAG_KEEP_BROKEN;
|
control->flags |= FLAG_KEEP_BROKEN;
|
||||||
fatal(control, "Failed to create %s\n", control->outfile);
|
fatal_goto(("Failed to create %s\n", control->outfile), error);
|
||||||
}
|
}
|
||||||
control->fd_out = fd_out;
|
control->fd_out = fd_out;
|
||||||
if (!STDIN)
|
if (!STDIN)
|
||||||
preserve_perms(control, fd_in, fd_out);
|
if (unlikely(!preserve_perms(control, fd_in, fd_out))) goto error;
|
||||||
} else
|
} else
|
||||||
open_tmpoutbuf(control);
|
if (unlikely(!open_tmpoutbuf(control))) goto error;
|
||||||
|
|
||||||
/* Write zeroes to header at beginning of file */
|
/* Write zeroes to header at beginning of file */
|
||||||
if (unlikely(!STDOUT && write(fd_out, header, sizeof(header)) != sizeof(header)))
|
if (unlikely(!STDOUT && write(fd_out, header, sizeof(header)) != sizeof(header)))
|
||||||
fatal(control, "Cannot write file header\n");
|
fatal_goto(("Cannot write file header\n"), error);
|
||||||
|
|
||||||
rzip_fd(control, fd_in, fd_out);
|
rzip_fd(control, fd_in, fd_out);
|
||||||
|
|
||||||
/* Wwrite magic at end b/c lzma does not tell us properties until it is done */
|
/* Wwrite magic at end b/c lzma does not tell us properties until it is done */
|
||||||
if (!STDOUT)
|
if (!STDOUT)
|
||||||
write_magic(control);
|
if (unlikely(!write_magic(control))) goto error;
|
||||||
|
|
||||||
if (ENCRYPT)
|
if (ENCRYPT)
|
||||||
release_hashes(control);
|
release_hashes(control);
|
||||||
|
|
||||||
if (unlikely(close(fd_in)))
|
if (unlikely(close(fd_in))) {
|
||||||
fatal(control, "Failed to close fd_in\n");
|
fatal("Failed to close fd_in\n");
|
||||||
|
fd_in = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
if (unlikely(!STDOUT && close(fd_out)))
|
if (unlikely(!STDOUT && close(fd_out)))
|
||||||
fatal(control, "Failed to close fd_out\n");
|
fatal_return(("Failed to close fd_out\n"), false);
|
||||||
if (TMP_OUTBUF)
|
if (TMP_OUTBUF)
|
||||||
close_tmpoutbuf(control);
|
close_tmpoutbuf(control);
|
||||||
|
|
||||||
if (!KEEP_FILES) {
|
if (!KEEP_FILES) {
|
||||||
if (unlikely(unlink(control->infile)))
|
if (unlikely(unlink(control->infile)))
|
||||||
fatal(control, "Failed to unlink %s\n", control->infile);
|
fatal_return(("Failed to unlink %s\n", control->infile), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(control->outfile);
|
free(control->outfile);
|
||||||
|
return true;
|
||||||
|
error:
|
||||||
|
if (STDIN && (fd_in > 0)) close(fd_in);
|
||||||
|
if ((!STDOUT) && (fd_out > 0)) close(fd_out);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialize_control(rzip_control *control)
|
bool initialize_control(rzip_control *control)
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
char *eptr; /* for environment */
|
char *eptr; /* for environment */
|
||||||
|
|
@ -1160,6 +1199,7 @@ void initialize_control(rzip_control *control)
|
||||||
control->suffix = strdup(".lrz");
|
control->suffix = strdup(".lrz");
|
||||||
control->compression_level = 7;
|
control->compression_level = 7;
|
||||||
control->ramsize = get_ram(control);
|
control->ramsize = get_ram(control);
|
||||||
|
if (unlikely(control->ramsize == -1)) return false;
|
||||||
/* for testing single CPU */
|
/* for testing single CPU */
|
||||||
control->threads = PROCESSORS; /* get CPUs for LZMA */
|
control->threads = PROCESSORS; /* get CPUs for LZMA */
|
||||||
control->page_size = PAGE_SIZE;
|
control->page_size = PAGE_SIZE;
|
||||||
|
|
@ -1169,10 +1209,10 @@ void initialize_control(rzip_control *control)
|
||||||
* The next 2 bytes encode how many times to hash the password.
|
* The next 2 bytes encode how many times to hash the password.
|
||||||
* The last 9 bytes are random data, making 16 bytes of salt */
|
* The last 9 bytes are random data, making 16 bytes of salt */
|
||||||
if (unlikely(gettimeofday(&tv, NULL)))
|
if (unlikely(gettimeofday(&tv, NULL)))
|
||||||
fatal(control, "Failed to gettimeofday in main\n");
|
fatal_return(("Failed to gettimeofday in main\n"), false);
|
||||||
control->secs = tv.tv_sec;
|
control->secs = tv.tv_sec;
|
||||||
control->encloops = nloops(control->secs, control->salt, control->salt + 1);
|
control->encloops = nloops(control->secs, control->salt, control->salt + 1);
|
||||||
get_rand(control, control->salt + 2, 6);
|
if (unlikely(!get_rand(control, control->salt + 2, 6))) return false;
|
||||||
|
|
||||||
/* Get Temp Dir */
|
/* Get Temp Dir */
|
||||||
eptr = getenv("TMP");
|
eptr = getenv("TMP");
|
||||||
|
|
@ -1180,10 +1220,11 @@ void initialize_control(rzip_control *control)
|
||||||
size_t len = strlen(eptr);
|
size_t len = strlen(eptr);
|
||||||
control->tmpdir = malloc(len+2);
|
control->tmpdir = malloc(len+2);
|
||||||
if (control->tmpdir == NULL)
|
if (control->tmpdir == NULL)
|
||||||
fatal(control, "Failed to allocate for tmpdir\n");
|
fatal_return(("Failed to allocate for tmpdir\n"), false);
|
||||||
strcpy(control->tmpdir, eptr);
|
strcpy(control->tmpdir, eptr);
|
||||||
if (eptr[len - 2] != '/')
|
if (eptr[len - 2] != '/')
|
||||||
eptr[len - 2] = '/'; /* need a trailing slash */
|
eptr[len - 2] = '/'; /* need a trailing slash */
|
||||||
eptr[len - 1] = 0;
|
eptr[len - 1] = 0;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
26
lrzip.h
26
lrzip.h
|
|
@ -23,23 +23,23 @@
|
||||||
|
|
||||||
inline i64 get_ram(rzip_control *control);
|
inline i64 get_ram(rzip_control *control);
|
||||||
i64 nloops(i64 seconds, uchar *b1, uchar *b2);
|
i64 nloops(i64 seconds, uchar *b1, uchar *b2);
|
||||||
void write_magic(rzip_control *control);
|
bool write_magic(rzip_control *control);
|
||||||
void read_magic(rzip_control *control, int fd_in, i64 *expected_size);
|
bool read_magic(rzip_control *control, int fd_in, i64 *expected_size);
|
||||||
void preserve_perms(rzip_control *control, int fd_in, int fd_out);
|
void preserve_perms(rzip_control *control, int fd_in, int fd_out);
|
||||||
int open_tmpoutfile(rzip_control *control);
|
int open_tmpoutfile(rzip_control *control);
|
||||||
void dump_tmpoutfile(rzip_control *control, int fd_out);
|
bool dump_tmpoutfile(rzip_control *control, int fd_out);
|
||||||
int open_tmpinfile(rzip_control *control);
|
int open_tmpinfile(rzip_control *control);
|
||||||
void read_tmpinfile(rzip_control *control, int fd_in);
|
bool read_tmpinfile(rzip_control *control, int fd_in);
|
||||||
void decompress_file(rzip_control *control);
|
bool decompress_file(rzip_control *control);
|
||||||
void get_header_info(rzip_control *control, int fd_in, uchar *ctype, i64 *c_len, i64 *u_len, i64 *last_head);
|
bool get_header_info(rzip_control *control, int fd_in, uchar *ctype, i64 *c_len, i64 *u_len, i64 *last_head);
|
||||||
void get_fileinfo(rzip_control *control);
|
bool get_fileinfo(rzip_control *control);
|
||||||
void compress_file(rzip_control *control);
|
bool compress_file(rzip_control *control);
|
||||||
void write_fdout(rzip_control *control, void *buf, i64 len);
|
bool write_fdout(rzip_control *control, void *buf, i64 len);
|
||||||
void write_fdin(rzip_control *control);
|
bool write_fdin(rzip_control *control);
|
||||||
void flush_tmpoutbuf(rzip_control *control);
|
bool flush_tmpoutbuf(rzip_control *control);
|
||||||
void close_tmpoutbuf(rzip_control *control);
|
void close_tmpoutbuf(rzip_control *control);
|
||||||
void clear_tmpinbuf(rzip_control *control);
|
void clear_tmpinbuf(rzip_control *control);
|
||||||
inline void clear_tmpinfile(rzip_control *control);
|
inline bool clear_tmpinfile(rzip_control *control);
|
||||||
void close_tmpinbuf(rzip_control *control);
|
void close_tmpinbuf(rzip_control *control);
|
||||||
void initialize_control(rzip_control *control);
|
bool initialize_control(rzip_control *control);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#ifdef HAVE_STRING_H
|
#ifdef HAVE_STRING_H
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -34,6 +35,34 @@
|
||||||
# include <malloc.h>
|
# include <malloc.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_ALLOCA_H
|
||||||
|
# include <alloca.h>
|
||||||
|
#elif defined __GNUC__
|
||||||
|
# define alloca __builtin_alloca
|
||||||
|
#elif defined _AIX
|
||||||
|
# define alloca __alloca
|
||||||
|
#elif defined _MSC_VER
|
||||||
|
# include <malloc.h>
|
||||||
|
# define alloca _alloca
|
||||||
|
#else
|
||||||
|
# include <stddef.h>
|
||||||
|
# ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
# endif
|
||||||
|
void *alloca (size_t);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define free(X) do { free((X)); (X) = NULL; } while (0)
|
||||||
|
|
||||||
|
#ifndef strdupa
|
||||||
|
# define strdupa(str) strcpy(alloca(strlen(str) + 1), str)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef strndupa
|
||||||
|
# define strndupa(str, len) strncpy(alloca(len + 1), str, len)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef uchar
|
#ifndef uchar
|
||||||
#define uchar unsigned char
|
#define uchar unsigned char
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -326,6 +355,9 @@ struct rzip_control {
|
||||||
const char *util_outfile;
|
const char *util_outfile;
|
||||||
char delete_outfile;
|
char delete_outfile;
|
||||||
FILE *outputfile;
|
FILE *outputfile;
|
||||||
|
char library_mode : 1;
|
||||||
|
void (*log_cb)(void *, unsigned int, const char *, const char *, va_list);
|
||||||
|
void *log_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stream {
|
struct stream {
|
||||||
|
|
|
||||||
42
main.c
42
main.c
|
|
@ -221,7 +221,7 @@ int main(int argc, char *argv[])
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'b':
|
case 'b':
|
||||||
if (control->flags & FLAG_NOT_LZMA)
|
if (control->flags & FLAG_NOT_LZMA)
|
||||||
failure(control, "Can only use one of -l, -b, -g, -z or -n\n");
|
failure("Can only use one of -l, -b, -g, -z or -n\n");
|
||||||
control->flags |= FLAG_BZIP2_COMPRESS;
|
control->flags |= FLAG_BZIP2_COMPRESS;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
|
|
@ -242,7 +242,7 @@ int main(int argc, char *argv[])
|
||||||
break;
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
if (control->flags & FLAG_NOT_LZMA)
|
if (control->flags & FLAG_NOT_LZMA)
|
||||||
failure(control, "Can only use one of -l, -b, -g, -z or -n\n");
|
failure("Can only use one of -l, -b, -g, -z or -n\n");
|
||||||
control->flags |= FLAG_ZLIB_COMPRESS;
|
control->flags |= FLAG_ZLIB_COMPRESS;
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
|
|
@ -260,40 +260,40 @@ int main(int argc, char *argv[])
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
if (control->flags & FLAG_NOT_LZMA)
|
if (control->flags & FLAG_NOT_LZMA)
|
||||||
failure(control, "Can only use one of -l, -b, -g, -z or -n\n");
|
failure("Can only use one of -l, -b, -g, -z or -n\n");
|
||||||
control->flags |= FLAG_LZO_COMPRESS;
|
control->flags |= FLAG_LZO_COMPRESS;
|
||||||
break;
|
break;
|
||||||
case 'L':
|
case 'L':
|
||||||
control->compression_level = atoi(optarg);
|
control->compression_level = atoi(optarg);
|
||||||
if (control->compression_level < 1 || control->compression_level > 9)
|
if (control->compression_level < 1 || control->compression_level > 9)
|
||||||
failure(control, "Invalid compression level (must be 1-9)\n");
|
failure("Invalid compression level (must be 1-9)\n");
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
if (control->flags & FLAG_NOT_LZMA)
|
if (control->flags & FLAG_NOT_LZMA)
|
||||||
failure(control, "Can only use one of -l, -b, -g, -z or -n\n");
|
failure("Can only use one of -l, -b, -g, -z or -n\n");
|
||||||
control->flags |= FLAG_NO_COMPRESS;
|
control->flags |= FLAG_NO_COMPRESS;
|
||||||
break;
|
break;
|
||||||
case 'N':
|
case 'N':
|
||||||
control->nice_val = atoi(optarg);
|
control->nice_val = atoi(optarg);
|
||||||
if (control->nice_val < -20 || control->nice_val > 19)
|
if (control->nice_val < -20 || control->nice_val > 19)
|
||||||
failure(control, "Invalid nice value (must be -20..19)\n");
|
failure("Invalid nice value (must be -20..19)\n");
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
if (control->outdir)
|
if (control->outdir)
|
||||||
failure(control, "Cannot have -o and -O together\n");
|
failure("Cannot have -o and -O together\n");
|
||||||
if (unlikely(STDOUT))
|
if (unlikely(STDOUT))
|
||||||
failure(control, "Cannot specify an output filename when outputting to stdout\n");
|
failure("Cannot specify an output filename when outputting to stdout\n");
|
||||||
control->outname = optarg;
|
control->outname = optarg;
|
||||||
control->suffix = "";
|
control->suffix = "";
|
||||||
break;
|
break;
|
||||||
case 'O':
|
case 'O':
|
||||||
if (control->outname) /* can't mix -o and -O */
|
if (control->outname) /* can't mix -o and -O */
|
||||||
failure(control, "Cannot have options -o and -O together\n");
|
failure("Cannot have options -o and -O together\n");
|
||||||
if (unlikely(STDOUT))
|
if (unlikely(STDOUT))
|
||||||
failure(control, "Cannot specify an output directory when outputting to stdout\n");
|
failure("Cannot specify an output directory when outputting to stdout\n");
|
||||||
control->outdir = malloc(strlen(optarg) + 2);
|
control->outdir = malloc(strlen(optarg) + 2);
|
||||||
if (control->outdir == NULL)
|
if (control->outdir == NULL)
|
||||||
fatal(control, "Failed to allocate for outdir\n");
|
fatal("Failed to allocate for outdir\n");
|
||||||
strcpy(control->outdir,optarg);
|
strcpy(control->outdir,optarg);
|
||||||
if (strcmp(optarg+strlen(optarg) - 1, "/")) /* need a trailing slash */
|
if (strcmp(optarg+strlen(optarg) - 1, "/")) /* need a trailing slash */
|
||||||
strcat(control->outdir, "/");
|
strcat(control->outdir, "/");
|
||||||
|
|
@ -301,23 +301,23 @@ int main(int argc, char *argv[])
|
||||||
case 'p':
|
case 'p':
|
||||||
control->threads = atoi(optarg);
|
control->threads = atoi(optarg);
|
||||||
if (control->threads < 1)
|
if (control->threads < 1)
|
||||||
failure(control, "Must have at least one thread\n");
|
failure("Must have at least one thread\n");
|
||||||
break;
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
control->flags &= ~FLAG_SHOW_PROGRESS;
|
control->flags &= ~FLAG_SHOW_PROGRESS;
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
if (control->outname)
|
if (control->outname)
|
||||||
failure(control, "Specified output filename already, can't specify an extension.\n");
|
failure("Specified output filename already, can't specify an extension.\n");
|
||||||
if (unlikely(STDOUT))
|
if (unlikely(STDOUT))
|
||||||
failure(control, "Cannot specify a filename suffix when outputting to stdout\n");
|
failure("Cannot specify a filename suffix when outputting to stdout\n");
|
||||||
control->suffix = optarg;
|
control->suffix = optarg;
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
if (control->outname)
|
if (control->outname)
|
||||||
failure(control, "Cannot specify an output file name when just testing.\n");
|
failure("Cannot specify an output file name when just testing.\n");
|
||||||
if (!KEEP_FILES)
|
if (!KEEP_FILES)
|
||||||
failure(control, "Doubt that you want to delete a file when just testing.\n");
|
failure("Doubt that you want to delete a file when just testing.\n");
|
||||||
control->flags |= FLAG_TEST_ONLY;
|
control->flags |= FLAG_TEST_ONLY;
|
||||||
break;
|
break;
|
||||||
case 'T':
|
case 'T':
|
||||||
|
|
@ -344,7 +344,7 @@ int main(int argc, char *argv[])
|
||||||
break;
|
break;
|
||||||
case 'z':
|
case 'z':
|
||||||
if (control->flags & FLAG_NOT_LZMA)
|
if (control->flags & FLAG_NOT_LZMA)
|
||||||
failure(control, "Can only use one of -l, -b, -g, -z or -n\n");
|
failure("Can only use one of -l, -b, -g, -z or -n\n");
|
||||||
control->flags |= FLAG_ZPAQ_COMPRESS;
|
control->flags |= FLAG_ZPAQ_COMPRESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -354,7 +354,7 @@ int main(int argc, char *argv[])
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
if (control->outname && argc > 1)
|
if (control->outname && argc > 1)
|
||||||
failure(control, "Cannot specify output filename with more than 1 file\n");
|
failure("Cannot specify output filename with more than 1 file\n");
|
||||||
|
|
||||||
if (VERBOSE && !SHOW_PROGRESS) {
|
if (VERBOSE && !SHOW_PROGRESS) {
|
||||||
print_err("Cannot have -v and -q options. -v wins.\n");
|
print_err("Cannot have -v and -q options. -v wins.\n");
|
||||||
|
|
@ -400,13 +400,13 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
stat(control->infile, &infile_stat);
|
stat(control->infile, &infile_stat);
|
||||||
if (unlikely(S_ISDIR(infile_stat.st_mode)))
|
if (unlikely(S_ISDIR(infile_stat.st_mode)))
|
||||||
failure(control, "lrzip only works directly on FILES.\n"
|
failure("lrzip only works directly on FILES.\n"
|
||||||
"Use lrztar or pipe through tar for compressing directories.\n");
|
"Use lrztar or pipe through tar for compressing directories.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (INFO && STDIN)
|
if (INFO && STDIN)
|
||||||
failure(control, "Will not get file info from STDIN\n");
|
failure("Will not get file info from STDIN\n");
|
||||||
|
|
||||||
if (control->outname && (strcmp(control->outname, "-") == 0)) {
|
if (control->outname && (strcmp(control->outname, "-") == 0)) {
|
||||||
control->flags |= FLAG_STDOUT;
|
control->flags |= FLAG_STDOUT;
|
||||||
|
|
@ -460,7 +460,7 @@ int main(int argc, char *argv[])
|
||||||
gettimeofday(&start_time, NULL);
|
gettimeofday(&start_time, NULL);
|
||||||
|
|
||||||
if (unlikely(STDIN && ENCRYPT))
|
if (unlikely(STDIN && ENCRYPT))
|
||||||
failure(control, "Unable to work from STDIN while reading password\n");
|
failure("Unable to work from STDIN while reading password\n");
|
||||||
|
|
||||||
if (DECOMPRESS || TEST_ONLY)
|
if (DECOMPRESS || TEST_ONLY)
|
||||||
decompress_file(control);
|
decompress_file(control);
|
||||||
|
|
|
||||||
137
runzip.c
137
runzip.c
|
|
@ -49,21 +49,25 @@
|
||||||
/* needed for CRC routines */
|
/* needed for CRC routines */
|
||||||
#include "lzma/C/7zCrc.h"
|
#include "lzma/C/7zCrc.h"
|
||||||
|
|
||||||
static inline uchar read_u8(rzip_control *control, void *ss, int stream)
|
static inline uchar read_u8(rzip_control *control, void *ss, int stream, bool *err)
|
||||||
{
|
{
|
||||||
uchar b;
|
uchar b;
|
||||||
|
|
||||||
if (unlikely(read_stream(control, ss, stream, &b, 1) != 1))
|
if (unlikely(read_stream(control, ss, stream, &b, 1) != 1)) {
|
||||||
fatal(control, "Stream read u8 failed\n");
|
*err = true;
|
||||||
|
fatal_return(("Stream read u8 failed\n"), 0);
|
||||||
|
}
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u32 read_u32(rzip_control *control, void *ss, int stream)
|
static inline u32 read_u32(rzip_control *control, void *ss, int stream, bool *err)
|
||||||
{
|
{
|
||||||
u32 ret;
|
u32 ret;
|
||||||
|
|
||||||
if (unlikely(read_stream(control, ss, stream, (uchar *)&ret, 4) != 4))
|
if (unlikely(read_stream(control, ss, stream, (uchar *)&ret, 4) != 4)) {
|
||||||
fatal(control, "Stream read u32 failed\n");
|
*err = true;
|
||||||
|
fatal_return(("Stream read u32 failed\n"), 0);
|
||||||
|
}
|
||||||
ret = le32toh(ret);
|
ret = le32toh(ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -74,7 +78,7 @@ static inline i64 read_vchars(rzip_control *control, void *ss, int stream, int l
|
||||||
i64 s = 0;
|
i64 s = 0;
|
||||||
|
|
||||||
if (unlikely(read_stream(control, ss, stream, (uchar *)&s, length) != length))
|
if (unlikely(read_stream(control, ss, stream, (uchar *)&s, length) != length))
|
||||||
fatal(control, "Stream read of %d bytes failed\n", length);
|
fatal_return(("Stream read of %d bytes failed\n", length), -1);
|
||||||
s = le64toh(s);
|
s = le64toh(s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
@ -128,7 +132,7 @@ static i64 seekto_fdinend(rzip_control *control)
|
||||||
while ((tmpchar = getchar()) != EOF) {
|
while ((tmpchar = getchar()) != EOF) {
|
||||||
control->tmp_inbuf[control->in_len++] = (char)tmpchar;
|
control->tmp_inbuf[control->in_len++] = (char)tmpchar;
|
||||||
if (unlikely(control->in_len > control->in_maxlen))
|
if (unlikely(control->in_len > control->in_maxlen))
|
||||||
failure(control, "Trying to read greater than max_len\n");
|
failure_return(("Trying to read greater than max_len\n"), -1);
|
||||||
}
|
}
|
||||||
control->in_ofs = control->in_len;
|
control->in_ofs = control->in_len;
|
||||||
return control->in_ofs;
|
return control->in_ofs;
|
||||||
|
|
@ -137,11 +141,13 @@ static i64 seekto_fdinend(rzip_control *control)
|
||||||
static i64 read_header(rzip_control *control, void *ss, uchar *head)
|
static i64 read_header(rzip_control *control, void *ss, uchar *head)
|
||||||
{
|
{
|
||||||
int chunk_bytes = 2;
|
int chunk_bytes = 2;
|
||||||
|
bool err = false;
|
||||||
|
|
||||||
/* All chunks were unnecessarily encoded 8 bytes wide version 0.4x */
|
/* All chunks were unnecessarily encoded 8 bytes wide version 0.4x */
|
||||||
if (control->major_version == 0 && control->minor_version == 4)
|
if (control->major_version == 0 && control->minor_version == 4)
|
||||||
chunk_bytes = 8;
|
chunk_bytes = 8;
|
||||||
*head = read_u8(control, ss, 0);
|
*head = read_u8(control, ss, 0, &err);
|
||||||
|
if (err) return -1;
|
||||||
return read_vchars(control, ss, 0, chunk_bytes);
|
return read_vchars(control, ss, 0, chunk_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -151,18 +157,22 @@ static i64 unzip_literal(rzip_control *control, void *ss, i64 len, uint32 *cksum
|
||||||
uchar *buf;
|
uchar *buf;
|
||||||
|
|
||||||
if (unlikely(len < 0))
|
if (unlikely(len < 0))
|
||||||
failure(control, "len %lld is negative in unzip_literal!\n",len);
|
failure_return(("len %lld is negative in unzip_literal!\n",len), -1);
|
||||||
|
|
||||||
buf = (uchar *)malloc(len);
|
buf = (uchar *)malloc(len);
|
||||||
if (unlikely(!buf))
|
if (unlikely(!buf))
|
||||||
fatal(control, "Failed to malloc literal buffer of size %lld\n", len);
|
fatal_return(("Failed to malloc literal buffer of size %lld\n", len), -1);
|
||||||
|
|
||||||
stream_read = read_stream(control, ss, 1, buf, len);
|
stream_read = read_stream(control, ss, 1, buf, len);
|
||||||
if (unlikely(stream_read == -1 ))
|
if (unlikely(stream_read == -1 )) {
|
||||||
fatal(control, "Failed to read_stream in unzip_literal\n");
|
free(buf);
|
||||||
|
fatal_return(("Failed to read_stream in unzip_literal\n"), -1);
|
||||||
|
}
|
||||||
|
|
||||||
if (unlikely(write_1g(control, buf, (size_t)stream_read) != (ssize_t)stream_read))
|
if (unlikely(write_1g(control, buf, (size_t)stream_read) != (ssize_t)stream_read)) {
|
||||||
fatal(control, "Failed to write literal buffer of size %lld\n", stream_read);
|
free(buf);
|
||||||
|
fatal_return(("Failed to write literal buffer of size %lld\n", stream_read), -1);
|
||||||
|
}
|
||||||
|
|
||||||
if (!HAS_MD5)
|
if (!HAS_MD5)
|
||||||
*cksum = CrcUpdate(*cksum, buf, stream_read);
|
*cksum = CrcUpdate(*cksum, buf, stream_read);
|
||||||
|
|
@ -191,32 +201,36 @@ static i64 unzip_match(rzip_control *control, void *ss, i64 len, uint32 *cksum,
|
||||||
uchar *buf, *off_buf;
|
uchar *buf, *off_buf;
|
||||||
|
|
||||||
if (unlikely(len < 0))
|
if (unlikely(len < 0))
|
||||||
failure(control, "len %lld is negative in unzip_match!\n",len);
|
failure_return(("len %lld is negative in unzip_match!\n",len), -1);
|
||||||
|
|
||||||
total = 0;
|
total = 0;
|
||||||
cur_pos = seekcur_fdout(control);
|
cur_pos = seekcur_fdout(control);
|
||||||
if (unlikely(cur_pos == -1))
|
if (unlikely(cur_pos == -1))
|
||||||
fatal(control, "Seek failed on out file in unzip_match.\n");
|
fatal_return(("Seek failed on out file in unzip_match.\n"), -1);
|
||||||
|
|
||||||
/* Note the offset is in a different format v0.40+ */
|
/* Note the offset is in a different format v0.40+ */
|
||||||
offset = read_vchars(control, ss, 0, chunk_bytes);
|
offset = read_vchars(control, ss, 0, chunk_bytes);
|
||||||
|
if (unlikely(offset == -1)) return -1;
|
||||||
if (unlikely(seekto_fdhist(control, cur_pos - offset) == -1))
|
if (unlikely(seekto_fdhist(control, cur_pos - offset) == -1))
|
||||||
fatal(control, "Seek failed by %d from %d on history file in unzip_match\n",
|
fatal_return(("Seek failed by %d from %d on history file in unzip_match\n",
|
||||||
offset, cur_pos);
|
offset, cur_pos), -1);
|
||||||
|
|
||||||
buf = (uchar *)malloc(len);
|
buf = (uchar *)malloc(len);
|
||||||
if (unlikely(!buf))
|
if (unlikely(!buf))
|
||||||
fatal(control, "Failed to malloc match buffer of size %lld\n", len);
|
fatal_return(("Failed to malloc match buffer of size %lld\n", len), -1);
|
||||||
off_buf = buf;
|
off_buf = buf;
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
n = MIN(len, offset);
|
n = MIN(len, offset);
|
||||||
|
|
||||||
if (unlikely(read_fdhist(control, off_buf, (size_t)n) != (ssize_t)n))
|
if (unlikely(read_fdhist(control, off_buf, (size_t)n) != (ssize_t)n)) {
|
||||||
fatal(control, "Failed to read %d bytes in unzip_match\n", n);
|
free(buf);
|
||||||
|
fatal_return(("Failed to read %d bytes in unzip_match\n", n), -1);
|
||||||
if (unlikely(write_1g(control, off_buf, (size_t)n) != (ssize_t)n))
|
}
|
||||||
fatal(control, "Failed to write %d bytes in unzip_match\n", n);
|
if (unlikely(write_1g(control, off_buf, (size_t)n) != (ssize_t)n)) {
|
||||||
|
free(buf);
|
||||||
|
fatal_return(("Failed to write %d bytes in unzip_match\n", n), -1);
|
||||||
|
}
|
||||||
|
|
||||||
if (!HAS_MD5)
|
if (!HAS_MD5)
|
||||||
*cksum = CrcUpdate(*cksum, off_buf, n);
|
*cksum = CrcUpdate(*cksum, off_buf, n);
|
||||||
|
|
@ -233,7 +247,7 @@ static i64 unzip_match(rzip_control *control, void *ss, i64 len, uint32 *cksum,
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* decompress a section of an open file. Call fatal(control, ) on error
|
/* decompress a section of an open file. Call fatal_return(() on error
|
||||||
return the number of bytes that have been retrieved
|
return the number of bytes that have been retrieved
|
||||||
*/
|
*/
|
||||||
static i64 runzip_chunk(rzip_control *control, int fd_in, i64 expected_size, i64 tally)
|
static i64 runzip_chunk(rzip_control *control, int fd_in, i64 expected_size, i64 tally)
|
||||||
|
|
@ -245,6 +259,7 @@ static i64 runzip_chunk(rzip_control *control, int fd_in, i64 expected_size, i64
|
||||||
struct stat st;
|
struct stat st;
|
||||||
uchar head;
|
uchar head;
|
||||||
void *ss;
|
void *ss;
|
||||||
|
bool err = false;
|
||||||
|
|
||||||
/* for display of progress */
|
/* for display of progress */
|
||||||
unsigned long divisor[] = {1,1024,1048576,1073741824U};
|
unsigned long divisor[] = {1,1024,1048576,1073741824U};
|
||||||
|
|
@ -273,9 +288,9 @@ static i64 runzip_chunk(rzip_control *control, int fd_in, i64 expected_size, i64
|
||||||
else {
|
else {
|
||||||
/* Read in the stored chunk byte width from the file */
|
/* Read in the stored chunk byte width from the file */
|
||||||
if (unlikely(read_1g(control, fd_in, &chunk_bytes, 1) != 1))
|
if (unlikely(read_1g(control, fd_in, &chunk_bytes, 1) != 1))
|
||||||
fatal(control, "Failed to read chunk_bytes size in runzip_chunk\n");
|
fatal_return(("Failed to read chunk_bytes size in runzip_chunk\n"), -1);
|
||||||
if (unlikely(chunk_bytes < 1 || chunk_bytes > 8))
|
if (unlikely(chunk_bytes < 1 || chunk_bytes > 8))
|
||||||
failure(control, "chunk_bytes %d is invalid in runzip_chunk\n", chunk_bytes);
|
failure_return(("chunk_bytes %d is invalid in runzip_chunk\n", chunk_bytes), -1);
|
||||||
}
|
}
|
||||||
if (!tally && expected_size)
|
if (!tally && expected_size)
|
||||||
print_maxverbose("Expected size: %lld\n", expected_size);
|
print_maxverbose("Expected size: %lld\n", expected_size);
|
||||||
|
|
@ -283,23 +298,35 @@ static i64 runzip_chunk(rzip_control *control, int fd_in, i64 expected_size, i64
|
||||||
|
|
||||||
ofs = seekcur_fdin(control);
|
ofs = seekcur_fdin(control);
|
||||||
if (unlikely(ofs == -1))
|
if (unlikely(ofs == -1))
|
||||||
fatal(control, "Failed to seek input file in runzip_fd\n");
|
fatal_return(("Failed to seek input file in runzip_fd\n"), -1);
|
||||||
|
|
||||||
if (fstat(fd_in, &st) || st.st_size - ofs == 0)
|
if (fstat(fd_in, &st) || st.st_size - ofs == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ss = open_stream_in(control, fd_in, NUM_STREAMS, chunk_bytes);
|
ss = open_stream_in(control, fd_in, NUM_STREAMS, chunk_bytes);
|
||||||
if (unlikely(!ss))
|
if (unlikely(!ss))
|
||||||
failure(control, "Failed to open_stream_in in runzip_chunk\n");
|
failure_return(("Failed to open_stream_in in runzip_chunk\n"), -1);
|
||||||
|
|
||||||
while ((len = read_header(control, ss, &head)) || head) {
|
while ((len = read_header(control, ss, &head)) || head) {
|
||||||
|
i64 u;
|
||||||
|
if (unlikely(len == -1)) return -1;
|
||||||
switch (head) {
|
switch (head) {
|
||||||
case 0:
|
case 0:
|
||||||
total += unzip_literal(control, ss, len, &cksum);
|
u = unzip_literal(control, ss, len, &cksum);
|
||||||
|
if (unlikely(u == -1)) {
|
||||||
|
close_stream_in(ss);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
total += u;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
total += unzip_match(control, ss, len, &cksum, chunk_bytes);
|
u = unzip_match(control, ss, len, &cksum, chunk_bytes);
|
||||||
|
if (unlikely(u == -1)) {
|
||||||
|
close_stream_in(ss);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
total += u;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (expected_size) {
|
if (expected_size) {
|
||||||
|
|
@ -314,19 +341,25 @@ static i64 runzip_chunk(rzip_control *control, int fd_in, i64 expected_size, i64
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!HAS_MD5) {
|
if (!HAS_MD5) {
|
||||||
good_cksum = read_u32(control, ss, 0);
|
good_cksum = read_u32(control, ss, 0, &err);
|
||||||
if (unlikely(good_cksum != cksum))
|
if (unlikely(err)) {
|
||||||
failure(control, "Bad checksum: 0x%08x - expected: 0x%08x\n", cksum, good_cksum);
|
close_stream_in(ss);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (unlikely(good_cksum != cksum)) {
|
||||||
|
close_stream_in(ss);
|
||||||
|
failure_return(("Bad checksum: 0x%08x - expected: 0x%08x\n", cksum, good_cksum), -1);
|
||||||
|
}
|
||||||
print_maxverbose("Checksum for block: 0x%08x\n", cksum);
|
print_maxverbose("Checksum for block: 0x%08x\n", cksum);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(close_stream_in(ss)))
|
if (unlikely(close_stream_in(ss)))
|
||||||
fatal(control, "Failed to close stream!\n");
|
fatal_return(("Failed to close stream!\n"), -1);
|
||||||
|
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Decompress an open file. Call fatal(control, ) on error
|
/* Decompress an open file. Call fatal_return(() on error
|
||||||
return the number of bytes that have been retrieved
|
return the number of bytes that have been retrieved
|
||||||
*/
|
*/
|
||||||
i64 runzip_fd(rzip_control *control, int fd_in, int fd_out, int fd_hist, i64 expected_size)
|
i64 runzip_fd(rzip_control *control, int fd_in, int fd_out, int fd_hist, i64 expected_size)
|
||||||
|
|
@ -334,22 +367,24 @@ i64 runzip_fd(rzip_control *control, int fd_in, int fd_out, int fd_hist, i64 exp
|
||||||
uchar md5_resblock[MD5_DIGEST_SIZE];
|
uchar md5_resblock[MD5_DIGEST_SIZE];
|
||||||
uchar md5_stored[MD5_DIGEST_SIZE];
|
uchar md5_stored[MD5_DIGEST_SIZE];
|
||||||
struct timeval start,end;
|
struct timeval start,end;
|
||||||
i64 total = 0;
|
i64 total = 0, u;
|
||||||
|
|
||||||
if (!NO_MD5)
|
if (!NO_MD5)
|
||||||
md5_init_ctx (&control->ctx);
|
md5_init_ctx (&control->ctx);
|
||||||
gettimeofday(&start,NULL);
|
gettimeofday(&start,NULL);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
total += runzip_chunk(control, fd_in, expected_size, total);
|
u = runzip_chunk(control, fd_in, expected_size, total);
|
||||||
|
if (unlikely(u == -1)) return -1;
|
||||||
|
total += u;
|
||||||
if (TMP_OUTBUF)
|
if (TMP_OUTBUF)
|
||||||
flush_tmpoutbuf(control);
|
{ if (unlikely(!flush_tmpoutbuf(control))) return -1; }
|
||||||
else if (STDOUT)
|
else if (STDOUT)
|
||||||
dump_tmpoutfile(control, fd_out);
|
{ if (unlikely(!dump_tmpoutfile(control, fd_out))) return -1; }
|
||||||
if (TMP_INBUF)
|
if (TMP_INBUF)
|
||||||
clear_tmpinbuf(control);
|
clear_tmpinbuf(control);
|
||||||
else if (STDIN)
|
else if (STDIN)
|
||||||
clear_tmpinfile(control);
|
if (unlikely(!clear_tmpinfile(control))) return -1;
|
||||||
} while (total < expected_size || (!expected_size && !control->eof));
|
} while (total < expected_size || (!expected_size && !control->eof));
|
||||||
|
|
||||||
gettimeofday(&end,NULL);
|
gettimeofday(&end,NULL);
|
||||||
|
|
@ -365,14 +400,14 @@ i64 runzip_fd(rzip_control *control, int fd_in, int fd_out, int fd_hist, i64 exp
|
||||||
i64 fdinend = seekto_fdinend(control);
|
i64 fdinend = seekto_fdinend(control);
|
||||||
|
|
||||||
if (unlikely(fdinend == -1))
|
if (unlikely(fdinend == -1))
|
||||||
failure(control, "Failed to seekto_fdinend in rzip_fd\n");
|
failure_return(("Failed to seekto_fdinend in rzip_fd\n"), -1);
|
||||||
if (unlikely(seekto_fdin(control, fdinend - MD5_DIGEST_SIZE) == -1))
|
if (unlikely(seekto_fdin(control, fdinend - MD5_DIGEST_SIZE) == -1))
|
||||||
failure(control, "Failed to seekto_fdin in rzip_fd\n");
|
failure_return(("Failed to seekto_fdin in rzip_fd\n"), -1);
|
||||||
|
|
||||||
if (unlikely(read_1g(control, fd_in, md5_stored, MD5_DIGEST_SIZE) != MD5_DIGEST_SIZE))
|
if (unlikely(read_1g(control, fd_in, md5_stored, MD5_DIGEST_SIZE) != MD5_DIGEST_SIZE))
|
||||||
fatal(control, "Failed to read md5 data in runzip_fd\n");
|
fatal_return(("Failed to read md5 data in runzip_fd\n"), -1);
|
||||||
if (ENCRYPT)
|
if (ENCRYPT)
|
||||||
lrz_decrypt(control, md5_stored, MD5_DIGEST_SIZE, control->salt_pass);
|
if (unlikely(!lrz_decrypt(control, md5_stored, MD5_DIGEST_SIZE, control->salt_pass))) return -1;
|
||||||
for (i = 0; i < MD5_DIGEST_SIZE; i++)
|
for (i = 0; i < MD5_DIGEST_SIZE; i++)
|
||||||
if (md5_stored[i] != md5_resblock[i]) {
|
if (md5_stored[i] != md5_resblock[i]) {
|
||||||
print_output("MD5 CHECK FAILED.\nStored:");
|
print_output("MD5 CHECK FAILED.\nStored:");
|
||||||
|
|
@ -381,7 +416,7 @@ i64 runzip_fd(rzip_control *control, int fd_in, int fd_out, int fd_hist, i64 exp
|
||||||
print_output("\nOutput file:");
|
print_output("\nOutput file:");
|
||||||
for (j = 0; j < MD5_DIGEST_SIZE; j++)
|
for (j = 0; j < MD5_DIGEST_SIZE; j++)
|
||||||
print_output("%02x", md5_resblock[j] & 0xFF);
|
print_output("%02x", md5_resblock[j] & 0xFF);
|
||||||
failure(control, "\n");
|
failure_return(("\n"), -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -400,11 +435,11 @@ i64 runzip_fd(rzip_control *control, int fd_in, int fd_out, int fd_hist, i64 exp
|
||||||
close_tmpoutbuf(control);
|
close_tmpoutbuf(control);
|
||||||
memcpy(md5_stored, md5_resblock, MD5_DIGEST_SIZE);
|
memcpy(md5_stored, md5_resblock, MD5_DIGEST_SIZE);
|
||||||
if (unlikely(seekto_fdhist(control, 0) == -1))
|
if (unlikely(seekto_fdhist(control, 0) == -1))
|
||||||
fatal(control, "Failed to seekto_fdhist in runzip_fd\n");
|
fatal_return(("Failed to seekto_fdhist in runzip_fd\n"), -1);
|
||||||
if (unlikely((md5_fstream = fdopen(fd_hist, "r")) == NULL))
|
if (unlikely((md5_fstream = fdopen(fd_hist, "r")) == NULL))
|
||||||
fatal(control, "Failed to fdopen fd_hist in runzip_fd\n");
|
fatal_return(("Failed to fdopen fd_hist in runzip_fd\n"), -1);
|
||||||
if (unlikely(md5_stream(md5_fstream, md5_resblock)))
|
if (unlikely(md5_stream(md5_fstream, md5_resblock)))
|
||||||
fatal(control, "Failed to md5_stream in runzip_fd\n");
|
fatal_return(("Failed to md5_stream in runzip_fd\n"), -1);
|
||||||
/* We don't close the file here as it's closed in main */
|
/* We don't close the file here as it's closed in main */
|
||||||
for (i = 0; i < MD5_DIGEST_SIZE; i++)
|
for (i = 0; i < MD5_DIGEST_SIZE; i++)
|
||||||
if (md5_stored[i] != md5_resblock[i]) {
|
if (md5_stored[i] != md5_resblock[i]) {
|
||||||
|
|
@ -414,7 +449,7 @@ i64 runzip_fd(rzip_control *control, int fd_in, int fd_out, int fd_hist, i64 exp
|
||||||
print_output("\nOutput file:");
|
print_output("\nOutput file:");
|
||||||
for (j = 0; j < MD5_DIGEST_SIZE; j++)
|
for (j = 0; j < MD5_DIGEST_SIZE; j++)
|
||||||
print_output("%02x", md5_resblock[j] & 0xFF);
|
print_output("%02x", md5_resblock[j] & 0xFF);
|
||||||
failure(control, "\n");
|
failure_return(("\n"), -1);
|
||||||
}
|
}
|
||||||
print_output("MD5 integrity of written file matches archive\n");
|
print_output("MD5 integrity of written file matches archive\n");
|
||||||
if (!HAS_MD5)
|
if (!HAS_MD5)
|
||||||
|
|
|
||||||
252
rzip.c
252
rzip.c
|
|
@ -142,7 +142,7 @@ struct sliding_buffer {
|
||||||
int fd; /* The fd of the mmap */
|
int fd; /* The fd of the mmap */
|
||||||
} sb; /* Sliding buffer */
|
} sb; /* Sliding buffer */
|
||||||
|
|
||||||
static void remap_low_sb(rzip_control *control)
|
static bool remap_low_sb(rzip_control *control)
|
||||||
{
|
{
|
||||||
i64 new_offset;
|
i64 new_offset;
|
||||||
|
|
||||||
|
|
@ -150,19 +150,20 @@ static void remap_low_sb(rzip_control *control)
|
||||||
round_to_page(&new_offset);
|
round_to_page(&new_offset);
|
||||||
print_maxverbose("Sliding main buffer to offset %lld\n", new_offset);
|
print_maxverbose("Sliding main buffer to offset %lld\n", new_offset);
|
||||||
if (unlikely(munmap(sb.buf_low, sb.size_low)))
|
if (unlikely(munmap(sb.buf_low, sb.size_low)))
|
||||||
fatal(control, "Failed to munmap in remap_low_sb\n");
|
fatal_return(("Failed to munmap in remap_low_sb\n"), false);
|
||||||
if (new_offset + sb.size_low > sb.orig_size)
|
if (new_offset + sb.size_low > sb.orig_size)
|
||||||
sb.size_low = sb.orig_size - new_offset;
|
sb.size_low = sb.orig_size - new_offset;
|
||||||
sb.offset_low = new_offset;
|
sb.offset_low = new_offset;
|
||||||
sb.buf_low = (uchar *)mmap(sb.buf_low, sb.size_low, PROT_READ, MAP_SHARED, sb.fd, sb.orig_offset + sb.offset_low);
|
sb.buf_low = (uchar *)mmap(sb.buf_low, sb.size_low, PROT_READ, MAP_SHARED, sb.fd, sb.orig_offset + sb.offset_low);
|
||||||
if (unlikely(sb.buf_low == MAP_FAILED))
|
if (unlikely(sb.buf_low == MAP_FAILED))
|
||||||
fatal(control, "Failed to re mmap in remap_low_sb\n");
|
fatal_return(("Failed to re mmap in remap_low_sb\n"), false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void remap_high_sb(rzip_control *control, i64 p)
|
static inline bool remap_high_sb(rzip_control *control, i64 p)
|
||||||
{
|
{
|
||||||
if (unlikely(munmap(sb.buf_high, sb.size_high)))
|
if (unlikely(munmap(sb.buf_high, sb.size_high)))
|
||||||
fatal(control, "Failed to munmap in remap_high_sb\n");
|
fatal_return(("Failed to munmap in remap_high_sb\n"), false);
|
||||||
sb.size_high = sb.high_length; /* In case we shrunk it when we hit the end of the file */
|
sb.size_high = sb.high_length; /* In case we shrunk it when we hit the end of the file */
|
||||||
sb.offset_high = p;
|
sb.offset_high = p;
|
||||||
/* Make sure offset is rounded to page size of total offset */
|
/* Make sure offset is rounded to page size of total offset */
|
||||||
|
|
@ -171,7 +172,8 @@ static inline void remap_high_sb(rzip_control *control, i64 p)
|
||||||
sb.size_high = sb.orig_size - sb.offset_high;
|
sb.size_high = sb.orig_size - sb.offset_high;
|
||||||
sb.buf_high = (uchar *)mmap(sb.buf_high, sb.size_high, PROT_READ, MAP_SHARED, sb.fd, sb.orig_offset + sb.offset_high);
|
sb.buf_high = (uchar *)mmap(sb.buf_high, sb.size_high, PROT_READ, MAP_SHARED, sb.fd, sb.orig_offset + sb.offset_high);
|
||||||
if (unlikely(sb.buf_high == MAP_FAILED))
|
if (unlikely(sb.buf_high == MAP_FAILED))
|
||||||
fatal(control, "Failed to re mmap in remap_high_sb\n");
|
fatal_return(("Failed to re mmap in remap_high_sb\n"), false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We use a "sliding mmap" to effectively read more than we can fit into the
|
/* We use a "sliding mmap" to effectively read more than we can fit into the
|
||||||
|
|
@ -185,45 +187,49 @@ static uchar *get_sb(rzip_control *control, i64 p)
|
||||||
i64 low_end = sb.offset_low + sb.size_low;
|
i64 low_end = sb.offset_low + sb.size_low;
|
||||||
|
|
||||||
if (unlikely(sb.offset_search > low_end))
|
if (unlikely(sb.offset_search > low_end))
|
||||||
remap_low_sb(control);
|
if (unlikely(!remap_low_sb(control))) return NULL;
|
||||||
if (p >= sb.offset_low && p < low_end)
|
if (p >= sb.offset_low && p < low_end)
|
||||||
return (sb.buf_low + p - sb.offset_low);
|
return (sb.buf_low + p - sb.offset_low);
|
||||||
if (p >= sb.offset_high && p < (sb.offset_high + sb.size_high))
|
if (p >= sb.offset_high && p < (sb.offset_high + sb.size_high))
|
||||||
return (sb.buf_high + (p - sb.offset_high));
|
return (sb.buf_high + (p - sb.offset_high));
|
||||||
/* p is not within the low or high buffer range */
|
/* p is not within the low or high buffer range */
|
||||||
remap_high_sb(control, p);
|
if (unlikely(!remap_high_sb(control, p))) return NULL;
|
||||||
return (sb.buf_high + (p - sb.offset_high));
|
return (sb.buf_high + (p - sb.offset_high));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* All put_u8/u32/vchars go to stream 0 */
|
/* All put_u8/u32/vchars go to stream 0 */
|
||||||
static inline void put_u8(rzip_control *control, void *ss, uchar b)
|
static inline bool put_u8(rzip_control *control, void *ss, uchar b)
|
||||||
{
|
{
|
||||||
if (unlikely(write_stream(control, ss, 0, &b, 1)))
|
if (unlikely(write_stream(control, ss, 0, &b, 1)))
|
||||||
fatal(control, "Failed to put_u8\n");
|
fatal_return(("Failed to put_u8\n"), false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void put_u32(rzip_control *control, void *ss, uint32_t s)
|
static inline bool put_u32(rzip_control *control, void *ss, uint32_t s)
|
||||||
{
|
{
|
||||||
s = htole32(s);
|
s = htole32(s);
|
||||||
if (unlikely(write_stream(control, ss, 0, (uchar *)&s, 4)))
|
if (unlikely(write_stream(control, ss, 0, (uchar *)&s, 4)))
|
||||||
fatal(control, "Failed to put_u32\n");
|
fatal_return(("Failed to put_u32\n"), false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Put a variable length of bytes dependant on how big the chunk is */
|
/* Put a variable length of bytes dependant on how big the chunk is */
|
||||||
static inline void put_vchars(rzip_control *control, void *ss, i64 s, int length)
|
static inline bool put_vchars(rzip_control *control, void *ss, i64 s, int length)
|
||||||
{
|
{
|
||||||
s = htole64(s);
|
s = htole64(s);
|
||||||
if (unlikely(write_stream(control, ss, 0, (uchar *)&s, length)))
|
if (unlikely(write_stream(control, ss, 0, (uchar *)&s, length)))
|
||||||
fatal(control, "Failed to put_vchars\n");
|
fatal_return(("Failed to put_vchars\n"), false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void put_header(rzip_control *control, void *ss, uchar head, i64 len)
|
static bool put_header(rzip_control *control, void *ss, uchar head, i64 len)
|
||||||
{
|
{
|
||||||
put_u8(control, ss, head);
|
if (unlikely(!put_u8(control, ss, head))) return false;
|
||||||
put_vchars(control, ss, len, 2);
|
if (unlikely(!put_vchars(control, ss, len, 2))) return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void put_match(rzip_control *control, struct rzip_state *st, i64 p, i64 offset, i64 len)
|
static bool put_match(rzip_control *control, struct rzip_state *st, i64 p, i64 offset, i64 len)
|
||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
i64 ofs;
|
i64 ofs;
|
||||||
|
|
@ -232,8 +238,8 @@ static void put_match(rzip_control *control, struct rzip_state *st, i64 p, i64 o
|
||||||
n = 0xFFFF;
|
n = 0xFFFF;
|
||||||
|
|
||||||
ofs = (p - offset);
|
ofs = (p - offset);
|
||||||
put_header(control, st->ss, 1, n);
|
if (unlikely(!put_header(control, st->ss, 1, n))) return false;
|
||||||
put_vchars(control, st->ss, ofs, st->chunk_bytes);
|
if (unlikely(!put_vchars(control, st->ss, ofs, st->chunk_bytes))) return false;
|
||||||
|
|
||||||
st->stats.matches++;
|
st->stats.matches++;
|
||||||
st->stats.match_bytes += n;
|
st->stats.match_bytes += n;
|
||||||
|
|
@ -241,6 +247,7 @@ static void put_match(rzip_control *control, struct rzip_state *st, i64 p, i64 o
|
||||||
p += n;
|
p += n;
|
||||||
offset += n;
|
offset += n;
|
||||||
} while (len);
|
} while (len);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write some data to a stream mmap encoded. Return -1 on failure */
|
/* write some data to a stream mmap encoded. Return -1 on failure */
|
||||||
|
|
@ -254,20 +261,23 @@ static int write_sbstream(rzip_control *control, void *ss, int stream, i64 p, i6
|
||||||
n = MIN(sinfo->bufsize - sinfo->s[stream].buflen, len);
|
n = MIN(sinfo->bufsize - sinfo->s[stream].buflen, len);
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
memcpy(sinfo->s[stream].buf + sinfo->s[stream].buflen + i,
|
uchar *u;
|
||||||
get_sb(control, p + i), 1);
|
|
||||||
|
u = get_sb(control, p + i);
|
||||||
|
if (unlikely(!u)) return -1;
|
||||||
|
memcpy(sinfo->s[stream].buf + sinfo->s[stream].buflen + i, u, 1);
|
||||||
}
|
}
|
||||||
sinfo->s[stream].buflen += n;
|
sinfo->s[stream].buflen += n;
|
||||||
p += n;
|
p += n;
|
||||||
len -= n;
|
len -= n;
|
||||||
|
|
||||||
if (sinfo->s[stream].buflen == sinfo->bufsize)
|
if (sinfo->s[stream].buflen == sinfo->bufsize)
|
||||||
flush_buffer(control, sinfo, stream);
|
if (unlikely(!flush_buffer(control, sinfo, stream))) return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void put_literal(rzip_control *control, struct rzip_state *st, i64 last, i64 p)
|
static bool put_literal(rzip_control *control, struct rzip_state *st, i64 last, i64 p)
|
||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
i64 len = p - last;
|
i64 len = p - last;
|
||||||
|
|
@ -277,12 +287,13 @@ static void put_literal(rzip_control *control, struct rzip_state *st, i64 last,
|
||||||
st->stats.literals++;
|
st->stats.literals++;
|
||||||
st->stats.literal_bytes += len;
|
st->stats.literal_bytes += len;
|
||||||
|
|
||||||
put_header(control, st->ss, 0, len);
|
if (unlikely(!put_header(control, st->ss, 0, len))) return false;
|
||||||
|
|
||||||
if (unlikely(len && write_sbstream(control, st->ss, 1, last, len)))
|
if (unlikely(len && write_sbstream(control, st->ss, 1, last, len)))
|
||||||
fatal(control, "Failed to write_stream in put_literal\n");
|
fatal_return(("Failed to write_stream in put_literal\n"), false);
|
||||||
last += len;
|
last += len;
|
||||||
} while (p > last);
|
} while (p > last);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Could give false positive on offset 0. Who cares. */
|
/* Could give false positive on offset 0. Who cares. */
|
||||||
|
|
@ -404,8 +415,14 @@ again:
|
||||||
|
|
||||||
static inline tag next_tag(rzip_control *control, struct rzip_state *st, i64 p, tag t)
|
static inline tag next_tag(rzip_control *control, struct rzip_state *st, i64 p, tag t)
|
||||||
{
|
{
|
||||||
t ^= st->hash_index[*get_sb(control, p - 1)];
|
uchar *u;
|
||||||
t ^= st->hash_index[*get_sb(control, p + MINIMUM_MATCH - 1)];
|
|
||||||
|
u = get_sb(control, p - 1);
|
||||||
|
if (unlikely(!u)) return -1;
|
||||||
|
t ^= st->hash_index[*u];
|
||||||
|
u = get_sb(control, p + MINIMUM_MATCH - 1);
|
||||||
|
if (unlikely(!u)) return -1;
|
||||||
|
t ^= st->hash_index[*u];
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -413,9 +430,13 @@ static inline tag full_tag(rzip_control *control, struct rzip_state *st, i64 p)
|
||||||
{
|
{
|
||||||
tag ret = 0;
|
tag ret = 0;
|
||||||
int i;
|
int i;
|
||||||
|
uchar *u;
|
||||||
|
|
||||||
for (i = 0; i < MINIMUM_MATCH; i++)
|
for (i = 0; i < MINIMUM_MATCH; i++) {
|
||||||
ret ^= st->hash_index[*get_sb(control, p + i)];
|
u = get_sb(control, p + i);
|
||||||
|
if (unlikely(!u)) return -1;
|
||||||
|
ret ^= st->hash_index[*u];
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -515,7 +536,7 @@ static void show_distrib(rzip_control *control, struct rzip_state *st)
|
||||||
primary * 100.0 / (total ? : 1));
|
primary * 100.0 / (total ? : 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hash_search(rzip_control *control, struct rzip_state *st, double pct_base, double pct_multiple)
|
static bool hash_search(rzip_control *control, struct rzip_state *st, double pct_base, double pct_multiple)
|
||||||
{
|
{
|
||||||
int lastpct = 0, last_chunkpct = 0;
|
int lastpct = 0, last_chunkpct = 0;
|
||||||
i64 cksum_limit = 0, p, end;
|
i64 cksum_limit = 0, p, end;
|
||||||
|
|
@ -544,7 +565,7 @@ static void hash_search(rzip_control *control, struct rzip_state *st, double pct
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(!st->hash_table))
|
if (unlikely(!st->hash_table))
|
||||||
fatal(control, "Failed to allocate hash table in hash_search\n");
|
fatal_return(("Failed to allocate hash table in hash_search\n"), false);
|
||||||
|
|
||||||
st->minimum_tag_mask = tag_mask;
|
st->minimum_tag_mask = tag_mask;
|
||||||
st->tag_clean_ptr = 0;
|
st->tag_clean_ptr = 0;
|
||||||
|
|
@ -558,8 +579,10 @@ static void hash_search(rzip_control *control, struct rzip_state *st, double pct
|
||||||
current.p = p;
|
current.p = p;
|
||||||
current.ofs = 0;
|
current.ofs = 0;
|
||||||
|
|
||||||
if (likely(end > 0))
|
if (likely(end > 0)) {
|
||||||
t = full_tag(control, st, p);
|
t = full_tag(control, st, p);
|
||||||
|
if (unlikely(t == -1)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
while (p < end) {
|
while (p < end) {
|
||||||
i64 reverse, mlen, offset = 0;
|
i64 reverse, mlen, offset = 0;
|
||||||
|
|
@ -567,6 +590,7 @@ static void hash_search(rzip_control *control, struct rzip_state *st, double pct
|
||||||
p++;
|
p++;
|
||||||
sb.offset_search = p;
|
sb.offset_search = p;
|
||||||
t = next_tag(control, st, p, t);
|
t = next_tag(control, st, p, t);
|
||||||
|
if (unlikely(t == -1)) return false;
|
||||||
|
|
||||||
/* Don't look for a match if there are no tags with
|
/* Don't look for a match if there are no tags with
|
||||||
this number of bits in the hash table. */
|
this number of bits in the hash table. */
|
||||||
|
|
@ -593,12 +617,13 @@ static void hash_search(rzip_control *control, struct rzip_state *st, double pct
|
||||||
if ((current.len >= GREAT_MATCH || p >= current.p + MINIMUM_MATCH)
|
if ((current.len >= GREAT_MATCH || p >= current.p + MINIMUM_MATCH)
|
||||||
&& current.len >= MINIMUM_MATCH) {
|
&& current.len >= MINIMUM_MATCH) {
|
||||||
if (st->last_match < current.p)
|
if (st->last_match < current.p)
|
||||||
put_literal(control, st, st->last_match, current.p);
|
if (unlikely(!put_literal(control, st, st->last_match, current.p))) return false;
|
||||||
put_match(control, st, current.p, current.ofs, current.len);
|
if (unlikely(!put_match(control, st, current.p, current.ofs, current.len))) return false;
|
||||||
st->last_match = current.p + current.len;
|
st->last_match = current.p + current.len;
|
||||||
current.p = p = st->last_match;
|
current.p = p = st->last_match;
|
||||||
current.len = 0;
|
current.len = 0;
|
||||||
t = full_tag(control, st, p);
|
t = full_tag(control, st, p);
|
||||||
|
if (unlikely(t == -1)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(p % 128 == 0)) {
|
if (unlikely(p % 128 == 0)) {
|
||||||
|
|
@ -621,7 +646,7 @@ static void hash_search(rzip_control *control, struct rzip_state *st, double pct
|
||||||
uchar *ckbuf = malloc(n);
|
uchar *ckbuf = malloc(n);
|
||||||
|
|
||||||
if (unlikely(!ckbuf))
|
if (unlikely(!ckbuf))
|
||||||
fatal(control, "Failed to malloc ckbuf in hash_search\n");
|
fatal_return(("Failed to malloc ckbuf in hash_search\n"), false);
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
memcpy(ckbuf + i, get_sb(control, cksum_limit + i), 1);
|
memcpy(ckbuf + i, get_sb(control, cksum_limit + i), 1);
|
||||||
st->cksum = CrcUpdate(st->cksum, ckbuf, n);
|
st->cksum = CrcUpdate(st->cksum, ckbuf, n);
|
||||||
|
|
@ -643,7 +668,7 @@ static void hash_search(rzip_control *control, struct rzip_state *st, double pct
|
||||||
uchar *ckbuf = malloc(n);
|
uchar *ckbuf = malloc(n);
|
||||||
|
|
||||||
if (unlikely(!ckbuf))
|
if (unlikely(!ckbuf))
|
||||||
fatal(control, "Failed to malloc ckbuf in hash_search\n");
|
fatal_return(("Failed to malloc ckbuf in hash_search\n"), false);
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
memcpy(ckbuf + i, get_sb(control, cksum_limit + i), 1);
|
memcpy(ckbuf + i, get_sb(control, cksum_limit + i), 1);
|
||||||
st->cksum = CrcUpdate(st->cksum, ckbuf, n);
|
st->cksum = CrcUpdate(st->cksum, ckbuf, n);
|
||||||
|
|
@ -653,8 +678,9 @@ static void hash_search(rzip_control *control, struct rzip_state *st, double pct
|
||||||
free(ckbuf);
|
free(ckbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
put_literal(control, st, 0, 0);
|
if (unlikely(!put_literal(control, st, 0, 0))) return false;
|
||||||
put_u32(control, st->ss, st->cksum);
|
if (unlikely(!put_u32(control, st->ss, st->cksum))) return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -676,7 +702,7 @@ static inline void *fake_mremap(void *old_address, size_t old_size, size_t new_s
|
||||||
* anonymous ram and reading stdin into it. It means the maximum ram
|
* anonymous ram and reading stdin into it. It means the maximum ram
|
||||||
* we can use will be less but we will already have determined this in
|
* we can use will be less but we will already have determined this in
|
||||||
* rzip_chunk */
|
* rzip_chunk */
|
||||||
static void mmap_stdin(rzip_control *control, uchar *buf, struct rzip_state *st)
|
static bool mmap_stdin(rzip_control *control, uchar *buf, struct rzip_state *st)
|
||||||
{
|
{
|
||||||
i64 len = st->chunk_size;
|
i64 len = st->chunk_size;
|
||||||
uchar *offset_buf = buf;
|
uchar *offset_buf = buf;
|
||||||
|
|
@ -688,7 +714,7 @@ static void mmap_stdin(rzip_control *control, uchar *buf, struct rzip_state *st)
|
||||||
ret = MIN(len, one_g);
|
ret = MIN(len, one_g);
|
||||||
ret = read(0, offset_buf, (size_t)ret);
|
ret = read(0, offset_buf, (size_t)ret);
|
||||||
if (unlikely(ret < 0))
|
if (unlikely(ret < 0))
|
||||||
fatal(control, "Failed to read in mmap_stdin\n");
|
fatal_return(("Failed to read in mmap_stdin\n"), false);
|
||||||
total += ret;
|
total += ret;
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
/* Should be EOF */
|
/* Should be EOF */
|
||||||
|
|
@ -703,7 +729,7 @@ static void mmap_stdin(rzip_control *control, uchar *buf, struct rzip_state *st)
|
||||||
st->chunk_size = 0;
|
st->chunk_size = 0;
|
||||||
}
|
}
|
||||||
if (unlikely(buf == MAP_FAILED))
|
if (unlikely(buf == MAP_FAILED))
|
||||||
fatal(control, "Failed to remap to smaller buf in mmap_stdin\n");
|
fatal_return(("Failed to remap to smaller buf in mmap_stdin\n"), false);
|
||||||
control->eof = st->stdin_eof = 1;
|
control->eof = st->stdin_eof = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -711,9 +737,10 @@ static void mmap_stdin(rzip_control *control, uchar *buf, struct rzip_state *st)
|
||||||
len -= ret;
|
len -= ret;
|
||||||
}
|
}
|
||||||
control->st_size += total;
|
control->st_size += total;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_sliding_mmap(rzip_control *control, struct rzip_state *st, int fd_in, i64 offset)
|
static bool init_sliding_mmap(rzip_control *control, struct rzip_state *st, int fd_in, i64 offset)
|
||||||
{
|
{
|
||||||
/* Initialise the high buffer */
|
/* Initialise the high buffer */
|
||||||
if (!STDIN) {
|
if (!STDIN) {
|
||||||
|
|
@ -723,7 +750,7 @@ static void init_sliding_mmap(rzip_control *control, struct rzip_state *st, int
|
||||||
sb.high_length += control->page_size - (sb.high_length % control->page_size);
|
sb.high_length += control->page_size - (sb.high_length % control->page_size);
|
||||||
sb.buf_high = (uchar *)mmap(NULL, sb.high_length, PROT_READ, MAP_SHARED, fd_in, offset);
|
sb.buf_high = (uchar *)mmap(NULL, sb.high_length, PROT_READ, MAP_SHARED, fd_in, offset);
|
||||||
if (unlikely(sb.buf_high == MAP_FAILED))
|
if (unlikely(sb.buf_high == MAP_FAILED))
|
||||||
fatal(control, "Unable to mmap buf_high in init_sliding_mmap\n");
|
fatal_return(("Unable to mmap buf_high in init_sliding_mmap\n"), false);
|
||||||
sb.size_high = sb.high_length;
|
sb.size_high = sb.high_length;
|
||||||
sb.offset_high = 0;
|
sb.offset_high = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -732,36 +759,45 @@ static void init_sliding_mmap(rzip_control *control, struct rzip_state *st, int
|
||||||
sb.size_low = st->mmap_size;
|
sb.size_low = st->mmap_size;
|
||||||
sb.orig_size = st->chunk_size;
|
sb.orig_size = st->chunk_size;
|
||||||
sb.fd = fd_in;
|
sb.fd = fd_in;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* compress a chunk of an open file. Assumes that the file is able to
|
/* compress a chunk of an open file. Assumes that the file is able to
|
||||||
be mmap'd and is seekable */
|
be mmap'd and is seekable */
|
||||||
static void rzip_chunk(rzip_control *control, struct rzip_state *st, int fd_in, int fd_out, i64 offset,
|
static bool rzip_chunk(rzip_control *control, struct rzip_state *st, int fd_in, int fd_out, i64 offset,
|
||||||
double pct_base, double pct_multiple)
|
double pct_base, double pct_multiple)
|
||||||
{
|
{
|
||||||
init_sliding_mmap(control, st, fd_in, offset);
|
if (unlikely(!init_sliding_mmap(control, st, fd_in, offset))) return false;
|
||||||
|
|
||||||
st->ss = open_stream_out(control, fd_out, NUM_STREAMS, st->chunk_size, st->chunk_bytes);
|
st->ss = open_stream_out(control, fd_out, NUM_STREAMS, st->chunk_size, st->chunk_bytes);
|
||||||
if (unlikely(!st->ss))
|
if (unlikely(!st->ss))
|
||||||
fatal(control, "Failed to open streams in rzip_chunk\n");
|
fatal_return(("Failed to open streams in rzip_chunk\n"), false);
|
||||||
|
|
||||||
print_verbose("Beginning rzip pre-processing phase\n");
|
print_verbose("Beginning rzip pre-processing phase\n");
|
||||||
hash_search(control, st, pct_base, pct_multiple);
|
if (unlikely(!hash_search(control, st, pct_base, pct_multiple))) {
|
||||||
|
close_stream_out(control, st->ss);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* unmap buffer before closing and reallocating streams */
|
/* unmap buffer before closing and reallocating streams */
|
||||||
if (unlikely(munmap(sb.buf_low, sb.size_low)))
|
if (unlikely(munmap(sb.buf_low, sb.size_low))) {
|
||||||
fatal(control, "Failed to munmap in rzip_chunk\n");
|
close_stream_out(control, st->ss);
|
||||||
|
fatal_return(("Failed to munmap in rzip_chunk\n"), false);
|
||||||
|
}
|
||||||
if (!STDIN) {
|
if (!STDIN) {
|
||||||
if (unlikely(munmap(sb.buf_high, sb.size_high)))
|
if (unlikely(munmap(sb.buf_high, sb.size_high))) {
|
||||||
fatal(control, "Failed to munmap in rzip_chunk\n");
|
close_stream_out(control, st->ss);
|
||||||
|
fatal_return(("Failed to munmap in rzip_chunk\n"), false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(close_stream_out(control, st->ss)))
|
if (unlikely(close_stream_out(control, st->ss)))
|
||||||
fatal(control, "Failed to flush/close streams in rzip_chunk\n");
|
fatal_return(("Failed to flush/close streams in rzip_chunk\n"), false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* compress a whole file chunks at a time */
|
/* compress a whole file chunks at a time */
|
||||||
void rzip_fd(rzip_control *control, int fd_in, int fd_out)
|
bool rzip_fd(rzip_control *control, int fd_in, int fd_out)
|
||||||
{
|
{
|
||||||
/* add timers for ETA estimates
|
/* add timers for ETA estimates
|
||||||
* Base it off the file size and number of iterations required
|
* Base it off the file size and number of iterations required
|
||||||
|
|
@ -784,15 +820,19 @@ void rzip_fd(rzip_control *control, int fd_in, int fd_out)
|
||||||
|
|
||||||
st = calloc(sizeof(*st), 1);
|
st = calloc(sizeof(*st), 1);
|
||||||
if (unlikely(!st))
|
if (unlikely(!st))
|
||||||
fatal(control, "Failed to allocate control state in rzip_fd\n");
|
fatal_return(("Failed to allocate control state in rzip_fd\n"), false);
|
||||||
|
|
||||||
if (LZO_COMPRESS) {
|
if (LZO_COMPRESS) {
|
||||||
if (unlikely(lzo_init() != LZO_E_OK))
|
if (unlikely(lzo_init() != LZO_E_OK)) {
|
||||||
fatal(control, "lzo_init() failed\n");
|
free(st);
|
||||||
|
fatal_return(("lzo_init() failed\n"), false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(fstat(fd_in, &s)))
|
if (unlikely(fstat(fd_in, &s))) {
|
||||||
fatal(control, "Failed to stat fd_in in rzip_fd\n");
|
free(st);
|
||||||
|
fatal_return(("Failed to stat fd_in in rzip_fd\n"), false);
|
||||||
|
}
|
||||||
|
|
||||||
if (!STDIN) {
|
if (!STDIN) {
|
||||||
len = control->st_size = s.st_size;
|
len = control->st_size = s.st_size;
|
||||||
|
|
@ -804,14 +844,18 @@ void rzip_fd(rzip_control *control, int fd_in, int fd_out)
|
||||||
/* Check if there's enough free space on the device chosen to fit the
|
/* Check if there's enough free space on the device chosen to fit the
|
||||||
* compressed file, based on the compressed file being as large as the
|
* compressed file, based on the compressed file being as large as the
|
||||||
* uncompressed file. */
|
* uncompressed file. */
|
||||||
if (unlikely(fstatvfs(fd_out, &fbuf)))
|
if (unlikely(fstatvfs(fd_out, &fbuf))) {
|
||||||
fatal(control, "Failed to fstatvfs in compress_file\n");
|
free(st);
|
||||||
|
fatal_return(("Failed to fstatvfs in compress_file\n"), false);
|
||||||
|
}
|
||||||
free_space = (i64)fbuf.f_bsize * (i64)fbuf.f_bavail;
|
free_space = (i64)fbuf.f_bsize * (i64)fbuf.f_bavail;
|
||||||
if (free_space < control->st_size) {
|
if (free_space < control->st_size) {
|
||||||
if (FORCE_REPLACE)
|
if (FORCE_REPLACE)
|
||||||
print_err("Warning, possibly inadequate free space detected, but attempting to compress due to -f option being used.\n");
|
print_err("Warning, possibly inadequate free space detected, but attempting to compress due to -f option being used.\n");
|
||||||
else
|
else {
|
||||||
failure(control, "Possibly inadequate free space to compress file, use -f to override.\n");
|
free(st);
|
||||||
|
failure_return(("Possibly inadequate free space to compress file, use -f to override.\n"), false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -855,7 +899,11 @@ void rzip_fd(rzip_control *control, int fd_in, int fd_out)
|
||||||
last.tv_sec = last.tv_usec = 0;
|
last.tv_sec = last.tv_usec = 0;
|
||||||
gettimeofday(&start, NULL);
|
gettimeofday(&start, NULL);
|
||||||
|
|
||||||
prepare_streamout_threads(control);
|
if (unlikely(!prepare_streamout_threads(control))) {
|
||||||
|
free(st->hash_table);
|
||||||
|
free(st);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
while (!pass || len > 0 || (STDIN && !st->stdin_eof)) {
|
while (!pass || len > 0 || (STDIN && !st->stdin_eof)) {
|
||||||
double pct_base, pct_multiple;
|
double pct_base, pct_multiple;
|
||||||
|
|
@ -878,26 +926,47 @@ retry:
|
||||||
sb.buf_low = mmap(NULL, st->mmap_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
sb.buf_low = mmap(NULL, st->mmap_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||||
/* Better to shrink the window to the largest size that works than fail */
|
/* Better to shrink the window to the largest size that works than fail */
|
||||||
if (sb.buf_low == MAP_FAILED) {
|
if (sb.buf_low == MAP_FAILED) {
|
||||||
if (unlikely(errno != ENOMEM))
|
if (unlikely(errno != ENOMEM)) {
|
||||||
fatal(control, "Failed to mmap %s\n", control->infile);
|
close_streamout_threads(control);
|
||||||
|
free(st->hash_table);
|
||||||
|
free(st);
|
||||||
|
fatal_return(("Failed to mmap %s\n", control->infile), false);
|
||||||
|
}
|
||||||
st->mmap_size = st->mmap_size / 10 * 9;
|
st->mmap_size = st->mmap_size / 10 * 9;
|
||||||
round_to_page(&st->mmap_size);
|
round_to_page(&st->mmap_size);
|
||||||
if (unlikely(!st->mmap_size))
|
if (unlikely(!st->mmap_size)) {
|
||||||
fatal(control, "Unable to mmap any ram\n");
|
close_streamout_threads(control);
|
||||||
|
free(st->hash_table);
|
||||||
|
free(st);
|
||||||
|
fatal_return(("Unable to mmap any ram\n"), false);
|
||||||
|
}
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
st->chunk_size = st->mmap_size;
|
st->chunk_size = st->mmap_size;
|
||||||
mmap_stdin(control, sb.buf_low, st);
|
if (unlikely(!mmap_stdin(control, sb.buf_low, st))) {
|
||||||
|
close_streamout_threads(control);
|
||||||
|
free(st->hash_table);
|
||||||
|
free(st);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* NOTE The buf is saved here for !STDIN mode */
|
/* NOTE The buf is saved here for !STDIN mode */
|
||||||
sb.buf_low = (uchar *)mmap(sb.buf_low, st->mmap_size, PROT_READ, MAP_SHARED, fd_in, offset);
|
sb.buf_low = (uchar *)mmap(sb.buf_low, st->mmap_size, PROT_READ, MAP_SHARED, fd_in, offset);
|
||||||
if (sb.buf_low == MAP_FAILED) {
|
if (sb.buf_low == MAP_FAILED) {
|
||||||
if (unlikely(errno != ENOMEM))
|
if (unlikely(errno != ENOMEM)) {
|
||||||
fatal(control, "Failed to mmap %s\n", control->infile);
|
close_streamout_threads(control);
|
||||||
|
free(st->hash_table);
|
||||||
|
free(st);
|
||||||
|
fatal_return(("Failed to mmap %s\n", control->infile), false);
|
||||||
|
}
|
||||||
st->mmap_size = st->mmap_size / 10 * 9;
|
st->mmap_size = st->mmap_size / 10 * 9;
|
||||||
round_to_page(&st->mmap_size);
|
round_to_page(&st->mmap_size);
|
||||||
if (unlikely(!st->mmap_size))
|
if (unlikely(!st->mmap_size)) {
|
||||||
fatal(control, "Unable to mmap any ram\n");
|
close_streamout_threads(control);
|
||||||
|
free(st->hash_table);
|
||||||
|
free(st);
|
||||||
|
fatal_return(("Unable to mmap any ram\n"), false);
|
||||||
|
}
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
if (st->mmap_size < st->chunk_size)
|
if (st->mmap_size < st->chunk_size)
|
||||||
|
|
@ -970,18 +1039,30 @@ retry:
|
||||||
|
|
||||||
if (st->chunk_size == len)
|
if (st->chunk_size == len)
|
||||||
control->eof = 1;
|
control->eof = 1;
|
||||||
rzip_chunk(control, st, fd_in, fd_out, offset, pct_base, pct_multiple);
|
if (unlikely(!rzip_chunk(control, st, fd_in, fd_out, offset, pct_base, pct_multiple))) {
|
||||||
|
close_streamout_threads(control);
|
||||||
|
free(st->hash_table);
|
||||||
|
free(st);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* st->chunk_size may be shrunk in rzip_chunk */
|
/* st->chunk_size may be shrunk in rzip_chunk */
|
||||||
last_chunk = st->chunk_size;
|
last_chunk = st->chunk_size;
|
||||||
len -= st->chunk_size;
|
len -= st->chunk_size;
|
||||||
if (unlikely(len > 0 && control->eof))
|
if (unlikely(len > 0 && control->eof)) {
|
||||||
failure(control, "Wrote EOF to file yet chunk_size was shrunk, corrupting archive.\n");
|
close_streamout_threads(control);
|
||||||
|
free(st->hash_table);
|
||||||
|
free(st);
|
||||||
|
failure_return(("Wrote EOF to file yet chunk_size was shrunk, corrupting archive.\n"), false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close_streamout_threads(control);
|
|
||||||
if (likely(st->hash_table))
|
if (likely(st->hash_table))
|
||||||
free(st->hash_table);
|
free(st->hash_table);
|
||||||
|
if (unlikely(!close_streamout_threads(control))) {
|
||||||
|
free(st);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!NO_MD5) {
|
if (!NO_MD5) {
|
||||||
/* Temporary workaround till someone fixes apple md5 */
|
/* Temporary workaround till someone fixes apple md5 */
|
||||||
|
|
@ -994,13 +1075,21 @@ retry:
|
||||||
}
|
}
|
||||||
/* When encrypting data, we encrypt the MD5 value as well */
|
/* When encrypting data, we encrypt the MD5 value as well */
|
||||||
if (ENCRYPT)
|
if (ENCRYPT)
|
||||||
lrz_encrypt(control, md5_resblock, MD5_DIGEST_SIZE, control->salt_pass);
|
if (unlikely(!lrz_encrypt(control, md5_resblock, MD5_DIGEST_SIZE, control->salt_pass))) {
|
||||||
if (unlikely(write_1g(control, md5_resblock, MD5_DIGEST_SIZE) != MD5_DIGEST_SIZE))
|
free(st);
|
||||||
fatal(control, "Failed to write md5 in rzip_fd\n");
|
return false;
|
||||||
|
}
|
||||||
|
if (unlikely(write_1g(control, md5_resblock, MD5_DIGEST_SIZE) != MD5_DIGEST_SIZE)) {
|
||||||
|
free(st);
|
||||||
|
fatal_return(("Failed to write md5 in rzip_fd\n"), false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TMP_OUTBUF)
|
if (TMP_OUTBUF)
|
||||||
flush_tmpoutbuf(control);
|
if (unlikely(!flush_tmpoutbuf(control))) {
|
||||||
|
free(st);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
gettimeofday(¤t, NULL);
|
gettimeofday(¤t, NULL);
|
||||||
if (STDIN)
|
if (STDIN)
|
||||||
|
|
@ -1025,6 +1114,7 @@ retry:
|
||||||
1.0 * s.st_size / s2.st_size, chunkmbs);
|
1.0 * s.st_size / s2.st_size, chunkmbs);
|
||||||
|
|
||||||
free(st);
|
free(st);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rzip_control_free(rzip_control *control)
|
void rzip_control_free(rzip_control *control)
|
||||||
|
|
|
||||||
2
rzip.h
2
rzip.h
|
|
@ -21,7 +21,7 @@
|
||||||
#define RZIP_H
|
#define RZIP_H
|
||||||
#include "lrzip_private.h"
|
#include "lrzip_private.h"
|
||||||
|
|
||||||
void rzip_fd(rzip_control *control, int fd_in, int fd_out);
|
bool rzip_fd(rzip_control *control, int fd_in, int fd_out);
|
||||||
void rzip_control_free(rzip_control *control);
|
void rzip_control_free(rzip_control *control);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
268
stream.c
268
stream.c
|
|
@ -105,53 +105,61 @@ static pthread_mutex_t output_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
static pthread_cond_t output_cond = PTHREAD_COND_INITIALIZER;
|
static pthread_cond_t output_cond = PTHREAD_COND_INITIALIZER;
|
||||||
static pthread_t *threads;
|
static pthread_t *threads;
|
||||||
|
|
||||||
static void init_mutex(rzip_control *control, pthread_mutex_t *mutex)
|
static bool init_mutex(rzip_control *control, pthread_mutex_t *mutex)
|
||||||
{
|
{
|
||||||
if (unlikely(pthread_mutex_init(mutex, NULL)))
|
if (unlikely(pthread_mutex_init(mutex, NULL)))
|
||||||
fatal(control, "pthread_mutex_init failed");
|
fatal_return(("pthread_mutex_init failed"), false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unlock_mutex(rzip_control *control, pthread_mutex_t *mutex)
|
static bool unlock_mutex(rzip_control *control, pthread_mutex_t *mutex)
|
||||||
{
|
{
|
||||||
if (unlikely(pthread_mutex_unlock(mutex)))
|
if (unlikely(pthread_mutex_unlock(mutex)))
|
||||||
fatal(control, "pthread_mutex_unlock failed");
|
fatal_return(("pthread_mutex_unlock failed"), false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lock_mutex(rzip_control *control, pthread_mutex_t *mutex)
|
static bool lock_mutex(rzip_control *control, pthread_mutex_t *mutex)
|
||||||
{
|
{
|
||||||
if (unlikely(pthread_mutex_lock(mutex)))
|
if (unlikely(pthread_mutex_lock(mutex)))
|
||||||
fatal(control, "pthread_mutex_lock failed");
|
fatal_return(("pthread_mutex_lock failed"), false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cond_wait(rzip_control *control, pthread_cond_t *cond, pthread_mutex_t *mutex)
|
static bool cond_wait(rzip_control *control, pthread_cond_t *cond, pthread_mutex_t *mutex)
|
||||||
{
|
{
|
||||||
if (unlikely(pthread_cond_wait(cond, mutex)))
|
if (unlikely(pthread_cond_wait(cond, mutex)))
|
||||||
fatal(control, "pthread_cond_wait failed");
|
fatal_return(("pthread_cond_wait failed"), false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cond_broadcast(rzip_control *control, pthread_cond_t *cond)
|
static bool cond_broadcast(rzip_control *control, pthread_cond_t *cond)
|
||||||
{
|
{
|
||||||
if (unlikely(pthread_cond_broadcast(cond)))
|
if (unlikely(pthread_cond_broadcast(cond)))
|
||||||
fatal(control, "pthread_cond_broadcast failed");
|
fatal_return(("pthread_cond_broadcast failed"), false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_pthread(rzip_control *control, pthread_t *thread, pthread_attr_t * attr,
|
bool create_pthread(rzip_control *control, pthread_t *thread, pthread_attr_t * attr,
|
||||||
void * (*start_routine)(void *), void *arg)
|
void * (*start_routine)(void *), void *arg)
|
||||||
{
|
{
|
||||||
if (unlikely(pthread_create(thread, attr, start_routine, arg)))
|
if (unlikely(pthread_create(thread, attr, start_routine, arg)))
|
||||||
fatal(control, "pthread_create");
|
fatal_return(("pthread_create"), false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void detach_pthread(rzip_control *control, pthread_t *thread)
|
bool detach_pthread(rzip_control *control, pthread_t *thread)
|
||||||
{
|
{
|
||||||
if (unlikely(pthread_detach(*thread)))
|
if (unlikely(pthread_detach(*thread)))
|
||||||
fatal(control, "pthread_detach");
|
fatal_return(("pthread_detach"), false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void join_pthread(rzip_control *control, pthread_t th, void **thread_return)
|
bool join_pthread(rzip_control *control, pthread_t th, void **thread_return)
|
||||||
{
|
{
|
||||||
if (pthread_join(th, thread_return))
|
if (pthread_join(th, thread_return))
|
||||||
fatal(control, "pthread_join");
|
fatal_return(("pthread_join"), false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* just to keep things clean, declare function here
|
/* just to keep things clean, declare function here
|
||||||
|
|
@ -164,12 +172,14 @@ static inline FILE *fake_fmemopen(rzip_control *control, void *buf, size_t bufle
|
||||||
FILE *in;
|
FILE *in;
|
||||||
|
|
||||||
if (unlikely(strcmp(mode, "r")))
|
if (unlikely(strcmp(mode, "r")))
|
||||||
failure(control, "fake_fmemopen only supports mode \"r\".");
|
failure_return(("fake_fmemopen only supports mode \"r\"."), NULL);
|
||||||
in = tmpfile();
|
in = tmpfile();
|
||||||
if (unlikely(!in))
|
if (unlikely(!in))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (unlikely(fwrite(buf, buflen, 1, in) != 1))
|
if (unlikely(fwrite(buf, buflen, 1, in) != 1)) {
|
||||||
|
fclose(in);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
rewind(in);
|
rewind(in);
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
@ -179,7 +189,7 @@ static inline FILE *fake_open_memstream(rzip_control *control, char **buf, size_
|
||||||
FILE *out;
|
FILE *out;
|
||||||
|
|
||||||
if (unlikely(buf == NULL || length == NULL))
|
if (unlikely(buf == NULL || length == NULL))
|
||||||
failure(control, "NULL parameter to fake_open_memstream");
|
failure_return(("NULL parameter to fake_open_memstream"), NULL);
|
||||||
out = tmpfile();
|
out = tmpfile();
|
||||||
if (unlikely(!out))
|
if (unlikely(!out))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -197,10 +207,14 @@ static inline int fake_open_memstream_update_buffer(FILE *fp, uchar **buf, size_
|
||||||
*buf = (uchar *)malloc(*length);
|
*buf = (uchar *)malloc(*length);
|
||||||
if (unlikely(!*buf))
|
if (unlikely(!*buf))
|
||||||
return -1;
|
return -1;
|
||||||
if (unlikely(fread(*buf, *length, 1, fp) != 1))
|
if (unlikely(fread(*buf, *length, 1, fp) != 1)) {
|
||||||
|
free(*buf);
|
||||||
return -1;
|
return -1;
|
||||||
if (unlikely(fseek(fp, original_pos, SEEK_SET)))
|
}
|
||||||
|
if (unlikely(fseek(fp, original_pos, SEEK_SET))) {
|
||||||
|
free(*buf);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -238,8 +252,11 @@ static int zpaq_compress_buf(rzip_control *control, struct compress_thread *cthr
|
||||||
zpipe_compress(in, out, control->msgout, cthread->s_len,
|
zpipe_compress(in, out, control->msgout, cthread->s_len,
|
||||||
(int)(SHOW_PROGRESS), thread);
|
(int)(SHOW_PROGRESS), thread);
|
||||||
|
|
||||||
if (unlikely(memstream_update_buffer(out, &c_buf, &dlen)))
|
if (unlikely(memstream_update_buffer(out, &c_buf, &dlen))) {
|
||||||
fatal(control, "Failed to memstream_update_buffer in zpaq_compress_buf");
|
fclose(in);
|
||||||
|
fclose(out);
|
||||||
|
fatal_return(("Failed to memstream_update_buffer in zpaq_compress_buf"), -1);
|
||||||
|
}
|
||||||
|
|
||||||
fclose(in);
|
fclose(in);
|
||||||
fclose(out);
|
fclose(out);
|
||||||
|
|
@ -495,13 +512,17 @@ static int zpaq_decompress_buf(rzip_control *control, struct uncomp_thread *ucth
|
||||||
out = open_memstream((char **)&c_buf, &dlen);
|
out = open_memstream((char **)&c_buf, &dlen);
|
||||||
if (unlikely(!out)) {
|
if (unlikely(!out)) {
|
||||||
print_err("Failed to open_memstream in zpaq_decompress_buf\n");
|
print_err("Failed to open_memstream in zpaq_decompress_buf\n");
|
||||||
|
fclose(in);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
zpipe_decompress(in, out, control->msgout, ucthread->u_len, (int)(SHOW_PROGRESS), thread);
|
zpipe_decompress(in, out, control->msgout, ucthread->u_len, (int)(SHOW_PROGRESS), thread);
|
||||||
|
|
||||||
if (unlikely(memstream_update_buffer(out, &c_buf, &dlen)))
|
if (unlikely(memstream_update_buffer(out, &c_buf, &dlen))) {
|
||||||
fatal(control, "Failed to memstream_update_buffer in zpaq_decompress_buf");
|
fclose(in);
|
||||||
|
fclose(out);
|
||||||
|
fatal_return(("Failed to memstream_update_buffer in zpaq_decompress_buf"), -1);
|
||||||
|
}
|
||||||
|
|
||||||
fclose(in);
|
fclose(in);
|
||||||
fclose(out);
|
fclose(out);
|
||||||
|
|
@ -673,9 +694,9 @@ ssize_t put_fdout(rzip_control *control, void *offset_buf, ssize_t ret)
|
||||||
/* The data won't fit in a temporary output buffer so we have
|
/* The data won't fit in a temporary output buffer so we have
|
||||||
* to fall back to temporary files. */
|
* to fall back to temporary files. */
|
||||||
print_verbose("Unable to decompress entirely in ram, will use physical files\n");
|
print_verbose("Unable to decompress entirely in ram, will use physical files\n");
|
||||||
write_fdout(control, control->tmp_outbuf, control->out_len);
|
if (unlikely(!write_fdout(control, control->tmp_outbuf, control->out_len))) return -1;
|
||||||
close_tmpoutbuf(control);
|
close_tmpoutbuf(control);
|
||||||
write_fdout(control, offset_buf, ret);
|
if (unlikely(!write_fdout(control, offset_buf, ret))) return -1;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
memcpy(control->tmp_outbuf + control->out_ofs, offset_buf, ret);
|
memcpy(control->tmp_outbuf + control->out_ofs, offset_buf, ret);
|
||||||
|
|
@ -707,7 +728,7 @@ ssize_t write_1g(rzip_control *control, void *buf, i64 len)
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void read_fdin(struct rzip_control *control, i64 len)
|
static bool read_fdin(struct rzip_control *control, i64 len)
|
||||||
{
|
{
|
||||||
int tmpchar;
|
int tmpchar;
|
||||||
i64 i;
|
i64 i;
|
||||||
|
|
@ -715,11 +736,12 @@ static void read_fdin(struct rzip_control *control, i64 len)
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
tmpchar = getchar();
|
tmpchar = getchar();
|
||||||
if (unlikely(tmpchar == EOF))
|
if (unlikely(tmpchar == EOF))
|
||||||
failure(control, "Reached end of file on STDIN prematurely on read_fdin, asked for %lld got %lld\n",
|
failure_return(("Reached end of file on STDIN prematurely on read_fdin, asked for %lld got %lld\n",
|
||||||
len, i);
|
len, i), false);
|
||||||
control->tmp_inbuf[control->in_ofs + i] = (char)tmpchar;
|
control->tmp_inbuf[control->in_ofs + i] = (char)tmpchar;
|
||||||
}
|
}
|
||||||
control->in_len = control->in_ofs + len;
|
control->in_len = control->in_ofs + len;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ditto for read */
|
/* Ditto for read */
|
||||||
|
|
@ -733,13 +755,13 @@ ssize_t read_1g(rzip_control *control, int fd, void *buf, i64 len)
|
||||||
/* We're decompressing from STDIN */
|
/* We're decompressing from STDIN */
|
||||||
if (unlikely(control->in_ofs + len > control->in_maxlen)) {
|
if (unlikely(control->in_ofs + len > control->in_maxlen)) {
|
||||||
/* We're unable to fit it all into the temp buffer */
|
/* We're unable to fit it all into the temp buffer */
|
||||||
write_fdin(control);
|
if (unlikely(!write_fdin(control))) return -1;
|
||||||
read_tmpinfile(control, control->fd_in);
|
if (unlikely(!read_tmpinfile(control, control->fd_in))) return -1;
|
||||||
close_tmpinbuf(control);
|
close_tmpinbuf(control);
|
||||||
goto read_fd;
|
goto read_fd;
|
||||||
}
|
}
|
||||||
if (control->in_ofs + len > control->in_len)
|
if (control->in_ofs + len > control->in_len)
|
||||||
read_fdin(control, control->in_ofs + len - control->in_len);
|
if (unlikely(!read_fdin(control, control->in_ofs + len - control->in_len))) return false;
|
||||||
memcpy(buf, control->tmp_inbuf + control->in_ofs, len);
|
memcpy(buf, control->tmp_inbuf + control->in_ofs, len);
|
||||||
control->in_ofs += len;
|
control->in_ofs += len;
|
||||||
return len;
|
return len;
|
||||||
|
|
@ -747,7 +769,7 @@ ssize_t read_1g(rzip_control *control, int fd, void *buf, i64 len)
|
||||||
|
|
||||||
if (TMP_OUTBUF && fd == control->fd_out) {
|
if (TMP_OUTBUF && fd == control->fd_out) {
|
||||||
if (unlikely(control->out_ofs + len > control->out_maxlen))
|
if (unlikely(control->out_ofs + len > control->out_maxlen))
|
||||||
failure(control, "Trying to read beyond out_ofs in tmpoutbuf\n");
|
failure_return(("Trying to read beyond out_ofs in tmpoutbuf\n"), -1);
|
||||||
memcpy(buf, control->tmp_outbuf + control->out_ofs, len);
|
memcpy(buf, control->tmp_outbuf + control->out_ofs, len);
|
||||||
control->out_ofs += len;
|
control->out_ofs += len;
|
||||||
return len;
|
return len;
|
||||||
|
|
@ -876,7 +898,7 @@ static int read_seekto(rzip_control *control, struct stream_info *sinfo, i64 pos
|
||||||
|
|
||||||
if (TMP_INBUF) {
|
if (TMP_INBUF) {
|
||||||
if (spos > control->in_len)
|
if (spos > control->in_len)
|
||||||
read_fdin(control, spos - control->in_len);
|
if (unlikely(!read_fdin(control, spos - control->in_len))) return -1;
|
||||||
control->in_ofs = spos;
|
control->in_ofs = spos;
|
||||||
if (unlikely(spos < 0)) {
|
if (unlikely(spos < 0)) {
|
||||||
print_err("Trying to seek to %lld outside tmp inbuf in read_seekto\n", spos);
|
print_err("Trying to seek to %lld outside tmp inbuf in read_seekto\n", spos);
|
||||||
|
|
@ -896,7 +918,7 @@ static i64 get_seek(rzip_control *control, int fd)
|
||||||
return control->out_relofs + control->out_ofs;
|
return control->out_relofs + control->out_ofs;
|
||||||
ret = lseek(fd, 0, SEEK_CUR);
|
ret = lseek(fd, 0, SEEK_CUR);
|
||||||
if (unlikely(ret == -1))
|
if (unlikely(ret == -1))
|
||||||
fatal(control, "Failed to lseek in get_seek\n");
|
fatal_return(("Failed to lseek in get_seek\n"), -1);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -908,11 +930,11 @@ static i64 get_readseek(rzip_control *control, int fd)
|
||||||
return control->in_ofs;
|
return control->in_ofs;
|
||||||
ret = lseek(fd, 0, SEEK_CUR);
|
ret = lseek(fd, 0, SEEK_CUR);
|
||||||
if (unlikely(ret == -1))
|
if (unlikely(ret == -1))
|
||||||
fatal(control, "Failed to lseek in get_seek\n");
|
fatal_return(("Failed to lseek in get_seek\n"), -1);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepare_streamout_threads(rzip_control *control)
|
bool prepare_streamout_threads(rzip_control *control)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
@ -926,30 +948,47 @@ void prepare_streamout_threads(rzip_control *control)
|
||||||
control->threads = 1;
|
control->threads = 1;
|
||||||
threads = calloc(sizeof(pthread_t), control->threads);
|
threads = calloc(sizeof(pthread_t), control->threads);
|
||||||
if (unlikely(!threads))
|
if (unlikely(!threads))
|
||||||
fatal(control, "Unable to calloc threads in prepare_streamout_threads\n");
|
fatal_return(("Unable to calloc threads in prepare_streamout_threads\n"), false);
|
||||||
|
|
||||||
cthread = calloc(sizeof(struct compress_thread), control->threads);
|
cthread = calloc(sizeof(struct compress_thread), control->threads);
|
||||||
if (unlikely(!cthread))
|
if (unlikely(!cthread)) {
|
||||||
fatal(control, "Unable to calloc cthread in prepare_streamout_threads\n");
|
free(threads);
|
||||||
|
fatal_return(("Unable to calloc cthread in prepare_streamout_threads\n"), false);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < control->threads; i++)
|
for (i = 0; i < control->threads; i++)
|
||||||
init_mutex(control, &cthread[i].mutex);
|
if (unlikely(!init_mutex(control, &cthread[i].mutex))) {
|
||||||
|
int x;
|
||||||
|
for (x = 0; x < i; x++) pthread_mutex_destroy(&cthread[x].mutex);
|
||||||
|
free(threads);
|
||||||
|
free(cthread);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void close_streamout_threads(rzip_control *control)
|
bool close_streamout_threads(rzip_control *control)
|
||||||
{
|
{
|
||||||
int i, close_thread = output_thread;
|
int i, close_thread = output_thread;
|
||||||
|
|
||||||
/* Wait for the threads in the correct order in case they end up
|
/* Wait for the threads in the correct order in case they end up
|
||||||
* serialised */
|
* serialised */
|
||||||
for (i = 0; i < control->threads; i++) {
|
for (i = 0; i < control->threads; i++) {
|
||||||
lock_mutex(control, &cthread[close_thread].mutex);
|
if (unlikely(!lock_mutex(control, &cthread[close_thread].mutex))) {
|
||||||
|
int x;
|
||||||
|
for (x = 0; x < i; x++) unlock_mutex(control, &cthread[close_thread].mutex);
|
||||||
|
free(cthread);
|
||||||
|
free(threads);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (++close_thread == control->threads)
|
if (++close_thread == control->threads)
|
||||||
close_thread = 0;
|
close_thread = 0;
|
||||||
}
|
}
|
||||||
free(cthread);
|
free(cthread);
|
||||||
free(threads);
|
free(threads);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* open a set of output streams, compressing with the given
|
/* open a set of output streams, compressing with the given
|
||||||
|
|
@ -1044,8 +1083,12 @@ retest_malloc:
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
sinfo->s[i].buf = calloc(sinfo->bufsize , 1);
|
sinfo->s[i].buf = calloc(sinfo->bufsize , 1);
|
||||||
if (unlikely(!sinfo->s[i].buf))
|
if (unlikely(!sinfo->s[i].buf)) {
|
||||||
fatal(control, "Unable to malloc buffer of size %lld in open_stream_out\n", sinfo->bufsize);
|
fatal("Unable to malloc buffer of size %lld in open_stream_out\n", sinfo->bufsize);
|
||||||
|
free(sinfo->s);
|
||||||
|
free(sinfo);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (void *)sinfo;
|
return (void *)sinfo;
|
||||||
|
|
@ -1054,7 +1097,7 @@ retest_malloc:
|
||||||
/* The block headers are all encrypted so we read the data and salt associated
|
/* The block headers are all encrypted so we read the data and salt associated
|
||||||
* with them, decrypt the data, then return the decrypted version of the
|
* with them, decrypt the data, then return the decrypted version of the
|
||||||
* values */
|
* values */
|
||||||
static void decrypt_header(rzip_control *control, uchar *head, uchar *c_type,
|
static bool decrypt_header(rzip_control *control, uchar *head, uchar *c_type,
|
||||||
i64 *c_len, i64 *u_len, i64 *last_head)
|
i64 *c_len, i64 *u_len, i64 *last_head)
|
||||||
{
|
{
|
||||||
uchar *buf = head + SALT_LEN;
|
uchar *buf = head + SALT_LEN;
|
||||||
|
|
@ -1064,12 +1107,13 @@ static void decrypt_header(rzip_control *control, uchar *head, uchar *c_type,
|
||||||
memcpy(buf + 9, u_len, 8);
|
memcpy(buf + 9, u_len, 8);
|
||||||
memcpy(buf + 17, last_head, 8);
|
memcpy(buf + 17, last_head, 8);
|
||||||
|
|
||||||
lrz_decrypt(control, buf, 25, head);
|
if (unlikely(!lrz_decrypt(control, buf, 25, head))) return false;
|
||||||
|
|
||||||
memcpy(c_type, buf, 1);
|
memcpy(c_type, buf, 1);
|
||||||
memcpy(c_len, buf + 1, 8);
|
memcpy(c_len, buf + 1, 8);
|
||||||
memcpy(u_len, buf + 9, 8);
|
memcpy(u_len, buf + 9, 8);
|
||||||
memcpy(last_head, buf + 17, 8);
|
memcpy(last_head, buf + 17, 8);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* prepare a set of n streams for reading on file descriptor f */
|
/* prepare a set of n streams for reading on file descriptor f */
|
||||||
|
|
@ -1094,8 +1138,11 @@ void *open_stream_in(rzip_control *control, int f, int n, char chunk_bytes)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ucthread = calloc(sizeof(struct uncomp_thread), total_threads);
|
ucthread = calloc(sizeof(struct uncomp_thread), total_threads);
|
||||||
if (unlikely(!ucthread))
|
if (unlikely(!ucthread)) {
|
||||||
fatal(control, "Unable to calloc cthread in open_stream_in\n");
|
free(sinfo);
|
||||||
|
free(threads);
|
||||||
|
fatal_return(("Unable to calloc cthread in open_stream_in\n"), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
sinfo->num_streams = n;
|
sinfo->num_streams = n;
|
||||||
sinfo->fd = f;
|
sinfo->fd = f;
|
||||||
|
|
@ -1129,6 +1176,7 @@ void *open_stream_in(rzip_control *control, int f, int n, char chunk_bytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sinfo->initial_pos = get_readseek(control, f);
|
sinfo->initial_pos = get_readseek(control, f);
|
||||||
|
if (unlikely(sinfo->initial_pos == -1)) goto failed;
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
uchar c, enc_head[25 + SALT_LEN];
|
uchar c, enc_head[25 + SALT_LEN];
|
||||||
|
|
@ -1176,7 +1224,7 @@ again:
|
||||||
header_length = 1 + (read_len * 3);
|
header_length = 1 + (read_len * 3);
|
||||||
}
|
}
|
||||||
if (ENCRYPT)
|
if (ENCRYPT)
|
||||||
decrypt_header(control, enc_head, &c, &v1, &v2, &sinfo->s[i].last_head);
|
if (unlikely(!decrypt_header(control, enc_head, &c, &v1, &v2, &sinfo->s[i].last_head))) goto failed;
|
||||||
|
|
||||||
v1 = le64toh(v1);
|
v1 = le64toh(v1);
|
||||||
v2 = le64toh(v2);
|
v2 = le64toh(v2);
|
||||||
|
|
@ -1219,32 +1267,38 @@ failed:
|
||||||
* by reading what has been written, encrypting it, and writing back over it.
|
* by reading what has been written, encrypting it, and writing back over it.
|
||||||
* This is very convoluted depending on whether a last_head value is written
|
* This is very convoluted depending on whether a last_head value is written
|
||||||
* to this block or not. See the callers of this function */
|
* to this block or not. See the callers of this function */
|
||||||
static void rewrite_encrypted(rzip_control *control, struct stream_info *sinfo, i64 ofs)
|
static bool rewrite_encrypted(rzip_control *control, struct stream_info *sinfo, i64 ofs)
|
||||||
{
|
{
|
||||||
uchar *buf, *head;
|
uchar *buf, *head;
|
||||||
i64 cur_ofs;
|
i64 cur_ofs;
|
||||||
|
|
||||||
cur_ofs = get_seek(control, sinfo->fd) - sinfo->initial_pos;
|
cur_ofs = get_seek(control, sinfo->fd) - sinfo->initial_pos;
|
||||||
|
if (unlikely(cur_ofs == -1)) return false;
|
||||||
head = malloc(25 + SALT_LEN);
|
head = malloc(25 + SALT_LEN);
|
||||||
if (unlikely(!head))
|
if (unlikely(!head))
|
||||||
fatal(control, "Failed to malloc head in rewrite_encrypted\n");
|
fatal_return(("Failed to malloc head in rewrite_encrypted\n"), false);
|
||||||
buf = head + SALT_LEN;
|
buf = head + SALT_LEN;
|
||||||
get_rand(control, head, SALT_LEN);
|
if (unlikely(!get_rand(control, head, SALT_LEN))) goto error;
|
||||||
if (unlikely(seekto(control, sinfo, ofs - SALT_LEN)))
|
if (unlikely(seekto(control, sinfo, ofs - SALT_LEN)))
|
||||||
failure(control, "Failed to seekto buf ofs in rewrite_encrypted\n");
|
failure_goto(("Failed to seekto buf ofs in rewrite_encrypted\n"), error);
|
||||||
if (unlikely(write_buf(control, head, SALT_LEN)))
|
if (unlikely(write_buf(control, head, SALT_LEN)))
|
||||||
failure(control, "Failed to write_buf head in rewrite_encrypted\n");
|
failure_goto(("Failed to write_buf head in rewrite_encrypted\n"), error);
|
||||||
if (unlikely(read_buf(control, sinfo->fd, buf, 25)))
|
if (unlikely(read_buf(control, sinfo->fd, buf, 25)))
|
||||||
failure(control, "Failed to read_buf buf in rewrite_encrypted\n");
|
|
||||||
|
failure_goto(("Failed to read_buf buf in rewrite_encrypted\n"), error);
|
||||||
|
|
||||||
lrz_encrypt(control, buf, 25, head);
|
if (unlikely(!lrz_encrypt(control, buf, 25, head))) goto error;
|
||||||
|
|
||||||
if (unlikely(seekto(control, sinfo, ofs)))
|
if (unlikely(seekto(control, sinfo, ofs)))
|
||||||
failure(control, "Failed to seek back to ofs in rewrite_encrypted\n");
|
failure_goto(("Failed to seek back to ofs in rewrite_encrypted\n"), error);
|
||||||
if (unlikely(write_buf(control, buf, 25)))
|
if (unlikely(write_buf(control, buf, 25)))
|
||||||
failure(control, "Failed to write_buf encrypted buf in rewrite_encrypted\n");
|
failure_goto(("Failed to write_buf encrypted buf in rewrite_encrypted\n"), error);
|
||||||
free(head);
|
free(head);
|
||||||
seekto(control, sinfo, cur_ofs);
|
seekto(control, sinfo, cur_ofs);
|
||||||
|
return true;
|
||||||
|
error:
|
||||||
|
free(head);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enter with s_buf allocated,s_buf points to the compressed data after the
|
/* Enter with s_buf allocated,s_buf points to the compressed data after the
|
||||||
|
|
@ -1287,7 +1341,7 @@ retry:
|
||||||
ret = gzip_compress_buf(control, cti);
|
ret = gzip_compress_buf(control, cti);
|
||||||
else if (ZPAQ_COMPRESS)
|
else if (ZPAQ_COMPRESS)
|
||||||
ret = zpaq_compress_buf(control, cti, i);
|
ret = zpaq_compress_buf(control, cti, i);
|
||||||
else failure(control, "Dunno wtf compression to use!\n");
|
else failure_goto(("Dunno wtf compression to use!\n"), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
padded_len = cti->c_len;
|
padded_len = cti->c_len;
|
||||||
|
|
@ -1298,15 +1352,15 @@ retry:
|
||||||
padded_len = MIN_SIZE;
|
padded_len = MIN_SIZE;
|
||||||
cti->s_buf = realloc(cti->s_buf, MIN_SIZE);
|
cti->s_buf = realloc(cti->s_buf, MIN_SIZE);
|
||||||
if (unlikely(!cti->s_buf))
|
if (unlikely(!cti->s_buf))
|
||||||
fatal(control, "Failed to realloc s_buf in compthread\n");
|
fatal_goto(("Failed to realloc s_buf in compthread\n"), error);
|
||||||
get_rand(control, cti->s_buf + cti->c_len, MIN_SIZE - cti->c_len);
|
if (unlikely(!get_rand(control, cti->s_buf + cti->c_len, MIN_SIZE - cti->c_len))) goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If compression fails for whatever reason multithreaded, then wait
|
/* If compression fails for whatever reason multithreaded, then wait
|
||||||
* for the previous thread to finish, serialising the work to decrease
|
* for the previous thread to finish, serialising the work to decrease
|
||||||
* the memory requirements, increasing the chance of success */
|
* the memory requirements, increasing the chance of success */
|
||||||
if (unlikely(ret && waited))
|
if (unlikely(ret && waited))
|
||||||
failure(control, "Failed to compress in compthread\n");
|
failure_goto(("Failed to compress in compthread\n"), error);
|
||||||
|
|
||||||
if (!waited) {
|
if (!waited) {
|
||||||
lock_mutex(control, &output_lock);
|
lock_mutex(control, &output_lock);
|
||||||
|
|
@ -1332,7 +1386,7 @@ retry:
|
||||||
if (TMP_OUTBUF) {
|
if (TMP_OUTBUF) {
|
||||||
if (!control->magic_written)
|
if (!control->magic_written)
|
||||||
write_magic(control);
|
write_magic(control);
|
||||||
flush_tmpoutbuf(control);
|
if (unlikely(!flush_tmpoutbuf(control))) goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write chunk bytes of this block */
|
/* Write chunk bytes of this block */
|
||||||
|
|
@ -1346,13 +1400,14 @@ retry:
|
||||||
|
|
||||||
/* First chunk of this stream, write headers */
|
/* First chunk of this stream, write headers */
|
||||||
ctis->initial_pos = get_seek(control, ctis->fd);
|
ctis->initial_pos = get_seek(control, ctis->fd);
|
||||||
|
if (unlikely(ctis->initial_pos == -1)) goto error;
|
||||||
|
|
||||||
for (j = 0; j < ctis->num_streams; j++) {
|
for (j = 0; j < ctis->num_streams; j++) {
|
||||||
/* If encrypting, we leave SALT_LEN room to write in salt
|
/* If encrypting, we leave SALT_LEN room to write in salt
|
||||||
* later */
|
* later */
|
||||||
if (ENCRYPT) {
|
if (ENCRYPT) {
|
||||||
if (unlikely(write_val(control, 0, SALT_LEN)))
|
if (unlikely(write_val(control, 0, SALT_LEN)))
|
||||||
fatal(control, "Failed to write_buf blank salt in compthread %d\n", i);
|
fatal_goto(("Failed to write_buf blank salt in compthread %d\n", i), error);
|
||||||
ctis->cur_pos += SALT_LEN;
|
ctis->cur_pos += SALT_LEN;
|
||||||
}
|
}
|
||||||
ctis->s[j].last_head = ctis->cur_pos + 1 + (write_len * 2);
|
ctis->s[j].last_head = ctis->cur_pos + 1 + (write_len * 2);
|
||||||
|
|
@ -1365,23 +1420,23 @@ retry:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(seekto(control, ctis, ctis->s[cti->streamno].last_head)))
|
if (unlikely(seekto(control, ctis, ctis->s[cti->streamno].last_head)))
|
||||||
fatal(control, "Failed to seekto in compthread %d\n", i);
|
fatal_goto(("Failed to seekto in compthread %d\n", i), error);
|
||||||
|
|
||||||
if (unlikely(write_val(control, ctis->cur_pos, write_len)))
|
if (unlikely(write_val(control, ctis->cur_pos, write_len)))
|
||||||
fatal(control, "Failed to write_val cur_pos in compthread %d\n", i);
|
fatal_goto(("Failed to write_val cur_pos in compthread %d\n", i), error);
|
||||||
|
|
||||||
if (ENCRYPT)
|
if (ENCRYPT)
|
||||||
rewrite_encrypted(control, ctis, ctis->s[cti->streamno].last_head - 17);
|
rewrite_encrypted(control, ctis, ctis->s[cti->streamno].last_head - 17);
|
||||||
|
|
||||||
ctis->s[cti->streamno].last_head = ctis->cur_pos + 1 + (write_len * 2) + (ENCRYPT ? SALT_LEN : 0);
|
ctis->s[cti->streamno].last_head = ctis->cur_pos + 1 + (write_len * 2) + (ENCRYPT ? SALT_LEN : 0);
|
||||||
if (unlikely(seekto(control, ctis, ctis->cur_pos)))
|
if (unlikely(seekto(control, ctis, ctis->cur_pos)))
|
||||||
fatal(control, "Failed to seekto cur_pos in compthread %d\n", i);
|
fatal_goto(("Failed to seekto cur_pos in compthread %d\n", i), error);
|
||||||
|
|
||||||
print_maxverbose("Thread %ld writing %lld compressed bytes from stream %d\n", i, padded_len, cti->streamno);
|
print_maxverbose("Thread %ld writing %lld compressed bytes from stream %d\n", i, padded_len, cti->streamno);
|
||||||
|
|
||||||
if (ENCRYPT) {
|
if (ENCRYPT) {
|
||||||
if (unlikely(write_val(control, 0, SALT_LEN)))
|
if (unlikely(write_val(control, 0, SALT_LEN)))
|
||||||
fatal(control, "Failed to write_buf header salt in compthread %d\n", i);
|
fatal_goto(("Failed to write_buf header salt in compthread %d\n", i), error);
|
||||||
ctis->cur_pos += SALT_LEN;
|
ctis->cur_pos += SALT_LEN;
|
||||||
ctis->s[cti->streamno].last_headofs = ctis->cur_pos;
|
ctis->s[cti->streamno].last_headofs = ctis->cur_pos;
|
||||||
}
|
}
|
||||||
|
|
@ -1390,19 +1445,19 @@ retry:
|
||||||
write_val(control, cti->c_len, write_len) ||
|
write_val(control, cti->c_len, write_len) ||
|
||||||
write_val(control, cti->s_len, write_len) ||
|
write_val(control, cti->s_len, write_len) ||
|
||||||
write_val(control, 0, write_len))) {
|
write_val(control, 0, write_len))) {
|
||||||
fatal(control, "Failed write in compthread %d\n", i);
|
fatal_goto(("Failed write in compthread %d\n", i), error);
|
||||||
}
|
}
|
||||||
ctis->cur_pos += 1 + (write_len * 3);
|
ctis->cur_pos += 1 + (write_len * 3);
|
||||||
|
|
||||||
if (ENCRYPT) {
|
if (ENCRYPT) {
|
||||||
get_rand(control, cti->salt, SALT_LEN);
|
if (unlikely(!get_rand(control, cti->salt, SALT_LEN))) goto error;
|
||||||
if (unlikely(write_buf(control, cti->salt, SALT_LEN)))
|
if (unlikely(write_buf(control, cti->salt, SALT_LEN)))
|
||||||
fatal(control, "Failed to write_buf block salt in compthread %d\n", i);
|
fatal_goto(("Failed to write_buf block salt in compthread %d\n", i), error);
|
||||||
lrz_encrypt(control, cti->s_buf, padded_len, cti->salt);
|
if (unlikely(!lrz_encrypt(control, cti->s_buf, padded_len, cti->salt))) goto error;
|
||||||
ctis->cur_pos += SALT_LEN;
|
ctis->cur_pos += SALT_LEN;
|
||||||
}
|
}
|
||||||
if (unlikely(write_buf(control, cti->s_buf, padded_len)))
|
if (unlikely(write_buf(control, cti->s_buf, padded_len)))
|
||||||
fatal(control, "Failed to write_buf s_buf in compthread %d\n", i);
|
fatal_goto(("Failed to write_buf s_buf in compthread %d\n", i), error);
|
||||||
|
|
||||||
ctis->cur_pos += padded_len;
|
ctis->cur_pos += padded_len;
|
||||||
free(cti->s_buf);
|
free(cti->s_buf);
|
||||||
|
|
@ -1413,12 +1468,13 @@ retry:
|
||||||
cond_broadcast(control, &output_cond);
|
cond_broadcast(control, &output_cond);
|
||||||
unlock_mutex(control, &output_lock);
|
unlock_mutex(control, &output_lock);
|
||||||
|
|
||||||
|
error:
|
||||||
unlock_mutex(control, &cti->mutex);
|
unlock_mutex(control, &cti->mutex);
|
||||||
|
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear_buffer(rzip_control *control, struct stream_info *sinfo, int streamno, int newbuf)
|
static bool clear_buffer(rzip_control *control, struct stream_info *sinfo, int streamno, int newbuf)
|
||||||
{
|
{
|
||||||
static long i = 0;
|
static long i = 0;
|
||||||
stream_thread_struct *s;
|
stream_thread_struct *s;
|
||||||
|
|
@ -1435,30 +1491,39 @@ static void clear_buffer(rzip_control *control, struct stream_info *sinfo, int s
|
||||||
i, cthread[i].s_len, streamno);
|
i, cthread[i].s_len, streamno);
|
||||||
|
|
||||||
s = malloc(sizeof(stream_thread_struct));
|
s = malloc(sizeof(stream_thread_struct));
|
||||||
if (unlikely(!s))
|
if (unlikely(!s)) {
|
||||||
fatal(control, "Unable to malloc in clear_buffer");
|
unlock_mutex(control, &cthread[i].mutex);
|
||||||
|
fatal_return(("Unable to malloc in clear_buffer"), false);
|
||||||
|
}
|
||||||
s->i = i;
|
s->i = i;
|
||||||
s->control = control;
|
s->control = control;
|
||||||
create_pthread(control, &threads[i], NULL, compthread, s);
|
if (unlikely((!create_pthread(control, &threads[i], NULL, compthread, s)) ||
|
||||||
detach_pthread(control, &threads[i]);
|
(!detach_pthread(control, &threads[i])))) {
|
||||||
|
unlock_mutex(control, &cthread[i].mutex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (newbuf) {
|
if (newbuf) {
|
||||||
/* The stream buffer has been given to the thread, allocate a
|
/* The stream buffer has been given to the thread, allocate a
|
||||||
* new one. */
|
* new one. */
|
||||||
sinfo->s[streamno].buf = malloc(sinfo->bufsize);
|
sinfo->s[streamno].buf = malloc(sinfo->bufsize);
|
||||||
if (unlikely(!sinfo->s[streamno].buf))
|
if (unlikely(!sinfo->s[streamno].buf)) {
|
||||||
fatal(control, "Unable to malloc buffer of size %lld in flush_buffer\n", sinfo->bufsize);
|
unlock_mutex(control, &cthread[i].mutex);
|
||||||
|
fatal_return(("Unable to malloc buffer of size %lld in flush_buffer\n", sinfo->bufsize), false);
|
||||||
|
}
|
||||||
sinfo->s[streamno].buflen = 0;
|
sinfo->s[streamno].buflen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (++i == control->threads)
|
if (++i == control->threads)
|
||||||
i = 0;
|
i = 0;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* flush out any data in a stream buffer */
|
/* flush out any data in a stream buffer */
|
||||||
void flush_buffer(rzip_control *control, struct stream_info *sinfo, int streamno)
|
bool flush_buffer(rzip_control *control, struct stream_info *sinfo, int streamno)
|
||||||
{
|
{
|
||||||
clear_buffer(control, sinfo, streamno, 1);
|
return clear_buffer(control, sinfo, streamno, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *ucompthread(void *data)
|
static void *ucompthread(void *data)
|
||||||
|
|
@ -1494,7 +1559,7 @@ retry:
|
||||||
ret = zpaq_decompress_buf(control, uci, i);
|
ret = zpaq_decompress_buf(control, uci, i);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
failure(control, "Dunno wtf decompression type to use!\n");
|
failure_return(("Dunno wtf decompression type to use!\n"), NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1503,7 +1568,7 @@ retry:
|
||||||
* parallel */
|
* parallel */
|
||||||
if (unlikely(ret)) {
|
if (unlikely(ret)) {
|
||||||
if (unlikely(waited))
|
if (unlikely(waited))
|
||||||
failure(control, "Failed to decompress in ucompthread\n");
|
failure_return(("Failed to decompress in ucompthread\n"), NULL);
|
||||||
print_maxverbose("Unable to decompress in parallel, waiting for previous thread to complete before trying again\n");
|
print_maxverbose("Unable to decompress in parallel, waiting for previous thread to complete before trying again\n");
|
||||||
/* We do not strictly need to wait for this, so it's used when
|
/* We do not strictly need to wait for this, so it's used when
|
||||||
* decompression fails due to inadequate memory to try again
|
* decompression fails due to inadequate memory to try again
|
||||||
|
|
@ -1536,7 +1601,7 @@ static int fill_buffer(rzip_control *control, struct stream_info *sinfo, int str
|
||||||
goto out;
|
goto out;
|
||||||
fill_another:
|
fill_another:
|
||||||
if (unlikely(ucthread[s->uthread_no].busy))
|
if (unlikely(ucthread[s->uthread_no].busy))
|
||||||
failure(control, "Trying to start a busy thread, this shouldn't happen!\n");
|
failure_return(("Trying to start a busy thread, this shouldn't happen!\n"), -1);
|
||||||
|
|
||||||
if (unlikely(read_seekto(control, sinfo, s->last_head)))
|
if (unlikely(read_seekto(control, sinfo, s->last_head)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -1576,7 +1641,7 @@ fill_another:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ENCRYPT) {
|
if (ENCRYPT) {
|
||||||
decrypt_header(control, enc_head, &c_type, &c_len, &u_len, &last_head);
|
if (unlikely(!decrypt_header(control, enc_head, &c_type, &c_len, &u_len, &last_head))) return -1;
|
||||||
if (unlikely(read_buf(control, sinfo->fd, blocksalt, SALT_LEN)))
|
if (unlikely(read_buf(control, sinfo->fd, blocksalt, SALT_LEN)))
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -1589,14 +1654,14 @@ fill_another:
|
||||||
|
|
||||||
s_buf = malloc(MAX(u_len, MIN_SIZE));
|
s_buf = malloc(MAX(u_len, MIN_SIZE));
|
||||||
if (unlikely(u_len && !s_buf))
|
if (unlikely(u_len && !s_buf))
|
||||||
fatal(control, "Unable to malloc buffer of size %lld in fill_buffer\n", u_len);
|
fatal_return(("Unable to malloc buffer of size %lld in fill_buffer\n", u_len), -1);
|
||||||
sinfo->ram_alloced += u_len;
|
sinfo->ram_alloced += u_len;
|
||||||
|
|
||||||
if (unlikely(read_buf(control, sinfo->fd, s_buf, padded_len)))
|
if (unlikely(read_buf(control, sinfo->fd, s_buf, padded_len)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (ENCRYPT)
|
if (ENCRYPT)
|
||||||
lrz_decrypt(control, s_buf, padded_len, blocksalt);
|
if (unlikely(!lrz_decrypt(control, s_buf, padded_len, blocksalt))) return -1;
|
||||||
|
|
||||||
ucthread[s->uthread_no].s_buf = s_buf;
|
ucthread[s->uthread_no].s_buf = s_buf;
|
||||||
ucthread[s->uthread_no].c_len = c_len;
|
ucthread[s->uthread_no].c_len = c_len;
|
||||||
|
|
@ -1612,10 +1677,13 @@ fill_another:
|
||||||
|
|
||||||
st = malloc(sizeof(stream_thread_struct));
|
st = malloc(sizeof(stream_thread_struct));
|
||||||
if (unlikely(!st))
|
if (unlikely(!st))
|
||||||
fatal(control, "Unable to malloc in fill_buffer");
|
fatal_return(("Unable to malloc in fill_buffer"), -1);
|
||||||
st->i = s->uthread_no;
|
st->i = s->uthread_no;
|
||||||
st->control = control;
|
st->control = control;
|
||||||
create_pthread(control, &threads[s->uthread_no], NULL, ucompthread, st);
|
if (unlikely(!create_pthread(control, &threads[s->uthread_no], NULL, ucompthread, st))) {
|
||||||
|
free(st);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (++s->uthread_no == s->base_thread + s->total_threads)
|
if (++s->uthread_no == s->base_thread + s->total_threads)
|
||||||
s->uthread_no = s->base_thread;
|
s->uthread_no = s->base_thread;
|
||||||
|
|
@ -1636,7 +1704,7 @@ out:
|
||||||
unlock_mutex(control, &output_lock);
|
unlock_mutex(control, &output_lock);
|
||||||
|
|
||||||
/* join_pthread here will make it wait till the data is ready */
|
/* join_pthread here will make it wait till the data is ready */
|
||||||
join_pthread(control, threads[s->unext_thread], NULL);
|
if (unlikely(!join_pthread(control, threads[s->unext_thread], NULL))) return -1;
|
||||||
ucthread[s->unext_thread].busy = 0;
|
ucthread[s->unext_thread].busy = 0;
|
||||||
|
|
||||||
print_maxverbose("Taking decompressed data from thread %ld\n", s->unext_thread);
|
print_maxverbose("Taking decompressed data from thread %ld\n", s->unext_thread);
|
||||||
|
|
@ -1668,7 +1736,7 @@ int write_stream(rzip_control *control, void *ss, int streamno, uchar *p, i64 le
|
||||||
|
|
||||||
/* Flush the buffer every sinfo->bufsize into one thread */
|
/* Flush the buffer every sinfo->bufsize into one thread */
|
||||||
if (sinfo->s[streamno].buflen == sinfo->bufsize)
|
if (sinfo->s[streamno].buflen == sinfo->bufsize)
|
||||||
flush_buffer(control, sinfo, streamno);
|
if (unlikely(!flush_buffer(control, sinfo, streamno))) return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1712,7 +1780,7 @@ int close_stream_out(rzip_control *control, void *ss)
|
||||||
|
|
||||||
for (i = 0; i < sinfo->num_streams; i++) {
|
for (i = 0; i < sinfo->num_streams; i++) {
|
||||||
if (sinfo->s[i].buflen)
|
if (sinfo->s[i].buflen)
|
||||||
clear_buffer(control, sinfo, i, 0);
|
if (unlikely(!clear_buffer(control, sinfo, i, 0))) return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ENCRYPT) {
|
if (ENCRYPT) {
|
||||||
|
|
@ -1779,14 +1847,16 @@ static int lzo_compresses(rzip_control *control, uchar *s_buf, i64 s_len)
|
||||||
return 1;
|
return 1;
|
||||||
wrkmem = (lzo_bytep) malloc(LZO1X_1_MEM_COMPRESS);
|
wrkmem = (lzo_bytep) malloc(LZO1X_1_MEM_COMPRESS);
|
||||||
if (unlikely(wrkmem == NULL))
|
if (unlikely(wrkmem == NULL))
|
||||||
fatal(control, "Unable to allocate wrkmem in lzo_compresses\n");
|
fatal_return(("Unable to allocate wrkmem in lzo_compresses\n"), 0);
|
||||||
|
|
||||||
in_len = MIN(test_len, buftest_size);
|
in_len = MIN(test_len, buftest_size);
|
||||||
dlen = STREAM_BUFSIZE + STREAM_BUFSIZE / 16 + 64 + 3;
|
dlen = STREAM_BUFSIZE + STREAM_BUFSIZE / 16 + 64 + 3;
|
||||||
|
|
||||||
c_buf = malloc(dlen);
|
c_buf = malloc(dlen);
|
||||||
if (unlikely(!c_buf))
|
if (unlikely(!c_buf)) {
|
||||||
fatal(control, "Unable to allocate c_buf in lzo_compresses\n");
|
free(wrkmem);
|
||||||
|
fatal_return(("Unable to allocate c_buf in lzo_compresses\n"), 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Test progressively larger blocks at a time and as soon as anything
|
/* Test progressively larger blocks at a time and as soon as anything
|
||||||
compressible is found, jump out as a success */
|
compressible is found, jump out as a success */
|
||||||
|
|
|
||||||
10
stream.h
10
stream.h
|
|
@ -23,16 +23,16 @@
|
||||||
#include "lrzip_private.h"
|
#include "lrzip_private.h"
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
void create_pthread(pthread_t *thread, pthread_attr_t *attr,
|
bool create_pthread(pthread_t *thread, pthread_attr_t *attr,
|
||||||
void * (*start_routine)(void *), void *arg);
|
void * (*start_routine)(void *), void *arg);
|
||||||
void join_pthread(pthread_t th, void **thread_return);
|
bool join_pthread(pthread_t th, void **thread_return);
|
||||||
ssize_t write_1g(rzip_control *control, void *buf, i64 len);
|
ssize_t write_1g(rzip_control *control, void *buf, i64 len);
|
||||||
ssize_t read_1g(rzip_control *control, int fd, void *buf, i64 len);
|
ssize_t read_1g(rzip_control *control, int fd, void *buf, i64 len);
|
||||||
void prepare_streamout_threads(rzip_control *control);
|
bool prepare_streamout_threads(rzip_control *control);
|
||||||
void close_streamout_threads(rzip_control *control);
|
bool close_streamout_threads(rzip_control *control);
|
||||||
void *open_stream_out(rzip_control *control, int f, unsigned int n, i64 chunk_limit, char cbytes);
|
void *open_stream_out(rzip_control *control, int f, unsigned int n, i64 chunk_limit, char cbytes);
|
||||||
void *open_stream_in(rzip_control *control, int f, int n, char cbytes);
|
void *open_stream_in(rzip_control *control, int f, int n, char cbytes);
|
||||||
void flush_buffer(rzip_control *control, struct stream_info *sinfo, int stream);
|
bool flush_buffer(rzip_control *control, struct stream_info *sinfo, int stream);
|
||||||
int write_stream(rzip_control *control, void *ss, int streamno, uchar *p, i64 len);
|
int write_stream(rzip_control *control, void *ss, int streamno, uchar *p, i64 len);
|
||||||
i64 read_stream(rzip_control *control, void *ss, int streamno, uchar *p, i64 len);
|
i64 read_stream(rzip_control *control, void *ss, int streamno, uchar *p, i64 len);
|
||||||
int close_stream_out(rzip_control *control, void *ss);
|
int close_stream_out(rzip_control *control, void *ss);
|
||||||
|
|
|
||||||
89
util.c
89
util.c
|
|
@ -91,7 +91,7 @@ void unlink_files(rzip_control *control)
|
||||||
unlink(control->util_infile);
|
unlink(control->util_infile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fatal_exit(rzip_control *control)
|
void fatal_exit(rzip_control *control)
|
||||||
{
|
{
|
||||||
struct termios termios_p;
|
struct termios termios_p;
|
||||||
|
|
||||||
|
|
@ -103,35 +103,7 @@ static void fatal_exit(rzip_control *control)
|
||||||
unlink_files(control);
|
unlink_files(control);
|
||||||
fprintf(control->outputfile, "Fatal error - exiting\n");
|
fprintf(control->outputfile, "Fatal error - exiting\n");
|
||||||
fflush(control->outputfile);
|
fflush(control->outputfile);
|
||||||
abort();
|
exit(1);
|
||||||
}
|
|
||||||
|
|
||||||
/* Failure when there is likely to be a meaningful error in perror */
|
|
||||||
void fatal(const rzip_control *control, const char *format, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
if (format) {
|
|
||||||
va_start(ap, format);
|
|
||||||
vfprintf(stderr, format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
perror(NULL);
|
|
||||||
fatal_exit((rzip_control*)control);
|
|
||||||
}
|
|
||||||
|
|
||||||
void failure(const rzip_control *control, const char *format, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
if (format) {
|
|
||||||
va_start(ap, format);
|
|
||||||
vfprintf(stderr, format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
fatal_exit((rzip_control*)control);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_overhead(rzip_control *control)
|
void setup_overhead(rzip_control *control)
|
||||||
|
|
@ -178,7 +150,7 @@ void round_to_page(i64 *size)
|
||||||
*size = PAGE_SIZE;
|
*size = PAGE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_rand(rzip_control *control, uchar *buf, int len)
|
bool get_rand(rzip_control *control, uchar *buf, int len)
|
||||||
{
|
{
|
||||||
int fd, i;
|
int fd, i;
|
||||||
|
|
||||||
|
|
@ -188,26 +160,20 @@ void get_rand(rzip_control *control, uchar *buf, int len)
|
||||||
buf[i] = (uchar)random();
|
buf[i] = (uchar)random();
|
||||||
} else {
|
} else {
|
||||||
if (unlikely(read(fd, buf, len) != len))
|
if (unlikely(read(fd, buf, len) != len))
|
||||||
fatal(control, "Failed to read fd in get_rand\n");
|
fatal_return(("Failed to read fd in get_rand\n"), false);
|
||||||
if (unlikely(close(fd)))
|
if (unlikely(close(fd)))
|
||||||
fatal(control, "Failed to close fd in get_rand\n");
|
fatal_return(("Failed to close fd in get_rand\n"), false);
|
||||||
}
|
}
|
||||||
}
|
return true;
|
||||||
|
}bool read_config(rzip_control *control)
|
||||||
void read_config(rzip_control *control)
|
|
||||||
{
|
{
|
||||||
/* check for lrzip.conf in ., $HOME/.lrzip and /etc/lrzip */
|
/* check for lrzip.conf in ., $HOME/.lrzip and /etc/lrzip */
|
||||||
char *HOME, *homeconf;
|
char *HOME, homeconf[255];
|
||||||
char *parametervalue;
|
char *parametervalue;
|
||||||
char *parameter;
|
char *parameter;
|
||||||
char *line;
|
char line[255];
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
line = malloc(255);
|
|
||||||
homeconf = malloc(255);
|
|
||||||
if (line == NULL || homeconf == NULL)
|
|
||||||
fatal(control, "Fatal Memory Error in read_config");
|
|
||||||
|
|
||||||
fp = fopen("lrzip.conf", "r");
|
fp = fopen("lrzip.conf", "r");
|
||||||
if (fp)
|
if (fp)
|
||||||
fprintf(control->msgout, "Using configuration file ./lrzip.conf\n");
|
fprintf(control->msgout, "Using configuration file ./lrzip.conf\n");
|
||||||
|
|
@ -219,15 +185,13 @@ void read_config(rzip_control *control)
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
HOME=getenv("HOME");
|
HOME=getenv("HOME");
|
||||||
if (HOME) {
|
if (HOME) {
|
||||||
strcpy(homeconf, HOME);
|
snprintf(homeconf, sizeof(homeconf), "%s/.lrzip/lrzip.conf", HOME);
|
||||||
strcat(homeconf,"/.lrzip/lrzip.conf");
|
|
||||||
fp = fopen(homeconf, "r");
|
fp = fopen(homeconf, "r");
|
||||||
if (fp)
|
if (fp)
|
||||||
fprintf(control->msgout, "Using configuration file %s\n", homeconf);
|
fprintf(control->msgout, "Using configuration file %s\n", homeconf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fp == NULL)
|
if (fp == NULL) return true;
|
||||||
goto out;
|
|
||||||
|
|
||||||
/* if we get here, we have a file. read until no more. */
|
/* if we get here, we have a file. read until no more. */
|
||||||
|
|
||||||
|
|
@ -257,11 +221,11 @@ void read_config(rzip_control *control)
|
||||||
} else if (isparameter(parameter, "compressionlevel")) {
|
} else if (isparameter(parameter, "compressionlevel")) {
|
||||||
control->compression_level = atoi(parametervalue);
|
control->compression_level = atoi(parametervalue);
|
||||||
if ( control->compression_level < 1 || control->compression_level > 9 )
|
if ( control->compression_level < 1 || control->compression_level > 9 )
|
||||||
failure(control, "CONF.FILE error. Compression Level must between 1 and 9");
|
failure_return(("CONF.FILE error. Compression Level must between 1 and 9"), false);
|
||||||
} else if (isparameter(parameter, "compressionmethod")) {
|
} else if (isparameter(parameter, "compressionmethod")) {
|
||||||
/* valid are rzip, gzip, bzip2, lzo, lzma (default), and zpaq */
|
/* valid are rzip, gzip, bzip2, lzo, lzma (default), and zpaq */
|
||||||
if (control->flags & FLAG_NOT_LZMA)
|
if (control->flags & FLAG_NOT_LZMA)
|
||||||
failure(control, "CONF.FILE error. Can only specify one compression method");
|
failure_return(("CONF.FILE error. Can only specify one compression method"), false);
|
||||||
if (isparameter(parametervalue, "bzip2"))
|
if (isparameter(parametervalue, "bzip2"))
|
||||||
control->flags |= FLAG_BZIP2_COMPRESS;
|
control->flags |= FLAG_BZIP2_COMPRESS;
|
||||||
else if (isparameter(parametervalue, "gzip"))
|
else if (isparameter(parametervalue, "gzip"))
|
||||||
|
|
@ -273,7 +237,7 @@ void read_config(rzip_control *control)
|
||||||
else if (isparameter(parametervalue, "zpaq"))
|
else if (isparameter(parametervalue, "zpaq"))
|
||||||
control->flags |= FLAG_ZPAQ_COMPRESS;
|
control->flags |= FLAG_ZPAQ_COMPRESS;
|
||||||
else if (!isparameter(parametervalue, "lzma")) /* oops, not lzma! */
|
else if (!isparameter(parametervalue, "lzma")) /* oops, not lzma! */
|
||||||
failure(control, "CONF.FILE error. Invalid compression method %s specified\n",parametervalue);
|
failure_return(("CONF.FILE error. Invalid compression method %s specified\n",parametervalue), false);
|
||||||
} else if (isparameter(parameter, "lzotest")) {
|
} else if (isparameter(parameter, "lzotest")) {
|
||||||
/* default is yes */
|
/* default is yes */
|
||||||
if (isparameter(parametervalue, "no"))
|
if (isparameter(parametervalue, "no"))
|
||||||
|
|
@ -289,13 +253,13 @@ void read_config(rzip_control *control)
|
||||||
} else if (isparameter(parameter, "outputdirectory")) {
|
} else if (isparameter(parameter, "outputdirectory")) {
|
||||||
control->outdir = malloc(strlen(parametervalue) + 2);
|
control->outdir = malloc(strlen(parametervalue) + 2);
|
||||||
if (!control->outdir)
|
if (!control->outdir)
|
||||||
fatal(control, "Fatal Memory Error in read_config");
|
fatal_return(("Fatal Memory Error in read_config"), false);
|
||||||
strcpy(control->outdir, parametervalue);
|
strcpy(control->outdir, parametervalue);
|
||||||
if (strcmp(parametervalue + strlen(parametervalue) - 1, "/"))
|
if (strcmp(parametervalue + strlen(parametervalue) - 1, "/"))
|
||||||
strcat(control->outdir, "/");
|
strcat(control->outdir, "/");
|
||||||
} else if (isparameter(parameter,"verbosity")) {
|
} else if (isparameter(parameter,"verbosity")) {
|
||||||
if (control->flags & FLAG_VERBOSE)
|
if (control->flags & FLAG_VERBOSE)
|
||||||
failure(control, "CONF.FILE error. Verbosity already defined.");
|
failure_return(("CONF.FILE error. Verbosity already defined."), false);
|
||||||
if (isparameter(parametervalue, "yes"))
|
if (isparameter(parametervalue, "yes"))
|
||||||
control->flags |= FLAG_VERBOSITY;
|
control->flags |= FLAG_VERBOSITY;
|
||||||
else if (isparameter(parametervalue,"max"))
|
else if (isparameter(parametervalue,"max"))
|
||||||
|
|
@ -309,7 +273,7 @@ void read_config(rzip_control *control)
|
||||||
} else if (isparameter(parameter,"nice")) {
|
} else if (isparameter(parameter,"nice")) {
|
||||||
control->nice_val = atoi(parametervalue);
|
control->nice_val = atoi(parametervalue);
|
||||||
if (control->nice_val < -20 || control->nice_val > 19)
|
if (control->nice_val < -20 || control->nice_val > 19)
|
||||||
failure(control, "CONF.FILE error. Nice must be between -20 and 19");
|
failure_return(("CONF.FILE error. Nice must be between -20 and 19"), false);
|
||||||
} else if (isparameter(parameter, "keepbroken")) {
|
} else if (isparameter(parameter, "keepbroken")) {
|
||||||
if (isparameter(parametervalue, "yes" ))
|
if (isparameter(parametervalue, "yes" ))
|
||||||
control->flags |= FLAG_KEEP_BROKEN;
|
control->flags |= FLAG_KEEP_BROKEN;
|
||||||
|
|
@ -324,7 +288,7 @@ void read_config(rzip_control *control)
|
||||||
} else if (isparameter(parameter, "tmpdir")) {
|
} else if (isparameter(parameter, "tmpdir")) {
|
||||||
control->tmpdir = realloc(NULL, strlen(parametervalue) + 2);
|
control->tmpdir = realloc(NULL, strlen(parametervalue) + 2);
|
||||||
if (!control->tmpdir)
|
if (!control->tmpdir)
|
||||||
fatal(control, "Fatal Memory Error in read_config");
|
fatal_return(("Fatal Memory Error in read_config"), false);
|
||||||
strcpy(control->tmpdir, parametervalue);
|
strcpy(control->tmpdir, parametervalue);
|
||||||
if (strcmp(parametervalue + strlen(parametervalue) - 1, "/"))
|
if (strcmp(parametervalue + strlen(parametervalue) - 1, "/"))
|
||||||
strcat(control->tmpdir, "/");
|
strcat(control->tmpdir, "/");
|
||||||
|
|
@ -338,11 +302,7 @@ void read_config(rzip_control *control)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(fclose(fp)))
|
if (unlikely(fclose(fp)))
|
||||||
fatal(control, "Failed to fclose fp in read_config\n");
|
fatal_return(("Failed to fclose fp in read_config\n"), false);
|
||||||
out:
|
|
||||||
/* clean up */
|
|
||||||
free(line);
|
|
||||||
free(homeconf);
|
|
||||||
|
|
||||||
/* fprintf(stderr, "\nWindow = %d \
|
/* fprintf(stderr, "\nWindow = %d \
|
||||||
\nCompression Level = %d \
|
\nCompression Level = %d \
|
||||||
|
|
@ -350,6 +310,7 @@ out:
|
||||||
\nOutput Directory = %s \
|
\nOutput Directory = %s \
|
||||||
\nFlags = %d\n", control->window,control->compression_level, control->threshold, control->outdir, control->flags);
|
\nFlags = %d\n", control->window,control->compression_level, control->threshold, control->outdir, control->flags);
|
||||||
*/
|
*/
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xor128 (void *pa, const void *pb)
|
static void xor128 (void *pa, const void *pb)
|
||||||
|
|
@ -380,7 +341,7 @@ static void lrz_keygen(const rzip_control *control, const uchar *salt, uchar *ke
|
||||||
munlock(buf, sizeof(buf));
|
munlock(buf, sizeof(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
void lrz_crypt(const rzip_control *control, uchar *buf, i64 len, const uchar *salt, int encrypt)
|
bool lrz_crypt(const rzip_control *control, uchar *buf, i64 len, const uchar *salt, int encrypt)
|
||||||
{
|
{
|
||||||
/* Encryption requires CBC_LEN blocks so we can use ciphertext
|
/* Encryption requires CBC_LEN blocks so we can use ciphertext
|
||||||
* stealing to not have to pad the block */
|
* stealing to not have to pad the block */
|
||||||
|
|
@ -388,6 +349,7 @@ void lrz_crypt(const rzip_control *control, uchar *buf, i64 len, const uchar *sa
|
||||||
uchar tmp0[CBC_LEN], tmp1[CBC_LEN];
|
uchar tmp0[CBC_LEN], tmp1[CBC_LEN];
|
||||||
aes_context aes_ctx;
|
aes_context aes_ctx;
|
||||||
i64 N, M;
|
i64 N, M;
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
/* Generate unique key and IV for each block of data based on salt */
|
/* Generate unique key and IV for each block of data based on salt */
|
||||||
mlock(&aes_ctx, sizeof(aes_ctx));
|
mlock(&aes_ctx, sizeof(aes_ctx));
|
||||||
|
|
@ -402,7 +364,7 @@ void lrz_crypt(const rzip_control *control, uchar *buf, i64 len, const uchar *sa
|
||||||
if (encrypt == LRZ_ENCRYPT) {
|
if (encrypt == LRZ_ENCRYPT) {
|
||||||
print_maxverbose("Encrypting data \n");
|
print_maxverbose("Encrypting data \n");
|
||||||
if (unlikely(aes_setkey_enc(&aes_ctx, key, 128)))
|
if (unlikely(aes_setkey_enc(&aes_ctx, key, 128)))
|
||||||
failure(control, "Failed to aes_setkey_enc in lrz_crypt\n");
|
failure_goto(("Failed to aes_setkey_enc in lrz_crypt\n"), error);
|
||||||
aes_crypt_cbc(&aes_ctx, AES_ENCRYPT, N, iv, buf, buf);
|
aes_crypt_cbc(&aes_ctx, AES_ENCRYPT, N, iv, buf, buf);
|
||||||
|
|
||||||
if (M) {
|
if (M) {
|
||||||
|
|
@ -415,7 +377,7 @@ void lrz_crypt(const rzip_control *control, uchar *buf, i64 len, const uchar *sa
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (unlikely(aes_setkey_dec(&aes_ctx, key, 128)))
|
if (unlikely(aes_setkey_dec(&aes_ctx, key, 128)))
|
||||||
failure(control, "Failed to aes_setkey_dec in lrz_crypt\n");
|
failure_goto(("Failed to aes_setkey_dec in lrz_crypt\n"), error);
|
||||||
print_maxverbose("Decrypting data \n");
|
print_maxverbose("Decrypting data \n");
|
||||||
if (M) {
|
if (M) {
|
||||||
aes_crypt_cbc(&aes_ctx, AES_DECRYPT, N - CBC_LEN,
|
aes_crypt_cbc(&aes_ctx, AES_DECRYPT, N - CBC_LEN,
|
||||||
|
|
@ -435,12 +397,15 @@ void lrz_crypt(const rzip_control *control, uchar *buf, i64 len, const uchar *sa
|
||||||
iv, buf, buf);
|
iv, buf, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = true;
|
||||||
|
error:
|
||||||
memset(&aes_ctx, 0, sizeof(aes_ctx));
|
memset(&aes_ctx, 0, sizeof(aes_ctx));
|
||||||
memset(iv, 0, HASH_LEN);
|
memset(iv, 0, HASH_LEN);
|
||||||
memset(key, 0, HASH_LEN);
|
memset(key, 0, HASH_LEN);
|
||||||
munlock(&aes_ctx, sizeof(aes_ctx));
|
munlock(&aes_ctx, sizeof(aes_ctx));
|
||||||
munlock(iv, HASH_LEN);
|
munlock(iv, HASH_LEN);
|
||||||
munlock(key, HASH_LEN);
|
munlock(key, HASH_LEN);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lrz_stretch(rzip_control *control)
|
void lrz_stretch(rzip_control *control)
|
||||||
|
|
|
||||||
70
util.h
70
util.h
|
|
@ -20,33 +20,85 @@
|
||||||
#define LRZIP_UTIL_H
|
#define LRZIP_UTIL_H
|
||||||
|
|
||||||
#include "lrzip_private.h"
|
#include "lrzip_private.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
void register_infile(rzip_control *control, const char *name, char delete);
|
void register_infile(rzip_control *control, const char *name, char delete);
|
||||||
void register_outfile(rzip_control *control, const char *name, char delete);
|
void register_outfile(rzip_control *control, const char *name, char delete);
|
||||||
void unlink_files(rzip_control *control);
|
void unlink_files(rzip_control *control);
|
||||||
void register_outputfile(rzip_control *control, FILE *f);
|
void register_outputfile(rzip_control *control, FILE *f);
|
||||||
void fatal(const rzip_control *control, const char *format, ...);
|
void fatal_exit(rzip_control *control);
|
||||||
void failure(const rzip_control *control, const char *format, ...);
|
/* Failure when there is likely to be a meaningful error in perror */
|
||||||
|
static inline void fatal(const rzip_control *control, unsigned int line, const char *file, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
if (!control->log_cb) {
|
||||||
|
vfprintf(stderr, format, ap);
|
||||||
|
perror(NULL);
|
||||||
|
} else
|
||||||
|
control->log_cb(control->log_data, line, file, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
if (!control->library_mode)
|
||||||
|
fatal_exit((rzip_control*)control);
|
||||||
|
}
|
||||||
|
#ifdef fatal
|
||||||
|
# undef fatal
|
||||||
|
#endif
|
||||||
|
#define fatal(stuff...) fatal(control, __LINE__, __FILE__, stuff)
|
||||||
|
#define fatal_return(stuff, ...) do { \
|
||||||
|
fatal stuff; \
|
||||||
|
return __VA_ARGS__; \
|
||||||
|
} while (0)
|
||||||
|
#define fatal_goto(stuff, label) do { \
|
||||||
|
fatal stuff; \
|
||||||
|
goto label; \
|
||||||
|
} while (0)
|
||||||
|
static inline void failure(const rzip_control *control, unsigned int line, const char *file, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
if (!control->log_cb)
|
||||||
|
vfprintf(stderr, format, ap);
|
||||||
|
else
|
||||||
|
control->log_cb(control->log_data, line, file, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
if (!control->library_mode)
|
||||||
|
fatal_exit((rzip_control*)control);
|
||||||
|
}
|
||||||
|
#ifdef failure
|
||||||
|
# undef failure
|
||||||
|
#endif
|
||||||
|
#define failure(stuff...) failure(control, __LINE__, __FILE__, stuff)
|
||||||
|
#define failure_return(stuff, ...) do { \
|
||||||
|
failure stuff; \
|
||||||
|
return __VA_ARGS__; \
|
||||||
|
} while (0)
|
||||||
|
#define failure_goto(stuff, label) do { \
|
||||||
|
failure stuff; \
|
||||||
|
goto label; \
|
||||||
|
} while (0)
|
||||||
void setup_overhead(rzip_control *control);
|
void setup_overhead(rzip_control *control);
|
||||||
void setup_ram(rzip_control *control);
|
void setup_ram(rzip_control *control);
|
||||||
void round_to_page(i64 *size);
|
void round_to_page(i64 *size);
|
||||||
void get_rand(rzip_control *control, uchar *buf, int len);
|
bool get_rand(rzip_control *control, uchar *buf, int len);
|
||||||
void read_config(rzip_control *control);
|
bool read_config(rzip_control *control);
|
||||||
void lrz_stretch(rzip_control *control);
|
void lrz_stretch(rzip_control *control);
|
||||||
void lrz_stretch2(rzip_control *control);
|
void lrz_stretch2(rzip_control *control);
|
||||||
void lrz_crypt(const rzip_control *control, uchar *buf, i64 len, const uchar *salt, int encrypt);
|
bool lrz_crypt(const rzip_control *control, uchar *buf, i64 len, const uchar *salt, int encrypt);
|
||||||
|
|
||||||
#define LRZ_DECRYPT (0)
|
#define LRZ_DECRYPT (0)
|
||||||
#define LRZ_ENCRYPT (1)
|
#define LRZ_ENCRYPT (1)
|
||||||
|
|
||||||
static inline void lrz_encrypt(const rzip_control *control, uchar *buf, i64 len, const uchar *salt)
|
static inline bool lrz_encrypt(const rzip_control *control, uchar *buf, i64 len, const uchar *salt)
|
||||||
{
|
{
|
||||||
lrz_crypt(control, buf, len, salt, LRZ_ENCRYPT);
|
return lrz_crypt(control, buf, len, salt, LRZ_ENCRYPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void lrz_decrypt(const rzip_control *control, uchar *buf, i64 len, const uchar *salt)
|
static inline bool lrz_decrypt(const rzip_control *control, uchar *buf, i64 len, const uchar *salt)
|
||||||
{
|
{
|
||||||
lrz_crypt(control, buf, len, salt, LRZ_DECRYPT);
|
return lrz_crypt(control, buf, len, salt, LRZ_DECRYPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue