src/import-yum.c
author J. Ali Harlow <ali@juiblex.co.uk>
Wed Apr 29 17:00:01 2009 +0100 (2009-04-29)
changeset 361 2523d03a840e
parent 263 23c56c3f0449
child 394 afe520f454bd
permissions -rw-r--r--
Add support for preloading lua modules. This is useful both when
providing lua bindings to applications based on librazor and when
producing static binaries using librazor (where otherwise the lua
POSIX library would need to be included as an additional dynamic
object).
rhughes@241
     1
/*
rhughes@241
     2
 * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
rhughes@241
     3
 * Copyright (C) 2008  Red Hat, Inc
rhughes@241
     4
 *
rhughes@241
     5
 * This program is free software; you can redistribute it and/or modify
rhughes@241
     6
 * it under the terms of the GNU General Public License as published by
rhughes@241
     7
 * the Free Software Foundation; either version 2 of the License, or
rhughes@241
     8
 * (at your option) any later version.
rhughes@241
     9
 *
rhughes@241
    10
 * This program is distributed in the hope that it will be useful,
rhughes@241
    11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
rhughes@241
    12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
rhughes@241
    13
 * GNU General Public License for more details.
rhughes@241
    14
 *
rhughes@241
    15
 * You should have received a copy of the GNU General Public License along
rhughes@241
    16
 * with this program; if not, write to the Free Software Foundation, Inc.,
rhughes@241
    17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
rhughes@241
    18
 */
rhughes@241
    19
rhughes@241
    20
#define _GNU_SOURCE
rhughes@241
    21
rhughes@241
    22
#include <string.h>
rhughes@241
    23
#include <stdio.h>
krh@247
    24
#include <stdint.h>
rhughes@241
    25
#include <sys/stat.h>
rhughes@241
    26
#include <unistd.h>
rhughes@241
    27
#include <fcntl.h>
rhughes@241
    28
#include <errno.h>
rhughes@241
    29
rhughes@241
    30
#include <expat.h>
rhughes@241
    31
#include <zlib.h>
rhughes@241
    32
#include "razor.h"
rhughes@241
    33
rhughes@241
    34
/* Import a yum filelist as a razor package set. */
rhughes@241
    35
rhughes@241
    36
enum {
rhughes@241
    37
	YUM_STATE_BEGIN,
rhughes@241
    38
	YUM_STATE_PACKAGE_NAME,
rhughes@241
    39
	YUM_STATE_PACKAGE_ARCH,
jbowes@258
    40
	YUM_STATE_SUMMARY,
jbowes@258
    41
	YUM_STATE_DESCRIPTION,
jbowes@258
    42
	YUM_STATE_URL,
jbowes@258
    43
	YUM_STATE_LICENSE,
rhughes@241
    44
	YUM_STATE_CHECKSUM,
rhughes@241
    45
	YUM_STATE_REQUIRES,
rhughes@241
    46
	YUM_STATE_PROVIDES,
rhughes@241
    47
	YUM_STATE_OBSOLETES,
rhughes@241
    48
	YUM_STATE_CONFLICTS,
rhughes@241
    49
	YUM_STATE_FILE
rhughes@241
    50
};
rhughes@241
    51
rhughes@241
    52
struct yum_context {
rhughes@241
    53
	XML_Parser primary_parser;
rhughes@241
    54
	XML_Parser filelists_parser;
rhughes@241
    55
	XML_Parser current_parser;
rhughes@241
    56
rhughes@241
    57
	struct razor_importer *importer;
rhughes@241
    58
	struct import_property_context *current_property_context;
jbowes@258
    59
	char name[256], arch[64], summary[512], description[4096];
jbowes@258
    60
	char url[256], license[64], buffer[512], *p;
rhughes@241
    61
	char pkgid[128];
krh@247
    62
	uint32_t property_type;
rhughes@241
    63
	int state;
jbowes@263
    64
jbowes@263
    65
	int total, current;
rhughes@241
    66
};
rhughes@241
    67
krh@247
    68
static uint32_t
krh@247
    69
