import.c
author Kristian H?gsberg <krh@redhat.com>
Sat Sep 29 23:30:35 2007 -0400 (2007-09-29)
changeset 42 aedfc8f95227
parent 31 50fd9002d5ee
child 46 8de578466ece
permissions -rw-r--r--
Get version flags for requires in rpmdb importer.
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@30
    63
		razor_importer_add_requires(importer, name, version);
krh@30
    64
		break;
krh@30
    65
	case RZR_PROVIDES:
krh@30
    66
		razor_importer_add_provides(importer, name, version);
krh@30
    67
		break;
krh@30
    68
	}
krh@27
    69
}
krh@27
    70
krh@27
    71
static void
krh@27
    72
start_element(void *data, const char *name, const char **atts)
krh@27
    73
{
krh@30
    74
	struct razor_importer *importer = data;
krh@27
    75
krh@27
    76
	if (strcmp(name, "package") == 0)
krh@30
    77
		parse_package(importer, atts, NULL);
krh@27
    78
	else if (strcmp(name, "requires") == 0)
krh@30
    79
		parse_property(importer, atts, (void *) RZR_REQUIRES);
krh@27
    80
	else if (strcmp(name, "provides") == 0)
krh@30
    81
		parse_property(importer, atts, (void*) RZR_PROVIDES);
krh@27
    82
}
krh@27
    83
krh@27
    84
static void
krh@27
    85
end_element (void *data, const char *name)
krh@27
    86
{
krh@30
    87
	struct razor_importer *importer = data;
krh@27
    88
krh@27
    89
	if (strcmp(name, "package") == 0)
krh@30
    90
		razor_importer_finish_package(importer);
krh@27
    91
}
krh@27
    92
krh@27
    93
static int
krh@30
    94
import_rzr_file(struct razor_importer *importer, const char *filename)
krh@27
    95
{
krh@27
    96
	SHA_CTX sha1;
krh@27
    97
	XML_Parser parser;
krh@27
    98
	int fd;
krh@27
    99
	void *p;
krh@27
   100
	struct stat stat;
krh@27
   101
	unsigned char hash[20];
krh@27
   102
krh@27
   103
	fd = open(filename, O_RDONLY);
krh@27
   104
	if (fstat(fd, &stat) < 0)
krh@27
   105
		return -1;
krh@27
   106
	p = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
krh@27
   107
	if (p == MAP_FAILED)
krh@27
   108
		return -1;
krh@27
   109
krh@27
   110
	parser = XML_ParserCreate(NULL);
krh@30
   111
	XML_SetUserData(parser, importer);
krh@27
   112
	XML_SetElementHandler(parser, start_element, end_element);
krh@27
   113
	if (XML_Parse(parser, p, stat.st_size, 1) == XML_STATUS_ERROR) {
krh@27
   114
		fprintf(stderr,
krh@27
   115
			"%s at line %d, %s\n",
krh@27
   116
			XML_ErrorString(XML_GetErrorCode(parser)),
krh@27
   117
			XML_GetCurrentLineNumber(parser),
krh@27
   118
			filename);
krh@27
   119
		return 1;
krh@27
   120
	}
krh@27
   121
krh@27
   122
	XML_ParserFree(parser);
krh@27
   123
krh@27
   124
	SHA1_Init(&sha1);
krh@27
   125
	SHA1_Update(&sha1, p, stat.st_size);
krh@27
   126
	SHA1_Final(hash, &sha1);
krh@27
   127
krh@27
   128
	close(fd);
krh@27
   129
krh@27
   130
	munmap(p, stat.st_size);
krh@27
   131
krh@27
   132
	return 0;
krh@27
   133
}
krh@27
   134
krh@27
   135
struct razor_set *
krh@27
   136
razor_import_rzr_files(int count, const char *files[])
krh@27
   137
{
krh@30
   138
	struct razor_importer *importer;
krh@27
   139
	int i;
krh@27
   140
krh@30
   141
	importer = razor_importer_new();
krh@27
   142
krh@27
   143
	for (i = 0; i < count; i++) {
krh@30
   144
		if (import_rzr_file(importer, files[i]) < 0) {
krh@27
   145
			fprintf(stderr, "failed to import %s\n", files[i]);
krh@27
   146
			exit(-1);
krh@27
   147
		}
krh@27
   148
	}
krh@27
   149
krh@30
   150
	return razor_importer_finish(importer);
krh@27
   151
}
krh@27
   152
krh@27
   153
/* Import a yum filelist as a razor package set. */
krh@27
   154
krh@27
   155
enum {
krh@27
   156
	YUM_STATE_BEGIN,
krh@30
   157
	YUM_STATE_PACKAGE_NAME,
krh@30
   158
	YUM_STATE_REQUIRES,
krh@30
   159
	YUM_STATE_PROVIDES
krh@27
   160
};
krh@27
   161
