import.c
author Kristian H?gsberg <krh@redhat.com>
Sun Nov 04 00:58:25 2007 -0400 (2007-11-04)
changeset 68 0587f1759f09
parent 67 cfe57117efee
child 70 e94d16f789e5
permissions -rw-r--r--
Don't reset yum parser state when finishing parsing rpm:entry.

This fixes the bug where each package on got on of each property type.
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@28
    12
#include <rpm/rpmlib.h>
krh@28
    13
#include <rpm/rpmdb.h>
krh@27
    14
#include "sha1.h"
krh@27
    15
#include "razor.h"
krh@27
    16
krh@27
    17
static void
krh@30
    18
parse_package(struct razor_importer *importer, const char **atts, void *data)
krh@27
    19
{
krh@27
    20
	const char *name = NULL, *version = NULL;
krh@27
    21
	int i;
krh@27
    22
krh@27
    23
	for (i = 0; atts[i]; i += 2) {
krh@27
    24
		if (strcmp(atts[i], "name") == 0)
krh@27
    25
			name = atts[i + 1];
krh@27
    26
		else if (strcmp(atts[i], "version") == 0)
krh@27
    27
			version = atts[i + 1];
krh@27
    28
	}
krh@27
    29
krh@27
    30
	if (name == NULL || version == NULL) {
krh@27
    31
		fprintf(stderr, "invalid package tag, "
krh@27
    32
			"missing name or version attributes\n");
krh@27
    33
		return;
krh@27
    34
	}
krh@27
    35
krh@30
    36
	razor_importer_begin_package(importer, name, version);
krh@27
    37
}
krh@27
    38
krh@30
    39
enum {
krh@30
    40
	RZR_REQUIRES, RZR_PROVIDES
krh@30
    41
};
krh@30
    42
krh@27
    43
static void
krh@30
    44
parse_property(struct razor_importer *importer, const char **atts, void *data)
krh@27
    45
{
krh@27
    46
	const char *name = NULL, *version = NULL;
krh@27
    47
	int i;
krh@27
    48
krh@27
    49
	for (i = 0; atts[i]; i += 2) {
krh@27
    50
		if (strcmp(atts[i], "name") == 0)
krh@27
    51
			name = atts[i + 1];
krh@27
    52
		if (strcmp(atts[i], "version") == 0)
krh@27
    53
			version = atts[i + 1];
krh@27
    54
	}
krh@27
    55
	
krh@27
    56
	if (name == NULL) {
krh@27
    57
		fprintf(stderr, "invalid tag, missing name attribute\n");
krh@27
    58
		return;
krh@27
    59
	}
krh@27
    60
krh@30
    61
	switch ((int) data) {
krh@30
    62
	case RZR_REQUIRES:
krh@66
    63
		razor_importer_add_property(importer, name, version,
krh@66
    64
					    RAZOR_PROPERTY_REQUIRES);
krh@30
    65
		break;
krh@30
    66
	case RZR_PROVIDES:
krh@66
    67
		razor_importer_add_property(importer, name, version,
krh@66
    68
					    RAZOR_PROPERTY_PROVIDES);
krh@30
    69
		break;
krh@30
    70
	}
krh@27
    71
}
krh@27
    72
krh@27
    73
static void
krh@27
    74
start_element(void *data, const char *name, const char **atts)
krh@27
    75
{
krh@30
    76
	struct razor_importer *importer = data;
krh@27
    77
krh@27
    78
	if (strcmp(name, "package") == 0)
krh@30
    79
		parse_package(importer, atts, NULL);
krh@27
    80
	else if (strcmp(name, "requires") == 0)
krh@30
    81
		parse_property(importer, atts, (void *) RZR_REQUIRES);
krh@27
    82
	else if (strcmp(name, "provides") == 0)
krh@30
    83
		parse_property(importer, atts, (void*) RZR_PROVIDES);
krh@27
    84
}
krh@27
    85
krh@27
    86
static void
krh@27
    87
end_element (void *data, const char *name)
krh@27
    88
{
krh@30
    89
	struct razor_importer *importer = data;
krh@27
    90
krh@27
    91
	if (strcmp(name, "package") == 0)
krh@30
    92
		razor_importer_finish_package(importer);
krh@27
    93
}
krh@27
    94
krh@27
    95
static int
krh@30
    96