yum_to_razor_relation (const char *flags)
rhughes@241
    70
{
rhughes@241
    71
	if (flags[0] == 'L') {
rhughes@241
    72
		if (flags[1] == 'T')
krh@247
    73
			return RAZOR_PROPERTY_LESS;
rhughes@241
    74
		else
krh@247
    75
			return RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL;
rhughes@241
    76
	} else if (flags[0] == 'G') {
rhughes@241
    77
		if (flags[1] == 'T')
krh@247
    78
			return RAZOR_PROPERTY_GREATER;
rhughes@241
    79
		else
krh@247
    80
			return RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL;
rhughes@241
    81
	} else
krh@247
    82
		return RAZOR_PROPERTY_EQUAL;
rhughes@241
    83
}
rhughes@241
    84
rhughes@241
    85
static void
rhughes@241
    86
yum_primary_start_element(void *data, const char *name, const char **atts)
rhughes@241
    87
{
rhughes@241
    88
	struct yum_context *ctx = data;
krh@247
    89
	const char *n, *epoch, *version, *release;
rhughes@241
    90
	char buffer[128];
krh@247
    91
	uint32_t pre, relation, flags;
rhughes@241
    92
	int i;
rhughes@241
    93
jbowes@263
    94
	if (strcmp(name, "metadata") == 0) {
jbowes@263
    95
		for (i = 0; atts[i]; i += 2) {
jbowes@263
    96
			if (strcmp(atts[i], "packages") == 0)
jbowes@263
    97
				ctx->total = atoi(atts[i + 1]);
jbowes@263
    98
		}
jbowes@263
    99
	} else if (strcmp(name, "name") == 0) {
rhughes@241
   100
		ctx->state = YUM_STATE_PACKAGE_NAME;
rhughes@241
   101
		ctx->p = ctx->name;
rhughes@241
   102
	} else if (strcmp(name, "arch") == 0) {
rhughes@241
   103
		ctx->state = YUM_STATE_PACKAGE_ARCH;
rhughes@241
   104
		ctx->p = ctx->arch;
rhughes@241
   105
	} else if (strcmp(name, "version") == 0) {
rhughes@241
   106
		epoch = NULL;
rhughes@241
   107
		version = NULL;
rhughes@241
   108
		release = NULL;
rhughes@241
   109
		for (i = 0; atts[i]; i += 2) {
rhughes@241
   110
			if (strcmp(atts[i], "epoch") == 0)
rhughes@241
   111
				epoch = atts[i + 1];
rhughes@241
   112
			else if (strcmp(atts[i], "ver") == 0)
rhughes@241
   113
				version = atts[i + 1];
rhughes@241
   114
			else if (strcmp(atts[i], "rel") == 0)
rhughes@241
   115
				release = atts[i + 1];
rhughes@241
   116
		}
rhughes@241
   117
		if (version == NULL || release == NULL) {
rhughes@241
   118
			fprintf(stderr, "invalid version tag, "
rhughes@241
   119
				"missing version or  release attribute\n");
rhughes@241
   120
			return;
rhughes@241
   121
		}
rhughes@241
   122
rhughes@241
   123
		razor_build_evr(buffer, sizeof buffer, epoch, version, release);
rhughes@241
   124
		razor_importer_begin_package(ctx->importer,
rhughes@241
   125
					     ctx->name, buffer, ctx->arch);
jbowes@258
   126
	} else if (strcmp(name, "summary") == 0) {
jbowes@258
   127
		ctx->p = ctx->summary;
jbowes@258
   128
		ctx->state = YUM_STATE_SUMMARY;
jbowes@258
   129
	} else if (strcmp(name, "description") == 0) {
jbowes@258
   130
		ctx->p = ctx->description;
jbowes@258
   131
		ctx->state = YUM_STATE_DESCRIPTION;
jbowes@258
   132
	} else if (strcmp(name, "url") == 0) {
jbowes@258
   133
		ctx->p = ctx->url;
jbowes@258
   134
		ctx->state = YUM_STATE_URL;
rhughes@241
   135
	} else if (strcmp(name, "checksum") == 0) {
rhughes@241
   136
		ctx->p = ctx->pkgid;
rhughes@241
   137
		ctx->state = YUM_STATE_CHECKSUM;
jbowes@258
   138
	} else if (strcmp(name, "rpm:license") == 0) {
jbowes@258
   139
		ctx->p = ctx->license;
jbowes@258
   140
		ctx->state = YUM_STATE_LICENSE;
rhughes@241
   141
	} else if (strcmp(name, "rpm:requires") == 0) {
rhughes@241
   142
		ctx->state = YUM_STATE_REQUIRES;
krh@247
   143
		ctx->property_type = RAZOR_PROPERTY_REQUIRES;
rhughes@241
   144
	} else if (strcmp(name, "rpm:provides") == 0) {
rhughes@241
   145
		ctx->state = YUM_STATE_PROVIDES;
krh@247
   146
		ctx->property_type = RAZOR_PROPERTY_PROVIDES;
rhughes@241
   147
	} else if (strcmp(name, "rpm:obsoletes") == 0) {
rhughes@241
   148
		ctx->state = YUM_STATE_OBSOLETES;
krh@247
   149
		ctx->property_type = RAZOR_PROPERTY_OBSOLETES;
rhughes@241
   150
	} else if (strcmp(name, "rpm:conflicts") == 0) {
rhughes@241
   151
		ctx->state = YUM_STATE_CONFLICTS;
krh@247
   152
		ctx->property_type = RAZOR_PROPERTY_CONFLICTS;
rhughes@241
   153
	} else if (strcmp(name, "rpm:entry") == 0 &&
rhughes@241
   154
		   ctx->state != YUM_STATE_BEGIN) {
rhughes@241
   155
		n = NULL;
rhughes@241
   156
		epoch = NULL;
rhughes@241
   157
		version = NULL;
rhughes@241
   158
		release = NULL;
krh@247
   159
		relation = RAZOR_PROPERTY_EQUAL;
krh@247
   160
		pre = 0;
rhughes@241
   161
		for (i = 0; atts[i]; i += 2) {
rhughes@241
   162
			if (strcmp(atts[i], "name") == 0)
rhughes@241
   163
				n = atts[i + 1];
rhughes@241
   164
			else if (strcmp(atts[i], "epoch") == 0)
rhughes@241
   165
				epoch = atts[i + 1];
rhughes@241
   166
			else if (strcmp(atts[i], "ver") == 0)
rhughes@241
   167
				version = atts[i + 1];
rhughes@241
   168
			else if (strcmp(atts[i], "rel") == 0)
rhughes@241
   169
				release = atts[i + 1];
rhughes@241
   170
			else if (strcmp(atts[i], "flags") == 0)
krh@247
   171
				relation = yum_to_razor_relation(atts[i + 1]);
krh@247
   172
			else if (strcmp(atts[i], "pre") == 0)
krh@247
   173
				pre = 
krh@247
   174
					RAZOR_PROPERTY_PRE |
krh@247
   175
					RAZOR_PROPERTY_POST |
krh@247
   176
					RAZOR_PROPERTY_PREUN |
krh@247
   177
					RAZOR_PROPERTY_POSTUN;
rhughes@241
   178
		}
rhughes@241
   179
rhughes@241
   180
		if (n == NULL) {
rhughes@241
   181
			fprintf(stderr, "invalid rpm:entry, "
rhughes@241
   182
				"missing name or version attributes\n");
rhughes@241
   183
			return;
rhughes@241
   184
		}
rhughes@241
   185
rhughes@241
   186
		razor_build_evr(buffer, sizeof buffer, epoch, version, release);
krh@247
   187
		flags = ctx->property_type | relation | pre;
krh@247
   188
		razor_importer_add_property(ctx->importer, n, flags, buffer);
rhughes@241
   189
	}
rhughes@241
   190
}
rhughes@241
   191
