2 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
3 * Copyright (C) 2008 Red Hat, Inc
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
37 /* Import a yum filelist as a razor package set. */
41 YUM_STATE_PACKAGE_NAME,
42 YUM_STATE_PACKAGE_ARCH,
44 YUM_STATE_DESCRIPTION,
56 XML_Parser primary_parser;
57 XML_Parser filelists_parser;
58 XML_Parser current_parser;
60 struct razor_importer *importer;
61 struct import_property_context *current_property_context;
62 char name[256], arch[64], summary[512], description[4096];
63 char url[256], license[64], buffer[512], *p;
65 uint32_t property_type;
72 yum_to_razor_relation (const char *flags)
74 if (flags[0] == 'L') {
76 return RAZOR_PROPERTY_LESS;
78 return RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL;
79 } else if (flags[0] == 'G') {
81 return RAZOR_PROPERTY_GREATER;
83 return RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL;
85 return RAZOR_PROPERTY_EQUAL;
89 yum_primary_start_element(void *data, const char *name, const char **atts)
91 struct yum_context *ctx = data;
92 const char *n, *epoch, *version, *release;
94 uint32_t pre, relation, flags;
97 if (strcmp(name, "metadata") == 0) {
98 for (i = 0; atts[i]; i += 2) {
99 if (strcmp(atts[i], "packages") == 0)
100 ctx->total = atoi(atts[i + 1]);
102 } else if (strcmp(name, "name") == 0) {
103 ctx->state = YUM_STATE_PACKAGE_NAME;
105 } else if (strcmp(name, "arch") == 0) {
106 ctx->state = YUM_STATE_PACKAGE_ARCH;
108 } else if (strcmp(name, "version") == 0) {
112 for (i = 0; atts[i]; i += 2) {
113 if (strcmp(atts[i], "epoch") == 0)
115 else if (strcmp(atts[i], "ver") == 0)
116 version = atts[i + 1];
117 else if (strcmp(atts[i], "rel") == 0)
118 release = atts[i + 1];
120 if (version == NULL || release == NULL) {
121 fprintf(stderr, "invalid version tag, "
122 "missing version or release attribute\n");
126 razor_build_evr(buffer, sizeof buffer, epoch, version, release);
127 razor_importer_begin_package(ctx->importer,
128 ctx->name, buffer, ctx->arch);
129 } else if (strcmp(name, "summary") == 0) {
130 ctx->p = ctx->summary;
131 ctx->state = YUM_STATE_SUMMARY;
132 } else if (strcmp(name, "description") == 0) {
133 ctx->p = ctx->description;
134 ctx->state = YUM_STATE_DESCRIPTION;
135 } else if (strcmp(name, "url") == 0) {
137 ctx->state = YUM_STATE_URL;
138 } else if (strcmp(name, "checksum") == 0) {
140 ctx->state = YUM_STATE_CHECKSUM;
141 } else if (strcmp(name, "rpm:license") == 0) {
142 ctx->p = ctx->license;
143 ctx->state = YUM_STATE_LICENSE;
144 } else if (strcmp(name, "rpm:requires") == 0) {
145 ctx->state = YUM_STATE_REQUIRES;
146 ctx->property_type = RAZOR_PROPERTY_REQUIRES;
147 } else if (strcmp(name, "rpm:provides") == 0) {
148 ctx->state = YUM_STATE_PROVIDES;
149 ctx->property_type = RAZOR_PROPERTY_PROVIDES;
150 } else if (strcmp(name, "rpm:obsoletes") == 0) {
151 ctx->state = YUM_STATE_OBSOLETES;
152 ctx->property_type = RAZOR_PROPERTY_OBSOLETES;
153 } else if (strcmp(name, "rpm:conflicts") == 0) {
154 ctx->state = YUM_STATE_CONFLICTS;
155 ctx->property_type = RAZOR_PROPERTY_CONFLICTS;
156 } else if (strcmp(name, "rpm:entry") == 0 &&
157 ctx->state != YUM_STATE_BEGIN) {
162 relation = RAZOR_PROPERTY_EQUAL;
164 for (i = 0; atts[i]; i += 2) {
165 if (strcmp(atts[i], "name") == 0)
167 else if (strcmp(atts[i], "epoch") == 0)
169 else if (strcmp(atts[i], "ver") == 0)
170 version = atts[i + 1];
171 else if (strcmp(atts[i], "rel") == 0)
172 release = atts[i + 1];
173 else if (strcmp(atts[i], "flags") == 0)
174 relation = yum_to_razor_relation(atts[i + 1]);
175 else if (strcmp(atts[i], "pre") == 0)
176 pre = RAZOR_PROPERTY_PRE;
180 fprintf(stderr, "invalid rpm:entry, "
181 "missing name or version attributes\n");
185 razor_build_evr(buffer, sizeof buffer, epoch, version, release);
186 flags = ctx->property_type | relation | pre;
187 razor_importer_add_property(ctx->importer, n, flags, buffer);
192 yum_primary_end_element (void *data, const char *name)
194 struct yum_context *ctx = data;
196 switch (ctx->state) {
197 case YUM_STATE_PACKAGE_NAME:
198 case YUM_STATE_PACKAGE_ARCH:
199 case YUM_STATE_SUMMARY:
200 case YUM_STATE_DESCRIPTION:
202 case YUM_STATE_LICENSE:
203 case YUM_STATE_CHECKSUM:
205 ctx->state = YUM_STATE_BEGIN;
209 if (strcmp(name, "package") == 0) {
210 razor_importer_add_details(ctx->importer, ctx->summary,
211 ctx->description, ctx->url,
214 XML_StopParser(ctx->current_parser, XML_TRUE);
215 ctx->current_parser = ctx->filelists_parser;
217 printf("\rimporting %d/%d", ++ctx->current, ctx->total);
223 yum_character_data (void *data, const XML_Char *s, int len)
225 struct yum_context *ctx = data;
227 switch (ctx->state) {
228 case YUM_STATE_PACKAGE_NAME:
229 case YUM_STATE_PACKAGE_ARCH:
230 case YUM_STATE_SUMMARY:
231 case YUM_STATE_DESCRIPTION:
233 case YUM_STATE_LICENSE:
234 case YUM_STATE_CHECKSUM:
236 memcpy(ctx->p, s, len);
244 yum_filelists_start_element(void *data, const char *name, const char **atts)
246 struct yum_context *ctx = data;
247 const char *pkg, *pkgid;
250 if (strcmp(name, "package") == 0) {
253 for (i = 0; atts[i]; i += 2) {
254 if (strcmp(atts[i], "name") == 0)
256 else if (strcmp(atts[i], "pkgid") == 0)
259 if (strcmp(pkgid, ctx->pkgid) != 0)
260 fprintf(stderr, "primary.xml and filelists.xml "
261 "mismatch for %s: %s vs %s",
262 pkg, pkgid, ctx->pkgid);
263 } else if (strcmp(name, "file") == 0) {
264 ctx->state = YUM_STATE_FILE;
265 ctx->p = ctx->buffer;
271 yum_filelists_end_element (void *data, const char *name)
273 struct yum_context *ctx = data;
275 ctx->state = YUM_STATE_BEGIN;
276 if (strcmp(name, "package") == 0) {
277 XML_StopParser(ctx->current_parser, XML_TRUE);
278 ctx->current_parser = ctx->primary_parser;
279 razor_importer_finish_package(ctx->importer);
280 } else if (strcmp(name, "file") == 0)
281 razor_importer_add_file(ctx->importer, ctx->buffer);
285 #define XML_BUFFER_SIZE 4096
287 struct razor_stream {
293 static int razor_stream_open(struct razor_stream *rs, const char *uri,
294 struct razor_error **error)
296 rs->strm.zalloc = Z_NULL;
297 rs->strm.zfree = Z_NULL;
298 rs->strm.opaque = Z_NULL;
299 rs->strm.avail_in = 0;
300 rs->strm.next_in = Z_NULL;
302 if (inflateInit2(&rs->strm, 15 + 16) != Z_OK) {
303 razor_set_error(error, RAZOR_GENERAL_ERROR,
304 RAZOR_GENERAL_ERROR_FAILED, uri,
305 "Failed to initialize inflator");
309 rs->in = razor_uri_get_contents(uri, &rs->in_length, 0, error);
311 (void)inflateEnd(&rs->strm);
315 rs->strm.avail_in = rs->in_length;
316 rs->strm.next_in = rs->in;
322 razor_stream_read(struct razor_stream *rs, unsigned char *buf, size_t len)
326 rs->strm.avail_out = len;
327 rs->strm.next_out = buf;
329 r = inflate(&rs->strm, Z_NO_FLUSH);
330 assert(r != Z_STREAM_ERROR); /* state not clobbered */
338 return len - rs->strm.avail_out;
341 static void razor_stream_close(struct razor_stream *rs)
343 (void)inflateEnd(&rs->strm);
344 (void)razor_uri_free_contents(rs->in, rs->in_length);
348 razor_set_create_from_yum(const char *yum_uri)
350 struct yum_context ctx={0};
354 XML_ParsingStatus status;
355 struct razor_error *error = NULL;
356 struct razor_stream primary, filelists;
358 ctx.importer = razor_importer_create();
359 ctx.state = YUM_STATE_BEGIN;
361 ctx.primary_parser = XML_ParserCreate(NULL);
362 XML_SetUserData(ctx.primary_parser, &ctx);
363 XML_SetElementHandler(ctx.primary_parser,
364 yum_primary_start_element,
365 yum_primary_end_element);
366 XML_SetCharacterDataHandler(ctx.primary_parser,
369 ctx.filelists_parser = XML_ParserCreate(NULL);
370 XML_SetUserData(ctx.filelists_parser, &ctx);
371 XML_SetElementHandler(ctx.filelists_parser,
372 yum_filelists_start_element,
373 yum_filelists_end_element);
374 XML_SetCharacterDataHandler(ctx.filelists_parser,
377 uri = razor_path_relative_to_uri(yum_uri, "repodata/primary.xml.gz",
380 fprintf(stderr, "%s: %s\n", yum_uri,
381 razor_error_get_msg(error));
382 razor_error_free(error);
385 if (razor_stream_open(&primary, uri, &error)) {
386 fprintf(stderr, "%s: %s\n", uri, razor_error_get_msg(error));
392 uri = razor_path_relative_to_uri(yum_uri, "repodata/filelists.xml.gz",
395 razor_stream_close(&primary);
396 fprintf(stderr, "%s: %s\n", yum_uri,
397 razor_error_get_msg(error));
398 razor_error_free(error);
401 if (razor_stream_open(&filelists, uri, &error)) {
402 razor_stream_close(&primary);
403 fprintf(stderr, "%s: %s\n", uri, razor_error_get_msg(error));
409 ctx.current_parser = ctx.primary_parser;
414 XML_GetParsingStatus(ctx.current_parser, &status);
415 switch (status.parsing) {
417 XML_ResumeParser(ctx.current_parser);
420 case XML_INITIALIZED:
421 buf = XML_GetBuffer(ctx.current_parser,
423 if (ctx.current_parser == ctx.primary_parser)
424 len = razor_stream_read(&primary, buf,
427 len = razor_stream_read(&filelists, buf,
431 "couldn't read input: %s\n",
436 XML_ParseBuffer(ctx.current_parser, len, len == 0);
441 } while (status.parsing != XML_FINISHED);
444 XML_ParserFree(ctx.primary_parser);
445 XML_ParserFree(ctx.filelists_parser);
447 razor_stream_close(&primary);
448 razor_stream_close(&filelists);
450 printf ("\nsaving\n");
451 return razor_importer_finish(ctx.importer);