--- /dev/null
+ /*
+ * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
+ * Copyright (C) 2008 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+ #define _GNU_SOURCE
+
+ #include <string.h>
+ #include "razor-internal.h"
+ #include "razor.h"
+
+ void
+ razor_importer_begin_package(struct razor_importer *importer,
+ const char *name,
+ const char *version,
+ const char *arch)
+ {
+ struct razor_package *p;
+
+ p = array_add(&importer->set->packages, sizeof *p);
+ p->name = hashtable_tokenize(&importer->table, name);
+ p->flags = 0;
+ p->version = hashtable_tokenize(&importer->table, version);
+ p->arch = hashtable_tokenize(&importer->table, arch);
+
+ importer->package = p;
+ array_init(&importer->properties);
+ }
+
+
+ void
+ razor_importer_finish_package(struct razor_importer *importer)
+ {
+ list_set_array(&importer->package->properties,
+ &importer->set->property_pool,
+ &importer->properties,
+ 1);
+
+ array_release(&importer->properties);
+ }
+
+ void
++razor_importer_add_details(struct razor_importer *importer,
++ const char *summary,
++ const char *description,
++ const char *url,
++ const char *license)
++{
++ importer->package->summary = hashtable_tokenize(&importer->details_table, summary);
++ importer->package->description = hashtable_tokenize(&importer->details_table, description);
++ importer->package->url = hashtable_tokenize(&importer->details_table, url);
++ importer->package->license = hashtable_tokenize(&importer->details_table, license);
++}
++
++void
+ razor_importer_add_property(struct razor_importer *importer,
+ const char *name,
+ uint32_t flags,
+ const char *version)
+ {
+ struct razor_property *p;
+ uint32_t *r;
+
+ p = array_add(&importer->set->properties, sizeof *p);
+ p->name = hashtable_tokenize(&importer->table, name);
+ p->flags = flags;
+ p->version = hashtable_tokenize(&importer->table, version);
+ list_set_ptr(&p->packages, importer->package -
+ (struct razor_package *) importer->set->packages.data);
+
+ r = array_add(&importer->properties, sizeof *r);
+ *r = p - (struct razor_property *) importer->set->properties.data;
+
+ if (((flags & RAZOR_PROPERTY_TYPE_MASK) == RAZOR_PROPERTY_REQUIRES) &&
+ *name == '/') {
+ r = array_add(&importer->file_requires, sizeof *r);
+ *r = p->name;
+ }
+ }
+
+ void
+ razor_importer_add_file(struct razor_importer *importer, const char *name)
+ {
+ struct import_entry *e;
+
+ e = array_add(&importer->files, sizeof *e);
+
+ e->package = importer->package -
+ (struct razor_package *) importer->set->packages.data;
+ e->name = strdup(name);
+ }
+
+ struct razor_importer *
+ razor_importer_new(void)
+ {
+ struct razor_importer *importer;
+
+ importer = zalloc(sizeof *importer);
+ importer->set = razor_set_create();
+ hashtable_init(&importer->table, &importer->set->string_pool);
++ hashtable_init(&importer->details_table,
++ &importer->set->details_string_pool);
++ hashtable_init(&importer->file_table,
++ &importer->set->file_string_pool);
+
+ return importer;
+ }
+
+ /* Destroy an importer without creating the set. */
+ void
+ razor_importer_destroy(struct razor_importer *importer)
+ {
+ /* FIXME: write this */
+ }
+
+ static int
+ compare_packages(const void *p1, const void *p2, void *data)
+ {
+ const struct razor_package *pkg1 = p1, *pkg2 = p2;
+ struct razor_set *set = data;
+ char *pool = set->string_pool.data;
+
+ /* FIXME: what if the flags are different? */
+ if (pkg1->name == pkg2->name)
+ return razor_versioncmp(&pool[pkg1->version], &pool[pkg2->version]);
+ else
+ return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
+ }
+
+ static int
+ compare_properties(const void *p1, const void *p2, void *data)
+ {
+ const struct razor_property *prop1 = p1, *prop2 = p2;
+ struct razor_set *set = data;
+ char *pool = set->string_pool.data;
+
+ if (prop1->name != prop2->name)
+ return strcmp(&pool[prop1->name], &pool[prop2->name]);
+ else if (prop1->flags != prop2->flags)
+ return prop1->flags - prop2->flags;
+ else
+ return razor_versioncmp(&pool[prop1->version], &pool[prop2->version]);
+ }
+
+ static uint32_t *
+ uniqueify_properties(struct razor_set *set)
+ {
+ struct razor_property *rp, *up, *rp_end;
+ struct array *pkgs, *p;
+ struct list_head *r;
+ uint32_t *map, *rmap;
+ int i, count, unique;
+
+ count = set->properties.size / sizeof(struct razor_property);
+ map = razor_qsort_with_data(set->properties.data,
+ count,
+ sizeof(struct razor_property),
+ compare_properties,
+ set);
+
+ rp_end = set->properties.data + set->properties.size;
+ rmap = malloc(count * sizeof *map);
+ pkgs = zalloc(count * sizeof *pkgs);
+ for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
+ if (rp->name != up->name ||
+ rp->flags != up->flags ||
+ rp->version != up->version) {
+ up++;
+ up->name = rp->name;
+ up->flags = rp->flags;
+ up->version = rp->version;
+ }
+
+ unique = up - (struct razor_property *) set->properties.data;
+ rmap[map[i]] = unique;
+ r = array_add(&pkgs[unique], sizeof *r);
+ *r = rp->packages;
+ }
+ free(map);
+
+ if (up != rp)
+ up++;
+ set->properties.size = (void *) up - set->properties.data;
+ rp_end = up;
+ for (rp = set->properties.data, p = pkgs; rp < rp_end; rp++, p++) {
+ list_set_array(&rp->packages, &set->package_pool, p, 0);
+ array_release(p);
+ }
+
+ free(pkgs);
+
+ return rmap;
+ }
+
+ static int
+ compare_filenames(const void *p1, const void *p2, void *data)
+ {
+ const struct import_entry *e1 = p1;
+ const struct import_entry *e2 = p2;
+ const char *n1 = e1->name;
+ const char *n2 = e2->name;
+
+ /* Need to make sure that the contents of a directory
+ * are sorted immediately after it. So "foo/bar" has to
+ * sort before "foo.conf"
+ *
+ * FIXME: this is about 60% slower than strcmp
+ */
+ while (*n1 && *n2) {
+ if (*n1 < *n2)
+ return *n2 == '/' ? 1 : -1;
+ else if (*n1 > *n2)
+ return *n1 == '/' ? -1 : 1;
+ n1++;
+ n2++;
+ }
+ if (*n1)
+ return 1;
+ else if (*n2)
+ return -1;
+ else
+ return 0;
+ }
+
+ static void
+ count_entries(struct import_directory *d)
+ {
+ struct import_directory *p, *end;
+
+ p = d->files.data;
+ end = d->files.data + d->files.size;
+ d->count = 0;
+ while (p < end) {
+ count_entries(p);
+ d->count += p->count + 1;
+ p++;
+ }
+ }
+
+ static void
+ serialize_files(struct razor_set *set,
+ struct import_directory *d, struct array *array)
+ {
+ struct import_directory *p, *end;
+ struct razor_entry *e = NULL;
+ uint32_t s;
+
+ p = d->files.data;
+ end = d->files.data + d->files.size;
+ s = array->size / sizeof *e + d->files.size / sizeof *p;
+ while (p < end) {
+ e = array_add(array, sizeof *e);
+ e->name = p->name;
+ e->flags = 0;
+ e->start = p->count > 0 ? s : 0;
+ s += p->count;
+
+ list_set_array(&e->packages, &set->package_pool, &p->packages, 0);
+ array_release(&p->packages);
+ p++;
+ }
+ if (e != NULL)
+ e->flags |= RAZOR_ENTRY_LAST;
+
+ p = d->files.data;
+ end = d->files.data + d->files.size;
+ while (p < end) {
+ serialize_files(set, p, array);
+ p++;
+ }
+ }
+
+ static void
+ remap_property_package_links(struct array *properties, uint32_t *rmap)
+ {
+ struct razor_property *p, *end;
+
+ end = properties->data + properties->size;
+ for (p = properties->data; p < end; p++)
+ list_remap_head(&p->packages, rmap);
+ }
+
+ static void
+ build_file_tree(struct razor_importer *importer)
+ {
+ int count, i, length;
+ struct import_entry *filenames;
+ char *f, *end;
+ uint32_t name, *r;
+ char dirname[256];
+ struct import_directory *d, root;
+ struct razor_entry *e;
+
+ count = importer->files.size / sizeof (struct import_entry);
+ razor_qsort_with_data(importer->files.data,
+ count,
+ sizeof (struct import_entry),
+ compare_filenames,
+ NULL);
+
+ root.name = hashtable_tokenize(&importer->table, "");
+ array_init(&root.files);
+ array_init(&root.packages);
+ root.last = NULL;
+
+ filenames = importer->files.data;
+ for (i = 0; i < count; i++) {
+ f = filenames[i].name;
+ if (*f != '/')
+ continue;
+ f++;
+
+ d = &root;
+ while (*f) {
+ end = strchr(f, '/');
+ if (end == NULL)
+ end = f + strlen(f);
+ length = end - f;
+ memcpy(dirname, f, length);
+ dirname[length] ='\0';
+ name = hashtable_tokenize(&importer->table, dirname);
+ if (d->last == NULL || d->last->name != name) {
+ d->last = array_add(&d->files, sizeof *d);
+ d->last->name = name;
+ d->last->last = NULL;
+ array_init(&d->last->files);
+ array_init(&d->last->packages);
+ }
+ d = d->last;
+ f = end + 1;
+ if (*end == '\0')
+ break;
+ }
+
+ r = array_add(&d->packages, sizeof *r);
+ *r = filenames[i].package;
+ free(filenames[i].name);
+ }
+
+ count_entries(&root);
+ e = importer->set->files.data;
+ e->name = root.name;
+ e->flags = RAZOR_ENTRY_LAST;
+ e->start = importer->files.size ? 1 : 0;
+ list_set_empty(&e->packages);
+
+ serialize_files(importer->set, &root, &importer->set->files);
+
+ array_release(&importer->files);
+ }
+
+ static void
+ list_to_array(struct list *list, struct array *array)
+ {
+ uint32_t *item;
+
+ while (list) {
+ item = array_add(array, sizeof *item);
+ *item = list->data;
+ list = list_next(list);
+ }
+ }
+
+ static int
+ compare_file_requires(const void *p1, const void *p2, void *data)
+ {
+ uint32_t *f1 = (void *)p1, *f2 = (void *)p2;
+ const char *pool = data;
+
+ return strcmp(&pool[*f1], &pool[*f2]);
+ }
+
+ static void
+ find_file_provides(struct razor_importer *importer)
+ {
+ struct razor_property *prop;
+ struct razor_entry *top, *entry;
+ struct razor_package *packages;
+ struct array pkgprops;
+ struct list *pkg;
+ uint32_t *req, *req_start, *req_end;
+ uint32_t *map, *newprop;
+ char *pool;
+
+ pool = importer->set->string_pool.data;
+ packages = importer->set->packages.data;
+ top = importer->set->files.data;
+
+ req = req_start = importer->file_requires.data;
+ req_end = importer->file_requires.data + importer->file_requires.size;
+ map = razor_qsort_with_data(req, req_end - req, sizeof *req,
+ compare_file_requires, pool);
+ free(map);
+
+ for (req = req_start; req < req_end; req++) {
+ if (req > req_start && req[0] == req[-1])
+ continue;
+ entry = razor_set_find_entry(importer->set, top, &pool[*req]);
+ if (!entry)
+ continue;
+
+ for (pkg = list_first(&entry->packages, &importer->set->package_pool); pkg; pkg = list_next(pkg)) {
+ prop = array_add(&importer->set->properties, sizeof *prop);
+ prop->name = *req;
+ prop->flags =
+ RAZOR_PROPERTY_PROVIDES | RAZOR_PROPERTY_EQUAL;
+ prop->version = hashtable_tokenize(&importer->table, "");
+ list_set_ptr(&prop->packages, pkg->data);
+
+ /* Update property list of pkg */
+ array_init(&pkgprops);
+ list_to_array(list_first(&packages[pkg->data].properties, &importer->set->property_pool), &pkgprops);
+ newprop = array_add(&pkgprops, sizeof *newprop);
+ *newprop = prop - (struct razor_property *)importer->set->properties.data;
+ list_set_array(&packages[pkg->data].properties, &importer->set->property_pool, &pkgprops, 1);
+ array_release(&pkgprops);
+ }
+ }
+
+ array_release(&importer->file_requires);
+ }
+
+ static void
+ build_package_file_lists(struct razor_set *set, uint32_t *rmap)
+ {
+ struct razor_package *p, *packages;
+ struct array *pkgs;
+ struct razor_entry *e, *end;
+ struct list *r;
+ uint32_t *q;
+ int i, count;
+
+ count = set->packages.size / sizeof *p;
+ pkgs = zalloc(count * sizeof *pkgs);
+
+ end = set->files.data + set->files.size;
+ for (e = set->files.data; e < end; e++) {
+ list_remap_head(&e->packages, rmap);
+ r = list_first(&e->packages, &set->package_pool);
+ while (r) {
+ q = array_add(&pkgs[r->data], sizeof *q);
+ *q = e - (struct razor_entry *) set->files.data;
+ r = list_next(r);
+ }
+ }
+
+ packages = set->packages.data;
+ for (i = 0; i < count; i++) {
+ list_set_array(&packages[i].files, &set->file_pool, &pkgs[i], 0);
+ array_release(&pkgs[i]);
+ }
+ free(pkgs);
+ }
+
+ struct razor_set *
+ razor_importer_finish(struct razor_importer *importer)
+ {
+ struct razor_set *set;
+ uint32_t *map, *rmap;
+ int i, count;
+
+ build_file_tree(importer);
+ find_file_provides(importer);
+
+ map = uniqueify_properties(importer->set);
+ list_remap_pool(&importer->set->property_pool, map);
+ free(map);
+
+ count = importer->set->packages.size / sizeof(struct razor_package);
+ map = razor_qsort_with_data(importer->set->packages.data,
+ count,
+ sizeof(struct razor_package),
+ compare_packages,
+ importer->set);
+
+ rmap = malloc(count * sizeof *rmap);
+ for (i = 0; i < count; i++)
+ rmap[map[i]] = i;
+ free(map);
+
+ list_remap_pool(&importer->set->package_pool, rmap);
+ build_package_file_lists(importer->set, rmap);
+ remap_property_package_links(&importer->set->properties, rmap);
+ free(rmap);
+
+ set = importer->set;
+ hashtable_release(&importer->table);
+ free(importer);
+
+ return set;
+ }
--- /dev/null
+ #ifndef _RAZOR_INTERNAL_H_
+ #define _RAZOR_INTERNAL_H_
+
+ #include <stdlib.h>
+ #include <stdint.h>
+
+ void *zalloc(size_t size);
+
+ struct array {
+ void *data;
+ int size, alloc;
+ };
+
+ void array_init(struct array *array);
+ void array_release(struct array *array);
+ void *array_add(struct array *array, int size);
+
+
+ struct list_head {
+ uint32_t list_ptr : 24;
+ uint32_t flags : 8;
+ };
+
+ struct list {
+ uint32_t data : 24;
+ uint32_t flags : 8;
+ };
+
+ void list_set_empty(struct list_head *head);
+ void list_set_ptr(struct list_head *head, uint32_t ptr);
+ void list_set_array(struct list_head *head, struct array *pool, struct array *items, int force_indirect);
+
+ struct list *list_first(struct list_head *head, struct array *pool);
+ struct list *list_next(struct list *list);
+
+ void list_remap_pool(struct array *pool, uint32_t *map);
+ void list_remap_head(struct list_head *list, uint32_t *map);
+
+
+ struct hashtable {
+ struct array buckets;
+ struct array *pool;
+ };
+
+ void hashtable_init(struct hashtable *table, struct array *pool);
+ void hashtable_release(struct hashtable *table);
+ uint32_t hashtable_insert(struct hashtable *table, const char *key);
+ uint32_t hashtable_lookup(struct hashtable *table, const char *key);
+ uint32_t hashtable_tokenize(struct hashtable *table, const char *string);
+
+
+ struct razor_set_section {
+ uint32_t type;
+ uint32_t offset;
+ uint32_t size;
+ };
+
+ struct razor_set_header {
+ uint32_t magic;
+ uint32_t version;
+ struct razor_set_section sections[0];
+ };
+
-#define RAZOR_MAGIC 0x7a7a7a7a
++#define RAZOR_MAGIC 0x7a7a7a7a
++#define RAZOR_DETAILS_MAGIC 0x7a7a7a7b
++#define RAZOR_FILES_MAGIC 0x7a7a7a7c
+ #define RAZOR_VERSION 1
+
-#define RAZOR_STRING_POOL 0
-#define RAZOR_PACKAGES 1
-#define RAZOR_PROPERTIES 2
-#define RAZOR_FILES 3
-#define RAZOR_PACKAGE_POOL 4
-#define RAZOR_PROPERTY_POOL 5
-#define RAZOR_FILE_POOL 6
++#define RAZOR_STRING_POOL 0
++#define RAZOR_PACKAGES 1
++#define RAZOR_PROPERTIES 2
++#define RAZOR_PACKAGE_POOL 3
++#define RAZOR_PROPERTY_POOL 4
++
++#define RAZOR_DETAILS_STRING_POOL 0
++
++#define RAZOR_FILES 0
++#define RAZOR_FILE_POOL 1
++#define RAZOR_FILE_STRING_POOL 2
+
+ struct razor_package {
- uint32_t name : 24;
- uint32_t flags : 8;
++ uint name : 24;
++ uint flags : 8;
+ uint32_t version;
+ uint32_t arch;
++ uint32_t summary;
++ uint32_t description;
++ uint32_t url;
++ uint32_t license;
+ struct list_head properties;
+ struct list_head files;
+ };
+
++
+ struct razor_property {
+ uint32_t name;
+ uint32_t flags;
+ uint32_t version;
+ struct list_head packages;
+ };
+
+ struct razor_entry {
+ uint32_t name : 24;
+ uint32_t flags : 8;
+ uint32_t start;
+ struct list_head packages;
+ };
+
+ #define RAZOR_ENTRY_LAST 0x80
+
+ struct razor_set {
+ struct array string_pool;
+ struct array packages;
+ struct array properties;
+ struct array files;
+ struct array package_pool;
+ struct array property_pool;
+ struct array file_pool;
++ struct array file_string_pool;
++ struct array details_string_pool;
+ struct razor_set_header *header;
++ struct razor_set_header *details_header;
++ struct razor_set_header *files_header;
+ };
+
+ struct import_entry {
+ uint32_t package;
+ char *name;
+ };
+
+ struct import_directory {
+ uint32_t name, count;
+ struct array files;
+ struct array packages;
+ struct import_directory *last;
+ };
+
+ struct razor_importer {
+ struct razor_set *set;
+ struct hashtable table;
++ struct hashtable file_table;
++ struct hashtable details_table;
+ struct razor_package *package;
+ struct array properties;
+ struct array files;
+ struct array file_requires;
+ };
+
+ struct razor_package_iterator {
+ struct razor_set *set;
+ struct razor_package *package, *end;
+ struct list *index;
+ int free_index;
+ };
+
+ void
+ razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
+ struct razor_set *set,
+ struct razor_property *property);
+
+ struct razor_property_iterator {
+ struct razor_set *set;
+ struct razor_property *property, *end;
+ struct list *index;
+ };
+
+ #define ALIGN(value, base) (((value) + (base - 1)) & ~((base) - 1))
+
+ struct razor_entry *
+ razor_set_find_entry(struct razor_set *set,
+ struct razor_entry *dir, const char *pattern);
+
+ struct razor_merger *
+ razor_merger_create(struct razor_set *set1, struct razor_set *set2);
+ void
+ razor_merger_add_package(struct razor_merger *merger,
+ struct razor_package *package);
+ struct razor_set *
+ razor_merger_finish(struct razor_merger *merger);
+
+ /* Utility functions */
+
+ int razor_create_dir(const char *root, const char *path);
+ int razor_write(int fd, const void *data, size_t size);
+
+
+ typedef int (*razor_compare_with_data_func_t)(const void *p1,
+ const void *p,
+ void *data);
+ uint32_t *
+ razor_qsort_with_data(void *base, size_t nelem, size_t size,
+ razor_compare_with_data_func_t compare, void *data);
+
+ #endif /* _RAZOR_INTERNAL_H_ */
--- /dev/null
+ /*
+ * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
+ * Copyright (C) 2008 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+ #define _GNU_SOURCE
+
+ #include <stdlib.h>
+ #include <stddef.h>
+ #include <stdint.h>
+ #include <stdio.h>
+ #include <string.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <sys/mman.h>
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <errno.h>
+ #include <ctype.h>
+ #include <fnmatch.h>
+
+ #include "razor.h"
+ #include "razor-internal.h"
+
+ void *
+ zalloc(size_t size)
+ {
+ void *p;
+
+ p = malloc(size);
+ memset(p, 0, size);
+
+ return p;
+ }
+
+ struct razor_set_section razor_sections[] = {
+ { RAZOR_STRING_POOL, offsetof(struct razor_set, string_pool) },
+ { RAZOR_PACKAGES, offsetof(struct razor_set, packages) },
+ { RAZOR_PROPERTIES, offsetof(struct razor_set, properties) },
- { RAZOR_FILES, offsetof(struct razor_set, files) },
+ { RAZOR_PACKAGE_POOL, offsetof(struct razor_set, package_pool) },
+ { RAZOR_PROPERTY_POOL, offsetof(struct razor_set, property_pool) },
- { RAZOR_FILE_POOL, offsetof(struct razor_set, file_pool) },
+ };
+
++struct razor_set_section razor_files_sections[] = {
++ { RAZOR_FILES, offsetof(struct razor_set, files) },
++ { RAZOR_FILE_POOL, offsetof(struct razor_set, file_pool) },
++ { RAZOR_FILE_STRING_POOL, offsetof(struct razor_set, file_string_pool) },
++};
++
++struct razor_set_section razor_details_sections[] = {
++ { RAZOR_DETAILS_STRING_POOL, offsetof(struct razor_set, details_string_pool) },
++};
+ struct razor_set *
+ razor_set_create(void)
+ {
+ struct razor_set *set;
+ struct razor_entry *e;
+ char *empty;
+
+ set = zalloc(sizeof *set);
+
+ e = array_add(&set->files, sizeof *e);
+ empty = array_add(&set->string_pool, 1);
+ *empty = '\0';
+ e->name = 0;
+ e->flags = RAZOR_ENTRY_LAST;
+ e->start = 0;
+ list_set_empty(&e->packages);
+
+ return set;
+ }
+
+ struct razor_set *
+ razor_set_open(const char *filename)
+ {
+ struct razor_set *set;
+ struct razor_set_section *s;
+ struct stat stat;
+ struct array *array;
+ int fd;
+
+ set = zalloc(sizeof *set);
+ fd = open(filename, O_RDONLY);
+ if (fstat(fd, &stat) < 0)
+ return NULL;
+ set->header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (set->header == MAP_FAILED) {
+ free(set);
+ return NULL;
+ }
+
+ for (s = set->header->sections; ~s->type; s++) {
+ if (s->type >= ARRAY_SIZE(razor_sections))
+ continue;
+ if (s->type != razor_sections[s->type].type)
+ continue;
+ array = (void *) set + razor_sections[s->type].offset;
+ array->data = (void *) set->header + s->offset;
+ array->size = s->size;
+ array->alloc = s->size;
+ }
+ close(fd);
+
+ return set;
+ }
+
+ void
++razor_set_open_details(struct razor_set *set, const char *filename)
++{
++ struct razor_set_section *s;
++ struct stat stat;
++ struct array *array;
++ int fd;
++
++ fd = open(filename, O_RDONLY);
++ if (fstat(fd, &stat) < 0)
++ return;
++ set->details_header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
++ if (set->details_header == MAP_FAILED)
++ return;
++
++ for (s = set->details_header->sections; ~s->type; s++) {
++ if (s->type >= ARRAY_SIZE(razor_details_sections))
++ continue;
++ if (s->type != razor_details_sections[s->type].type)
++ continue;
++ array = (void *) set + razor_details_sections[s->type].offset;
++ array->data = (void *) set->details_header + s->offset;
++ array->size = s->size;
++ array->alloc = s->size;
++ }
++ close(fd);
++}
++
++void
++razor_set_open_files(struct razor_set *set, const char *filename)
++{
++ struct razor_set_section *s;
++ struct stat stat;
++ struct array *array;
++ int fd;
++
++ fd = open(filename, O_RDONLY);
++ if (fstat(fd, &stat) < 0)
++ return;
++ set->files_header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
++ if (set->files_header == MAP_FAILED)
++ return;
++
++ for (s = set->files_header->sections; ~s->type; s++) {
++ if (s->type >= ARRAY_SIZE(razor_files_sections))
++ continue;
++ if (s->type != razor_files_sections[s->type].type)
++ continue;
++ array = (void *) set + razor_files_sections[s->type].offset;
++ array->data = (void *) set->files_header + s->offset;
++ array->size = s->size;
++ array->alloc = s->size;
++ }
++ close(fd);
++}
++
++void
+ razor_set_destroy(struct razor_set *set)
+ {
+ unsigned int size;
+ struct array *a;
+ int i;
+
+ if (set->header) {
+ for (i = 0; set->header->sections[i].type; i++)
+ ;
+ size = set->header->sections[i].type;
+ munmap(set->header, size);
+ } else {
+ for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
+ a = (void *) set + razor_sections[i].offset;
+ free(a->data);
+ }
+ }
+
++ if (set->details_header) {
++ for (i = 0; set->details_header->sections[i].type; i++)
++ ;
++ size = set->details_header->sections[i].type;
++ munmap(set->details_header, size);
++ } else {
++ for (i = 0; i < ARRAY_SIZE(razor_details_sections); i++) {
++ a = (void *) set + razor_details_sections[i].offset;
++ free(a->data);
++ }
++ }
++
++ if (set->files_header) {
++ for (i = 0; set->files_header->sections[i].type; i++)
++ ;
++ size = set->files_header->sections[i].type;
++ munmap(set->files_header, size);
++ } else {
++ for (i = 0; i < ARRAY_SIZE(razor_files_sections); i++) {
++ a = (void *) set + razor_files_sections[i].offset;
++ free(a->data);
++ }
++ }
++
+ free(set);
+ }
+
-int
-razor_set_write_to_fd(struct razor_set *set, int fd)
++static int
++razor_set_write_sections_to_fd(struct razor_set *set, int fd, int magic,
++ struct razor_set_section *sections,
++ size_t array_size)
+ {
+ char data[4096];
+ struct razor_set_header *header = (struct razor_set_header *) data;
+ struct array *a;
+ uint32_t offset;
+ int i;
+
+ memset(data, 0, sizeof data);
- header->magic = RAZOR_MAGIC;
++ header->magic = magic;
+ header->version = RAZOR_VERSION;
+ offset = sizeof data;
+
- for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
- if (razor_sections[i].type != i)
++ for (i = 0; i < array_size; i++) {
++ if (sections[i].type != i)
+ continue;
- a = (void *) set + razor_sections[i].offset;
++ a = (void *) set + sections[i].offset;
+ header->sections[i].type = i;
+ header->sections[i].offset = offset;
+ header->sections[i].size = a->size;
+ offset += ALIGN(a->size, 4096);
+ }
+
+ header->sections[i].type = ~0;
+ header->sections[i].offset = 0;
+ header->sections[i].size = 0;
+
+ razor_write(fd, data, sizeof data);
+ memset(data, 0, sizeof data);
- for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
- if (razor_sections[i].type != i)
++ for (i = 0; i < array_size; i++) {
++ if (sections[i].type != i)
+ continue;
- a = (void *) set + razor_sections[i].offset;
++ a = (void *) set + sections[i].offset;
+ razor_write(fd, a->data, a->size);
+ razor_write(fd, data, ALIGN(a->size, 4096) - a->size);
+ }
+
+ return 0;
+ }
+
+ int
-razor_set_write(struct razor_set *set, const char *filename)
++razor_set_write_to_fd(struct razor_set *set, int fd,
++ enum razor_repo_file_type type)
++{
++ switch (type) {
++ case RAZOR_REPO_FILE_MAIN:
++ return razor_set_write_sections_to_fd(set, fd, RAZOR_MAGIC,
++ razor_sections,
++ ARRAY_SIZE(razor_sections));
++
++ case RAZOR_REPO_FILE_DETAILS:
++ return razor_set_write_sections_to_fd(set, fd, RAZOR_DETAILS_MAGIC,
++ razor_details_sections,
++ ARRAY_SIZE(razor_details_sections));
++ case RAZOR_REPO_FILE_FILES:
++ return razor_set_write_sections_to_fd(set, fd, RAZOR_FILES_MAGIC,
++ razor_files_sections,
++ ARRAY_SIZE(razor_files_sections));
++ default:
++ return -1;
++ }
++}
++
++int
++razor_set_write(struct razor_set *set, const char *filename,
++ enum razor_repo_file_type type)
+ {
+ int fd, status;
+
+ fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
+ if (fd < 0)
+ return -1;
+
- status = razor_set_write_to_fd(set, fd);
++ status = razor_set_write_to_fd(set, fd, type);
+ if (status) {
+ close(fd);
+ return status;
+ }
+
+ return close(fd);
+ }
-
+ void
+ razor_build_evr(char *evr_buf, int size, const char *epoch,
+ const char *version, const char *release)
+ {
+ int len;
+
+ if (!version || !*version) {
+ *evr_buf = '\0';
+ return;
+ }
+
+ if (epoch && *epoch && strcmp(epoch, "0") != 0) {
+ len = snprintf(evr_buf, size, "%s:", epoch);
+ evr_buf += len;
+ size -= len;
+ }
+ len = snprintf(evr_buf, size, "%s", version);
+ evr_buf += len;
+ size -= len;
+ if (release && *release)
+ snprintf(evr_buf, size, "-%s", release);
+ }
+
+ int
+ razor_versioncmp(const char *s1, const char *s2)
+ {
+ const char *p1, *p2;
+ long n1, n2;
+ int res;
+
+ n1 = strtol(s1, (char **) &p1, 10);
+ n2 = strtol(s2, (char **) &p2, 10);
+
+ /* Epoch; if one but not the other has an epoch set, default
+ * the epoch-less version to 0. */
+ res = (*p1 == ':') - (*p2 == ':');
+ if (res < 0) {
+ n1 = 0;
+ p1 = s1;
+ p2++;
+ } else if (res > 0) {
+ p1++;
+ n2 = 0;
+ p2 = s2;
+ }
+
+ if (n1 != n2)
+ return n1 - n2;
+ while (*p1 && *p2) {
+ if (*p1 != *p2)
+ return *p1 - *p2;
+ p1++;
+ p2++;
+ if (isdigit(*p1) && isdigit(*p2))
+ return razor_versioncmp(p1, p2);
+ }
+
+ return *p1 - *p2;
+ }
+
+ struct razor_package *
+ razor_set_get_package(struct razor_set *set, const char *package)
+ {
+ struct razor_package_iterator *pi;
+ struct razor_package *p;
+ const char *name, *version, *arch;
+
+ pi = razor_package_iterator_create(set);
+ while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
+ if (strcmp(package, name) == 0)
+ break;
+ }
+ razor_package_iterator_destroy(pi);
+
+ return p;
+ }
+
++void
++razor_package_get_details(struct razor_set *set, struct razor_package *package,
++ const char **summary, const char **description,
++ const char **url, const char **license)
++{
++ const char *pool = set->details_string_pool.data;
++
++ *summary = &pool[package->summary];
++ *description = &pool[package->description];
++ *url = &pool[package->url];
++ *license = &pool[package->license];
++}
++
+ struct razor_entry *
+ razor_set_find_entry(struct razor_set *set,
+ struct razor_entry *dir, const char *pattern)
+ {
+ struct razor_entry *e;
+ const char *n, *pool = set->string_pool.data;
+ int len;
+
+ e = (struct razor_entry *) set->files.data + dir->start;
+ do {
+ n = pool + e->name;
+ if (strcmp(pattern + 1, n) == 0)
+ return e;
+ len = strlen(n);
+ if (e->start != 0 && strncmp(pattern + 1, n, len) == 0 &&
+ pattern[len + 1] == '/') {
+ return razor_set_find_entry(set, e, pattern + len + 1);
+ }
+ } while (!((e++)->flags & RAZOR_ENTRY_LAST));
+
+ return NULL;
+ }
+
+ static void
+ list_dir(struct razor_set *set, struct razor_entry *dir,
+ char *prefix, const char *pattern)
+ {
+ struct razor_entry *e;
+ const char *n, *pool = set->string_pool.data;
+
+ e = (struct razor_entry *) set->files.data + dir->start;
+ do {
+ n = pool + e->name;
+ if (pattern && pattern[0] && fnmatch(pattern, n, 0) != 0)
+ continue;
+ printf("%s/%s\n", prefix, n);
+ if (e->start) {
+ char *sub = prefix + strlen (prefix);
+ *sub = '/';
+ strcpy (sub + 1, n);
+ list_dir(set, e, prefix, pattern);
+ *sub = '\0';
+ }
+ } while (!((e++)->flags & RAZOR_ENTRY_LAST));
+ }
+
+ void
+ razor_set_list_files(struct razor_set *set, const char *pattern)
+ {
+ struct razor_entry *e;
+ char buffer[512], *p, *base;
+
+ if (pattern == NULL || !strcmp (pattern, "/")) {
+ buffer[0] = '\0';
+ list_dir(set, set->files.data, buffer, NULL);
+ return;
+ }
+
+ strcpy(buffer, pattern);
+ e = razor_set_find_entry(set, set->files.data, buffer);
+ if (e && e->start > 0) {
+ base = NULL;
+ } else {
+ p = strrchr(buffer, '/');
+ if (p) {
+ *p = '\0';
+ base = p + 1;
+ } else {
+ base = NULL;
+ }
+ }
+ e = razor_set_find_entry(set, set->files.data, buffer);
+ if (e->start != 0)
+ list_dir(set, e, buffer, base);
+ }
+
+ static struct list *
+ list_package_files(struct razor_set *set, struct list *r,
+ struct razor_entry *dir, uint32_t end,
+ char *prefix)
+ {
+ struct razor_entry *e, *f, *entries;
+ uint32_t next, file;
+ char *pool;
+ int len;
+
+ entries = (struct razor_entry *) set->files.data;
+ pool = set->string_pool.data;
+
+ e = entries + dir->start;
+ do {
+ if (entries + r->data == e) {
+ printf("%s/%s\n", prefix, pool + e->name);
+ r = list_next(r);
+ if (!r)
+ return NULL;
+ if (r->data >= end)
+ return r;
+ }
+ } while (!((e++)->flags & RAZOR_ENTRY_LAST));
+
+ e = entries + dir->start;
+ do {
+ if (e->start == 0)
+ continue;
+
+ if (e->flags & RAZOR_ENTRY_LAST)
+ next = end;
+ else {
+ f = e + 1;
+ while (f->start == 0 && !(f->flags & RAZOR_ENTRY_LAST))
+ f++;
+ if (f->start == 0)
+ next = end;
+ else
+ next = f->start;
+ }
+
+ file = r->data;
+ if (e->start <= file && file < next) {
+ len = strlen(prefix);
+ prefix[len] = '/';
+ strcpy(prefix + len + 1, pool + e->name);
+ r = list_package_files(set, r, e, next, prefix);
+ prefix[len] = '\0';
+ }
+ } while (!((e++)->flags & RAZOR_ENTRY_LAST) && r != NULL);
+
+ return r;
+ }
+
+ void
+ razor_set_list_package_files(struct razor_set *set, const char *name)
+ {
+ struct razor_package *package;
+ struct list *r;
+ uint32_t end;
+ char buffer[512];
+
+ package = razor_set_get_package(set, name);
+
+ r = list_first(&package->files, &set->file_pool);
+ end = set->files.size / sizeof (struct razor_entry);
+ buffer[0] = '\0';
+ list_package_files(set, r, set->files.data, end, buffer);
+ }
+
+ /* The diff order matters. We should sort the packages so that a
+ * REMOVE of a package comes before the INSTALL, and so that all
+ * requires for a package have been installed before the package.
+ **/
+
+ void
+ razor_set_diff(struct razor_set *set, struct razor_set *upstream,
+ razor_package_callback_t callback, void *data)
+ {
+ struct razor_package_iterator *pi1, *pi2;
+ struct razor_package *p1, *p2;
+ const char *name1, *name2, *version1, *version2, *arch1, *arch2;
+ int res;
+
+ pi1 = razor_package_iterator_create(set);
+ pi2 = razor_package_iterator_create(upstream);
+
+ razor_package_iterator_next(pi1, &p1, &name1, &version1, &arch1);
+ razor_package_iterator_next(pi2, &p2, &name2, &version2, &arch2);
+
+ while (p1 || p2) {
+ if (p1 && p2) {
+ res = strcmp(name1, name2);
+ if (res == 0)
+ res = razor_versioncmp(version1, version2);
+ } else {
+ res = 0;
+ }
+
+ if (p2 == NULL || res < 0)
+ callback(name1, version1, NULL, arch1, data);
+ else if (p1 == NULL || res > 0)
+ callback(name2, NULL, version2, arch2, data);
+
+ if (p1 != NULL && res <= 0)
+ razor_package_iterator_next(pi1, &p1,
+ &name1, &version1, &arch1);
+ if (p2 != NULL && res >= 0)
+ razor_package_iterator_next(pi2, &p2,
+ &name2, &version2, &arch2);
+ }
+
+ razor_package_iterator_destroy(pi1);
+ razor_package_iterator_destroy(pi2);
+ }
struct razor_package;
struct razor_property;
+enum razor_repo_file_type {
+ RAZOR_REPO_FILE_MAIN,
+ RAZOR_REPO_FILE_DETAILS,
+ RAZOR_REPO_FILE_FILES
+};
+
- enum razor_property_type {
- RAZOR_PROPERTY_REQUIRES,
- RAZOR_PROPERTY_PROVIDES,
- RAZOR_PROPERTY_CONFLICTS,
- RAZOR_PROPERTY_OBSOLETES
+ enum razor_property_flags {
+ RAZOR_PROPERTY_LESS = 1 << 0,
+ RAZOR_PROPERTY_GREATER = 1 << 1,
+ RAZOR_PROPERTY_EQUAL = 1 << 2,
+ RAZOR_PROPERTY_RELATION_MASK =
+ RAZOR_PROPERTY_LESS |
+ RAZOR_PROPERTY_GREATER |
+ RAZOR_PROPERTY_EQUAL,
+
+ RAZOR_PROPERTY_REQUIRES = 0 << 3,
+ RAZOR_PROPERTY_PROVIDES = 1 << 3,
+ RAZOR_PROPERTY_CONFLICTS = 2 << 3,
+ RAZOR_PROPERTY_OBSOLETES = 3 << 3,
+ RAZOR_PROPERTY_TYPE_MASK = 3 << 3,
+
+ RAZOR_PROPERTY_PRE = 1 << 5,
+ RAZOR_PROPERTY_POST = 1 << 6,
+ RAZOR_PROPERTY_PREUN = 1 << 7,
+ RAZOR_PROPERTY_POSTUN = 1 << 8
};
- enum razor_version_relation {
- RAZOR_VERSION_LESS,
- RAZOR_VERSION_LESS_OR_EQUAL,
- RAZOR_VERSION_EQUAL,
- RAZOR_VERSION_GREATER_OR_EQUAL,
- RAZOR_VERSION_GREATER
- };
- extern const char * const razor_version_relations[];
+ const char *
+ razor_property_relation_to_string(struct razor_property *p);
+ const char *
+ razor_property_type_to_string(struct razor_property *p);
struct razor_set *razor_set_create(void);
struct razor_set *razor_set_open(const char *filename);
const char *name,
const char *version,
const char *arch);
+void razor_importer_add_details(struct razor_importer *importer,
+ const char *summary,
+ const char *description,
+ const char *url,
+ const char *license);
void razor_importer_add_property(struct razor_importer *importer,
const char *name,
- enum razor_version_relation relation,
- const char *version,
- enum razor_property_type type);
+ uint32_t flags,
+ const char *version);
void razor_importer_add_file(struct razor_importer *importer,
const char *name);
void razor_importer_finish_package(struct razor_importer *importer);
--- /dev/null
+ #include <stdlib.h>
+ #include <stdint.h>
+ #include <stdio.h>
+ #include <sys/stat.h>
+ #include <dirent.h>
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include "razor.h"
+ #include "razor-internal.h"
+
+ static const char system_repo_filename[] = "system.repo";
+ static const char next_repo_filename[] = "system-next.repo";
+ static const char razor_root_path[] = "/var/lib/razor";
+
+ struct razor_root {
+ struct razor_set *system;
+ struct razor_set *next;
+ int fd;
+ char path[PATH_MAX];
+ char new_path[PATH_MAX];
+ };
+
+ int
+ razor_root_create(const char *root)
+ {
+ struct stat buf;
+ struct razor_set *set;
+ char path[PATH_MAX];
+
+ if (stat(root, &buf) < 0) {
+ if (mkdir(root, 0777) < 0) {
+ fprintf(stderr,
+ "could not create install root \"%s\"\n",
+ root);
+ return -1;
+ }
+ fprintf(stderr, "created install root \"%s\"\n", root);
+ } else if (!S_ISDIR(buf.st_mode)) {
+ fprintf(stderr,
+ "install root \"%s\" exists, but is not a directory\n",
+ root);
+ return -1;
+ }
+
+ snprintf(path, sizeof path, "%s/%s",
+ razor_root_path, system_repo_filename);
+ if (razor_create_dir(root, path) < 0) {
+ fprintf(stderr, "could not create %s%s\n",
+ root, razor_root_path);
+ return -1;
+ }
+
+ set = razor_set_create();
+ snprintf(path, sizeof path, "%s%s/%s",
+ root, razor_root_path, system_repo_filename);
+ if (stat(path, &buf) == 0) {
+ fprintf(stderr,
+ "a razor install root is already initialized\n");
+ return -1;
+ }
- if (razor_set_write(set, path) < 0) {
++ if (razor_set_write(set, path, RAZOR_REPO_FILE_MAIN) < 0) {
+ fprintf(stderr, "could not write initial package set\n");
+ return -1;
+ }
+ razor_set_destroy(set);
+
+ return 0;
+ }
+
+ struct razor_root *
+ razor_root_open(const char *root, int flags)
+ {
+ struct razor_root *image;
+
+ image = malloc(sizeof *image);
+ if (image == NULL)
+ return NULL;
+
+ /* Create the new next repo file up front to ensure exclusive
+ * access. */
+ snprintf(image->new_path, sizeof image->new_path,
+ "%s%s/%s", root, razor_root_path, next_repo_filename);
+ image->fd = open(image->new_path,
+ O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666);
+ if (image->fd < 0) {
+ fprintf(stderr, "failed to get lock file, "
+ "maybe previous operation crashed?\n");
+
+ /* FIXME: Use fcntl advisory locking on the system
+ * package set file to figure out whether previous
+ * operation crashed or is still in progress. */
+
+ free(image);
+ return NULL;
+ }
+
+ snprintf(image->path, sizeof image->path,
+ "%s%s/%s", root, razor_root_path, system_repo_filename);
+ image->system = razor_set_open(image->path);
+ if (image->system == NULL) {
+ unlink(image->new_path);
+ close(image->fd);
+ free(image);
+ return NULL;
+ }
+
+ return image;
+ }
+
+ struct razor_set *
+ razor_root_open_read_only(const char *root)
+ {
+ char path[PATH_MAX];
+
+ snprintf(path, sizeof path, "%s%s/%s",
+ root, razor_root_path, system_repo_filename);
+
+ return razor_set_open(path);
+ }
+
+ struct razor_transaction *
+ razor_root_create_transaction(struct razor_root *image,
+ struct razor_set *upstream)
+ {
+ /* FIXME: This should take a number of upstream repos. */
+ return razor_transaction_create(image->system, upstream);
+ }
+
+ int
+ razor_root_close(struct razor_root *image)
+ {
+ unlink(image->new_path);
+ close(image->fd);
+ free(image);
+
+ return 0;
+ }
+
+ void
+ razor_root_update(struct razor_root *root, struct razor_set *next)
+ {
- razor_set_write_to_fd(next, root->fd);
++ razor_set_write_to_fd(next, root->fd, RAZOR_REPO_FILE_MAIN);
+ root->next = next;
+
+ /* Sync the new repo file so the new package set is on disk
+ * before we start upgrading. */
+ fsync(root->fd);
+ printf("wrote %s\n", root->new_path);
+ }
+
+ int
+ razor_root_commit(struct razor_root *image)
+ {
+ /* Make it so. */
+ rename(image->new_path, image->path);
+ printf("renamed %s to %s\n", image->new_path, image->path);
+ close(image->fd);
+ free(image);
+
+ return 0;
+ }
+
+ void
+ razor_root_diff(struct razor_root *root,
+ razor_package_callback_t callback, void *data)
+ {
+ return razor_set_diff(root->system, root->next, callback, data);
+ }
int
razor_importer_add_rpm(struct razor_importer *importer, struct razor_rpm *rpm)
{
- const char *name, *version, *release, *arch;
+ const char *name, *version, *release, *arch, *summary;
- const uint_32 *epoch;
+ const uint32_t *epoch;
char evr[128], buf[16];
name = razor_rpm_get_indirect(rpm, RPMTAG_NAME, NULL);
--- /dev/null
+ /*
+ * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
+ * Copyright (C) 2008 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+ #include <stdio.h>
+ #include <stddef.h>
+ #include <string.h>
+ #include <fcntl.h>
+ #include <rpm/rpmlib.h>
+ #include <rpm/rpmdb.h>
+
+ #include "razor.h"
+
+ union rpm_entry {
+ void *p;
+ char *string;
+ char **list;
+ uint_32 *flags;
+ uint_32 integer;
+ };
+
+ static uint32_t
+ rpm_to_razor_flags(uint32_t flags)
+ {
+ uint32_t razor_flags;
+
+ razor_flags = 0;
+ if (flags & RPMSENSE_LESS)
+ razor_flags |= RAZOR_PROPERTY_LESS;
+ if (flags & RPMSENSE_EQUAL)
+ razor_flags |= RAZOR_PROPERTY_EQUAL;
+ if (flags & RPMSENSE_GREATER)
+ razor_flags |= RAZOR_PROPERTY_GREATER;
+
+ if (flags & RPMSENSE_SCRIPT_PRE)
+ razor_flags |= RAZOR_PROPERTY_PRE;
+ if (flags & RPMSENSE_SCRIPT_POST)
+ razor_flags |= RAZOR_PROPERTY_POST;
+ if (flags & RPMSENSE_SCRIPT_PREUN)
+ razor_flags |= RAZOR_PROPERTY_PREUN;
+ if (flags & RPMSENSE_SCRIPT_POSTUN)
+ razor_flags |= RAZOR_PROPERTY_POSTUN;
+
+ return razor_flags;
+ }
+
+ static void
+ add_properties(struct razor_importer *importer,
+ uint32_t type_flags,
+ Header h, int_32 name_tag, int_32 version_tag, int_32 flags_tag)
+ {
+ union rpm_entry names, versions, flags;
+ int_32 i, type, count;
+
+ headerGetEntry(h, name_tag, &type, &names.p, &count);
+ headerGetEntry(h, version_tag, &type, &versions.p, &count);
+ headerGetEntry(h, flags_tag, &type, &flags.p, &count);
+
+ for (i = 0; i < count; i++)
+ razor_importer_add_property(importer,
+ names.list[i],
+ rpm_to_razor_flags (flags.flags[i]) | type_flags,
+ versions.list[i]);
+ }
+
+ struct razor_set *
+ razor_set_create_from_rpmdb(void)
+ {
+ struct razor_importer *importer;
+ rpmdbMatchIterator iter;
+ Header h;
+ int_32 type, count, i;
+ union rpm_entry name, epoch, version, release, arch;
++ union rpm_entry summary, description, url, license;
+ union rpm_entry basenames, dirnames, dirindexes;
+ char filename[PATH_MAX], evr[128], buf[16];
+ rpmdb db;
+
+ rpmReadConfigFiles(NULL, NULL);
+
+ if (rpmdbOpen("", &db, O_RDONLY, 0644) != 0) {
+ fprintf(stderr, "cannot open rpm database\n");
+ exit(1);
+ }
+
+ importer = razor_importer_new();
+
+ iter = rpmdbInitIterator(db, 0, NULL, 0);
+ while (h = rpmdbNextIterator(iter), h != NULL) {
+ headerGetEntry(h, RPMTAG_NAME, &type, &name.p, &count);
+ headerGetEntry(h, RPMTAG_EPOCH, &type, &epoch.p, &count);
+ headerGetEntry(h, RPMTAG_VERSION, &type, &version.p, &count);
+ headerGetEntry(h, RPMTAG_RELEASE, &type, &release.p, &count);
+ headerGetEntry(h, RPMTAG_ARCH, &type, &arch.p, &count);
++ headerGetEntry(h, RPMTAG_SUMMARY, &type, &summary.p, &count);
++ headerGetEntry(h, RPMTAG_DESCRIPTION, &type, &description.p,
++ &count);
++ headerGetEntry(h, RPMTAG_URL, &type, &url.p, &count);
++ headerGetEntry(h, RPMTAG_LICENSE, &type, &license.p, &count);
+
+ if (epoch.flags != NULL) {
+ snprintf(buf, sizeof buf, "%u", *epoch.flags);
+ razor_build_evr(evr, sizeof evr,
+ buf, version.string, release.string);
+ } else {
+ razor_build_evr(evr, sizeof evr,
+ NULL, version.string, release.string);
+ }
+
+ razor_importer_begin_package(importer,
+ name.string, evr, arch.string);
++ razor_importer_add_details(importer, summary.string,
++ description.string, url.string,
++ license.string);
+
+ add_properties(importer, RAZOR_PROPERTY_REQUIRES, h,
+ RPMTAG_REQUIRENAME,
+ RPMTAG_REQUIREVERSION,
+ RPMTAG_REQUIREFLAGS);
+
+ add_properties(importer, RAZOR_PROPERTY_PROVIDES, h,
+ RPMTAG_PROVIDENAME,
+ RPMTAG_PROVIDEVERSION,
+ RPMTAG_PROVIDEFLAGS);
+
+ add_properties(importer, RAZOR_PROPERTY_OBSOLETES, h,
+ RPMTAG_OBSOLETENAME,
+ RPMTAG_OBSOLETEVERSION,
+ RPMTAG_OBSOLETEFLAGS);
+
+ add_properties(importer, RAZOR_PROPERTY_CONFLICTS, h,
+ RPMTAG_CONFLICTNAME,
+ RPMTAG_CONFLICTVERSION,
+ RPMTAG_CONFLICTFLAGS);
+
+ headerGetEntry(h, RPMTAG_BASENAMES, &type,
+ &basenames.p, &count);
+ headerGetEntry(h, RPMTAG_DIRNAMES, &type,
+ &dirnames.p, &count);
+ headerGetEntry(h, RPMTAG_DIRINDEXES, &type,
+ &dirindexes.p, &count);
+ for (i = 0; i < count; i++) {
+ snprintf(filename, sizeof filename, "%s%s",
+ dirnames.list[dirindexes.flags[i]],
+ basenames.list[i]);
+ razor_importer_add_file(importer, filename);
+ }
+
+ razor_importer_finish_package(importer);
+ }
+
+ rpmdbClose(db);
+
+ return razor_importer_finish(importer);
+ }
struct razor_importer *importer;
struct import_property_context *current_property_context;
- char name[256], arch[64], buffer[512], *p;
+ char name[256], arch[64], summary[512], description[4096];
+ char url[256], license[64], buffer[512], *p;
char pkgid[128];
+ uint32_t property_type;
int state;
};
} else if (strcmp(name, "checksum") == 0) {
ctx->p = ctx->pkgid;
ctx->state = YUM_STATE_CHECKSUM;
+ } else if (strcmp(name, "rpm:license") == 0) {
+ ctx->p = ctx->license;
+ ctx->state = YUM_STATE_LICENSE;
} else if (strcmp(name, "rpm:requires") == 0) {
ctx->state = YUM_STATE_REQUIRES;
+ ctx->property_type = RAZOR_PROPERTY_REQUIRES;
} else if (strcmp(name, "rpm:provides") == 0) {
ctx->state = YUM_STATE_PROVIDES;
+ ctx->property_type = RAZOR_PROPERTY_PROVIDES;
} else if (strcmp(name, "rpm:obsoletes") == 0) {
ctx->state = YUM_STATE_OBSOLETES;
+ ctx->property_type = RAZOR_PROPERTY_OBSOLETES;
} else if (strcmp(name, "rpm:conflicts") == 0) {
ctx->state = YUM_STATE_CONFLICTS;
+ ctx->property_type = RAZOR_PROPERTY_CONFLICTS;
} else if (strcmp(name, "rpm:entry") == 0 &&
ctx->state != YUM_STATE_BEGIN) {
n = NULL;
return 1;
set = razor_transaction_finish(trans);
- razor_set_write(set, updated_repo_filename);
+ razor_set_write(set, updated_repo_filename, RAZOR_REPO_FILE_MAIN);
razor_set_destroy(set);
+ razor_set_destroy(upstream);
printf("wrote system-updated.repo\n");
return 0;
pkg = razor_set_get_package(ctx->repo_set,
ctx->install_pkgs[i]);
razor_transaction_install_package(ctx->trans, pkg);
- }
+ }
for (i = 0; i < ctx->n_remove_pkgs; i++) {
- pkg = razor_set_get_package(ctx->repo_set,
+ pkg = razor_set_get_package(ctx->system_set,
ctx->remove_pkgs[i]);
+ if (!pkg)
+ pkg = razor_set_get_package(ctx->repo_set,
+ ctx->remove_pkgs[i]);
+
razor_transaction_remove_package(ctx->trans, pkg);
- }
+ }
errors = razor_transaction_resolve(ctx->trans);
printf("\n");