/* Find how deeply inside an .RPM the real data is */ /* kept, and report the offset in bytes */ /* Wouldn't it be a lot more sane if we could just untar these things? */ #ifndef _GNU_SOURCE # define _GNU_SOURCE #endif #include #include #include #ifndef ARRAY_SIZE # define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #endif #ifndef BUFSIZ # define BUFSIZ 8192 #endif #define MAGIC_SIZE 3 int main(int argc, char *argv[]) { size_t i, read_cnt, offset, left; FILE *fp = stdin; char p[BUFSIZ]; const char magics[][MAGIC_SIZE] = { { '\037', '\213', '\010' }, /* gzip */ { 'B', 'Z', 'h' }, /* bzip */ }; if (argc != 1) { puts("Usage: rpmoffset < rpmfile"); return 1; } /* fp = fopen(argv[1], "r"); */ offset = left = 0; while (1) { read_cnt = fread(p + left, 1, sizeof(p) - left, fp); if (read_cnt + left < MAGIC_SIZE) break; for (i = 0; i < ARRAY_SIZE(magics); ++i) { char *needle = memmem(p, sizeof(p), magics[i], MAGIC_SIZE); if (needle) { printf("%zu\n", offset + (needle - p)); return 0; } } offset += read_cnt; if (left == 0) { offset -= MAGIC_SIZE - 1; left = MAGIC_SIZE - 1; } memmove(p, p + read_cnt - MAGIC_SIZE - 1, MAGIC_SIZE - 1); } if (ferror(stdin)) perror(argv[0]); return 1; }