import_rzr_file(struct razor_importer *importer, const char *filename)
krh@27
    97
{
krh@27
    98
	SHA_CTX sha1;
krh@27
    99
	XML_Parser parser;
krh@27
   100
	int fd;
krh@27
   101
	void *p;
krh@27
   102
	struct stat stat;
krh@27
   103
	unsigned char hash[20];
krh@27
   104
krh@27
   105
	fd = open(filename, O_RDONLY);
krh@27
   106
	if (fstat(fd, &stat) < 0)
krh@27
   107
		return -1;
krh@27
   108
	p = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
krh@27
   109
	if (p == MAP_FAILED)
krh@27
   110
		return -1;
krh@27
   111
krh@27
   112
	parser = XML_ParserCreate(NULL);
krh@30
   113
	XML_SetUserData(parser, importer);
krh@27
   114
	XML_SetElementHandler(parser, start_element, end_element);
krh@27
   115
	if (XML_Parse(parser, p, stat.st_size, 1) == XML_STATUS_ERROR) {
krh@27
   116
		fprintf(stderr,
krh@46
   117
			"%s at line %ld, %s\n",
krh@27
   118
			XML_ErrorString(XML_GetErrorCode(parser)),
krh@27
   119
			XML_GetCurrentLineNumber(parser),
krh@27
   120
			filename);
krh@27
   121
		return 1;
krh@27
   122
	}
krh@27
   123
krh@27
   124
	XML_ParserFree(parser);
krh@27
   125
krh@27
   126
	SHA1_Init(&sha1);
krh@27
   127
	SHA1_Update(&sha1, p, stat.st_size);
krh@27
   128
	SHA1_Final(hash, &sha1);
krh@27
   129
krh@27
   130
	close(fd);
krh@27
   131
krh@27
   132
	munmap(p, stat.st_size);
krh@27
   133
krh@27
   134
	return 0;
krh@27
   135
}
krh@27
   136
krh@27
   137
struct razor_set *
krh@27
   138
razor_import_rzr_files(int count, const char *files[])
krh@27
   139
{
krh@30
   140
	struct razor_importer *importer;
krh@27
   141
	int i;
krh@27
   142
krh@30
   143
	importer = razor_importer_new();
krh@27
   144
krh@27
   145
	for (i = 0; i < count; i++) {
krh@30
   146
		if (import_rzr_file(importer, files[i]) < 0) {
krh@27
   147
			fprintf(stderr, "failed to import %s\n", files[i]);
krh@27
   148
			exit(-1);
krh@27
   149
		}
krh@27
   150
	}
krh@27
   151
krh@30
   152
	return razor_importer_finish(importer);
krh@27
   153
}
krh@27
   154
krh@27
   155
/* Import a yum filelist as a razor package set. */
krh@27
   156
krh@27
   157
enum {
krh@27
   158
	YUM_STATE_BEGIN,
krh@30
   159
	YUM_STATE_PACKAGE_NAME,
krh@30
   160
	YUM_STATE_REQUIRES,
krh@46
   161
	YUM_STATE_PROVIDES,
krh@67
   162
	YUM_STATE_OBSOLETES,
krh@67
   163
	YUM_STATE_CONFLICTS,
krh@46
   164
	YUM_STATE_FILE
krh@27
   165
};
krh@27
   166
krh@27
   167
struct yum_context {
krh@30
   168
	struct razor_importer *importer;
krh@27
   169
	struct import_property_context *current_property_context;
krh@48
   170
	char name[256], buffer[512], *p;
krh@27
   171
	int state;
krh@27
   172
};
krh@27
   173
krh@27
   174
static void
krh@27
   175
