src/import-yum.c
author J. Ali Harlow <ali@juiblex.co.uk>
Sat Oct 04 18:12:58 2014 +0100 (2014-10-04)
changeset 454 56ff755c268c
parent 438 fab0b8a61dcb
child 455 df914f383f5c
permissions -rw-r--r--
Only export symbols starting with razor_ in dynamic library.

Apart from being good practice to avoid clashes with higher-level
libraries and the application, this also fixes an obscure bug: The
gnulib library is used both by librazor (the dynamic library) and
by razor (the executable). In doing so, we want to have two separate
copies of the library despite the code duplication this involves.
Without the explicit limit to export only razor_ symbols, the razor
executable under mingw64 was picking up the getopt_long function
from librazor and the optind variable from libgnu which meant that
it did not see optind changing. Hiding librazor's copy of getopt
causes the linker to find libgnu's copy and everything works.

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