import.c
author Kristian H?gsberg <krh@redhat.com>
Sat Dec 29 15:36:13 2007 -0500 (2007-12-29)
changeset 87 c1e04d4e3bc9
parent 70 e94d16f789e5
child 90 7bd64a40cb03
permissions -rw-r--r--
Drop table based section lookup and look up sections on demand.
krh@27
     1
#define _GNU_SOURCE
krh@27
     2
krh@27
     3
#include <string.h>
krh@27
     4
#include <stdio.h>
krh@27
     5
#include <sys/stat.h>
krh@27
     6
#include <sys/mman.h>
krh@27
     7
#include <unistd.h>
krh@27
     8
#include <fcntl.h>
krh@27
     9
#include <errno.h>
krh@27
    10
krh@27
    11
#include <expat.h>
krh@70
    12
#include <zlib.h>
krh@28
    13
#include <rpm/rpmlib.h>
krh@28
    14
#include <rpm/rpmdb.h>
krh@27
    15
#include "sha1.h"
krh@27
    16
#include "razor.h"
krh@27
    17
krh@27
    18
/* Import a yum filelist as a razor package set. */
krh@27
    19
krh@27
    20
enum {
krh@27
    21
	YUM_STATE_BEGIN,
krh@30
    22
	YUM_STATE_PACKAGE_NAME,
krh@70
    23
	YUM_STATE_CHECKSUM,
krh@30
    24
	YUM_STATE_REQUIRES,
krh@46
    25
	YUM_STATE_PROVIDES,
krh@67
    26
	YUM_STATE_OBSOLETES,
krh@67
    27
	YUM_STATE_CONFLICTS,
krh@46
    28
	YUM_STATE_FILE
krh@27
    29
};
krh@27
    30
krh@27
    31
struct yum_context {
krh@70
    32
	XML_Parser primary_parser;
krh@70
    33
	XML_Parser filelists_parser;
krh@70
    34
	XML_Parser current_parser;
krh@70
    35
krh@30
    36
	struct razor_importer *importer;
krh@27
    37
	struct import_property_context *current_property_context;
krh@48
    38
	char name[256], buffer[512], *p;
krh@70
    39
	char pkgid[128];
krh@27
    40
	int state;
krh@27
    41
};
krh@27
    42
krh@27
    43
static void
krh@70
    44
