commit:     aeadc86f00479f0b842c8f3f0905d21b35565c13
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Sun Nov 17 12:46:22 2019 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Sun Nov 17 12:46:22 2019 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=aeadc86f

libq/xpak: try to seek to XPAKSTART in _xpak_open

To make it easier to deal with assembled files (like binpkgs) just embed
the offset logic in _xpak_open.  This makes qxpak operate directly on
tbz2 files, removing the need to split out using qtbz2 first.

Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 libq/xpak.c | 39 +++++++++++++++++++++++++++++++++------
 1 file changed, 33 insertions(+), 6 deletions(-)

diff --git a/libq/xpak.c b/libq/xpak.c
index 9692eab..82667b0 100644
--- a/libq/xpak.c
+++ b/libq/xpak.c
@@ -4,6 +4,7 @@
  *
  * Copyright 2005-2010 Ned Ludd        - <so...@gentoo.org>
  * Copyright 2005-2014 Mike Frysinger  - <vap...@gentoo.org>
+ * Copyright 2019-     Fabian Groffen  - <grob...@gentoo.org>
  */
 
 #include "main.h"
@@ -37,6 +38,10 @@
 #define XPAK_START_LEN       (8 + 4 + 4)
 #define XPAK_END_MSG         "XPAKSTOP"
 #define XPAK_END_MSG_LEN     8
+#define TBZ2_END_MSG         "STOP"
+#define TBZ2_END_MSG_LEN     4
+#define TBZ2_END_SIZE_LEN    4
+#define TBZ2_FOOTER_LEN      (TBZ2_END_MSG_LEN + TBZ2_END_SIZE_LEN)
 
 typedef struct {
        void *ctx;
@@ -87,14 +92,36 @@ static _xpak_archive *_xpak_open(const int fd)
        if ((ret.fp = fdopen(fd, "r")) == NULL)
                return NULL;
 
-       /* verify this xpak doesnt suck */
+       /* verify this xpak doesn't suck */
        if (fread(buf, 1, XPAK_START_LEN, ret.fp) != XPAK_START_LEN)
                goto close_and_ret;
-       if (memcmp(buf, XPAK_START_MSG, XPAK_START_MSG_LEN)) {
+       if (memcmp(buf, XPAK_START_MSG, XPAK_START_MSG_LEN) != 0) {
+               /* stream not positioned at XPAKSTART, let's see if we can
+                * reposition the stream */
+               if (fseek(ret.fp, -TBZ2_FOOTER_LEN, SEEK_END) == 0)
+               {
+                       if (fread(buf, 1, TBZ2_FOOTER_LEN, ret.fp) != 
TBZ2_FOOTER_LEN)
+                               goto close_and_ret;
+
+                       if (memcmp(buf + TBZ2_END_SIZE_LEN,
+                                               TBZ2_END_MSG, TBZ2_END_MSG_LEN) 
== 0)
+                       {
+                               int xpaklen = READ_BE_INT32(buf);
+
+                               if (fseek(ret.fp, -(xpaklen + TBZ2_FOOTER_LEN), 
SEEK_END) == 0)
+                               {
+                                       if (fread(buf, 1, XPAK_START_LEN, 
ret.fp) != XPAK_START_LEN)
+                                               goto close_and_ret;
+                                       if (memcmp(buf, XPAK_START_MSG, 
XPAK_START_MSG_LEN) == 0)
+                                               goto setup_lens;
+                               }
+                       }
+               }
                warn("Not an xpak file");
                goto close_and_ret;
        }
 
+setup_lens:
        /* calc index and data sizes */
        ret.index_len = READ_BE_INT32((unsigned char*)buf+XPAK_START_MSG_LEN);
        ret.data_len = READ_BE_INT32((unsigned char*)buf+XPAK_START_MSG_LEN+4);
@@ -124,7 +151,7 @@ xpak_process_fd(
        xpak_callback_t func)
 {
        _xpak_archive *x;
-       char buf[BUFSIZE], ext[BUFSIZE*32];
+       char buf[BUFSIZE];
        size_t in;
 
        x = _xpak_open(fd);
@@ -142,8 +169,8 @@ xpak_process_fd(
 
        if (get_data) {
                /* the xpak may be large (like when it has CONTENTS) #300744 */
-               x->data = (size_t)x->data_len < sizeof(ext) ?
-                       ext : xmalloc(x->data_len);
+               x->data = xmalloc(x->data_len);
+
                in = fread(x->data, 1, x->data_len, x->fp);
                if (in != (size_t)x->data_len)
                        err("insufficient data read, got %zd, requested %d",
@@ -157,7 +184,7 @@ xpak_process_fd(
 
        _xpak_close(x);
 
-       if (get_data && x->data != ext)
+       if (get_data)
                free(x->data);
 
        return 0;

Reply via email to