yum_start_element(void *data, const char *name, const char **atts)
krh@27
   176
{
krh@27
   177
	struct yum_context *ctx = data;
krh@62
   178
	const char *n, *version, *release;
krh@62
   179
	char buffer[128];
krh@27
   180
	int i;
krh@27
   181
krh@27
   182
	if (strcmp(name, "name") == 0) {
krh@27
   183
		ctx->state = YUM_STATE_PACKAGE_NAME;
krh@48
   184
		ctx->p = ctx->name;
krh@27
   185
	} else if (strcmp(name, "version") == 0) {
krh@27
   186
		version = NULL;
krh@62
   187
		release = NULL;
krh@27
   188
		for (i = 0; atts[i]; i += 2) {
krh@27
   189
			if (strcmp(atts[i], "ver") == 0)
krh@27
   190
				version = atts[i + 1];
krh@62
   191
			else if (strcmp(atts[i], "rel") == 0)
krh@62
   192
				release = atts[i + 1];
krh@27
   193
		}
krh@62
   194
		if (version == NULL || release == NULL) {
krh@62
   195
			fprintf(stderr, "invalid version tag, "
krh@62
   196
				"missing version or  release attribute\n");
krh@62
   197
			return;
krh@62
   198
		}
krh@62
   199
krh@62
   200
		snprintf(buffer, sizeof buffer, "%s-%s", version, release);
krh@62
   201
		razor_importer_begin_package(ctx->importer, ctx->name, buffer);
krh@27
   202
	} else if (strcmp(name, "rpm:requires") == 0) {
krh@30
   203
		ctx->state = YUM_STATE_REQUIRES;
krh@27
   204
	} else if (strcmp(name, "rpm:provides") == 0) {
krh@30
   205
		ctx->state = YUM_STATE_PROVIDES;
krh@67
   206
	} else if (strcmp(name, "rpm:obsoletes") == 0) {
krh@67
   207
		ctx->state = YUM_STATE_OBSOLETES;
krh@67
   208
	} else if (strcmp(name, "rpm:conflicts") == 0) {
krh@67
   209
		ctx->state = YUM_STATE_CONFLICTS;
krh@27
   210
	} else if (strcmp(name, "rpm:entry") == 0 &&
krh@30
   211
		   ctx->state != YUM_STATE_BEGIN) {
krh@27
   212
		n = NULL;
krh@27
   213
		version = NULL;
krh@62
   214
		release = NULL;
krh@27
   215
		for (i = 0; atts[i]; i += 2) {
krh@27
   216
			if (strcmp(atts[i], "name") == 0)
krh@27
   217
				n = atts[i + 1];
krh@27
   218
			else if (strcmp(atts[i], "ver") == 0)
krh@27
   219
				version = atts[i + 1];
krh@62
   220
			else if (strcmp(atts[i], "rel") == 0)
krh@62
   221
				release = atts[i + 1];
krh@27
   222
		}
krh@27
   223
krh@27
   224
		if (n == NULL) {
krh@27
   225
			fprintf(stderr, "invalid rpm:entry, "
krh@27
   226
				"missing name or version attributes\n");
krh@27
   227
			return;
krh@27
   228
		}
krh@27
   229
krh@62
   230
		if (version && release)
krh@62
   231
			snprintf(buffer, sizeof buffer,
krh@62
   232
				 "%s-%s", version, release);
krh@62
   233
		else if (version)
krh@62
   234
			strcpy(buffer, version);
krh@62
   235
		else
krh@62
   236
			buffer[0] = '\0';
krh@62
   237
			
krh@30
   238
		switch (ctx->state) {
krh@30
   239
		case YUM_STATE_REQUIRES:
krh@66
   240
			razor_importer_add_property(ctx->importer, n, buffer,
krh@66
   241
						    RAZOR_PROPERTY_REQUIRES);
krh@30
   242
			break;
krh@30
   243
		case YUM_STATE_PROVIDES:
krh@66
   244
			razor_importer_add_property(ctx->importer, n, buffer,
krh@66
   245
						    RAZOR_PROPERTY_PROVIDES);
krh@30
   246
			break;
krh@67
   247
		case YUM_STATE_OBSOLETES:
krh@67
   248
			razor_importer_add_property(ctx->importer, n, buffer,
krh@67
   249
						    RAZOR_PROPERTY_OBSOLETES);
krh@67
   250
			break;
krh@67
   251
		case YUM_STATE_CONFLICTS:
krh@67
   252
			razor_importer_add_property(ctx->importer, n, buffer,
krh@67
   253
						    RAZOR_PROPERTY_CONFLICTS);
krh@67
   254
			break;
krh@30
   255
		}
krh@46
   256
	} else if (strcmp(name, "file") == 0) {
krh@46
   257
		ctx->state = YUM_STATE_FILE;
krh@48
   258
		ctx->p = ctx->buffer;
krh@27
   259
	}
krh@27
   260
}
krh@27
   261
krh@27
   262
static void
krh@27
   263
yum_end_element (void *data, const char *name)
krh@27
   264
{
krh@27
   265
	struct yum_context *ctx = data;
krh@27
   266
krh@68
   267
	switch (ctx->state) {
krh@68
   268
	case YUM_STATE_PACKAGE_NAME:
krh@68
   269
	case YUM_STATE_FILE:
krh@68
   270
		ctx->state = YUM_STATE_BEGIN;
krh@68
   271
		break;
krh@68
   272
	}
krh@68
   273
krh@48
   274
	if (strcmp(name, "package") == 0)
krh@30
   275
		razor_importer_finish_package(ctx->importer);
krh@48
   276
	else if (strcmp(name, "file") == 0)
krh@48
   277
		razor_importer_add_file(ctx->importer, ctx->buffer);
krh@27
   278
}
krh@27
   279
