import.c
author Kristian H?gsberg <krh@redhat.com>
Tue Sep 18 15:02:04 2007 -0400 (2007-09-18)
changeset 27 5dbd81809d26
child 28 c8958f67afd8
permissions -rw-r--r--
Split importers to import.c.
     1 #define _GNU_SOURCE
     2 
     3 #include <string.h>
     4 #include <stdio.h>
     5 #include <sys/stat.h>
     6 #include <sys/mman.h>
     7 #include <unistd.h>
     8 #include <fcntl.h>
     9 #include <errno.h>
    10 
    11 #include <expat.h>
    12 #include "sha1.h"
    13 #include "razor.h"
    14 
    15 static void
    16 parse_package(struct import_context *ctx, const char **atts, void *data)
    17 {
    18 	const char *name = NULL, *version = NULL;
    19 	int i;
    20 
    21 	for (i = 0; atts[i]; i += 2) {
    22 		if (strcmp(atts[i], "name") == 0)
    23 			name = atts[i + 1];
    24 		else if (strcmp(atts[i], "version") == 0)
    25 			version = atts[i + 1];
    26 	}
    27 
    28 	if (name == NULL || version == NULL) {
    29 		fprintf(stderr, "invalid package tag, "
    30 			"missing name or version attributes\n");
    31 		return;
    32 	}
    33 
    34 	import_context_add_package(ctx, name, version);
    35 }
    36 
    37 static void
    38 parse_property(struct import_context *ctx, const char **atts, void *data)
    39 {
    40 	const char *name = NULL, *version = NULL;
    41 	int i;
    42 
    43 	for (i = 0; atts[i]; i += 2) {
    44 		if (strcmp(atts[i], "name") == 0)
    45 			name = atts[i + 1];
    46 		if (strcmp(atts[i], "version") == 0)
    47 			version = atts[i + 1];
    48 	}
    49 	
    50 	if (name == NULL) {
    51 		fprintf(stderr, "invalid tag, missing name attribute\n");
    52 		return;
    53 	}
    54 
    55 	import_context_add_property(ctx, data, name, version);
    56 }
    57 
    58 static void
    59 start_element(void *data, const char *name, const char **atts)
    60 {
    61 	struct import_context *ctx = data;
    62 
    63 	if (strcmp(name, "package") == 0)
    64 		parse_package(ctx, atts, NULL);
    65 	else if (strcmp(name, "requires") == 0)
    66 		parse_property(ctx, atts, &ctx->requires);
    67 	else if (strcmp(name, "provides") == 0)
    68 		parse_property(ctx, atts, &ctx->provides);
    69 }
    70 
    71 static void
    72 end_element (void *data, const char *name)
    73 {
    74 	struct import_context *ctx = data;
    75 
    76 	if (strcmp(name, "package") == 0)
    77 		import_context_finish_package(ctx);
    78 }
    79 
    80 static int
    81 import_rzr_file(struct import_context *ctx, const char *filename)
    82 {
    83 	SHA_CTX sha1;
    84 	XML_Parser parser;
    85 	int fd;
    86 	void *p;
    87 	struct stat stat;
    88 	unsigned char hash[20];
    89 
    90 	fd = open(filename, O_RDONLY);
    91 	if (fstat(fd, &stat) < 0)
    92 		return -1;
    93 	p = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    94 	if (p == MAP_FAILED)
    95 		return -1;
    96 
    97 	parser = XML_ParserCreate(NULL);
    98 	XML_SetUserData(parser, ctx);
    99 	XML_SetElementHandler(parser, start_element, end_element);
   100 	if (XML_Parse(parser, p, stat.st_size, 1) == XML_STATUS_ERROR) {
   101 		fprintf(stderr,
   102 			"%s at line %d, %s\n",
   103 			XML_ErrorString(XML_GetErrorCode(parser)),
   104 			XML_GetCurrentLineNumber(parser),
   105 			filename);
   106 		return 1;
   107 	}
   108 
   109 	XML_ParserFree(parser);
   110 
   111 	SHA1_Init(&sha1);
   112 	SHA1_Update(&sha1, p, stat.st_size);
   113 	SHA1_Final(hash, &sha1);
   114 
   115 	close(fd);
   116 
   117 	munmap(p, stat.st_size);
   118 
   119 	return 0;
   120 }
   121 
   122 struct razor_set *
   123 razor_import_rzr_files(int count, const char *files[])
   124 {
   125 	struct import_context ctx;
   126 	int i;
   127 
   128 	razor_prepare_import(&ctx);
   129 
   130 	for (i = 0; i < count; i++) {
   131 		if (import_rzr_file(&ctx, files[i]) < 0) {
   132 			fprintf(stderr, "failed to import %s\n", files[i]);
   133 			exit(-1);
   134 		}
   135 	}
   136 
   137 	return razor_finish_import(&ctx);
   138 }
   139 
   140 /* Import a yum filelist as a razor package set. */
   141 
   142 enum {
   143 	YUM_STATE_BEGIN,
   144 	YUM_STATE_PACKAGE_NAME
   145 };
   146 
   147 struct yum_context {
   148 	struct import_context ctx;
   149 	struct import_property_context *current_property_context;
   150 	char *name;
   151 	int state;
   152 };
   153 
   154 static void
   155 yum_start_element(void *data, const char *name, const char **atts)
   156 {
   157 	struct yum_context *ctx = data;
   158 	const char *n, *version;
   159 	int i;
   160 
   161 	if (strcmp(name, "name") == 0) {
   162 		ctx->state = YUM_STATE_PACKAGE_NAME;
   163 	} else if (strcmp(name, "version") == 0) {
   164 		version = NULL;
   165 		for (i = 0; atts[i]; i += 2) {
   166 			if (strcmp(atts[i], "ver") == 0)
   167 				version = atts[i + 1];
   168 		}
   169 		import_context_add_package(&ctx->ctx, ctx->name, version);
   170 	} else if (strcmp(name, "rpm:requires") == 0) {
   171 		ctx->current_property_context = &ctx->ctx.requires;
   172 	} else if (strcmp(name, "rpm:provides") == 0) {
   173 		ctx->current_property_context = &ctx->ctx.provides;
   174 	} else if (strcmp(name, "rpm:entry") == 0 &&
   175 		   ctx->current_property_context != NULL) {
   176 		n = NULL;
   177 		version = NULL;
   178 		for (i = 0; atts[i]; i += 2) {
   179 			if (strcmp(atts[i], "name") == 0)
   180 				n = atts[i + 1];
   181 			else if (strcmp(atts[i], "ver") == 0)
   182 				version = atts[i + 1];
   183 		}
   184 
   185 		if (n == NULL) {
   186 			fprintf(stderr, "invalid rpm:entry, "
   187 				"missing name or version attributes\n");
   188 			return;
   189 		}
   190 
   191 		import_context_add_property(&ctx->ctx,
   192 					    ctx->current_property_context,
   193 					    n, version);
   194 	}
   195 }
   196 
   197 static void
   198 yum_end_element (void *data, const char *name)
   199 {
   200 	struct yum_context *ctx = data;
   201 
   202 	if (strcmp(name, "package") == 0) {
   203 		free(ctx->name);
   204 		import_context_finish_package(&ctx->ctx);
   205 	} else if (strcmp(name, "name") == 0) {
   206 		ctx->state = 0;
   207 	} else if (strcmp(name, "rpm:requires") == 0) {
   208 		ctx->current_property_context = NULL;
   209 	} else if (strcmp(name, "rpm:provides") == 0) {
   210 		ctx->current_property_context = NULL;
   211 	}
   212 }
   213 
   214 static void
   215 yum_character_data (void *data, const XML_Char *s, int len)
   216 {
   217 	struct yum_context *ctx = data;
   218 
   219 	if (ctx->state == YUM_STATE_PACKAGE_NAME)
   220 		ctx->name = strndup(s, len);
   221 }
   222 
   223 struct razor_set *
   224 razor_set_create_from_yum_filelist(int fd)
   225 {
   226 	struct yum_context ctx;
   227 	XML_Parser parser;
   228 	char buf[4096];
   229 	int len;
   230 
   231 	razor_prepare_import(&ctx.ctx);
   232 
   233 	parser = XML_ParserCreate(NULL);
   234 	XML_SetUserData(parser, &ctx);
   235 	XML_SetElementHandler(parser, yum_start_element, yum_end_element);
   236 	XML_SetCharacterDataHandler(parser, yum_character_data);
   237 
   238 	while (1) {
   239 		len = read(fd, buf, sizeof buf);
   240 		if (len < 0) {
   241 			fprintf(stderr,
   242 				"couldn't read input: %s\n", strerror(errno));
   243 			return NULL;
   244 		} else if (len == 0)
   245 			break;
   246 
   247 		if (XML_Parse(parser, buf, len, 0) == XML_STATUS_ERROR) {
   248 			fprintf(stderr,
   249 				"%s at line %d\n",
   250 				XML_ErrorString(XML_GetErrorCode(parser)),
   251 				XML_GetCurrentLineNumber(parser));
   252 			return NULL;
   253 		}
   254 	}
   255 
   256 	XML_ParserFree(parser);
   257 
   258 	return razor_finish_import(&ctx.ctx);
   259 }