Support RPM_INSTALL_PREFIX{n} during uninstall
authorJ. Ali Harlow <ali@juiblex.co.uk>
Fri, 3 Jul 2009 17:02:33 +0000 (18:02 +0100)
committerJ. Ali Harlow <ali@juiblex.co.uk>
Fri, 3 Jul 2009 17:02:33 +0000 (18:02 +0100)
librazor/importer.c
librazor/merger.c
librazor/razor-internal.h
librazor/razor.c
librazor/razor.h
librazor/rpm.c
librazor/util.c
src/import-rpmdb.c
src/main.c
test/remove.sh

index bb4695a..e3956e0 100644 (file)
@@ -94,6 +94,7 @@ razor_importer_begin_package(struct razor_importer *importer,
 
        importer->package = p;
        array_init(&importer->properties);
+       array_init(&importer->install_prefixes);
 
        empty = hashtable_tokenize(&importer->details_table, "");
        importer->package->preun.program = empty;
@@ -116,7 +117,13 @@ razor_importer_finish_package(struct razor_importer *importer)
                       &importer->properties,
                       1);
 
+       list_set_array(&importer->package->install_prefixes,
+                      &importer->set->prefix_pool,
+                      &importer->install_prefixes,
+                      0);
+
        array_release(&importer->properties);
+       array_release(&importer->install_prefixes);
 }
 
 /**
@@ -176,6 +183,23 @@ razor_importer_add_script(struct razor_importer *importer,
 }
 
 /**
+ * razor_importer_add_install_prefixes:
+ * @importer: the %razor_importer
+ * @install_prefix: the relocated prefix
+ *
+ * Adds a relocated prefix for the current package.
+ **/
+RAZOR_EXPORT void
+razor_importer_add_install_prefix(struct razor_importer *importer,
+                                 const char *install_prefix)
+{
+       uint32_t *r;
+
+       r = array_add(&importer->install_prefixes, sizeof *r);
+       *r = hashtable_tokenize(&importer->table, install_prefix);
+}
+
+/**
  * razor_importer_add_property:
  * @importer: the %razor_importer
  * @name: name of the property
index 0935e23..39d8ccc 100644 (file)
@@ -75,12 +75,13 @@ void
 razor_merger_add_package(struct razor_merger *merger,
                         struct razor_package *package)
 {
-       char *pool;
+       char *pool, *s;
        struct list *r;
        struct razor_package *p;
        struct razor_set *set1;
        struct source *source;
-       uint32_t flags;
+       uint32_t flags, *prefix;
+       struct array install_prefixes;
 
        assert(merger->committed == 0);
 
@@ -117,6 +118,18 @@ razor_merger_add_package(struct razor_merger *merger,
                r = list_next(r);
        }
 
+       array_init(&install_prefixes);
+       r = list_first(&package->install_prefixes, &source->set->prefix_pool);
+       while (r) {
+               s = (char *)source->set->string_pool.data + r->data;
+               prefix = array_add(&install_prefixes, sizeof *prefix);
+               *prefix = hashtable_tokenize(&merger->table, s);
+               r = list_next(r);
+       }
+       list_set_array(&p->install_prefixes, &merger->set->prefix_pool,
+                       &install_prefixes, 0);
+       array_release(&install_prefixes);
+
        p->preun.program = hashtable_tokenize(&merger->table,
                                              &pool[package->preun.program]);
        p->preun.body = hashtable_tokenize(&merger->table,
index 0a8fc69..31a6b5e 100644 (file)
@@ -61,6 +61,7 @@ struct razor_set_header {
 #define RAZOR_PROPERTIES               "properties"
 #define RAZOR_PACKAGE_POOL             "package_pool"
 #define RAZOR_PROPERTY_POOL            "property_pool"
+#define RAZOR_PREFIX_POOL              "prefix_pool"
 
 #define RAZOR_DETAILS_STRING_POOL      "details_string_pool"
 
@@ -84,6 +85,7 @@ struct razor_package {
        uint32_t license;
        struct list_head properties;
        struct list_head files;
+       struct list_head install_prefixes;
        struct razor_script preun;
        struct razor_script postun;
 };
@@ -113,6 +115,7 @@ struct razor_set {
        struct array package_pool;
        struct array property_pool;
        struct array file_pool;
+       struct array prefix_pool;
        struct array file_string_pool;
        struct array details_string_pool;
 
@@ -147,6 +150,7 @@ struct razor_importer {
        struct array properties;
        struct array files;
        struct array file_requires;
+       struct array install_prefixes;
 };
 
 struct razor_package_iterator {
@@ -220,4 +224,16 @@ uint32_t *
 razor_qsort_with_data(void *base, size_t nelem, size_t size,
                      razor_compare_with_data_func_t compare, void *data);
 
+struct environment {
+       int is_set;
+       struct array vars, string_pool;
+};
+
+void environment_init(struct environment *env);
+void environment_add_variable(struct environment *env,
+                             const char *variable, const char *value);
+void environment_set(struct environment *env);
+void environment_unset(struct environment *env);
+void environment_release(struct environment *env);
+
 #endif /* _RAZOR_INTERNAL_H_ */
