aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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]);