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@70: #include krh@28: #include krh@28: #include krh@27: #include "sha1.h" krh@27: #include "razor.h" 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@70: YUM_STATE_CHECKSUM, 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@70: XML_Parser primary_parser; krh@70: XML_Parser filelists_parser; krh@70: XML_Parser current_parser; krh@70: krh@30: struct razor_importer *importer; krh@27: struct import_property_context *current_property_context; krh@48: char name[256], buffer[512], *p; krh@70: char pkgid[128]; krh@27: int state; krh@27: }; krh@27: krh@27: static void krh@70: yum_primary_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@70: } else if (strcmp(name, "checksum") == 0) { krh@70: ctx->p = ctx->pkgid; krh@70: ctx->state = YUM_STATE_CHECKSUM; 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@27: } krh@27: } krh@27: krh@27: static void krh@70: yum_primary_end_element (void *data, const char *name) krh@27: { krh@27: struct yum_context *ctx = data; krh@27: krh@68: switch (ctx->state) { krh@68: case YUM_STATE_PACKAGE_NAME: krh@70: case YUM_STATE_CHECKSUM: krh@68: case YUM_STATE_FILE: krh@68: ctx->state = YUM_STATE_BEGIN; krh@68: break; krh@68: } krh@68: krh@70: if (strcmp(name, "package") == 0) { krh@70: XML_StopParser(ctx->current_parser, XML_TRUE); krh@70: ctx->current_parser = ctx->filelists_parser; krh@70: } 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@70: case YUM_STATE_CHECKSUM: 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@70: static void krh@70: yum_filelists_start_element(void *data, const char *name, const char **atts) krh@70: { krh@70: struct yum_context *ctx = data; krh@70: const char *pkg, *pkgid; krh@70: int i; krh@70: krh@70: if (strcmp(name, "package") == 0) { krh@70: pkg = NULL; krh@70: pkgid = NULL; krh@70: for (i = 0; atts[i]; i += 2) { krh@70: if (strcmp(atts[i], "name") == 0) krh@70: pkg = atts[i + 1]; krh@70: else if (strcmp(atts[i], "pkgid") == 0) krh@70: pkgid = atts[i + 1]; krh@70: } krh@70: if (strcmp(pkgid, ctx->pkgid) != 0) krh@70: fprintf(stderr, "primary.xml and filelists.xml " krh@70: "mismatch for %s: %s vs %s", krh@70: pkg, pkgid, ctx->pkgid); krh@70: } else if (strcmp(name, "file") == 0) { krh@70: ctx->state = YUM_STATE_FILE; krh@70: ctx->p = ctx->buffer; krh@70: } krh@70: } krh@70: krh@70: krh@70: static void krh@70: yum_filelists_end_element (void *data, const char *name) krh@70: { krh@70: struct yum_context *ctx = data; krh@70: krh@70: ctx->state = YUM_STATE_BEGIN; krh@70: if (strcmp(name, "package") == 0) { krh@70: XML_StopParser(ctx->current_parser, XML_TRUE); krh@70: ctx->current_parser = ctx->primary_parser; krh@70: razor_importer_finish_package(ctx->importer); krh@70: } else if (strcmp(name, "file") == 0) krh@70: razor_importer_add_file(ctx->importer, ctx->buffer); krh@70: krh@70: } krh@70: krh@70: #define XML_BUFFER_SIZE 4096 krh@70: krh@27: struct razor_set * krh@70: razor_set_create_from_yum(void) krh@27: { krh@27: struct yum_context ctx; krh@70: void *buf; krh@70: int len, ret; krh@70: gzFile primary, filelists; krh@70: XML_ParsingStatus status; krh@27: krh@30: ctx.importer = razor_importer_new(); krh@62: ctx.state = YUM_STATE_BEGIN; krh@27: krh@70: ctx.primary_parser = XML_ParserCreate(NULL); krh@70: XML_SetUserData(ctx.primary_parser, &ctx); krh@70: XML_SetElementHandler(ctx.primary_parser, krh@70: yum_primary_start_element, krh@70: yum_primary_end_element); krh@70: XML_SetCharacterDataHandler(ctx.primary_parser, krh@70: yum_character_data); krh@27: krh@70: ctx.filelists_parser = XML_ParserCreate(NULL); krh@70: XML_SetUserData(ctx.filelists_parser, &ctx); krh@70: XML_SetElementHandler(ctx.filelists_parser, krh@70: yum_filelists_start_element, krh@70: yum_filelists_end_element); krh@70: XML_SetCharacterDataHandler(ctx.filelists_parser, krh@70: yum_character_data); krh@70: krh@70: primary = gzopen("primary.xml.gz", "rb"); krh@70: if (primary == NULL) krh@70: return NULL; krh@70: filelists = gzopen("filelists.xml.gz", "rb"); krh@70: if (filelists == NULL) krh@70: return NULL; krh@70: krh@70: ctx.current_parser = ctx.primary_parser; krh@70: krh@70: do { krh@70: XML_GetParsingStatus(ctx.current_parser, &status); krh@70: switch (status.parsing) { krh@70: case XML_SUSPENDED: krh@70: ret = XML_ResumeParser(ctx.current_parser); krh@27: break; krh@70: case XML_PARSING: krh@70: case XML_INITIALIZED: krh@70: buf = XML_GetBuffer(ctx.current_parser, krh@70: XML_BUFFER_SIZE); krh@70: if (ctx.current_parser == ctx.primary_parser) krh@70: len = gzread(primary, buf, XML_BUFFER_SIZE); krh@70: else krh@70: len = gzread(filelists, buf, XML_BUFFER_SIZE); krh@70: if (len < 0) { krh@70: fprintf(stderr, krh@70: "couldn't read input: %s\n", krh@70: strerror(errno)); krh@70: return NULL; krh@70: } krh@27: krh@70: XML_ParseBuffer(ctx.current_parser, len, len == 0); krh@70: break; krh@70: case XML_FINISHED: krh@70: break; krh@27: } krh@70: } while (status.parsing != XML_FINISHED); krh@27: krh@70: krh@70: XML_ParserFree(ctx.primary_parser); krh@70: XML_ParserFree(ctx.filelists_parser); krh@70: krh@70: gzclose(primary); krh@70: gzclose(filelists); 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: }