diff -r f23a93d41f32 -r 773e6a26707f rpm.c --- a/rpm.c Wed Nov 07 00:33:56 2007 -0500 +++ b/rpm.c Thu Nov 08 22:36:16 2007 -0500 @@ -7,6 +7,8 @@ #include #include +#include "razor.h" + #define RPM_LEAD_SIZE 96 struct rpm_lead { @@ -35,92 +37,229 @@ int count; }; +struct properties { + struct rpm_header_index *name; + struct rpm_header_index *version; + struct rpm_header_index *flags; +}; + +struct rpm { + struct rpm_header *signature; + struct rpm_header *header; + + struct rpm_header_index *name; + struct rpm_header_index *version; + struct rpm_header_index *release; + + struct rpm_header_index *dirnames; + struct rpm_header_index *dirindexes; + struct rpm_header_index *basenames; + + struct properties provides; + struct properties requires; + struct properties obsoletes; + struct properties conflicts; + + const char *pool; + void *map; + size_t size; +}; + #define ALIGN(value, base) (((value) + (base - 1)) & ~((base) - 1)) -static void dump_header(struct rpm_header *header) +static void +import_properties(struct razor_importer *importer, + struct properties *properties, + const char *pool, unsigned long type) +{ + const char *name, *version; + int i, count; + + /* assert: count is the same for all arrays */ + + if (properties->name == NULL) + return; + + count = ntohl(properties->name->count); + name = pool + ntohl(properties->name->offset); + version = pool + ntohl(properties->version->offset); + for (i = 0; i < count; i++) { + razor_importer_add_property(importer, name, version, type); + name += strlen(name) + 1; + version += strlen(version) + 1; + } +} + +static void +import_files(struct razor_importer *importer, struct rpm *rpm) +{ + const char *name, **dir; + unsigned long *index; + int i, count; + char buffer[256]; + + /* assert: count is the same for all arrays */ + + if (rpm->dirnames == NULL) + return; + + count = ntohl(rpm->dirnames->count); + dir = calloc(count, sizeof *dir); + name = rpm->pool + ntohl(rpm->dirnames->offset); + for (i = 0; i < count; i++) { + dir[i] = name; + name += strlen(name) + 1; + } + + count = ntohl(rpm->basenames->count); + index = (unsigned long *) (rpm->pool + ntohl(rpm->dirindexes->offset)); + name = rpm->pool + ntohl(rpm->basenames->offset); + for (i = 0; i < count; i++) { + snprintf(buffer, sizeof buffer, + "%s%s", dir[ntohl(*index)], name); + razor_importer_add_file(importer, buffer); + name += strlen(name) + 1; + index++; + } +} + +static int +razor_rpm_open(struct rpm *rpm, const char *filename) { struct rpm_header_index *base, *index; - int i, j, nindex, tag, offset, type, count; - char *pool, *name; + struct stat buf; + int fd, nindex, hsize, i; - nindex = ntohl(header->nindex); - printf("header index records: %d\n", nindex); - printf("header storage size: %d\n", ntohl(header->hsize)); - base = (struct rpm_header_index *) (header + 1); - pool = (void *) (header + 1) + nindex * sizeof *index; + memset(rpm, 0, sizeof *rpm); + if (stat(filename, &buf) < 0) { + fprintf(stderr, "no such file %s (%m)\n", filename); + return -1; + } - printf("headers:\n"); + fd = open(filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "couldn't open %s\n", filename); + return -1; + } + rpm->size = buf.st_size; + rpm->map = mmap(NULL, rpm->size, PROT_READ, MAP_PRIVATE, fd, 0); + if (rpm->map == MAP_FAILED) { + fprintf(stderr, "couldn't mmap %s\n", filename); + return -1; + } + close(fd); + + rpm->signature = rpm->map + RPM_LEAD_SIZE; + nindex = ntohl(rpm->signature->nindex); + hsize = ntohl(rpm->signature->hsize); + rpm->header = (void *) (rpm->signature + 1) + + ALIGN(nindex * sizeof *index + hsize, 8); + + nindex = ntohl(rpm->header->nindex); + base = (struct rpm_header_index *) (rpm->header + 1); + rpm->pool = (void *) base + nindex * sizeof *index; + for (i = 0; i < nindex; i++) { index = base + i; - tag = ntohl(index->tag); - offset = ntohl(index->offset); - type = ntohl(index->type); - count = ntohl(index->count); - printf(" 0x%08x 0x%08x 0x%08x 0x%08x\n", - tag, type, offset, count); - - switch (tag) { + switch (ntohl(index->tag)) { case RPMTAG_NAME: - name = "name"; + rpm->name = index; break; case RPMTAG_VERSION: - name = "version"; + rpm->version = index; break; case RPMTAG_RELEASE: - name = "release"; + rpm->release = index; break; + case RPMTAG_REQUIRENAME: - name = "requires"; + rpm->requires.name = index; break; - default: - name = "unknown"; + case RPMTAG_REQUIREVERSION: + rpm->requires.version = index; break; - } + case RPMTAG_REQUIREFLAGS: + rpm->requires.flags = index; + break; - switch (type) { - case RPM_STRING_TYPE: - printf(" (%s %s)\n", name, pool + offset); + case RPMTAG_PROVIDENAME: + rpm->provides.name = index; break; - case RPM_STRING_ARRAY_TYPE: - printf(" (%s", name); - for (j = 0; j < count; j++) { - printf(" %s", pool + offset); - offset += strlen(pool + offset) + 1; - } - printf(")\n"); + case RPMTAG_PROVIDEVERSION: + rpm->provides.version = index; + break; + case RPMTAG_PROVIDEFLAGS: + rpm->provides.flags = index; + break; + + case RPMTAG_OBSOLETENAME: + rpm->obsoletes.name = index; + break; + case RPMTAG_OBSOLETEVERSION: + rpm->obsoletes.version = index; + break; + case RPMTAG_OBSOLETEFLAGS: + rpm->obsoletes.flags = index; + break; + + case RPMTAG_CONFLICTNAME: + rpm->conflicts.name = index; + break; + case RPMTAG_CONFLICTVERSION: + rpm->conflicts.version = index; + break; + case RPMTAG_CONFLICTFLAGS: + rpm->conflicts.flags = index; + break; + + case RPMTAG_DIRINDEXES: + rpm->dirindexes = index; + break; + case RPMTAG_BASENAMES: + rpm->basenames = index; + break; + case RPMTAG_DIRNAMES: + rpm->dirnames = index; break; } } + + return 0; } -void -razor_rpm_dump(const char *filename) +static int +razor_rpm_close(struct rpm *rpm) { - struct stat buf; - void *p; - int fd, nindex, hsize; - struct rpm_header *signature, *header; - struct rpm_header_index *index; + return munmap(rpm->map, rpm->size); +} - if (stat(filename, &buf) < 0) { - fprintf(stderr, "no such file %s\n", filename); - return; +int +razor_importer_add_rpm(struct razor_importer *importer, const char *filename) +{ + struct rpm rpm; + + if (razor_rpm_open(&rpm, filename) < 0) { + fprintf(stderr, "failed to open rpm %s (%m)\n", filename); + return -1; } - fd = open(filename, O_RDONLY); - p = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - close(fd); + razor_importer_begin_package(importer, + rpm.pool + ntohl(rpm.name->offset), + rpm.pool + ntohl(rpm.version->offset)); - printf("%s: %ldkB\n", filename, buf.st_size / 1024); - signature = p + RPM_LEAD_SIZE; + import_properties(importer, &rpm.requires, + rpm.pool, RAZOR_PROPERTY_REQUIRES); + import_properties(importer, &rpm.provides, + rpm.pool, RAZOR_PROPERTY_PROVIDES); + import_properties(importer, &rpm.conflicts, + rpm.pool, RAZOR_PROPERTY_CONFLICTS); + import_properties(importer, &rpm.obsoletes, + rpm.pool, RAZOR_PROPERTY_OBSOLETES); + import_files(importer, &rpm); - nindex = ntohl(signature->nindex); - hsize = ntohl(signature->hsize); - header = (void *) (signature + 1) + - ALIGN(nindex * sizeof *index + hsize, 8); + razor_importer_finish_package(importer); - dump_header(signature); - dump_header(header); + razor_rpm_close(&rpm); - munmap(p, buf.st_size); + return 0; }