Add support for preloading lua modules. This is useful both when
providing lua bindings to applications based on librazor and when
producing static binaries using librazor (where otherwise the lua
POSIX library would need to be included as an additional dynamic
object).
2 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
3 * Copyright (C) 2008 Red Hat, Inc
4 * Copyright (C) 2009 J. Ali Harlow <ali@juiblex.co.uk>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include <sys/types.h>
37 #include <winsock2.h> /* For ntohl() */
39 #include <arpa/inet.h>
46 #include "razor-internal.h"
52 #define RPM_LEAD_SIZE 96
55 PIPE = 1, /*!< pipe/fifo */
56 CDEV = 2, /*!< character device */
57 XDIR = 4, /*!< directory */
58 BDEV = 6, /*!< block device */
59 REG = 8, /*!< regular file */
60 LINK = 10, /*!< hard link */
61 SOCK = 12 /*!< socket */
65 RPMSENSE_LESS = 1 << 1,
66 RPMSENSE_GREATER = 1 << 2,
67 RPMSENSE_EQUAL = 1 << 3,
68 RPMSENSE_PREREQ = 1 << 6,
69 RPMSENSE_SCRIPT_PRE = 1 << 9,
70 RPMSENSE_SCRIPT_POST = 1 << 10,
71 RPMSENSE_SCRIPT_PREUN = 1 << 11,
72 RPMSENSE_SCRIPT_POSTUN = 1 << 12,
76 RPMTAG_NAME = 1000, /* s */
77 RPMTAG_VERSION = 1001, /* s */
78 RPMTAG_RELEASE = 1002, /* s */
79 RPMTAG_EPOCH = 1003, /* i */
80 RPMTAG_SUMMARY = 1004, /* s{} */
81 RPMTAG_DESCRIPTION = 1005, /* s{} */
82 RPMTAG_BUILDTIME = 1006, /* i */
83 RPMTAG_BUILDHOST = 1007, /* s */
84 RPMTAG_INSTALLTIME = 1008, /* i */
85 RPMTAG_SIZE = 1009, /* i */
86 RPMTAG_DISTRIBUTION = 1010, /* s */
87 RPMTAG_VENDOR = 1011, /* s */
88 RPMTAG_GIF = 1012, /* x */
89 RPMTAG_XPM = 1013, /* x */
90 RPMTAG_LICENSE = 1014, /* s */
91 RPMTAG_PACKAGER = 1015, /* s */
92 RPMTAG_GROUP = 1016, /* s{} */
93 RPMTAG_CHANGELOG = 1017, /*!< s[] internal */
94 RPMTAG_SOURCE = 1018, /* s[] */
95 RPMTAG_PATCH = 1019, /* s[] */
96 RPMTAG_URL = 1020, /* s */
97 RPMTAG_OS = 1021, /* s legacy used int */
98 RPMTAG_ARCH = 1022, /* s legacy used int */
99 RPMTAG_PREIN = 1023, /* s */
100 RPMTAG_POSTIN = 1024, /* s */
101 RPMTAG_PREUN = 1025, /* s */
102 RPMTAG_POSTUN = 1026, /* s */
103 RPMTAG_OLDFILENAMES = 1027, /* s[] obsolete */
104 RPMTAG_FILESIZES = 1028, /* i */
105 RPMTAG_FILESTATES = 1029, /* c */
106 RPMTAG_FILEMODES = 1030, /* h */
107 RPMTAG_FILEUIDS = 1031, /*!< internal */
108 RPMTAG_FILEGIDS = 1032, /*!< internal */
109 RPMTAG_FILERDEVS = 1033, /* h */
110 RPMTAG_FILEMTIMES = 1034, /* i */
111 RPMTAG_FILEMD5S = 1035, /* s[] */
112 RPMTAG_FILELINKTOS = 1036, /* s[] */
113 RPMTAG_FILEFLAGS = 1037, /* i */
114 RPMTAG_ROOT = 1038, /*!< internal - obsolete */
115 RPMTAG_FILEUSERNAME = 1039, /* s[] */
116 RPMTAG_FILEGROUPNAME = 1040, /* s[] */
117 RPMTAG_EXCLUDE = 1041, /*!< internal - obsolete */
118 RPMTAG_EXCLUSIVE = 1042, /*!< internal - obsolete */
120 RPMTAG_SOURCERPM = 1044, /* s */
121 RPMTAG_FILEVERIFYFLAGS = 1045, /* i */
122 RPMTAG_ARCHIVESIZE = 1046, /* i */
123 RPMTAG_PROVIDENAME = 1047, /* s[] */
124 RPMTAG_REQUIREFLAGS = 1048, /* i */
125 RPMTAG_REQUIRENAME = 1049, /* s[] */
126 RPMTAG_REQUIREVERSION = 1050, /* s[] */
127 RPMTAG_NOSOURCE = 1051, /*!< internal */
128 RPMTAG_NOPATCH = 1052, /*!< internal */
129 RPMTAG_CONFLICTFLAGS = 1053, /* i */
130 RPMTAG_CONFLICTNAME = 1054, /* s[] */
131 RPMTAG_CONFLICTVERSION = 1055, /* s[] */
132 RPMTAG_DEFAULTPREFIX = 1056, /*!< internal - deprecated */
133 RPMTAG_BUILDROOT = 1057, /*!< internal */
134 RPMTAG_INSTALLPREFIX = 1058, /*!< internal - deprecated */
135 RPMTAG_EXCLUDEARCH = 1059,
136 RPMTAG_EXCLUDEOS = 1060,
137 RPMTAG_EXCLUSIVEARCH = 1061,
138 RPMTAG_EXCLUSIVEOS = 1062,
139 RPMTAG_AUTOREQPROV = 1063, /*!< internal */
140 RPMTAG_RPMVERSION = 1064, /* s */
141 RPMTAG_TRIGGERSCRIPTS = 1065, /* s[] */
142 RPMTAG_TRIGGERNAME = 1066, /* s[] */
143 RPMTAG_TRIGGERVERSION = 1067, /* s[] */
144 RPMTAG_TRIGGERFLAGS = 1068, /* i */
145 RPMTAG_TRIGGERINDEX = 1069, /* i */
146 RPMTAG_VERIFYSCRIPT = 1079, /* s */
147 RPMTAG_CHANGELOGTIME = 1080, /* i */
148 RPMTAG_CHANGELOGNAME = 1081, /* s[] */
149 RPMTAG_CHANGELOGTEXT = 1082, /* s[] */
150 RPMTAG_BROKENMD5 = 1083, /*!< internal - obsolete */
151 RPMTAG_PREREQ = 1084, /*!< internal */
152 RPMTAG_PREINPROG = 1085, /* s */
153 RPMTAG_POSTINPROG = 1086, /* s */
154 RPMTAG_PREUNPROG = 1087, /* s */
155 RPMTAG_POSTUNPROG = 1088, /* s */
156 RPMTAG_BUILDARCHS = 1089,
157 RPMTAG_OBSOLETENAME = 1090, /* s[] */
158 RPMTAG_VERIFYSCRIPTPROG = 1091, /* s */
159 RPMTAG_TRIGGERSCRIPTPROG = 1092, /* s */
160 RPMTAG_DOCDIR = 1093, /*!< internal */
161 RPMTAG_COOKIE = 1094, /* s */
162 RPMTAG_FILEDEVICES = 1095, /* i */
163 RPMTAG_FILEINODES = 1096, /* i */
164 RPMTAG_FILELANGS = 1097, /* s[] */
165 RPMTAG_PREFIXES = 1098, /* s[] */
166 RPMTAG_INSTPREFIXES = 1099, /* s[] */
167 RPMTAG_TRIGGERIN = 1100, /*!< internal */
168 RPMTAG_TRIGGERUN = 1101, /*!< internal */
169 RPMTAG_TRIGGERPOSTUN = 1102, /*!< internal */
170 RPMTAG_AUTOREQ = 1103, /*!< internal */
171 RPMTAG_AUTOPROV = 1104, /*!< internal */
172 RPMTAG_CAPABILITY = 1105, /*!< internal - obsolete */
173 RPMTAG_SOURCEPACKAGE = 1106, /*!< i src.rpm header marker */
174 RPMTAG_OLDORIGFILENAMES = 1107, /*!< internal - obsolete */
175 RPMTAG_BUILDPREREQ = 1108, /*!< internal */
176 RPMTAG_BUILDREQUIRES = 1109, /*!< internal */
177 RPMTAG_BUILDCONFLICTS = 1110, /*!< internal */
178 RPMTAG_BUILDMACROS = 1111, /*!< internal - unused */
179 RPMTAG_PROVIDEFLAGS = 1112, /* i */
180 RPMTAG_PROVIDEVERSION = 1113, /* s[] */
181 RPMTAG_OBSOLETEFLAGS = 1114, /* i */
182 RPMTAG_OBSOLETEVERSION = 1115, /* s[] */
183 RPMTAG_DIRINDEXES = 1116, /* i */
184 RPMTAG_BASENAMES = 1117, /* s[] */
185 RPMTAG_DIRNAMES = 1118, /* s[] */
186 RPMTAG_ORIGDIRINDEXES = 1119, /*!< internal */
187 RPMTAG_ORIGBASENAMES = 1120, /*!< internal */
188 RPMTAG_ORIGDIRNAMES = 1121, /*!< internal */
189 RPMTAG_OPTFLAGS = 1122, /* s */
190 RPMTAG_DISTURL = 1123, /* s */
191 RPMTAG_PAYLOADFORMAT = 1124, /* s */
192 RPMTAG_PAYLOADCOMPRESSOR = 1125, /* s */
193 RPMTAG_PAYLOADFLAGS = 1126, /* s */
194 RPMTAG_INSTALLCOLOR = 1127, /*!< i transaction color when installed */
195 RPMTAG_INSTALLTID = 1128, /* i */
196 RPMTAG_REMOVETID = 1129, /* i */
197 RPMTAG_SHA1RHN = 1130, /*!< internal - obsolete */
198 RPMTAG_RHNPLATFORM = 1131, /* s */
199 RPMTAG_PLATFORM = 1132, /* s */
200 RPMTAG_PATCHESNAME = 1133, /*!< placeholder (SuSE) */
201 RPMTAG_PATCHESFLAGS = 1134, /*!< placeholder (SuSE) */
202 RPMTAG_PATCHESVERSION = 1135, /*!< placeholder (SuSE) */
203 RPMTAG_CACHECTIME = 1136, /* i */
204 RPMTAG_CACHEPKGPATH = 1137, /* s */
205 RPMTAG_CACHEPKGSIZE = 1138, /* i */
206 RPMTAG_CACHEPKGMTIME = 1139, /* i */
207 RPMTAG_FILECOLORS = 1140, /* i */
208 RPMTAG_FILECLASS = 1141, /* i */
209 RPMTAG_CLASSDICT = 1142, /* s[] */
210 RPMTAG_FILEDEPENDSX = 1143, /* i */
211 RPMTAG_FILEDEPENDSN = 1144, /* i */
212 RPMTAG_DEPENDSDICT = 1145, /* i */
213 RPMTAG_SOURCEPKGID = 1146, /* x */
214 RPMTAG_FILECONTEXTS = 1147, /* s[] */
215 RPMTAG_FSCONTEXTS = 1148, /*!< s[] extension */
216 RPMTAG_RECONTEXTS = 1149, /*!< s[] extension */
217 RPMTAG_POLICIES = 1150, /*!< s[] selinux *.te policy file. */
218 RPMTAG_PRETRANS = 1151, /* s */
219 RPMTAG_POSTTRANS = 1152, /* s */
220 RPMTAG_PRETRANSPROG = 1153, /* s */
221 RPMTAG_POSTTRANSPROG = 1154, /* s */
222 RPMTAG_DISTTAG = 1155, /* s */
223 RPMTAG_SUGGESTSNAME = 1156, /* s[] extension placeholder */
224 RPMTAG_SUGGESTSVERSION = 1157, /* s[] extension placeholder */
225 RPMTAG_SUGGESTSFLAGS = 1158, /* i extension placeholder */
226 RPMTAG_ENHANCESNAME = 1159, /* s[] extension placeholder */
227 RPMTAG_ENHANCESVERSION = 1160, /* s[] extension placeholder */
228 RPMTAG_ENHANCESFLAGS = 1161, /* i extension placeholder */
229 RPMTAG_PRIORITY = 1162, /* i extension placeholder */
230 RPMTAG_CVSID = 1163, /* s */
231 RPMTAG_TRIGGERPREIN = 1171, /*!< internal */
235 unsigned char magic[4];
236 unsigned char reserved[4];
241 struct rpm_header_index {
249 struct rpm_header *signature;
250 struct rpm_header *header;
252 unsigned int n_prefixes;
253 const char **prefixes;
258 struct razor_relocations *relocations;
261 enum razor_relocation_flags {
262 RAZOR_RELOCATION_ACTIVE = 1 << 0,
265 struct razor_relocation {
266 enum razor_relocation_flags flags;
273 struct razor_relocations {
274 /* Ordered such that if oldpath 1 starts with oldpath 2, then
275 * oldpath 1 is listed first (ie., /usr/bin comes before /usr)
276 * and terminated with a NULL oldpath.
278 struct razor_relocation *relocations;
283 RAZOR_EXPORT struct razor_relocations *razor_relocations_create(void)
285 return calloc(1, sizeof(struct razor_relocations));
288 RAZOR_EXPORT void razor_relocations_add(struct razor_relocations *rr,
289 const char *oldpath, const char *newpath)
294 if (newpath && !strcmp(oldpath, newpath))
297 for (i = 0; i < rr->n_relocations; i++) {
298 len = rr->relocations[i].oldlen;
299 if (!strncmp(rr->relocations[i].oldpath, oldpath, len)) {
300 found = !strcmp(rr->relocations[i].oldpath, oldpath);
307 free(rr->relocations[i].oldpath);
308 free(rr->relocations[i].newpath);
310 rr->relocations[i] = rr->relocations[i + 1];
311 } while (rr->relocations[++i].oldpath);
317 free(rr->relocations[i].newpath);
318 rr->relocations[i].newpath = strdup(newpath);
319 rr->relocations[i].newlen = strlen(newpath);
323 if (!rr->n_relocations++)
324 rr->relocations = calloc(1, sizeof *rr->relocations);
326 rr->relocations = realloc(rr->relocations,
327 rr->n_relocations * sizeof *rr->relocations);
328 memmove(rr->relocations + i + 1, rr->relocations + i,
329 (rr->n_relocations - i - 1) * sizeof *rr->relocations);
332 rr->relocations[i].flags = 0;
333 rr->relocations[i].oldpath = strdup(oldpath);
334 rr->relocations[i].newpath = strdup(newpath);
335 rr->relocations[i].oldlen = strlen(oldpath);
336 rr->relocations[i].newlen = strlen(newpath);
340 razor_relocations_set_rpm(struct razor_relocations *rr, struct razor_rpm *rpm)
344 for (i = 0; i < rr->n_relocations; i++) {
345 rr->relocations[i].flags &= ~RAZOR_RELOCATION_ACTIVE;
346 for (j = 0; j < rpm->n_prefixes; j++)
347 if (!strcmp(rpm->prefixes[j],
348 rr->relocations[i].oldpath)) {
349 rr->relocations[i].flags |= RAZOR_RELOCATION_ACTIVE;
355 RAZOR_EXPORT const char *
356 razor_relocations_apply(struct razor_relocations *rr, const char *path)
361 for (i = 0; i < rr->n_relocations; i++)
362 if (rr->relocations[i].flags & RAZOR_RELOCATION_ACTIVE &&
363 !strncmp(path, rr->relocations[i].oldpath,
364 rr->relocations[i].oldlen))
367 if (i < rr->n_relocations) {
369 len = strlen(path + rr->relocations[i].oldlen) +
370 rr->relocations[i].newlen;
371 rr->path = malloc(len + 1);
372 memcpy(rr->path, rr->relocations[i].newpath,
373 rr->relocations[i].newlen);
374 strcpy(rr->path + rr->relocations[i].newlen,
375 path + rr->relocations[i].oldlen);
381 RAZOR_EXPORT void razor_relocations_destroy(struct razor_relocations *rr)
384 free(rr->relocations);
388 static struct rpm_header_index *
389 razor_rpm_get_header(struct razor_rpm *rpm, unsigned int tag)
391 struct rpm_header_index *index, *end;
393 index = (struct rpm_header_index *) (rpm->header + 1);
394 end = index + ntohl(rpm->header->nindex);
395 while (index < end) {
396 if (ntohl(index->tag) == tag)
405 razor_rpm_get_indirect(struct razor_rpm *rpm,
406 unsigned int tag, unsigned int *count)
408 struct rpm_header_index *index;
410 index = razor_rpm_get_header(rpm, tag);
413 *count = ntohl(index->count);
415 return rpm->pool + ntohl(index->offset);
422 rpm_to_razor_flags(uint32_t flags)
424 uint32_t razor_flags;
427 if (flags & RPMSENSE_LESS)
428 razor_flags |= RAZOR_PROPERTY_LESS;
429 if (flags & RPMSENSE_EQUAL)
430 razor_flags |= RAZOR_PROPERTY_EQUAL;
431 if (flags & RPMSENSE_GREATER)
432 razor_flags |= RAZOR_PROPERTY_GREATER;
434 if (flags & RPMSENSE_SCRIPT_PRE)
435 razor_flags |= RAZOR_PROPERTY_PRE;
436 if (flags & RPMSENSE_SCRIPT_POST)
437 razor_flags |= RAZOR_PROPERTY_POST;
438 if (flags & RPMSENSE_SCRIPT_PREUN)
439 razor_flags |= RAZOR_PROPERTY_PREUN;
440 if (flags & RPMSENSE_SCRIPT_POSTUN)
441 razor_flags |= RAZOR_PROPERTY_POSTUN;
447 import_properties(struct razor_importer *importer, uint32_t type,
448 struct razor_rpm *rpm,
449 int name_tag, int version_tag, int flags_tag)
451 const char *name, *version;
452 const uint32_t *flags;
454 unsigned int i, count;
456 name = razor_rpm_get_indirect(rpm, name_tag, &count);
460 flags = razor_rpm_get_indirect(rpm, flags_tag, &count);
462 version = razor_rpm_get_indirect(rpm, version_tag, &count);
463 for (i = 0; i < count; i++) {
464 f = rpm_to_razor_flags(ntohl(flags[i]));
465 razor_importer_add_property(importer, name, f | type, version);
466 name += strlen(name) + 1;
467 version += strlen(version) + 1;
472 import_files(struct razor_importer *importer, struct razor_rpm *rpm)
475 const uint32_t *index;
476 unsigned int i, count;
479 if (rpm->dirs == NULL)
482 /* assert: count is the same for all arrays */
483 index = razor_rpm_get_indirect(rpm, RPMTAG_DIRINDEXES, &count);
484 name = razor_rpm_get_indirect(rpm, RPMTAG_BASENAMES, &count);
485 for (i = 0; i < count; i++) {
486 snprintf(buffer, sizeof buffer,
487 "%s%s", rpm->dirs[ntohl(*index)], name);
488 razor_importer_add_file(importer, buffer);
489 name += strlen(name) + 1;
494 RAZOR_EXPORT struct razor_rpm *
495 razor_rpm_open(const char *filename)
497 struct razor_rpm *rpm;
498 struct rpm_header_index *base, *index;
499 unsigned int count, i, nindex, hsize;
500 const char *name, *prefix;
502 assert (filename != NULL);
504 rpm = malloc(sizeof *rpm);
507 memset(rpm, 0, sizeof *rpm);
509 rpm->map = razor_file_get_contents(filename, &rpm->size);
511 fprintf(stderr, "couldn't get contents of %s (%s)\n", filename,
516 rpm->signature = rpm->map + RPM_LEAD_SIZE;
517 nindex = ntohl(rpm->signature->nindex);
518 hsize = ntohl(rpm->signature->hsize);
519 rpm->header = (void *) (rpm->signature + 1) +
520 ALIGN(nindex * sizeof *index + hsize, 8);
521 nindex = ntohl(rpm->header->nindex);
522 hsize = ntohl(rpm->header->hsize);
523 rpm->payload = (void *) (rpm->header + 1) +
524 nindex * sizeof *index + hsize;
526 base = (struct rpm_header_index *) (rpm->header + 1);
527 rpm->pool = (void *) base + nindex * sizeof *index;
529 /* Look up dir names now so we can index them directly. */
530 name = razor_rpm_get_indirect(rpm, RPMTAG_DIRNAMES, &count);
532 rpm->dirs = calloc(count, sizeof *rpm->dirs);
533 for (i = 0; i < count; i++) {
535 name += strlen(name) + 1;
538 name = razor_rpm_get_indirect(rpm, RPMTAG_OLDFILENAMES,
541 fprintf(stderr, "old filenames not supported\n");
546 prefix = razor_rpm_get_indirect(rpm, RPMTAG_PREFIXES, &count);
548 rpm->prefixes = calloc(count, sizeof *rpm->prefixes);
549 for (i = 0; i < count; i++) {
550 rpm->prefixes[i] = prefix;
551 prefix += strlen(prefix) + 1;
553 rpm->n_prefixes = count;
555 prefix = razor_rpm_get_indirect(rpm, RPMTAG_DEFAULTPREFIX,
558 fprintf(stderr, "default prefix not supported\n");
566 RAZOR_EXPORT void razor_rpm_set_relocations(struct razor_rpm *rpm,
567 struct razor_relocations *rr)
569 assert (rpm != NULL);
571 rpm->relocations = rr;
574 struct cpio_file_header {
593 #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
594 #define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
595 #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
596 #define ORIG_NAME 0x08 /* bit 3 set: original file name present */
597 #define COMMENT 0x10 /* bit 4 set: file comment present */
598 #define RESERVED 0xE0 /* bits 5..7: reserved */
602 struct razor_rpm *rpm;
604 unsigned char buffer[32768];
609 installer_inflate(struct installer *installer)
614 if (installer->rest > sizeof installer->buffer)
615 length = sizeof installer->buffer;
617 length = installer->rest;
619 installer->stream.next_out = installer->buffer;
620 installer->stream.avail_out = length;
621 err = inflate(&installer->stream, Z_SYNC_FLUSH);
622 if (err != Z_OK && err != Z_STREAM_END) {
623 fprintf(stderr, "inflate error: %d (%s)\n", err,
628 installer->rest -= length;
629 installer->length = length;
635 installer_align(struct installer *installer, size_t size)
637 unsigned char buffer[4];
640 installer->stream.next_out = buffer;
641 installer->stream.avail_out =
642 (size - installer->stream.total_out) & (size - 1);
644 if (installer->stream.avail_out == 0)
647 err = inflate(&installer->stream, Z_SYNC_FLUSH);
648 if (err != Z_OK && err != Z_STREAM_END) {
649 fprintf(stderr, "inflate error: %d (%s)\n", err,
658 create_path(struct installer *installer, const char *path, unsigned int mode)
660 char buffer[PATH_MAX];
664 if (razor_create_dir(installer->root, path) < 0)
667 snprintf(buffer, sizeof buffer, "%s%s", installer->root, path);
669 switch (mode >> 12) {
671 /* FIXME: handle the case where a file is already there. */
672 fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
675 fprintf(stderr, "failed to create file %s\n", buffer);
678 while (installer->rest > 0) {
679 if (installer_inflate(installer)) {
680 fprintf(stderr, "failed to inflate\n");
683 if (razor_write(fd, installer->buffer,
684 installer->length)) {
685 fprintf(stderr, "failed to write payload\n");
690 fprintf(stderr, "failed to close %s: %s\n", buffer,
696 ret = mkdir(buffer, mode & 0x1ff);
697 if (ret == 0 || errno != EEXIST)
699 if (stat(buffer, &buf) || !S_ISDIR(buf.st_mode)) {
700 /* FIXME: also check that mode match. */
702 "%s exists but is not a directory\n", buffer);
708 if (installer_inflate(installer)) {
709 fprintf(stderr, "failed to inflate\n");
712 if (installer->length >= sizeof installer->buffer) {
713 fprintf(stderr, "link name too long\n");
716 installer->buffer[installer->length] = '\0';
717 if (symlink((const char *) installer->buffer, buffer)) {
718 perror("failed to create symlink");
729 printf("%s: unhandled file type %d\n", buffer, mode >> 12);
732 printf("%s: unknown file type %d\n", buffer, mode >> 12);
737 static int chroot_push(const char *root)
741 if (geteuid() == 0) {
742 fd = open("/", O_RDONLY, 0);
743 if (chroot(root) < 0) {
744 fprintf(stderr, "failed to chroot to %s: %s\n",
745 root, strerror(errno));
754 static void chroot_pop(int fd)
766 run_script_lua(const char *root, unsigned int script_tag, const char *script)
789 root_fd = chroot_push(root);
790 retval = run_lua_script(root_fd < 0 ? root : NULL, name, script, -1);
793 fprintf(stderr, "lua not available to run script\n");
795 #endif /* HAVE_LUA */
801 run_script_external(const char *root, const char *program, const char *script)
806 if (program == NULL) {
808 program = getenv("COMSPEC");
810 program = strchr(program, '=');
815 program = "c:\\windows\\system32\\cmd.exe";
821 root_fd = chroot_push(root);
822 fp = popen(program, "w");
827 } else if (fwrite(script, strlen(script), 1, fp) != 1) {
828 perror("failed to write script to program");
841 run_script(struct installer *installer,
842 unsigned int program_tag, unsigned int script_tag)
845 const char *script = NULL, *program = NULL;
847 program = razor_rpm_get_indirect(installer->rpm, program_tag, NULL);
848 script = razor_rpm_get_indirect(installer->rpm, script_tag, NULL);
849 if (program == NULL && script == NULL)
851 else if (strcmp(program, "<lua>") == 0)
852 retval = run_script_lua(installer->root, script_tag, script);
854 retval = run_script_external(installer->root, program, script);
860 installer_init(struct installer *installer)
862 unsigned char *gz_header;
863 int method, flags, err;
865 gz_header = installer->rpm->payload;
866 if (gz_header[0] != 0x1f || gz_header[1] != 0x8b) {
867 fprintf(stderr, "payload section doesn't have gz header\n");
871 method = gz_header[2];
872 flags = gz_header[3];
874 if (method != Z_DEFLATED || flags != 0) {
876 "unknown payload compression method or flags set\n");
880 installer->stream.zalloc = NULL;
881 installer->stream.zfree = NULL;
882 installer->stream.opaque = NULL;
884 installer->stream.next_in = gz_header + 10;
885 installer->stream.avail_in =
886 (installer->rpm->map + installer->rpm->size) -
887 (void *) installer->stream.next_in;
888 installer->stream.next_out = NULL;
889 installer->stream.avail_out = 0;
891 err = inflateInit2(&installer->stream, -MAX_WBITS);
893 fprintf(stderr, "inflateInit error: %d\n", err);
901 installer_finish(struct installer *installer)
905 err = inflateEnd(&installer->stream);
908 fprintf(stderr, "inflateEnd error: %d\n", err);
916 fixed_hex_to_ulong(const char *hex, int length)
921 for (i = 0, l = 0; i < length; i++) {
923 l = l * 16 + hex[i] - '0';
925 l = l * 16 + hex[i] - 'a' + 10;
932 razor_rpm_install(struct razor_rpm *rpm, const char *root)
934 struct installer installer;
935 struct cpio_file_header *header;
941 assert (rpm != NULL);
942 assert (root != NULL);
945 installer.root = root;
947 /* FIXME: Only do this before a transaction, not per rpm. */
948 if (*root && (stat(root, &buf) < 0 || !S_ISDIR(buf.st_mode))) {
950 "root installation directory \"%s\" does not exist\n",
955 if (rpm->relocations)
956 razor_relocations_set_rpm(rpm->relocations, rpm);
958 if (installer_init(&installer))
961 run_script(&installer, RPMTAG_PREINPROG, RPMTAG_PREIN);
963 while (installer.stream.avail_in > 0) {
964 installer.rest = sizeof *header;
965 if (installer_inflate(&installer))
968 header = (struct cpio_file_header *) installer.buffer;
969 mode = fixed_hex_to_ulong(header->mode, sizeof header->mode);
970 filesize = fixed_hex_to_ulong(header->filesize,
971 sizeof header->filesize);
973 installer.rest = fixed_hex_to_ulong(header->namesize,
974 sizeof header->namesize);
976 if (installer_inflate(&installer) ||
977 installer_align(&installer, 4))
980 path = (const char *) installer.buffer;
981 /* This convention is so lame... */
982 if (strcmp(path, "TRAILER!!!") == 0)
985 installer.rest = filesize;
987 if (rpm->relocations)
988 path = razor_relocations_apply(rpm->relocations, path);
989 if (create_path(&installer, path, mode) < 0)
991 if (installer_align(&installer, 4))
995 if (installer_finish(&installer))
998 run_script(&installer, RPMTAG_POSTINPROG, RPMTAG_POSTIN);
1004 razor_rpm_close(struct razor_rpm *rpm)
1008 assert (rpm != NULL);
1011 free(rpm->prefixes);
1012 err = razor_file_free_contents(rpm->map, rpm->size);
1019 razor_importer_add_rpm(struct razor_importer *importer, struct razor_rpm *rpm)
1021 const char *name, *version, *release, *arch;
1022 const char *summary, *description, *url, *license;
1023 const uint32_t *epoch;
1024 char evr[128], buf[16];
1026 assert (importer != NULL);
1027 assert (rpm != NULL);
1029 name = razor_rpm_get_indirect(rpm, RPMTAG_NAME, NULL);
1030 epoch = razor_rpm_get_indirect(rpm, RPMTAG_EPOCH, NULL);
1031 version = razor_rpm_get_indirect(rpm, RPMTAG_VERSION, NULL);
1032 release = razor_rpm_get_indirect(rpm, RPMTAG_RELEASE, NULL);
1033 arch = razor_rpm_get_indirect(rpm, RPMTAG_ARCH, NULL);
1035 summary = razor_rpm_get_indirect(rpm, RPMTAG_SUMMARY, NULL);
1036 description = razor_rpm_get_indirect(rpm, RPMTAG_DESCRIPTION, NULL);
1037 url = razor_rpm_get_indirect(rpm, RPMTAG_URL, NULL);
1038 license = razor_rpm_get_indirect(rpm, RPMTAG_LICENSE, NULL);
1041 snprintf(buf, sizeof buf, "%lu", ntohl(*epoch));
1042 razor_build_evr(evr, sizeof evr, buf, version, release);
1044 razor_build_evr(evr, sizeof evr, NULL, version, release);
1046 razor_importer_begin_package(importer, name, evr, arch);
1048 razor_importer_add_details(importer, summary, description, url,
1051 import_properties(importer, RAZOR_PROPERTY_REQUIRES, rpm,
1053 RPMTAG_REQUIREVERSION,
1054 RPMTAG_REQUIREFLAGS);
1056 import_properties(importer, RAZOR_PROPERTY_PROVIDES, rpm,
1058 RPMTAG_PROVIDEVERSION,
1059 RPMTAG_PROVIDEFLAGS);
1061 import_properties(importer, RAZOR_PROPERTY_OBSOLETES, rpm,
1062 RPMTAG_OBSOLETENAME,
1063 RPMTAG_OBSOLETEVERSION,
1064 RPMTAG_OBSOLETEFLAGS);
1066 import_properties(importer, RAZOR_PROPERTY_CONFLICTS, rpm,
1067 RPMTAG_CONFLICTNAME,
1068 RPMTAG_CONFLICTVERSION,
1069 RPMTAG_CONFLICTFLAGS);
1071 import_files(importer, rpm);
1073 razor_importer_finish_package(importer);