diff options
Diffstat (limited to 'rpmoffset.c')
-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]); |