aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MANIFEST1
-rw-r--r--Makefile.PL2
-rw-r--r--NEWS1
-rw-r--r--URPM.xs17
-rw-r--r--xfile.h177
5 files changed, 190 insertions, 8 deletions
diff --git a/MANIFEST b/MANIFEST
index cf8bc4f..988e406 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -2,6 +2,7 @@ README
MANIFEST
Makefile.PL
typemap
+xfile.h
URPM.xs
URPM.pm
URPM/Build.pm
diff --git a/Makefile.PL b/Makefile.PL
index 26a1fbc..ed3e63c 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -50,7 +50,7 @@ ChangeLog:
}
my @rpmflags;
-my $ldflags = `pkg-config --libs rpm`;
+my $ldflags = `pkg-config --libs rpm liblzma`;
my $ccflags = join(' ', '-Wall -Wextra -fno-strict-aliasing', @rpmflags);
print "Found RPM version $version (compiling with flags: $ccflags)\n";
diff --git a/NEWS b/NEWS
index 2010fd4..c917c6a 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,6 @@
Version 4.0 - ? October 2010, by Per Øyvind Karlsen
+- add support for uncompressed & xz/lzma compressed synthesis
- fix URPM::DB::open() to work properly with relative paths
- ditch legacy behaviour compatibility for packages without epoch, always promote
epoch
diff --git a/URPM.xs b/URPM.xs
index 89ff008..dc77356 100644
--- a/URPM.xs
+++ b/URPM.xs
@@ -20,7 +20,6 @@
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
-#include <zlib.h>
#include <libintl.h>
#undef Fflush
@@ -41,6 +40,8 @@
#include <rpmbuild.h>
#include <rpmlog.h>
+#include "xfile.h"
+
struct s_Package {
char *info;
int filesize;
@@ -3443,7 +3444,8 @@ Urpm_parse_synthesis__XS(urpm, filename, ...)
char *p, *eol;
int buff_len;
struct s_Package pkg;
- gzFile gzF;
+ xFile xF;
+ lzma_ret ret = LZMA_STREAM_END;
int start_id = 1 + av_len(depslist);
SV *callback = NULL;
@@ -3460,12 +3462,12 @@ Urpm_parse_synthesis__XS(urpm, filename, ...)
}
PUTBACK;
- if ((gzF = gzopen(filename, "rb")) != NULL) {
+ if ((xF = xOpen(filename)).type < XF_FAIL) {
memset(&pkg, 0, sizeof(struct s_Package));
buff[sizeof(buff)-1] = 0;
p = buff;
int ok = 1;
- while ((buff_len = gzread(gzF, p, sizeof(buff)-1-(p-buff))) >= 0 &&
+ while ((buff_len = xRead(&xF, &ret, p, sizeof(buff)-1-(p-buff))) >= 0 &&
(buff_len += p-buff)) {
buff[buff_len] = 0;
p = buff;
@@ -3477,11 +3479,11 @@ Urpm_parse_synthesis__XS(urpm, filename, ...)
} while ((eol = strchr(p, '\n')) != NULL);
} else {
/* a line larger than sizeof(buff) has been encountered, bad file problably */
- fprintf(stderr, "invalid line <%s>\n", p);
+ fprintf(stderr, "invalid line <%s>\n%s\n", p, buff);
ok = 0;
break;
}
- if (gzeof(gzF)) {
+ if (xF.eof) {
if (!parse_line(depslist, provides, obsoletes, &pkg, p, urpm, callback)) ok = 0;
break;
} else {
@@ -3491,7 +3493,8 @@ Urpm_parse_synthesis__XS(urpm, filename, ...)
p = &buff[buff_len-(p-buff)];
}
}
- if (gzclose(gzF) != 0) ok = 0;
+ if(ret != LZMA_STREAM_END) ok = 0;
+ if (xClose(&xF) != 0) ok = 0;
SPAGAIN;
if (ok) {
XPUSHs(sv_2mortal(newSViv(start_id)));
diff --git a/xfile.h b/xfile.h
new file mode 100644
index 0000000..2ca8902
--- /dev/null
+++ b/xfile.h
@@ -0,0 +1,177 @@
+#include <magic.h>
+#include <lzma.h>
+#include <zlib.h>
+
+#define kBufferSize (1 << 15)
+
+typedef struct lzma_file {
+ uint8_t buf[kBufferSize];
+ lzma_stream strm;
+ FILE *fp;
+ lzma_bool eof;
+} lzma_FILE;
+
+typedef enum xFile_e {
+ XF_ASCII,
+ XF_GZIP,
+ XF_LZMA,
+ XF_XZ,
+ XF_FAIL
+} xFile_t;
+
+typedef struct xFile_s {
+ xFile_t type;
+ lzma_bool eof;
+ union {
+ gzFile gz;
+ lzma_FILE *xz;
+ } f;
+ FILE *fp;
+} xFile;
+
+static lzma_FILE *lzma_open(lzma_ret *lzma_error, FILE *fp, uint64_t memlimit)
+{
+ lzma_ret *ret = lzma_error;
+ lzma_FILE *lzma_file;
+ lzma_stream tmp = LZMA_STREAM_INIT;
+
+ lzma_file = calloc(1, sizeof(*lzma_file));
+
+ lzma_file->fp = fp;
+ lzma_file->eof = 0;
+ lzma_file->strm = tmp;
+
+ *ret = lzma_auto_decoder(&lzma_file->strm, memlimit, 0);
+
+ if (*ret != LZMA_OK) {
+ (void) fclose(lzma_file->fp);
+ memset(lzma_file, 0, sizeof(*lzma_file));
+ free(lzma_file);
+ return NULL;
+ }
+ return lzma_file;
+}
+
+static ssize_t lzma_read(lzma_ret *lzma_error, lzma_FILE *lzma_file, void *buf, size_t len)
+{
+ lzma_ret *ret = lzma_error;
+ lzma_bool eof = 0;
+
+ if (!lzma_file)
+ return -1;
+ if (lzma_file->eof)
+ return 0;
+
+ lzma_file->strm.next_out = buf;
+ lzma_file->strm.avail_out = len;
+ for (;;) {
+ if (!lzma_file->strm.avail_in) {
+ lzma_file->strm.next_in = (uint8_t *)lzma_file->buf;
+ lzma_file->strm.avail_in = fread(lzma_file->buf, 1, kBufferSize, lzma_file->fp);
+ if (!lzma_file->strm.avail_in)
+ eof = 1;
+ }
+ *ret = lzma_code(&lzma_file->strm, LZMA_RUN);
+ if (*ret == LZMA_STREAM_END) {
+ lzma_file->eof = 1;
+ return len - lzma_file->strm.avail_out;
+ }
+ if (*ret != LZMA_OK)
+ return -1;
+ if (!lzma_file->strm.avail_out)
+ return len;
+ if (eof)
+ return -1;
+ }
+}
+
+
+static xFile xOpen(const char *path) {
+ xFile xF = {XF_FAIL, 0, {NULL}, NULL};
+ lzma_ret ret = LZMA_OK;
+ const char *message, *tmp;
+ magic_t cookie;
+ cookie = magic_open(MAGIC_NONE);
+ if(!magic_load(cookie, NULL)) {
+ message = magic_file(cookie, path);
+ if(strstr(message, "gzip compressed"))
+ xF.type = XF_GZIP;
+ else if(strstr(message, "xz compressed"))
+ xF.type = XF_XZ;
+ else if(strstr(message, "LZMA compressed"))
+ xF.type = XF_LZMA;
+ else if(strstr(message, "ASCII"))
+ xF.type = XF_ASCII;
+ magic_close(cookie);
+ }
+ if(xF.type == XF_FAIL && (tmp = rindex(path, '.'))) {
+ if(!strcmp(tmp, ".cz") || !strcmp(tmp, ".cz"))
+ xF.type = XF_GZIP;
+ else if(!strcmp(tmp, ".xz"))
+ xF.type = XF_XZ;
+ else if(!strcmp(tmp, ".lzma"))
+ xF.type = XF_LZMA;
+ }
+
+ switch(xF.type) {
+ case XF_GZIP:
+ xF.f.gz = gzopen(path, "rb");
+ break;
+ case XF_ASCII:
+ case XF_LZMA:
+ case XF_XZ:
+ xF.fp = fopen(path, "rb");
+ if(xF.type == XF_ASCII) break;
+ xF.f.xz = lzma_open(&ret, xF.fp, -1);
+ if(ret != LZMA_OK)
+ xF.type = XF_FAIL;
+ break;
+ default:
+ break;
+ }
+
+ return xF;
+}
+
+static int xClose(xFile *xF) {
+ int ret = -1;
+ switch(xF->type) {
+ case XF_GZIP:
+ ret = gzclose(xF->f.gz);
+ break;
+ case XF_LZMA:
+ case XF_XZ:
+ lzma_end(&xF->f.xz->strm);
+ free(xF->f.xz);
+ case XF_ASCII:
+ ret = fclose(xF->fp);
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static ssize_t xRead(xFile *xF, lzma_ret *ret, void *buf, size_t len) {
+ ssize_t sz;
+ switch(xF->type) {
+ case XF_GZIP:
+ sz = gzread(xF->f.gz, buf, len);
+ xF->eof = gzeof(xF->f.gz);
+ break;
+ case XF_LZMA:
+ case XF_XZ:
+ sz = lzma_read(ret, xF->f.xz, buf, len);
+ xF->eof = xF->f.xz->eof;
+ break;
+ case XF_ASCII:
+ sz = fread(buf, 1, len, xF->fp);
+ xF->eof = feof(xF->fp);
+ break;
+ default:
+ break;
+ }
+ return sz;
+}
+
+