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@27: #include "sha1.h" krh@27: #include "razor.h" krh@27: krh@27: static void krh@27: parse_package(struct import_context *ctx, 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@27: import_context_add_package(ctx, name, version); krh@27: } krh@27: krh@27: static void krh@27: parse_property(struct import_context *ctx, 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@27: import_context_add_property(ctx, data, name, version); krh@27: } krh@27: krh@27: static void krh@27: start_element(void *data, const char *name, const char **atts) krh@27: { krh@27: struct import_context *ctx = data; krh@27: krh@27: if (strcmp(name, "package") == 0) krh@27: parse_package(ctx, atts, NULL); krh@27: else if (strcmp(name, "requires") == 0) krh@27: parse_property(ctx, atts, &ctx->requires); krh@27: else if (strcmp(name, "provides") == 0) krh@27: parse_property(ctx, atts, &ctx->provides); krh@27: } krh@27: krh@27: static void krh@27: end_element (void *data, const char *name) krh@27: { krh@27: struct import_context *ctx = data; krh@27: krh@27: if (strcmp(name, "package") == 0) krh@27: import_context_finish_package(ctx); krh@27: } krh@27: krh@27: static int krh@27: import_rzr_file(struct import_context *ctx, 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@27: XML_SetUserData(parser, ctx); 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@27: "%s at line %d, %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@27: struct import_context ctx; krh@27: int i; krh@27: krh@27: razor_prepare_import(&ctx); krh@27: krh@27: for (i = 0; i < count; i++) { krh@27: if (import_rzr_file(&ctx, 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@27: return razor_finish_import(&ctx); 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@27: YUM_STATE_PACKAGE_NAME krh@27: }; krh@27: krh@27: struct yum_context { krh@27: struct import_context ctx; krh@27: struct import_property_context *current_property_context; krh@27: char *name; 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@27: const char *n, *version; krh@27: int i; krh@27: krh@27: if (strcmp(name, "name") == 0) { krh@27: ctx->state = YUM_STATE_PACKAGE_NAME; krh@27: } else if (strcmp(name, "version") == 0) { krh@27: version = 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@27: } krh@27: import_context_add_package(&ctx->ctx, ctx->name, version); krh@27: } else if (strcmp(name, "rpm:requires") == 0) { krh@27: ctx->current_property_context = &ctx->ctx.requires; krh@27: } else if (strcmp(name, "rpm:provides") == 0) { krh@27: ctx->current_property_context = &ctx->ctx.provides; krh@27: } else if (strcmp(name, "rpm:entry") == 0 && krh@27: ctx->current_property_context != NULL) { krh@27: n = NULL; krh@27: version = 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@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@27: import_context_add_property(&ctx->ctx, krh@27: ctx->current_property_context, krh@27: n, version); 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@27: if (strcmp(name, "package") == 0) { krh@27: free(ctx->name); krh@27: import_context_finish_package(&ctx->ctx); krh@27: } else if (strcmp(name, "name") == 0) { krh@27: ctx->state = 0; krh@27: } else if (strcmp(name, "rpm:requires") == 0) { krh@27: ctx->current_property_context = NULL; krh@27: } else if (strcmp(name, "rpm:provides") == 0) { krh@27: ctx->current_property_context = NULL; krh@27: } 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@27: if (ctx->state == YUM_STATE_PACKAGE_NAME) krh@27: ctx->name = strndup(s, len); 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@27: razor_prepare_import(&ctx.ctx); 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@27: "%s at line %d\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@27: return razor_finish_import(&ctx.ctx); krh@27: }