2012-03-07 12:04:24 +01:00
|
|
|
/*
|
2016-06-11 01:22:34 +02:00
|
|
|
Copyright (C) 2012-2016 Con Kolivas
|
2012-03-07 12:04:24 +01:00
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
2011-08-12 08:42:57 +02:00
|
|
|
#include <liblrzip_private.h>
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_SYS_TIME_H
|
|
|
|
|
# include <sys/time.h>
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef HAVE_SYS_RESOURCE_H
|
|
|
|
|
# include <sys/resource.h>
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef HAVE_SYS_TYPES_H
|
|
|
|
|
# include <sys/types.h>
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef HAVE_SYS_STAT_H
|
|
|
|
|
# include <sys/stat.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* needed for CRC routines */
|
|
|
|
|
#include "lzma/C/7zCrc.h"
|
|
|
|
|
#include "util.h"
|
2012-07-07 13:39:40 +02:00
|
|
|
#include "lrzip_core.h"
|
2011-08-12 08:42:57 +02:00
|
|
|
#include "rzip.h"
|
|
|
|
|
|
2011-08-17 13:28:43 +02:00
|
|
|
#if defined(__APPLE__) || defined(__FreeBSD__)
|
2011-08-17 13:03:02 +02:00
|
|
|
# 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();
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!in)
|
|
|
|
|
return NULL;
|
2011-08-17 13:03:02 +02:00
|
|
|
if (fwrite(buf, buflen, 1, in) != 1) {
|
|
|
|
|
fclose(in);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
rewind(in);
|
2011-09-13 06:40:51 +02:00
|
|
|
return in;
|
2011-08-17 13:03:02 +02:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2011-08-13 09:43:19 +02:00
|
|
|
static void liblrzip_index_update(size_t x, size_t *idx, void **queue)
|
|
|
|
|
{
|
|
|
|
|
for (; x < *idx; x++)
|
2011-08-16 08:13:41 +02:00
|
|
|
queue[x] = queue[x + 1];
|
2011-08-13 09:43:19 +02:00
|
|
|
(*idx)--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool liblrzip_setup_flags(Lrzip *lr)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return false;
|
2011-08-13 09:43:19 +02:00
|
|
|
#define MODE_CHECK(X) \
|
|
|
|
|
case LRZIP_MODE_COMPRESS_##X: \
|
|
|
|
|
lr->control->flags ^= FLAG_NOT_LZMA; \
|
|
|
|
|
lr->control->flags |= FLAG_##X##_COMPRESS; \
|
|
|
|
|
break
|
|
|
|
|
|
2011-08-13 10:06:30 +02:00
|
|
|
|
2011-08-13 09:43:19 +02:00
|
|
|
switch (lr->mode) {
|
|
|
|
|
case LRZIP_MODE_DECOMPRESS:
|
|
|
|
|
lr->control->flags |= FLAG_DECOMPRESS;
|
|
|
|
|
break;
|
|
|
|
|
case LRZIP_MODE_TEST:
|
|
|
|
|
lr->control->flags |= FLAG_TEST_ONLY;
|
|
|
|
|
break;
|
|
|
|
|
case LRZIP_MODE_INFO:
|
|
|
|
|
lr->control->flags |= FLAG_INFO;
|
|
|
|
|
break;
|
|
|
|
|
case LRZIP_MODE_COMPRESS_NONE:
|
|
|
|
|
lr->control->flags ^= FLAG_NOT_LZMA;
|
|
|
|
|
lr->control->flags |= FLAG_NO_COMPRESS;
|
|
|
|
|
break;
|
|
|
|
|
case LRZIP_MODE_COMPRESS_LZMA:
|
|
|
|
|
lr->control->flags ^= FLAG_NOT_LZMA;
|
|
|
|
|
break;
|
|
|
|
|
MODE_CHECK(LZO);
|
|
|
|
|
MODE_CHECK(BZIP2);
|
|
|
|
|
MODE_CHECK(ZLIB);
|
|
|
|
|
MODE_CHECK(ZPAQ);
|
|
|
|
|
#undef MODE_CHECK
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
setup_overhead(lr->control);
|
|
|
|
|
if (lr->flags & LRZIP_FLAG_VERIFY) {
|
|
|
|
|
lr->control->flags |= FLAG_CHECK;
|
|
|
|
|
lr->control->flags |= FLAG_HASH;
|
|
|
|
|
}
|
|
|
|
|
if (lr->flags & LRZIP_FLAG_REMOVE_DESTINATION)
|
|
|
|
|
lr->control->flags |= FLAG_FORCE_REPLACE;
|
|
|
|
|
if (lr->flags & LRZIP_FLAG_REMOVE_SOURCE)
|
|
|
|
|
lr->control->flags &= ~FLAG_KEEP_FILES;
|
|
|
|
|
if (lr->flags & LRZIP_FLAG_KEEP_BROKEN)
|
|
|
|
|
lr->control->flags |= FLAG_KEEP_BROKEN;
|
|
|
|
|
if (lr->flags & LRZIP_FLAG_DISABLE_LZO_CHECK)
|
|
|
|
|
lr->control->flags &= ~FLAG_THRESHOLD;
|
|
|
|
|
if (lr->flags & LRZIP_FLAG_UNLIMITED_RAM)
|
|
|
|
|
lr->control->flags |= FLAG_UNLIMITED;
|
|
|
|
|
if (lr->flags & LRZIP_FLAG_ENCRYPT)
|
|
|
|
|
lr->control->flags |= FLAG_ENCRYPT;
|
|
|
|
|
if (lr->control->log_level > 0) {
|
|
|
|
|
lr->control->flags |= FLAG_SHOW_PROGRESS;
|
|
|
|
|
if (lr->control->log_level > 1) {
|
|
|
|
|
lr->control->flags |= FLAG_VERBOSITY;
|
|
|
|
|
if (lr->control->log_level > 2)
|
|
|
|
|
lr->control->flags |= FLAG_VERBOSITY_MAX;
|
|
|
|
|
}
|
|
|
|
|
} else lr->control->flags ^= (FLAG_VERBOSE | FLAG_SHOW_PROGRESS);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-08-12 08:42:57 +02:00
|
|
|
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)
|
|
|
|
|
{
|
2011-08-13 09:43:19 +02:00
|
|
|
size_t x;
|
|
|
|
|
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!lr) || (!lr->infilename_buckets))
|
|
|
|
|
return;
|
2011-08-12 08:42:57 +02:00
|
|
|
rzip_control_free(lr->control);
|
2011-08-13 09:43:19 +02:00
|
|
|
for (x = 0; x < lr->infilename_idx; x++)
|
|
|
|
|
free(lr->infilenames[x]);
|
|
|
|
|
free(lr->infilenames);
|
2011-08-12 08:42:57 +02:00
|
|
|
free(lr->infiles);
|
|
|
|
|
free(lr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Lrzip *lrzip_new(Lrzip_Mode mode)
|
|
|
|
|
{
|
|
|
|
|
Lrzip *lr;
|
|
|
|
|
|
|
|
|
|
lr = calloc(1, sizeof(Lrzip));
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return NULL;
|
2011-08-12 08:42:57 +02:00
|
|
|
lr->control = calloc(1, sizeof(rzip_control));
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr->control)
|
|
|
|
|
goto error;
|
|
|
|
|
if (!initialize_control(lr->control))
|
|
|
|
|
goto error;
|
2011-08-12 08:42:57 +02:00
|
|
|
lr->mode = mode;
|
|
|
|
|
lr->control->library_mode = 1;
|
|
|
|
|
return lr;
|
|
|
|
|
error:
|
|
|
|
|
lrzip_free(lr);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Lrzip_Mode lrzip_mode_get(Lrzip *lr)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return LRZIP_MODE_NONE;
|
2011-08-12 08:42:57 +02:00
|
|
|
return lr->mode;
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-13 09:43:19 +02:00
|
|
|
bool lrzip_mode_set(Lrzip *lr, Lrzip_Mode mode)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!lr) || (mode > LRZIP_MODE_COMPRESS_ZPAQ))
|
|
|
|
|
return false;
|
2011-08-13 09:43:19 +02:00
|
|
|
lr->mode = mode;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool lrzip_compression_level_set(Lrzip *lr, unsigned int level)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!lr) || (!level) || (level > 9))
|
|
|
|
|
return false;
|
2011-08-13 09:43:19 +02:00
|
|
|
lr->control->compression_level = level;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned int lrzip_compression_level_get(Lrzip *lr)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return 0;
|
2011-09-13 06:40:51 +02:00
|
|
|
return lr->control->compression_level;
|
2011-08-13 09:43:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void lrzip_flags_set(Lrzip *lr, unsigned int flags)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return;
|
2011-08-13 09:43:19 +02:00
|
|
|
lr->flags = flags;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned int lrzip_flags_get(Lrzip *lr)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return 0;
|
2011-08-13 09:43:19 +02:00
|
|
|
return lr->flags;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void lrzip_nice_set(Lrzip *lr, int nice)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!lr) || (nice < -19) || (nice > 20))
|
|
|
|
|
return;
|
2011-08-13 09:43:19 +02:00
|
|
|
lr->control->nice_val = nice;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int lrzip_nice_get(Lrzip *lr)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return 0;
|
2011-08-13 09:43:19 +02:00
|
|
|
return lr->control->nice_val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void lrzip_threads_set(Lrzip *lr, unsigned int threads)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!lr) || (!threads))
|
|
|
|
|
return;
|
2011-08-13 09:43:19 +02:00
|
|
|
lr->control->threads = threads;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned int lrzip_threads_get(Lrzip *lr)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return 0;
|
2011-08-13 09:43:19 +02:00
|
|
|
return lr->control->threads;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void lrzip_compression_window_max_set(Lrzip *lr, int64_t size)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return;
|
2011-08-13 09:43:19 +02:00
|
|
|
lr->control->window = size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64_t lrzip_compression_window_max_get(Lrzip *lr)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return -1;
|
2011-08-13 09:43:19 +02:00
|
|
|
return lr->control->window;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned int lrzip_files_count(Lrzip *lr)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return 0;
|
2011-08-13 09:43:19 +02:00
|
|
|
return lr->infile_idx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned int lrzip_filenames_count(Lrzip *lr)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return 0;
|
2011-08-13 09:43:19 +02:00
|
|
|
return lr->infilename_idx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FILE **lrzip_files_get(Lrzip *lr)
|
2011-08-12 08:42:57 +02:00
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return NULL;
|
2011-08-12 08:42:57 +02:00
|
|
|
return lr->infiles;
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-13 09:43:19 +02:00
|
|
|
char **lrzip_filenames_get(Lrzip *lr)
|
2011-08-12 08:42:57 +02:00
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return NULL;
|
2011-08-13 09:43:19 +02:00
|
|
|
return lr->infilenames;
|
|
|
|
|
}
|
2011-08-12 08:42:57 +02:00
|
|
|
|
2011-08-13 09:43:19 +02:00
|
|
|
bool lrzip_file_add(Lrzip *lr, FILE *file)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!lr) || (!file))
|
|
|
|
|
return false;
|
|
|
|
|
if (lr->infilenames)
|
|
|
|
|
return false;
|
2011-08-12 08:42:57 +02:00
|
|
|
if (!lr->infile_buckets) {
|
|
|
|
|
/* no files added */
|
2011-08-13 09:43:19 +02:00
|
|
|
lr->infiles = calloc(INFILE_BUCKET_SIZE + 1, sizeof(void*));
|
2011-08-12 08:42:57 +02:00
|
|
|
lr->infile_buckets++;
|
|
|
|
|
} else if (lr->infile_idx == INFILE_BUCKET_SIZE * lr->infile_buckets + 1) {
|
|
|
|
|
/* all buckets full, create new bucket */
|
2011-08-13 09:43:19 +02:00
|
|
|
FILE **tmp;
|
2011-08-12 08:42:57 +02:00
|
|
|
|
2011-08-13 09:43:19 +02:00
|
|
|
tmp = realloc(lr->infiles, (++lr->infile_buckets * INFILE_BUCKET_SIZE + 1) * sizeof(void*));
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!tmp)
|
|
|
|
|
return false;
|
2011-08-12 08:42:57 +02:00
|
|
|
lr->infiles = tmp;
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-13 09:43:19 +02:00
|
|
|
lr->infiles[lr->infile_idx++] = file;
|
2011-08-13 10:06:30 +02:00
|
|
|
return true;
|
2011-08-12 08:42:57 +02:00
|
|
|
}
|
|
|
|
|
|
2011-08-13 09:43:19 +02:00
|
|
|
bool lrzip_file_del(Lrzip *lr, FILE *file)
|
2011-08-12 08:42:57 +02:00
|
|
|
{
|
|
|
|
|
size_t x;
|
2011-08-13 10:06:30 +02:00
|
|
|
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!lr) || (!file))
|
|
|
|
|
return false;
|
|
|
|
|
if (!lr->infile_buckets)
|
|
|
|
|
return true;
|
2011-08-12 08:42:57 +02:00
|
|
|
|
|
|
|
|
for (x = 0; x <= lr->infile_idx + 1; x++) {
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr->infiles[x])
|
|
|
|
|
return true; /* not found */
|
|
|
|
|
if (lr->infiles[x] != file)
|
|
|
|
|
continue; /* not a match */
|
2011-08-13 09:43:19 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* update index */
|
|
|
|
|
liblrzip_index_update(x, &lr->infile_idx, (void**)lr->infiles);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-17 01:04:25 +02:00
|
|
|
FILE *lrzip_file_pop(Lrzip *lr)
|
|
|
|
|
{
|
|
|
|
|
FILE *ret;
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!lr) || (!lr->infile_buckets))
|
|
|
|
|
return NULL;
|
2011-08-17 01:04:25 +02:00
|
|
|
ret = lr->infiles[0];
|
|
|
|
|
lrzip_file_del(lr, ret);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-13 09:43:19 +02:00
|
|
|
void lrzip_files_clear(Lrzip *lr)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!lr) || (!lr->infile_buckets))
|
|
|
|
|
return;
|
2011-08-13 09:43:19 +02:00
|
|
|
free(lr->infiles);
|
|
|
|
|
lr->infiles = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool lrzip_filename_add(Lrzip *lr, const char *file)
|
|
|
|
|
{
|
|
|
|
|
struct stat st;
|
|
|
|
|
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!lr) || (!file) || (!file[0]) || (!strcmp(file, "-")))
|
|
|
|
|
return false;
|
|
|
|
|
if (lr->infiles)
|
|
|
|
|
return false;
|
|
|
|
|
if (stat(file, &st))
|
|
|
|
|
return false;
|
|
|
|
|
if (S_ISDIR(st.st_mode))
|
|
|
|
|
return false;
|
2011-08-13 09:43:19 +02:00
|
|
|
|
|
|
|
|
if (!lr->infilename_buckets) {
|
|
|
|
|
/* no files added */
|
|
|
|
|
lr->infilenames = calloc(INFILE_BUCKET_SIZE + 1, sizeof(void*));
|
|
|
|
|
lr->infilename_buckets++;
|
|
|
|
|
} else if (lr->infilename_idx == INFILE_BUCKET_SIZE * lr->infilename_buckets + 1) {
|
|
|
|
|
/* all buckets full, create new bucket */
|
|
|
|
|
char **tmp;
|
|
|
|
|
|
|
|
|
|
tmp = realloc(lr->infilenames, (++lr->infilename_buckets * INFILE_BUCKET_SIZE + 1) * sizeof(void*));
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!tmp)
|
|
|
|
|
return false;
|
2011-08-13 09:43:19 +02:00
|
|
|
lr->infilenames = tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lr->infilenames[lr->infilename_idx++] = strdup(file);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool lrzip_filename_del(Lrzip *lr, const char *file)
|
|
|
|
|
{
|
|
|
|
|
size_t x;
|
2011-08-13 10:06:30 +02:00
|
|
|
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!lr) || (!file) || (!file[0]))
|
|
|
|
|
return false;
|
|
|
|
|
if (!lr->infilename_buckets)
|
|
|
|
|
return true;
|
2011-08-13 09:43:19 +02:00
|
|
|
|
|
|
|
|
for (x = 0; x <= lr->infilename_idx + 1; x++) {
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr->infilenames[x])
|
|
|
|
|
return true; /* not found */
|
|
|
|
|
if (strcmp(lr->infilenames[x], file))
|
|
|
|
|
continue; /* not a match */
|
2011-08-13 09:43:19 +02:00
|
|
|
free(lr->infilenames[x]);
|
2011-08-12 08:42:57 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* update index */
|
2011-08-13 09:43:19 +02:00
|
|
|
liblrzip_index_update(x, &lr->infilename_idx, (void**)lr->infilenames);
|
2011-08-12 08:42:57 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-17 01:04:25 +02:00
|
|
|
const char *lrzip_filename_pop(Lrzip *lr)
|
|
|
|
|
{
|
|
|
|
|
static char buf[4096];
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!lr) || (!lr->infilename_buckets))
|
|
|
|
|
return NULL;
|
2011-08-17 01:04:25 +02:00
|
|
|
strcat(buf, lr->infilenames[0]);
|
|
|
|
|
lrzip_filename_del(lr, buf);
|
|
|
|
|
return &buf[0];
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-13 09:43:19 +02:00
|
|
|
void lrzip_filenames_clear(Lrzip *lr)
|
|
|
|
|
{
|
|
|
|
|
size_t x;
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!lr) || (!lr->infilename_buckets))
|
|
|
|
|
return;
|
2011-08-13 09:43:19 +02:00
|
|
|
for (x = 0; x < lr->infilename_idx; x++)
|
|
|
|
|
free(lr->infilenames[x]);
|
|
|
|
|
free(lr->infilenames);
|
|
|
|
|
lr->infilenames = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void lrzip_suffix_set(Lrzip *lr, const char *suffix)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!lr) || (!suffix) || (!suffix[0]))
|
|
|
|
|
return;
|
2011-08-13 09:43:19 +02:00
|
|
|
free(lr->control->suffix);
|
|
|
|
|
lr->control->suffix = strdup(suffix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *lrzip_suffix_get(Lrzip *lr)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return NULL;
|
2011-08-13 09:43:19 +02:00
|
|
|
return lr->control->suffix;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void lrzip_outdir_set(Lrzip *lr, const char *dir)
|
|
|
|
|
{
|
|
|
|
|
const char *slash;
|
|
|
|
|
char *buf;
|
|
|
|
|
size_t len;
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!lr) || (!dir) || (!dir[0]))
|
|
|
|
|
return;
|
2011-08-13 09:43:19 +02:00
|
|
|
free(lr->control->outdir);
|
|
|
|
|
slash = strrchr(dir, '/');
|
|
|
|
|
if (slash && (slash[1] == 0)) {
|
|
|
|
|
lr->control->outdir = strdup(dir);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
len = strlen(dir);
|
|
|
|
|
buf = malloc(len + 2);
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!buf)
|
|
|
|
|
return;
|
2011-08-13 09:43:19 +02:00
|
|
|
memcpy(buf, dir, len);
|
|
|
|
|
buf[len] = '/';
|
|
|
|
|
buf[len + 1] = 0;
|
|
|
|
|
lr->control->outdir = buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *lrzip_outdir_get(Lrzip *lr)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return NULL;
|
2011-08-13 09:43:19 +02:00
|
|
|
return lr->control->outdir;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void lrzip_outfile_set(Lrzip *lr, FILE *file)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!lr) || (file && (file == stderr)))
|
|
|
|
|
return;
|
|
|
|
|
if (lr->control->outname)
|
|
|
|
|
return;
|
2011-08-13 09:43:19 +02:00
|
|
|
lr->control->outFILE = file;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FILE *lrzip_outfile_get(Lrzip *lr)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return NULL;
|
2011-08-13 09:43:19 +02:00
|
|
|
return lr->control->outFILE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void lrzip_outfilename_set(Lrzip *lr, const char *file)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!lr) || (file && (!file[0])))
|
|
|
|
|
return;
|
|
|
|
|
if (lr->control->outFILE)
|
|
|
|
|
return;
|
|
|
|
|
if (lr->control->outname && file && (!strcmp(lr->control->outname, file)))
|
|
|
|
|
return;
|
2011-08-13 09:43:19 +02:00
|
|
|
free(lr->control->outname);
|
|
|
|
|
lr->control->outname = file ? strdup(file) : NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *lrzip_outfilename_get(Lrzip *lr)
|
2011-08-12 08:42:57 +02:00
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return NULL;
|
2011-08-13 09:43:19 +02:00
|
|
|
return lr->control->outname;
|
2011-08-12 08:42:57 +02:00
|
|
|
}
|
|
|
|
|
|
2011-08-13 09:43:19 +02:00
|
|
|
const unsigned char *lrzip_md5digest_get(Lrzip *lr)
|
2011-08-12 08:42:57 +02:00
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return NULL;
|
2011-08-13 09:43:19 +02:00
|
|
|
return lr->control->md5_resblock;
|
2011-08-12 08:42:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool lrzip_run(Lrzip *lr)
|
|
|
|
|
{
|
|
|
|
|
struct timeval start_time, end_time;
|
|
|
|
|
rzip_control *control;
|
|
|
|
|
double seconds,total_time; // for timers
|
|
|
|
|
int hours,minutes;
|
|
|
|
|
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!liblrzip_setup_flags(lr))
|
|
|
|
|
return false;
|
2011-08-12 08:42:57 +02:00
|
|
|
control = lr->control;
|
|
|
|
|
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!lr->infile_idx) && (!lr->infilename_idx))
|
|
|
|
|
return false;
|
2011-08-13 09:43:19 +02:00
|
|
|
if (lr->control->outFILE) {
|
|
|
|
|
if (lr->control->outFILE == lr->control->msgout)
|
2011-08-12 08:42:57 +02:00
|
|
|
lr->control->msgout = stderr;
|
2011-08-13 09:43:19 +02:00
|
|
|
lr->control->flags |= FLAG_STDOUT;
|
|
|
|
|
register_outputfile(lr->control, lr->control->msgout);
|
|
|
|
|
}
|
2011-08-12 08:42:57 +02:00
|
|
|
|
2011-08-13 09:43:19 +02:00
|
|
|
if (lr->infilenames)
|
|
|
|
|
lr->control->infile = lr->infilenames[0];
|
|
|
|
|
else {
|
|
|
|
|
lr->control->inFILE = lr->infiles[0];
|
2017-06-04 07:28:18 +02:00
|
|
|
if ( lr->infiles[0] == stdin )
|
|
|
|
|
control->flags |= FLAG_STDIN;
|
2011-08-13 09:43:19 +02:00
|
|
|
}
|
2011-08-12 08:42:57 +02:00
|
|
|
|
2011-08-13 09:43:19 +02:00
|
|
|
if ((!STDOUT) && (!lr->control->msgout)) lr->control->msgout = stdout;
|
|
|
|
|
register_outputfile(lr->control, lr->control->msgout);
|
2011-08-12 08:42:57 +02:00
|
|
|
|
2011-08-13 09:43:19 +02:00
|
|
|
setup_ram(lr->control);
|
2011-08-12 08:42:57 +02:00
|
|
|
|
2011-08-13 09:43:19 +02:00
|
|
|
gettimeofday(&start_time, NULL);
|
2011-08-12 08:42:57 +02:00
|
|
|
|
2011-08-13 09:43:19 +02:00
|
|
|
if (ENCRYPT && (!lr->control->pass_cb)) {
|
|
|
|
|
print_err("No password callback set!\n");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2011-08-12 08:42:57 +02:00
|
|
|
|
2011-08-13 09:43:19 +02:00
|
|
|
if (DECOMPRESS || TEST_ONLY) {
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!decompress_file(lr->control))
|
|
|
|
|
return false;
|
2011-08-13 09:43:19 +02:00
|
|
|
} else if (INFO) {
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!get_fileinfo(lr->control))
|
|
|
|
|
return false;
|
|
|
|
|
} else if (!compress_file(lr->control))
|
|
|
|
|
return false;
|
2011-08-13 09:43:19 +02:00
|
|
|
|
|
|
|
|
/* compute total time */
|
|
|
|
|
gettimeofday(&end_time, NULL);
|
|
|
|
|
total_time = (end_time.tv_sec + (double)end_time.tv_usec / 1000000) -
|
2011-09-13 06:40:51 +02:00
|
|
|
(start_time.tv_sec + (double)start_time.tv_usec / 1000000);
|
2011-08-13 09:43:19 +02:00
|
|
|
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);
|
2011-08-12 08:42:57 +02:00
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2011-08-13 09:43:19 +02:00
|
|
|
|
|
|
|
|
void lrzip_log_level_set(Lrzip *lr, int level)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return;
|
2011-08-13 09:43:19 +02:00
|
|
|
lr->control->log_level = level;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int lrzip_log_level_get(Lrzip *lr)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return 0;
|
2011-08-13 09:43:19 +02:00
|
|
|
return lr->control->log_level;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void lrzip_log_cb_set(Lrzip *lr, Lrzip_Log_Cb cb, void *log_data)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return;
|
2015-03-10 10:27:38 +01:00
|
|
|
lr->control->log_cb = cb;
|
2011-08-13 09:43:19 +02:00
|
|
|
lr->control->log_data = log_data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void lrzip_log_stdout_set(Lrzip *lr, FILE *out)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return;
|
2011-08-13 09:43:19 +02:00
|
|
|
lr->control->msgout = out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FILE *lrzip_log_stdout_get(Lrzip *lr)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return NULL;
|
2011-08-13 09:43:19 +02:00
|
|
|
return lr->control->msgout;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void lrzip_log_stderr_set(Lrzip *lr, FILE *err)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return;
|
2011-08-13 09:43:19 +02:00
|
|
|
lr->control->msgerr = err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FILE *lrzip_log_stderr_get(Lrzip *lr)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return NULL;
|
2011-08-13 09:43:19 +02:00
|
|
|
return lr->control->msgerr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void lrzip_pass_cb_set(Lrzip *lr, Lrzip_Password_Cb cb, void *data)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return;
|
2015-03-10 10:27:38 +01:00
|
|
|
lr->control->pass_cb = cb;
|
2011-08-13 09:43:19 +02:00
|
|
|
lr->control->pass_data = data;
|
|
|
|
|
}
|
2011-08-13 10:05:01 +02:00
|
|
|
|
|
|
|
|
void lrzip_info_cb_set(Lrzip *lr, Lrzip_Info_Cb cb, void *data)
|
|
|
|
|
{
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
|
|
|
|
return;
|
2015-03-10 10:27:38 +01:00
|
|
|
lr->control->info_cb = cb;
|
2011-08-13 10:05:01 +02:00
|
|
|
lr->control->info_data = data;
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-17 13:03:02 +02:00
|
|
|
bool lrzip_compress_full(void *dest, unsigned long *dest_len, const void *source, unsigned long source_len, Lrzip_Mode mode, int compress_level)
|
|
|
|
|
{
|
2015-02-08 23:19:03 +01:00
|
|
|
FILE *s = NULL, *d = NULL;
|
|
|
|
|
Lrzip *lr = NULL;
|
|
|
|
|
bool ret = false;
|
2011-08-17 13:03:02 +02:00
|
|
|
struct stat st;
|
|
|
|
|
int fd;
|
|
|
|
|
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!dest) || (!dest_len) || (!source) || (!source_len) || (mode < LRZIP_MODE_COMPRESS_NONE))
|
2015-02-08 23:19:03 +01:00
|
|
|
goto out;
|
2011-08-17 13:03:02 +02:00
|
|
|
|
|
|
|
|
lrzip_init();
|
|
|
|
|
if (!mode) mode = LRZIP_MODE_COMPRESS_LZMA;
|
|
|
|
|
lr = lrzip_new(mode);
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
2015-02-08 23:19:03 +01:00
|
|
|
goto out;
|
2011-08-17 13:03:02 +02:00
|
|
|
lrzip_config_env(lr);
|
|
|
|
|
|
|
|
|
|
s = fmemopen((void*)source, source_len, "r");
|
|
|
|
|
d = tmpfile();
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!s) || (!d))
|
2015-02-08 23:19:03 +01:00
|
|
|
goto out;
|
2011-08-17 13:03:02 +02:00
|
|
|
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lrzip_file_add(lr, s))
|
2015-02-08 23:19:03 +01:00
|
|
|
goto out;
|
2011-08-17 13:03:02 +02:00
|
|
|
lrzip_outfile_set(lr, d);
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lrzip_compression_level_set(lr, compress_level))
|
2015-02-08 23:19:03 +01:00
|
|
|
goto out;
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lrzip_run(lr))
|
2015-02-08 23:19:03 +01:00
|
|
|
goto out;
|
2011-08-17 13:03:02 +02:00
|
|
|
|
|
|
|
|
fd = fileno(d);
|
2011-09-13 06:53:11 +02:00
|
|
|
if (fstat(fd, &st))
|
2015-02-08 23:19:03 +01:00
|
|
|
goto out;
|
2011-08-17 13:03:02 +02:00
|
|
|
*dest_len = st.st_size;
|
2012-03-07 03:01:39 +01:00
|
|
|
if (unlikely((i64)fread(dest, sizeof(char), st.st_size, d) != st.st_size))
|
2015-02-08 23:19:03 +01:00
|
|
|
goto out;
|
2011-08-17 13:16:37 +02:00
|
|
|
if (unlikely(ferror(d)))
|
2015-02-08 23:19:03 +01:00
|
|
|
goto out;
|
|
|
|
|
ret = true;
|
2011-08-17 13:03:02 +02:00
|
|
|
|
2015-02-08 23:19:03 +01:00
|
|
|
out:
|
2011-08-17 13:03:02 +02:00
|
|
|
if (s) fclose(s);
|
|
|
|
|
if (d) fclose(d);
|
|
|
|
|
lrzip_free(lr);
|
2015-02-08 23:19:03 +01:00
|
|
|
return ret;
|
2011-08-17 13:03:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool lrzip_decompress(void *dest, unsigned long *dest_len, const void *source, unsigned long source_len)
|
|
|
|
|
{
|
2015-02-08 23:19:03 +01:00
|
|
|
FILE *s = NULL, *d = NULL;
|
|
|
|
|
Lrzip *lr = NULL;
|
|
|
|
|
bool ret = false;
|
2011-08-17 13:03:02 +02:00
|
|
|
struct stat st;
|
|
|
|
|
int fd;
|
|
|
|
|
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!dest) || (!dest_len) || (!source) || (!source_len))
|
2015-02-08 23:19:03 +01:00
|
|
|
goto out;
|
2011-08-17 13:03:02 +02:00
|
|
|
|
|
|
|
|
lrzip_init();
|
|
|
|
|
lr = lrzip_new(LRZIP_MODE_DECOMPRESS);
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lr)
|
2015-02-08 23:19:03 +01:00
|
|
|
goto out;
|
2011-08-17 13:03:02 +02:00
|
|
|
lrzip_config_env(lr);
|
|
|
|
|
|
|
|
|
|
s = fmemopen((void*)source, source_len, "r");
|
|
|
|
|
d = tmpfile();
|
2011-09-13 06:53:11 +02:00
|
|
|
if ((!s) || (!d))
|
2015-02-08 23:19:03 +01:00
|
|
|
goto out;
|
2011-08-17 13:03:02 +02:00
|
|
|
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lrzip_file_add(lr, s))
|
2015-02-08 23:19:03 +01:00
|
|
|
goto out;
|
2011-08-17 13:03:02 +02:00
|
|
|
lrzip_outfile_set(lr, d);
|
2011-09-13 06:53:11 +02:00
|
|
|
if (!lrzip_run(lr))
|
2015-02-08 23:19:03 +01:00
|
|
|
goto out;
|
2011-08-17 13:03:02 +02:00
|
|
|
|
|
|
|
|
fd = fileno(d);
|
2011-09-13 06:53:11 +02:00
|
|
|
if (fstat(fd, &st))
|
2015-02-08 23:19:03 +01:00
|
|
|
goto out;
|
2011-08-17 13:03:02 +02:00
|
|
|
*dest_len = st.st_size;
|
2012-03-07 03:01:39 +01:00
|
|
|
if (unlikely((i64)fread(dest, sizeof(char), st.st_size, d) != st.st_size))
|
2015-02-08 23:19:03 +01:00
|
|
|
goto out;
|
2011-08-17 13:16:37 +02:00
|
|
|
if (unlikely(ferror(d)))
|
2015-02-08 23:19:03 +01:00
|
|
|
goto out;
|
|
|
|
|
ret = true;
|
2011-08-17 13:03:02 +02:00
|
|
|
|
2015-02-08 23:19:03 +01:00
|
|
|
out:
|
2011-08-17 13:03:02 +02:00
|
|
|
if (s) fclose(s);
|
|
|
|
|
if (d) fclose(d);
|
|
|
|
|
lrzip_free(lr);
|
2015-02-08 23:19:03 +01:00
|
|
|
return ret;
|
2011-08-17 13:03:02 +02:00
|
|
|
}
|