1.1 --- a/librazor/rpm.c Tue Jan 13 17:04:51 2009 +0000
1.2 +++ b/librazor/rpm.c Thu Jan 22 22:54:45 2009 +0000
1.3 @@ -1,6 +1,7 @@
1.4 /*
1.5 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
1.6 * Copyright (C) 2008 Red Hat, Inc
1.7 + * Copyright (C) 2009 J. Ali Harlow <ali@juiblex.co.uk>
1.8 *
1.9 * This program is free software; you can redistribute it and/or modify
1.10 * it under the terms of the GNU General Public License as published by
1.11 @@ -248,12 +249,144 @@
1.12 struct rpm_header *signature;
1.13 struct rpm_header *header;
1.14 const char **dirs;
1.15 + unsigned int n_prefixes;
1.16 + const char **prefixes;
1.17 const char *pool;
1.18 void *map;
1.19 size_t size;
1.20 void *payload;
1.21 + struct razor_relocations *relocations;
1.22 };
1.23
1.24 +enum razor_relocation_flags {
1.25 + RAZOR_RELOCATION_ACTIVE = 1 << 0,
1.26 +};
1.27 +
1.28 +struct razor_relocation {
1.29 + enum razor_relocation_flags flags;
1.30 + size_t oldlen;
1.31 + size_t newlen;
1.32 + char *oldpath;
1.33 + char *newpath;
1.34 +};
1.35 +
1.36 +struct razor_relocations {
1.37 + /* Ordered such that if oldpath 1 starts with oldpath 2, then
1.38 + * oldpath 1 is listed first (ie., /usr/bin comes before /usr)
1.39 + * and terminated with a NULL oldpath.
1.40 + */
1.41 + struct razor_relocation *relocations;
1.42 + int n_relocations;
1.43 + char *path;
1.44 +};
1.45 +
1.46 +RAZOR_EXPORT struct razor_relocations *razor_relocations_create(void)
1.47 +{
1.48 + return calloc(1, sizeof(struct razor_relocations));
1.49 +}
1.50 +
1.51 +RAZOR_EXPORT void razor_relocations_add(struct razor_relocations *rr,
1.52 + const char *oldpath, const char *newpath)
1.53 +{
1.54 + int i, found = 0;
1.55 + size_t len;
1.56 +
1.57 + if (newpath && !strcmp(oldpath, newpath))
1.58 + newpath = NULL;
1.59 +
1.60 + for (i = 0; i < rr->n_relocations; i++) {
1.61 + len = rr->relocations[i].oldlen;
1.62 + if (!strncmp(rr->relocations[i].oldpath, oldpath, len)) {
1.63 + found = !strcmp(rr->relocations[i].oldpath, oldpath);
1.64 + break;
1.65 + }
1.66 + }
1.67 +
1.68 + if (!newpath) {
1.69 + if (found) {
1.70 + free(rr->relocations[i].oldpath);
1.71 + free(rr->relocations[i].newpath);
1.72 + do {
1.73 + rr->relocations[i] = rr->relocations[i + 1];
1.74 + } while (rr->relocations[++i].oldpath);
1.75 + }
1.76 + return;
1.77 + }
1.78 +
1.79 + if (found) {
1.80 + free(rr->relocations[i].newpath);
1.81 + rr->relocations[i].newpath = strdup(newpath);
1.82 + rr->relocations[i].newlen = strlen(newpath);
1.83 + return;
1.84 + }
1.85 +
1.86 + if (!rr->n_relocations++)
1.87 + rr->relocations = calloc(1, sizeof *rr->relocations);
1.88 + else {
1.89 + rr->relocations = realloc(rr->relocations,
1.90 + rr->n_relocations * sizeof *rr->relocations);
1.91 + memmove(rr->relocations + i + 1, rr->relocations + i,
1.92 + (rr->n_relocations - i - 1) * sizeof *rr->relocations);
1.93 + }
1.94 +
1.95 + rr->relocations[i].flags = 0;
1.96 + rr->relocations[i].oldpath = strdup(oldpath);
1.97 + rr->relocations[i].newpath = strdup(newpath);
1.98 + rr->relocations[i].oldlen = strlen(oldpath);
1.99 + rr->relocations[i].newlen = strlen(newpath);
1.100 +}
1.101 +
1.102 +RAZOR_EXPORT void
1.103 +razor_relocations_set_rpm(struct razor_relocations *rr, struct razor_rpm *rpm)
1.104 +{
1.105 + int i, j;
1.106 +
1.107 + for (i = 0; i < rr->n_relocations; i++) {
1.108 + rr->relocations[i].flags &= ~RAZOR_RELOCATION_ACTIVE;
1.109 + for (j = 0; j < rpm->n_prefixes; j++)
1.110 + if (!strcmp(rpm->prefixes[j],
1.111 + rr->relocations[i].oldpath)) {
1.112 + rr->relocations[i].flags |= RAZOR_RELOCATION_ACTIVE;
1.113 + break;
1.114 + }
1.115 + }
1.116 +}
1.117 +
1.118 +RAZOR_EXPORT const char *
1.119 +razor_relocations_apply(struct razor_relocations *rr, const char *path)
1.120 +{
1.121 + int i;
1.122 + size_t len;
1.123 +
1.124 + for (i = 0; i < rr->n_relocations; i++)
1.125 + if (rr->relocations[i].flags & RAZOR_RELOCATION_ACTIVE &&
1.126 + !strncmp(path, rr->relocations[i].oldpath,
1.127 + rr->relocations[i].oldlen))
1.128 + break;
1.129 +
1.130 + if (i < rr->n_relocations) {
1.131 + free(rr->path);
1.132 + len = strlen(path + rr->relocations[i].oldlen) +
1.133 + rr->relocations[i].newlen;
1.134 + rr->path = malloc(len + 1);
1.135 + memcpy(rr->path, rr->relocations[i].newpath,
1.136 + rr->relocations[i].newlen);
1.137 + strcpy(rr->path + rr->relocations[i].newlen,
1.138 + path + rr->relocations[i].oldlen);
1.139 + return rr->path;
1.140 + } else
1.141 + return path;
1.142 +}
1.143 +
1.144 +RAZOR_EXPORT void razor_relocations_destroy(struct razor_relocations *rr)
1.145 +{
1.146 + printf("razor_relocations_destroy(rr=%p): path=%p, rel=%p\n",
1.147 + rr,rr->path,rr->relocations);
1.148 + free(rr->path);
1.149 + free(rr->relocations);
1.150 + free(rr);
1.151 +}
1.152 +
1.153 static struct rpm_header_index *
1.154 razor_rpm_get_header(struct razor_rpm *rpm, unsigned int tag)
1.155 {
1.156 @@ -366,7 +499,7 @@
1.157 struct razor_rpm *rpm;
1.158 struct rpm_header_index *base, *index;
1.159 unsigned int count, i, nindex, hsize;
1.160 - const char *name;
1.161 + const char *name, *prefix;
1.162
1.163 assert (filename != NULL);
1.164
1.165 @@ -412,9 +545,34 @@
1.166 }
1.167 }
1.168
1.169 + prefix = razor_rpm_get_indirect(rpm, RPMTAG_PREFIXES, &count);
1.170 + if (prefix) {
1.171 + rpm->prefixes = calloc(count, sizeof *rpm->prefixes);
1.172 + for (i = 0; i < count; i++) {
1.173 + rpm->prefixes[i] = prefix;
1.174 + prefix += strlen(prefix) + 1;
1.175 + }
1.176 + rpm->n_prefixes = count;
1.177 + } else {
1.178 + prefix = razor_rpm_get_indirect(rpm, RPMTAG_DEFAULTPREFIX,
1.179 + &count);
1.180 + if (prefix) {
1.181 + fprintf(stderr, "default prefix not supported\n");
1.182 + return NULL;
1.183 + }
1.184 + }
1.185 +
1.186 return rpm;
1.187 }
1.188
1.189 +RAZOR_EXPORT void razor_rpm_set_relocations(struct razor_rpm *rpm,
1.190 + struct razor_relocations *rr)
1.191 +{
1.192 + assert (rpm != NULL);
1.193 +
1.194 + rpm->relocations = rr;
1.195 +}
1.196 +
1.197 struct cpio_file_header {
1.198 char magic[6];
1.199 char inode[8];
1.200 @@ -744,7 +902,7 @@
1.201 struct cpio_file_header *header;
1.202 struct stat buf;
1.203 unsigned int mode;
1.204 - char *path;
1.205 + const char *path;
1.206 size_t filesize;
1.207
1.208 assert (rpm != NULL);
1.209 @@ -761,6 +919,9 @@
1.210 return -1;
1.211 }
1.212
1.213 + if (rpm->relocations)
1.214 + razor_relocations_set_rpm(rpm->relocations, rpm);
1.215 +
1.216 if (installer_init(&installer))
1.217 return -1;
1.218
1.219 @@ -783,13 +944,16 @@
1.220 installer_align(&installer, 4))
1.221 return -1;
1.222
1.223 - path = (char *) installer.buffer;
1.224 + path = (const char *) installer.buffer;
1.225 /* This convention is so lame... */
1.226 if (strcmp(path, "TRAILER!!!") == 0)
1.227 break;
1.228
1.229 installer.rest = filesize;
1.230 - if (create_path(&installer, path + 1, mode) < 0)
1.231 + path++;
1.232 + if (rpm->relocations)
1.233 + path = razor_relocations_apply(rpm->relocations, path);
1.234 + if (create_path(&installer, path, mode) < 0)
1.235 return -1;
1.236 if (installer_align(&installer, 4))
1.237 return -1;
1.238 @@ -811,6 +975,7 @@
1.239 assert (rpm != NULL);
1.240
1.241 free(rpm->dirs);
1.242 + free(rpm->prefixes);
1.243 err = razor_file_free_contents(rpm->map, rpm->size);
1.244 free(rpm);
1.245