yum_primary_start_element(void *data, const char *name, const char **atts)
krh@27
    45
{
krh@27
    46
	struct yum_context *ctx = data;
krh@62
    47
	const char *n, *version, *release;
krh@62
    48
	char buffer[128];
krh@27
    49
	int i;
krh@27
    50
krh@27
    51
	if (strcmp(name, "name") == 0) {
krh@27
    52
		ctx->state = YUM_STATE_PACKAGE_NAME;
krh@48
    53
		ctx->p = ctx->name;
krh@27
    54
	} else if (strcmp(name, "version") == 0) {
krh@27
    55
		version = NULL;
krh@62
    56
		release = NULL;
krh@27
    57
		for (i = 0; atts[i]; i += 2) {
krh@27
    58
			if (strcmp(atts[i], "ver") == 0)
krh@27
    59
				version = atts[i + 1];
krh@62
    60
			else if (strcmp(atts[i], "rel") == 0)
krh@62
    61
				release = atts[i + 1];
krh@27
    62
		}
krh@62
    63
		if (version == NULL || release == NULL) {
krh@62
    64
			fprintf(stderr, "invalid version tag, "
krh@62
    65
				"missing version or  release attribute\n");
krh@62
    66
			return;
krh@62
    67
		}
krh@62
    68
krh@62
    69
		snprintf(buffer, sizeof buffer, "%s-%s", version, release);
krh@62
    70
		razor_importer_begin_package(ctx->importer, ctx->name, buffer);
krh@70
    71
	} else if (strcmp(name, "checksum") == 0) {
krh@70
    72
		ctx->p = ctx->pkgid;
krh@70
    73
		ctx->state = YUM_STATE_CHECKSUM;
krh@27
    74
	} else if (strcmp(name, "rpm:requires") == 0) {
krh@30
    75
		ctx->state = YUM_STATE_REQUIRES;
krh@27
    76
	} else if (strcmp(name, "rpm:provides") == 0) {
krh@30
    77
		ctx->state = YUM_STATE_PROVIDES;
krh@67
    78
	} else if (strcmp(name, "rpm:obsoletes") == 0) {
krh@67
    79
		ctx->state = YUM_STATE_OBSOLETES;
krh@67
    80
	} else if (strcmp(name, "rpm:conflicts") == 0) {
krh@67
    81
		ctx->state = YUM_STATE_CONFLICTS;
krh@27
    82
	} else if (strcmp(name, "rpm:entry") == 0 &&
krh@30
    83
		   ctx->state != YUM_STATE_BEGIN) {
krh@27
    84
		n = NULL;
krh@27
    85
		version = NULL;
krh@62
    86
		release = NULL;
krh@27
    87
		for (i = 0; atts[i]; i += 2) {
krh@27
    88
			if (strcmp(atts[i], "name") == 0)
krh@27
    89
				n = atts[i + 1];
krh@27
    90
			else if (strcmp(atts[i], "ver") == 0)
krh@27
    91
				version = atts[i + 1];
krh@62
    92
			else if (strcmp(atts[i], "rel") == 0)
krh@62
    93
				release = atts[i + 1];
krh@27
    94
		}
krh@27
    95
krh@27
    96
		if (n == NULL) {
krh@27
    97
			fprintf(stderr, "invalid rpm:entry, "
krh@27
    98
				"missing name or version attributes\n");
krh@27
    99
			return;
krh@27
   100
		}
krh@27
   101
krh@62
   102
		if (version && release)
krh@62
   103
			snprintf(buffer, sizeof buffer,
krh@62
   104
				 "%s-%s", version, release);
krh@62
   105
		else if (version)
krh@62
   106
			strcpy(buffer, version);
krh@62
   107
		else
krh@62
   108
			buffer[0] = '\0';
krh@62
   109
			
krh@30
   110
		switch (ctx->state) {
krh@30
   111
		case YUM_STATE_REQUIRES:
krh@66
   112
			razor_importer_add_property(ctx->importer, n, buffer,
krh@66
   113
						    RAZOR_PROPERTY_REQUIRES);
krh@30
   114
			break;
krh@30
   115
		case YUM_STATE_PROVIDES:
krh@66
   116
			razor_importer_add_property(ctx->importer, n, buffer,
krh@66
   117
						    RAZOR_PROPERTY_PROVIDES);
krh@30
   118
			break;
krh@67
   119
		case YUM_STATE_OBSOLETES:
krh@67
   120
			razor_importer_add_property(ctx->importer, n, buffer,
krh@67
   121
						    RAZOR_PROPERTY_OBSOLETES);
krh@67
   122
			break;
krh@67
   123
		case YUM_STATE_CONFLICTS:
krh@67
   124
			razor_importer_add_property(ctx->importer, n, buffer,
krh@67
   125
						    RAZOR_PROPERTY_CONFLICTS);
krh@67
   126
			break;
krh@30
   127
		}
krh@27
   128
	}
krh@27
   129
}
krh@27
   130
krh@27
   131
static void
krh@70
   132
yum_primary_end_element (void *data, const char *name)
krh@27
   133
{
krh@27
   134
	struct yum_context *ctx = data;
krh@27
   135
krh@68
   136
	switch (ctx->state) {
krh@68
   137
	case YUM_STATE_PACKAGE_NAME:
krh@70
   138
	case YUM_STATE_CHECKSUM:
krh@68
   139
	case YUM_STATE_FILE:
krh@68
   140
		ctx->state = YUM_STATE_BEGIN;
krh@68
   141
		break;
krh@68
   142
	}
krh@68
   143
krh@70
   144
	if (strcmp(name, "package") == 0) {
krh@70
   145
		XML_StopParser(ctx->current_parser, XML_TRUE);
krh@70
   146
		ctx->current_parser = ctx->filelists_parser;
krh@70
   147
	}
krh@27
   148
}
krh@27
   149
krh@27
   150
static void
krh@27
   151
yum_character_data (void *data, const XML_Char *s, int len)
krh@27
   152
{
krh@27
   153
	struct yum_context *ctx = data;
krh@27
   154
krh@48
   155
	switch (ctx->state) {
krh@48
   156
	case YUM_STATE_PACKAGE_NAME:
krh@70
   157
	case YUM_STATE_CHECKSUM:
krh@48
   158
	case YUM_STATE_FILE:
krh@48
   159
		memcpy(ctx->p, s, len);
krh@48
   160
		ctx->p += len;
krh@48
   161
		*ctx->p = '\0';
krh@48
   162
		break;
krh@46
   163
	}
krh@27
   164
}
krh@27
   165