index a5e1a37..3fac1f2 100644 (file)
@@ -67,6 +67,7 @@ struct razor_set_section_index razor_sections[] = {
        { RAZOR_PROPERTIES,     offsetof(struct razor_set, properties) },
        { RAZOR_PACKAGE_POOL,   offsetof(struct razor_set, package_pool) },
        { RAZOR_PROPERTY_POOL,  offsetof(struct razor_set, property_pool) },
+       { RAZOR_PREFIX_POOL,    offsetof(struct razor_set, prefix_pool) },
 };
 
 struct razor_set_section_index razor_files_sections[] = {
@@ -377,9 +378,9 @@ razor_versioncmp(const char *s1, const char *s2)
 }
 
 static const char *
-razor_package_get_details_type(struct razor_set *set,
-                              struct razor_package *package,
-                              enum razor_detail_type type)
+razor_package_get_details_string(struct razor_set *set,
+                                struct razor_package *package,
+                                enum razor_detail_type type)
 {
        const char *pool;
 
@@ -434,6 +435,24 @@ razor_package_get_details_type(struct razor_set *set,
        }
 }
 
+static const char *const *
+razor_package_get_details_array(struct razor_set *set,
+                               struct razor_package *package,
+                               enum razor_detail_type type)
+{
+       switch (type) {
+       case RAZOR_DETAIL_PREFIXES:
+               /* We don't track prefixes in packages. Install prefixes
+                * are tracked, but we don't provide an API to get them.
+                */
+               return NULL;
+
+       default:
+               fprintf(stderr, "type %u not found\n", type);
+               return NULL;
+       }
+}
+
 /**
  * razor_package_get_details_varg:
  * @set: a %razor_set
@@ -447,14 +466,22 @@ razor_package_get_details_varg(struct razor_set *set,
 {
        int i;
        enum razor_detail_type type;
-       const char **data;
+       const char **string;
+       const char *const **array;
 
        for (i = 0;; i += 2) {
                type = va_arg(args, enum razor_detail_type);
                if (type == RAZOR_DETAIL_LAST)
                        break;
-               data = va_arg(args, const char **);
-               *data = razor_package_get_details_type(set, package, type);
+               if (type == RAZOR_DETAIL_PREFIXES) {
+                       array = va_arg(args, const char *const **);
+                       *array = razor_package_get_details_array(set, package,
+                                                                type);
+               } else {
+                       string = va_arg(args, const char **);
+                       *string = razor_package_get_details_string(set, package,
+                                                                  type);
+               }
        }
 
 }
@@ -501,7 +528,10 @@ razor_package_remove(struct razor_set *set, struct razor_package *package,
        struct razor_package *p;
        char buffer[PATH_MAX];
        const char *name, *program, *script;
-       int retval = 0, count;
+       int retval = 0, i, count;
+       struct environment env;
+       struct list *link;
+       const char *prefix;
 
        razor_package_get_details(set, package,
                                  RAZOR_DETAIL_PREUNPROG, &program,
@@ -535,7 +565,22 @@ razor_package_remove(struct razor_set *set, struct razor_package *package,
                                  RAZOR_DETAIL_POSTUN, &script,
                                  RAZOR_DETAIL_LAST);
 
-       return razor_run_script(root, RAZOR_PROPERTY_POSTUN, program, script);
+       environment_init(&env);
+       link = list_first(&package->install_prefixes, &set->prefix_pool);
+       for (i = 0; link; i++) {
+               prefix = (const char *)set->string_pool.data + link->data;
+               sprintf(buffer, "RPM_INSTALL_PREFIX%d", i);
+               environment_add_variable(&env, buffer, prefix);
+               link = list_next(link);
+       }
+       environment_set(&env);
+
+       retval = razor_run_script(root, RAZOR_PROPERTY_POSTUN, program, script);
+
+       environment_unset(&env);
+       environment_release(&env);
+
+       return retval;
 }
 
 RAZOR_EXPORT const char *
index a2fb076..f63b96b 100644 (file)
@@ -41,7 +41,8 @@ enum razor_detail_type {
        RAZOR_DETAIL_PREUNPROG,
        RAZOR_DETAIL_PREUN,
        RAZOR_DETAIL_POSTUNPROG,
-       RAZOR_DETAIL_POSTUN
+       RAZOR_DETAIL_POSTUN,
+       RAZOR_DETAIL_PREFIXES
 };
 
 enum razor_property_flags {
@@ -349,6 +350,8 @@ void razor_importer_add_script(struct razor_importer *importer,
                               enum razor_property_flags script,
                               const char *program,
                               const char *body);
+void razor_importer_add_install_prefix(struct razor_importer *importer,
+                                      const char *install_prefix);
 void razor_importer_add_property(struct razor_importer *importer,
                                 const char *name,
                                 uint32_t flags,
index 87f910c..f3c2724 100644 (file)
@@ -509,7 +509,7 @@ razor_rpm_build_evr(struct razor_rpm *rpm)
 }
 
 static const char *
-razor_rpm_get_details_type(struct razor_rpm *rpm, enum razor_detail_type type)
+razor_rpm_get_details_string(struct razor_rpm *rpm, enum razor_detail_type type)
 {
        switch(type) {
        case RAZOR_DETAIL_NAME:
@@ -553,19 +553,39 @@ razor_rpm_get_details_type(struct razor_rpm *rpm, enum razor_detail_type type)
        }
 }
 
+static const char *const *
+razor_rpm_get_details_array(struct razor_rpm *rpm, enum razor_detail_type type)
+{
+       switch(type) {
+       case RAZOR_DETAIL_PREFIXES:
+               return rpm->prefixes;
+
+       default:
+               /* Impossible */
+               fprintf(stderr, "type %u not found\n", type);
+               return NULL;
+       }
+}
+
 void
 razor_rpm_get_details_varg(struct razor_rpm *rpm, va_list args)
 {
        int i;
        enum razor_detail_type type;
-       const char **data;
+       const char **string;
+       const char *const **array;
 
        for (i = 0;; i += 2) {
                type = va_arg(args, enum razor_detail_type);
                if (type == RAZOR_DETAIL_LAST)
                        break;
-               data = va_arg(args, const char **);
-                *data = razor_rpm_get_details_type(rpm, type);
+               if (type == RAZOR_DETAIL_PREFIXES) {
+                       array = va_arg(args, const char *const **);
+                       *array = razor_rpm_get_details_array(rpm, type);
+               } else {
+                       string = va_arg(args, const char **);
+                       *string = razor_rpm_get_details_string(rpm, type);
+               }
         }
 }
 
