2 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
3 * Copyright (C) 2008 Red Hat, Inc
4 * Copyright (C) 2009, 2011, 2014, 2016 J. Ali Harlow <ali@juiblex.co.uk>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
35 #include "plover/plover.h"
36 #include "plover/uri-handler.h"
37 #include "plover/inputstream.h"
39 /* Import a yum filelist as a razor package set. */
43 YUM_STATE_PACKAGE_NAME,
44 YUM_STATE_PACKAGE_ARCH,
46 YUM_STATE_DESCRIPTION,
54 YUM_STATE_SKIPPING_PACKAGE,
59 XML_Parser primary_parser;
60 XML_Parser filelists_parser;
61 XML_Parser current_parser;
63 struct razor_importer *importer;
64 struct import_property_context *current_property_context;
67 char name[256], arch[64], summary[512], description[4096];
68 char url[256], license[64], buffer[512], *p;
69 char pkgid[128], evr[128];
70 uint32_t property_type;
77 yum_to_razor_relation (const char *flags)
79 if (flags[0] == 'L') {
81 return RAZOR_PROPERTY_LESS;
83 return RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL;
84 } else if (flags[0] == 'G') {
86 return RAZOR_PROPERTY_GREATER;
88 return RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL;
90 return RAZOR_PROPERTY_EQUAL;
94 yum_primary_start_element(void *data, const char *name, const char **atts)
96 struct yum_context *ctx = data;
97 const char *n, *epoch, *version, *release;
101 uint32_t pre, relation, flags;
104 if (ctx->state == YUM_STATE_SKIPPING_PACKAGE)
107 if (strcmp(name, "metadata") == 0) {
108 for (i = 0; atts[i]; i += 2) {
109 if (strcmp(atts[i], "packages") == 0)
110 ctx->total = atoi(atts[i + 1]);
112 } else if (strcmp(name, "package") == 0) {
113 *ctx->name=*ctx->arch=*ctx->summary=*ctx->description='\0';
114 *ctx->url=*ctx->license='\0';
115 } else if (strcmp(name, "name") == 0) {
116 ctx->state = YUM_STATE_PACKAGE_NAME;
118 } else if (strcmp(name, "arch") == 0) {
119 ctx->state = YUM_STATE_PACKAGE_ARCH;
121 } else if (strcmp(name, "version") == 0) {
125 for (i = 0; atts[i]; i += 2) {
126 if (strcmp(atts[i], "epoch") == 0)
128 else if (strcmp(atts[i], "ver") == 0)
129 version = atts[i + 1];
130 else if (strcmp(atts[i], "rel") == 0)
131 release = atts[i + 1];
133 if (version == NULL || release == NULL) {
134 fprintf(stderr, "invalid version tag, "
135 "missing version or release attribute\n");
139 razor_build_evr(ctx->evr, sizeof ctx->evr, epoch, version,
141 if (!strcmp(ctx->arch, "noarch") ||
142 !strcmp(ctx->arch, razor_system_arch())) {
143 razor_importer_begin_package(ctx->importer, ctx->name,
144 ctx->evr, ctx->arch);
146 ctx->state = YUM_STATE_SKIPPING_PACKAGE;
147 } else if (strcmp(name, "summary") == 0) {
148 ctx->p = ctx->summary;
149 ctx->state = YUM_STATE_SUMMARY;
150 } else if (strcmp(name, "description") == 0) {
151 ctx->p = ctx->description;
152 ctx->state = YUM_STATE_DESCRIPTION;
153 } else if (strcmp(name, "url") == 0) {
155 ctx->state = YUM_STATE_URL;
156 } else if (strcmp(name, "checksum") == 0) {
158 ctx->state = YUM_STATE_CHECKSUM;
159 } else if (strcmp(name, "location") == 0) {
160 if (ctx->state != YUM_STATE_SKIPPING_PACKAGE) {
161 for (i = 0; atts[i]; i += 2)
162 if (strcmp(atts[i], "href") == 0) {
163 nevra=g_strconcat(ctx->name,"-",ctx->evr,".",
165 s=razor_path_relative_to_uri(ctx->base_uri,
167 g_tree_insert(ctx->uris,nevra,g_strdup(s));
172 } else if (strcmp(name, "rpm:license") == 0) {
173 ctx->p = ctx->license;
174 ctx->state = YUM_STATE_LICENSE;
175 } else if (strcmp(name, "rpm:requires") == 0) {
176 ctx->state = YUM_STATE_REQUIRES;
177 ctx->property_type = RAZOR_PROPERTY_REQUIRES;
178 } else if (strcmp(name, "rpm:provides") == 0) {
179 ctx->state = YUM_STATE_PROVIDES;
180 ctx->property_type = RAZOR_PROPERTY_PROVIDES;
181 } else if (strcmp(name, "rpm:obsoletes") == 0) {
182 ctx->state = YUM_STATE_OBSOLETES;
183 ctx->property_type = RAZOR_PROPERTY_OBSOLETES;
184 } else if (strcmp(name, "rpm:conflicts") == 0) {
185 ctx->state = YUM_STATE_CONFLICTS;
186 ctx->property_type = RAZOR_PROPERTY_CONFLICTS;
187 } else if (strcmp(name, "rpm:entry") == 0 &&
188 ctx->state != YUM_STATE_BEGIN) {
193 relation = RAZOR_PROPERTY_EQUAL;
195 for (i = 0; atts[i]; i += 2) {
196 if (strcmp(atts[i], "name") == 0)
198 else if (strcmp(atts[i], "epoch") == 0)
200 else if (strcmp(atts[i], "ver") == 0)
201 version = atts[i + 1];
202 else if (strcmp(atts[i], "rel") == 0)
203 release = atts[i + 1];
204 else if (strcmp(atts[i], "flags") == 0)
205 relation = yum_to_razor_relation(atts[i + 1]);
206 else if (strcmp(atts[i], "pre") == 0)
207 pre = RAZOR_PROPERTY_PRE;
211 fprintf(stderr, "invalid rpm:entry, "
212 "missing name or version attributes\n");
216 razor_build_evr(buffer, sizeof buffer, epoch, version, release);
217 flags = ctx->property_type | relation | pre;
218 razor_importer_add_property(ctx->importer, n, flags, buffer);
223 yum_primary_end_element (void *data, const char *name)
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 ctx->state = YUM_STATE_BEGIN;
240 if (strcmp(name, "package") == 0) {
241 if (ctx->state != YUM_STATE_SKIPPING_PACKAGE)
242 razor_importer_add_details(ctx->importer, ctx->summary,
243 ctx->description, ctx->url,
246 XML_StopParser(ctx->current_parser, XML_TRUE);
247 ctx->current_parser = ctx->filelists_parser;
252 yum_character_data (void *data, const XML_Char *s, int len)
254 struct yum_context *ctx = data;
256 switch (ctx->state) {
257 case YUM_STATE_PACKAGE_NAME:
258 case YUM_STATE_PACKAGE_ARCH:
259 case YUM_STATE_SUMMARY:
260 case YUM_STATE_DESCRIPTION:
262 case YUM_STATE_LICENSE:
263 case YUM_STATE_CHECKSUM:
265 memcpy(ctx->p, s, len);
273 yum_filelists_start_element(void *data, const char *name, const char **atts)
275 struct yum_context *ctx = data;
276 const char *pkg, *pkgid;
279 if (strcmp(name, "package") == 0 &&
280 ctx->state != YUM_STATE_SKIPPING_PACKAGE) {
283 for (i = 0; atts[i]; i += 2) {
284 if (strcmp(atts[i], "name") == 0)
286 else if (strcmp(atts[i], "pkgid") == 0)
289 if (strcmp(pkgid, ctx->pkgid) != 0)
290 fprintf(stderr, "primary.xml and filelists.xml "
291 "mismatch for %s: %s vs %s",
292 pkg, pkgid, ctx->pkgid);
293 } else if (strcmp(name, "file") == 0) {
294 if (ctx->state != YUM_STATE_SKIPPING_PACKAGE)
295 ctx->state = YUM_STATE_FILE;
296 ctx->p = ctx->buffer;
301 yum_filelists_end_element (void *data, const char *name)
303 struct yum_context *ctx = data;
305 if (strcmp(name, "package") == 0) {
306 XML_StopParser(ctx->current_parser, XML_TRUE);
307 ctx->current_parser = ctx->primary_parser;
308 if (ctx->state != YUM_STATE_SKIPPING_PACKAGE)
309 razor_importer_finish_package(ctx->importer);
310 ctx->state = YUM_STATE_BEGIN;
311 } else if (strcmp(name, "file") == 0) {
312 if (ctx->state != YUM_STATE_SKIPPING_PACKAGE)
313 razor_importer_add_file(ctx->importer, ctx->buffer);
315 if (ctx->state != YUM_STATE_SKIPPING_PACKAGE)
316 ctx->state = YUM_STATE_BEGIN;
319 static int plover_system_arch_is_x86(void)
321 const char *arch=razor_system_arch();
322 if (!arch || arch[0]!='i' || arch[1]<'3' || arch[1]>'6')
325 return !strcmp(arch+2,"86");
328 #define XML_BUFFER_SIZE 4096
330 PloverRepository *plover_repository_new_from_yum_uri(const char *base_uri,
333 struct yum_context ctx;
337 const char *name,*version,*arch;
340 GInputStream *stream;
341 GInputStream *primary,*filelists;
342 GZlibDecompressor *decompressor;
343 XML_ParsingStatus status;
344 struct razor_set *razor;
345 struct razor_package_iterator *iter;
346 struct razor_package *pkg;
347 PloverPackageSet *set;
348 PloverRepository *repository;
349 g_return_val_if_fail(plover__uri_validate(base_uri),NULL);
350 plover__uri_handler_init();
351 ctx.importer=razor_importer_create();
352 ctx.state=YUM_STATE_BEGIN;
353 ctx.base_uri=base_uri;
354 ctx.primary_parser=XML_ParserCreate(NULL);
355 XML_SetUserData(ctx.primary_parser,&ctx);
356 XML_SetElementHandler(ctx.primary_parser,yum_primary_start_element,
357 yum_primary_end_element);
358 XML_SetCharacterDataHandler(ctx.primary_parser,yum_character_data);
359 ctx.filelists_parser=XML_ParserCreate(NULL);
360 XML_SetUserData(ctx.filelists_parser,&ctx);
361 XML_SetElementHandler(ctx.filelists_parser,yum_filelists_start_element,
362 yum_filelists_end_element);
363 XML_SetCharacterDataHandler(ctx.filelists_parser,yum_character_data);
364 uri=razor_path_relative_to_uri(base_uri,"repodata/primary.xml.gz",NULL);
365 stream=plover_razor_input_stream_new(uri,error);
368 XML_ParserFree(ctx.primary_parser);
369 XML_ParserFree(ctx.filelists_parser);
372 decompressor=g_zlib_decompressor_new(G_ZLIB_COMPRESSOR_FORMAT_GZIP);
373 primary=g_converter_input_stream_new(G_INPUT_STREAM(stream),
374 G_CONVERTER(decompressor));
375 g_object_unref(stream);
376 g_object_unref(decompressor);
377 uri=razor_path_relative_to_uri(base_uri,"repodata/filelists.xml.gz",NULL);
378 stream=plover_razor_input_stream_new(uri,error);
381 g_object_unref(primary);
382 XML_ParserFree(ctx.primary_parser);
383 XML_ParserFree(ctx.filelists_parser);
386 decompressor=g_zlib_decompressor_new(G_ZLIB_COMPRESSOR_FORMAT_GZIP);
387 filelists=g_converter_input_stream_new(G_INPUT_STREAM(stream),
388 G_CONVERTER(decompressor));
389 g_object_unref(stream);
390 g_object_unref(decompressor);
391 ctx.current_parser=ctx.primary_parser;
392 ctx.uris=g_tree_new_full((GCompareDataFunc)strcmp,NULL,g_free,NULL);
396 XML_GetParsingStatus(ctx.current_parser,&status);
397 switch (status.parsing)
400 XML_ResumeParser(ctx.current_parser);
403 case XML_INITIALIZED:
404 buf=XML_GetBuffer(ctx.current_parser,XML_BUFFER_SIZE);
405 if (ctx.current_parser==ctx.primary_parser)
406 len=g_input_stream_read(G_INPUT_STREAM(primary),buf,
407 XML_BUFFER_SIZE,NULL,error);
409 len=g_input_stream_read(G_INPUT_STREAM(filelists),buf,
410 XML_BUFFER_SIZE,NULL,error);
413 XML_ParseBuffer(ctx.current_parser,len,!len);
418 } while (status.parsing!=XML_FINISHED);
419 XML_ParserFree(ctx.primary_parser);
420 XML_ParserFree(ctx.filelists_parser);
421 g_object_unref(primary);
422 g_object_unref(filelists);
423 razor=razor_importer_finish(ctx.importer);
424 #if RAZOR_HEADER_VERSION_MIN<=1
426 * Header version 1 is supported by plover v0.3 and is used on
427 * 32-bit intel machines which allows the setup and update
428 * applications from v0.3 to work. On other machines, we don't
429 * want these old applications to work (since they would do
430 * the wrong thing) and so we use the current header version
431 * which they don't support.
433 if (plover_system_arch_is_x86())
434 razor_set_set_header_version(razor,1);
436 uris=g_ptr_array_new();
437 iter=razor_package_iterator_create(razor);
438 while(razor_package_iterator_next(iter,&pkg,RAZOR_DETAIL_NAME,&name,
439 RAZOR_DETAIL_VERSION,&version,RAZOR_DETAIL_ARCH,&arch,RAZOR_DETAIL_LAST))
441 s=g_strconcat(name,"-",version,".",arch,NULL);
442 g_ptr_array_add(uris,g_tree_lookup(ctx.uris,s));
445 razor_package_iterator_destroy(iter);
446 g_ptr_array_add(uris,NULL);
447 g_tree_unref(ctx.uris);
448 rpm_uris=(gchar **)g_ptr_array_free(uris,FALSE);
449 set=plover_package_set_new_from_razor(razor);
450 razor_set_unref(razor);
451 repository=plover_repository_new_from_package_set(set,
452 (const char **)rpm_uris);
454 g_strfreev(rpm_uris);
458 struct razor_set *plover_razor_set_create_from_yum_uri(const char *base_uri,
461 PloverRepository *repository;
462 PloverPackageSet *set;
463 struct razor_set *razor;
464 g_return_val_if_fail(plover__uri_validate(base_uri),NULL);
465 repository=plover_repository_new_from_yum_uri(base_uri,error);
468 set=plover_repository_get_package_set(repository);
469 razor=plover_package_set_get_razor(set);
470 razor_set_ref(razor);
471 g_object_unref(repository);
475 struct razor_set *plover_razor_set_create_from_yum(const char *base,
480 struct razor_set *set;
481 file=g_file_new_for_path(base);
482 base_uri=g_file_get_uri(file);
483 g_object_unref(file);
484 set=plover_razor_set_create_from_yum_uri(base_uri,error);