diff --git a/liblrzip.c b/liblrzip.c index 2895da9..7871ad3 100644 --- a/liblrzip.c +++ b/liblrzip.c @@ -19,6 +19,23 @@ #include "lrzip.h" #include "rzip.h" +#ifdef __APPLE__ +# define fmemopen(s, len, modes) fake_fmemopen((s), (len), (modes)) +static FILE *fake_fmemopen(void *buf, size_t buflen, const char *mode) +{ + FILE *in; + + in = tmpfile(); + if (!in) return NULL; + if (fwrite(buf, buflen, 1, in) != 1) { + fclose(in); + return NULL; + } + rewind(in); + return in; +} +#endif + static void liblrzip_index_update(size_t x, size_t *idx, void **queue) { for (; x < *idx; x++) @@ -543,3 +560,81 @@ void lrzip_info_cb_set(Lrzip *lr, Lrzip_Info_Cb cb, void *data) lr->control->info_data = data; } +bool lrzip_compress_full(void *dest, unsigned long *dest_len, const void *source, unsigned long source_len, Lrzip_Mode mode, int compress_level) +{ + Lrzip *lr; + FILE *s, *d; + struct stat st; + int fd; + + if ((!dest) || (!dest_len) || (!source) || (!source_len) || (mode < LRZIP_MODE_COMPRESS_NONE)) return false; + + lrzip_init(); + if (!mode) mode = LRZIP_MODE_COMPRESS_LZMA; + lr = lrzip_new(mode); + if (!lr) return false; + lrzip_config_env(lr); + + s = fmemopen((void*)source, source_len, "r"); + d = tmpfile(); + if ((!s) || (!d)) goto error; + + if (!lrzip_file_add(lr, s)) goto error; + lrzip_outfile_set(lr, d); + if (!lrzip_compression_level_set(lr, compress_level)) goto error; + if (!lrzip_run(lr)) goto error; + + fd = fileno(d); + if (fstat(fd, &st)) goto error; + *dest_len = st.st_size; + fread(dest, sizeof(char), st.st_size, d); + if (ferror(d)) goto error; + fclose(s); + fclose(d); + return true; + +error: + if (s) fclose(s); + if (d) fclose(d); + lrzip_free(lr); + return false; +} + + +bool lrzip_decompress(void *dest, unsigned long *dest_len, const void *source, unsigned long source_len) +{ + Lrzip *lr; + FILE *s, *d; + struct stat st; + int fd; + + if ((!dest) || (!dest_len) || (!source) || (!source_len)) return false; + + lrzip_init(); + lr = lrzip_new(LRZIP_MODE_DECOMPRESS); + if (!lr) return false; + lrzip_config_env(lr); + + s = fmemopen((void*)source, source_len, "r"); + d = tmpfile(); + if ((!s) || (!d)) goto error; + + if (!lrzip_file_add(lr, s)) goto error; + lrzip_outfile_set(lr, d); + if (!lrzip_run(lr)) goto error; + + fd = fileno(d); + if (fstat(fd, &st)) goto error; + *dest_len = st.st_size; + fread(dest, sizeof(char), st.st_size, d); + if (ferror(d)) goto error; + fclose(s); + fclose(d); + return true; + +error: + if (s) fclose(s); + if (d) fclose(d); + lrzip_free(lr); + return false; +} diff --git a/liblrzip.h b/liblrzip.h index 4c29319..89c7c4f 100644 --- a/liblrzip.h +++ b/liblrzip.h @@ -112,5 +112,43 @@ void lrzip_log_stderr_set(Lrzip *lr, FILE *err); FILE *lrzip_log_stderr_get(Lrzip *lr); void lrzip_pass_cb_set(Lrzip *lr, Lrzip_Password_Cb cb, void *data); void lrzip_info_cb_set(Lrzip *lr, Lrzip_Info_Cb cb, void *data); +bool lrzip_decompress(void *dest, unsigned long *dest_len, const void *source, unsigned long source_len); +bool lrzip_compress_full(void *dest, unsigned long *dest_len, const void *source, unsigned long source_len, Lrzip_Mode mode, int compress_level); + +static inline bool lrzip_compress(void *dest, unsigned long *dest_len, const void *source, unsigned long source_len) +{ return lrzip_compress_full(dest, dest_len, source, source_len, LRZIP_MODE_COMPRESS_LZMA, 7); } + +static inline bool lrzip_lcompress(void *dest, unsigned long *dest_len, const void *source, unsigned long source_len) +{ return lrzip_compress_full(dest, dest_len, source, source_len, LRZIP_MODE_COMPRESS_LZO, 7); } + +static inline bool lrzip_gcompress(void *dest, unsigned long *dest_len, const void *source, unsigned long source_len) +{ return lrzip_compress_full(dest, dest_len, source, source_len, LRZIP_MODE_COMPRESS_ZLIB, 7); } + +static inline bool lrzip_zcompress(void *dest, unsigned long *dest_len, const void *source, unsigned long source_len) +{ return lrzip_compress_full(dest, dest_len, source, source_len, LRZIP_MODE_COMPRESS_ZPAQ, 7); } + +static inline bool lrzip_bcompress(void *dest, unsigned long *dest_len, const void *source, unsigned long source_len) +{ return lrzip_compress_full(dest, dest_len, source, source_len, LRZIP_MODE_COMPRESS_BZIP2, 7); } + +static inline bool lrzip_rcompress(void *dest, unsigned long *dest_len, const void *source, unsigned long source_len) +{ return lrzip_compress_full(dest, dest_len, source, source_len, LRZIP_MODE_COMPRESS_NONE, 7); } + +static inline bool lrzip_compress2(void *dest, unsigned long *dest_len, const void *source, unsigned long source_len, int compress_level) +{ return lrzip_compress_full(dest, dest_len, source, source_len, LRZIP_MODE_COMPRESS_LZMA, compress_level); } + +static inline bool lrzip_lcompress2(void *dest, unsigned long *dest_len, const void *source, unsigned long source_len, int compress_level) +{ return lrzip_compress_full(dest, dest_len, source, source_len, LRZIP_MODE_COMPRESS_LZO, compress_level); } + +static inline bool lrzip_gcompress2(void *dest, unsigned long *dest_len, const void *source, unsigned long source_len, int compress_level) +{ return lrzip_compress_full(dest, dest_len, source, source_len, LRZIP_MODE_COMPRESS_ZLIB, compress_level); } + +static inline bool lrzip_zcompress2(void *dest, unsigned long *dest_len, const void *source, unsigned long source_len, int compress_level) +{ return lrzip_compress_full(dest, dest_len, source, source_len, LRZIP_MODE_COMPRESS_ZPAQ, compress_level); } + +static inline bool lrzip_bcompress2(void *dest, unsigned long *dest_len, const void *source, unsigned long source_len, int compress_level) +{ return lrzip_compress_full(dest, dest_len, source, source_len, LRZIP_MODE_COMPRESS_BZIP2, compress_level); } + +static inline bool lrzip_rcompress2(void *dest, unsigned long *dest_len, const void *source, unsigned long source_len, int compress_level) +{ return lrzip_compress_full(dest, dest_len, source, source_len, LRZIP_MODE_COMPRESS_NONE, compress_level); } #endif