1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/yum.c Fri Feb 29 11:53:15 2008 -0500
1.3 @@ -0,0 +1,312 @@
1.4 +#define _GNU_SOURCE
1.5 +
1.6 +#include <string.h>
1.7 +#include <stdio.h>
1.8 +#include <sys/stat.h>
1.9 +#include <sys/mman.h>
1.10 +#include <unistd.h>
1.11 +#include <fcntl.h>
1.12 +#include <errno.h>
1.13 +
1.14 +#include <expat.h>
1.15 +#include <zlib.h>
1.16 +#include "razor.h"
1.17 +
1.18 +/* Import a yum filelist as a razor package set. */
1.19 +
1.20 +enum {
1.21 + YUM_STATE_BEGIN,
1.22 + YUM_STATE_PACKAGE_NAME,
1.23 + YUM_STATE_CHECKSUM,
1.24 + YUM_STATE_REQUIRES,
1.25 + YUM_STATE_PROVIDES,
1.26 + YUM_STATE_OBSOLETES,
1.27 + YUM_STATE_CONFLICTS,
1.28 + YUM_STATE_FILE
1.29 +};
1.30 +
1.31 +struct yum_context {
1.32 + XML_Parser primary_parser;
1.33 + XML_Parser filelists_parser;
1.34 + XML_Parser current_parser;
1.35 +
1.36 + struct razor_importer *importer;
1.37 + struct import_property_context *current_property_context;
1.38 + char name[256], buffer[512], *p;
1.39 + char pkgid[128];
1.40 + int state;
1.41 +};
1.42 +
1.43 +static enum razor_version_relation
1.44 +yum_to_razor_flags (const char *flags)
1.45 +{
1.46 + /* FIXME? */
1.47 + if (!flags)
1.48 + return RAZOR_VERSION_EQUAL;
1.49 +
1.50 + if (flags[0] == 'L') {
1.51 + if (flags[1] == 'T')
1.52 + return RAZOR_VERSION_LESS;
1.53 + else
1.54 + return RAZOR_VERSION_LESS_OR_EQUAL;
1.55 + } else if (flags[0] == 'G') {
1.56 + if (flags[1] == 'T')
1.57 + return RAZOR_VERSION_GREATER;
1.58 + else
1.59 + return RAZOR_VERSION_GREATER_OR_EQUAL;
1.60 + } else
1.61 + return RAZOR_VERSION_EQUAL;
1.62 +}
1.63 +
1.64 +static void
1.65 +yum_primary_start_element(void *data, const char *name, const char **atts)
1.66 +{
1.67 + struct yum_context *ctx = data;
1.68 + const char *n, *version, *release, *flags;
1.69 + char buffer[128];
1.70 + int i;
1.71 +
1.72 + if (strcmp(name, "name") == 0) {
1.73 + ctx->state = YUM_STATE_PACKAGE_NAME;
1.74 + ctx->p = ctx->name;
1.75 + } else if (strcmp(name, "version") == 0) {
1.76 + version = NULL;
1.77 + release = NULL;
1.78 + for (i = 0; atts[i]; i += 2) {
1.79 + if (strcmp(atts[i], "ver") == 0)
1.80 + version = atts[i + 1];
1.81 + else if (strcmp(atts[i], "rel") == 0)
1.82 + release = atts[i + 1];
1.83 + }
1.84 + if (version == NULL || release == NULL) {
1.85 + fprintf(stderr, "invalid version tag, "
1.86 + "missing version or release attribute\n");
1.87 + return;
1.88 + }
1.89 +
1.90 + snprintf(buffer, sizeof buffer, "%s-%s", version, release);
1.91 + razor_importer_begin_package(ctx->importer, ctx->name, buffer);
1.92 + } else if (strcmp(name, "checksum") == 0) {
1.93 + ctx->p = ctx->pkgid;
1.94 + ctx->state = YUM_STATE_CHECKSUM;
1.95 + } else if (strcmp(name, "rpm:requires") == 0) {
1.96 + ctx->state = YUM_STATE_REQUIRES;
1.97 + } else if (strcmp(name, "rpm:provides") == 0) {
1.98 + ctx->state = YUM_STATE_PROVIDES;
1.99 + } else if (strcmp(name, "rpm:obsoletes") == 0) {
1.100 + ctx->state = YUM_STATE_OBSOLETES;
1.101 + } else if (strcmp(name, "rpm:conflicts") == 0) {
1.102 + ctx->state = YUM_STATE_CONFLICTS;
1.103 + } else if (strcmp(name, "rpm:entry") == 0 &&
1.104 + ctx->state != YUM_STATE_BEGIN) {
1.105 + n = NULL;
1.106 + version = NULL;
1.107 + release = NULL;
1.108 + flags = NULL;
1.109 + for (i = 0; atts[i]; i += 2) {
1.110 + if (strcmp(atts[i], "name") == 0)
1.111 + n = atts[i + 1];
1.112 + else if (strcmp(atts[i], "ver") == 0)
1.113 + version = atts[i + 1];
1.114 + else if (strcmp(atts[i], "rel") == 0)
1.115 + release = atts[i + 1];
1.116 + else if (strcmp(atts[i], "flags") == 0)
1.117 + flags = atts[i + 1];
1.118 + }
1.119 +
1.120 + if (n == NULL) {
1.121 + fprintf(stderr, "invalid rpm:entry, "
1.122 + "missing name or version attributes\n");
1.123 + return;
1.124 + }
1.125 +
1.126 + if (version && release)
1.127 + snprintf(buffer, sizeof buffer,
1.128 + "%s-%s", version, release);
1.129 + else if (version)
1.130 + strcpy(buffer, version);
1.131 + else
1.132 + buffer[0] = '\0';
1.133 +
1.134 + switch (ctx->state) {
1.135 + case YUM_STATE_REQUIRES:
1.136 + razor_importer_add_property(ctx->importer, n,
1.137 + yum_to_razor_flags (flags),
1.138 + buffer,
1.139 + RAZOR_PROPERTY_REQUIRES);
1.140 + break;
1.141 + case YUM_STATE_PROVIDES:
1.142 + razor_importer_add_property(ctx->importer, n,
1.143 + yum_to_razor_flags (flags),
1.144 + buffer,
1.145 + RAZOR_PROPERTY_PROVIDES);
1.146 + break;
1.147 + case YUM_STATE_OBSOLETES:
1.148 + razor_importer_add_property(ctx->importer, n,
1.149 + yum_to_razor_flags (flags),
1.150 + buffer,
1.151 + RAZOR_PROPERTY_OBSOLETES);
1.152 + break;
1.153 + case YUM_STATE_CONFLICTS:
1.154 + razor_importer_add_property(ctx->importer, n,
1.155 + yum_to_razor_flags (flags),
1.156 + buffer,
1.157 + RAZOR_PROPERTY_CONFLICTS);
1.158 + break;
1.159 + }
1.160 + }
1.161 +}
1.162 +
1.163 +static void
1.164 +yum_primary_end_element (void *data, const char *name)
1.165 +{
1.166 + struct yum_context *ctx = data;
1.167 +
1.168 + switch (ctx->state) {
1.169 + case YUM_STATE_PACKAGE_NAME:
1.170 + case YUM_STATE_CHECKSUM:
1.171 + case YUM_STATE_FILE:
1.172 + ctx->state = YUM_STATE_BEGIN;
1.173 + break;
1.174 + }
1.175 +
1.176 + if (strcmp(name, "package") == 0) {
1.177 + XML_StopParser(ctx->current_parser, XML_TRUE);
1.178 + ctx->current_parser = ctx->filelists_parser;
1.179 + }
1.180 +}
1.181 +
1.182 +static void
1.183 +yum_character_data (void *data, const XML_Char *s, int len)
1.184 +{
1.185 + struct yum_context *ctx = data;
1.186 +
1.187 + switch (ctx->state) {
1.188 + case YUM_STATE_PACKAGE_NAME:
1.189 + case YUM_STATE_CHECKSUM:
1.190 + case YUM_STATE_FILE:
1.191 + memcpy(ctx->p, s, len);
1.192 + ctx->p += len;
1.193 + *ctx->p = '\0';
1.194 + break;
1.195 + }
1.196 +}
1.197 +
1.198 +static void
1.199 +yum_filelists_start_element(void *data, const char *name, const char **atts)
1.200 +{
1.201 + struct yum_context *ctx = data;
1.202 + const char *pkg, *pkgid;
1.203 + int i;
1.204 +
1.205 + if (strcmp(name, "package") == 0) {
1.206 + pkg = NULL;
1.207 + pkgid = NULL;
1.208 + for (i = 0; atts[i]; i += 2) {
1.209 + if (strcmp(atts[i], "name") == 0)
1.210 + pkg = atts[i + 1];
1.211 + else if (strcmp(atts[i], "pkgid") == 0)
1.212 + pkgid = atts[i + 1];
1.213 + }
1.214 + if (strcmp(pkgid, ctx->pkgid) != 0)
1.215 + fprintf(stderr, "primary.xml and filelists.xml "
1.216 + "mismatch for %s: %s vs %s",
1.217 + pkg, pkgid, ctx->pkgid);
1.218 + } else if (strcmp(name, "file") == 0) {
1.219 + ctx->state = YUM_STATE_FILE;
1.220 + ctx->p = ctx->buffer;
1.221 + }
1.222 +}
1.223 +
1.224 +
1.225 +static void
1.226 +yum_filelists_end_element (void *data, const char *name)
1.227 +{
1.228 + struct yum_context *ctx = data;
1.229 +
1.230 + ctx->state = YUM_STATE_BEGIN;
1.231 + if (strcmp(name, "package") == 0) {
1.232 + XML_StopParser(ctx->current_parser, XML_TRUE);
1.233 + ctx->current_parser = ctx->primary_parser;
1.234 + razor_importer_finish_package(ctx->importer);
1.235 + } else if (strcmp(name, "file") == 0)
1.236 + razor_importer_add_file(ctx->importer, ctx->buffer);
1.237 +
1.238 +}
1.239 +
1.240 +#define XML_BUFFER_SIZE 4096
1.241 +
1.242 +struct razor_set *
1.243 +razor_set_create_from_yum(void)
1.244 +{
1.245 + struct yum_context ctx;
1.246 + void *buf;
1.247 + int len, ret;
1.248 + gzFile primary, filelists;
1.249 + XML_ParsingStatus status;
1.250 +
1.251 + ctx.importer = razor_importer_new();
1.252 + ctx.state = YUM_STATE_BEGIN;
1.253 +
1.254 + ctx.primary_parser = XML_ParserCreate(NULL);
1.255 + XML_SetUserData(ctx.primary_parser, &ctx);
1.256 + XML_SetElementHandler(ctx.primary_parser,
1.257 + yum_primary_start_element,
1.258 + yum_primary_end_element);
1.259 + XML_SetCharacterDataHandler(ctx.primary_parser,
1.260 + yum_character_data);
1.261 +
1.262 + ctx.filelists_parser = XML_ParserCreate(NULL);
1.263 + XML_SetUserData(ctx.filelists_parser, &ctx);
1.264 + XML_SetElementHandler(ctx.filelists_parser,
1.265 + yum_filelists_start_element,
1.266 + yum_filelists_end_element);
1.267 + XML_SetCharacterDataHandler(ctx.filelists_parser,
1.268 + yum_character_data);
1.269 +
1.270 + primary = gzopen("primary.xml.gz", "rb");
1.271 + if (primary == NULL)
1.272 + return NULL;
1.273 + filelists = gzopen("filelists.xml.gz", "rb");
1.274 + if (filelists == NULL)
1.275 + return NULL;
1.276 +
1.277 + ctx.current_parser = ctx.primary_parser;
1.278 +
1.279 + do {
1.280 + XML_GetParsingStatus(ctx.current_parser, &status);
1.281 + switch (status.parsing) {
1.282 + case XML_SUSPENDED:
1.283 + ret = XML_ResumeParser(ctx.current_parser);
1.284 + break;
1.285 + case XML_PARSING:
1.286 + case XML_INITIALIZED:
1.287 + buf = XML_GetBuffer(ctx.current_parser,
1.288 + XML_BUFFER_SIZE);
1.289 + if (ctx.current_parser == ctx.primary_parser)
1.290 + len = gzread(primary, buf, XML_BUFFER_SIZE);
1.291 + else
1.292 + len = gzread(filelists, buf, XML_BUFFER_SIZE);
1.293 + if (len < 0) {
1.294 + fprintf(stderr,
1.295 + "couldn't read input: %s\n",
1.296 + strerror(errno));
1.297 + return NULL;
1.298 + }
1.299 +
1.300 + XML_ParseBuffer(ctx.current_parser, len, len == 0);
1.301 + break;
1.302 + case XML_FINISHED:
1.303 + break;
1.304 + }
1.305 + } while (status.parsing != XML_FINISHED);
1.306 +
1.307 +
1.308 + XML_ParserFree(ctx.primary_parser);
1.309 + XML_ParserFree(ctx.filelists_parser);
1.310 +
1.311 + gzclose(primary);
1.312 + gzclose(filelists);
1.313 +
1.314 + return razor_importer_finish(ctx.importer);
1.315 +}