rpm.c
author Kristian H?gsberg <krh@redhat.com>
Thu Nov 08 22:36:16 2007 -0500 (2007-11-08)
changeset 76 773e6a26707f
parent 74 f23a93d41f32
child 77 3d14834c56ea
permissions -rw-r--r--
Drop support for half-baked rzr file idea.
krh@74
     1
#include <stdio.h>
krh@74
     2
#include <string.h>
krh@74
     3
#include <sys/stat.h>
krh@74
     4
#include <sys/mman.h>
krh@74
     5
#include <fcntl.h>
krh@74
     6
#include <unistd.h>
krh@74
     7
#include <arpa/inet.h>
krh@74
     8
#include <rpm/rpmlib.h>
krh@74
     9
krh@75
    10
#include "razor.h"
krh@75
    11
krh@74
    12
#define	RPM_LEAD_SIZE 96
krh@74
    13
krh@74
    14
struct rpm_lead {
krh@74
    15
	unsigned char magic[4];
krh@74
    16
	unsigned char major;
krh@74
    17
	unsigned char minor;
krh@74
    18
	short type;
krh@74
    19
	short archnum;
krh@74
    20
	char name[66];
krh@74
    21
	short osnum;
krh@74
    22
	short signature_type;
krh@74
    23
	char reserved[16];
krh@74
    24
};
krh@74
    25
krh@74
    26
struct rpm_header {
krh@74
    27
	unsigned char magic[4];
krh@74
    28
	unsigned char reserved[4];
krh@74
    29
	int nindex;
krh@74
    30
	int hsize;
krh@74
    31
};
krh@74
    32
krh@74
    33
struct rpm_header_index {
krh@74
    34
	int tag;
krh@74
    35
	int type;
krh@74
    36
	int offset;
krh@74
    37
	int count;
krh@74
    38
};
krh@74
    39
krh@75
    40
struct properties {
krh@75
    41
	struct rpm_header_index *name;
krh@75
    42
	struct rpm_header_index *version;
krh@75
    43
	struct rpm_header_index *flags;
krh@75
    44
};
krh@75
    45
krh@75
    46
struct rpm {
krh@75
    47
	struct rpm_header *signature;
krh@75
    48
	struct rpm_header *header;
krh@75
    49
krh@75
    50
	struct rpm_header_index *name;
krh@75
    51
	struct rpm_header_index *version;
krh@75
    52
	struct rpm_header_index *release;
krh@75
    53
krh@75
    54
	struct rpm_header_index *dirnames;
krh@75
    55
	struct rpm_header_index *dirindexes;
krh@75
    56
	struct rpm_header_index *basenames;
krh@75
    57
krh@75
    58
	struct properties provides;
krh@75
    59
	struct properties requires;
krh@75
    60
	struct properties obsoletes;
krh@75
    61
	struct properties conflicts;
krh@75
    62
krh@75
    63
	const char *pool;
krh@75
    64
	void *map;
krh@75
    65
	size_t size;
krh@75
    66
};
krh@75
    67
krh@74
    68
#define ALIGN(value, base) (((value) + (base - 1)) & ~((base) - 1))
krh@74
    69
krh@75
    70
static void
krh@75
    71
import_properties(struct razor_importer *importer,
krh@75
    72
		  struct properties *properties,
krh@75
    73
		  const char *pool, unsigned long type)
krh@75
    74
{
krh@75
    75
	const char *name, *version;
krh@75
    76
	int i, count;
krh@75
    77
krh@75
    78
	/* assert: count is the same for all arrays */
krh@75
    79
krh@75
    80
	if (properties->name == NULL)
krh@75
    81
		return;
krh@75
    82
krh@75
    83
	count = ntohl(properties->name->count);
krh@75
    84
	name = pool + ntohl(properties->name->offset);
krh@75
    85
	version = pool + ntohl(properties->version->offset);
krh@75
    86
	for (i = 0; i < count; i++) {
krh@75
    87
		razor_importer_add_property(importer, name, version, type);
krh@75
    88
		name += strlen(name) + 1;
krh@75
    89
		version += strlen(version) + 1;
krh@75
    90
	}
krh@75
    91
}
krh@75
    92
krh@75
    93
static void
krh@75
    94