@@ -635,11 +655,12 @@ razor_rpm_open(const char *filename)
 
        prefix = razor_rpm_get_indirect(rpm, RPMTAG_PREFIXES, &count);
        if (prefix) {
-               rpm->prefixes = calloc(count, sizeof *rpm->prefixes);
+               rpm->prefixes = calloc(count + 1, sizeof *rpm->prefixes);
                for (i = 0; i < count; i++) {
                        rpm->prefixes[i] = prefix;
                        prefix += strlen(prefix) + 1;
                }
+               rpm->prefixes[i] = NULL;
                rpm->n_prefixes = count;
        } else {
                prefix = razor_rpm_get_indirect(rpm, RPMTAG_DEFAULTPREFIX,
@@ -935,7 +956,7 @@ run_script(struct installer *installer,
        struct razor_rpm *rpm = installer->rpm;
        const char *script = NULL, *program = NULL, *prefix;
        char buf[32], *p;
-       struct array prefix_pool;
+       struct environment env;
 
        program = razor_rpm_get_indirect(rpm, program_tag, NULL);
        script = razor_rpm_get_indirect(rpm, script_tag, NULL);
@@ -943,16 +964,14 @@ run_script(struct installer *installer,
                return 0;
 
        if (rpm->relocations) {
-               array_init(&prefix_pool);
+               environment_init(&env);
                for(i = 0; i < rpm->n_prefixes; i++) {
                        prefix = razor_relocations_apply(rpm->relocations,
                                                         rpm->prefixes[i]);
                        sprintf(buf, "RPM_INSTALL_PREFIX%d", i);
-                       p = array_add(&prefix_pool,
-                                     strlen(buf) + strlen(prefix) + 2);
-                       sprintf(p, "%s=%s", buf, prefix);
-                       putenv(p);
+                       environment_add_variable(&env, buf, prefix);
                }
+               environment_set(&env);
        }
 
        if (program && strcmp(program, "<lua>") == 0)
@@ -961,11 +980,8 @@ run_script(struct installer *installer,
                retval = run_script_external(installer->root, program, script);
 
        if (rpm->relocations) {
-               for(i = 0; i < rpm->n_prefixes; i++) {
-                       sprintf(buf, "RPM_INSTALL_PREFIX%d=", i);
-                       putenv(buf);
-               }
-               array_release(&prefix_pool);
+               environment_unset(&env);
+               environment_release(&env);
        }
 
        return retval;
index 5d1bc53..6bc5f6e 100644 (file)
@@ -36,6 +36,7 @@
 #if HAVE_SYS_MMAN_H
 #include <sys/mman.h>
 #endif
+#include <assert.h>
 
 #include "razor.h"
 #include "razor-internal.h"
@@ -293,3 +294,71 @@ razor_qsort_with_data(void *base, size_t nelem, size_t size,
 
        return map;
 }
+
+void environment_init(struct environment *env)
+{
+       env->is_set = 0;
+       array_init(&env->string_pool);
+       array_init(&env->vars);
+}
+
+void environment_add_variable(struct environment *env,
+                             const char *variable, const char *value)
+{
+       char *s;
+       uint32_t *r;
+       assert(!env->is_set);
+
+       s = array_add(&env->string_pool,
+                     strlen(variable) + strlen(value) + 2);
+       sprintf(s, "%s=%s", variable, value);
+       r = array_add(&env->vars, sizeof *r);
+       *r = s - (char *)env->string_pool.data;
+}
+
+void environment_set(struct environment *env)
+{
+       int i, count;
+       char *s;
+        uint32_t *r;
+
+       if (!env->is_set) {
+               count = env->vars.size / sizeof(uint32_t);
+               r = (uint32_t *)env->vars.data;
+               for (i = 0; i < count; i++) {
+                       s = env->string_pool.data + *r++;
+                       putenv(s);
+               }
+
+               env->is_set = 1;
+       }
+}
+
+void environment_unset(struct environment *env)
+{
+       int i, count;
+       char c, *s, *t;
+        uint32_t *r;
+
+       if (env->is_set) {
+               count = env->vars.size / sizeof(uint32_t);
+               r = (uint32_t *)env->vars.data;
+               for (i = 0; i < count; i++) {
+                       s = env->string_pool.data + *r++;
+                       t = strchr(s, '=') + 1;
+                       c = *t;
+                       *t = '\0';
+                       putenv(s);
+                       *t = c;
+               }
+
+               env->is_set = 0;
+       }
+}
+
+void environment_release(struct environment *env)
+{
+       environment_unset(env);
+       array_release(&env->string_pool);
+       array_release(&env->vars);
+}
index 8ec7cbe..530c122 100644 (file)
@@ -105,6 +105,7 @@ razor_set_create_from_rpmdb(void)
        union rpm_entry name, epoch, version, release, arch;
        union rpm_entry summary, description, url, license;
        union rpm_entry basenames, dirnames, dirindexes;
+       union rpm_entry install_prefixes;
        char filename[PATH_MAX], evr[128], buf[16];
        rpmdb db;
        int imported_count = 0;
@@ -185,6 +186,12 @@ razor_set_create_from_rpmdb(void)
                add_script(importer, RAZOR_PROPERTY_POSTUN, h,
                           RPMTAG_POSTUNPROG, RPMTAG_POSTUN);
 
+               headerGetEntry(h, RPMTAG_INSTPREFIXES, &type,
+                              &install_prefixes.p, &count);
+               for (i = 0; i < count; i++)
+                       razor_importer_add_install_prefix(importer,
+                                                         install_prefixes.list[i]);
+
                razor_importer_finish_package(importer);
 
                printf("\rimporting %d", ++imported_count);
index 74908e6..43a6612 100644 (file)
@@ -808,6 +808,7 @@ download_packages(struct razor_set *system, struct razor_set *next)
 static struct razor_set *
 relocate_packages(struct razor_set *set, struct razor_relocations *relocations)
 {
+       int i;
        struct razor_importer *importer;
        struct razor_property_iterator *prop_iter;
        struct razor_package_iterator *pkg_iter;
@@ -817,6 +818,8 @@ relocate_packages(struct razor_set *set, struct razor_relocations *relocations)
        struct razor_rpm *rpm;
        const char *name, *version, *arch, *summary, *desc, *url, *license;
        const char *preunprog, *preun, *postunprog, *postun;
+       const char *install_prefix;
+       const char *const *prefixes;
        char file[PATH_MAX];
        uint32_t flags;
 
@@ -847,12 +850,22 @@ relocate_packages(struct razor_set *set, struct razor_relocations *relocations)
                }
 
                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);
 
+               razor_rpm_get_details(rpm, RAZOR_DETAIL_PREFIXES, &prefixes,
+                                     RAZOR_DETAIL_LAST);
+               for (i = 0; prefixes && prefixes[i]; i++) {
+                       install_prefix = razor_relocations_apply(relocations,
+                                                                prefixes[i]);
+                       razor_importer_add_install_prefix(importer,
+                                                         install_prefix);
+               }
+
+               razor_rpm_close(rpm);
+
                prop_iter = razor_property_iterator_create(set, package);
                while (razor_property_iterator_next(prop_iter, &property,
                                                    &name, &flags, &version))
index 293b8b4..ce2ceda 100755 (executable)
@@ -58,20 +58,20 @@ 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 zip || exit 1
-fs_check_file /usr/var/lib/zip/data.zap
+../src/razor install --relocate /usr=/opt zip || exit 1
+fs_check_file /opt/var/lib/zip/data.zap
 ../src/razor remove zip || exit 1
-check_file /usr/bin/zap
-check_no_file /usr/bin/zip
-fs_check_no_file /usr/var/lib/zip/data.zap
-../src/razor install zsh || exit 1
-../src/razor install zsh2 || exit 1
+check_file /opt/bin/zap
+check_no_file /opt/bin/zip
+fs_check_no_file /opt/var/lib/zip/data.zap
+../src/razor install --relocate /usr=/opt zsh || exit 1
+../src/razor install --relocate /usr=/opt zsh2 || exit 1
 ../src/razor remove zsh || exit 1
 check_file /etc/zsh.conf
-check_no_file /usr/bin/zsh
-../src/razor install zsh2 || exit 1
-../src/razor install zsh2 || exit 1
-fs_check_file /usr/var/lib/zip/data.zap
+check_no_file /opt/bin/zsh
+check_no_file /opt/var/lib/zsh/data.zip
+../src/razor install --relocate /usr=/opt zsh2 || exit 1
+fs_check_file /opt/var/lib/zip/data.zap
 ../src/razor remove zsh2 zip || exit 1
-fs_check_no_file /usr/var/lib/zip/data.zap
+fs_check_no_file /opt/var/lib/zip/data.zap
 rm -rf "$RAZOR_ROOT"