krh@27
   280
static void
krh@27
   281
yum_character_data (void *data, const XML_Char *s, int len)
krh@27
   282
{
krh@27
   283
	struct yum_context *ctx = data;
krh@27
   284
krh@48
   285
	switch (ctx->state) {
krh@48
   286
	case YUM_STATE_PACKAGE_NAME:
krh@48
   287
	case YUM_STATE_FILE:
krh@48
   288
		memcpy(ctx->p, s, len);
krh@48
   289
		ctx->p += len;
krh@48
   290
		*ctx->p = '\0';
krh@48
   291
		break;
krh@46
   292
	}
krh@27
   293
}
krh@27
   294
krh@27
   295
struct razor_set *
krh@27
   296
razor_set_create_from_yum_filelist(int fd)
krh@27
   297
{
krh@27
   298
	struct yum_context ctx;
krh@27
   299
	XML_Parser parser;
krh@27
   300
	char buf[4096];
krh@27
   301
	int len;
krh@27
   302
krh@30
   303
	ctx.importer = razor_importer_new();	
krh@62
   304
	ctx.state = YUM_STATE_BEGIN;
krh@27
   305
krh@27
   306
	parser = XML_ParserCreate(NULL);
krh@27
   307
	XML_SetUserData(parser, &ctx);
krh@27
   308
	XML_SetElementHandler(parser, yum_start_element, yum_end_element);
krh@27
   309
	XML_SetCharacterDataHandler(parser, yum_character_data);
krh@27
   310
krh@27
   311
	while (1) {
krh@27
   312
		len = read(fd, buf, sizeof buf);
krh@27
   313
		if (len < 0) {
krh@27
   314
			fprintf(stderr,
krh@27
   315
				"couldn't read input: %s\n", strerror(errno));
krh@27
   316
			return NULL;
krh@27
   317
		} else if (len == 0)
krh@27
   318
			break;
krh@27
   319
krh@27
   320
		if (XML_Parse(parser, buf, len, 0) == XML_STATUS_ERROR) {
krh@27
   321
			fprintf(stderr,
krh@46
   322
				"%s at line %ld\n",
krh@27
   323
				XML_ErrorString(XML_GetErrorCode(parser)),
krh@27
   324
				XML_GetCurrentLineNumber(parser));
krh@27
   325
			return NULL;
krh@27
   326
		}
krh@27
   327
	}
krh@27
   328
krh@27
   329
	XML_ParserFree(parser);
krh@27
   330
krh@30
   331
	return razor_importer_finish(ctx.importer);
krh@27
   332
}
krh@28
   333
krh@31
   334
union rpm_entry {
krh@31
   335
	void *p;
krh@31
   336
	char *string;
krh@31
   337
	char **list;
krh@42
   338
	unsigned int *flags;
krh@31
   339
};
krh@31
   340
krh@28
   341
struct razor_set *
krh@28
   342
