rpm.c
changeset 75 93278d8ec39c
parent 74 f23a93d41f32
child 77 3d14834c56ea
     1.1 --- a/rpm.c	Wed Nov 07 00:33:56 2007 -0500
     1.2 +++ b/rpm.c	Thu Nov 08 17:14:19 2007 -0500
     1.3 @@ -7,6 +7,8 @@
     1.4  #include <arpa/inet.h>
     1.5  #include <rpm/rpmlib.h>
     1.6  
     1.7 +#include "razor.h"
     1.8 +
     1.9  #define	RPM_LEAD_SIZE 96
    1.10  
    1.11  struct rpm_lead {
    1.12 @@ -35,92 +37,229 @@
    1.13  	int count;
    1.14  };
    1.15  
    1.16 +struct properties {
    1.17 +	struct rpm_header_index *name;
    1.18 +	struct rpm_header_index *version;
    1.19 +	struct rpm_header_index *flags;
    1.20 +};
    1.21 +
    1.22 +struct rpm {
    1.23 +	struct rpm_header *signature;
    1.24 +	struct rpm_header *header;
    1.25 +
    1.26 +	struct rpm_header_index *name;
    1.27 +	struct rpm_header_index *version;
    1.28 +	struct rpm_header_index *release;
    1.29 +
    1.30 +	struct rpm_header_index *dirnames;
    1.31 +	struct rpm_header_index *dirindexes;
    1.32 +	struct rpm_header_index *basenames;
    1.33 +
    1.34 +	struct properties provides;
    1.35 +	struct properties requires;
    1.36 +	struct properties obsoletes;
    1.37 +	struct properties conflicts;
    1.38 +
    1.39 +	const char *pool;
    1.40 +	void *map;
    1.41 +	size_t size;
    1.42 +};
    1.43 +
    1.44  #define ALIGN(value, base) (((value) + (base - 1)) & ~((base) - 1))
    1.45  
    1.46 -static void dump_header(struct rpm_header *header)
    1.47 +static void
    1.48 +import_properties(struct razor_importer *importer,
    1.49 +		  struct properties *properties,
    1.50 +		  const char *pool, unsigned long type)
    1.51 +{
    1.52 +	const char *name, *version;
    1.53 +	int i, count;
    1.54 +
    1.55 +	/* assert: count is the same for all arrays */
    1.56 +
    1.57 +	if (properties->name == NULL)
    1.58 +		return;
    1.59 +
    1.60 +	count = ntohl(properties->name->count);
    1.61 +	name = pool + ntohl(properties->name->offset);
    1.62 +	version = pool + ntohl(properties->version->offset);
    1.63 +	for (i = 0; i < count; i++) {
    1.64 +		razor_importer_add_property(importer, name, version, type);
    1.65 +		name += strlen(name) + 1;
    1.66 +		version += strlen(version) + 1;
    1.67 +	}
    1.68 +}
    1.69 +
    1.70 +static void
    1.71 +import_files(struct razor_importer *importer, struct rpm *rpm)
    1.72 +{
    1.73 +	const char *name, **dir;
    1.74 +	unsigned long *index;
    1.75 +	int i, count;
    1.76 +	char buffer[256];
    1.77 +
    1.78 +	/* assert: count is the same for all arrays */
    1.79 +
    1.80 +	if (rpm->dirnames == NULL)
    1.81 +		return;
    1.82 +
    1.83 +	count = ntohl(rpm->dirnames->count);
    1.84 +	dir = calloc(count, sizeof *dir);
    1.85 +	name = rpm->pool + ntohl(rpm->dirnames->offset);
    1.86 +	for (i = 0; i < count; i++) {
    1.87 +		dir[i] = name;
    1.88 +		name += strlen(name) + 1;
    1.89 +	}
    1.90 +
    1.91 +	count = ntohl(rpm->basenames->count);
    1.92 +	index = (unsigned long *) (rpm->pool + ntohl(rpm->dirindexes->offset));
    1.93 +	name = rpm->pool + ntohl(rpm->basenames->offset);
    1.94 +	for (i = 0; i < count; i++) {
    1.95 +		snprintf(buffer, sizeof buffer,
    1.96 +			 "%s%s", dir[ntohl(*index)], name);
    1.97 +		razor_importer_add_file(importer, buffer);
    1.98 +		name += strlen(name) + 1;
    1.99 +		index++;
   1.100 +	}
   1.101 +}
   1.102 +
   1.103 +static int
   1.104 +razor_rpm_open(struct rpm *rpm, const char *filename)
   1.105  {
   1.106  	struct rpm_header_index *base, *index;
   1.107 -	int i, j, nindex, tag, offset, type, count;
   1.108 -	char *pool, *name;
   1.109 +	struct stat buf;
   1.110 +	int fd, nindex, hsize, i;
   1.111  
   1.112 -	nindex = ntohl(header->nindex);
   1.113 -	printf("header index records: %d\n", nindex);
   1.114 -	printf("header storage size: %d\n", ntohl(header->hsize));
   1.115 -	base = (struct rpm_header_index *) (header + 1);
   1.116 -	pool = (void *) (header + 1) + nindex * sizeof *index;
   1.117 +	memset(rpm, 0, sizeof *rpm);
   1.118 +	if (stat(filename, &buf) < 0) {
   1.119 +		fprintf(stderr, "no such file %s (%m)\n", filename);
   1.120 +		return -1;
   1.121 +	}
   1.122  
   1.123 -	printf("headers:\n");
   1.124 +	fd = open(filename, O_RDONLY);
   1.125 +	if (fd < 0) {
   1.126 +		fprintf(stderr, "couldn't open %s\n", filename);
   1.127 +		return -1;
   1.128 +	}
   1.129 +	rpm->size = buf.st_size;
   1.130 +	rpm->map = mmap(NULL, rpm->size, PROT_READ, MAP_PRIVATE, fd, 0);
   1.131 +	if (rpm->map == MAP_FAILED) {
   1.132 +		fprintf(stderr, "couldn't mmap %s\n", filename);
   1.133 +		return -1;
   1.134 +	}
   1.135 +	close(fd);
   1.136 +
   1.137 +	rpm->signature = rpm->map + RPM_LEAD_SIZE;
   1.138 +	nindex = ntohl(rpm->signature->nindex);
   1.139 +	hsize = ntohl(rpm->signature->hsize);
   1.140 +	rpm->header = (void *) (rpm->signature + 1) +
   1.141 +		ALIGN(nindex * sizeof *index + hsize, 8);
   1.142 +
   1.143 +	nindex = ntohl(rpm->header->nindex);
   1.144 +	base = (struct rpm_header_index *) (rpm->header + 1);
   1.145 +	rpm->pool = (void *) base + nindex * sizeof *index;
   1.146 +
   1.147  	for (i = 0; i < nindex; i++) {
   1.148  		index = base + i;
   1.149 -		tag = ntohl(index->tag);
   1.150 -		offset = ntohl(index->offset);
   1.151 -		type = ntohl(index->type);
   1.152 -		count = ntohl(index->count);
   1.153 -		printf("  0x%08x 0x%08x 0x%08x 0x%08x\n",
   1.154 -		       tag, type, offset, count);
   1.155 -
   1.156 -		switch (tag) {
   1.157 +		switch (ntohl(index->tag)) {
   1.158  		case RPMTAG_NAME:
   1.159 -			name = "name";
   1.160 +			rpm->name = index;
   1.161  			break;
   1.162  		case RPMTAG_VERSION:
   1.163 -			name = "version";
   1.164 +			rpm->version = index;
   1.165  			break;
   1.166  		case RPMTAG_RELEASE:
   1.167 -			name = "release";
   1.168 +			rpm->release = index;
   1.169  			break;
   1.170 +
   1.171  		case RPMTAG_REQUIRENAME:
   1.172 -			name = "requires";
   1.173 +			rpm->requires.name = index;
   1.174  			break;
   1.175 -		default:
   1.176 -			name = "unknown";
   1.177 +		case RPMTAG_REQUIREVERSION:
   1.178 +			rpm->requires.version = index;
   1.179  			break;
   1.180 -		}
   1.181 +		case RPMTAG_REQUIREFLAGS:
   1.182 +			rpm->requires.flags = index;
   1.183 +			break;
   1.184  
   1.185 -		switch (type) {
   1.186 -		case RPM_STRING_TYPE:
   1.187 -			printf("    (%s %s)\n", name, pool + offset);
   1.188 +		case RPMTAG_PROVIDENAME:
   1.189 +			rpm->provides.name = index;
   1.190  			break;
   1.191 -		case RPM_STRING_ARRAY_TYPE:
   1.192 -			printf("    (%s", name);
   1.193 -			for (j = 0; j < count; j++) {
   1.194 -				printf(" %s", pool + offset);
   1.195 -				offset += strlen(pool + offset) + 1;
   1.196 -			}
   1.197 -			printf(")\n");
   1.198 +		case RPMTAG_PROVIDEVERSION:
   1.199 +			rpm->provides.version = index;
   1.200 +			break;
   1.201 +		case RPMTAG_PROVIDEFLAGS:
   1.202 +			rpm->provides.flags = index;
   1.203 +			break;
   1.204 +
   1.205 +		case RPMTAG_OBSOLETENAME:
   1.206 +			rpm->obsoletes.name = index;
   1.207 +			break;
   1.208 +		case RPMTAG_OBSOLETEVERSION:
   1.209 +			rpm->obsoletes.version = index;
   1.210 +			break;
   1.211 +		case RPMTAG_OBSOLETEFLAGS:
   1.212 +			rpm->obsoletes.flags = index;
   1.213 +			break;
   1.214 +
   1.215 +		case RPMTAG_CONFLICTNAME:
   1.216 +			rpm->conflicts.name = index;
   1.217 +			break;
   1.218 +		case RPMTAG_CONFLICTVERSION:
   1.219 +			rpm->conflicts.version = index;
   1.220 +			break;
   1.221 +		case RPMTAG_CONFLICTFLAGS:
   1.222 +			rpm->conflicts.flags = index;
   1.223 +			break;
   1.224 +
   1.225 +		case RPMTAG_DIRINDEXES:
   1.226 +			rpm->dirindexes = index;
   1.227 +			break;
   1.228 +		case RPMTAG_BASENAMES:
   1.229 +			rpm->basenames = index;
   1.230 +			break;
   1.231 +		case RPMTAG_DIRNAMES:
   1.232 +			rpm->dirnames = index;
   1.233  			break;
   1.234  		}
   1.235  	}
   1.236 +
   1.237 +	return 0;
   1.238  }
   1.239  
   1.240 -void
   1.241 -razor_rpm_dump(const char *filename)
   1.242 +static int
   1.243 +razor_rpm_close(struct rpm *rpm)
   1.244  {
   1.245 -	struct stat buf;
   1.246 -	void *p;
   1.247 -	int fd, nindex, hsize;
   1.248 -	struct rpm_header *signature, *header;
   1.249 -	struct rpm_header_index *index;
   1.250 +	return munmap(rpm->map, rpm->size);
   1.251 +}
   1.252  
   1.253 -	if (stat(filename, &buf) < 0) {
   1.254 -		fprintf(stderr, "no such file %s\n", filename);
   1.255 -		return;
   1.256 +int
   1.257 +razor_importer_add_rpm(struct razor_importer *importer, const char *filename)
   1.258 +{
   1.259 +	struct rpm rpm;
   1.260 +
   1.261 +	if (razor_rpm_open(&rpm, filename) < 0) {
   1.262 +		fprintf(stderr, "failed to open rpm %s (%m)\n", filename);
   1.263 +		return -1;
   1.264  	}
   1.265  
   1.266 -	fd = open(filename, O_RDONLY);
   1.267 -	p = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
   1.268 -	close(fd);
   1.269 +	razor_importer_begin_package(importer,
   1.270 +				     rpm.pool + ntohl(rpm.name->offset),
   1.271 +				     rpm.pool + ntohl(rpm.version->offset));
   1.272  
   1.273 -	printf("%s: %ldkB\n", filename, buf.st_size / 1024);
   1.274 -	signature = p + RPM_LEAD_SIZE;
   1.275 +	import_properties(importer, &rpm.requires,
   1.276 +			  rpm.pool, RAZOR_PROPERTY_REQUIRES);
   1.277 +	import_properties(importer, &rpm.provides,
   1.278 +			  rpm.pool, RAZOR_PROPERTY_PROVIDES);
   1.279 +	import_properties(importer, &rpm.conflicts,
   1.280 +			  rpm.pool, RAZOR_PROPERTY_CONFLICTS);
   1.281 +	import_properties(importer, &rpm.obsoletes,
   1.282 +			  rpm.pool, RAZOR_PROPERTY_OBSOLETES);
   1.283 +	import_files(importer, &rpm);
   1.284  
   1.285 -	nindex = ntohl(signature->nindex);
   1.286 -	hsize = ntohl(signature->hsize);
   1.287 -	header = (void *) (signature + 1) +
   1.288 -		ALIGN(nindex * sizeof *index + hsize, 8);
   1.289 +	razor_importer_finish_package(importer);
   1.290  
   1.291 -	dump_header(signature);
   1.292 -	dump_header(header);
   1.293 +	razor_rpm_close(&rpm);
   1.294  
   1.295 -	munmap(p, buf.st_size);
   1.296 +	return 0;
   1.297  }