Commit 9808dbe6 authored by Bernhard Link's avatar Bernhard Link

add support for external uncompression programs

parent b5d64771
2008-09-07
* add support for external uncompression programs
- speeding up updating, as downloading and uncompressing
can happen at the same time
- support lzma compressed .deb and .diff (when unlzma is available)
- supporting .bz2 compressed files even when compiled without libbz2
(but needing runtime bunzip2 then)
2008-08-24
* unify reading of compressed files, adding support for:
- extracting section and priority from a .diff.bz2
......
......@@ -526,12 +526,18 @@ static inline retvalue todo_done(struct tobedone *todo, const char *method, cons
}
/* check uncompressed file */
static inline retvalue indexfile_done(void *data, const char *compressed, bool early) {
static inline retvalue indexfile_done(void *data, const char *compressed, bool failed, bool early) {
struct tobedone *todo = data;
retvalue r;
struct checksums *checksums;
bool improves;
if( failed ) {
if( !early )
todo_free(todo);
return RET_ERROR;
}
/* file got uncompressed, check if it has the correct checksum */
if( todo->checksums_p != NULL ) {
......@@ -825,6 +831,8 @@ static retvalue uridone(struct aptmethod *method, const char *uri, const char *f
r = todo_done(todo, method->name, filename,
checksumsfromapt, database);
// TODO: check if unlinking can be done before so the
// free stuff can be implemented easier
/* remove item: */
if( lasttodo == NULL )
method->tobedone = todo->next;
......@@ -1377,7 +1385,7 @@ retvalue aptmethod_download(struct aptmethodrun *run, struct database *database)
r = readwrite(run, &workleft, database);
RET_UPDATE(result,r);
// TODO: check interrupted here...
} while( workleft > 0 );
} while( workleft > 0 || uncompress_running() );
return result;
}
......
......@@ -29,6 +29,7 @@
#include <archive.h>
#include "error.h"
#include "uncompression.h"
#include "ar.h"
/* Arr, me matees, Arr */
......@@ -49,9 +50,10 @@ struct ar_archive {
char ah_size[10];
char ah_magictrailer[2];
} currentheader;
off_t bytes_left;
off_t member_size, next_position;
void *readbuffer;
bool wasodd;
/*@null@*/struct compressedfile *member;
enum compression compression;
};
static ssize_t readwait(int fd, /*@out@*/void *buf, size_t count) {
......@@ -127,6 +129,7 @@ retvalue ar_open(/*@out@*/struct ar_archive **n, const char *filename) {
free(ar);
return RET_ERROR_OOM;
}
ar->next_position = sizeof(AR_MAGIC) - 1;
*n = ar;
return RET_OK;
......@@ -145,22 +148,19 @@ void ar_close(/*@only@*/struct ar_archive *ar) {
retvalue ar_nextmember(struct ar_archive *ar,/*@out@*/char **filename) {
ssize_t bytesread;
char *p;
off_t s;
assert(ar->readbuffer == NULL);
assert(ar->fd >= 0);
/* seek over what is left from the last part: */
if( ar->bytes_left >0 || ar->wasodd ) {
off_t s;
s = lseek(ar->fd,ar->bytes_left+(ar->wasodd?1:0),SEEK_CUR);
if( s == (off_t)-1 ) {
int e = errno;
fprintf(stderr,
"Error %d seeking to next member in ar file %s: %s\n",
e, ar->filename, strerror(e));
return RET_ERRNO(e);
}
s = lseek(ar->fd, ar->next_position, SEEK_SET);
if( s == (off_t)-1 ) {
int e = errno;
fprintf(stderr,
"Error %d seeking to next member in ar file %s: %s\n",
e, ar->filename, strerror(e));
return RET_ERRNO(e);
}
/* read the next header from the file */
......@@ -168,6 +168,7 @@ retvalue ar_nextmember(struct ar_archive *ar,/*@out@*/char **filename) {
return RET_ERROR_INTERRUPTED;
bytesread = readwait(ar->fd,&ar->currentheader,sizeof(ar->currentheader));
ar->next_position += sizeof(ar->currentheader);
if( bytesread == 0 )
return RET_NOTHING;
if( bytesread != sizeof(ar->currentheader) ){
......@@ -192,14 +193,15 @@ retvalue ar_nextmember(struct ar_archive *ar,/*@out@*/char **filename) {
ar->currentheader.ah_size[11] = '\0'; // ugly, but it works
ar->bytes_left = strtoul(ar->currentheader.ah_size,&p,10);
ar->member_size = strtoul(ar->currentheader.ah_size,&p,10);
if( *p != '\0' && *p != ' ' ) {
fprintf(stderr, "Error calculating length field in ar file %s\n",
ar->filename);
return RET_ERROR;
}
if( (ar->bytes_left & 1) != 0 )
ar->wasodd = true;
ar->next_position += ar->member_size;
if( (ar->member_size & 1) != 0 )
ar->next_position ++;
/* get the name of the file */
if( false ) {
......@@ -216,49 +218,75 @@ retvalue ar_nextmember(struct ar_archive *ar,/*@out@*/char **filename) {
i--;
*filename = strndup(ar->currentheader.ah_filename,i);
}
ar->compression = c_none;
return RET_OK;
}
void ar_archivemember_setcompression(struct ar_archive *ar, enum compression compression) {
ar->compression = compression;
}
ssize_t ar_archivemember_read(struct archive *a, void *d, const void **p) {
struct ar_archive *ar = d;
ssize_t bytesread;
assert( ar->readbuffer != NULL );
if( ar->bytes_left == 0 )
if( ar->member == NULL )
return 0;
*p = ar->readbuffer;
bytesread = read(ar->fd,ar->readbuffer,(ar->bytes_left > BLOCKSIZE)?BLOCKSIZE:ar->bytes_left);
bytesread = uncompress_read(ar->member, ar->readbuffer, BLOCKSIZE);
if( bytesread < 0 ) {
int e = errno;
archive_set_error(a, e, "Error %d reading from file: %s",
e, strerror(e));
return -1;
}
if( bytesread == 0 ) {
archive_set_error(a,EIO,"Unexpected end of file");
retvalue r;
const char *msg;
int e;
r = uncompress_fdclose(ar->member, &e, &msg);
ar->member = NULL;
archive_set_error(a, e, msg);
return -1;
}
ar->bytes_left -= bytesread;
return bytesread;
}
int ar_archivemember_open(struct archive *a, void *d) {
struct ar_archive *ar = d;
retvalue r;
const char *msg;
int e;
assert( uncompression_supported(ar->compression) );
assert(ar->readbuffer == NULL );
ar->readbuffer = malloc(BLOCKSIZE);
if( ar->readbuffer == NULL ) {
archive_set_error(a,ENOMEM,"Out of memory");
archive_set_error(a, ENOMEM, "Out of memory");
return ARCHIVE_FATAL;
}
return ARCHIVE_OK;
r = uncompress_fdopen(&ar->member, ar->fd, ar->member_size,
ar->compression, &e, &msg);
if( RET_IS_OK(r) )
return ARCHIVE_OK;
archive_set_error(a, e, msg);
return ARCHIVE_FATAL;
}
int ar_archivemember_close(UNUSED(struct archive *a), void *d) {
struct ar_archive *ar = d;
retvalue r;
const char *msg;
int e;
free(ar->readbuffer);
ar->readbuffer = NULL;
return ARCHIVE_OK;
if( ar->member == NULL )
return ARCHIVE_OK;
r = uncompress_fdclose(ar->member, &e, &msg);
ar->member = NULL;
if( RET_IS_OK(r) )
return ARCHIVE_OK;
archive_set_error(a, e, msg);
return ARCHIVE_FATAL;
}
......@@ -9,6 +9,9 @@ void ar_close(/*@only@*/struct ar_archive *);
/* RET_OK = next is there, RET_NOTHING = eof, < 0 = error */
retvalue ar_nextmember(struct ar_archive *,/*@out@*/char **filename);
/* set compression for the next member */
void ar_archivemember_setcompression(struct ar_archive *, enum compression);
/* the following can be used for libarchive to read an file in the ar
* after ar_nextmember returned sucessfully.
* All references get invalid after the ar_nextmember is called again. */
......
......@@ -27,6 +27,7 @@
#include <archive.h>
#include <archive_entry.h>
#include "error.h"
#include "uncompression.h"
#include "ar.h"
#include "chunks.h"
#include "debfile.h"
......@@ -110,7 +111,8 @@ static retvalue read_control_tar(char **control, const char *debfile, struct ar_
retvalue r;
archive_read_support_format_tar(tar);
a = archive_read_open(tar,ar,
archive_read_support_format_gnutar(tar);
a = archive_read_open(tar, ar,
ar_archivemember_open,
ar_archivemember_read,
ar_archivemember_close);
......@@ -155,6 +157,7 @@ static retvalue read_control_tar(char **control, const char *debfile, struct ar_
retvalue extractcontrol(char **control,const char *debfile) {
struct ar_archive *ar;
retvalue r;
bool hadcandidate = false;
r = ar_open(&ar,debfile);
if( RET_WAS_ERROR(r) )
......@@ -162,32 +165,31 @@ retvalue extractcontrol(char **control,const char *debfile) {
assert( r != RET_NOTHING);
do {
char *filename;
enum compression c;
r = ar_nextmember(ar, &filename);
if( RET_IS_OK(r) ) {
if( strcmp(filename,"control.tar.gz") == 0 ) {
struct archive *tar;
tar = archive_read_new();
archive_read_support_compression_gzip(tar);
r = read_control_tar(control, debfile, ar, tar);
archive_read_finish(tar);
if( r != RET_NOTHING ) {
ar_close(ar);
free(filename);
return r;
}
if( strncmp(filename, "control.tar", 11) != 0 ) {
free(filename);
continue;
}
/* see below for a discussion about this #ifdef */
#ifdef HAVE_LIBBZ2
if( strcmp(filename,"control.tar.bz2") == 0 ) {
hadcandidate = true;
for( c = 0 ; c < c_COUNT ; c++ ) {
if( strcmp(filename + 11,
uncompression_suffix[c]) == 0)
break;
}
if( c >= c_COUNT ) {
free(filename);
continue;
}
ar_archivemember_setcompression(ar, c);
if( uncompression_supported(c) ) {
struct archive *tar;
tar = archive_read_new();
archive_read_support_compression_gzip(tar);
archive_read_support_compression_bzip2(tar);
r = read_control_tar(control, debfile, ar, tar);
// TODO run archive_read_close to get error messages?
archive_read_finish(tar);
if( r != RET_NOTHING ) {
ar_close(ar);
......@@ -196,11 +198,15 @@ retvalue extractcontrol(char **control,const char *debfile) {
}
}
#endif
free(filename);
}
} while( RET_IS_OK(r) );
ar_close(ar);
fprintf(stderr,"Could not find a control.tar.gz file within '%s'!\n",debfile);
if( hadcandidate )
fprintf(stderr,
"Could not find a suitable control.tar file within '%s'!\n", debfile);
else
fprintf(stderr,
"Could not find a control.tar file within '%s'!\n", debfile);
return RET_ERROR_MISSING;
}
......@@ -27,6 +27,7 @@
#include <archive.h>
#include <archive_entry.h>
#include "error.h"
#include "uncompression.h"
#include "ar.h"
#include "filelist.h"
#include "debfile.h"
......@@ -39,22 +40,28 @@ static retvalue read_data_tar(/*@out@*/char **list, /*@out@*/size_t *size, const
struct archive_entry *entry;
struct filelistcompressor c;
retvalue r;
int a;
int a, e;
r = filelistcompressor_setup(&c);
if( RET_WAS_ERROR(r) )
return r;
archive_read_support_format_tar(tar);
archive_read_support_format_gnutar(tar);
a = archive_read_open(tar,ar,
ar_archivemember_open,
ar_archivemember_read,
ar_archivemember_close);
if( a != ARCHIVE_OK ) {
filelistcompressor_cancel(&c);
fprintf(stderr,"open data.tar.gz within '%s' failed: %d:%d:%s\n",
debfile,
a,archive_errno(tar),
e = archive_errno(tar);
if( e == -EINVAL) /* special code to say there is none */
fprintf(stderr,
"open data.tar within '%s' failed: %s\n",
debfile, archive_error_string(tar));
else
fprintf(stderr,
"open data.tar within '%s' failed: %d:%d:%s\n", debfile, a, e,
archive_error_string(tar));
return RET_ERROR;
}
......@@ -83,21 +90,43 @@ static retvalue read_data_tar(/*@out@*/char **list, /*@out@*/size_t *size, const
a = archive_read_data_skip(tar);
if( a != ARCHIVE_OK ) {
int e = archive_errno(tar);
printf("Error skipping %s within data.tar.gz from %s: %d=%s\n",
if( e == -EINVAL ) {
r = RET_ERROR;
fprintf(stderr,
"Error skipping %s within data.tar from %s: %s\n",
archive_entry_pathname(entry),
debfile,
e, archive_error_string(tar));
debfile, archive_error_string(tar));
} else {
fprintf(stderr,
"Error %d skipping %s within data.tar from %s: %s\n",
e, archive_entry_pathname(entry),
debfile, archive_error_string(tar));
if( e != 0 )
r = RET_ERRNO(e);
else
r = RET_ERROR;
}
filelistcompressor_cancel(&c);
return (e!=0)?(RET_ERRNO(e)):RET_ERROR;
return r;
}
}
if( a != ARCHIVE_EOF ) {
int e = archive_errno(tar);
printf("Error reading data.tar.gz from %s: %d=%s\n",
debfile,
e, archive_error_string(tar));
if( e == -EINVAL ) {
r = RET_ERROR;
fprintf(stderr,
"Error reading data.tar from %s: %s\n", debfile, archive_error_string(tar));
} else {
fprintf(stderr,
"Error %d reading data.tar from %s: %s\n",
e, debfile, archive_error_string(tar));
if( e != 0 )
r = RET_ERRNO(e);
else
r = RET_ERROR;
}
filelistcompressor_cancel(&c);
return (e!=0)?(RET_ERRNO(e)):RET_ERROR;
return r;
}
return filelistcompressor_finish(&c, list, size);
}
......@@ -106,6 +135,7 @@ static retvalue read_data_tar(/*@out@*/char **list, /*@out@*/size_t *size, const
retvalue getfilelist(/*@out@*/char **filelist, size_t *size, const char *debfile) {
struct ar_archive *ar;
retvalue r;
bool hadcandidate = false;
r = ar_open(&ar,debfile);
if( RET_WAS_ERROR(r) )
......@@ -113,39 +143,32 @@ retvalue getfilelist(/*@out@*/char **filelist, size_t *size, const char *debfile
assert( r != RET_NOTHING);
do {
char *filename;
enum compression c;
r = ar_nextmember(ar, &filename);
if( RET_IS_OK(r) ) {
if( strcmp(filename,"data.tar.gz") == 0 ) {
struct archive *tar;
tar = archive_read_new();
archive_read_support_compression_gzip(tar);
r = read_data_tar(filelist, size,
debfile, ar, tar);
archive_read_finish(tar);
if( r != RET_NOTHING ) {
ar_close(ar);
free(filename);
return r;
}
if( strncmp(filename, "data.tar", 8) != 0 ) {
free(filename);
continue;
}
hadcandidate = true;
for( c = 0 ; c < c_COUNT ; c++ ) {
if( strcmp(filename + 8,
uncompression_suffix[c]) == 0)
break;
}
/* TODO: here some better heuristic would be nice,
* but when compiling against the static libarchive this is what needed,
* and when libarchive is compiled locally it will have bz2 support
* essentially when we have it, too.
* Thus this ifdef is quite a good choice, especially as no offical
* files should have this member, anyway */
#ifdef HAVE_LIBBZ2
if( strcmp(filename,"data.tar.bz2") == 0 ) {
if( c >= c_COUNT ) {
free(filename);
continue;
}
ar_archivemember_setcompression(ar, c);
if( uncompression_supported(c) ) {
struct archive *tar;
tar = archive_read_new();
archive_read_support_compression_gzip(tar);
archive_read_support_compression_bzip2(tar);
r = read_data_tar(filelist, size,
debfile, ar, tar);
// TODO: check how to get an error message here..
archive_read_finish(tar);
if( r != RET_NOTHING ) {
ar_close(ar);
......@@ -154,11 +177,15 @@ retvalue getfilelist(/*@out@*/char **filelist, size_t *size, const char *debfile
}
}
#endif
free(filename);
}
} while( RET_IS_OK(r) );
ar_close(ar);
fprintf(stderr,"Could not find a data.tar.gz file within '%s'!\n",debfile);
if( hadcandidate )
fprintf(stderr,
"Could not find a suitable data.tar file within '%s'!\n", debfile);
else
fprintf(stderr,
"Could not find a data.tar file within '%s'!\n", debfile);
return RET_ERROR_MISSING;
}
......@@ -12,7 +12,7 @@ Package: reprepro
Architecture: any
Depends: ${shlibs:Depends}, ${reprepro:Depends}, ${misc:Depends}
Recommends: apt
Suggests: gnupg-agent, inoticoming
Suggests: gnupg-agent, inoticoming, lzma
Description: Debian package repository producer
reprepro is a tool to manage a repository of Debian packages
(.deb, .udeb, .dsc, ...). It stores files either being
......
......@@ -263,6 +263,35 @@ access this repository.
Versions before 3.0 will not recognize that and destroy it.
Thus it is still switched off by default, even though it gives an space
and speed improvement.
.TP
.BI \-\-gunzip " gz-uncompressor"
While reprepro links against \fBlibz\fP, it will look for the program given
with this option (or \fBgunzip\fP if not given) and use that when uncompressing
index files while downloading from remote repositories.
(So that downloading and uncompression can happen at the same time).
If the program is not found or is \fBNONE\fP (all-uppercase) then uncompressing
will always be done using the built in uncompression method.
The program has to accept the compressed file as stdin and write
the uncompressed file into stdout.
.TP
.BI \-\-bunzip2 " bz2-uncompressor"
When uncompressing downloaded index files or when not linked against \fBlibbz2\fP
reprepro will use this program to uncompress \fB.bz2\fP files.
The default value is \fBbunzip2\fP.
If the program is not found or is \fBNONE\fP (all-uppercase) then uncompressing
will always be done using the built in uncompression method or not be possible
when not linked against \fBlibbz2\fP.
The program has to accept the compressed fiile as stdin and write
the uncompressed file into stdout.
.TP
.BI \-\-unlzma " lzma-uncompressor"
When trying to uncompress or read \fPlzma\fP compressed files, this program
will be used.
The default value is \fBunlzma\fP.
If the program is not found or is \fBNONE\fP (all-uppercase) then uncompressing
lzma files will not be possible.
The program has to accept the compressed file as stdin and write
the uncompressed file into stdout.
.SH COMMANDS
.TP
.BR export " [ " \fIcodenames\fP " ]"
......@@ -639,6 +668,13 @@ hack around broken .deb files that cannot be read by reprepro.
Add packages from the specified filename to part specified
by \fB-C\fP \fB-A\fP and \fB-T\fP of the specified distribution.
Very strange things can happen if you use it improperly.
.TP
.B __dumpuncompressors
List what compressions format can be uncompressed and how.
.TP
.BI __uncompress " format compressed-file uncompressed-file"
Use builtin or external uncompression to uncompress the specified
file of the specified format into the specified target.
.SH "CONFIG FILES"
.B reprepo
uses three config files, which are searched in
......
......@@ -10,6 +10,8 @@ bool interrupted(void);
/* retvalue is simply an int.
* just named to show it follows the given semantics */
/*@numabstract@*/ enum retvalue_enum {
RET_ERROR_BZ2 = -11,
RET_ERROR_Z = -10,
RET_ERROR_INTERRUPTED = -9,
RET_ERROR_UNKNOWNFIELD = -8,
RET_ERROR_MISSING = -7,
......@@ -40,9 +42,6 @@ typedef enum retvalue_enum retvalue;
/* code a errno in a error */
#define RET_ERRNO(err) ((err>0)?((retvalue)-err):RET_ERROR)
/* code a zlib-error in a error */
#define RET_ZERRNO(zerr) ((zerr>=Z_OK)?RET_OK:((zerr==Z_ERRNO)?RET_ERRNO(errno):((retvalue)(-5000+zerr))))
/* code a db-error in a error */
// TODO: to be implemented...
#define RET_DBERR(e) RET_ERROR
......
......@@ -94,7 +94,10 @@ static char /*@only@*/ /*@null@*/
*x_priority = NULL,
*x_component = NULL,
*x_architecture = NULL,
*x_packagetype = NULL;
*x_packagetype = NULL,
*gunzip = NULL,
*bunzip2 = NULL,
*unlzma = NULL;
static int delete = D_COPY;
static bool nothingiserror = false;
static bool nolistsdownload = false;
......@@ -119,7 +122,7 @@ static off_t reservedotherspace = 1024*1024;
* to change something owned by lower owners. */
enum config_option_owner config_state,
#define O(x) owner_ ## x = CONFIG_OWNER_DEFAULT
O(fast), O(x_outdir), O(x_basedir), O(x_distdir), O(dbdir), O(x_listdir), O(x_confdir), O(x_logdir), O(x_overridedir), O(x_methoddir), O(x_section), O(x_priority), O(x_component), O(x_architecture), O(x_packagetype), O(nothingiserror), O(nolistsdownload), O(keepunreferenced), O(keepdirectories), O(askforpassphrase), O(skipold), O(export), O(waitforlock), O(spacecheckmode), O(reserveddbspace), O(reservedotherspace), O(guessgpgtty), O(verbosedatabase), O(oldfilesdb);
O(fast), O(x_outdir), O(x_basedir), O(x_distdir), O(dbdir), O(x_listdir), O(x_confdir), O(x_logdir), O(x_overridedir), O(x_methoddir), O(x_section), O(x_priority), O(x_component), O(x_architecture), O(x_packagetype), O(nothingiserror), O(nolistsdownload), O(keepunreferenced), O(keepdirectories), O(askforpassphrase), O(skipold), O(export), O(waitforlock), O(spacecheckmode), O(reserveddbspace), O(reservedotherspace), O(guessgpgtty), O(verbosedatabase), O(oldfilesdb), O(gunzip), O(bunzip2), O(unlzma);
#undef O
#define CONFIGSET(variable,value) if(owner_ ## variable <= config_state) { \
......@@ -266,6 +269,54 @@ ACTION_N(n, n, printargs) {
return RET_OK;
}
ACTION_N(n, n, dumpuncompressors) {
enum compression c;
assert( argc == 1 );
for( c = 0 ; c < c_COUNT ; c++ ) {
if( c == c_none )
continue;
printf("%s: ", uncompression_suffix[c]);
if( uncompression_builtin(c) ) {
if( extern_uncompressors[c] != NULL )
printf("built-in + '%s'\n",
extern_uncompressors[c]);
else
printf("built-in\n");
} else if( extern_uncompressors[c] != NULL )
printf("'%s'\n", extern_uncompressors[c]);
else switch( c ) {
case c_bzip2:
printf("not supported (install bzip2 or use --bunzip2 to tell where bunzip2 is).\n");
break;
case c_lzma:
printf("not supported (install lzma or use --unlzma to tell where unlzma is).\n");
break;
default:
printf("not supported\n");
}
}
return RET_OK;
}
ACTION_N(n, n, uncompress) {
enum compression c;
assert( argc == 4 );
c = c_none + 1;
while( c < c_COUNT && strcmp(argv[1], uncompression_suffix[c]) != 0 )
c++;
if( c >= c_COUNT ) {
fprintf(stderr, "Unknown compression format '%s'\n", argv[1]);
return RET_ERROR;
}
if( !uncompression_supported(c) ) {
fprintf(stderr, "Cannot uncompress format '%s'\nCheck __dumpuncompressors for more details.\n", argv[1]);
return RET_ERROR;
}
return uncompress_file(argv[2], argv[3], c);
}
ACTION_N(n, n, extractcontrol) {
retvalue result;
char *control;
......@@ -274,8 +325,10 @@ ACTION_N(n, n, extractcontrol) {
result = extractcontrol(&control,argv[1]);
if( RET_IS_OK(result) )
printf("%s\n",control);
if( RET_IS_OK(result) ) {
puts(control);
free(control);
}
return result;
}
......@@ -2367,6 +2420,10 @@ static const struct action {
} all_actions[] = {
{"__d", A_N(printargs),
-1, -1, NULL},
{"__dumpuncompressors", A_N(dumpuncompressors),
0, 0, "__dumpuncompressors"},
{"__uncompress", A_N(uncompress),
3, 3, "__uncompress .gz|.bz2|.lzma <compressed-filename> <into-filename>"},
{"__extractcontrol", A_N(extractcontrol),
1, 1, "__extractcontrol <.deb-file>"},
{"__extractfilelist", A_N(extractfilelist),
......@@ -2701,6 +2758,9 @@ LO_WAITFORLOCK,
LO_SPACECHECK,
LO_SAFETYMARGIN,
LO_DBSAFETYMARGIN,
LO_GUNZIP,
LO_BUNZIP2,
LO_UNLZMA,
LO_UNIGNORE};
static int longoption = 0;
const char *programname;
......@@ -2943,6 +3003,15 @@ static void handle_option(int c,const char *optarg) {
"--dbsafetymargin",
optarg, LONG_MAX));
break;
case LO_GUNZIP:
CONFIGDUP(gunzip, optarg);
break;
case LO_BUNZIP2:
CONFIGDUP(bunzip2, optarg);
break;
case LO_UNLZMA:
CONFIGDUP(unlzma, optarg);
break;
default:
fprintf (stderr,"Error parsing arguments!\n");
exit(EXIT_FAILURE);
......@@ -3105,6 +3174,9 @@ int main(int argc,char *argv[]) {
{"spacecheck", required_argument, &longoption, LO_SPACECHECK},
{"safetymargin", required_argument, &longoption, LO_SAFETYMARGIN},
{"dbsafetymargin", required_argument, &longoption, LO_DBSAFETYMARGIN},
{"gunzip", required_argument, &longoption, LO_GUNZIP},
{"bunzip2", required_argument, &longoption, LO_BUNZIP2},
{"unlzma", required_argument, &longoption, LO_UNLZMA},
{NULL, 0, NULL, 0}
};
const struct action *a;
......@@ -3221,7 +3293,10 @@ int main(int argc,char *argv[]) {
global.methoddir = x_methoddir;
global.listdir = x_listdir;
uncompressions_check();
uncompressions_check(gunzip, bunzip2, unlzma);
free(gunzip);
free(bunzip2);
free(unlzma);
a = all_actions;
while( a->name != NULL ) {
......
......@@ -111,14 +111,21 @@ bool sourceextraction_needs(struct sourceextraction *e, int *ofs_p) {
return false;
*ofs_p = e->difffile;
return true;
} else if( e->debiantarfile >= 0 ) {
#ifdef HAVE_LIBARCHIVE
} else if( e->debiantarfile >= 0 && e->debiancompression <= c_bzip2 ) {
#warning TODO: think about adding support for other decompressions here, too.
if( e->debiancompression > c_bzip2 )
// TODO: errormessage
return false;
*ofs_p = e->debiantarfile;
return true;
#else
return false;
#endif
} else if( e->tarfile >= 0 ) {
#ifdef HAVE_LIBARCHIVE
if( e->debiancompression > c_bzip2 )
// TODO: dito
if( e->tarcompression > c_bzip2 )
// TODO: errormessage
return false;
*ofs_p = e->tarfile;
......@@ -475,6 +482,7 @@ static retvalue parse_tarfile(struct sourceextraction *e, const char *filename,
if( FAILEDTOALLOC(tar) )
return RET_ERROR_OOM;