razor_set_create_from_rpmdb(void)
krh@28
   343
{
krh@30
   344
	struct razor_importer *importer;
krh@28
   345
	rpmdbMatchIterator iter;
krh@28
   346
	Header h;
krh@28
   347
	int_32 type, count, i;
krh@42
   348
	union rpm_entry name, version, release;
krh@42
   349
	union rpm_entry property_names, property_versions, property_flags;
krh@46
   350
	union rpm_entry basenames, dirnames, dirindexes;
krh@46
   351
	char filename[PATH_MAX];
krh@28
   352
	rpmdb db;
krh@28
   353
krh@28
   354
	rpmReadConfigFiles(NULL, NULL);
krh@28
   355
krh@28
   356
	if (rpmdbOpen("", &db, O_RDONLY, 0644) != 0) {
krh@28
   357
		fprintf(stderr, "cannot open rpm database\n");
krh@28
   358
		exit(1);
krh@28
   359
	}
krh@28
   360
krh@30
   361
	importer = razor_importer_new();
krh@28
   362
krh@28
   363
	iter = rpmdbInitIterator(db, 0, NULL, 0);
krh@28
   364
	while (h = rpmdbNextIterator(iter), h != NULL) {
krh@31
   365
		headerGetEntry(h, RPMTAG_NAME, &type, &name.p, &count);
krh@42
   366
		headerGetEntry(h, RPMTAG_VERSION, &type, &version.p, &count);
krh@31
   367
		headerGetEntry(h, RPMTAG_RELEASE, &type, &release.p, &count);
krh@59
   368
		snprintf(filename, sizeof filename, "%s-%s",
krh@59
   369
			 version.string, release.string);
krh@59
   370
		razor_importer_begin_package(importer, name.string, filename);
krh@28
   371
krh@42
   372
		headerGetEntry(h, RPMTAG_REQUIRENAME, &type,
krh@42
   373
			       &property_names.p, &count);
krh@28
   374
		headerGetEntry(h, RPMTAG_REQUIREVERSION, &type,
krh@31
   375
			       &property_versions.p, &count);
krh@42
   376
		headerGetEntry(h, RPMTAG_REQUIREFLAGS, &type,
krh@42
   377
			       &property_flags.p, &count);
krh@28
   378
		for (i = 0; i < count; i++)
krh@66
   379
			razor_importer_add_property(importer,
krh@42
   380
						    property_names.list[i],
krh@66
   381
						    property_versions.list[i],
krh@66
   382
						    RAZOR_PROPERTY_REQUIRES);
krh@28
   383
krh@42
   384
		headerGetEntry(h, RPMTAG_PROVIDENAME, &type,
krh@42
   385
			       &property_names.p, &count);
krh@28
   386
		headerGetEntry(h, RPMTAG_PROVIDEVERSION, &type,
krh@31
   387
			       &property_versions.p, &count);
krh@67
   388
		headerGetEntry(h, RPMTAG_PROVIDEFLAGS, &type,
krh@67
   389
			       &property_flags.p, &count);
krh@28
   390
		for (i = 0; i < count; i++)
krh@66
   391
			razor_importer_add_property(importer,
krh@42
   392
						    property_names.list[i],
krh@66
   393
						    property_versions.list[i],
krh@66
   394
						    RAZOR_PROPERTY_PROVIDES);
krh@28
   395
krh@67
   396
		headerGetEntry(h, RPMTAG_OBSOLETENAME, &type,
krh@67
   397
			       &property_names.p, &count);
krh@67
   398
		headerGetEntry(h, RPMTAG_OBSOLETEVERSION, &type,
krh@67
   399
			       &property_versions.p, &count);
krh@67
   400
		headerGetEntry(h, RPMTAG_OBSOLETEFLAGS, &type,
krh@67
   401
			       &property_flags.p, &count);
krh@67
   402
		for (i = 0; i < count; i++)
krh@67
   403
			razor_importer_add_property(importer,
krh@67
   404
						    property_names.list[i],
krh@67
   405
						    property_versions.list[i],
krh@67
   406
						    RAZOR_PROPERTY_OBSOLETES);
krh@67
   407
krh@67
   408
		headerGetEntry(h, RPMTAG_CONFLICTNAME, &type,
krh@67
   409
			       &property_names.p, &count);
krh@67
   410
		headerGetEntry(h, RPMTAG_CONFLICTVERSION, &type,
krh@67
   411
			       &property_versions.p, &count);
krh@67
   412
		headerGetEntry(h, RPMTAG_CONFLICTFLAGS, &type,
krh@67
   413
			       &property_flags.p, &count);
krh@67
   414
		for (i = 0; i < count; i++)
krh@67
   415
			razor_importer_add_property(importer,
krh@67
   416
						    property_names.list[i],
krh@67
   417
						    property_versions.list[i],
krh@67
   418
						    RAZOR_PROPERTY_CONFLICTS);
krh@67
   419
krh@46
   420
		headerGetEntry(h, RPMTAG_BASENAMES, &type,
krh@46
   421
			       &basenames.p, &count);
krh@46
   422
		headerGetEntry(h, RPMTAG_DIRNAMES, &type,
krh@46
   423
			       &dirnames.p, &count);
krh@46
   424
		headerGetEntry(h, RPMTAG_DIRINDEXES, &type,
krh@46
   425
			       &dirindexes.p, &count);
krh@46
   426
		for (i = 0; i < count; i++) {
krh@46
   427
			snprintf(filename, sizeof filename, "%s%s",
krh@46
   428
				 dirnames.list[dirindexes.flags[i]],
krh@46
   429
				 basenames.list[i]);
krh@46
   430
			razor_importer_add_file(importer, filename);
krh@46
   431
		}
krh@46
   432
krh@30
   433
		razor_importer_finish_package(importer);
krh@28
   434
	}
krh@28
   435
krh@28
   436
	rpmdbClose(db);
krh@28
   437
krh@30
   438
	return razor_importer_finish(importer);
krh@28
   439
}