## Process this file with automake to produce Makefile.in
-SUBDIRS = data docs gl librazor src po
+SUBDIRS = data docs gl librazor src test po
ACLOCAL_AMFLAGS = -I gl/m4
docs/version.xml
po/Makefile.in
gl/Makefile
+test/Makefile
])
dnl ==========================================================================
/*
* Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
* Copyright (C) 2008 Red Hat, Inc
+ * Copyright (C) 2009 J. Ali Harlow <ali@juiblex.co.uk>
*
* 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
free(pi);
}
+RAZOR_EXPORT struct razor_file_iterator *
+razor_file_iterator_create(struct razor_set *set, struct razor_package *package)
+{
+ struct razor_file_iterator *fi;
+
+ assert (set != NULL);
+ assert (package != NULL);
+
+ fi = zalloc(sizeof *fi);
+ fi->set = set;
+ fi->index = list_first(&package->files, &set->file_pool);
+ array_init(&fi->path);
+
+ return fi;
+}
+
+RAZOR_EXPORT int
+razor_file_iterator_next(struct razor_file_iterator *fi,
+ const char **name)
+{
+ struct razor_entry *e, *dir, *entries;
+ char *pool, *s, *f;
+
+ assert (fi != NULL);
+
+ if (!fi->index) {
+ *name = NULL;
+ return 0;
+ }
+
+ entries = (struct razor_entry *) fi->set->files.data;
+ pool = fi->set->file_string_pool.data;
+
+ dir = entries;
+ fi->path.size = 0;
+ for(;;) {
+ e = dir;
+ do {
+ if (entries + fi->index->data == e) {
+ f = pool + e->name;
+ s = array_add(&fi->path, strlen(f) + 1);
+ strcpy(s, f);
+ if (fi->path.size == 1) {
+ array_add(&fi->path, 1);
+ strcpy(fi->path.data, "/");
+ }
+ *name = fi->path.data;
+ fi->index = list_next(fi->index);
+ return 1;
+ }
+ } while (!((e++)->flags & RAZOR_ENTRY_LAST));
+ for(e--; e >= dir; e--)
+ if (e->start && fi->index->data >= e->start)
+ break;
+ if (e < dir)
+ break;
+ f = pool + e->name;
+ s = array_add(&fi->path, strlen(f) + 1);
+ strcpy(s, f);
+ s += strlen(f);
+ *s = '/';
+ dir = entries + e->start;
+ }
+
+ printf("file_iterator_next: Failed to find file %d\n",fi->index->data);
+ *name = NULL;
+ return 0;
+}
+
+RAZOR_EXPORT void razor_file_iterator_destroy(struct razor_file_iterator *fi)
+{
+ assert (fi != NULL);
+
+ array_release(&fi->path);
+ free(fi);
+}
+
struct razor_package_query {
struct razor_set *set;
char *vector;
struct list *index;
};
+struct razor_file_iterator {
+ struct razor_set *set;
+ struct array path;
+ struct list *index;
+};
+
struct razor_entry *
razor_set_find_entry(struct razor_set *set,
struct razor_entry *dir, const char *pattern);
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->file_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;
-}
-
RAZOR_EXPORT void
razor_set_list_package_files(struct razor_set *set,
struct razor_package *package)
{
- struct list *r;
- uint32_t end;
- char buffer[512];
+ struct razor_file_iterator *fi;
+ const char *name;
assert (set != NULL);
assert (package != NULL);
- 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);
+ fi = razor_file_iterator_create(set, package);
+
+ while (razor_file_iterator_next(fi, &name))
+ printf("%s\n", name);
+
+ razor_file_iterator_destroy(fi);
}
/* The diff order matters. We should sort the packages so that a
void
razor_property_iterator_destroy(struct razor_property_iterator *pi);
+struct razor_file_iterator;
+struct razor_file_iterator *
+razor_file_iterator_create(struct razor_set *set,
+ struct razor_package *package);
+int razor_file_iterator_next(struct razor_file_iterator *fi,
+ const char **name);
+void razor_file_iterator_destroy(struct razor_file_iterator *fi);
+
void razor_set_list_files(struct razor_set *set, const char *prefix);
void razor_set_list_package_files(struct razor_set *set,
struct razor_package *package);
* installing or removing RPM files.
**/
+struct razor_relocations;
struct razor_rpm;
+struct razor_relocations *razor_relocations_create(void);
+void razor_relocations_add(struct razor_relocations *relocations,
+ const char *oldpath, const char *newpath);
+void razor_relocations_set_rpm(struct razor_relocations *relocations,
+ struct razor_rpm *rpm);
+const char *razor_relocations_apply(struct razor_relocations *relocations,
+ const char *path);
+void razor_relocations_destroy(struct razor_relocations *relocations);
+
struct razor_rpm *razor_rpm_open(const char *filename);
+void razor_rpm_set_relocations(struct razor_rpm *rpm,
+ struct razor_relocations *relocations);
int razor_rpm_install(struct razor_rpm *rpm, const char *root);
int razor_rpm_close(struct razor_rpm *rpm);
/*
* Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
* Copyright (C) 2008 Red Hat, Inc
+ * Copyright (C) 2009 J. Ali Harlow <ali@juiblex.co.uk>
*
* 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
struct rpm_header *signature;
struct rpm_header *header;
const char **dirs;
+ unsigned int n_prefixes;
+ const char **prefixes;
const char *pool;
void *map;
size_t size;
void *payload;
+ struct razor_relocations *relocations;
};
+enum razor_relocation_flags {
+ RAZOR_RELOCATION_ACTIVE = 1 << 0,
+};
+
+struct razor_relocation {
+ enum razor_relocation_flags flags;
+ size_t oldlen;
+ size_t newlen;
+ char *oldpath;
+ char *newpath;
+};
+
+struct razor_relocations {
+ /* Ordered such that if oldpath 1 starts with oldpath 2, then
+ * oldpath 1 is listed first (ie., /usr/bin comes before /usr)
+ * and terminated with a NULL oldpath.
+ */
+ struct razor_relocation *relocations;
+ int n_relocations;
+ char *path;
+};
+
+RAZOR_EXPORT struct razor_relocations *razor_relocations_create(void)
+{
+ return calloc(1, sizeof(struct razor_relocations));
+}
+
+RAZOR_EXPORT void razor_relocations_add(struct razor_relocations *rr,
+ const char *oldpath, const char *newpath)
+{
+ int i, found = 0;
+ size_t len;
+
+ if (newpath && !strcmp(oldpath, newpath))
+ newpath = NULL;
+
+ for (i = 0; i < rr->n_relocations; i++) {
+ len = rr->relocations[i].oldlen;
+ if (!strncmp(rr->relocations[i].oldpath, oldpath, len)) {
+ found = !strcmp(rr->relocations[i].oldpath, oldpath);
+ break;
+ }
+ }
+
+ if (!newpath) {
+ if (found) {
+ free(rr->relocations[i].oldpath);
+ free(rr->relocations[i].newpath);
+ do {
+ rr->relocations[i] = rr->relocations[i + 1];
+ } while (rr->relocations[++i].oldpath);
+ }
+ return;
+ }
+
+ if (found) {
+ free(rr->relocations[i].newpath);
+ rr->relocations[i].newpath = strdup(newpath);
+ rr->relocations[i].newlen = strlen(newpath);
+ return;
+ }
+
+ if (!rr->n_relocations++)
+ rr->relocations = calloc(1, sizeof *rr->relocations);
+ else {
+ rr->relocations = realloc(rr->relocations,
+ rr->n_relocations * sizeof *rr->relocations);
+ memmove(rr->relocations + i + 1, rr->relocations + i,
+ (rr->n_relocations - i - 1) * sizeof *rr->relocations);
+ }
+
+ rr->relocations[i].flags = 0;
+ rr->relocations[i].oldpath = strdup(oldpath);
+ rr->relocations[i].newpath = strdup(newpath);
+ rr->relocations[i].oldlen = strlen(oldpath);
+ rr->relocations[i].newlen = strlen(newpath);
+}
+
+RAZOR_EXPORT void
+razor_relocations_set_rpm(struct razor_relocations *rr, struct razor_rpm *rpm)
+{
+ int i, j;
+
+ for (i = 0; i < rr->n_relocations; i++) {
+ rr->relocations[i].flags &= ~RAZOR_RELOCATION_ACTIVE;
+ for (j = 0; j < rpm->n_prefixes; j++)
+ if (!strcmp(rpm->prefixes[j],
+ rr->relocations[i].oldpath)) {
+ rr->relocations[i].flags |= RAZOR_RELOCATION_ACTIVE;
+ break;
+ }
+ }
+}
+
+RAZOR_EXPORT const char *
+razor_relocations_apply(struct razor_relocations *rr, const char *path)
+{
+ int i;
+ size_t len;
+
+ for (i = 0; i < rr->n_relocations; i++)
+ if (rr->relocations[i].flags & RAZOR_RELOCATION_ACTIVE &&
+ !strncmp(path, rr->relocations[i].oldpath,
+ rr->relocations[i].oldlen))
+ break;
+
+ if (i < rr->n_relocations) {
+ free(rr->path);
+ len = strlen(path + rr->relocations[i].oldlen) +
+ rr->relocations[i].newlen;
+ rr->path = malloc(len + 1);
+ memcpy(rr->path, rr->relocations[i].newpath,
+ rr->relocations[i].newlen);
+ strcpy(rr->path + rr->relocations[i].newlen,
+ path + rr->relocations[i].oldlen);
+ return rr->path;
+ } else
+ return path;
+}
+
+RAZOR_EXPORT void razor_relocations_destroy(struct razor_relocations *rr)
+{
+ printf("razor_relocations_destroy(rr=%p): path=%p, rel=%p\n",
+ rr,rr->path,rr->relocations);
+ free(rr->path);
+ free(rr->relocations);
+ free(rr);
+}
+
static struct rpm_header_index *
razor_rpm_get_header(struct razor_rpm *rpm, unsigned int tag)
{
struct razor_rpm *rpm;
struct rpm_header_index *base, *index;
unsigned int count, i, nindex, hsize;
- const char *name;
+ const char *name, *prefix;
assert (filename != NULL);
}
}
+ prefix = razor_rpm_get_indirect(rpm, RPMTAG_PREFIXES, &count);
+ if (prefix) {
+ rpm->prefixes = calloc(count, sizeof *rpm->prefixes);
+ for (i = 0; i < count; i++) {
+ rpm->prefixes[i] = prefix;
+ prefix += strlen(prefix) + 1;
+ }
+ rpm->n_prefixes = count;
+ } else {
+ prefix = razor_rpm_get_indirect(rpm, RPMTAG_DEFAULTPREFIX,
+ &count);
+ if (prefix) {
+ fprintf(stderr, "default prefix not supported\n");
+ return NULL;
+ }
+ }
+
return rpm;
}
+RAZOR_EXPORT void razor_rpm_set_relocations(struct razor_rpm *rpm,
+ struct razor_relocations *rr)
+{
+ assert (rpm != NULL);
+
+ rpm->relocations = rr;
+}
+
struct cpio_file_header {
char magic[6];
char inode[8];
struct cpio_file_header *header;
struct stat buf;
unsigned int mode;
- char *path;
+ const char *path;
size_t filesize;
assert (rpm != NULL);
return -1;
}
+ if (rpm->relocations)
+ razor_relocations_set_rpm(rpm->relocations, rpm);
+
if (installer_init(&installer))
return -1;
installer_align(&installer, 4))
return -1;
- path = (char *) installer.buffer;
+ path = (const char *) installer.buffer;
/* This convention is so lame... */
if (strcmp(path, "TRAILER!!!") == 0)
break;
installer.rest = filesize;
- if (create_path(&installer, path + 1, mode) < 0)
+ path++;
+ if (rpm->relocations)
+ path = razor_relocations_apply(rpm->relocations, path);
+ if (create_path(&installer, path, mode) < 0)
return -1;
if (installer_align(&installer, 4))
return -1;
assert (rpm != NULL);
free(rpm->dirs);
+ free(rpm->prefixes);
err = razor_file_free_contents(rpm->map, rpm->size);
free(rpm);
test_driver_LDADD = $(EXPAT_LIBS) $(top_builddir)/librazor/librazor.la $(EXTRA_LIBS)
TESTS = test-driver
+XFAIL_TESTS = test-driver
EXTRA_DIST = \
test.xml
/*
* Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
* Copyright (C) 2008 Red Hat, Inc
+ * Copyright (C) 2009 J. Ali Harlow <ali@juiblex.co.uk>
*
* 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
return 0;
}
+static struct razor_set *
+relocate_packages(struct razor_set *set, struct razor_relocations *relocations)
+{
+ struct razor_importer *importer;
+ struct razor_property_iterator *prop_iter;
+ struct razor_package_iterator *pkg_iter;
+ struct razor_file_iterator *file_iter;
+ struct razor_package *package;
+ struct razor_property *property;
+ struct razor_rpm *rpm;
+ const char *name, *version, *arch, *summary, *desc, *url, *license;
+ char file[PATH_MAX];
+ uint32_t flags;
+
+ importer = razor_importer_create();
+ pkg_iter = razor_package_iterator_create(set);
+
+ while (razor_package_iterator_next(pkg_iter, &package,
+ RAZOR_DETAIL_NAME, &name,
+ RAZOR_DETAIL_VERSION, &version,
+ RAZOR_DETAIL_ARCH, &arch,
+ RAZOR_DETAIL_SUMMARY, &summary,
+ RAZOR_DETAIL_DESCRIPTION, &desc,
+ RAZOR_DETAIL_URL, &url,
+ RAZOR_DETAIL_LICENSE, &license,
+ RAZOR_DETAIL_LAST)) {
+ snprintf(file, sizeof file,
+ "rpms/%s", rpm_filename(name, version, arch));
+ rpm = razor_rpm_open(file);
+ if (rpm == NULL) {
+ fprintf(stderr, "failed to open rpm %s\n", file);
+ razor_package_iterator_destroy(pkg_iter);
+ razor_importer_destroy(importer);
+ return NULL;
+ }
+
+ razor_relocations_set_rpm(relocations, rpm);
+ razor_rpm_close(rpm);
+
+ razor_importer_begin_package(importer, name, version, arch);
+ razor_importer_add_details(importer,
+ summary, desc, url, license);
+
+ prop_iter = razor_property_iterator_create(set, package);
+ while (razor_property_iterator_next(prop_iter, &property,
+ &name, &flags, &version))
+ razor_importer_add_property(importer,
+ name, flags, version);
+ razor_property_iterator_destroy(prop_iter);
+
+ file_iter = razor_file_iterator_create(set, package);
+ while (razor_file_iterator_next(file_iter, &name)) {
+ name = razor_relocations_apply(relocations, name);
+ razor_importer_add_file(importer, name);
+ }
+ razor_file_iterator_destroy(file_iter);
+
+ razor_importer_finish_package(importer);
+ }
+
+ razor_package_iterator_destroy(pkg_iter);
+ return razor_importer_finish(importer);
+}
+
static int
-install_packages(struct razor_set *system, struct razor_set *next)
+install_packages(struct razor_set *system, struct razor_set *next,
+ struct razor_relocations *relocations)
{
struct razor_install_iterator *ii;
struct razor_package *package;
fprintf(stderr, "failed to open rpm %s\n", file);
return -1;
}
+ if (relocations)
+ razor_rpm_set_relocations(rpm, relocations);
if (razor_rpm_install(rpm, install_root) < 0) {
fprintf(stderr,
"failed to install rpm %s\n", file);
command_install(int argc, const char *argv[])
{
struct razor_root *root;
- struct razor_set *system, *upstream, *next;
+ struct razor_relocations *relocations=NULL;
+ struct razor_set *system, *upstream, *next, *set;
struct razor_transaction *trans;
- int i = 0, dependencies = 1;
-
- if (i < argc && strcmp(argv[i], "--no-dependencies") == 0) {
- dependencies = 0;
- i++;
- }
+ int i, len, dependencies = 1;
+ char *oldpath;
root = razor_root_open(install_root);
if (root == NULL)
return 1;
+ for (i = 0; i < argc; i++) {
+ if (strcmp(argv[i], "--no-dependencies") == 0)
+ dependencies = 0;
+ else if (strcmp(argv[i], "--relocate") == 0) {
+ i++;
+ if (i >= argc || strchr(argv[i], '=') == NULL) {
+ fprintf(stderr,
+ "Usage: razor install [OPTION...] RPM\n");
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, " [--no-dependencies]\n");
+ fprintf(stderr,
+ " [--relocate OLDPATH=NEWPATH] RPM\n");
+ return -1;
+ }
+ len = strchr(argv[i], '=') - argv[i];
+ oldpath = malloc(len + 1);
+ strncpy(oldpath, argv[i], len);
+ oldpath[len] = '\0';
+ if (!relocations)
+ relocations = razor_relocations_create();
+ razor_relocations_add(relocations, oldpath,
+ argv[i] + len + 1);
+ free(oldpath);
+ } else
+ break;
+ }
+
system = razor_root_get_system_set(root);
upstream = razor_set_open(rawhide_repo_filename);
if (upstream == NULL ||
return 1;
}
+ if (relocations) {
+ set = relocate_packages(upstream, relocations);
+ razor_set_destroy(upstream);
+ upstream = set;
+ }
+
trans = razor_transaction_create(system, upstream);
for (; i < argc; i++) {
return 1;
}
- install_packages(system, next);
+ install_packages(system, next, relocations);
+ if (relocations)
+ razor_relocations_destroy(relocations);
razor_set_destroy(next);
razor_set_destroy(upstream);
--- /dev/null
+## Process this file with automake to produce Makefile.in
+
+check_SCRIPTS = relocate
+
+relocate: relocate.sh primary.xml.gz
+ cp $(srcdir)/relocate.sh relocate
+
+primary.xml.gz: zsh.spec zip.spec zap.spec Makefile
+ rm -rf rpmbuild rpms repodata
+ mkdir -p rpmbuild/BUILD rpmbuild/RPMS
+ rpmbuild --define "_topdir `pwd`/rpmbuild" -bb $(srcdir)/zap.spec
+ rpmbuild --define "_topdir `pwd`/rpmbuild" -bb $(srcdir)/zip.spec
+ rpmbuild --define "_topdir `pwd`/rpmbuild" -bb $(srcdir)/zsh.spec
+ mkdir rpms
+ mv rpmbuild/RPMS/noarch/*.rpm rpms
+ rm -rf rpmbuild
+ createrepo -o . rpms
+ cp repodata/primary.xml.gz repodata/filelists.xml.gz .
+
+TESTS = $(check_SCRIPTS)
+
+EXTRA_DIST = \
+ zap.spec \
+ zip.spec \
+ zsh.spec \
+ relocate.sh
+
+clean-local :
+ rm -f *~
+
--- /dev/null
+#!/bin/sh
+check_file()
+{
+ ../src/razor list-files | grep -x "$1" > /dev/null
+ if [ $? -ne 0 ]; then
+ echo $1: Not in database >&2
+ exit 1
+ fi
+ if [ ! -e "$RAZOR_ROOT$1" ]; then
+ echo $1: Not in filesystem >&2
+ exit 1
+ fi
+}
+export RAZOR_ROOT=`mktemp -dt` || exit 1
+../src/razor init || exit 1
+export YUM_URL="file://localhost/`pwd`"
+../src/razor import-yum || exit 1
+../src/razor install zap || exit 1
+../src/razor install --relocate /usr=/opt --relocate /etc=/opt/etc zsh || exit 1
+check_file /etc/zsh.conf
+check_file /usr/bin/zap
+check_file /opt/bin/zip
+check_file /opt/bin/zsh
+rm -rf "$RAZOR_ROOT"
--- /dev/null
+Name: zap
+Summary: Test package
+Group: Test
+License: GPL
+Version: 1
+Release: 1
+Source: zap.tar
+BuildArch: noarch
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+Prefix: /usr
+
+%description
+Test package
+
+%prep
+
+%build
+
+%install
+mkdir -p $RPM_BUILD_ROOT/usr/bin
+touch $RPM_BUILD_ROOT/usr/bin/zap
+
+%clean
+
+%files
+/usr/bin/zap
--- /dev/null
+Name: zip
+Summary: Test package
+Group: Test
+License: GPL
+Version: 1
+Release: 1
+Source: zip.tar
+BuildArch: noarch
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+Prefix: /usr
+Requires: zap
+
+%description
+Test package
+
+%prep
+
+%build
+
+%install
+mkdir -p $RPM_BUILD_ROOT/usr/bin
+touch $RPM_BUILD_ROOT/usr/bin/zip
+
+%clean
+
+%files
+/usr/bin/zip
--- /dev/null
+Name: zsh
+Summary: Test package
+Group: Test
+License: GPL
+Version: 1
+Release: 1
+Source: zsh.tar
+BuildArch: noarch
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+Prefix: /usr
+Requires: zip
+
+%description
+Test package
+
+%prep
+
+%build
+
+%install
+mkdir -p $RPM_BUILD_ROOT/usr/bin
+mkdir -p $RPM_BUILD_ROOT/etc
+touch $RPM_BUILD_ROOT/usr/bin/zsh
+touch $RPM_BUILD_ROOT/etc/zsh.conf
+
+%clean
+
+%files
+/usr/bin/zsh
+/etc/zsh.conf