diff options
author | Mike Frysinger <vapier@gentoo.org> | 2012-05-17 00:53:41 -0400 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2012-05-17 00:53:41 -0400 |
commit | de35a1cd59302a1cc6d3766fcc053b130ab4efa0 (patch) | |
tree | 737119d16ecc7b41071fd038658bcb715db8f1a3 | |
parent | rpmoffset: provide a local memmem for non-glibc systems (diff) | |
download | rpm2targz-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.c | 47 |
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]); |