krh@27
   162
struct yum_context {
krh@30
   163
	struct razor_importer *importer;
krh@27
   164
	struct import_property_context *current_property_context;
krh@27
   165
	char *name;
krh@27
   166
	int state;
krh@27
   167
};
krh@27
   168
krh@27
   169
static void
krh@27
   170
yum_start_element(void *data, const char *name, const char **atts)
krh@27
   171
{
krh@27
   172
	struct yum_context *ctx = data;
krh@27
   173
	const char *n, *version;
krh@27
   174
	int i;
krh@27
   175
krh@27
   176
	if (strcmp(name, "name") == 0) {
krh@27
   177
		ctx->state = YUM_STATE_PACKAGE_NAME;
krh@27
   178
	} else if (strcmp(name, "version") == 0) {
krh@27
   179
		version = NULL;
krh@27
   180
		for (i = 0; atts[i]; i += 2) {
krh@27
   181
			if (strcmp(atts[i], "ver") == 0)
krh@27
   182
				version = atts[i + 1];
krh@27
   183
		}
krh@30
   184
		razor_importer_begin_package(ctx->importer, ctx->name, version);
krh@27
   185
	} else if (strcmp(name, "rpm:requires") == 0) {
krh@30
   186
		ctx->state = YUM_STATE_REQUIRES;
krh@27
   187
	} else if (strcmp(name, "rpm:provides") == 0) {
krh@30
   188
		ctx->state = YUM_STATE_PROVIDES;
krh@27
   189
	} else if (strcmp(name, "rpm:entry") == 0 &&
krh@30
   190
		   ctx->state != YUM_STATE_BEGIN) {
krh@27
   191
		n = NULL;
krh@27
   192
		version = NULL;
krh@27
   193
		for (i = 0; atts[i]; i += 2) {
krh@27
   194
			if (strcmp(atts[i], "name") == 0)
krh@27
   195
				n = atts[i + 1];
krh@27
   196
			else if (strcmp(atts[i], "ver") == 0)
krh@27
   197
				version = atts[i + 1];
krh@27
   198
		}
krh@27
   199
krh@27
   200
		if (n == NULL) {
krh@27
   201
			fprintf(stderr, "invalid rpm:entry, "
krh@27
   202
				"missing name or version attributes\n");
krh@27
   203
			return;
krh@27
   204
		}
krh@27
   205
krh@30
   206
		switch (ctx->state) {
krh@30
   207
		case YUM_STATE_REQUIRES:
krh@30
   208
			razor_importer_add_requires(ctx->importer, n, version);
krh@30
   209
			break;
krh@30
   210
		case YUM_STATE_PROVIDES:
krh@30
   211
			razor_importer_add_provides(ctx->importer, n, version);
krh@30
   212
			break;
krh@30
   213
		}
krh@30
   214
krh@27
   215
	}
krh@27
   216
}
krh@27
   217
krh@27
   218
static void
krh@27
   219
yum_end_element (void *data, const char *name)
krh@27
   220
{
krh@27
   221
	struct yum_context *ctx = data;
krh@27
   222
krh@27
   223
	if (strcmp(name, "package") == 0) {
krh@27
   224
		free(ctx->name);
krh@30
   225
		razor_importer_finish_package(ctx->importer);
krh@27
   226
	} else if (strcmp(name, "name") == 0) {
krh@30
   227
		ctx->state = YUM_STATE_BEGIN;
krh@27
   228
	} else if (strcmp(name, "rpm:requires") == 0) {
krh@30
   229
		ctx->state = YUM_STATE_BEGIN;
krh@27
   230
	} else if (strcmp(name, "rpm:provides") == 0) {
krh@30
   231
		ctx->state = YUM_STATE_BEGIN;
krh@27
   232
	}
krh@27
   233
}
krh@27
   234
krh@27
   235
static void
krh@27
   236
yum_character_data (void *data, const XML_Char *s, int len)
krh@27
   237
{
krh@27
   238
	struct yum_context *ctx = data;
krh@27
   239
krh@27
   240
	if (ctx->state == YUM_STATE_PACKAGE_NAME)
krh@27
   241
		ctx->name = strndup(s, len);
krh@27
   242
}
krh@27
   243
krh@27
   244
struct razor_set *
krh@27
   245
