krh@74: #include krh@74: #include krh@74: #include krh@74: #include krh@74: #include krh@74: #include krh@74: #include krh@74: #include krh@74: krh@75: #include "razor.h" krh@75: krh@74: #define RPM_LEAD_SIZE 96 krh@74: krh@74: struct rpm_lead { krh@74: unsigned char magic[4]; krh@74: unsigned char major; krh@74: unsigned char minor; krh@74: short type; krh@74: short archnum; krh@74: char name[66]; krh@74: short osnum; krh@74: short signature_type; krh@74: char reserved[16]; krh@74: }; krh@74: krh@74: struct rpm_header { krh@74: unsigned char magic[4]; krh@74: unsigned char reserved[4]; krh@74: int nindex; krh@74: int hsize; krh@74: }; krh@74: krh@74: struct rpm_header_index { krh@74: int tag; krh@74: int type; krh@74: int offset; krh@74: int count; krh@74: }; krh@74: krh@75: struct properties { krh@75: struct rpm_header_index *name; krh@75: struct rpm_header_index *version; krh@75: struct rpm_header_index *flags; krh@75: }; krh@75: krh@75: struct rpm { krh@75: struct rpm_header *signature; krh@75: struct rpm_header *header; krh@75: krh@75: struct rpm_header_index *name; krh@75: struct rpm_header_index *version; krh@75: struct rpm_header_index *release; krh@75: krh@75: struct rpm_header_index *dirnames; krh@75: struct rpm_header_index *dirindexes; krh@75: struct rpm_header_index *basenames; krh@75: krh@75: struct properties provides; krh@75: struct properties requires; krh@75: struct properties obsoletes; krh@75: struct properties conflicts; krh@75: krh@75: const char *pool; krh@75: void *map; krh@75: size_t size; krh@75: }; krh@75: krh@74: #define ALIGN(value, base) (((value) + (base - 1)) & ~((base) - 1)) krh@74: krh@75: static void krh@75: import_properties(struct razor_importer *importer, krh@75: struct properties *properties, krh@75: const char *pool, unsigned long type) krh@75: { krh@75: const char *name, *version; krh@75: int i, count; krh@75: krh@75: /* assert: count is the same for all arrays */ krh@75: krh@75: if (properties->name == NULL) krh@75: return; krh@75: krh@75: count = ntohl(properties->name->count); krh@75: name = pool + ntohl(properties->name->offset); krh@75: version = pool + ntohl(properties->version->offset); krh@75: for (i = 0; i < count; i++) { krh@75: razor_importer_add_property(importer, name, version, type); krh@75: name += strlen(name) + 1; krh@75: version += strlen(version) + 1; krh@75: } krh@75: } krh@75: krh@75: static void krh@75: import_files(struct razor_importer *importer, struct rpm *rpm) krh@75: { krh@75: const char *name, **dir; krh@75: unsigned long *index; krh@75: int i, count; krh@75: char buffer[256]; krh@75: krh@75: /* assert: count is the same for all arrays */ krh@75: krh@75: if (rpm->dirnames == NULL) krh@75: return; krh@75: krh@75: count = ntohl(rpm->dirnames->count); krh@75: dir = calloc(count, sizeof *dir); krh@75: name = rpm->pool + ntohl(rpm->dirnames->offset); krh@75: for (i = 0; i < count; i++) { krh@75: dir[i] = name; krh@75: name += strlen(name) + 1; krh@75: } krh@75: krh@75: count = ntohl(rpm->basenames->count); krh@75: index = (unsigned long *) (rpm->pool + ntohl(rpm->dirindexes->offset)); krh@75: name = rpm->pool + ntohl(rpm->basenames->offset); krh@75: for (i = 0; i < count; i++) { krh@75: snprintf(buffer, sizeof buffer, krh@75: "%s%s", dir[ntohl(*index)], name); krh@75: razor_importer_add_file(importer, buffer); krh@75: name += strlen(name) + 1; krh@75: index++; krh@75: } krh@75: } krh@75: krh@75: static int krh@75: razor_rpm_open(struct rpm *rpm, const char *filename) krh@74: { krh@74: struct rpm_header_index *base, *index; krh@75: struct stat buf; krh@75: int fd, nindex, hsize, i; krh@74: krh@75: memset(rpm, 0, sizeof *rpm); krh@75: if (stat(filename, &buf) < 0) { krh@75: fprintf(stderr, "no such file %s (%m)\n", filename); krh@75: return -1; krh@75: } krh@74: krh@75: fd = open(filename, O_RDONLY); krh@75: if (fd < 0) { krh@75: fprintf(stderr, "couldn't open %s\n", filename); krh@75: return -1; krh@75: } krh@75: rpm->size = buf.st_size; krh@75: rpm->map = mmap(NULL, rpm->size, PROT_READ, MAP_PRIVATE, fd, 0); krh@75: if (rpm->map == MAP_FAILED) { krh@75: fprintf(stderr, "couldn't mmap %s\n", filename); krh@75: return -1; krh@75: } krh@75: close(fd); krh@75: krh@75: rpm->signature = rpm->map + RPM_LEAD_SIZE; krh@75: nindex = ntohl(rpm->signature->nindex); krh@75: hsize = ntohl(rpm->signature->hsize); krh@75: rpm->header = (void *) (rpm->signature + 1) + krh@75: ALIGN(nindex * sizeof *index + hsize, 8); krh@75: krh@75: nindex = ntohl(rpm->header->nindex); krh@75: base = (struct rpm_header_index *) (rpm->header + 1); krh@75: rpm->pool = (void *) base + nindex * sizeof *index; krh@75: krh@74: for (i = 0; i < nindex; i++) { krh@74: index = base + i; krh@75: switch (ntohl(index->tag)) { krh@74: case RPMTAG_NAME: krh@75: rpm->name = index; krh@74: break; krh@74: case RPMTAG_VERSION: krh@75: rpm->version = index; krh@74: break; krh@74: case RPMTAG_RELEASE: krh@75: rpm->release = index; krh@74: break; krh@75: krh@74: case RPMTAG_REQUIRENAME: krh@75: rpm->requires.name = index; krh@74: break; krh@75: case RPMTAG_REQUIREVERSION: krh@75: rpm->requires.version = index; krh@74: break; krh@75: case RPMTAG_REQUIREFLAGS: krh@75: rpm->requires.flags = index; krh@75: break; krh@74: krh@75: case RPMTAG_PROVIDENAME: krh@75: rpm->provides.name = index; krh@74: break; krh@75: case RPMTAG_PROVIDEVERSION: krh@75: rpm->provides.version = index; krh@75: break; krh@75: case RPMTAG_PROVIDEFLAGS: krh@75: rpm->provides.flags = index; krh@75: break; krh@75: krh@75: case RPMTAG_OBSOLETENAME: krh@75: rpm->obsoletes.name = index; krh@75: break; krh@75: case RPMTAG_OBSOLETEVERSION: krh@75: rpm->obsoletes.version = index; krh@75: break; krh@75: case RPMTAG_OBSOLETEFLAGS: krh@75: rpm->obsoletes.flags = index; krh@75: break; krh@75: krh@75: case RPMTAG_CONFLICTNAME: krh@75: rpm->conflicts.name = index; krh@75: break; krh@75: case RPMTAG_CONFLICTVERSION: krh@75: rpm->conflicts.version = index; krh@75: break; krh@75: case RPMTAG_CONFLICTFLAGS: krh@75: rpm->conflicts.flags = index; krh@75: break; krh@75: krh@75: case RPMTAG_DIRINDEXES: krh@75: rpm->dirindexes = index; krh@75: break; krh@75: case RPMTAG_BASENAMES: krh@75: rpm->basenames = index; krh@75: break; krh@75: case RPMTAG_DIRNAMES: krh@75: rpm->dirnames = index; krh@74: break; krh@74: } krh@74: } krh@75: krh@75: return 0; krh@74: } krh@74: krh@75: static int krh@75: razor_rpm_close(struct rpm *rpm) krh@74: { krh@75: return munmap(rpm->map, rpm->size); krh@75: } krh@74: krh@75: int krh@75: razor_importer_add_rpm(struct razor_importer *importer, const char *filename) krh@75: { krh@75: struct rpm rpm; krh@75: krh@75: if (razor_rpm_open(&rpm, filename) < 0) { krh@75: fprintf(stderr, "failed to open rpm %s (%m)\n", filename); krh@75: return -1; krh@74: } krh@74: krh@75: razor_importer_begin_package(importer, krh@75: rpm.pool + ntohl(rpm.name->offset), krh@75: rpm.pool + ntohl(rpm.version->offset)); krh@74: krh@75: import_properties(importer, &rpm.requires, krh@75: rpm.pool, RAZOR_PROPERTY_REQUIRES); krh@75: import_properties(importer, &rpm.provides, krh@75: rpm.pool, RAZOR_PROPERTY_PROVIDES); krh@75: import_properties(importer, &rpm.conflicts, krh@75: rpm.pool, RAZOR_PROPERTY_CONFLICTS); krh@75: import_properties(importer, &rpm.obsoletes, krh@75: rpm.pool, RAZOR_PROPERTY_OBSOLETES); krh@75: import_files(importer, &rpm); krh@74: krh@75: razor_importer_finish_package(importer); krh@74: krh@75: razor_rpm_close(&rpm); krh@74: krh@75: return 0; krh@74: }