summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO2
-rw-r--r--main.c60
-rw-r--r--razor.c11
-rw-r--r--razor.h5
-rw-r--r--rpm.c251
5 files changed, 264 insertions, 65 deletions
diff --git a/TODO b/TODO
index 746d240..69c8175 100644
--- a/TODO
+++ b/TODO
@@ -94,3 +94,5 @@ Misc ideas:
- use hash tables for dirs when importing files to avoid qsorting all
files in rawhide.
+
+- corner cases such as no files/properties in repo etc segfault.
diff --git a/main.c b/main.c
index 00ce88a..5a47b5f 100644
--- a/main.c
+++ b/main.c
@@ -5,7 +5,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
-
+#include <dirent.h>
#include <curl/curl.h>
#include "razor.h"
@@ -292,9 +292,51 @@ command_diff(int argc, const char *argv[])
}
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;
}
@@ -306,20 +348,20 @@ static struct {
} 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
diff --git a/razor.c b/razor.c
index 8f90dcc..b6e25f6 100644
--- a/razor.c
+++ b/razor.c
@@ -470,6 +470,14 @@ razor_importer_new(void)
return importer;
}
+/* Destroy an importer without creating the set. */
+void
+razor_importer_destroy(struct razor_importer *importer)
+{
+ /* FIXME: write this */
+}
+
+
typedef int (*compare_with_data_func_t)(const void *p1,
const void *p,
void *data);
@@ -551,6 +559,9 @@ qsort_with_data(void *base, size_t nelem, size_t size,
unsigned long *map;
int i;
+ if (nelem == 0)
+ return NULL;
+
ctx.size = size;
ctx.compare = compare;
ctx.data = data;
diff --git a/razor.h b/razor.h
index 44872d6..17f6fef 100644
--- a/razor.h
+++ b/razor.h
@@ -47,6 +47,7 @@ razor_set_diff(struct razor_set *set, struct razor_set *upstream,
struct razor_importer;
struct razor_importer *razor_importer_new(void);
+void razor_importer_destroy(struct razor_importer *importer);
void razor_importer_begin_package(struct razor_importer *importer,
const char *name, const char *version);
void razor_importer_add_property(struct razor_importer *importer,
@@ -55,6 +56,10 @@ void razor_importer_add_property(struct razor_importer *importer,
void razor_importer_add_file(struct razor_importer *importer,
const char *name);
void razor_importer_finish_package(struct razor_importer *importer);
+
+int razor_importer_add_rpm(struct razor_importer *importer,
+ const char *filename);
+
struct razor_set *razor_importer_finish(struct razor_importer *importer);
struct razor_set *razor_import_rzr_files(int count, const char **files);
diff --git a/rpm.c b/rpm.c
index 4424fd1..614f957 100644
--- a/rpm.c
+++ b/rpm.c
@@ -7,6 +7,8 @@
#include <arpa/inet.h>
#include <rpm/rpmlib.h>
+#include "razor.h"
+
#define RPM_LEAD_SIZE 96
struct rpm_lead {
@@ -35,92 +37,229 @@ struct rpm_header_index {
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;
}