Only export symbols starting with razor_ in dynamic library.
Apart from being good practice to avoid clashes with higher-level
libraries and the application, this also fixes an obscure bug: The
gnulib library is used both by librazor (the dynamic library) and
by razor (the executable). In doing so, we want to have two separate
copies of the library despite the code duplication this involves.
Without the explicit limit to export only razor_ symbols, the razor
executable under mingw64 was picking up the getopt_long function
from librazor and the optind variable from libgnu which meant that
it did not see optind changing. Hiding librazor's copy of getopt
causes the linker to find libgnu's copy and everything works.
Note that under mingw librazor-#.dll still contains undocumented
(private) razor_ symbols but these will do no harm as long as nobody
tries to use them.
2 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
3 * Copyright (C) 2008 Red Hat, Inc
4 * Copyright (C) 2009, 2011, 2012 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;
262 enum razor_relocation_flags {
263 RAZOR_RELOCATION_ACTIVE = 1 << 0,
266 struct razor_relocation {
267 enum razor_relocation_flags flags;
274 struct razor_relocations {
275 /* Ordered such that if oldpath 1 starts with oldpath 2, then
276 * oldpath 1 is listed first (ie., /usr/bin comes before /usr)
277 * and terminated with a NULL oldpath.
279 struct razor_relocation *relocations;
284 RAZOR_EXPORT struct razor_relocations *razor_relocations_create(void)
286 return calloc(1, sizeof(struct razor_relocations));
289 RAZOR_EXPORT void razor_relocations_add(struct razor_relocations *rr,
290 const char *oldpath, const char *newpath)
295 if (newpath && !strcmp(oldpath, newpath))
298 for (i = 0; i < rr->n_relocations; i++) {
299 len = rr->relocations[i].oldlen;
300 if (!strncmp(rr->relocations[i].oldpath, oldpath, len)) {
301 found = !strcmp(rr->relocations[i].oldpath, oldpath);
308 free(rr->relocations[i].oldpath);
309 free(rr->relocations[i].newpath);
311 rr->relocations[i] = rr->relocations[i + 1];
312 } while (rr->relocations[++i].oldpath);
318 free(rr->relocations[i].newpath);
319 rr->relocations[i].newpath = strdup(newpath);
320 rr->relocations[i].newlen = strlen(newpath);
324 if (!rr->n_relocations++)
325 rr->relocations = calloc(1, sizeof *rr->relocations);
327 rr->relocations = realloc(rr->relocations,
328 rr->n_relocations * sizeof *rr->relocations);
329 memmove(rr->relocations + i + 1, rr->relocations + i,
330 (rr->n_relocations - i - 1) * sizeof *rr->relocations);
333 rr->relocations[i].flags = 0;
334 rr->relocations[i].oldpath = strdup(oldpath);
335 rr->relocations[i].newpath = strdup(newpath);
336 rr->relocations[i].oldlen = strlen(oldpath);
337 rr->relocations[i].newlen = strlen(newpath);
341 razor_relocations_set_rpm(struct razor_relocations *rr, struct razor_rpm *rpm)
345 for (i = 0; i < rr->n_relocations; i++) {
346 rr->relocations[i].flags &= ~RAZOR_RELOCATION_ACTIVE;
347 for (j = 0; j < rpm->n_prefixes; j++)
348 if (!strcmp(rpm->prefixes[j],
349 rr->relocations[i].oldpath)) {
350 rr->relocations[i].flags |= RAZOR_RELOCATION_ACTIVE;
356 RAZOR_EXPORT const char *
357 razor_relocations_apply(struct razor_relocations *rr, const char *path)
362 for (i = 0; i < rr->n_relocations; i++)
363 if (rr->relocations[i].flags & RAZOR_RELOCATION_ACTIVE &&
364 !strncmp(path, rr->relocations[i].oldpath,
365 rr->relocations[i].oldlen))
368 if (i < rr->n_relocations) {
370 len = strlen(path + rr->relocations[i].oldlen) +
371 rr->relocations[i].newlen;
372 rr->path = malloc(len + 1);
373 memcpy(rr->path, rr->relocations[i].newpath,
374 rr->relocations[i].newlen);
375 strcpy(rr->path + rr->relocations[i].newlen,
376 path + rr->relocations[i].oldlen);
382 RAZOR_EXPORT void razor_relocations_destroy(struct razor_relocations *rr)
385 free(rr->relocations);
389 static struct rpm_header_index *
390 razor_rpm_get_header(struct razor_rpm *rpm, unsigned int tag)
392 struct rpm_header_index *index, *end;
394 index = (struct rpm_header_index *) (rpm->header + 1);
395 end = index + ntohl(rpm->header->nindex);
396 while (index < end) {
397 if (ntohl(index->tag) == tag)
406 razor_rpm_get_indirect(struct razor_rpm *rpm,
407 unsigned int tag, unsigned int *count)
409 struct rpm_header_index *index;
411 index = razor_rpm_get_header(rpm, tag);
414 *count = ntohl(index->count);
416 return rpm->pool + ntohl(index->offset);
423 rpm_to_razor_flags(uint32_t flags)
425 uint32_t razor_flags;
428 if (flags & RPMSENSE_LESS)
429 razor_flags |= RAZOR_PROPERTY_LESS;
430 if (flags & RPMSENSE_EQUAL)
431 razor_flags |= RAZOR_PROPERTY_EQUAL;
432 if (flags & RPMSENSE_GREATER)
433 razor_flags |= RAZOR_PROPERTY_GREATER;
435 if (flags & RPMSENSE_SCRIPT_PRE)
436 razor_flags |= RAZOR_PROPERTY_PRE;
437 if (flags & RPMSENSE_SCRIPT_POST)
438 razor_flags |= RAZOR_PROPERTY_POST;
439 if (flags & RPMSENSE_SCRIPT_PREUN)
440 razor_flags |= RAZOR_PROPERTY_PREUN;
441 if (flags & RPMSENSE_SCRIPT_POSTUN)
442 razor_flags |= RAZOR_PROPERTY_POSTUN;
448 import_properties(struct razor_importer *importer, uint32_t type,
449 struct razor_rpm *rpm,
450 int name_tag, int version_tag, int flags_tag)
452 const char *name, *version;
453 const uint32_t *flags;
455 unsigned int i, count;
457 name = razor_rpm_get_indirect(rpm, name_tag, &count);
461 flags = razor_rpm_get_indirect(rpm, flags_tag, &count);
463 version = razor_rpm_get_indirect(rpm, version_tag, &count);
464 for (i = 0; i < count; i++) {
465 f = rpm_to_razor_flags(ntohl(flags[i]));
466 razor_importer_add_property(importer, name, f | type, version);
467 name += strlen(name) + 1;
468 version += strlen(version) + 1;
473 import_files(struct razor_importer *importer, struct razor_rpm *rpm)
476 const uint32_t *index;
477 unsigned int i, count;
480 if (rpm->dirs == NULL)
483 /* assert: count is the same for all arrays */
484 index = razor_rpm_get_indirect(rpm, RPMTAG_DIRINDEXES, &count);
485 name = razor_rpm_get_indirect(rpm, RPMTAG_BASENAMES, &count);
486 for (i = 0; i < count; i++) {
487 snprintf(buffer, sizeof buffer,
488 "%s%s", rpm->dirs[ntohl(*index)], name);
489 razor_importer_add_file(importer, buffer);
490 name += strlen(name) + 1;
496 razor_rpm_build_evr(struct razor_rpm *rpm)
498 const char *version, *release;
499 const uint32_t *epoch;
500 char evr[128], buf[16];
502 epoch = razor_rpm_get_indirect(rpm, RPMTAG_EPOCH, NULL);
503 version = razor_rpm_get_indirect(rpm, RPMTAG_VERSION, NULL);
504 release = razor_rpm_get_indirect(rpm, RPMTAG_RELEASE, NULL);
506 snprintf(buf, sizeof buf, "%lu", (unsigned long)ntohl(*epoch));
507 razor_build_evr(evr, sizeof evr, epoch ? buf : NULL, version, release);
508 rpm->evr = strdup(evr);
512 razor_rpm_get_details_string(struct razor_rpm *rpm, enum razor_detail_type type)
515 case RAZOR_DETAIL_NAME:
516 return razor_rpm_get_indirect(rpm, RPMTAG_NAME, NULL);
518 case RAZOR_DETAIL_VERSION:
520 razor_rpm_build_evr(rpm);
523 case RAZOR_DETAIL_ARCH:
524 return razor_rpm_get_indirect(rpm, RPMTAG_ARCH, NULL);
526 case RAZOR_DETAIL_SUMMARY:
527 return razor_rpm_get_indirect(rpm, RPMTAG_SUMMARY, NULL);
529 case RAZOR_DETAIL_DESCRIPTION:
530 return razor_rpm_get_indirect(rpm, RPMTAG_DESCRIPTION, NULL);
532 case RAZOR_DETAIL_URL:
533 return razor_rpm_get_indirect(rpm, RPMTAG_URL, NULL);
535 case RAZOR_DETAIL_LICENSE:
536 return razor_rpm_get_indirect(rpm, RPMTAG_LICENSE, NULL);
538 case RAZOR_DETAIL_PREUNPROG:
539 return razor_rpm_get_indirect(rpm, RPMTAG_PREUNPROG, NULL);
541 case RAZOR_DETAIL_PREUN:
542 return razor_rpm_get_indirect(rpm, RPMTAG_PREUN, NULL);
544 case RAZOR_DETAIL_POSTUNPROG:
545 return razor_rpm_get_indirect(rpm, RPMTAG_POSTUNPROG, NULL);
547 case RAZOR_DETAIL_POSTUN:
548 return razor_rpm_get_indirect(rpm, RPMTAG_POSTUN, NULL);
551 fprintf(stderr, "type %u not found\n", type);
556 static const char *const *
557 razor_rpm_get_details_array(struct razor_rpm *rpm, enum razor_detail_type type)
560 case RAZOR_DETAIL_PREFIXES:
561 return rpm->prefixes;
565 fprintf(stderr, "type %u not found\n", type);
571 razor_rpm_get_details_varg(struct razor_rpm *rpm, va_list args)
574 enum razor_detail_type type;
576 const char *const **array;
578 for (i = 0;; i += 2) {
579 type = va_arg(args, enum razor_detail_type);
580 if (type == RAZOR_DETAIL_LAST)
582 if (type == RAZOR_DETAIL_PREFIXES) {
583 array = va_arg(args, const char *const **);
584 *array = razor_rpm_get_details_array(rpm, type);
586 string = va_arg(args, const char **);
587 *string = razor_rpm_get_details_string(rpm, type);
593 razor_rpm_get_details(struct razor_rpm *rpm, ...)
600 razor_rpm_get_details_varg(rpm, args);
604 RAZOR_EXPORT struct razor_rpm *
605 razor_rpm_open(const char *filename, struct razor_error **error)
607 struct razor_rpm *rpm;
608 struct rpm_header_index *base, *index;
609 unsigned int count, i, nindex, hsize;
610 const char *name, *prefix;
612 assert (filename != NULL);
614 rpm = zalloc(sizeof *rpm);
616 razor_set_error(error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
617 "Not enough memory");
620 memset(rpm, 0, sizeof *rpm);
622 rpm->map = razor_file_get_contents(filename, &rpm->size, 0, error);
628 rpm->signature = rpm->map + RPM_LEAD_SIZE;
629 nindex = ntohl(rpm->signature->nindex);
630 hsize = ntohl(rpm->signature->hsize);
631 rpm->header = (void *) (rpm->signature + 1) +
632 ALIGN(nindex * sizeof *index + hsize, 8);
633 nindex = ntohl(rpm->header->nindex);
634 hsize = ntohl(rpm->header->hsize);
635 rpm->payload = (void *) (rpm->header + 1) +
636 nindex * sizeof *index + hsize;
638 base = (struct rpm_header_index *) (rpm->header + 1);
639 rpm->pool = (void *) base + nindex * sizeof *index;
641 /* Look up dir names now so we can index them directly. */
642 name = razor_rpm_get_indirect(rpm, RPMTAG_DIRNAMES, &count);
644 rpm->dirs = calloc(count, sizeof *rpm->dirs);
645 for (i = 0; i < count; i++) {
647 name += strlen(name) + 1;
650 name = razor_rpm_get_indirect(rpm, RPMTAG_OLDFILENAMES,
653 razor_rpm_close(rpm);
654 razor_set_error(error, RAZOR_GENERAL_ERROR,
655 RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
657 "Old filenames not supported");
662 prefix = razor_rpm_get_indirect(rpm, RPMTAG_PREFIXES, &count);
664 rpm->prefixes = calloc(count + 1, sizeof *rpm->prefixes);
665 for (i = 0; i < count; i++) {
666 rpm->prefixes[i] = prefix;
667 prefix += strlen(prefix) + 1;
669 rpm->prefixes[i] = NULL;
670 rpm->n_prefixes = count;
672 prefix = razor_rpm_get_indirect(rpm, RPMTAG_DEFAULTPREFIX,
675 razor_rpm_close(rpm);
676 razor_set_error(error, RAZOR_GENERAL_ERROR,
677 RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
679 "Default prefix not supported");
687 RAZOR_EXPORT void razor_rpm_set_relocations(struct razor_rpm *rpm,
688 struct razor_relocations *rr)
690 assert (rpm != NULL);
692 rpm->relocations = rr;
695 struct cpio_file_header {
714 #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
715 #define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
716 #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
717 #define ORIG_NAME 0x08 /* bit 3 set: original file name present */
718 #define COMMENT 0x10 /* bit 4 set: file comment present */
719 #define RESERVED 0xE0 /* bits 5..7: reserved */
723 struct razor_rpm *rpm;
724 struct razor_atomic *atomic;
726 unsigned char buffer[32768];
731 installer_inflate(struct installer *installer)
736 if (installer->rest > sizeof installer->buffer)
737 length = sizeof installer->buffer;
739 length = installer->rest;
741 installer->stream.next_out = installer->buffer;
742 installer->stream.avail_out = length;
743 err = inflate(&installer->stream, Z_SYNC_FLUSH);
744 if (err != Z_OK && err != Z_STREAM_END) {
745 razor_atomic_abort(installer->atomic, RAZOR_ZLIB_ERROR, err,
746 "Failed to inflate");
750 installer->rest -= length;
751 installer->length = length;
757 installer_align(struct installer *installer, size_t size)
759 unsigned char buffer[4];
762 installer->stream.next_out = buffer;
763 installer->stream.avail_out =
764 (size - installer->stream.total_out) & (size - 1);
766 if (installer->stream.avail_out == 0)
769 err = inflate(&installer->stream, Z_SYNC_FLUSH);
770 if (err != Z_OK && err != Z_STREAM_END) {
771 razor_atomic_abort(installer->atomic, RAZOR_ZLIB_ERROR, err,
772 "Failed to inflate");
780 create_path(struct installer *installer, const char *path, unsigned int mode)
785 if (razor_atomic_make_dirs(installer->atomic, installer->root, path))
788 buffer = razor_concat(installer->root, path, NULL);
790 switch (mode >> 12) {
792 /* FIXME: handle the case where a file is already there. */
793 h = razor_atomic_create_file(installer->atomic, buffer, mode);
797 while (installer->rest > 0) {
798 if (installer_inflate(installer))
800 if (razor_atomic_write(installer->atomic, h,
805 return razor_atomic_close(installer->atomic, h);
807 ret = razor_atomic_create_dir(installer->atomic, buffer, mode);
812 if (installer_inflate(installer))
814 if (installer->length >= sizeof installer->buffer) {
815 razor_atomic_abort(installer->atomic,
817 RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
818 "Link target too long");
821 installer->buffer[installer->length] = '\0';
822 ret = razor_atomic_create_symlink(installer->atomic,
823 (const char *)installer->buffer, buffer);
827 s = "Symbolic links";
834 buffer = razor_concat(s, " are not supported on this platform",
836 razor_atomic_abort(installer->atomic, RAZOR_GENERAL_ERROR,
837 RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED, buffer);
841 s = "Character devices";
851 razor_atomic_abort(installer->atomic, RAZOR_GENERAL_ERROR,
852 RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED, "Unknown file type");
857 static int chroot_push(const char *root)
861 if (geteuid() == 0) {
862 fd = open("/", O_RDONLY, 0);
863 if (chroot(root) < 0) {
864 fprintf(stderr, "failed to chroot to %s: %s\n",
865 root, strerror(errno));
874 static void chroot_pop(int fd)
886 run_script_lua(const char *root, unsigned int script_tag, const char *script,
910 root_fd = chroot_push(root);
911 retval = run_lua_script(root_fd < 0 ? root : NULL, name, script, -1,
915 fprintf(stderr, "lua not available to run script\n");
917 #endif /* HAVE_LUA */
923 run_script_external(const char *root, const char *program, const char *script,
928 char buf[32], *command;
930 if (program == NULL) {
932 program = getenv("COMSPEC");
934 program = strchr(program, '=');
939 program = "c:\\windows\\system32\\cmd.exe";
945 root_fd = chroot_push(root);
947 sprintf(buf, "%d", arg1);
948 command = malloc(strlen(program) + strlen(buf) + 2);
949 sprintf(command, "%s %s", program, buf);
951 command = strdup(program);
952 fp = popen(command, "w");
958 } else if (script && fwrite(script, strlen(script), 1, fp) != 1) {
959 perror("failed to write script to program");
972 run_script(struct installer *installer,
973 unsigned int program_tag, unsigned int script_tag, int arg1)
976 struct razor_rpm *rpm = installer->rpm;
977 const char *script = NULL, *program = NULL, *prefix;
979 struct environment env;
981 program = razor_rpm_get_indirect(rpm, program_tag, NULL);
982 script = razor_rpm_get_indirect(rpm, script_tag, NULL);
983 if (program == NULL && script == NULL)
986 if (rpm->relocations) {
987 environment_init(&env);
988 for(i = 0; i < rpm->n_prefixes; i++) {
989 prefix = razor_relocations_apply(rpm->relocations,
991 sprintf(buf, "RPM_INSTALL_PREFIX%d", i);
992 environment_add_variable(&env, buf, prefix);
994 environment_set(&env);
997 if (program && strcmp(program, "<lua>") == 0)
998 retval = run_script_lua(installer->root, script_tag, script,
1001 retval = run_script_external(installer->root, program, script,
1004 if (rpm->relocations) {
1005 environment_unset(&env);
1006 environment_release(&env);
1013 razor_run_script(const char *root, enum razor_property_flags script,
1014 const char *program, const char *body, int arg1)
1017 unsigned int script_tag;
1019 if (program && !*program)
1023 if (program == NULL && body == NULL)
1026 if (program && strcmp(program, "<lua>") == 0)
1029 case RAZOR_PROPERTY_PRE:
1030 script_tag = RPMTAG_PREIN;
1032 case RAZOR_PROPERTY_POST:
1033 script_tag = RPMTAG_POSTIN;
1035 case RAZOR_PROPERTY_PREUN:
1036 script_tag = RPMTAG_PREUN;
1038 case RAZOR_PROPERTY_POSTUN:
1039 script_tag = RPMTAG_POSTUN;
1045 retval = run_script_lua(root, script_tag, body, arg1);
1048 retval = run_script_external(root, program, body, arg1);
1054 installer_init(struct installer *installer)
1056 unsigned char *gz_header;
1057 int method, flags, err;
1058 char buffer[32], *s;
1060 gz_header = installer->rpm->payload;
1061 if (gz_header[0] != 0x1f || gz_header[1] != 0x8b) {
1062 razor_atomic_abort(installer->atomic, RAZOR_GENERAL_ERROR,
1063 RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
1064 "Payload section doesn't have gz header");
1068 method = gz_header[2];
1069 flags = gz_header[3];
1071 if (method != Z_DEFLATED || flags != 0) {
1072 razor_atomic_abort(installer->atomic, RAZOR_GENERAL_ERROR,
1073 RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
1074 "Unknown payload compression method or "
1079 installer->stream.zalloc = NULL;
1080 installer->stream.zfree = NULL;
1081 installer->stream.opaque = NULL;
1083 installer->stream.next_in = gz_header + 10;
1084 installer->stream.avail_in =
1085 (installer->rpm->map + installer->rpm->size) -
1086 (void *) installer->stream.next_in;
1087 installer->stream.next_out = NULL;
1088 installer->stream.avail_out = 0;
1090 err = inflateInit2(&installer->stream, -MAX_WBITS);
1092 sprintf(buffer, "%d", err);
1093 s = razor_concat("inflateEnd error: ", buffer, NULL);
1094 razor_atomic_abort(installer->atomic, RAZOR_ZLIB_ERROR, err, s);
1103 installer_finish(struct installer *installer)
1106 char buffer[32], *s;
1108 err = inflateEnd(&installer->stream);
1111 sprintf(buffer, "%d", err);
1112 s = razor_concat("inflateEnd error: ", buffer, NULL);
1113 razor_atomic_abort(installer->atomic, RAZOR_ZLIB_ERROR, err, s);
1117 return razor_atomic_in_error_state(installer->atomic);
1120 static unsigned long
1121 fixed_hex_to_ulong(const char *hex, int length)
1126 for (i = 0, l = 0; i < length; i++) {
1128 l = l * 16 + hex[i] - '0';
1130 l = l * 16 + hex[i] - 'a' + 10;
1137 razor_rpm_install(struct razor_rpm *rpm, struct razor_atomic *atomic,
1138 const char *root, int install_count,
1139 enum razor_stage_type stage)
1141 struct installer installer;
1142 struct cpio_file_header *header;
1148 int retval = 0, code;
1150 assert (rpm != NULL);
1151 assert (root != NULL);
1153 installer.rpm = rpm;
1154 installer.root = root;
1155 installer.atomic = atomic;
1157 /* FIXME: Only do this before a transaction, not per rpm. */
1158 if (*root && ((retval = stat(root, &buf)) || !S_ISDIR(buf.st_mode))) {
1159 code = retval ? errno : ENOTDIR;
1160 s = razor_concat(root, ": Directory does not exist", NULL);
1161 razor_atomic_abort(atomic, RAZOR_POSIX_ERROR, code, s);
1166 if (rpm->relocations)
1167 razor_relocations_set_rpm(rpm->relocations, rpm);
1169 if (stage & RAZOR_STAGE_SCRIPTS_PRE)
1170 retval = run_script(&installer, RPMTAG_PREINPROG, RPMTAG_PREIN,
1173 if (!retval && (stage & RAZOR_STAGE_FILES)) {
1174 if (installer_init(&installer))
1177 while (installer.stream.avail_in > 0) {
1178 installer.rest = sizeof *header;
1179 if (installer_inflate(&installer))
1182 header = (struct cpio_file_header *) installer.buffer;
1183 mode = fixed_hex_to_ulong(header->mode,
1184 sizeof header->mode);
1185 filesize = fixed_hex_to_ulong(header->filesize,
1186 sizeof header->filesize);
1189 fixed_hex_to_ulong(header->namesize,
1190 sizeof header->namesize);
1192 if (installer_inflate(&installer) ||
1193 installer_align(&installer, 4))
1196 path = (const char *) installer.buffer;
1197 /* This convention is so lame... */
1198 if (strcmp(path, "TRAILER!!!") == 0)
1201 installer.rest = filesize;
1203 if (rpm->relocations)
1204 path = razor_relocations_apply(rpm->relocations,
1206 if (create_path(&installer, path, mode))
1208 if (installer_align(&installer, 4))
1212 if (installer_finish(&installer))
1215 retval = razor_atomic_in_error_state(atomic);
1218 if (!retval && (stage & RAZOR_STAGE_SCRIPTS_POST))
1219 retval = run_script(&installer, RPMTAG_POSTINPROG,
1220 RPMTAG_POSTIN, install_count);
1226 razor_rpm_close(struct razor_rpm *rpm)
1230 assert (rpm != NULL);
1233 free(rpm->prefixes);
1234 err = razor_file_free_contents(rpm->map, rpm->size);
1242 razor_importer_add_rpm(struct razor_importer *importer, struct razor_rpm *rpm)
1244 const char *name, *version, *arch;
1245 const char *summary, *description, *url, *license;
1247 assert (importer != NULL);
1248 assert (rpm != NULL);
1250 razor_rpm_get_details(rpm,
1251 RAZOR_DETAIL_NAME, &name,
1252 RAZOR_DETAIL_VERSION, &version,
1253 RAZOR_DETAIL_ARCH, &arch,
1254 RAZOR_DETAIL_SUMMARY, &summary,
1255 RAZOR_DETAIL_DESCRIPTION, &description,
1256 RAZOR_DETAIL_URL, &url,
1257 RAZOR_DETAIL_LICENSE, &license,
1260 razor_importer_begin_package(importer, name, version, arch);
1262 razor_importer_add_details(importer, summary, description, url,
1265 import_properties(importer, RAZOR_PROPERTY_REQUIRES, rpm,
1267 RPMTAG_REQUIREVERSION,
1268 RPMTAG_REQUIREFLAGS);
1270 import_properties(importer, RAZOR_PROPERTY_PROVIDES, rpm,
1272 RPMTAG_PROVIDEVERSION,
1273 RPMTAG_PROVIDEFLAGS);
1275 import_properties(importer, RAZOR_PROPERTY_OBSOLETES, rpm,
1276 RPMTAG_OBSOLETENAME,
1277 RPMTAG_OBSOLETEVERSION,
1278 RPMTAG_OBSOLETEFLAGS);
1280 import_properties(importer, RAZOR_PROPERTY_CONFLICTS, rpm,
1281 RPMTAG_CONFLICTNAME,
1282 RPMTAG_CONFLICTVERSION,
1283 RPMTAG_CONFLICTFLAGS);
1285 import_files(importer, rpm);
1287 razor_importer_finish_package(importer);