Extend rpm dumper into an rpm importer.
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 }