import_files(struct razor_importer *importer, struct rpm *rpm)
krh@75
    95
{
krh@75
    96
	const char *name, **dir;
krh@75
    97
	unsigned long *index;
krh@75
    98
	int i, count;
krh@75
    99
	char buffer[256];
krh@75
   100
krh@75
   101
	/* assert: count is the same for all arrays */
krh@75
   102
krh@75
   103
	if (rpm->dirnames == NULL)
krh@75
   104
		return;
krh@75
   105
krh@75
   106
	count = ntohl(rpm->dirnames->count);
krh@75
   107
	dir = calloc(count, sizeof *dir);
krh@75
   108
	name = rpm->pool + ntohl(rpm->dirnames->offset);
krh@75
   109
	for (i = 0; i < count; i++) {
krh@75
   110
		dir[i] = name;
krh@75
   111
		name += strlen(name) + 1;
krh@75
   112
	}
krh@75
   113
krh@75
   114
	count = ntohl(rpm->basenames->count);
krh@75
   115
	index = (unsigned long *) (rpm->pool + ntohl(rpm->dirindexes->offset));
krh@75
   116
	name = rpm->pool + ntohl(rpm->basenames->offset);
krh@75
   117
	for (i = 0; i < count; i++) {
krh@75
   118
		snprintf(buffer, sizeof buffer,
krh@75
   119
			 "%s%s", dir[ntohl(*index)], name);
krh@75
   120
		razor_importer_add_file(importer, buffer);
krh@75
   121
		name += strlen(name) + 1;
krh@75
   122
		index++;
krh@75
   123
	}
krh@75
   124
}
krh@75
   125
krh@75
   126
static int
krh@75
   127
razor_rpm_open(struct rpm *rpm, const char *filename)
krh@74
   128
{
krh@74
   129
	struct rpm_header_index *base, *index;
krh@75
   130
	struct stat buf;
krh@75
   131
	int fd, nindex, hsize, i;
krh@74
   132
krh@75
   133
	memset(rpm, 0, sizeof *rpm);
krh@75
   134
	if (stat(filename, &buf) < 0) {
krh@75
   135
		fprintf(stderr, "no such file %s (%m)\n", filename);
krh@75
   136
		return -1;
krh@75
   137
	}
krh@74
   138
krh@75
   139
	fd = open(filename, O_RDONLY);
krh@75
   140
	if (fd < 0) {
krh@75
   141
		fprintf(stderr, "couldn't open %s\n", filename);
krh@75
   142
		return -1;
krh@75
   143
	}
krh@75
   144
	rpm->size = buf.st_size;
krh@75
   145
	rpm->map = mmap(NULL, rpm->size, PROT_READ, MAP_PRIVATE, fd, 0);
krh@75
   146
	if (rpm->map == MAP_FAILED) {
krh@75
   147
		fprintf(stderr, "couldn't mmap %s\n", filename);
krh@75
   148
		return -1;
krh@75
   149
	}
krh@75
   150
	close(fd);
krh@75
   151
krh@75
   152
	rpm->signature = rpm->map + RPM_LEAD_SIZE;
krh@75
   153
	nindex = ntohl(rpm->signature->nindex);
krh@75
   154
	hsize = ntohl(rpm->signature->hsize);
krh@75
   155
	rpm->header = (void *) (rpm->signature + 1) +
krh@75
   156
		ALIGN(nindex * sizeof *index + hsize, 8);
krh@75
   157
krh@75
   158
	nindex = ntohl(rpm->header->nindex);
krh@75
   159
	base = (struct rpm_header_index *) (rpm->header + 1);
krh@75
   160
	rpm->pool = (void *) base + nindex * sizeof *index;
krh@75
   161
krh@74
   162
	for (i = 0; i < nindex; i++) {
krh@74
   163
		index = base + i;
krh@75
   164
		switch (ntohl(index->tag)) {
krh@74
   165
		case RPMTAG_NAME:
krh@75
   166
			rpm->name = index;
krh@74
   167
			break;
krh@74
   168
		case RPMTAG_VERSION:
krh@75
   169
			rpm->version = index;
krh@74
   170
			break;
krh@74
   171
		case RPMTAG_RELEASE:
krh@75
   172
			rpm->release = index;
krh@74
   173
			break;
krh@75
   174
krh@74
   175
		case RPMTAG_REQUIRENAME:
krh@75
   176
			rpm->requires.name = index;
krh@74
   177
			break;
krh@75
   178
		case RPMTAG_REQUIREVERSION:
krh@75
   179
			rpm->requires.version = index;
krh@74
   180
			break;
krh@75
   181
		case RPMTAG_REQUIREFLAGS:
krh@75
   182
			rpm->requires.flags = index;
krh@75
   183
			break;
krh@74
   184
krh@75
   185
		case RPMTAG_PROVIDENAME:
krh@75
   186
			rpm->provides.name = index;
krh@74
   187
			break;
krh@75
   188
		case RPMTAG_PROVIDEVERSION:
krh@75
   189
			rpm->provides.version = index;
krh@75
   190
			break;
krh@75
   191
		case RPMTAG_PROVIDEFLAGS:
krh@75
   192
			rpm->provides.flags = index;
krh@75
   193
			break;
krh@75
   194
krh@75
   195
		case RPMTAG_OBSOLETENAME:
krh@75
   196
			rpm->obsoletes.name = index;
krh@75
   197
			break;
krh@75
   198
		case RPMTAG_OBSOLETEVERSION:
krh@75
   199
			rpm->obsoletes.version = index;
krh@75
   200
			break;
krh@75
   201
		case RPMTAG_OBSOLETEFLAGS:
krh@75
   202
			rpm->obsoletes.flags = index;
krh@75
   203
			break;
krh@75
   204
krh@75
   205
		case RPMTAG_CONFLICTNAME:
krh@75
   206
			rpm->conflicts.name = index;
krh@75
   207
			break;
krh@75
   208
		case RPMTAG_CONFLICTVERSION:
krh@75
   209
			rpm->conflicts.version = index;
krh@75
   210
			break;
krh@75
   211
		case RPMTAG_CONFLICTFLAGS:
krh@75
   212
			rpm->conflicts.flags = index;
krh@75
   213
			break;
krh@75
   214
krh@75
   215
		case RPMTAG_DIRINDEXES:
krh@75
   216
			rpm->dirindexes = index;
krh@75
   217
			break;
krh@75
   218
		case RPMTAG_BASENAMES:
krh@75
   219
			rpm->basenames = index;
krh@75
   220
			break;
krh@75
   221
		case RPMTAG_DIRNAMES:
krh@75
   222
			rpm->dirnames = index;
krh@74
   223
			break;
krh@74
   224
		}
krh@74
   225
	}
krh@75
   226
krh@75
   227
	return 0;
krh@74
   228
}
krh@74
   229
