Extend rpm dumper into an rpm importer.
authorKristian H?gsberg <krh@redhat.com>
Thu Nov 08 17:14:19 2007 -0500 (2007-11-08)
changeset 7593278d8ec39c
parent 74 f23a93d41f32
child 76 773e6a26707f
Extend rpm dumper into an rpm importer.
TODO
main.c
razor.c
razor.h
rpm.c
     1.1 --- a/TODO	Wed Nov 07 00:33:56 2007 -0500
     1.2 +++ b/TODO	Thu Nov 08 17:14:19 2007 -0500
     1.3 @@ -94,3 +94,5 @@
     1.4  
     1.5  - use hash tables for dirs when importing files to avoid qsorting all
     1.6    files in rawhide.
     1.7 +
     1.8 +- corner cases such as no files/properties in repo etc segfault.
     2.1 --- a/main.c	Wed Nov 07 00:33:56 2007 -0500
     2.2 +++ b/main.c	Thu Nov 08 17:14:19 2007 -0500
     2.3 @@ -5,7 +5,7 @@
     2.4  #include <sys/types.h>
     2.5  #include <sys/stat.h>
     2.6  #include <unistd.h>
     2.7 -
     2.8 +#include <dirent.h>
     2.9  #include <curl/curl.h>
    2.10  #include "razor.h"
    2.11  
    2.12 @@ -292,9 +292,51 @@
    2.13  }
    2.14  
    2.15  static int
    2.16 -command_dump_rpm(int argc, const char *argv[])
    2.17 +command_import_rpms(int argc, const char *argv[])
    2.18  {
    2.19 -	razor_rpm_dump(argv[0]);
    2.20 +	DIR *dir;
    2.21 +	struct dirent *de;
    2.22 +	struct razor_importer *importer;
    2.23 +	struct razor_set *set;
    2.24 +	int len;
    2.25 +	char filename[256];
    2.26 +	const char *dirname = argv[0];
    2.27 +
    2.28 +	if (dirname == NULL) {
    2.29 +		fprintf(stderr, "usage: razor import-rpms DIR\n");
    2.30 +		return -1;
    2.31 +	}
    2.32 +
    2.33 +	dir = opendir(dirname);
    2.34 +	if (dir == NULL) {
    2.35 +		fprintf(stderr, "couldn't read dir %s\n", dirname);
    2.36 +		return -1;
    2.37 +	}
    2.38 +
    2.39 +	importer = razor_importer_new();
    2.40 +
    2.41 +	while (de = readdir(dir), de != NULL) {
    2.42 +		len = strlen(de->d_name);
    2.43 +		if (len < 5 || strcmp(de->d_name + len - 4, ".rpm") != 0)
    2.44 +		    continue;
    2.45 +		snprintf(filename, sizeof filename,
    2.46 +			 "%s/%s", dirname, de->d_name);
    2.47 +		if (razor_importer_add_rpm(importer, filename)) {
    2.48 +			fprintf(stderr, "couldn't import %s\n", filename);
    2.49 +			break;
    2.50 +		}
    2.51 +	}
    2.52 +
    2.53 +	if (de != NULL) {
    2.54 +		razor_importer_destroy(importer);
    2.55 +		return -1;
    2.56 +	}
    2.57 +
    2.58 +	set = razor_importer_finish(importer);
    2.59 +
    2.60 +	razor_set_write(set, repo_filename);
    2.61 +	razor_set_destroy(set);
    2.62 +	printf("wrote %s\n", repo_filename);
    2.63  
    2.64  	return 0;
    2.65  }
    2.66 @@ -306,20 +348,20 @@
    2.67  } razor_commands[] = {
    2.68  	{ "list", "list all packages", command_list },
    2.69  	{ "list-requires", "list all requires for the given package", command_list_requires },
    2.70 -	{ "list-provides", "list all provides for the give package", command_list_provides },
    2.71 -	{ "list-obsoletes", "list all obsoletes for the give package", command_list_obsoletes },
    2.72 -	{ "list-conflicts", "list all conflicts for the give package", command_list_conflicts },
    2.73 +	{ "list-provides", "list all provides for the given package", command_list_provides },
    2.74 +	{ "list-obsoletes", "list all obsoletes for the given package", command_list_obsoletes },
    2.75 +	{ "list-conflicts", "list all conflicts for the given package", command_list_conflicts },
    2.76  	{ "list-files", "list files for package set", command_list_files },
    2.77  	{ "list-file-packages", "list packages owning file", command_list_file_packages },
    2.78  	{ "list-package-files", "list files in package", command_list_package_files },
    2.79  	{ "what-requires", "list the packages that have the given requires", command_what_requires },
    2.80  	{ "what-provides", "list the packages that have the given provides", command_what_provides },
    2.81 -	{ "import-yum", "import yum filelist.xml on stdin", command_import_yum },
    2.82 +	{ "import-yum", "import yum metadata files", command_import_yum },
    2.83  	{ "import-rpmdb", "import the system rpm database", command_import_rpmdb },
    2.84 +	{ "import-rpms", "import rpms from the given directory", command_import_rpms },
    2.85  	{ "validate", "validate a package set", command_validate },
    2.86  	{ "update", "update all or specified packages", command_update },
    2.87 -	{ "diff", "show diff between two package sets", command_diff },
    2.88 -	{ "dump", "dump rpm file contents", command_dump_rpm }
    2.89 +	{ "diff", "show diff between two package sets", command_diff }
    2.90  };
    2.91  
    2.92  static int
     3.1 --- a/razor.c	Wed Nov 07 00:33:56 2007 -0500
     3.2 +++ b/razor.c	Thu Nov 08 17:14:19 2007 -0500
     3.3 @@ -470,6 +470,14 @@
     3.4  	return importer;
     3.5  }
     3.6  
     3.7 +/* Destroy an importer without creating the set. */
     3.8 +void
     3.9 +razor_importer_destroy(struct razor_importer *importer)
    3.10 +{
    3.11 +	/* FIXME: write this */
    3.12 +}
    3.13 +
    3.14 +
    3.15  typedef int (*compare_with_data_func_t)(const void *p1,
    3.16  					const void *p,
    3.17  					void *data);
    3.18 @@ -551,6 +559,9 @@
    3.19  	unsigned long *map;
    3.20  	int i;
    3.21  
    3.22 +	if (nelem == 0)
    3.23 +		return NULL;
    3.24 +
    3.25  	ctx.size = size;
    3.26  	ctx.compare = compare;
    3.27  	ctx.data = data;
     4.1 --- a/razor.h	Wed Nov 07 00:33:56 2007 -0500
     4.2 +++ b/razor.h	Thu Nov 08 17:14:19 2007 -0500
     4.3 @@ -47,6 +47,7 @@
     4.4  struct razor_importer;
     4.5  
     4.6  struct razor_importer *razor_importer_new(void);
     4.7 +void razor_importer_destroy(struct razor_importer *importer);
     4.8  void razor_importer_begin_package(struct razor_importer *importer,
     4.9  				const char *name, const char *version);
    4.10  void razor_importer_add_property(struct razor_importer *importer,
    4.11 @@ -55,6 +56,10 @@
    4.12  void razor_importer_add_file(struct razor_importer *importer,
    4.13  			     const char *name);
    4.14  void razor_importer_finish_package(struct razor_importer *importer);
    4.15 +
    4.16 +int razor_importer_add_rpm(struct razor_importer *importer,
    4.17 +			   const char *filename);
    4.18 +
    4.19  struct razor_set *razor_importer_finish(struct razor_importer *importer);
    4.20  
    4.21  struct razor_set *razor_import_rzr_files(int count, const char **files);
     5.1 --- a/rpm.c	Wed Nov 07 00:33:56 2007 -0500
     5.2 +++ b/rpm.c	Thu Nov 08 17:14:19 2007 -0500
     5.3 @@ -7,6 +7,8 @@
     5.4  #include <arpa/inet.h>
     5.5  #include <rpm/rpmlib.h>
     5.6  
     5.7 +#include "razor.h"
     5.8 +
     5.9  #define	RPM_LEAD_SIZE 96
    5.10  
    5.11  struct rpm_lead {
    5.12 @@ -35,92 +37,229 @@
    5.13  	int count;
    5.14  };
    5.15  
    5.16 +struct properties {
    5.17 +	struct rpm_header_index *name;
    5.18 +	struct rpm_header_index *version;
    5.19 +	struct rpm_header_index *flags;
    5.20 +};
    5.21 +
    5.22 +struct rpm {
    5.23 +	struct rpm_header *signature;
    5.24 +	struct rpm_header *header;
    5.25 +
    5.26 +	struct rpm_header_index *name;
    5.27 +	struct rpm_header_index *version;
    5.28 +	struct rpm_header_index *release;
    5.29 +
    5.30 +	struct rpm_header_index *dirnames;
    5.31 +	struct rpm_header_index *dirindexes;
    5.32 +	struct rpm_header_index *basenames;
    5.33 +
    5.34 +	struct properties provides;
    5.35 +	struct properties requires;
    5.36 +	struct properties obsoletes;
    5.37 +	struct properties conflicts;
    5.38 +
    5.39 +	const char *pool;
    5.40 +	void *map;
    5.41 +	size_t size;
    5.42 +};
    5.43 +
    5.44  #define ALIGN(value, base) (((value) + (base - 1)) & ~((base) - 1))
    5.45  
    5.46 -static void dump_header(struct rpm_header *header)
    5.47 +static void
    5.48 +import_properties(struct razor_importer *importer,
    5.49 +		  struct properties *properties,
    5.50 +		  const char *pool, unsigned long type)
    5.51 +{
    5.52 +	const char *name, *version;
    5.53 +	int i, count;
    5.54 +
    5.55 +	/* assert: count is the same for all arrays */
    5.56 +
    5.57 +	if (properties->name == NULL)
    5.58 +		return;
    5.59 +
    5.60 +	count = ntohl(properties->name->count);
    5.61 +	name = pool + ntohl(properties->name->offset);
    5.62 +	version = pool + ntohl(properties->version->offset);
    5.63 +	for (i = 0; i < count; i++) {
    5.64 +		razor_importer_add_property(importer, name, version, type);
    5.65 +		name += strlen(name) + 1;
    5.66 +		version += strlen(version) + 1;
    5.67 +	}
    5.68 +}
    5.69 +
    5.70 +static void
    5.71 +import_files(struct razor_importer *importer, struct rpm *rpm)
    5.72 +{
    5.73 +	const char *name, **dir;
    5.74 +	unsigned long *index;
    5.75 +	int i, count;
    5.76 +	char buffer[256];
    5.77 +
    5.78 +	/* assert: count is the same for all arrays */
    5.79 +
    5.80 +	if (rpm->dirnames == NULL)
    5.81 +		return;
    5.82 +
    5.83 +	count = ntohl(rpm->dirnames->count);
    5.84 +	dir = calloc(count, sizeof *dir);
    5.85 +	name = rpm->pool + ntohl(rpm->dirnames->offset);
    5.86 +	for (i = 0; i < count; i++) {
    5.87 +		dir[i] = name;
    5.88 +		name += strlen(name) + 1;
    5.89 +	}
    5.90 +
    5.91 +	count = ntohl(rpm->basenames->count);
    5.92 +	index = (unsigned long *) (rpm->pool + ntohl(rpm->dirindexes->offset));
    5.93 +	name = rpm->pool + ntohl(rpm->basenames->offset);
    5.94 +	for (i = 0; i < count; i++) {
    5.95 +		snprintf(buffer, sizeof buffer,
    5.96 +			 "%s%s", dir[ntohl(*index)], name);
    5.97 +		razor_importer_add_file(importer, buffer);
    5.98 +		name += strlen(name) + 1;
    5.99 +		index++;
   5.100 +	}
   5.101 +}
   5.102 +
   5.103 +static int
   5.104 +razor_rpm_open(struct rpm *rpm, const char *filename)
   5.105  {
   5.106  	struct rpm_header_index *base, *index;
   5.107 -	int i, j, nindex, tag, offset, type, count;
   5.108 -	char *pool, *name;
   5.109 +	struct stat buf;
   5.110 +	int fd, nindex, hsize, i;
   5.111  
   5.112 -	nindex = ntohl(header->nindex);
   5.113 -	printf("header index records: %d\n", nindex);
   5.114 -	printf("header storage size: %d\n", ntohl(header->hsize));
   5.115 -	base = (struct rpm_header_index *) (header + 1);
   5.116 -	pool = (void *) (header + 1) + nindex * sizeof *index;
   5.117 +	memset(rpm, 0, sizeof *rpm);
   5.118 +	if (stat(filename, &buf) < 0) {
   5.119 +		fprintf(stderr, "no such file %s (%m)\n", filename);
   5.120 +		return -1;
   5.121 +	}
   5.122  
   5.123 -	printf("headers:\n");
   5.124 +	fd = open(filename, O_RDONLY);
   5.125 +	if (fd < 0) {
   5.126 +		fprintf(stderr, "couldn't open %s\n", filename);
   5.127 +		return -1;
   5.128 +	}
   5.129 +	rpm->size = buf.st_size;
   5.130 +	rpm->map = mmap(NULL, rpm->size, PROT_READ, MAP_PRIVATE, fd, 0);
   5.131 +	if (rpm->map == MAP_FAILED) {
   5.132 +		fprintf(stderr, "couldn't mmap %s\n", filename);
   5.133 +		return -1;
   5.134 +	}
   5.135 +	close(fd);
   5.136 +
   5.137 +	rpm->signature = rpm->map + RPM_LEAD_SIZE;
   5.138 +	nindex = ntohl(rpm->signature->nindex);
   5.139 +	hsize = ntohl(rpm->signature->hsize);
   5.140 +	rpm->header = (void *) (rpm->signature + 1) +
   5.141 +		ALIGN(nindex * sizeof *index + hsize, 8);
   5.142 +
   5.143 +	nindex = ntohl(rpm->header->nindex);
   5.144 +	base = (struct rpm_header_index *) (rpm->header + 1);
   5.145 +	rpm->pool = (void *) base + nindex * sizeof *index;
   5.146 +
   5.147  	for (i = 0; i < nindex; i++) {
   5.148  		index = base + i;
   5.149 -		tag = ntohl(index->tag);
   5.150 -		offset = ntohl(index->offset);
   5.151 -		type = ntohl(index->type);
   5.152 -		count = ntohl(index->count);
   5.153 -		printf("  0x%08x 0x%08x 0x%08x 0x%08x\n",
   5.154 -		       tag, type, offset, count);
   5.155 -
   5.156 -		switch (tag) {
   5.157 +		switch (ntohl(index->tag)) {
   5.158  		case RPMTAG_NAME:
   5.159 -			name = "name";
   5.160 +			rpm->name = index;
   5.161  			break;
   5.162  		case RPMTAG_VERSION:
   5.163 -			name = "version";
   5.164 +			rpm->version = index;
   5.165  			break;
   5.166  		case RPMTAG_RELEASE:
   5.167 -			name = "release";
   5.168 +			rpm->release = index;
   5.169  			break;
   5.170 +
   5.171  		case RPMTAG_REQUIRENAME:
   5.172 -			name = "requires";
   5.173 +			rpm->requires.name = index;
   5.174  			break;
   5.175 -		default:
   5.176 -			name = "unknown";
   5.177 +		case RPMTAG_REQUIREVERSION:
   5.178 +			rpm->requires.version = index;
   5.179  			break;
   5.180 -		}
   5.181 +		case RPMTAG_REQUIREFLAGS:
   5.182 +			rpm->requires.flags = index;
   5.183 +			break;
   5.184  
   5.185 -		switch (type) {
   5.186 -		case RPM_STRING_TYPE:
   5.187 -			printf("    (%s %s)\n", name, pool + offset);
   5.188 +		case RPMTAG_PROVIDENAME:
   5.189 +			rpm->provides.name = index;
   5.190  			break;
   5.191 -		case RPM_STRING_ARRAY_TYPE:
   5.192 -			printf("    (%s", name);
   5.193 -			for (j = 0; j < count; j++) {
   5.194 -				printf(" %s", pool + offset);
   5.195 -				offset += strlen(pool + offset) + 1;
   5.196 -			}
   5.197 -			printf(")\n");
   5.198 +		case RPMTAG_PROVIDEVERSION:
   5.199 +			rpm->provides.version = index;
   5.200 +			break;
   5.201 +		case RPMTAG_PROVIDEFLAGS:
   5.202 +			rpm->provides.flags = index;
   5.203 +			break;
   5.204 +
   5.205 +		case RPMTAG_OBSOLETENAME:
   5.206 +			rpm->obsoletes.name = index;
   5.207 +			break;
   5.208 +		case RPMTAG_OBSOLETEVERSION:
   5.209 +			rpm->obsoletes.version = index;
   5.210 +			break;
   5.211 +		case RPMTAG_OBSOLETEFLAGS:
   5.212 +			rpm->obsoletes.flags = index;
   5.213 +			break;
   5.214 +
   5.215 +		case RPMTAG_CONFLICTNAME:
   5.216 +			rpm->conflicts.name = index;
   5.217 +			break;
   5.218 +		case RPMTAG_CONFLICTVERSION:
   5.219 +			rpm->conflicts.version = index;
   5.220 +			break;
   5.221 +		case RPMTAG_CONFLICTFLAGS:
   5.222 +			rpm->conflicts.flags = index;
   5.223 +			break;
   5.224 +
   5.225 +		case RPMTAG_DIRINDEXES:
   5.226 +			rpm->dirindexes = index;
   5.227 +			break;
   5.228 +		case RPMTAG_BASENAMES:
   5.229 +			rpm->basenames = index;
   5.230 +			break;
   5.231 +		case RPMTAG_DIRNAMES:
   5.232 +			rpm->dirnames = index;
   5.233  			break;
   5.234  		}
   5.235  	}
   5.236 +
   5.237 +	return 0;
   5.238  }
   5.239  
   5.240 -void
   5.241 -razor_rpm_dump(const char *filename)
   5.242 +static int
   5.243 +razor_rpm_close(struct rpm *rpm)
   5.244  {
   5.245 -	struct stat buf;
   5.246 -	void *p;
   5.247 -	int fd, nindex, hsize;
   5.248 -	struct rpm_header *signature, *header;
   5.249 -	struct rpm_header_index *index;
   5.250 +	return munmap(rpm->map, rpm->size);
   5.251 +}
   5.252  
   5.253 -	if (stat(filename, &buf) < 0) {
   5.254 -		fprintf(stderr, "no such file %s\n", filename);
   5.255 -		return;
   5.256 +int
   5.257 +razor_importer_add_rpm(struct razor_importer *importer, const char *filename)
   5.258 +{
   5.259 +	struct rpm rpm;
   5.260 +
   5.261 +	if (razor_rpm_open(&rpm, filename) < 0) {
   5.262 +		fprintf(stderr, "failed to open rpm %s (%m)\n", filename);
   5.263 +		return -1;
   5.264  	}
   5.265  
   5.266 -	fd = open(filename, O_RDONLY);
   5.267 -	p = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
   5.268 -	close(fd);
   5.269 +	razor_importer_begin_package(importer,
   5.270 +				     rpm.pool + ntohl(rpm.name->offset),
   5.271 +				     rpm.pool + ntohl(rpm.version->offset));
   5.272  
   5.273 -	printf("%s: %ldkB\n", filename, buf.st_size / 1024);
   5.274 -	signature = p + RPM_LEAD_SIZE;
   5.275 +	import_properties(importer, &rpm.requires,
   5.276 +			  rpm.pool, RAZOR_PROPERTY_REQUIRES);
   5.277 +	import_properties(importer, &rpm.provides,
   5.278 +			  rpm.pool, RAZOR_PROPERTY_PROVIDES);
   5.279 +	import_properties(importer, &rpm.conflicts,
   5.280 +			  rpm.pool, RAZOR_PROPERTY_CONFLICTS);
   5.281 +	import_properties(importer, &rpm.obsoletes,
   5.282 +			  rpm.pool, RAZOR_PROPERTY_OBSOLETES);
   5.283 +	import_files(importer, &rpm);
   5.284  
   5.285 -	nindex = ntohl(signature->nindex);
   5.286 -	hsize = ntohl(signature->hsize);
   5.287 -	header = (void *) (signature + 1) +
   5.288 -		ALIGN(nindex * sizeof *index + hsize, 8);
   5.289 +	razor_importer_finish_package(importer);
   5.290  
   5.291 -	dump_header(signature);
   5.292 -	dump_header(header);
   5.293 +	razor_rpm_close(&rpm);
   5.294  
   5.295 -	munmap(p, buf.st_size);
   5.296 +	return 0;
   5.297  }