diff --git a/lrzip.c b/lrzip.c index 15673e1..0c3463e 100644 --- a/lrzip.c +++ b/lrzip.c @@ -52,7 +52,6 @@ #include "runzip.h" #include "util.h" #include "stream.h" -#include "liblrzip.h" /* flag defines */ #define MAGIC_LEN (24) @@ -319,14 +318,14 @@ static bool fwrite_stdout(rzip_control *control, void *buf, i64 len) ret = one_g; else ret = len; - ret = fwrite(offset_buf, 1, ret, stdout); + ret = fwrite(offset_buf, 1, ret, control->outFILE); if (unlikely(ret <= 0)) fatal_return(("Failed to fwrite in fwrite_stdout\n"), false); len -= ret; offset_buf += ret; total += ret; } - fflush(stdout); + fflush(control->outFILE); return true; } @@ -375,10 +374,10 @@ bool dump_tmpoutfile(rzip_control *control, int fd_out) rewind(tmpoutfp); if (!TEST_ONLY) { - print_verbose("Dumping temporary file to stdout.\n"); + print_verbose("Dumping temporary file to control->outFILE.\n"); while ((tmpchar = fgetc(tmpoutfp)) != EOF) putchar(tmpchar); - fflush(stdout); + fflush(control->outFILE); rewind(tmpoutfp); } @@ -564,7 +563,7 @@ static bool get_hash(rzip_control *control, int make_hash) mlock(control->hash, HASH_LEN); if (control->pass_cb) { - control->pass_cb(control->pass_data, passphrase, PASS_LEN); + control->pass_cb(control->pass_data, passphrase, PASS_LEN - SALT_LEN); if (!passphrase[0]) { fatal("Supplied password was null!"); munlock(passphrase, PASS_LEN); @@ -574,6 +573,7 @@ static bool get_hash(rzip_control *control, int make_hash) release_hashes(control); return false; } + control->salt_pass_len = strlen(passphrase) + SALT_LEN; } else { /* Disable stdin echo to screen */ tcgetattr(fileno(stdin), &termios_p); @@ -1194,6 +1194,7 @@ bool initialize_control(rzip_control *control) memset(control, 0, sizeof(rzip_control)); control->msgout = stderr; + control->msgerr = stderr; register_outputfile(control, control->msgout); control->flags = FLAG_SHOW_PROGRESS | FLAG_KEEP_FILES | FLAG_THRESHOLD; control->suffix = strdup(".lrz"); diff --git a/lrzip_private.h b/lrzip_private.h index 3b8b98e..3dcb939 100644 --- a/lrzip_private.h +++ b/lrzip_private.h @@ -27,6 +27,7 @@ #include #include #include +#include #ifdef HAVE_STRING_H # include #endif @@ -52,6 +53,10 @@ extern "C" void *alloca (size_t); #endif +#ifndef MD5_DIGEST_SIZE +# define MD5_DIGEST_SIZE 16 +#endif + #define free(X) do { free((X)); (X) = NULL; } while (0) #ifndef strdupa @@ -262,31 +267,6 @@ typedef struct md5_ctx md5_ctx; #define TMP_INBUF (control->flags & FLAG_TMP_INBUF) #define ENCRYPT (control->flags & FLAG_ENCRYPT) -#define print_output(format, args...) do {\ - fprintf(control->msgout, format, ##args); \ - fflush(control->msgout); \ -} while (0) - -#define print_progress(format, args...) do {\ - if (SHOW_PROGRESS) \ - print_output(format, ##args); \ -} while (0) - -#define print_verbose(format, args...) do {\ - if (VERBOSE) \ - print_output(format, ##args); \ -} while (0) - -#define print_maxverbose(format, args...) do {\ - if (MAX_VERBOSE) \ - print_output(format, ##args); \ -} while (0) - - -#define print_err(format, args...) do {\ - fprintf(stderr, format, ##args); \ -} while (0) - /* Structure to save state of computation between the single steps. */ struct md5_ctx @@ -303,8 +283,10 @@ struct md5_ctx struct rzip_control { char *infile; + FILE *inFILE; // if a FILE is being read from char *outname; char *outfile; + FILE *outFILE; // if a FILE is being written to char *outdir; char *tmpdir; // when stdin, stdout, or test used uchar *tmp_outbuf; // Temporary file storage for stdout @@ -318,6 +300,7 @@ struct rzip_control { i64 in_len; i64 in_maxlen; FILE *msgout; //stream for output messages + FILE *msgerr; //stream for output errors char *suffix; uchar compression_level; i64 overhead; // compressor overhead @@ -349,6 +332,7 @@ struct rzip_control { unsigned char eof; unsigned char magic_written; md5_ctx ctx; + uchar md5_resblock[MD5_DIGEST_SIZE]; i64 md5_read; // How far into the file the md5 has done so far const char *util_infile; char delete_infile; @@ -356,7 +340,8 @@ struct rzip_control { char delete_outfile; FILE *outputfile; char library_mode : 1; - void (*log_cb)(void *, unsigned int, const char *, const char *, va_list); + int log_level; + void (*log_cb)(void *data, unsigned int level, unsigned int line, const char *file, const char *func, const char *format, va_list); void *log_data; }; @@ -387,4 +372,60 @@ struct stream_info { int chunks; char chunk_bytes; }; + +static inline void print_stuff(const rzip_control *control, int level, unsigned int line, const char *file, const char *func, const char *format, ...) +{ + va_list ap; + if (control->library_mode && control->log_cb && (control->log_level >= level)) { + va_start(ap, format); + control->log_cb(control->log_data, level, line, file, func, format, ap); + va_end(ap); + } else if (control->msgout) { + va_start(ap, format); + vfprintf(control->msgout, format, ap); + fflush(control->msgout); + va_end(ap); + } +} + +static inline void print_err(const rzip_control *control, unsigned int line, const char *file, const char *func, const char *format, ...) +{ + va_list ap; + if (control->library_mode && control->log_cb && (control->log_level >= 0)) { + va_start(ap, format); + control->log_cb(control->log_data, 0, line, file, func, format, ap); + va_end(ap); + } else if (control->msgerr) { + va_start(ap, format); + vfprintf(control->msgerr, format, ap); + va_end(ap); + } +} + +#define print_stuff(level, format, args...) do {\ + print_stuff(control, level, __LINE__, __FILE__, __func__, format, ##args); \ +} while (0) + +#define print_output(format, args...) do {\ + print_stuff(1, format, ##args); \ +} while (0) + +#define print_progress(format, args...) do {\ + if (SHOW_PROGRESS) \ + print_stuff(2, format, ##args); \ +} while (0) + +#define print_verbose(format, args...) do {\ + if (VERBOSE) \ + print_stuff(3, format, ##args); \ +} while (0) + +#define print_maxverbose(format, args...) do {\ + if (MAX_VERBOSE) \ + print_stuff(4, format, ##args); \ +} while (0) + +#define print_err(format, args...) do {\ + print_err(control, __LINE__, __FILE__, __func__, format, ##args); \ +} while (0) #endif diff --git a/main.c b/main.c index 122cc8b..bae4bb6 100644 --- a/main.c +++ b/main.c @@ -49,7 +49,6 @@ # include #endif -#include "liblrzip.h" #include "rzip.h" #include "lrzip.h" #include "util.h" @@ -284,6 +283,7 @@ int main(int argc, char *argv[]) if (unlikely(STDOUT)) failure("Cannot specify an output filename when outputting to stdout\n"); control->outname = optarg; + free(control->suffix); control->suffix = ""; break; case 'O': @@ -311,6 +311,7 @@ int main(int argc, char *argv[]) failure("Specified output filename already, can't specify an extension.\n"); if (unlikely(STDOUT)) failure("Cannot specify a filename suffix when outputting to stdout\n"); + free(control->suffix); control->suffix = optarg; break; case 't': @@ -410,6 +411,7 @@ int main(int argc, char *argv[]) if (control->outname && (strcmp(control->outname, "-") == 0)) { control->flags |= FLAG_STDOUT; + control->outFILE = stdout; control->msgout = stderr; register_outputfile(control, control->msgout); } @@ -419,6 +421,7 @@ int main(int argc, char *argv[]) if (!control->outname && STDIN) { control->flags |= FLAG_STDOUT; control->msgout = stderr; + control->outFILE = stdout; register_outputfile(control, control->msgout); } @@ -426,6 +429,7 @@ int main(int argc, char *argv[]) control->msgout = stdout; register_outputfile(control, control->msgout); } + if (STDIN) control->inFILE = stdin; /* Implement signal handler only once flags are set */ handler.sa_handler = &sighandler; sigaction(SIGTERM, &handler, 0); diff --git a/runzip.c b/runzip.c index a6cd358..0a2ee82 100644 --- a/runzip.c +++ b/runzip.c @@ -45,7 +45,6 @@ #include "stream.h" #include "util.h" #include "lrzip.h" -#include "liblrzip.h" /* needed for CRC routines */ #include "lzma/C/7zCrc.h" @@ -364,7 +363,6 @@ static i64 runzip_chunk(rzip_control *control, int fd_in, i64 expected_size, i64 */ i64 runzip_fd(rzip_control *control, int fd_in, int fd_out, int fd_hist, i64 expected_size) { - uchar md5_resblock[MD5_DIGEST_SIZE]; uchar md5_stored[MD5_DIGEST_SIZE]; struct timeval start,end; i64 total = 0, u; @@ -395,7 +393,7 @@ i64 runzip_fd(rzip_control *control, int fd_in, int fd_out, int fd_hist, i64 exp if (!NO_MD5) { int i,j; - md5_finish_ctx (&control->ctx, md5_resblock); + md5_finish_ctx (&control->ctx, control->md5_resblock); if (HAS_MD5) { i64 fdinend = seekto_fdinend(control); @@ -409,13 +407,13 @@ i64 runzip_fd(rzip_control *control, int fd_in, int fd_out, int fd_hist, i64 exp if (ENCRYPT) if (unlikely(!lrz_decrypt(control, md5_stored, MD5_DIGEST_SIZE, control->salt_pass))) return -1; for (i = 0; i < MD5_DIGEST_SIZE; i++) - if (md5_stored[i] != md5_resblock[i]) { + if (md5_stored[i] != control->md5_resblock[i]) { print_output("MD5 CHECK FAILED.\nStored:"); for (j = 0; j < MD5_DIGEST_SIZE; j++) print_output("%02x", md5_stored[j] & 0xFF); print_output("\nOutput file:"); for (j = 0; j < MD5_DIGEST_SIZE; j++) - print_output("%02x", md5_resblock[j] & 0xFF); + print_output("%02x", control->md5_resblock[j] & 0xFF); failure_return(("\n"), -1); } } @@ -423,7 +421,7 @@ i64 runzip_fd(rzip_control *control, int fd_in, int fd_out, int fd_hist, i64 exp if (HASH_CHECK || MAX_VERBOSE) { print_output("MD5: "); for (i = 0; i < MD5_DIGEST_SIZE; i++) - print_output("%02x", md5_resblock[i] & 0xFF); + print_output("%02x", control->md5_resblock[i] & 0xFF); print_output("\n"); } @@ -433,22 +431,22 @@ i64 runzip_fd(rzip_control *control, int fd_in, int fd_out, int fd_hist, i64 exp if (TMP_OUTBUF) close_tmpoutbuf(control); - memcpy(md5_stored, md5_resblock, MD5_DIGEST_SIZE); + memcpy(md5_stored, control->md5_resblock, MD5_DIGEST_SIZE); if (unlikely(seekto_fdhist(control, 0) == -1)) fatal_return(("Failed to seekto_fdhist in runzip_fd\n"), -1); if (unlikely((md5_fstream = fdopen(fd_hist, "r")) == NULL)) 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, control->md5_resblock))) fatal_return(("Failed to md5_stream in runzip_fd\n"), -1); /* We don't close the file here as it's closed in main */ for (i = 0; i < MD5_DIGEST_SIZE; i++) - if (md5_stored[i] != md5_resblock[i]) { + if (md5_stored[i] != control->md5_resblock[i]) { print_output("MD5 CHECK FAILED.\nStored:"); for (j = 0; j < MD5_DIGEST_SIZE; j++) print_output("%02x", md5_stored[j] & 0xFF); print_output("\nOutput file:"); for (j = 0; j < MD5_DIGEST_SIZE; j++) - print_output("%02x", md5_resblock[j] & 0xFF); + print_output("%02x", control->md5_resblock[j] & 0xFF); failure_return(("\n"), -1); } print_output("MD5 integrity of written file matches archive\n"); diff --git a/rzip.c b/rzip.c index a85728e..9a3a00e 100644 --- a/rzip.c +++ b/rzip.c @@ -54,7 +54,6 @@ #include "md5.h" #include "stream.h" #include "util.h" -#include "liblrzip.h" #include "lrzip.h" /* needed for CRC routines */ #include "lzma/C/7zCrc.h" @@ -712,7 +711,7 @@ static bool mmap_stdin(rzip_control *control, uchar *buf, struct rzip_state *st) total = 0; while (len > 0) { ret = MIN(len, one_g); - ret = read(0, offset_buf, (size_t)ret); + ret = read(fileno(control->inFILE), offset_buf, (size_t)ret); if (unlikely(ret < 0)) fatal_return(("Failed to read in mmap_stdin\n"), false); total += ret; @@ -806,7 +805,6 @@ bool rzip_fd(rzip_control *control, int fd_in, int fd_out) * If file size < compression window, can't do */ struct timeval current, start, last; - uchar md5_resblock[MD5_DIGEST_SIZE]; i64 len = 0, last_chunk = 0; int pass = 0, passes, j; struct rzip_state *st; @@ -1066,20 +1064,20 @@ retry: if (!NO_MD5) { /* Temporary workaround till someone fixes apple md5 */ - md5_finish_ctx(&control->ctx, md5_resblock); + md5_finish_ctx(&control->ctx, control->md5_resblock); if (HASH_CHECK || MAX_VERBOSE) { print_output("MD5: "); for (j = 0; j < MD5_DIGEST_SIZE; j++) - print_output("%02x", md5_resblock[j] & 0xFF); + print_output("%02x", control->md5_resblock[j] & 0xFF); print_output("\n"); } /* When encrypting data, we encrypt the MD5 value as well */ if (ENCRYPT) - if (unlikely(!lrz_encrypt(control, md5_resblock, MD5_DIGEST_SIZE, control->salt_pass))) { + if (unlikely(!lrz_encrypt(control, control->md5_resblock, MD5_DIGEST_SIZE, control->salt_pass))) { free(st); return false; } - if (unlikely(write_1g(control, md5_resblock, MD5_DIGEST_SIZE) != MD5_DIGEST_SIZE)) { + if (unlikely(write_1g(control, control->md5_resblock, MD5_DIGEST_SIZE) != MD5_DIGEST_SIZE)) { free(st); fatal_return(("Failed to write md5 in rzip_fd\n"), false); } @@ -1122,6 +1120,6 @@ void rzip_control_free(rzip_control *control) if (!control) return; free(control->tmpdir); - free(control->suffix); + if (control->suffix && control->suffix[0]) free(control->suffix); free(control); } diff --git a/stream.c b/stream.c index da79744..c946bfa 100644 --- a/stream.c +++ b/stream.c @@ -60,7 +60,6 @@ #include "util.h" #include "zpipe.h" -#include "liblrzip.h" #include "lrzip.h" @@ -865,7 +864,7 @@ static inline int read_val(rzip_control *control, int f, i64 *v, int len) return ret; } -static int fd_seekto(struct stream_info *sinfo, i64 spos, i64 pos) +static int fd_seekto(rzip_control *control, struct stream_info *sinfo, i64 spos, i64 pos) { if (unlikely(lseek(sinfo->fd, spos, SEEK_SET) != spos)) { print_err("Failed to seek to %lld in stream\n", pos); @@ -889,7 +888,7 @@ static int seekto(rzip_control *control, struct stream_info *sinfo, i64 pos) return 0; } - return fd_seekto(sinfo, spos, pos); + return fd_seekto(control, sinfo, spos, pos); } static int read_seekto(rzip_control *control, struct stream_info *sinfo, i64 pos) @@ -907,7 +906,7 @@ static int read_seekto(rzip_control *control, struct stream_info *sinfo, i64 pos return 0; } - return fd_seekto(sinfo, spos, pos); + return fd_seekto(control, sinfo, spos, pos); } static i64 get_seek(rzip_control *control, int fd) diff --git a/util.c b/util.c index 5c75377..58b1fa6 100644 --- a/util.c +++ b/util.c @@ -52,7 +52,6 @@ #include #include #include "lrzip_private.h" -#include "liblrzip.h" #include "util.h" #include "sha4.h" #include "aes.h" diff --git a/util.h b/util.h index 55d60f9..9193240 100644 --- a/util.h +++ b/util.h @@ -28,7 +28,7 @@ void unlink_files(rzip_control *control); void register_outputfile(rzip_control *control, FILE *f); void fatal_exit(rzip_control *control); /* 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, ...) +static inline void fatal(const rzip_control *control, unsigned int line, const char *file, const char *func, const char *format, ...) { va_list ap; @@ -37,7 +37,7 @@ static inline void fatal(const rzip_control *control, unsigned int line, const c vfprintf(stderr, format, ap); perror(NULL); } else - control->log_cb(control->log_data, line, file, format, ap); + control->log_cb(control->log_data, 0, line, file, func, format, ap); va_end(ap); if (!control->library_mode) fatal_exit((rzip_control*)control); @@ -45,7 +45,7 @@ static inline void fatal(const rzip_control *control, unsigned int line, const c #ifdef fatal # undef fatal #endif -#define fatal(stuff...) fatal(control, __LINE__, __FILE__, stuff) +#define fatal(stuff...) fatal(control, __LINE__, __FILE__, __func__, stuff) #define fatal_return(stuff, ...) do { \ fatal stuff; \ return __VA_ARGS__; \ @@ -54,7 +54,7 @@ static inline void fatal(const rzip_control *control, unsigned int line, const c fatal stuff; \ goto label; \ } while (0) -static inline void failure(const rzip_control *control, unsigned int line, const char *file, const char *format, ...) +static inline void failure(const rzip_control *control, unsigned int line, const char *file, const char *func, const char *format, ...) { va_list ap; @@ -62,7 +62,7 @@ static inline void failure(const rzip_control *control, unsigned int line, const if (!control->log_cb) vfprintf(stderr, format, ap); else - control->log_cb(control->log_data, line, file, format, ap); + control->log_cb(control->log_data, 0, line, file, func, format, ap); va_end(ap); if (!control->library_mode) fatal_exit((rzip_control*)control); @@ -70,7 +70,7 @@ static inline void failure(const rzip_control *control, unsigned int line, const #ifdef failure # undef failure #endif -#define failure(stuff...) failure(control, __LINE__, __FILE__, stuff) +#define failure(stuff...) failure(control, __LINE__, __FILE__, __func__, stuff) #define failure_return(stuff, ...) do { \ failure stuff; \ return __VA_ARGS__; \