rhughes@241
   192
static void
rhughes@241
   193
yum_primary_end_element (void *data, const char *name)
rhughes@241
   194
{
rhughes@241
   195
	struct yum_context *ctx = data;
rhughes@241
   196
rhughes@241
   197
	switch (ctx->state) {
rhughes@241
   198
	case YUM_STATE_PACKAGE_NAME:
rhughes@241
   199
	case YUM_STATE_PACKAGE_ARCH:
jbowes@258
   200
	case YUM_STATE_SUMMARY:
jbowes@258
   201
	case YUM_STATE_DESCRIPTION:
jbowes@258
   202
	case YUM_STATE_URL:
jbowes@258
   203
	case YUM_STATE_LICENSE:
rhughes@241
   204
	case YUM_STATE_CHECKSUM:
rhughes@241
   205
	case YUM_STATE_FILE:
rhughes@241
   206
		ctx->state = YUM_STATE_BEGIN;
rhughes@241
   207
		break;
rhughes@241
   208
	}
rhughes@241
   209
rhughes@241
   210
	if (strcmp(name, "package") == 0) {
jbowes@258
   211
		razor_importer_add_details(ctx->importer, ctx->summary,
jbowes@258
   212
					   ctx->description, ctx->url,
jbowes@258
   213
					   ctx->license);
jbowes@258
   214
rhughes@241
   215
		XML_StopParser(ctx->current_parser, XML_TRUE);
rhughes@241
   216
		ctx->current_parser = ctx->filelists_parser;
jbowes@263
   217
jbowes@263
   218
		printf("\rimporting %d/%d", ++ctx->current, ctx->total);
jbowes@263
   219
		fflush(stdout);
rhughes@241
   220
	}
rhughes@241
   221
}
rhughes@241
   222
