// gcc -Wall -I/usr/include/rpm rpmfile.c -lrpm -o rpmfile #include #include #include #include struct cpio_header { char magic[6]; char inode[8]; char mode[8]; char uid[8]; char gid[8]; char nlink[8]; char mtime[8]; char filesize[8]; char dev_major[8]; char dev_minor[8]; char rdev_major[8]; char rdev_minor[8]; char namesize[8]; char checksum[8]; }; int num8(char *s) { char c = s[8]; s[8] = 0; int n = strtoul(s, NULL, 16); s[8] = c; return n; } FD_t open_payload(const char *fname) { FD_t fd = Fopen(fname, "r.ufdio"); if (Ferror(fd)) error(1, 0, "%s: %s", fname, Fstrerror(fd)); Header h; int isSource; if (rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL)) error(1, 0, "%s: %s", fname, "bad RPM header"); char *method; if (headerGetEntry(h, RPMTAG_PAYLOADCOMPRESSOR, NULL, (void **) &method, NULL)) method = "gzip"; char *type = "r"; if (strcmp(method, "gzip") == 0) type = "r.gzdio"; if (strcmp(method, "bzip2") == 0) type = "r.bzdio"; FD_t zfd = Fdopen(fd, type); if (Ferror(zfd)) error(1, 0, "%s: %s", fname, Fstrerror(zfd)); if (fd != zfd) Fclose(fd); return zfd; } void rpmfile(const char *fname) { FD_t fd = open_payload(fname); while (1) { size_t n; struct cpio_header h; n = Fread(&h, sizeof(h), 1, fd); if (n != 1) error(1, 0, "%s: %s", fname, "bad cpio header"); if (strncmp(h.magic, "070701", 6)) error(1, 0, "%s: %s", fname, "bad cpio magic"); char path[PATH_MAX]; int len = num8(h.namesize); n = Fread(path, len, 1, fd); if (n != 1) error(1, 0, "%s: %s", fname, "bad cpio namesize"); if (strcmp(path, "TRAILER!!!") == 0) break; char buf[4096]; int size = num8(h.filesize); int toread = (size > sizeof(buf)) ? sizeof(buf) : size; int toseek = size - toread; n = 1; if (toread) n = Fread(buf, toread, 1, fd); if (toseek) n += Fseek(fd, toseek, SEEK_CUR); if (n != 1) error(1, 0, "%s: %s", fname, "bad cpio filesize"); int mode = num8(h.mode); printf("%s\t%s\t0%o\n", fname, path, mode); /* TODO: zero padded? how do I seek ? */ break; } Fclose(fd); } int main(int argc, char *argv[]) { while (--argc > 0) rpmfile(*++argv); return 0; }