krh@27: #define _GNU_SOURCE krh@27: krh@27: #include krh@27: #include krh@27: #include krh@27: #include krh@27: #include krh@27: #include krh@27: #include krh@27: krh@27: #include krh@28: #include krh@28: #include krh@27: #include "sha1.h" krh@27: #include "razor.h" krh@27: krh@27: static void krh@30: parse_package(struct razor_importer *importer, const char **atts, void *data) krh@27: { krh@27: const char *name = NULL, *version = NULL; krh@27: int i; krh@27: krh@27: for (i = 0; atts[i]; i += 2) { krh@27: if (strcmp(atts[i], "name") == 0) krh@27: name = atts[i + 1]; krh@27: else if (strcmp(atts[i], "version") == 0) krh@27: version = atts[i + 1]; krh@27: } krh@27: krh@27: if (name == NULL || version == NULL) { krh@27: fprintf(stderr, "invalid package tag, " krh@27: "missing name or version attributes\n"); krh@27: return; krh@27: } krh@27: krh@30: razor_importer_begin_package(importer, name, version); krh@27: } krh@27: krh@30: enum { krh@30: RZR_REQUIRES, RZR_PROVIDES krh@30: }; krh@30: krh@27: static void krh@30: parse_property(struct razor_importer *importer, const char **atts, void *data) krh@27: { krh@27: const char *name = NULL, *version = NULL; krh@27: int i; krh@27: krh@27: for (i = 0; atts[i]; i += 2) { krh@27: if (strcmp(atts[i], "name") == 0) krh@27: name = atts[i + 1]; krh@27: if (strcmp(atts[i], "version") == 0) krh@27: version = atts[i + 1]; krh@27: } krh@27: krh@27: if (name == NULL) { krh@27: fprintf(stderr, "invalid tag, missing name attribute\n"); krh@27: return; krh@27: } krh@27: krh@30: switch ((int) data) { krh@30: case RZR_REQUIRES: krh@66: razor_importer_add_property(importer, name, version, krh@66: RAZOR_PROPERTY_REQUIRES); krh@30: break; krh@30: case RZR_PROVIDES: krh@66: razor_importer_add_property(importer, name, version, krh@66: RAZOR_PROPERTY_PROVIDES); krh@30: break; krh@30: } krh@27: } krh@27: krh@27: static void krh@27: start_element(void *data, const char *name, const char **atts) krh@27: { krh@30: struct razor_importer *importer = data; krh@27: krh@27: if (strcmp(name, "package") == 0) krh@30: parse_package(importer, atts, NULL); krh@27: else if (strcmp(name, "requires") == 0) krh@30: parse_property(importer, atts, (void *) RZR_REQUIRES); krh@27: else if (strcmp(name, "provides") == 0) krh@30: parse_property(importer, atts, (void*) RZR_PROVIDES); krh@27: } krh@27: krh@27: static void krh@27: end_element (void *data, const char *name) krh@27: { krh@30: struct razor_importer *importer = data; krh@27: krh@27: if (strcmp(name, "package") == 0) krh@30: razor_importer_finish_package(importer); krh@27: } krh@27: krh@27: static int krh@30: import_rzr_file(struct razor_importer *importer, const char *filename) krh@27: { krh@27: SHA_CTX sha1; krh@27: XML_Parser parser; krh@27: int fd; krh@27: void *p; krh@27: struct stat stat; krh@27: unsigned char hash[20]; krh@27: krh@27: fd = open(filename, O_RDONLY); krh@27: if (fstat(fd, &stat) < 0) krh@27: return -1; krh@27: p = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0); krh@27: if (p == MAP_FAILED) krh@27: return -1; krh@27: krh@27: parser = XML_ParserCreate(NULL); krh@30: XML_SetUserData(parser, importer); krh@27: XML_SetElementHandler(parser, start_element, end_element); krh@27: if (XML_Parse(parser, p, stat.st_size, 1) == XML_STATUS_ERROR) { krh@27: fprintf(stderr, krh@46: "%s at line %ld, %s\n", krh@27: XML_ErrorString(XML_GetErrorCode(parser)), krh@27: XML_GetCurrentLineNumber(parser), krh@27: filename); krh@27: return 1; krh@27: } krh@27: krh@27: XML_ParserFree(parser); krh@27: krh@27: SHA1_Init(&sha1); krh@27: SHA1_Update(&sha1, p, stat.st_size); krh@27: SHA1_Final(hash, &sha1); krh@27: krh@27: close(fd); krh@27: krh@27: munmap(p, stat.st_size); krh@27: krh@27: return 0; krh@27: } krh@27: krh@27: struct razor_set * krh@27: razor_import_rzr_files(int count, const char *files[]) krh@27: { krh@30: struct razor_importer *importer; krh@27: int i; krh@27: krh@30: importer = razor_importer_new(); krh@27: krh@27: for (i = 0; i < count; i++) { krh@30: if (import_rzr_file(importer, files[i]) < 0) { krh@27: fprintf(stderr, "failed to import %s\n", files[i]); krh@27: exit(-1); krh@27: } krh@27: } krh@27: krh@30: return razor_importer_finish(importer); krh@27: } krh@27: krh@27: /* Import a yum filelist as a razor package set. */ krh@27: krh@27: enum { krh@27: YUM_STATE_BEGIN, krh@30: YUM_STATE_PACKAGE_NAME, krh@30: YUM_STATE_REQUIRES, krh@46: YUM_STATE_PROVIDES, krh@67: YUM_STATE_OBSOLETES, krh@67: YUM_STATE_CONFLICTS, krh@46: YUM_STATE_FILE krh@27: }; krh@27: krh@27: struct yum_context { krh@30: struct razor_importer *importer; krh@27: struct import_property_context *current_property_context; krh@48: char name[256], buffer[512], *p; krh@27: int state; krh@27: }; krh@27: krh@27: static void krh@27: yum_start_element(void *data, const char *name, const char **atts) krh@27: { krh@27: struct yum_context *ctx = data; krh@62: const char *n, *version, *release; krh@62: char buffer[128]; krh@27: int i; krh@27: krh@27: if (strcmp(name, "name") == 0) { krh@27: ctx->state = YUM_STATE_PACKAGE_NAME; krh@48: ctx->p = ctx->name; krh@27: } else if (strcmp(name, "version") == 0) { krh@27: version = NULL; krh@62: release = NULL; krh@27: for (i = 0; atts[i]; i += 2) { krh@27: if (strcmp(atts[i], "ver") == 0) krh@27: version = atts[i + 1]; krh@62: else if (strcmp(atts[i], "rel") == 0) krh@62: release = atts[i + 1]; krh@27: } krh@62: if (version == NULL || release == NULL) { krh@62: fprintf(stderr, "invalid version tag, " krh@62: "missing version or release attribute\n"); krh@62: return; krh@62: } krh@62: krh@62: snprintf(buffer, sizeof buffer, "%s-%s", version, release); krh@62: razor_importer_begin_package(ctx->importer, ctx->name, buffer); krh@27: } else if (strcmp(name, "rpm:requires") == 0) { krh@30: ctx->state = YUM_STATE_REQUIRES; krh@27: } else if (strcmp(name, "rpm:provides") == 0) { krh@30: ctx->state = YUM_STATE_PROVIDES; krh@67: } else if (strcmp(name, "rpm:obsoletes") == 0) { krh@67: ctx->state = YUM_STATE_OBSOLETES; krh@67: } else if (strcmp(name, "rpm:conflicts") == 0) { krh@67: ctx->state = YUM_STATE_CONFLICTS; krh@27: } else if (strcmp(name, "rpm:entry") == 0 && krh@30: ctx->state != YUM_STATE_BEGIN) { krh@27: n = NULL; krh@27: version = NULL; krh@62: release = NULL; krh@27: for (i = 0; atts[i]; i += 2) { krh@27: if (strcmp(atts[i], "name") == 0) krh@27: n = atts[i + 1]; krh@27: else if (strcmp(atts[i], "ver") == 0) krh@27: version = atts[i + 1]; krh@62: else if (strcmp(atts[i], "rel") == 0) krh@62: release = atts[i + 1]; krh@27: } krh@27: krh@27: if (n == NULL) { krh@27: fprintf(stderr, "invalid rpm:entry, " krh@27: "missing name or version attributes\n"); krh@27: return; krh@27: } krh@27: krh@62: if (version && release) krh@62: snprintf(buffer, sizeof buffer, krh@62: "%s-%s", version, release); krh@62: else if (version) krh@62: strcpy(buffer, version); krh@62: else krh@62: buffer[0] = '\0'; krh@62: krh@30: switch (ctx->state) { krh@30: case YUM_STATE_REQUIRES: krh@66: razor_importer_add_property(ctx->importer, n, buffer, krh@66: RAZOR_PROPERTY_REQUIRES); krh@30: break; krh@30: case YUM_STATE_PROVIDES: krh@66: razor_importer_add_property(ctx->importer, n, buffer, krh@66: RAZOR_PROPERTY_PROVIDES); krh@30: break; krh@67: case YUM_STATE_OBSOLETES: krh@67: razor_importer_add_property(ctx->importer, n, buffer, krh@67: RAZOR_PROPERTY_OBSOLETES); krh@67: break; krh@67: case YUM_STATE_CONFLICTS: krh@67: razor_importer_add_property(ctx->importer, n, buffer, krh@67: RAZOR_PROPERTY_CONFLICTS); krh@67: break; krh@30: } krh@46: } else if (strcmp(name, "file") == 0) { krh@46: ctx->state = YUM_STATE_FILE; krh@48: ctx->p = ctx->buffer; krh@27: } krh@27: } krh@27: krh@27: static void krh@27: yum_end_element (void *data, const char *name) krh@27: { krh@27: struct yum_context *ctx = data; krh@27: krh@46: ctx->state = YUM_STATE_BEGIN; krh@48: if (strcmp(name, "package") == 0) krh@30: razor_importer_finish_package(ctx->importer); krh@48: else if (strcmp(name, "file") == 0) krh@48: razor_importer_add_file(ctx->importer, ctx->buffer); krh@27: } krh@27: krh@27: static void krh@27: yum_character_data (void *data, const XML_Char *s, int len) krh@27: { krh@27: struct yum_context *ctx = data; krh@27: krh@48: switch (ctx->state) { krh@48: case YUM_STATE_PACKAGE_NAME: krh@48: case YUM_STATE_FILE: krh@48: memcpy(ctx->p, s, len); krh@48: ctx->p += len; krh@48: *ctx->p = '\0'; krh@48: break; krh@46: } krh@27: } krh@27: krh@27: struct razor_set * krh@27: razor_set_create_from_yum_filelist(int fd) krh@27: { krh@27: struct yum_context ctx; krh@27: XML_Parser parser; krh@27: char buf[4096]; krh@27: int len; krh@27: krh@30: ctx.importer = razor_importer_new(); krh@62: ctx.state = YUM_STATE_BEGIN; krh@27: krh@27: parser = XML_ParserCreate(NULL); krh@27: XML_SetUserData(parser, &ctx); krh@27: XML_SetElementHandler(parser, yum_start_element, yum_end_element); krh@27: XML_SetCharacterDataHandler(parser, yum_character_data); krh@27: krh@27: while (1) { krh@27: len = read(fd, buf, sizeof buf); krh@27: if (len < 0) { krh@27: fprintf(stderr, krh@27: "couldn't read input: %s\n", strerror(errno)); krh@27: return NULL; krh@27: } else if (len == 0) krh@27: break; krh@27: krh@27: if (XML_Parse(parser, buf, len, 0) == XML_STATUS_ERROR) { krh@27: fprintf(stderr, krh@46: "%s at line %ld\n", krh@27: XML_ErrorString(XML_GetErrorCode(parser)), krh@27: XML_GetCurrentLineNumber(parser)); krh@27: return NULL; krh@27: } krh@27: } krh@27: krh@27: XML_ParserFree(parser); krh@27: krh@30: return razor_importer_finish(ctx.importer); krh@27: } krh@28: krh@31: union rpm_entry { krh@31: void *p; krh@31: char *string; krh@31: char **list; krh@42: unsigned int *flags; krh@31: }; krh@31: krh@28: struct razor_set * krh@28: razor_set_create_from_rpmdb(void) krh@28: { krh@30: struct razor_importer *importer; krh@28: rpmdbMatchIterator iter; krh@28: Header h; krh@28: int_32 type, count, i; krh@42: union rpm_entry name, version, release; krh@42: union rpm_entry property_names, property_versions, property_flags; krh@46: union rpm_entry basenames, dirnames, dirindexes; krh@46: char filename[PATH_MAX]; krh@28: rpmdb db; krh@28: krh@28: rpmReadConfigFiles(NULL, NULL); krh@28: krh@28: if (rpmdbOpen("", &db, O_RDONLY, 0644) != 0) { krh@28: fprintf(stderr, "cannot open rpm database\n"); krh@28: exit(1); krh@28: } krh@28: krh@30: importer = razor_importer_new(); krh@28: krh@28: iter = rpmdbInitIterator(db, 0, NULL, 0); krh@28: while (h = rpmdbNextIterator(iter), h != NULL) { krh@31: headerGetEntry(h, RPMTAG_NAME, &type, &name.p, &count); krh@42: headerGetEntry(h, RPMTAG_VERSION, &type, &version.p, &count); krh@31: headerGetEntry(h, RPMTAG_RELEASE, &type, &release.p, &count); krh@59: snprintf(filename, sizeof filename, "%s-%s", krh@59: version.string, release.string); krh@59: razor_importer_begin_package(importer, name.string, filename); krh@28: krh@42: headerGetEntry(h, RPMTAG_REQUIRENAME, &type, krh@42: &property_names.p, &count); krh@28: headerGetEntry(h, RPMTAG_REQUIREVERSION, &type, krh@31: &property_versions.p, &count); krh@42: headerGetEntry(h, RPMTAG_REQUIREFLAGS, &type, krh@42: &property_flags.p, &count); krh@28: for (i = 0; i < count; i++) krh@66: razor_importer_add_property(importer, krh@42: property_names.list[i], krh@66: property_versions.list[i], krh@66: RAZOR_PROPERTY_REQUIRES); krh@28: krh@42: headerGetEntry(h, RPMTAG_PROVIDENAME, &type, krh@42: &property_names.p, &count); krh@28: headerGetEntry(h, RPMTAG_PROVIDEVERSION, &type, krh@31: &property_versions.p, &count); krh@67: headerGetEntry(h, RPMTAG_PROVIDEFLAGS, &type, krh@67: &property_flags.p, &count); krh@28: for (i = 0; i < count; i++) krh@66: razor_importer_add_property(importer, krh@42: property_names.list[i], krh@66: property_versions.list[i], krh@66: RAZOR_PROPERTY_PROVIDES); krh@28: krh@67: headerGetEntry(h, RPMTAG_OBSOLETENAME, &type, krh@67: &property_names.p, &count); krh@67: headerGetEntry(h, RPMTAG_OBSOLETEVERSION, &type, krh@67: &property_versions.p, &count); krh@67: headerGetEntry(h, RPMTAG_OBSOLETEFLAGS, &type, krh@67: &property_flags.p, &count); krh@67: for (i = 0; i < count; i++) krh@67: razor_importer_add_property(importer, krh@67: property_names.list[i], krh@67: property_versions.list[i], krh@67: RAZOR_PROPERTY_OBSOLETES); krh@67: krh@67: headerGetEntry(h, RPMTAG_CONFLICTNAME, &type, krh@67: &property_names.p, &count); krh@67: headerGetEntry(h, RPMTAG_CONFLICTVERSION, &type, krh@67: &property_versions.p, &count); krh@67: headerGetEntry(h, RPMTAG_CONFLICTFLAGS, &type, krh@67: &property_flags.p, &count); krh@67: for (i = 0; i < count; i++) krh@67: razor_importer_add_property(importer, krh@67: property_names.list[i], krh@67: property_versions.list[i], krh@67: RAZOR_PROPERTY_CONFLICTS); krh@67: krh@46: headerGetEntry(h, RPMTAG_BASENAMES, &type, krh@46: &basenames.p, &count); krh@46: headerGetEntry(h, RPMTAG_DIRNAMES, &type, krh@46: &dirnames.p, &count); krh@46: headerGetEntry(h, RPMTAG_DIRINDEXES, &type, krh@46: &dirindexes.p, &count); krh@46: for (i = 0; i < count; i++) { krh@46: snprintf(filename, sizeof filename, "%s%s", krh@46: dirnames.list[dirindexes.flags[i]], krh@46: basenames.list[i]); krh@46: razor_importer_add_file(importer, filename); krh@46: } krh@46: krh@30: razor_importer_finish_package(importer); krh@28: } krh@28: krh@28: rpmdbClose(db); krh@28: krh@30: return razor_importer_finish(importer); krh@28: }