krh@75
   230
static int
krh@75
   231
razor_rpm_close(struct rpm *rpm)
krh@74
   232
{
krh@75
   233
	return munmap(rpm->map, rpm->size);
krh@75
   234
}
krh@74
   235
krh@75
   236
int
krh@75
   237
razor_importer_add_rpm(struct razor_importer *importer, const char *filename)
krh@75
   238
{
krh@75
   239
	struct rpm rpm;
krh@75
   240
krh@75
   241
	if (razor_rpm_open(&rpm, filename) < 0) {
krh@75
   242
		fprintf(stderr, "failed to open rpm %s (%m)\n", filename);
krh@75
   243
		return -1;
krh@74
   244
	}
krh@74
   245
krh@75
   246
	razor_importer_begin_package(importer,
krh@75
   247
				     rpm.pool + ntohl(rpm.name->offset),
krh@75
   248
				     rpm.pool + ntohl(rpm.version->offset));
krh@74
   249
krh@75
   250
	import_properties(importer, &rpm.requires,
krh@75
   251
			  rpm.pool, RAZOR_PROPERTY_REQUIRES);
krh@75
   252
	import_properties(importer, &rpm.provides,
krh@75
   253
			  rpm.pool, RAZOR_PROPERTY_PROVIDES);
krh@75
   254
	import_properties(importer, &rpm.conflicts,
krh@75
   255
			  rpm.pool, RAZOR_PROPERTY_CONFLICTS);
krh@75
   256
	import_properties(importer, &rpm.obsoletes,
krh@75
   257
			  rpm.pool, RAZOR_PROPERTY_OBSOLETES);
krh@75
   258
	import_files(importer, &rpm);
krh@74
   259
krh@75
   260
	razor_importer_finish_package(importer);
krh@74
   261
krh@75
   262
	razor_rpm_close(&rpm);
krh@74
   263
krh@75
   264
	return 0;
krh@74
   265
}