Archiving support using Libarchive: Working archive extraction.
This commit is contained in:
parent
8e4b774c8c
commit
e09d8a485c
4 changed files with 264 additions and 37 deletions
|
@ -104,7 +104,7 @@ add_pathname(const char *fpath, const struct stat *sb,
|
||||||
* sets up the libarchive context.
|
* sets up the libarchive context.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
setup_archive(pc_ctx_t *pctx, struct stat *sbuf)
|
setup_archiver(pc_ctx_t *pctx, struct stat *sbuf)
|
||||||
{
|
{
|
||||||
char *tmpfile, *tmp;
|
char *tmpfile, *tmp;
|
||||||
int err, fd, pipefd[2];
|
int err, fd, pipefd[2];
|
||||||
|
@ -176,14 +176,15 @@ setup_archive(pc_ctx_t *pctx, struct stat *sbuf)
|
||||||
a_state.bufpos = 0;
|
a_state.bufpos = 0;
|
||||||
}
|
}
|
||||||
pctx->archive_size += a_state.arc_size;
|
pctx->archive_size += a_state.arc_size;
|
||||||
sbuf->st_size += a_state.arc_size;
|
|
||||||
fn = fn->next;
|
fn = fn->next;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&nftw_mutex);
|
pthread_mutex_unlock(&nftw_mutex);
|
||||||
|
sbuf->st_size = pctx->archive_size;
|
||||||
lseek(fd, 0, SEEK_SET);
|
lseek(fd, 0, SEEK_SET);
|
||||||
free(pbuf);
|
free(pbuf);
|
||||||
sbuf->st_uid = geteuid();
|
sbuf->st_uid = geteuid();
|
||||||
sbuf->st_gid = getegid();
|
sbuf->st_gid = getegid();
|
||||||
|
sbuf->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||||
|
|
||||||
if (pipe(pipefd) == -1) {
|
if (pipe(pipefd) == -1) {
|
||||||
log_msg(LOG_ERR, 1, "Unable to create archiver pipe.\n");
|
log_msg(LOG_ERR, 1, "Unable to create archiver pipe.\n");
|
||||||
|
@ -208,6 +209,32 @@ setup_archive(pc_ctx_t *pctx, struct stat *sbuf)
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
setup_extractor(pc_ctx_t *pctx)
|
||||||
|
{
|
||||||
|
int pipefd[2];
|
||||||
|
struct archive *arc;
|
||||||
|
|
||||||
|
if (pipe(pipefd) == -1) {
|
||||||
|
log_msg(LOG_ERR, 1, "Unable to create extractor pipe.\n");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pctx->uncompfd = pipefd[1]; // Write side
|
||||||
|
pctx->archive_data_fd = pipefd[0]; // Read side
|
||||||
|
|
||||||
|
arc = archive_read_new();
|
||||||
|
if (!arc) {
|
||||||
|
log_msg(LOG_ERR, 1, "Unable to create libarchive context.\n");
|
||||||
|
close(pipefd[0]); close(pipefd[1]);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
archive_read_support_format_all(arc);
|
||||||
|
pctx->archive_ctx = arc;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Routines to archive members and write the archive to pipe. Most of the following
|
* Routines to archive members and write the archive to pipe. Most of the following
|
||||||
* code is adapted from some of the Libarchive bsdtar code.
|
* code is adapted from some of the Libarchive bsdtar code.
|
||||||
|
@ -296,7 +323,7 @@ write_entry(pc_ctx_t *pctx, struct archive *arc, struct archive *in_arc,
|
||||||
* reads from the other end and compresses.
|
* reads from the other end and compresses.
|
||||||
*/
|
*/
|
||||||
static void *
|
static void *
|
||||||
archive_thread_func(void *dat) {
|
archiver_thread_func(void *dat) {
|
||||||
pc_ctx_t *pctx = (pc_ctx_t *)dat;
|
pc_ctx_t *pctx = (pc_ctx_t *)dat;
|
||||||
char fpath[PATH_MAX], *name;
|
char fpath[PATH_MAX], *name;
|
||||||
ssize_t rbytes;
|
ssize_t rbytes;
|
||||||
|
@ -390,5 +417,87 @@ done:
|
||||||
|
|
||||||
int
|
int
|
||||||
start_archiver(pc_ctx_t *pctx) {
|
start_archiver(pc_ctx_t *pctx) {
|
||||||
return (pthread_create(&(pctx->archive_thread), NULL, archive_thread_func, (void *)pctx));
|
return (pthread_create(&(pctx->archive_thread), NULL, archiver_thread_func, (void *)pctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract Thread function. Read an uncompressed archive from the pipe and extract
|
||||||
|
* members to disk. The decompressor writes to the other end of the pipe.
|
||||||
|
*/
|
||||||
|
static void *
|
||||||
|
extractor_thread_func(void *dat) {
|
||||||
|
pc_ctx_t *pctx = (pc_ctx_t *)dat;
|
||||||
|
char cwd[PATH_MAX], got_cwd;
|
||||||
|
int flags, rv;
|
||||||
|
struct archive_entry *entry;
|
||||||
|
struct archive *awd, *arc;
|
||||||
|
|
||||||
|
flags = ARCHIVE_EXTRACT_TIME;
|
||||||
|
flags |= ARCHIVE_EXTRACT_PERM;
|
||||||
|
flags |= ARCHIVE_EXTRACT_ACL;
|
||||||
|
flags |= ARCHIVE_EXTRACT_FFLAGS;
|
||||||
|
|
||||||
|
got_cwd = 1;
|
||||||
|
if (getcwd(cwd, PATH_MAX) == NULL) {
|
||||||
|
log_msg(LOG_WARN, 1, "Cannot get current directory.");
|
||||||
|
got_cwd = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chdir(pctx->to_filename) == -1) {
|
||||||
|
log_msg(LOG_ERR, 1, "Cannot change to dir: %s", pctx->to_filename);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
awd = archive_write_disk_new();
|
||||||
|
archive_write_disk_set_options(awd, flags);
|
||||||
|
archive_write_disk_set_standard_lookup(awd);
|
||||||
|
arc = (struct archive *)(pctx->archive_ctx);
|
||||||
|
archive_read_open_fd(arc, pctx->archive_data_fd, MMAP_SIZE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read archive entries and extract to disk.
|
||||||
|
*/
|
||||||
|
while ((rv = archive_read_next_header(arc, &entry)) != ARCHIVE_EOF) {
|
||||||
|
if (rv != ARCHIVE_OK)
|
||||||
|
log_msg(LOG_WARN, 0, "%s", archive_error_string(arc));
|
||||||
|
|
||||||
|
if (rv == ARCHIVE_FATAL) {
|
||||||
|
log_msg(LOG_ERR, 0, "Fatal error aborting extraction.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rv == ARCHIVE_RETRY) {
|
||||||
|
log_msg(LOG_INFO, 0, "Retrying extractor read ...");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = archive_read_extract2(arc, entry, awd);
|
||||||
|
if (rv != ARCHIVE_OK) {
|
||||||
|
log_msg(LOG_WARN, 0, "%s: %s", archive_entry_pathname(entry),
|
||||||
|
archive_error_string(arc));
|
||||||
|
|
||||||
|
} else if (pctx->verbose) {
|
||||||
|
log_msg(LOG_INFO, 0, "%10d %s", archive_entry_size(entry),
|
||||||
|
archive_entry_pathname(entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rv == ARCHIVE_FATAL) {
|
||||||
|
log_msg(LOG_ERR, 0, "Fatal error aborting extraction.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (got_cwd) {
|
||||||
|
rv = chdir(cwd);
|
||||||
|
}
|
||||||
|
archive_read_free(arc);
|
||||||
|
archive_write_free(awd);
|
||||||
|
done:
|
||||||
|
close(pctx->archive_data_fd);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
start_extractor(pc_ctx_t *pctx) {
|
||||||
|
return (pthread_create(&(pctx->archive_thread), NULL, extractor_thread_func, (void *)pctx));
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,8 +41,10 @@ typedef struct {
|
||||||
/*
|
/*
|
||||||
* Archiving related functions.
|
* Archiving related functions.
|
||||||
*/
|
*/
|
||||||
int setup_archive(pc_ctx_t *pctx, struct stat *sbuf);
|
int setup_archiver(pc_ctx_t *pctx, struct stat *sbuf);
|
||||||
int start_archiver(pc_ctx_t *pctx);
|
int start_archiver(pc_ctx_t *pctx);
|
||||||
|
int setup_extractor(pc_ctx_t *pctx);
|
||||||
|
int start_extractor(pc_ctx_t *pctx);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
168
pcompress.c
168
pcompress.c
|
@ -53,6 +53,7 @@
|
||||||
#include <crypto/crypto_utils.h>
|
#include <crypto/crypto_utils.h>
|
||||||
#include <crypto_xsalsa20.h>
|
#include <crypto_xsalsa20.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <pc_archive.h>
|
#include <pc_archive.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -644,7 +645,7 @@ cont:
|
||||||
#define UNCOMP_BAIL err = 1; goto uncomp_done
|
#define UNCOMP_BAIL err = 1; goto uncomp_done
|
||||||
|
|
||||||
int DLL_EXPORT
|
int DLL_EXPORT
|
||||||
start_decompress(pc_ctx_t *pctx, const char *filename, const char *to_filename)
|
start_decompress(pc_ctx_t *pctx, const char *filename, char *to_filename)
|
||||||
{
|
{
|
||||||
char algorithm[ALGO_SZ];
|
char algorithm[ALGO_SZ];
|
||||||
struct stat sbuf;
|
struct stat sbuf;
|
||||||
|
@ -689,23 +690,12 @@ start_decompress(pc_ctx_t *pctx, const char *filename, const char *to_filename)
|
||||||
if (sbuf.st_size == 0)
|
if (sbuf.st_size == 0)
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((uncompfd = open(to_filename, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR)) == -1) {
|
|
||||||
close(compfd);
|
|
||||||
log_msg(LOG_ERR, 1, "Cannot open: %s", to_filename);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
compfd = fileno(stdin);
|
compfd = fileno(stdin);
|
||||||
if (compfd == -1) {
|
if (compfd == -1) {
|
||||||
log_msg(LOG_ERR, 1, "fileno ");
|
log_msg(LOG_ERR, 1, "fileno ");
|
||||||
UNCOMP_BAIL;
|
UNCOMP_BAIL;
|
||||||
}
|
}
|
||||||
uncompfd = fileno(stdout);
|
|
||||||
if (uncompfd == -1) {
|
|
||||||
log_msg(LOG_ERR, 1, "fileno ");
|
|
||||||
UNCOMP_BAIL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -762,6 +752,76 @@ start_decompress(pc_ctx_t *pctx, const char *filename, const char *to_filename)
|
||||||
goto uncomp_done;
|
goto uncomp_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First check for archive mode. In that case the to_filename must be a directory.
|
||||||
|
*/
|
||||||
|
if (flags & FLAG_ARCHIVE) {
|
||||||
|
/*
|
||||||
|
* If to_filename is not set, we just use the current directory.
|
||||||
|
*/
|
||||||
|
if (to_filename == NULL) {
|
||||||
|
to_filename = ".";
|
||||||
|
pctx->to_filename = ".";
|
||||||
|
}
|
||||||
|
pctx->archive_mode = 1;
|
||||||
|
if (stat(to_filename, &sbuf) == -1) {
|
||||||
|
if (errno != ENOENT) {
|
||||||
|
log_msg(LOG_ERR, 1, "Target path is not a directory.");
|
||||||
|
err = 1;
|
||||||
|
goto uncomp_done;
|
||||||
|
}
|
||||||
|
if (mkdir(to_filename, S_IRUSR|S_IWUSR) == -1) {
|
||||||
|
log_msg(LOG_ERR, 1, "Unable to create target directory %s.", to_filename);
|
||||||
|
err = 1;
|
||||||
|
goto uncomp_done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!S_ISDIR(sbuf.st_mode)) {
|
||||||
|
log_msg(LOG_ERR, 0, "Target path is not a directory.", to_filename);
|
||||||
|
err = 1;
|
||||||
|
goto uncomp_done;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const char *origf;
|
||||||
|
|
||||||
|
if (to_filename == NULL) {
|
||||||
|
char *pos;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use unused space in archive_members_file buffer to hold generated
|
||||||
|
* filename so that it need not be explicitly freed at the end.
|
||||||
|
*/
|
||||||
|
to_filename = pctx->archive_members_file;
|
||||||
|
pctx->to_filename = pctx->archive_members_file;
|
||||||
|
pos = strrchr(filename, '.');
|
||||||
|
if (pos != NULL) {
|
||||||
|
if ((pos[0] == 'p' || pos[0] == 'P') && (pos[1] == 'z' || pos[1] == 'Z')) {
|
||||||
|
memcpy(to_filename, filename, pos - filename);
|
||||||
|
} else {
|
||||||
|
pos = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If no .pz extension is found then use <filename>.out as the
|
||||||
|
* decompressed file name.
|
||||||
|
*/
|
||||||
|
if (pos == NULL) {
|
||||||
|
strcpy(to_filename, filename);
|
||||||
|
strcat(to_filename, ".out");
|
||||||
|
log_msg(LOG_WARN, 0, "Using %s for output file name.", to_filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
origf = to_filename;
|
||||||
|
if ((to_filename = realpath(origf, NULL)) != NULL) {
|
||||||
|
free((void *)(to_filename));
|
||||||
|
log_msg(LOG_ERR, 0, "File %s exists", origf);
|
||||||
|
err = 1;
|
||||||
|
goto uncomp_done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
compressed_chunksize = chunksize + CHUNK_HDR_SZ + zlib_buf_extra(chunksize);
|
compressed_chunksize = chunksize + CHUNK_HDR_SZ + zlib_buf_extra(chunksize);
|
||||||
|
|
||||||
if (pctx->_props_func) {
|
if (pctx->_props_func) {
|
||||||
|
@ -955,7 +1015,6 @@ start_decompress(pc_ctx_t *pctx, const char *filename, const char *to_filename)
|
||||||
free(salt2);
|
free(salt2);
|
||||||
memset(salt1, 0, saltlen);
|
memset(salt1, 0, saltlen);
|
||||||
free(salt1);
|
free(salt1);
|
||||||
close(uncompfd); unlink(to_filename);
|
|
||||||
log_msg(LOG_ERR, 0, "Failed to get password.");
|
log_msg(LOG_ERR, 0, "Failed to get password.");
|
||||||
UNCOMP_BAIL;
|
UNCOMP_BAIL;
|
||||||
}
|
}
|
||||||
|
@ -970,7 +1029,6 @@ start_decompress(pc_ctx_t *pctx, const char *filename, const char *to_filename)
|
||||||
memset(salt1, 0, saltlen);
|
memset(salt1, 0, saltlen);
|
||||||
free(salt1);
|
free(salt1);
|
||||||
memset(pctx->user_pw, 0, pctx->user_pw_len);
|
memset(pctx->user_pw, 0, pctx->user_pw_len);
|
||||||
close(uncompfd); unlink(to_filename);
|
|
||||||
log_msg(LOG_ERR, 0, "Failed to initialize crypto");
|
log_msg(LOG_ERR, 0, "Failed to initialize crypto");
|
||||||
UNCOMP_BAIL;
|
UNCOMP_BAIL;
|
||||||
}
|
}
|
||||||
|
@ -985,7 +1043,6 @@ start_decompress(pc_ctx_t *pctx, const char *filename, const char *to_filename)
|
||||||
memset(salt1, 0, saltlen);
|
memset(salt1, 0, saltlen);
|
||||||
free(salt1);
|
free(salt1);
|
||||||
memset(pw, 0, MAX_PW_LEN);
|
memset(pw, 0, MAX_PW_LEN);
|
||||||
close(uncompfd); unlink(to_filename);
|
|
||||||
log_msg(LOG_ERR, 0, "Failed to initialize crypto");
|
log_msg(LOG_ERR, 0, "Failed to initialize crypto");
|
||||||
UNCOMP_BAIL;
|
UNCOMP_BAIL;
|
||||||
}
|
}
|
||||||
|
@ -999,7 +1056,6 @@ start_decompress(pc_ctx_t *pctx, const char *filename, const char *to_filename)
|
||||||
* Verify file header HMAC.
|
* Verify file header HMAC.
|
||||||
*/
|
*/
|
||||||
if (hmac_init(&hdr_mac, pctx->cksum, &(pctx->crypto_ctx)) == -1) {
|
if (hmac_init(&hdr_mac, pctx->cksum, &(pctx->crypto_ctx)) == -1) {
|
||||||
close(uncompfd); unlink(to_filename);
|
|
||||||
log_msg(LOG_ERR, 0, "Cannot initialize header hmac.");
|
log_msg(LOG_ERR, 0, "Cannot initialize header hmac.");
|
||||||
UNCOMP_BAIL;
|
UNCOMP_BAIL;
|
||||||
}
|
}
|
||||||
|
@ -1026,7 +1082,6 @@ start_decompress(pc_ctx_t *pctx, const char *filename, const char *to_filename)
|
||||||
free(salt1);
|
free(salt1);
|
||||||
memset(n1, 0, noncelen);
|
memset(n1, 0, noncelen);
|
||||||
if (memcmp(hdr_hash2, hdr_hash1, pctx->mac_bytes) != 0) {
|
if (memcmp(hdr_hash2, hdr_hash1, pctx->mac_bytes) != 0) {
|
||||||
close(uncompfd); unlink(to_filename);
|
|
||||||
log_msg(LOG_ERR, 0, "Header verification failed! File tampered or wrong password.");
|
log_msg(LOG_ERR, 0, "Header verification failed! File tampered or wrong password.");
|
||||||
UNCOMP_BAIL;
|
UNCOMP_BAIL;
|
||||||
}
|
}
|
||||||
|
@ -1056,12 +1111,48 @@ start_decompress(pc_ctx_t *pctx, const char *filename, const char *to_filename)
|
||||||
d2 = htonl(level);
|
d2 = htonl(level);
|
||||||
crc2 = lzma_crc32((uchar_t *)&d2, sizeof (level), crc2);
|
crc2 = lzma_crc32((uchar_t *)&d2, sizeof (level), crc2);
|
||||||
if (crc1 != crc2) {
|
if (crc1 != crc2) {
|
||||||
close(uncompfd); unlink(to_filename);
|
|
||||||
log_msg(LOG_ERR, 0, "Header verification failed! File tampered or wrong password.");
|
log_msg(LOG_ERR, 0, "Header verification failed! File tampered or wrong password.");
|
||||||
UNCOMP_BAIL;
|
UNCOMP_BAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & FLAG_ARCHIVE) {
|
||||||
|
if (pctx->enable_rabin_global) {
|
||||||
|
strcpy(pctx->archive_temp_file, to_filename);
|
||||||
|
strcat(pctx->archive_temp_file, "/.data");
|
||||||
|
if ((pctx->archive_temp_fd = open(pctx->archive_temp_file,
|
||||||
|
O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR)) == -1) {
|
||||||
|
log_msg(LOG_ERR, 1, "Cannot open temporary data file in target directory.");
|
||||||
|
UNCOMP_BAIL;
|
||||||
|
}
|
||||||
|
add_fname(pctx->archive_temp_file);
|
||||||
|
}
|
||||||
|
if (setup_extractor(pctx) == -1) {
|
||||||
|
log_msg(LOG_ERR, 0, "Setup of extraction context failed.");
|
||||||
|
UNCOMP_BAIL;
|
||||||
|
}
|
||||||
|
uncompfd = pctx->uncompfd;
|
||||||
|
|
||||||
|
if (start_extractor(pctx) == -1) {
|
||||||
|
log_msg(LOG_ERR, 0, "Unable to start extraction thread.");
|
||||||
|
UNCOMP_BAIL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!pctx->pipe_mode) {
|
||||||
|
if ((uncompfd = open(to_filename, O_WRONLY|O_CREAT|O_TRUNC,
|
||||||
|
S_IRUSR|S_IWUSR)) == -1) {
|
||||||
|
log_msg(LOG_ERR, 1, "Cannot open: %s", to_filename);
|
||||||
|
UNCOMP_BAIL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uncompfd = fileno(stdout);
|
||||||
|
if (uncompfd == -1) {
|
||||||
|
log_msg(LOG_ERR, 1, "fileno ");
|
||||||
|
UNCOMP_BAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nprocs = sysconf(_SC_NPROCESSORS_ONLN);
|
nprocs = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
if (pctx->nthreads > 0 && pctx->nthreads < nprocs)
|
if (pctx->nthreads > 0 && pctx->nthreads < nprocs)
|
||||||
nprocs = pctx->nthreads;
|
nprocs = pctx->nthreads;
|
||||||
|
@ -1126,10 +1217,20 @@ start_decompress(pc_ctx_t *pctx, const char *filename, const char *to_filename)
|
||||||
UNCOMP_BAIL;
|
UNCOMP_BAIL;
|
||||||
}
|
}
|
||||||
if (pctx->enable_rabin_global) {
|
if (pctx->enable_rabin_global) {
|
||||||
if ((tdat->rctx->out_fd = open(to_filename, O_RDONLY, 0)) == -1) {
|
if (pctx->archive_mode) {
|
||||||
log_msg(LOG_ERR, 1, "Unable to get new read handle to output file");
|
if ((tdat->rctx->out_fd = open(pctx->archive_temp_file,
|
||||||
|
O_RDONLY, 0)) == -1) {
|
||||||
|
log_msg(LOG_ERR, 1, "Unable to get new read handle"
|
||||||
|
" to output file");
|
||||||
UNCOMP_BAIL;
|
UNCOMP_BAIL;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if ((tdat->rctx->out_fd = open(to_filename, O_RDONLY, 0)) == -1) {
|
||||||
|
log_msg(LOG_ERR, 1, "Unable to get new read handle"
|
||||||
|
" to output file");
|
||||||
|
UNCOMP_BAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tdat->rctx->index_sem = &(tdat->index_sem);
|
tdat->rctx->index_sem = &(tdat->index_sem);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1326,6 +1427,13 @@ uncomp_done:
|
||||||
if (filename && compfd != -1) close(compfd);
|
if (filename && compfd != -1) close(compfd);
|
||||||
if (uncompfd != -1) close(uncompfd);
|
if (uncompfd != -1) close(uncompfd);
|
||||||
}
|
}
|
||||||
|
if (pctx->archive_mode) {
|
||||||
|
pthread_join(pctx->archive_thread, NULL);
|
||||||
|
if (pctx->enable_rabin_global) {
|
||||||
|
close(pctx->archive_temp_fd);
|
||||||
|
unlink(pctx->archive_temp_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!pctx->hide_cmp_stats) show_compression_stats(pctx);
|
if (!pctx->hide_cmp_stats) show_compression_stats(pctx);
|
||||||
|
|
||||||
|
@ -1630,6 +1738,9 @@ repeat:
|
||||||
}
|
}
|
||||||
|
|
||||||
wbytes = Write(w->wfd, tdat->cmp_seg, tdat->len_cmp);
|
wbytes = Write(w->wfd, tdat->cmp_seg, tdat->len_cmp);
|
||||||
|
if (pctx->archive_temp_fd != -1 && wbytes == tdat->len_cmp) {
|
||||||
|
wbytes = Write(pctx->archive_temp_fd, tdat->cmp_seg, tdat->len_cmp);
|
||||||
|
}
|
||||||
if (unlikely(wbytes != tdat->len_cmp)) {
|
if (unlikely(wbytes != tdat->len_cmp)) {
|
||||||
log_msg(LOG_ERR, 1, "Chunk Write: ");
|
log_msg(LOG_ERR, 1, "Chunk Write: ");
|
||||||
do_cancel:
|
do_cancel:
|
||||||
|
@ -1786,8 +1897,8 @@ start_compress(pc_ctx_t *pctx, const char *filename, uint64_t chunksize, int lev
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (setup_archive(pctx, &sbuf) == -1) {
|
if (setup_archiver(pctx, &sbuf) == -1) {
|
||||||
log_msg(LOG_ERR, 0, "Setup archive failed for %s", pctx->filename);
|
log_msg(LOG_ERR, 0, "Setup archiver failed.");
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2074,6 +2185,7 @@ start_compress(pc_ctx_t *pctx, const char *filename, uint64_t chunksize, int lev
|
||||||
if (start_archiver(pctx) != 0) {
|
if (start_archiver(pctx) != 0) {
|
||||||
COMP_BAIL;
|
COMP_BAIL;
|
||||||
}
|
}
|
||||||
|
flags |= FLAG_ARCHIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2552,6 +2664,7 @@ create_pc_context(void)
|
||||||
ctx->hide_cmp_stats = 1;
|
ctx->hide_cmp_stats = 1;
|
||||||
ctx->enable_rabin_split = 1;
|
ctx->enable_rabin_split = 1;
|
||||||
ctx->rab_blk_size = -1;
|
ctx->rab_blk_size = -1;
|
||||||
|
ctx->archive_temp_fd = -1;
|
||||||
|
|
||||||
return (ctx);
|
return (ctx);
|
||||||
}
|
}
|
||||||
|
@ -2906,7 +3019,7 @@ init_pc_context(pc_ctx_t *pctx, int argc, char *argv[])
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (pctx->do_uncompress && num_rem == 2) {
|
} else if (pctx->do_uncompress) {
|
||||||
/*
|
/*
|
||||||
* While decompressing, input can be stdin and output a physical file.
|
* While decompressing, input can be stdin and output a physical file.
|
||||||
*/
|
*/
|
||||||
|
@ -2918,13 +3031,12 @@ init_pc_context(pc_ctx_t *pctx, int argc, char *argv[])
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (num_rem == 2) {
|
||||||
my_optind++;
|
my_optind++;
|
||||||
if ((pctx->to_filename = realpath(argv[my_optind], NULL)) != NULL) {
|
|
||||||
free((void *)(pctx->to_filename));
|
|
||||||
log_msg(LOG_ERR, 0, "File %s exists", argv[my_optind]);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
pctx->to_filename = argv[my_optind];
|
pctx->to_filename = argv[my_optind];
|
||||||
|
} else {
|
||||||
|
pctx->to_filename = NULL;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ extern "C" {
|
||||||
#define FLAG_DEDUP 1
|
#define FLAG_DEDUP 1
|
||||||
#define FLAG_DEDUP_FIXED 2
|
#define FLAG_DEDUP_FIXED 2
|
||||||
#define FLAG_SINGLE_CHUNK 4
|
#define FLAG_SINGLE_CHUNK 4
|
||||||
|
#define FLAG_ARCHIVE 2048
|
||||||
#define UTILITY_VERSION "2.4"
|
#define UTILITY_VERSION "2.4"
|
||||||
#define MASK_CRYPTO_ALG 0x30
|
#define MASK_CRYPTO_ALG 0x30
|
||||||
#define MAX_LEVEL 14
|
#define MAX_LEVEL 14
|
||||||
|
@ -204,10 +205,13 @@ typedef struct pc_ctx {
|
||||||
void *archive_ctx;
|
void *archive_ctx;
|
||||||
pthread_t archive_thread;
|
pthread_t archive_thread;
|
||||||
int uncompfd, compfd;
|
int uncompfd, compfd;
|
||||||
|
char archive_temp_file[MAXPATHLEN];
|
||||||
|
int archive_temp_fd;
|
||||||
unsigned int chunk_num;
|
unsigned int chunk_num;
|
||||||
uint64_t largest_chunk, smallest_chunk, avg_chunk;
|
uint64_t largest_chunk, smallest_chunk, avg_chunk;
|
||||||
uint64_t chunksize, archive_size;
|
uint64_t chunksize, archive_size;
|
||||||
const char *algo, *filename, *to_filename;
|
const char *algo, *filename;
|
||||||
|
char *to_filename;
|
||||||
struct fn_list *fn;
|
struct fn_list *fn;
|
||||||
char *exec_name;
|
char *exec_name;
|
||||||
int do_compress, level;
|
int do_compress, level;
|
||||||
|
@ -259,7 +263,7 @@ void pc_set_userpw(pc_ctx_t *pctx, unsigned char *pwdata, int pwlen);
|
||||||
|
|
||||||
int start_pcompress(pc_ctx_t *pctx);
|
int start_pcompress(pc_ctx_t *pctx);
|
||||||
int start_compress(pc_ctx_t *pctx, const char *filename, uint64_t chunksize, int level);
|
int start_compress(pc_ctx_t *pctx, const char *filename, uint64_t chunksize, int level);
|
||||||
int start_decompress(pc_ctx_t *pctx, const char *filename, const char *to_filename);
|
int start_decompress(pc_ctx_t *pctx, const char *filename, char *to_filename);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue