yum.c
author Dan Winship <danw@gnome.org>
Fri Feb 29 11:53:15 2008 -0500 (2008-02-29)
changeset 137 4722cd3437cb
child 143 59a9513fac54
permissions -rw-r--r--
Redo updates and removes in terms of a single razor_transaction abstraction

Also does versioned depsolving at least partially.
Update main.c and test-driver.c for that, and fix some unrelated test-driver
bugs.

Now gets up to testUpdateSinglePackageObsoletesOldRequirement, although
it really should not be passing the multilib tests; apparently they aren't
clever enough in their testing of the depsolving algorithm and are allowing
it to come up with the right answer for the wrong reason.
danw@109
     1
#define _GNU_SOURCE
danw@109
     2
danw@109
     3
#include <string.h>
danw@109
     4
#include <stdio.h>
danw@109
     5
#include <sys/stat.h>
danw@109
     6
#include <sys/mman.h>
danw@109
     7
#include <unistd.h>
danw@109
     8
#include <fcntl.h>
danw@109
     9
#include <errno.h>
danw@109
    10
danw@109
    11
#include <expat.h>
danw@109
    12
#include <zlib.h>
danw@109
    13
#include "razor.h"
danw@109
    14
danw@109
    15
/* Import a yum filelist as a razor package set. */
danw@109
    16
danw@109
    17
enum {
danw@109
    18
	YUM_STATE_BEGIN,
danw@109
    19
	YUM_STATE_PACKAGE_NAME,
danw@109
    20
	YUM_STATE_CHECKSUM,
danw@109
    21
	YUM_STATE_REQUIRES,
danw@109
    22
	YUM_STATE_PROVIDES,
danw@109
    23
	YUM_STATE_OBSOLETES,
danw@109
    24
	YUM_STATE_CONFLICTS,
danw@109
    25
	YUM_STATE_FILE
danw@109
    26
};
danw@109
    27
danw@109
    28
struct yum_context {
danw@109
    29
	XML_Parser primary_parser;
danw@109
    30
	XML_Parser filelists_parser;
danw@109
    31
	XML_Parser current_parser;
danw@109
    32
danw@109
    33
	struct razor_importer *importer;
danw@109
    34
	struct import_property_context *current_property_context;
danw@109
    35
	char name[256], buffer[512], *p;
danw@109
    36
	char pkgid[128];
danw@109
    37
	int state;
danw@109
    38
};
danw@109
    39
danw@109
    40
static enum razor_version_relation
danw@109
    41
yum_to_razor_flags (const char *flags)
danw@109
    42
{
danw@109
    43
	/* FIXME? */
danw@109
    44
	if (!flags)
danw@109
    45
		return RAZOR_VERSION_EQUAL;
danw@109
    46
danw@109
    47
	if (flags[0] == 'L') {
danw@109
    48
		if (flags[1] == 'T')
danw@109
    49
			return RAZOR_VERSION_LESS;
danw@109
    50
		else
danw@109
    51
			return RAZOR_VERSION_LESS_OR_EQUAL;
danw@109
    52
	} else if (flags[0] == 'G') {
danw@109
    53
		if (flags[1] == 'T')
danw@109
    54
			return RAZOR_VERSION_GREATER;
danw@109
    55
		else
danw@109
    56
			return RAZOR_VERSION_GREATER_OR_EQUAL;
danw@109
    57
	} else
danw@109
    58
		return RAZOR_VERSION_EQUAL;
danw@109
    59
}
danw@109
    60
danw@109
    61
static void
danw@109
    62
yum_primary_start_element(void *data, const char *name, const char **atts)
danw@109
    63
{
danw@109
    64
	struct yum_context *ctx = data;
danw@109
    65
	const char *n, *version, *release, *flags;
danw@109
    66
	char buffer[128];
danw@109
    67
	int i;
danw@109
    68
danw@109
    69
	if (strcmp(name, "name") == 0) {
danw@109
    70
		ctx->state = YUM_STATE_PACKAGE_NAME;
danw@109
    71
		ctx->p = ctx->name;
danw@109
    72
	} else if (strcmp(name, "version") == 0) {
danw@109
    73
		version = NULL;
danw@109
    74
		release = NULL;
danw@109
    75
		for (i = 0; atts[i]; i += 2) {
danw@109
    76
			if (strcmp(atts[i], "ver") == 0)
danw@109
    77
				version = atts[i + 1];
danw@109
    78
			else if (strcmp(atts[i], "rel") == 0)
danw@109
    79
				release = atts[i + 1];
danw@109
    80
		}
danw@109
    81
		if (version == NULL || release == NULL) {
danw@109
    82
			fprintf(stderr, "invalid version tag, "
danw@109
    83
				"missing version or  release attribute\n");
danw@109
    84
			return;
danw@109
    85
		}
danw@109
    86
danw@109
    87
		snprintf(buffer, sizeof buffer, "%s-%s", version, release);
danw@109
    88
		razor_importer_begin_package(ctx->importer, ctx->name, buffer);
danw@109
    89
	} else if (strcmp(name, "checksum") == 0) {
danw@109
    90
		ctx->p = ctx->pkgid;
danw@109
    91
		ctx->state = YUM_STATE_CHECKSUM;
danw@109
    92
	} else if (strcmp(name, "rpm:requires") == 0) {
danw@109
    93
		ctx->state = YUM_STATE_REQUIRES;
danw@109
    94
	} else if (strcmp(name, "rpm:provides") == 0) {
danw@109
    95
		ctx->state = YUM_STATE_PROVIDES;
danw@109
    96
	} else if (strcmp(name, "rpm:obsoletes") == 0) {
danw@109
    97
		ctx->state = YUM_STATE_OBSOLETES;
danw@109
    98
	} else if (strcmp(name, "rpm:conflicts") == 0) {
danw@109
    99
		ctx->state = YUM_STATE_CONFLICTS;
danw@109
   100
	} else if (strcmp(name, "rpm:entry") == 0 &&
danw@109
   101
		   ctx->state != YUM_STATE_BEGIN) {
danw@109
   102
		n = NULL;
danw@109
   103
		version = NULL;
danw@109
   104
		release = NULL;
danw@109
   105
		flags = NULL;
danw@109
   106
		for (i = 0; atts[i]; i += 2) {
danw@109
   107
			if (strcmp(atts[i], "name") == 0)
danw@109
   108
				n = atts[i + 1];
danw@109
   109
			else if (strcmp(atts[i], "ver") == 0)
danw@109
   110
				version = atts[i + 1];
danw@109
   111
			else if (strcmp(atts[i], "rel") == 0)
danw@109
   112
				release = atts[i + 1];
danw@109
   113
			else if (strcmp(atts[i], "flags") == 0)
danw@109
   114
				flags = atts[i + 1];
danw@109
   115
		}
danw@109
   116
danw@109
   117
		if (n == NULL) {
danw@109
   118
			fprintf(stderr, "invalid rpm:entry, "
danw@109
   119
				"missing name or version attributes\n");
danw@109
   120
			return;
danw@109
   121
		}
danw@109
   122
danw@109
   123
		if (version && release)
danw@109
   124
			snprintf(buffer, sizeof buffer,
danw@109
   125
				 "%s-%s", version, release);
danw@109
   126
		else if (version)
danw@109
   127
			strcpy(buffer, version);
danw@109
   128
		else
danw@109
   129
			buffer[0] = '\0';
danw@109
   130
			
danw@109
   131
		switch (ctx->state) {
danw@109
   132
		case YUM_STATE_REQUIRES:
danw@109
   133
			razor_importer_add_property(ctx->importer, n,
danw@109
   134
						    yum_to_razor_flags (flags),
danw@109
   135
						    buffer,
danw@109
   136
						    RAZOR_PROPERTY_REQUIRES);
danw@109
   137
			break;
danw@109
   138
		case YUM_STATE_PROVIDES:
danw@109
   139
			razor_importer_add_property(ctx->importer, n,
danw@109
   140
						    yum_to_razor_flags (flags),
danw@109
   141
						    buffer,
danw@109
   142
						    RAZOR_PROPERTY_PROVIDES);
danw@109
   143
			break;
danw@109
   144
		case YUM_STATE_OBSOLETES:
danw@109
   145
			razor_importer_add_property(ctx->importer, n,
danw@109
   146
						    yum_to_razor_flags (flags),
danw@109
   147
						    buffer,
danw@109
   148
						    RAZOR_PROPERTY_OBSOLETES);
danw@109
   149
			break;
danw@109
   150
		case YUM_STATE_CONFLICTS:
danw@109
   151
			razor_importer_add_property(ctx->importer, n,
danw@109
   152
						    yum_to_razor_flags (flags),
danw@109
   153
						    buffer,
danw@109
   154
						    RAZOR_PROPERTY_CONFLICTS);
danw@109
   155
			break;
danw@109
   156
		}
danw@109
   157
	}
danw@109
   158
}
danw@109
   159
