diff --git a/Makefile.am b/Makefile.am index 122ee05..a71422c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,20 +23,20 @@ m4/ltversion.m4 SUBDIRS = lzma man doc -AM_CFLAGS = -I lzma/C -DNDEBUG +AM_CFLAGS = -I. -I lzma/C -DNDEBUG +AM_CXXFLAGS = $(AM_CFLAGS) lrztardir = @bindir@ lrztar_SCRIPTS = lrztar -bin_PROGRAMS = lrzip -lrzip_SOURCES = \ +noinst_LTLIBRARIES = libtmplrzip.la +libtmplrzip_la_SOURCES = \ zpipe.cpp \ zpipe.h \ lrzip_private.h \ liblrzip.h \ lrzip.c \ lrzip.h \ - main.c \ rzip.h \ rzip.c \ runzip.c \ @@ -51,12 +51,29 @@ lrzip_SOURCES = \ aes.h \ sha4.c \ sha4.h +libtmplrzip_la_LIBADD = lzma/C/liblzma.la -lrzip_LDADD = lzma/C/liblzma.la + +lib_LTLIBRARIES = liblrzip.la +liblrzip_la_SOURCES = \ + liblrzip.c +nodist_EXTRA_liblrzip_la_SOURCES = dummy.cxx +liblrzip_la_LIBADD = libtmplrzip.la + +bin_PROGRAMS = lrzip +lrzip_SOURCES = \ + main.c +nodist_EXTRA_lrzip_SOURCES = dummyy.cxx + +lrzip_LDADD = libtmplrzip.la if STATIC lrzip_LDFLAGS = -all-static endif +noinst_PROGRAMS = decompress_demo +decompress_demo_SOURCES = decompress_demo.c +decompress_demo_LDADD = liblrzip.la + dist_doc_DATA = \ AUTHORS \ BUGS \ diff --git a/compress_demo.c b/compress_demo.c new file mode 100644 index 0000000..5f3bf4c --- /dev/null +++ b/compress_demo.c @@ -0,0 +1,42 @@ +#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 new file mode 100644 index 0000000..3e03626 --- /dev/null +++ b/decompress_demo.c @@ -0,0 +1,42 @@ +#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 [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/liblrzip.c b/liblrzip.c new file mode 100644 index 0000000..ac01c98 --- /dev/null +++ b/liblrzip.c @@ -0,0 +1,240 @@ +#include + +#ifdef HAVE_SYS_TIME_H +# include +#endif +#ifdef HAVE_SYS_RESOURCE_H +# include +#endif +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif + +/* needed for CRC routines */ +#include "lzma/C/7zCrc.h" +#include "util.h" +#include "lrzip.h" +#include "rzip.h" + +bool lrzip_init(void) +{ + /* generate crc table */ + CrcGenerateTable(); + return true; +} + +void lrzip_config_env(Lrzip *lr) +{ + const char *eptr; + /* Get Preloaded Defaults from lrzip.conf + * Look in ., $HOME/.lrzip/, /etc/lrzip. + * If LRZIP=NOCONFIG is set, then ignore config + */ + eptr = getenv("LRZIP"); + if (!eptr) + read_config(lr->control); + else if (!strstr(eptr,"NOCONFIG")) + read_config(lr->control); +} + +void lrzip_free(Lrzip *lr) +{ + if (!lr) return; + rzip_control_free(lr->control); + for (; lr->infiles && *lr->infiles; lr->infiles++) + free(*lr->infiles); + free(lr->infiles); + free(lr->outfile); + free(lr); +} + +Lrzip *lrzip_new(Lrzip_Mode mode) +{ + Lrzip *lr; + + lr = calloc(1, sizeof(Lrzip)); + if (unlikely(!lr)) return NULL; + lr->control = calloc(1, sizeof(rzip_control)); + if (unlikely(!lr->control)) goto error; + if (unlikely(!initialize_control(lr->control))) goto error; + lr->mode = mode; + lr->control->library_mode = 1; +#define MODE_CHECK(X) \ + case LRZIP_MODE_##X: \ + lr->control->flags |= FLAG_##X; \ + break + + switch (mode) { + MODE_CHECK(DECOMPRESS); + MODE_CHECK(NO_COMPRESS); + MODE_CHECK(LZO_COMPRESS); + MODE_CHECK(BZIP2_COMPRESS); + MODE_CHECK(ZLIB_COMPRESS); + MODE_CHECK(ZPAQ_COMPRESS); +#undef MODE_CHECK + default: + goto error; + } + setup_overhead(lr->control); + return lr; +error: + lrzip_free(lr); + return NULL; +} + +Lrzip_Mode lrzip_mode_get(Lrzip *lr) +{ + if (!lr) return LRZIP_MODE_NONE; + return lr->mode; +} + +char **lrzip_files_get(Lrzip *lr) +{ + if (!lr) return NULL; + return lr->infiles; +} + +bool lrzip_file_add(Lrzip *lr, const char *file) +{ + if ((!lr) || (!file) || (!file[0])) return false; + + if (!lr->infile_buckets) { + /* no files added */ + lr->infiles = calloc(INFILE_BUCKET_SIZE + 1, sizeof(char*)); + lr->infile_buckets++; + } else if (lr->infile_idx == INFILE_BUCKET_SIZE * lr->infile_buckets + 1) { + /* all buckets full, create new bucket */ + char **tmp; + + tmp = realloc(lr->infiles, ++lr->infile_buckets * INFILE_BUCKET_SIZE + 1); + if (!tmp) return false; + lr->infiles = tmp; + } + + lr->infiles[lr->infile_idx++] = strdup(file); + return true; +} + +bool lrzip_file_del(Lrzip *lr, const char *file) +{ + size_t x; + + if ((!lr) || (!file) || (!file[0])) return false; + if (!lr->infile_buckets) return true; + + for (x = 0; x <= lr->infile_idx + 1; x++) { + if (!lr->infiles[x]) return true; /* not found */ + if (strcmp(lr->infiles[x], file)) continue; /* not a match */ + free(lr->infiles[x]); + break; + } + /* update index */ + for (; x < lr->infile_idx; x++) + lr->infiles[x] = lr->infiles[x] + 1; + lr->infile_idx--; + return true; +} + +void lrzip_outfile_set(Lrzip *lr, const char *file) +{ + if ((!lr) || (!file) || (!file[0])) return; + if (lr->outfile && (!strcmp(lr->outfile, file))) return; + free(lr->outfile); + lr->outfile = strdup(file); + lr->control->outname = lr->outfile; +} + +const char *lrzip_outfile_get(Lrzip *lr) +{ + if (!lr) return NULL; + return lr->outfile; +} + +bool lrzip_run(Lrzip *lr) +{ + struct timeval start_time, end_time; + rzip_control *control; + double seconds,total_time; // for timers + size_t i; + int hours,minutes; + + if (!lr) return false; + control = lr->control; + /* One extra iteration for the case of no parameters means we will default to stdin/out */ + for (i = 0; i < lr->infile_idx; i++) { + lr->control->infile = lr->infiles[i]; + if (lr->control->infile) { + if ((strcmp(lr->control->infile, "-") == 0)) + lr->control->flags |= FLAG_STDIN; + else { + struct stat infile_stat; + + stat(lr->control->infile, &infile_stat); + if (unlikely(S_ISDIR(infile_stat.st_mode))) { + print_err("lrzip only works directly on FILES.\n" + "Use lrztar or pipe through tar for compressing directories.\n"); + return false; + } + } + } + + if (lr->control->outname && (strcmp(lr->control->outname, "-") == 0)) { + lr->control->flags |= FLAG_STDOUT; + lr->control->msgout = stderr; + register_outputfile(lr->control, lr->control->msgout); + } + + /* If no output filename is specified, and we're using stdin, + * use stdout */ + if (!lr->control->outname && STDIN) { + lr->control->flags |= FLAG_STDOUT; + lr->control->msgout = stderr; + register_outputfile(lr->control, lr->control->msgout); + } + + if (!STDOUT) { + lr->control->msgout = stdout; + register_outputfile(lr->control, lr->control->msgout); + } + + if (CHECK_FILE) { + if (!DECOMPRESS) { + print_err("Can only check file written on decompression.\n"); + lr->control->flags &= ~FLAG_CHECK; + } else if (STDOUT) { + print_err("Can't check file written when writing to stdout. Checking disabled.\n"); + lr->control->flags &= ~FLAG_CHECK; + } + } + + setup_ram(lr->control); + + gettimeofday(&start_time, NULL); + + if (unlikely(ENCRYPT && (!lr->control->pass_cb))) { + print_err("No password callback set!\n"); + return false; + } + + if (DECOMPRESS || TEST_ONLY) + decompress_file(lr->control); + else if (INFO) + get_fileinfo(lr->control); + else + compress_file(lr->control); + + /* compute total time */ + gettimeofday(&end_time, NULL); + total_time = (end_time.tv_sec + (double)end_time.tv_usec / 1000000) - + (start_time.tv_sec + (double)start_time.tv_usec / 1000000); + hours = (int)total_time / 3600; + minutes = (int)(total_time / 60) % 60; + seconds = total_time - hours * 3600 - minutes * 60; + if (!INFO) + print_progress("Total time: %02d:%02d:%05.2f\n", hours, minutes, seconds); + } + return true; +} diff --git a/liblrzip_private.h b/liblrzip_private.h new file mode 100644 index 0000000..4ba061d --- /dev/null +++ b/liblrzip_private.h @@ -0,0 +1,20 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include + +#define INFILE_BUCKET_SIZE 10 + +struct Lrzip +{ + Lrzip_Mode mode; + rzip_control *control; + + char *outfile; + + /* bucket allocation is used here to avoid frequent calls to realloc */ + char **infiles; + size_t infile_idx; + size_t infile_buckets; +};