diff --git a/Makefile.am b/Makefile.am index a71422c..8df5f3a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -70,10 +70,13 @@ if STATIC lrzip_LDFLAGS = -all-static endif -noinst_PROGRAMS = decompress_demo +noinst_PROGRAMS = decompress_demo liblrzip_demo decompress_demo_SOURCES = decompress_demo.c decompress_demo_LDADD = liblrzip.la +liblrzip_demo_SOURCES = liblrzip_demo.c +liblrzip_demo_LDADD = liblrzip.la + dist_doc_DATA = \ AUTHORS \ BUGS \ diff --git a/compress_demo.c b/compress_demo.c deleted file mode 100644 index 5f3bf4c..0000000 --- a/compress_demo.c +++ /dev/null @@ -1,42 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#undef NDEBUG -#include -#include -#include -#include -#include - -static const char *suffix_me(const char *file) -{ - const char *p; - static char buf[4096]; - - p = strrchr(file, '.'); - if (p && (strlen(p + 1) < 4)) - strncat(buf, file, p - file); - else - strcat(buf, file); - return &buf[0]; -} - -int main(int argc, char *argv[]) -{ - Lrzip *lr; - if ((argc != 2) && (argc != 3)) { - fprintf(stderr, "Usage: %s file [file [file [... [outfile]]]]\n", argv[0]); - exit(1); - } - lr = lrzip_new(LRZIP_MODE_DECOMPRESS); - assert(lr); - lrzip_config_env(lr); - assert(lrzip_file_add(lr, argv[1])); - if (argc == 2) { - lrzip_outfile_set(lr, suffix_me(argv[1])); - } - else - lrzip_outfile_set(lr, argv[2]); - assert(lrzip_run(lr)); - return 0; -} diff --git a/decompress_demo.c b/decompress_demo.c index 3e03626..a980dd5 100644 --- a/decompress_demo.c +++ b/decompress_demo.c @@ -31,12 +31,11 @@ int main(int argc, char *argv[]) lr = lrzip_new(LRZIP_MODE_DECOMPRESS); assert(lr); lrzip_config_env(lr); - assert(lrzip_file_add(lr, argv[1])); - if (argc == 2) { - lrzip_outfile_set(lr, suffix_me(argv[1])); - } + assert(lrzip_filename_add(lr, argv[1])); + if (argc == 2) + lrzip_outfilename_set(lr, suffix_me(argv[1])); else - lrzip_outfile_set(lr, argv[2]); + lrzip_outfilename_set(lr, argv[2]); assert(lrzip_run(lr)); return 0; } diff --git a/liblrzip_demo.c b/liblrzip_demo.c new file mode 100644 index 0000000..aec4a2b --- /dev/null +++ b/liblrzip_demo.c @@ -0,0 +1,327 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#undef NDEBUG +#include +#include +#ifdef HAVE_STRING_H +# include +#endif +#include +#ifdef HAVE_ERRNO_H +# include +#else +#ifdef HAVE_UNISTD_H +# include +#endif +extern int errno; +#endif +#include +#include + +#define failure(format, args...) do { \ + fprintf(stderr, format, ##args); \ + exit(1); \ +} while (0) + +static void usage(void) +{ + printf("lrzip version %s\n", PACKAGE_VERSION); + printf("Copyright (C) Con Kolivas 2006-2011\n"); + printf("Based on rzip "); + printf("Copyright (C) Andrew Tridgell 1998-2003\n\n"); + printf("Usage: lrzip [options] \n"); + printf("General options:\n"); + printf(" -c check integrity of file written on decompression\n"); + printf(" -d decompress\n"); + printf(" -e password protected sha512/aes128 encryption on compression\n"); + printf(" -h|-? show help\n"); + printf(" -H display md5 hash integrity information\n"); + printf(" -i show compressed file information\n"); + printf(" -q don't show compression progress\n"); + printf(" -t test compressed file integrity\n"); + printf(" -v[v] Increase verbosity\n"); + printf(" -V show version\n"); + printf("Options affecting output:\n"); + printf(" -D delete existing files\n"); + printf(" -f force overwrite of any existing files\n"); + printf(" -k keep broken or damaged output files\n"); + printf(" -o filename specify the output file name and/or path\n"); + printf(" -O directory specify the output directory when -o is not used\n"); + printf(" -S suffix specify compressed suffix (default '.lrz')\n"); + printf("Options affecting compression:\n"); + printf(" -b bzip2 compression\n"); + printf(" -g gzip compression using zlib\n"); + printf(" -l lzo compression (ultra fast)\n"); + printf(" -n no backend compression - prepare for other compressor\n"); + printf(" -z zpaq compression (best, extreme compression, extremely slow)\n"); + printf("Low level options:\n"); + printf(" -L level set lzma/bzip2/gzip compression level (1-9, default 7)\n"); + printf(" -N value Set nice value to value (default 19)\n"); + printf(" -p value Set processor count to override number of threads\n"); + printf(" -T Disable LZO compressibility testing\n"); + printf(" -U Use unlimited window size beyond ramsize (potentially much slower)\n"); + printf(" -w size maximum compression window in hundreds of MB\n"); + printf(" default chosen by heuristic dependent on ram and chosen compression\n"); + printf("\nLRZIP=NOCONFIG environment variable setting can be used to bypass lrzip.conf.\n"); + printf("TMP environment variable will be used for storage of temporary files when needed.\n"); + printf("TMPDIR may also be stored in lrzip.conf file.\n"); + printf("\nIf no filenames or \"-\" is specified, stdin/out will be used.\n"); +} + +static int get_pass(char *s, size_t slen) +{ + int len; + + memset(s, 0, slen); + if (!fgets(s, slen, stdin)) { + fprintf(stderr, "Failed to retrieve passphrase\n"); + return -1; + } + len = strlen(s); + if (len > 0 && ('\r' == s[len - 1] || '\n' == s[len - 1])) + s[len - 1] = '\0'; + if (len > 1 && ('\r' == s[len - 2] || '\n' == s[len - 2])) + s[len - 2] = '\0'; + len = strlen(s); + if (!len) { + fprintf(stderr, "Empty passphrase\n"); + return -1; + } + return len; +} + +static void pass_cb(void *data __UNUSED__, char **pass_string, size_t pass_len) +{ + int len; + struct termios termios_p; + /* Disable stdin echo to screen */ + tcgetattr(fileno(stdin), &termios_p); + termios_p.c_lflag &= ~ECHO; + tcsetattr(fileno(stdin), 0, &termios_p); + + printf("Enter passphrase: "); + len = get_pass(*pass_string, pass_len); + printf("\n"); + + if (len < 1) exit(1); + + termios_p.c_lflag |= ECHO; + tcsetattr(fileno(stdin), 0, &termios_p); +} + +static void mode_check(Lrzip *lr, Lrzip_Mode mode) { + Lrzip_Mode current = lrzip_mode_get(lr); + if (current && (current != mode)) + failure("Can only use one of -l, -b, -g, -z or -n\n"); + lrzip_mode_set(lr, mode); +} + +int main(int argc, char *argv[]) +{ + Lrzip *lr; + extern int optind; + extern char *optarg; + int64_t x; + int c; + bool get_hash = false; + + lrzip_init(); + lr = lrzip_new(LRZIP_MODE_NONE); + assert(lr); + lrzip_config_env(lr); + lrzip_log_level_set(lr, 2); + while ((c = getopt(argc, argv, "bcdDefghHiklL:nN:o:O:p:qS:tTUvVw:z?")) != -1) { + switch (c) { + case 'b': + mode_check(lr, LRZIP_MODE_COMPRESS_BZIP2); + break; + case 'c': + lrzip_flags_set(lr, lrzip_flags_get(lr) | LRZIP_FLAG_VERIFY); + break; + case 'd': + mode_check(lr, LRZIP_MODE_DECOMPRESS); + break; + case 'D': + lrzip_flags_set(lr, lrzip_flags_get(lr) | LRZIP_FLAG_REMOVE_SOURCE); + break; + case 'e': + lrzip_flags_set(lr, lrzip_flags_get(lr) | LRZIP_FLAG_ENCRYPT); + break; + case 'f': + lrzip_flags_set(lr, lrzip_flags_get(lr) | LRZIP_FLAG_REMOVE_DESTINATION); + break; + case 'g': + mode_check(lr, LRZIP_MODE_COMPRESS_ZLIB); + break; + case 'h': + case '?': + usage(); + return -1; + case 'H': + get_hash = true; + break; + case 'i': + mode_check(lr, LRZIP_MODE_INFO); + break; + case 'k': + lrzip_flags_set(lr, lrzip_flags_get(lr) | LRZIP_FLAG_KEEP_BROKEN); + break; + case 'l': + mode_check(lr, LRZIP_MODE_COMPRESS_LZO); + break; + case 'L': + errno = 0; + x = strtol(optarg, NULL, 10); + if (errno || ((x < 1) || (x > 9))) + failure("Invalid compression level (must be 1-9)\n"); + lrzip_compression_level_set(lr, (unsigned int)x); + break; + case 'n': + mode_check(lr, LRZIP_MODE_COMPRESS_NONE); + break; + case 'N': + errno = 0; + x = strtol(optarg, NULL, 10); + if (errno || (x < -20 || x > 19)) + failure("Invalid nice value (must be -20..19)\n"); + lrzip_nice_set(lr, x); + break; + case 'o': + if (lrzip_outdir_get(lr)) + failure("Cannot have -o and -O together\n"); + if (!strcmp(optarg, "-")) + lrzip_outfile_set(lr, stdout); + else + lrzip_outfilename_set(lr, optarg); + break; + case 'O': + if (lrzip_outfilename_get(lr)) /* can't mix -o and -O */ + failure("Cannot have options -o and -O together\n"); + if (lrzip_outfile_get(lr)) + failure("Cannot specify an output directory when outputting to stdout\n"); + lrzip_outdir_set(lr, optarg); + break; + case 'p': + errno = 0; + x = strtol(optarg, NULL, 10); + if (errno || (x < 1)) + failure("Must have at least one thread\n"); + lrzip_threads_set(lr, (unsigned int)x); + break; + case 'q': + lrzip_log_level_set(lr, lrzip_log_level_get(lr) - 1); + break; + case 'S': + if (lrzip_outfilename_get(lr)) + failure("Specified output filename already, can't specify an extension.\n"); + if (lrzip_outfile_get(lr)) + failure("Cannot specify a filename suffix when outputting to stdout\n"); + lrzip_suffix_set(lr, optarg); + break; + case 't': + if (lrzip_outfilename_get(lr)) + failure("Cannot specify an output file name when just testing.\n"); + if (lrzip_flags_get(lr) & LRZIP_FLAG_REMOVE_SOURCE) + failure("Doubt that you want to delete a file when just testing.\n"); + mode_check(lr, LRZIP_MODE_TEST); + break; + case 'T': + lrzip_flags_set(lr, lrzip_flags_get(lr) | LRZIP_FLAG_DISABLE_LZO_CHECK); + break; + case 'U': + lrzip_flags_set(lr, lrzip_flags_get(lr) | LRZIP_FLAG_UNLIMITED_RAM); + break; + case 'v': + lrzip_log_level_set(lr, lrzip_log_level_get(lr) + 1); + break; + case 'V': + printf("lrzip version %s\n", PACKAGE_VERSION); + exit(0); + break; + case 'w': + errno = 0; + x = strtoll(optarg, NULL, 10); + if (errno || (x < 1)) + failure("Invalid compression window '%s'!\n", optarg); + lrzip_compression_window_max_set(lr, x); + break; + case 'z': + mode_check(lr, LRZIP_MODE_COMPRESS_ZPAQ); + break; + } + } + /* LZMA is the default */ + if (!lrzip_mode_get(lr)) lrzip_mode_set(lr, LRZIP_MODE_COMPRESS_LZMA); + argc -= optind, argv += optind; + + if (lrzip_outfilename_get(lr) && (argc > 1)) + failure("Cannot specify output filename with more than 1 file\n"); + + if ((lrzip_flags_get(lr) & LRZIP_FLAG_UNLIMITED_RAM) && lrzip_compression_window_max_get(lr)) { + fprintf(stderr, "If -U used, cannot specify a window size with -w.\n"); + lrzip_compression_window_max_set(lr, 0); + } + + if (argc < 1) lrzip_file_add(lr, stdin); + + if ((lrzip_flags_get(lr) & LRZIP_FLAG_UNLIMITED_RAM) && lrzip_files_count(lr)) { + fprintf(stderr, "Cannot have -U and stdin, unlimited mode disabled.\n"); + lrzip_flags_set(lr, lrzip_flags_get(lr) & ~LRZIP_FLAG_UNLIMITED_RAM); + } + + /* If no output filename is specified, and we're using stdin, + * use stdout */ + if (lrzip_files_count(lr) && (!lrzip_outfilename_get(lr))) + lrzip_outfile_set(lr, stdout); + + if (lrzip_flags_get(lr) & LRZIP_FLAG_VERIFY) { + if (lrzip_mode_get(lr) != LRZIP_MODE_DECOMPRESS) { + fprintf(stderr, "Can only check file written on decompression.\n"); + lrzip_flags_set(lr, lrzip_flags_get(lr) & ~LRZIP_FLAG_VERIFY); + } else if (lrzip_outfile_get(lr)) { + fprintf(stderr, "Can't check file written when writing to stdout. Checking disabled.\n"); + lrzip_flags_set(lr, lrzip_flags_get(lr) & ~LRZIP_FLAG_VERIFY); + } + } + + for (x = 0; x < argc; x++) { + if (argv[x][0] != '-') { + assert(lrzip_filename_add(lr, argv[x])); + continue; + } + if (argv[x][1] == 0) { + assert(lrzip_file_add(lr, stdin)); + continue; + } + } + if (argc == 1) { + if (!lrzip_files_count(lr)) lrzip_file_add(lr, stdin); + if (lrzip_filenames_count(lr)) { + if (!lrzip_outfilename_get(lr)) { + char buf[4096]; + const char *infile; + size_t len; + + infile = lrzip_filenames_get(lr)[0]; + len = strlen(infile); + if (!strcmp(infile + len - 4, ".lrz")) + strncat(buf, infile, len - 4); + else + snprintf(buf, sizeof(buf), "%s.out", infile); + lrzip_outfilename_set(lr, buf); + } + } else if (!lrzip_outfile_get(lr)) lrzip_outfile_set(lr, stdout); + } + lrzip_log_stdout_set(lr, stdout); + lrzip_log_stderr_set(lr, stderr); + lrzip_pass_cb_set(lr, pass_cb, NULL); + if (!lrzip_run(lr)) exit(1); + if (get_hash) { + const unsigned char *digest = lrzip_md5digest_get(lr); + for (x = 0; x < 16; x++) + fprintf(stdout, "%02x", digest[x] & 0xFF); + } + lrzip_free(lr); + return 0; +}