aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2012-05-17 00:53:41 -0400
committerMike Frysinger <vapier@gentoo.org>2012-05-17 00:53:41 -0400
commitde35a1cd59302a1cc6d3766fcc053b130ab4efa0 (patch)
tree737119d16ecc7b41071fd038658bcb715db8f1a3
parentrpmoffset: provide a local memmem for non-glibc systems (diff)
downloadrpm2targz-de35a1cd59302a1cc6d3766fcc053b130ab4efa0.tar.gz
rpm2targz-de35a1cd59302a1cc6d3766fcc053b130ab4efa0.tar.bz2
rpm2targz-de35a1cd59302a1cc6d3766fcc053b130ab4efa0.zip
rpmoffset: add support for LZMA archives
The LZMA format lacks proper magic markings (hence one of the driving forces for the new XZ format), so we have to rework things to deal with this fuzzy matching without throwing false positives. URL: https://bugs.gentoo.org/321439 Reported-by: Peter Volkov <pva@gentoo.org> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
-rw-r--r--rpmoffset.c47
1 files changed, 38 insertions, 9 deletions
diff --git a/rpmoffset.c b/rpmoffset.c
index 628af93..bd1f456 100644
--- a/rpmoffset.c
+++ b/rpmoffset.c
@@ -45,6 +45,16 @@ typedef struct {
const size_t len;
} magic_t;
+/* LZMA is some fuzzy crap */
+int is_magic_lzma(const char *buf)
+{
+ const unsigned char *ubuf = (const void *)buf;
+ return (ubuf[0] == 0x5d && ubuf[4] < 0x20) &&
+ (!memcmp(buf + 10, "\x00\x00\x00", 3) ||
+ !memcmp(buf + 5, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8));
+}
+#define magic_lzma_len 13
+
static const unsigned char magic_gzip[] = { '\037', '\213', '\010' };
static const unsigned char magic_bzip2[] = { 'B', 'Z', 'h' };
static const unsigned char magic_xz[] = { 0xFD, '7', 'z', 'X', 'Z', 0x00 };
@@ -56,12 +66,21 @@ static const magic_t magics[] = {
#undef DECLARE_MAGIC_T
};
#define MAGIC_SIZE_MIN 3
-#define MAGIC_SIZE_MAX 6
+#define MAGIC_SIZE_MAX 13
+
+static int show_magic;
+
+static int magic_finish(const char *magic, size_t offset)
+{
+ if (show_magic)
+ printf("%s ", magic);
+ printf("%zu\n", offset);
+ return 0;
+}
int main(int argc, char *argv[])
{
- int show_magic = 0;
- size_t i, read_cnt, offset, left;
+ size_t i, read_cnt, offset, left, lzma_offset;
FILE *fp = stdin;
char p[BUFSIZ];
@@ -76,6 +95,7 @@ int main(int argc, char *argv[])
}
/* fp = fopen(argv[1], "r"); */
+ lzma_offset = 0;
offset = left = 0;
while (1) {
read_cnt = fread(p + left, 1, sizeof(p) - left, fp);
@@ -89,12 +109,17 @@ int main(int argc, char *argv[])
continue;
needle = memmem(p, sizeof(p), magics[i].magic, magics[i].len);
- if (needle) {
- if (show_magic)
- printf("%s ", magics[i].type);
- printf("%zu\n", offset + (needle - p));
- return 0;
- }
+ if (needle)
+ return magic_finish(magics[i].type, offset + (needle - p));
+ }
+
+ /* Scan for LZMA magic, but don't return yet ... */
+ if (!lzma_offset && read_cnt + left >= magic_lzma_len) {
+ for (i = 0; i <= read_cnt + left - magic_lzma_len; ++i)
+ if (is_magic_lzma(p + i)) {
+ lzma_offset = offset + i;
+ break;
+ }
}
memmove(p, p + left + read_cnt - MAGIC_SIZE_MIN + 1, MAGIC_SIZE_MIN - 1);
@@ -106,6 +131,10 @@ int main(int argc, char *argv[])
}
}
+ /* Delay till the end for LZMA archives since it is too fuzzy */
+ if (lzma_offset)
+ return magic_finish("lzma", lzma_offset);
+
if (ferror(stdin))
perror(argv[0]);