krh@70
   166
static void
krh@70
   167
yum_filelists_start_element(void *data, const char *name, const char **atts)
krh@70
   168
{
krh@70
   169
	struct yum_context *ctx = data;
krh@70
   170
	const char *pkg, *pkgid;
krh@70
   171
	int i;
krh@70
   172
krh@70
   173
	if (strcmp(name, "package") == 0) {
krh@70
   174
		pkg = NULL;
krh@70
   175
		pkgid = NULL;
krh@70
   176
		for (i = 0; atts[i]; i += 2) {
krh@70
   177
			if (strcmp(atts[i], "name") == 0)
krh@70
   178
				pkg = atts[i + 1];
krh@70
   179
			else if (strcmp(atts[i], "pkgid") == 0)
krh@70
   180
				pkgid = atts[i + 1];
krh@70
   181
		}
krh@70
   182
		if (strcmp(pkgid, ctx->pkgid) != 0)
krh@70
   183
			fprintf(stderr, "primary.xml and filelists.xml "
krh@70
   184
				"mismatch for %s: %s vs %s",
krh@70
   185
				pkg, pkgid, ctx->pkgid);
krh@70
   186
	} else if (strcmp(name, "file") == 0) {
krh@70
   187
		ctx->state = YUM_STATE_FILE;
krh@70
   188
		ctx->p = ctx->buffer;
krh@70
   189
	}
krh@70
   190
}
krh@70
   191
krh@70
   192
krh@70
   193
static void
krh@70
   194
yum_filelists_end_element (void *data, const char *name)
krh@70
   195
{
krh@70
   196
	struct yum_context *ctx = data;
krh@70
   197
krh@70
   198
	ctx->state = YUM_STATE_BEGIN;
krh@70
   199
	if (strcmp(name, "package") == 0) {
krh@70
   200
		XML_StopParser(ctx->current_parser, XML_TRUE);
krh@70
   201
		ctx->current_parser = ctx->primary_parser;
krh@70
   202
		razor_importer_finish_package(ctx->importer);
krh@70
   203
	} else if (strcmp(name, "file") == 0)
krh@70
   204
		razor_importer_add_file(ctx->importer, ctx->buffer);
krh@70
   205
krh@70
   206
}
krh@70
   207
krh@70
   208
#define XML_BUFFER_SIZE 4096
krh@70
   209
krh@27
   210
struct razor_set *
krh@70
   211
