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