razor_set_create_from_yum_filelist(int fd)
krh@27
   246
{
krh@27
   247
	struct yum_context ctx;
krh@27
   248
	XML_Parser parser;
krh@27
   249
	char buf[4096];
krh@27
   250
	int len;
krh@27
   251
krh@30
   252
	ctx.importer = razor_importer_new();	
krh@27
   253
krh@27
   254
	parser = XML_ParserCreate(NULL);
krh@27
   255
	XML_SetUserData(parser, &ctx);
krh@27
   256
	XML_SetElementHandler(parser, yum_start_element, yum_end_element);
krh@27
   257
	XML_SetCharacterDataHandler(parser, yum_character_data);
krh@27
   258
krh@27
   259
	while (1) {
krh@27
   260
		len = read(fd, buf, sizeof buf);
krh@27
   261
		if (len < 0) {
krh@27
   262
			fprintf(stderr,
krh@27
   263
				"couldn't read input: %s\n", strerror(errno));
krh@27
   264
			return NULL;
krh@27
   265
		} else if (len == 0)
krh@27
   266
			break;
krh@27
   267
krh@27
   268
		if (XML_Parse(parser, buf, len, 0) == XML_STATUS_ERROR) {
krh@27
   269
			fprintf(stderr,
krh@27
   270
				"%s at line %d\n",
krh@27
   271
				XML_ErrorString(XML_GetErrorCode(parser)),
krh@27
   272
				XML_GetCurrentLineNumber(parser));
krh@27
   273
			return NULL;
krh@27
   274
		}
krh@27
   275
	}
krh@27
   276
krh@27
   277
	XML_ParserFree(parser);
krh@27
   278
krh@30
   279
	return razor_importer_finish(ctx.importer);
krh@27
   280
}
krh@28
   281
krh@31
   282
union rpm_entry {
krh@31
   283
	void *p;
krh@31
   284
	char *string;
krh@31
   285
	char **list;
krh@42
   286
	unsigned int *flags;
krh@31
   287
};
krh@31
   288
krh@28
   289
struct razor_set *
krh@28
   290
razor_set_create_from_rpmdb(void)
krh@28
   291
{
krh@30
   292
	struct razor_importer *importer;
krh@28
   293
	rpmdbMatchIterator iter;
krh@28
   294
	Header h;
krh@28
   295
	int_32 type, count, i;
krh@42
   296
	union rpm_entry name, version, release;
krh@42
   297
	union rpm_entry property_names, property_versions, property_flags;
krh@28
   298
	rpmdb db;
krh@28
   299
krh@28
   300
	rpmReadConfigFiles(NULL, NULL);
krh@28
   301
krh@28
   302
	if (rpmdbOpen("", &db, O_RDONLY, 0644) != 0) {
krh@28
   303
		fprintf(stderr, "cannot open rpm database\n");
krh@28
   304
		exit(1);
krh@28
   305
	}
krh@28
   306
krh@30
   307
	importer = razor_importer_new();
krh@28
   308
krh@28
   309
	iter = rpmdbInitIterator(db, 0, NULL, 0);
krh@28
   310
	while (h = rpmdbNextIterator(iter), h != NULL) {
krh@31
   311
		headerGetEntry(h, RPMTAG_NAME, &type, &name.p, &count);
krh@42
   312
		headerGetEntry(h, RPMTAG_VERSION, &type, &version.p, &count);
krh@31
   313
		headerGetEntry(h, RPMTAG_RELEASE, &type, &release.p, &count);
krh@31
   314
		razor_importer_begin_package(importer,
krh@31
   315
					     name.string, version.string);
krh@28
   316
krh@42
   317
		headerGetEntry(h, RPMTAG_REQUIRENAME, &type,
krh@42
   318
			       &property_names.p, &count);
krh@28
   319
		headerGetEntry(h, RPMTAG_REQUIREVERSION, &type,
krh@31
   320
			       &property_versions.p, &count);
krh@42
   321
		headerGetEntry(h, RPMTAG_REQUIREFLAGS, &type,
krh@42
   322
			       &property_flags.p, &count);
krh@28
   323
		for (i = 0; i < count; i++)
krh@30
   324
			razor_importer_add_requires(importer,
krh@42
   325
						    property_names.list[i],
krh@31
   326
						    property_versions.list[i]);
krh@28
   327
krh@42
   328
		headerGetEntry(h, RPMTAG_PROVIDENAME, &type,
krh@42
   329
			       &property_names.p, &count);
krh@28
   330
		headerGetEntry(h, RPMTAG_PROVIDEVERSION, &type,
krh@31
   331
			       &property_versions.p, &count);
krh@28
   332
		for (i = 0; i < count; i++)
krh@30
   333
			razor_importer_add_provides(importer,
krh@42
   334
						    property_names.list[i],
krh@31
   335
						    property_versions.list[i]);
krh@28
   336
krh@30
   337
		razor_importer_finish_package(importer);
krh@28
   338
	}
krh@28
   339
krh@28
   340
	rpmdbClose(db);
krh@28
   341
krh@30
   342
	return razor_importer_finish(importer);
krh@28
   343
}