razor_set_create_from_yum(void)
krh@27
   212
{
krh@27
   213
	struct yum_context ctx;
krh@70
   214
	void *buf;
krh@70
   215
	int len, ret;
krh@70
   216
	gzFile primary, filelists;
krh@70
   217
	XML_ParsingStatus status;
krh@27
   218
krh@30
   219
	ctx.importer = razor_importer_new();	
krh@62
   220
	ctx.state = YUM_STATE_BEGIN;
krh@27
   221
krh@70
   222
	ctx.primary_parser = XML_ParserCreate(NULL);
krh@70
   223
	XML_SetUserData(ctx.primary_parser, &ctx);
krh@70
   224
	XML_SetElementHandler(ctx.primary_parser,
krh@70
   225
			      yum_primary_start_element,
krh@70
   226
			      yum_primary_end_element);
krh@70
   227
	XML_SetCharacterDataHandler(ctx.primary_parser,
krh@70
   228
				    yum_character_data);
krh@27
   229
krh@70
   230
	ctx.filelists_parser = XML_ParserCreate(NULL);
krh@70
   231
	XML_SetUserData(ctx.filelists_parser, &ctx);
krh@70
   232
	XML_SetElementHandler(ctx.filelists_parser,
krh@70
   233
			      yum_filelists_start_element,
krh@70
   234
			      yum_filelists_end_element);
krh@70
   235
	XML_SetCharacterDataHandler(ctx.filelists_parser,
krh@70
   236
				    yum_character_data);
krh@70
   237
krh@70
   238
	primary = gzopen("primary.xml.gz", "rb");
krh@70
   239
	if (primary == NULL)
krh@70
   240
		return NULL;
krh@70
   241
	filelists = gzopen("filelists.xml.gz", "rb");
krh@70
   242
	if (filelists == NULL)
krh@70
   243
		return NULL;
krh@70
   244
krh@70
   245
	ctx.current_parser = ctx.primary_parser;
krh@70
   246
krh@70
   247
	do {
krh@70
   248
		XML_GetParsingStatus(ctx.current_parser, &status);
krh@70
   249
		switch (status.parsing) {
krh@70
   250
		case XML_SUSPENDED:
krh@70
   251
			ret = XML_ResumeParser(ctx.current_parser);
krh@27
   252
			break;
krh@70
   253
		case XML_PARSING:
krh@70
   254
		case XML_INITIALIZED:
krh@70
   255
			buf = XML_GetBuffer(ctx.current_parser,
krh@70
   256
					    XML_BUFFER_SIZE);
krh@70
   257
			if (ctx.current_parser == ctx.primary_parser)
krh@70
   258
				len = gzread(primary, buf, XML_BUFFER_SIZE);
krh@70
   259
			else
krh@70
   260
				len = gzread(filelists, buf, XML_BUFFER_SIZE);
krh@70
   261
			if (len < 0) {
krh@70
   262
				fprintf(stderr,
krh@70
   263
					"couldn't read input: %s\n",
krh@70
   264
					strerror(errno));
krh@70
   265
				return NULL;
krh@70
   266
			}
krh@27
   267
krh@70
   268
			XML_ParseBuffer(ctx.current_parser, len, len == 0);
krh@70
   269
			break;
krh@70
   270
		case XML_FINISHED:
krh@70
   271
			break;
krh@27
   272
		}
krh@70
   273
	} while (status.parsing != XML_FINISHED);
krh@27
   274
krh@70
   275
krh@70
   276
	XML_ParserFree(ctx.primary_parser);
krh@70
   277
	XML_ParserFree(ctx.filelists_parser);
krh@70
   278
krh@70
   279
	gzclose(primary);
krh@70
   280
	gzclose(filelists);
krh@27
   281
krh@30
   282
	return razor_importer_finish(ctx.importer);
krh@27
   283
}
krh@28
   284
krh@31
   285
union rpm_entry {
krh@31
   286
	void *p;
krh@31
   287
	char *string;
krh@31
   288
	char **list;
krh@42
   289
	unsigned int *flags;
krh@31
   290
};
krh@31
   291
krh@28
   292
struct razor_set *
krh@28
   293
