#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
-
+#include <dirent.h>
#include <curl/curl.h>
#include "razor.h"
}
static int
-command_dump_rpm(int argc, const char *argv[])
+command_import_rpms(int argc, const char *argv[])
{
- razor_rpm_dump(argv[0]);
+ DIR *dir;
+ struct dirent *de;
+ struct razor_importer *importer;
+ struct razor_set *set;
+ int len;
+ char filename[256];
+ const char *dirname = argv[0];
+
+ if (dirname == NULL) {
+ fprintf(stderr, "usage: razor import-rpms DIR\n");
+ return -1;
+ }
+
+ dir = opendir(dirname);
+ if (dir == NULL) {
+ fprintf(stderr, "couldn't read dir %s\n", dirname);
+ return -1;
+ }
+
+ importer = razor_importer_new();
+
+ while (de = readdir(dir), de != NULL) {
+ len = strlen(de->d_name);
+ if (len < 5 || strcmp(de->d_name + len - 4, ".rpm") != 0)
+ continue;
+ snprintf(filename, sizeof filename,
+ "%s/%s", dirname, de->d_name);
+ if (razor_importer_add_rpm(importer, filename)) {
+ fprintf(stderr, "couldn't import %s\n", filename);
+ break;
+ }
+ }
+
+ if (de != NULL) {
+ razor_importer_destroy(importer);
+ return -1;
+ }
+
+ set = razor_importer_finish(importer);
+
+ razor_set_write(set, repo_filename);
+ razor_set_destroy(set);
+ printf("wrote %s\n", repo_filename);
return 0;
}
} razor_commands[] = {
{ "list", "list all packages", command_list },
{ "list-requires", "list all requires for the given package", command_list_requires },
- { "list-provides", "list all provides for the give package", command_list_provides },
- { "list-obsoletes", "list all obsoletes for the give package", command_list_obsoletes },
- { "list-conflicts", "list all conflicts for the give package", command_list_conflicts },
+ { "list-provides", "list all provides for the given package", command_list_provides },
+ { "list-obsoletes", "list all obsoletes for the given package", command_list_obsoletes },
+ { "list-conflicts", "list all conflicts for the given package", command_list_conflicts },
{ "list-files", "list files for package set", command_list_files },
{ "list-file-packages", "list packages owning file", command_list_file_packages },
{ "list-package-files", "list files in package", command_list_package_files },
{ "what-requires", "list the packages that have the given requires", command_what_requires },
{ "what-provides", "list the packages that have the given provides", command_what_provides },
- { "import-yum", "import yum filelist.xml on stdin", command_import_yum },
+ { "import-yum", "import yum metadata files", command_import_yum },
{ "import-rpmdb", "import the system rpm database", command_import_rpmdb },
+ { "import-rpms", "import rpms from the given directory", command_import_rpms },
{ "validate", "validate a package set", command_validate },
{ "update", "update all or specified packages", command_update },
- { "diff", "show diff between two package sets", command_diff },
- { "dump", "dump rpm file contents", command_dump_rpm }
+ { "diff", "show diff between two package sets", command_diff }
};
static int
#include <arpa/inet.h>
#include <rpm/rpmlib.h>
+#include "razor.h"
+
#define RPM_LEAD_SIZE 96
struct rpm_lead {
int count;
};
+struct properties {
+ struct rpm_header_index *name;
+ struct rpm_header_index *version;
+ struct rpm_header_index *flags;
+};
+
+struct rpm {
+ struct rpm_header *signature;
+ struct rpm_header *header;
+
+ struct rpm_header_index *name;
+ struct rpm_header_index *version;
+ struct rpm_header_index *release;
+
+ struct rpm_header_index *dirnames;
+ struct rpm_header_index *dirindexes;
+ struct rpm_header_index *basenames;
+
+ struct properties provides;
+ struct properties requires;
+ struct properties obsoletes;
+ struct properties conflicts;
+
+ const char *pool;
+ void *map;
+ size_t size;
+};
+
#define ALIGN(value, base) (((value) + (base - 1)) & ~((base) - 1))
-static void dump_header(struct rpm_header *header)
+static void
+import_properties(struct razor_importer *importer,
+ struct properties *properties,
+ const char *pool, unsigned long type)
+{
+ const char *name, *version;
+ int i, count;
+
+ /* assert: count is the same for all arrays */
+
+ if (properties->name == NULL)
+ return;
+
+ count = ntohl(properties->name->count);
+ name = pool + ntohl(properties->name->offset);
+ version = pool + ntohl(properties->version->offset);
+ for (i = 0; i < count; i++) {
+ razor_importer_add_property(importer, name, version, type);
+ name += strlen(name) + 1;
+ version += strlen(version) + 1;
+ }
+}
+
+static void
+import_files(struct razor_importer *importer, struct rpm *rpm)
+{
+ const char *name, **dir;
+ unsigned long *index;
+ int i, count;
+ char buffer[256];
+
+ /* assert: count is the same for all arrays */
+
+ if (rpm->dirnames == NULL)
+ return;
+
+ count = ntohl(rpm->dirnames->count);
+ dir = calloc(count, sizeof *dir);
+ name = rpm->pool + ntohl(rpm->dirnames->offset);
+ for (i = 0; i < count; i++) {
+ dir[i] = name;
+ name += strlen(name) + 1;
+ }
+
+ count = ntohl(rpm->basenames->count);
+ index = (unsigned long *) (rpm->pool + ntohl(rpm->dirindexes->offset));
+ name = rpm->pool + ntohl(rpm->basenames->offset);
+ for (i = 0; i < count; i++) {
+ snprintf(buffer, sizeof buffer,
+ "%s%s", dir[ntohl(*index)], name);
+ razor_importer_add_file(importer, buffer);
+ name += strlen(name) + 1;
+ index++;
+ }
+}
+
+static int
+razor_rpm_open(struct rpm *rpm, const char *filename)
{
struct rpm_header_index *base, *index;
- int i, j, nindex, tag, offset, type, count;
- char *pool, *name;
+ struct stat buf;
+ int fd, nindex, hsize, i;
+
+ memset(rpm, 0, sizeof *rpm);
+ if (stat(filename, &buf) < 0) {
+ fprintf(stderr, "no such file %s (%m)\n", filename);
+ return -1;
+ }
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "couldn't open %s\n", filename);
+ return -1;
+ }
+ rpm->size = buf.st_size;
+ rpm->map = mmap(NULL, rpm->size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (rpm->map == MAP_FAILED) {
+ fprintf(stderr, "couldn't mmap %s\n", filename);
+ return -1;
+ }
+ close(fd);
- nindex = ntohl(header->nindex);
- printf("header index records: %d\n", nindex);
- printf("header storage size: %d\n", ntohl(header->hsize));
- base = (struct rpm_header_index *) (header + 1);
- pool = (void *) (header + 1) + nindex * sizeof *index;
+ rpm->signature = rpm->map + RPM_LEAD_SIZE;
+ nindex = ntohl(rpm->signature->nindex);
+ hsize = ntohl(rpm->signature->hsize);
+ rpm->header = (void *) (rpm->signature + 1) +
+ ALIGN(nindex * sizeof *index + hsize, 8);
+
+ nindex = ntohl(rpm->header->nindex);
+ base = (struct rpm_header_index *) (rpm->header + 1);
+ rpm->pool = (void *) base + nindex * sizeof *index;
- printf("headers:\n");
for (i = 0; i < nindex; i++) {
index = base + i;
- tag = ntohl(index->tag);
- offset = ntohl(index->offset);
- type = ntohl(index->type);
- count = ntohl(index->count);
- printf(" 0x%08x 0x%08x 0x%08x 0x%08x\n",
- tag, type, offset, count);
-
- switch (tag) {
+ switch (ntohl(index->tag)) {
case RPMTAG_NAME:
- name = "name";
+ rpm->name = index;
break;
case RPMTAG_VERSION:
- name = "version";
+ rpm->version = index;
break;
case RPMTAG_RELEASE:
- name = "release";
+ rpm->release = index;
break;
+
case RPMTAG_REQUIRENAME:
- name = "requires";
+ rpm->requires.name = index;
break;
- default:
- name = "unknown";
+ case RPMTAG_REQUIREVERSION:
+ rpm->requires.version = index;
+ break;
+ case RPMTAG_REQUIREFLAGS:
+ rpm->requires.flags = index;
+ break;
+
+ case RPMTAG_PROVIDENAME:
+ rpm->provides.name = index;
+ break;
+ case RPMTAG_PROVIDEVERSION:
+ rpm->provides.version = index;
+ break;
+ case RPMTAG_PROVIDEFLAGS:
+ rpm->provides.flags = index;
+ break;
+
+ case RPMTAG_OBSOLETENAME:
+ rpm->obsoletes.name = index;
+ break;
+ case RPMTAG_OBSOLETEVERSION:
+ rpm->obsoletes.version = index;
+ break;
+ case RPMTAG_OBSOLETEFLAGS:
+ rpm->obsoletes.flags = index;
+ break;
+
+ case RPMTAG_CONFLICTNAME:
+ rpm->conflicts.name = index;
+ break;
+ case RPMTAG_CONFLICTVERSION:
+ rpm->conflicts.version = index;
+ break;
+ case RPMTAG_CONFLICTFLAGS:
+ rpm->conflicts.flags = index;
break;
- }
- switch (type) {
- case RPM_STRING_TYPE:
- printf(" (%s %s)\n", name, pool + offset);
+ case RPMTAG_DIRINDEXES:
+ rpm->dirindexes = index;
+ break;
+ case RPMTAG_BASENAMES:
+ rpm->basenames = index;
break;
- case RPM_STRING_ARRAY_TYPE:
- printf(" (%s", name);
- for (j = 0; j < count; j++) {
- printf(" %s", pool + offset);
- offset += strlen(pool + offset) + 1;
- }
- printf(")\n");
+ case RPMTAG_DIRNAMES:
+ rpm->dirnames = index;
break;
}
}
+
+ return 0;
}
-void
-razor_rpm_dump(const char *filename)
+static int
+razor_rpm_close(struct rpm *rpm)
{
- struct stat buf;
- void *p;
- int fd, nindex, hsize;
- struct rpm_header *signature, *header;
- struct rpm_header_index *index;
+ return munmap(rpm->map, rpm->size);
+}
- if (stat(filename, &buf) < 0) {
- fprintf(stderr, "no such file %s\n", filename);
- return;
+int
+razor_importer_add_rpm(struct razor_importer *importer, const char *filename)
+{
+ struct rpm rpm;
+
+ if (razor_rpm_open(&rpm, filename) < 0) {
+ fprintf(stderr, "failed to open rpm %s (%m)\n", filename);
+ return -1;
}
- fd = open(filename, O_RDONLY);
- p = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- close(fd);
+ razor_importer_begin_package(importer,
+ rpm.pool + ntohl(rpm.name->offset),
+ rpm.pool + ntohl(rpm.version->offset));
- printf("%s: %ldkB\n", filename, buf.st_size / 1024);
- signature = p + RPM_LEAD_SIZE;
+ import_properties(importer, &rpm.requires,
+ rpm.pool, RAZOR_PROPERTY_REQUIRES);
+ import_properties(importer, &rpm.provides,
+ rpm.pool, RAZOR_PROPERTY_PROVIDES);
+ import_properties(importer, &rpm.conflicts,
+ rpm.pool, RAZOR_PROPERTY_CONFLICTS);
+ import_properties(importer, &rpm.obsoletes,
+ rpm.pool, RAZOR_PROPERTY_OBSOLETES);
+ import_files(importer, &rpm);
- nindex = ntohl(signature->nindex);
- hsize = ntohl(signature->hsize);
- header = (void *) (signature + 1) +
- ALIGN(nindex * sizeof *index + hsize, 8);
+ razor_importer_finish_package(importer);
- dump_header(signature);
- dump_header(header);
+ razor_rpm_close(&rpm);
- munmap(p, buf.st_size);
+ return 0;
}