diff options
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | main.c | 60 | ||||
-rw-r--r-- | razor.c | 11 | ||||
-rw-r--r-- | razor.h | 5 | ||||
-rw-r--r-- | rpm.c | 251 |
5 files changed, 264 insertions, 65 deletions
@@ -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. @@ -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 @@ -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; @@ -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); @@ -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; } |