razor_set_create_from_rpmdb(void)
krh@28
   294
{
krh@30
   295
	struct razor_importer *importer;
krh@28
   296
	rpmdbMatchIterator iter;
krh@28
   297
	Header h;
krh@28
   298
	int_32 type, count, i;
krh@42
   299
	union rpm_entry name, version, release;
krh@42
   300
	union rpm_entry property_names, property_versions, property_flags;
krh@46
   301
	union rpm_entry basenames, dirnames, dirindexes;
krh@46
   302
	char filename[PATH_MAX];
krh@28
   303
	rpmdb db;
krh@28
   304
krh@28
   305
	rpmReadConfigFiles(NULL, NULL);
krh@28
   306
krh@28
   307
	if (rpmdbOpen("", &db, O_RDONLY, 0644) != 0) {
krh@28
   308
		fprintf(stderr, "cannot open rpm database\n");
krh@28
   309
		exit(1);
krh@28
   310
	}
krh@28
   311
krh@30
   312
	importer = razor_importer_new();
krh@28
   313
krh@28
   314
	iter = rpmdbInitIterator(db, 0, NULL, 0);
krh@28
   315
	while (h = rpmdbNextIterator(iter), h != NULL) {
krh@31
   316
		headerGetEntry(h, RPMTAG_NAME, &type, &name.p, &count);
krh@42
   317
		headerGetEntry(h, RPMTAG_VERSION, &type, &version.p, &count);
krh@31
   318
		headerGetEntry(h, RPMTAG_RELEASE, &type, &release.p, &count);
krh@59
   319
		snprintf(filename, sizeof filename, "%s-%s",
krh@59
   320
			 version.string, release.string);
krh@59
   321
		razor_importer_begin_package(importer, name.string, filename);
krh@28
   322
krh@42
   323
		headerGetEntry(h, RPMTAG_REQUIRENAME, &type,
krh@42
   324
			       &property_names.p, &count);
krh@28
   325
		headerGetEntry(h, RPMTAG_REQUIREVERSION, &type,
krh@31
   326
			       &property_versions.p, &count);
krh@42
   327
		headerGetEntry(h, RPMTAG_REQUIREFLAGS, &type,
krh@42
   328
			       &property_flags.p, &count);
krh@28
   329
		for (i = 0; i < count; i++)
krh@66
   330
			razor_importer_add_property(importer,
krh@42
   331
						    property_names.list[i],
krh@66
   332
						    property_versions.list[i],
krh@66
   333
						    RAZOR_PROPERTY_REQUIRES);
krh@28
   334
krh@42
   335
		headerGetEntry(h, RPMTAG_PROVIDENAME, &type,
krh@42
   336
			       &property_names.p, &count);
krh@28
   337
		headerGetEntry(h, RPMTAG_PROVIDEVERSION, &type,
krh@31
   338
			       &property_versions.p, &count);
krh@67
   339
		headerGetEntry(h, RPMTAG_PROVIDEFLAGS, &type,
krh@67
   340
			       &property_flags.p, &count);
krh@28
   341
		for (i = 0; i < count; i++)
krh@66
   342
			razor_importer_add_property(importer,
krh@42
   343
						    property_names.list[i],
krh@66
   344
						    property_versions.list[i],
krh@66
   345
						    RAZOR_PROPERTY_PROVIDES);
krh@28
   346
krh@67
   347
		headerGetEntry(h, RPMTAG_OBSOLETENAME, &type,
krh@67
   348
			       &property_names.p, &count);
krh@67
   349
		headerGetEntry(h, RPMTAG_OBSOLETEVERSION, &type,
krh@67
   350
			       &property_versions.p, &count);
krh@67
   351
		headerGetEntry(h, RPMTAG_OBSOLETEFLAGS, &type,
krh@67
   352
			       &property_flags.p, &count);
krh@67
   353
		for (i = 0; i < count; i++)
krh@67
   354
			razor_importer_add_property(importer,
krh@67
   355
						    property_names.list[i],
krh@67
   356
						    property_versions.list[i],
krh@67
   357
						    RAZOR_PROPERTY_OBSOLETES);
krh@67
   358
krh@67
   359
		headerGetEntry(h, RPMTAG_CONFLICTNAME, &type,
krh@67
   360
			       &property_names.p, &count);
krh@67
   361
		headerGetEntry(h, RPMTAG_CONFLICTVERSION, &type,
krh@67
   362
			       &property_versions.p, &count);
krh@67
   363
		headerGetEntry(h, RPMTAG_CONFLICTFLAGS, &type,
krh@67
   364
			       &property_flags.p, &count);
krh@67
   365
		for (i = 0; i < count; i++)
krh@67
   366
			razor_importer_add_property(importer,
krh@67
   367
						    property_names.list[i],
krh@67
   368
						    property_versions.list[i],
krh@67
   369
						    RAZOR_PROPERTY_CONFLICTS);
krh@67
   370
krh@46
   371
		headerGetEntry(h, RPMTAG_BASENAMES, &type,
krh@46
   372
			       &basenames.p, &count);
krh@46
   373
		headerGetEntry(h, RPMTAG_DIRNAMES, &type,
krh@46
   374
			       &dirnames.p, &count);
krh@46
   375
		headerGetEntry(h, RPMTAG_DIRINDEXES, &type,
krh@46
   376
			       &dirindexes.p, &count);
krh@46
   377
		for (i = 0; i < count; i++) {
krh@46
   378
			snprintf(filename, sizeof filename, "%s%s",
krh@46
   379
				 dirnames.list[dirindexes.flags[i]],
krh@46
   380
				 basenames.list[i]);
krh@46
   381
			razor_importer_add_file(importer, filename);
krh@46
   382
		}
krh@46
   383
krh@30
   384
		razor_importer_finish_package(importer);
krh@28
   385
	}
krh@28
   386
krh@28
   387
	rpmdbClose(db);
krh@28
   388
krh@30
   389
	return razor_importer_finish(importer);
krh@28
   390
}