danw@109
   160
static void
danw@109
   161
yum_primary_end_element (void *data, const char *name)
danw@109
   162
{
danw@109
   163
	struct yum_context *ctx = data;
danw@109
   164
danw@109
   165
	switch (ctx->state) {
danw@109
   166
	case YUM_STATE_PACKAGE_NAME:
danw@109
   167
	case YUM_STATE_CHECKSUM:
danw@109
   168
	case YUM_STATE_FILE:
danw@109
   169
		ctx->state = YUM_STATE_BEGIN;
danw@109
   170
		break;
danw@109
   171
	}
danw@109
   172
danw@109
   173
	if (strcmp(name, "package") == 0) {
danw@109
   174
		XML_StopParser(ctx->current_parser, XML_TRUE);
danw@109
   175
		ctx->current_parser = ctx->filelists_parser;
danw@109
   176
	}
danw@109
   177
}
danw@109
   178
danw@109
   179
static void
danw@109
   180
yum_character_data (void *data, const XML_Char *s, int len)
danw@109
   181
{
danw@109
   182
	struct yum_context *ctx = data;
danw@109
   183
danw@109
   184
	switch (ctx->state) {
danw@109
   185
	case YUM_STATE_PACKAGE_NAME:
danw@109
   186
	case YUM_STATE_CHECKSUM:
danw@109
   187
	case YUM_STATE_FILE:
danw@109
   188
		memcpy(ctx->p, s, len);
danw@109
   189
		ctx->p += len;
danw@109
   190
		*ctx->p = '\0';
danw@109
   191
		break;
danw@109
   192
	}
danw@109
   193
}
danw@109
   194
danw@109
   195
static void
danw@109
   196
yum_filelists_start_element(void *data, const char *name, const char **atts)
danw@109
   197
{
danw@109
   198
	struct yum_context *ctx = data;
danw@109
   199
	const char *pkg, *pkgid;
danw@109
   200
	int i;
danw@109
   201
danw@109
   202
	if (strcmp(name, "package") == 0) {
danw@109
   203
		pkg = NULL;
danw@109
   204
		pkgid = NULL;
danw@109
   205
		for (i = 0; atts[i]; i += 2) {
danw@109
   206
			if (strcmp(atts[i], "name") == 0)
danw@109
   207
				pkg = atts[i + 1];
danw@109
   208
			else if (strcmp(atts[i], "pkgid") == 0)
danw@109
   209
				pkgid = atts[i + 1];
danw@109
   210
		}
danw@109
   211
		if (strcmp(pkgid, ctx->pkgid) != 0)
danw@109
   212
			fprintf(stderr, "primary.xml and filelists.xml "
danw@109
   213
				"mismatch for %s: %s vs %s",
danw@109
   214
				pkg, pkgid, ctx->pkgid);
danw@109
   215
	} else if (strcmp(name, "file") == 0) {
danw@109
   216
		ctx->state = YUM_STATE_FILE;
danw@109
   217
		ctx->p = ctx->buffer;
danw@109
   218
	}
danw@109
   219
}
danw@109
   220
danw@109
   221
danw@109
   222
static void
danw@109
   223
yum_filelists_end_element (void *data, const char *name)
danw@109
   224
{
danw@109
   225
	struct yum_context *ctx = data;
danw@109
   226
danw@109
   227
	ctx->state = YUM_STATE_BEGIN;
danw@109
   228
	if (strcmp(name, "package") == 0) {
danw@109
   229
		XML_StopParser(ctx->current_parser, XML_TRUE);
danw@109
   230
		ctx->current_parser = ctx->primary_parser;
danw@109
   231
		razor_importer_finish_package(ctx->importer);
danw@109
   232
	} else if (strcmp(name, "file") == 0)
danw@109
   233
		razor_importer_add_file(ctx->importer, ctx->buffer);
danw@109
   234
danw@109
   235
}
danw@109
   236
