Basic capability to list contents of an archive without extracting to disk.
This commit is contained in:
parent
3ddaf6d45f
commit
62568e9066
4 changed files with 90 additions and 38 deletions
|
@ -147,13 +147,13 @@ Standard Usage
|
||||||
|
|
||||||
Decompression and Archive extraction
|
Decompression and Archive extraction
|
||||||
------------------------------------
|
------------------------------------
|
||||||
pcompress -d <compressed file or '-'> [-m] [-K] [<target file or directory>]
|
pcompress -d <compressed file or '-'> [-m] [-K] [-i] [<target file or directory>]
|
||||||
|
|
||||||
-m Enable restoring *all* permissions, ACLs, Extended Attributes etc.
|
-m Enable restoring *all* permissions, ACLs, Extended Attributes etc.
|
||||||
Equivalent to the '-p' option in tar. Ownership is only extracted if run as
|
Equivalent to the '-p' option in tar. Ownership is only extracted if run as
|
||||||
root user.
|
root user.
|
||||||
|
|
||||||
-K Do not overwrite newer files.
|
-K Do not overwrite newer files.
|
||||||
|
-i Only list contents of the archive, do not extract.
|
||||||
|
|
||||||
-m and -K are only meaningful if the compressed file is an archive. For single file
|
-m and -K are only meaningful if the compressed file is an archive. For single file
|
||||||
compressed mode these options are ignored.
|
compressed mode these options are ignored.
|
||||||
|
|
|
@ -1205,6 +1205,7 @@ copy_data_out(struct archive *ar, struct archive *aw, struct archive_entry *entr
|
||||||
return (r);
|
return (r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return (ARCHIVE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1235,6 +1236,34 @@ archive_extract_entry(struct archive *a, struct archive_entry *entry,
|
||||||
return (r);
|
return (r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
copy_data_skip(struct archive *ar, struct archive_entry *entry, int typ)
|
||||||
|
{
|
||||||
|
int64_t offset;
|
||||||
|
const void *buff;
|
||||||
|
size_t size;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
r = archive_read_data_block(ar, &buff, &size, &offset);
|
||||||
|
if (r == ARCHIVE_EOF)
|
||||||
|
return (ARCHIVE_OK);
|
||||||
|
if (r != ARCHIVE_OK)
|
||||||
|
return (r);
|
||||||
|
}
|
||||||
|
return (ARCHIVE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
archive_list_entry(struct archive *a, struct archive_entry *entry, int typ)
|
||||||
|
{
|
||||||
|
printf("%s\n", archive_entry_pathname(entry));
|
||||||
|
if (!archive_entry_size_is_set(entry) || archive_entry_size(entry) > 0) {
|
||||||
|
return (copy_data_skip(a, entry, typ));
|
||||||
|
}
|
||||||
|
return (ARCHIVE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Extract Thread function. Read an uncompressed archive from the decompressor stage
|
* Extract Thread function. Read an uncompressed archive from the decompressor stage
|
||||||
* and extract members to disk.
|
* and extract members to disk.
|
||||||
|
@ -1248,37 +1277,43 @@ extractor_thread_func(void *dat) {
|
||||||
struct archive_entry *entry;
|
struct archive_entry *entry;
|
||||||
struct archive *awd, *arc;
|
struct archive *awd, *arc;
|
||||||
|
|
||||||
flags = ARCHIVE_EXTRACT_TIME;
|
/* Silence compiler. */
|
||||||
flags |= ARCHIVE_EXTRACT_SECURE_SYMLINKS;
|
awd = NULL;
|
||||||
flags |= ARCHIVE_EXTRACT_SECURE_NODOTDOT;
|
got_cwd = 0;
|
||||||
flags |= ARCHIVE_EXTRACT_SPARSE;
|
|
||||||
|
|
||||||
/*
|
if (!pctx->list_mode) {
|
||||||
* Extract all security attributes if we are root.
|
flags = ARCHIVE_EXTRACT_TIME;
|
||||||
*/
|
flags |= ARCHIVE_EXTRACT_SECURE_SYMLINKS;
|
||||||
if (pctx->force_archive_perms || geteuid() == 0) {
|
flags |= ARCHIVE_EXTRACT_SECURE_NODOTDOT;
|
||||||
if (geteuid() == 0)
|
flags |= ARCHIVE_EXTRACT_SPARSE;
|
||||||
flags |= ARCHIVE_EXTRACT_OWNER;
|
|
||||||
flags |= ARCHIVE_EXTRACT_PERM;
|
/*
|
||||||
flags |= ARCHIVE_EXTRACT_ACL;
|
* Extract all security attributes if we are root.
|
||||||
flags |= ARCHIVE_EXTRACT_XATTR;
|
*/
|
||||||
flags |= ARCHIVE_EXTRACT_FFLAGS;
|
if (pctx->force_archive_perms || geteuid() == 0) {
|
||||||
flags |= ARCHIVE_EXTRACT_MAC_METADATA;
|
if (geteuid() == 0)
|
||||||
|
flags |= ARCHIVE_EXTRACT_OWNER;
|
||||||
|
flags |= ARCHIVE_EXTRACT_PERM;
|
||||||
|
flags |= ARCHIVE_EXTRACT_ACL;
|
||||||
|
flags |= ARCHIVE_EXTRACT_XATTR;
|
||||||
|
flags |= ARCHIVE_EXTRACT_FFLAGS;
|
||||||
|
flags |= ARCHIVE_EXTRACT_MAC_METADATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pctx->no_overwrite_newer)
|
||||||
|
flags |= ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER;
|
||||||
|
|
||||||
|
got_cwd = 1;
|
||||||
|
if (getcwd(cwd, PATH_MAX) == NULL) {
|
||||||
|
log_msg(LOG_WARN, 1, "Cannot get current directory.");
|
||||||
|
got_cwd = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
awd = archive_write_disk_new();
|
||||||
|
archive_write_disk_set_options(awd, flags);
|
||||||
|
archive_write_disk_set_standard_lookup(awd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pctx->no_overwrite_newer)
|
|
||||||
flags |= ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER;
|
|
||||||
|
|
||||||
got_cwd = 1;
|
|
||||||
if (getcwd(cwd, PATH_MAX) == NULL) {
|
|
||||||
log_msg(LOG_WARN, 1, "Cannot get current directory.");
|
|
||||||
got_cwd = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctr = 1;
|
ctr = 1;
|
||||||
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);
|
arc = (struct archive *)(pctx->archive_ctx);
|
||||||
archive_read_open(arc, pctx, arc_open_callback, extract_read_callback, extract_close_callback);
|
archive_read_open(arc, pctx, arc_open_callback, extract_read_callback, extract_close_callback);
|
||||||
|
|
||||||
|
@ -1286,9 +1321,11 @@ extractor_thread_func(void *dat) {
|
||||||
* Change directory after opening the archive, otherwise archive_read_open() can fail
|
* Change directory after opening the archive, otherwise archive_read_open() can fail
|
||||||
* for relative paths.
|
* for relative paths.
|
||||||
*/
|
*/
|
||||||
if (chdir(pctx->to_filename) == -1) {
|
if (!pctx->list_mode) {
|
||||||
log_msg(LOG_ERR, 1, "Cannot change to dir: %s", pctx->to_filename);
|
if (chdir(pctx->to_filename) == -1) {
|
||||||
goto done;
|
log_msg(LOG_ERR, 1, "Cannot change to dir: %s", pctx->to_filename);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1342,7 +1379,11 @@ extractor_thread_func(void *dat) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rv = archive_extract_entry(arc, entry, awd, typ);
|
if (!pctx->list_mode) {
|
||||||
|
rv = archive_extract_entry(arc, entry, awd, typ);
|
||||||
|
} else {
|
||||||
|
rv = archive_list_entry(arc, entry, typ);
|
||||||
|
}
|
||||||
if (rv != ARCHIVE_OK) {
|
if (rv != ARCHIVE_OK) {
|
||||||
log_msg(LOG_WARN, 0, "%s: %s", archive_entry_pathname(entry),
|
log_msg(LOG_WARN, 0, "%s: %s", archive_entry_pathname(entry),
|
||||||
archive_error_string(arc));
|
archive_error_string(arc));
|
||||||
|
@ -1359,8 +1400,10 @@ extractor_thread_func(void *dat) {
|
||||||
ctr++;
|
ctr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (got_cwd) {
|
if (!pctx->list_mode) {
|
||||||
rv = chdir(cwd);
|
if (got_cwd) {
|
||||||
|
rv = chdir(cwd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
archive_read_free(arc);
|
archive_read_free(arc);
|
||||||
archive_write_free(awd);
|
archive_write_free(awd);
|
||||||
|
|
12
pcompress.c
12
pcompress.c
|
@ -137,7 +137,8 @@ usage(pc_ctx_t *pctx)
|
||||||
" %s -d <compressed file or '-'> [-m] [-K] [<target file or directory>]\n\n"
|
" %s -d <compressed file or '-'> [-m] [-K] [<target file or directory>]\n\n"
|
||||||
" -m Enable restoring *all* permissions, ACLs, Extended Attributes etc.\n"
|
" -m Enable restoring *all* permissions, ACLs, Extended Attributes etc.\n"
|
||||||
" Equivalent to the '-p' option in tar.\n"
|
" Equivalent to the '-p' option in tar.\n"
|
||||||
" -K Do not overwrite newer files.\n\n"
|
" -K Do not overwrite newer files.\n"
|
||||||
|
" -i Only list contents of the archive, do not extract.\n\n"
|
||||||
" -m and -K are only meaningful if the compressed file is an archive. For single file\n"
|
" -m and -K are only meaningful if the compressed file is an archive. For single file\n"
|
||||||
" compressed mode these options are ignored.\n\n"
|
" compressed mode these options are ignored.\n\n"
|
||||||
" <compressed file>\n"
|
" <compressed file>\n"
|
||||||
|
@ -848,6 +849,11 @@ start_decompress(pc_ctx_t *pctx, const char *filename, char *to_filename)
|
||||||
} else {
|
} else {
|
||||||
const char *origf;
|
const char *origf;
|
||||||
|
|
||||||
|
if (pctx->list_mode) {
|
||||||
|
log_msg(LOG_ERR, 0, "Nothing to list. The compressed file is not an archive.");
|
||||||
|
err = 1;
|
||||||
|
goto uncomp_done;
|
||||||
|
}
|
||||||
if (to_filename == NULL) {
|
if (to_filename == NULL) {
|
||||||
char *pos;
|
char *pos;
|
||||||
|
|
||||||
|
@ -2827,11 +2833,13 @@ init_pc_context(pc_ctx_t *pctx, int argc, char *argv[])
|
||||||
ff.enable_packjpg = 0;
|
ff.enable_packjpg = 0;
|
||||||
|
|
||||||
pthread_mutex_lock(&opt_parse);
|
pthread_mutex_lock(&opt_parse);
|
||||||
while ((opt = getopt(argc, argv, "dc:s:l:pt:MCDGEe:w:LPS:B:Fk:avmKjx")) != -1) {
|
while ((opt = getopt(argc, argv, "dc:s:l:pt:MCDGEe:w:LPS:B:Fk:avmKjxi")) != -1) {
|
||||||
int ovr;
|
int ovr;
|
||||||
int64_t chunksize;
|
int64_t chunksize;
|
||||||
|
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
case 'i':
|
||||||
|
pctx->list_mode = 1; // List mode also sets decompress flag
|
||||||
case 'd':
|
case 'd':
|
||||||
pctx->do_uncompress = 1;
|
pctx->do_uncompress = 1;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -239,6 +239,7 @@ typedef struct pc_ctx {
|
||||||
int btype, ctype;
|
int btype, ctype;
|
||||||
int min_chunk;
|
int min_chunk;
|
||||||
int enable_packjpg;
|
int enable_packjpg;
|
||||||
|
int list_mode;
|
||||||
|
|
||||||
unsigned int chunk_num;
|
unsigned int chunk_num;
|
||||||
uint64_t largest_chunk, smallest_chunk, avg_chunk;
|
uint64_t largest_chunk, smallest_chunk, avg_chunk;
|
||||||
|
|
Loading…
Reference in a new issue