rhughes@241
   223
static void
rhughes@241
   224
yum_character_data (void *data, const XML_Char *s, int len)
rhughes@241
   225
{
rhughes@241
   226
	struct yum_context *ctx = data;
rhughes@241
   227
rhughes@241
   228
	switch (ctx->state) {
rhughes@241
   229
	case YUM_STATE_PACKAGE_NAME:
rhughes@241
   230
	case YUM_STATE_PACKAGE_ARCH:
jbowes@258
   231
	case YUM_STATE_SUMMARY:
jbowes@258
   232
	case YUM_STATE_DESCRIPTION:
jbowes@258
   233
	case YUM_STATE_URL:
jbowes@258
   234
	case YUM_STATE_LICENSE:
rhughes@241
   235
	case YUM_STATE_CHECKSUM:
rhughes@241
   236
	case YUM_STATE_FILE:
rhughes@241
   237
		memcpy(ctx->p, s, len);
rhughes@241
   238
		ctx->p += len;
rhughes@241
   239
		*ctx->p = '\0';
rhughes@241
   240
		break;
rhughes@241
   241
	}
rhughes@241
   242
}
rhughes@241
   243
rhughes@241
   244
static void
rhughes@241
   245
yum_filelists_start_element(void *data, const char *name, const char **atts)
rhughes@241
   246
{
rhughes@241
   247
	struct yum_context *ctx = data;
rhughes@241
   248
	const char *pkg, *pkgid;
rhughes@241
   249
	int i;
rhughes@241
   250
rhughes@241
   251
	if (strcmp(name, "package") == 0) {
rhughes@241
   252
		pkg = NULL;
rhughes@241
   253
		pkgid = NULL;
rhughes@241
   254
		for (i = 0; atts[i]; i += 2) {
rhughes@241
   255
			if (strcmp(atts[i], "name") == 0)
rhughes@241
   256
				pkg = atts[i + 1];
rhughes@241
   257
			else if (strcmp(atts[i], "pkgid") == 0)
rhughes@241
   258
				pkgid = atts[i + 1];
rhughes@241
   259
		}
rhughes@241
   260
		if (strcmp(pkgid, ctx->pkgid) != 0)
rhughes@241
   261
			fprintf(stderr, "primary.xml and filelists.xml "
rhughes@241
   262
				"mismatch for %s: %s vs %s",
rhughes@241
   263
				pkg, pkgid, ctx->pkgid);
rhughes@241
   264
	} else if (strcmp(name, "file") == 0) {
rhughes@241
   265
		ctx->state = YUM_STATE_FILE;
rhughes@241
   266
		ctx->p = ctx->buffer;
rhughes@241
   267
	}
rhughes@241
   268
}
rhughes@241
   269
rhughes@241
   270
rhughes@241
   271
static void
rhughes@241
   272
yum_filelists_end_element (void *data, const char *name)
rhughes@241
   273
{
rhughes@241
   274
	struct yum_context *ctx = data;
rhughes@241
   275
rhughes@241
   276
	ctx->state = YUM_STATE_BEGIN;
rhughes@241
   277
	if (strcmp(name, "package") == 0) {
rhughes@241
   278
		XML_StopParser(ctx->current_parser, XML_TRUE);
rhughes@241
   279
		ctx->current_parser = ctx->primary_parser;
rhughes@241
   280
		razor_importer_finish_package(ctx->importer);
rhughes@241
   281
	} else if (strcmp(name, "file") == 0)
rhughes@241
   282
		razor_importer_add_file(ctx->importer, ctx->buffer);
rhughes@241
   283
rhughes@241
   284
}
rhughes@241
   285
rhughes@241
   286
#define XML_BUFFER_SIZE 4096
rhughes@241
   287
rhughes@241
   288