danw@109
   237
#define XML_BUFFER_SIZE 4096
danw@109
   238
danw@109
   239
struct razor_set *
danw@109
   240
razor_set_create_from_yum(void)
danw@109
   241
{
danw@109
   242
	struct yum_context ctx;
danw@109
   243
	void *buf;
danw@109
   244
	int len, ret;
danw@109
   245
	gzFile primary, filelists;
danw@109
   246
	XML_ParsingStatus status;
danw@109
   247
danw@109
   248
	ctx.importer = razor_importer_new();	
danw@109
   249
	ctx.state = YUM_STATE_BEGIN;
danw@109
   250
danw@109
   251
	ctx.primary_parser = XML_ParserCreate(NULL);
danw@109
   252
	XML_SetUserData(ctx.primary_parser, &ctx);
danw@109
   253
	XML_SetElementHandler(ctx.primary_parser,
danw@109
   254
			      yum_primary_start_element,
danw@109
   255
			      yum_primary_end_element);
danw@109
   256
	XML_SetCharacterDataHandler(ctx.primary_parser,
danw@109
   257
				    yum_character_data);
danw@109
   258
danw@109
   259
	ctx.filelists_parser = XML_ParserCreate(NULL);
danw@109
   260
	XML_SetUserData(ctx.filelists_parser, &ctx);
danw@109
   261
	XML_SetElementHandler(ctx.filelists_parser,
danw@109
   262
			      yum_filelists_start_element,
danw@109
   263
			      yum_filelists_end_element);
danw@109
   264
	XML_SetCharacterDataHandler(ctx.filelists_parser,
danw@109
   265
				    yum_character_data);
danw@109
   266
danw@109
   267
	primary = gzopen("primary.xml.gz", "rb");
danw@109
   268
	if (primary == NULL)
danw@109
   269
		return NULL;
danw@109
   270
	filelists = gzopen("filelists.xml.gz", "rb");
danw@109
   271
	if (filelists == NULL)
danw@109
   272
		return NULL;
danw@109
   273
danw@109
   274
	ctx.current_parser = ctx.primary_parser;
danw@109
   275
danw@109
   276
	do {
danw@109
   277
		XML_GetParsingStatus(ctx.current_parser, &status);
danw@109
   278
		switch (status.parsing) {
danw@109
   279
		case XML_SUSPENDED:
danw@109
   280
			ret = XML_ResumeParser(ctx.current_parser);
danw@109
   281
			break;
danw@109
   282
		case XML_PARSING:
danw@109
   283
		case XML_INITIALIZED:
danw@109
   284
			buf = XML_GetBuffer(ctx.current_parser,
danw@109
   285
					    XML_BUFFER_SIZE);
danw@109
   286
			if (ctx.current_parser == ctx.primary_parser)
danw@109
   287
				len = gzread(primary, buf, XML_BUFFER_SIZE);
danw@109
   288
			else
danw@109
   289
				len = gzread(filelists, buf, XML_BUFFER_SIZE);
danw@109
   290
			if (len < 0) {
danw@109
   291
				fprintf(stderr,
danw@109
   292
					"couldn't read input: %s\n",
danw@109
   293
					strerror(errno));
danw@109
   294
				return NULL;
danw@109
   295
			}
danw@109
   296
danw@109
   297
			XML_ParseBuffer(ctx.current_parser, len, len == 0);
danw@109
   298
			break;
danw@109
   299
		case XML_FINISHED:
danw@109
   300
			break;
danw@109
   301
		}
danw@109
   302
	} while (status.parsing != XML_FINISHED);
danw@109
   303
danw@109
   304
danw@109
   305
	XML_ParserFree(ctx.primary_parser);
danw@109
   306
	XML_ParserFree(ctx.filelists_parser);
danw@109
   307
danw@109
   308
	gzclose(primary);
danw@109
   309
	gzclose(filelists);
danw@109
   310
danw@109
   311
	return razor_importer_finish(ctx.importer);
danw@109
   312
}