struct razor_set *
rhughes@241
   289
razor_set_create_from_yum(void)
rhughes@241
   290
{
rhughes@241
   291
	struct yum_context ctx;
rhughes@241
   292
	void *buf;
rhughes@241
   293
	int len, ret;
rhughes@241
   294
	gzFile primary, filelists;
rhughes@241
   295
	XML_ParsingStatus status;
rhughes@241
   296
krh@249
   297
	ctx.importer = razor_importer_create();
rhughes@241
   298
	ctx.state = YUM_STATE_BEGIN;
rhughes@241
   299
rhughes@241
   300
	ctx.primary_parser = XML_ParserCreate(NULL);
rhughes@241
   301
	XML_SetUserData(ctx.primary_parser, &ctx);
rhughes@241
   302
	XML_SetElementHandler(ctx.primary_parser,
rhughes@241
   303
			      yum_primary_start_element,
rhughes@241
   304
			      yum_primary_end_element);
rhughes@241
   305
	XML_SetCharacterDataHandler(ctx.primary_parser,
rhughes@241
   306
				    yum_character_data);
rhughes@241
   307
rhughes@241
   308
	ctx.filelists_parser = XML_ParserCreate(NULL);
rhughes@241
   309
	XML_SetUserData(ctx.filelists_parser, &ctx);
rhughes@241
   310
	XML_SetElementHandler(ctx.filelists_parser,
rhughes@241
   311
			      yum_filelists_start_element,
rhughes@241
   312
			      yum_filelists_end_element);
rhughes@241
   313
	XML_SetCharacterDataHandler(ctx.filelists_parser,
rhughes@241
   314
				    yum_character_data);
rhughes@241
   315
rhughes@241
   316
	primary = gzopen("primary.xml.gz", "rb");
rhughes@241
   317
	if (primary == NULL)
rhughes@241
   318
		return NULL;
rhughes@241
   319
	filelists = gzopen("filelists.xml.gz", "rb");
rhughes@241
   320
	if (filelists == NULL)
rhughes@241
   321
		return NULL;
rhughes@241
   322
rhughes@241
   323
	ctx.current_parser = ctx.primary_parser;
rhughes@241
   324
jbowes@263
   325
	ctx.current = 0;
jbowes@263
   326
rhughes@241
   327
	do {
rhughes@241
   328
		XML_GetParsingStatus(ctx.current_parser, &status);
rhughes@241
   329
		switch (status.parsing) {
rhughes@241
   330
		case XML_SUSPENDED:
rhughes@241
   331
			ret = XML_ResumeParser(ctx.current_parser);
rhughes@241
   332
			break;
rhughes@241
   333
		case XML_PARSING:
rhughes@241
   334
		case XML_INITIALIZED:
rhughes@241
   335
			buf = XML_GetBuffer(ctx.current_parser,
rhughes@241
   336
					    XML_BUFFER_SIZE);
rhughes@241
   337
			if (ctx.current_parser == ctx.primary_parser)
rhughes@241
   338
				len = gzread(primary, buf, XML_BUFFER_SIZE);
rhughes@241
   339
			else
rhughes@241
   340
				len = gzread(filelists, buf, XML_BUFFER_SIZE);
rhughes@241
   341
			if (len < 0) {
rhughes@241
   342
				fprintf(stderr,
rhughes@241
   343
					"couldn't read input: %s\n",
rhughes@241
   344
					strerror(errno));
rhughes@241
   345
				return NULL;
rhughes@241
   346
			}
rhughes@241
   347
rhughes@241
   348
			XML_ParseBuffer(ctx.current_parser, len, len == 0);
rhughes@241
   349
			break;
rhughes@241
   350
		case XML_FINISHED:
rhughes@241
   351
			break;
rhughes@241
   352
		}
rhughes@241
   353
	} while (status.parsing != XML_FINISHED);
rhughes@241
   354
rhughes@241
   355
rhughes@241
   356
	XML_ParserFree(ctx.primary_parser);
rhughes@241
   357
	XML_ParserFree(ctx.filelists_parser);
rhughes@241
   358
rhughes@241
   359
	gzclose(primary);
rhughes@241
   360
	gzclose(filelists);
rhughes@241
   361
jbowes@263
   362
	printf ("\nsaving\n");
rhughes@241
   363
	return razor_importer_finish(ctx.importer);
rhughes@241
   364
}