rhughes@241: /* rhughes@241: * Copyright (C) 2008 Kristian Høgsberg rhughes@241: * Copyright (C) 2008 Red Hat, Inc ali@422: * Copyright (C) 2009, 2011, 2012 J. Ali Harlow rhughes@241: * rhughes@241: * This program is free software; you can redistribute it and/or modify rhughes@241: * it under the terms of the GNU General Public License as published by rhughes@241: * the Free Software Foundation; either version 2 of the License, or rhughes@241: * (at your option) any later version. rhughes@241: * rhughes@241: * This program is distributed in the hope that it will be useful, rhughes@241: * but WITHOUT ANY WARRANTY; without even the implied warranty of rhughes@241: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the rhughes@241: * GNU General Public License for more details. rhughes@241: * rhughes@241: * You should have received a copy of the GNU General Public License along rhughes@241: * with this program; if not, write to the Free Software Foundation, Inc., rhughes@241: * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. rhughes@241: */ rhughes@241: ali@327: #include "config.h" ali@327: rhughes@241: #include rhughes@241: #include rhughes@241: #include rhughes@241: #include rhughes@241: #include rhughes@241: #include rhughes@241: #include ali@330: #if HAVE_SYS_WAIT_H rhughes@241: #include ali@330: #endif rhughes@241: #include rhughes@241: #include rhughes@241: #include ali@329: #if MSWIN_API ali@335: #include /* For ntohl() */ ali@329: #else rhughes@241: #include ali@329: #endif ali@325: #include rhughes@241: #include richard@301: #include rhughes@241: rhughes@241: #include "razor.h" rhughes@241: #include "razor-internal.h" rhughes@241: ali@345: #ifndef O_BINARY ali@345: #define O_BINARY 0 ali@345: #endif ali@345: rhughes@241: #define RPM_LEAD_SIZE 96 rhughes@241: rhughes@241: enum { rhughes@241: PIPE = 1, /*!< pipe/fifo */ rhughes@241: CDEV = 2, /*!< character device */ rhughes@241: XDIR = 4, /*!< directory */ rhughes@241: BDEV = 6, /*!< block device */ rhughes@241: REG = 8, /*!< regular file */ rhughes@241: LINK = 10, /*!< hard link */ rhughes@241: SOCK = 12 /*!< socket */ rhughes@241: }; rhughes@241: rhughes@241: enum { krh@247: RPMSENSE_LESS = 1 << 1, krh@247: RPMSENSE_GREATER = 1 << 2, krh@247: RPMSENSE_EQUAL = 1 << 3, krh@247: RPMSENSE_PREREQ = 1 << 6, krh@247: RPMSENSE_SCRIPT_PRE = 1 << 9, krh@247: RPMSENSE_SCRIPT_POST = 1 << 10, krh@247: RPMSENSE_SCRIPT_PREUN = 1 << 11, krh@247: RPMSENSE_SCRIPT_POSTUN = 1 << 12, rhughes@241: }; rhughes@241: rhughes@241: enum { rhughes@241: RPMTAG_NAME = 1000, /* s */ rhughes@241: RPMTAG_VERSION = 1001, /* s */ rhughes@241: RPMTAG_RELEASE = 1002, /* s */ rhughes@241: RPMTAG_EPOCH = 1003, /* i */ rhughes@241: RPMTAG_SUMMARY = 1004, /* s{} */ rhughes@241: RPMTAG_DESCRIPTION = 1005, /* s{} */ rhughes@241: RPMTAG_BUILDTIME = 1006, /* i */ rhughes@241: RPMTAG_BUILDHOST = 1007, /* s */ rhughes@241: RPMTAG_INSTALLTIME = 1008, /* i */ rhughes@241: RPMTAG_SIZE = 1009, /* i */ rhughes@241: RPMTAG_DISTRIBUTION = 1010, /* s */ rhughes@241: RPMTAG_VENDOR = 1011, /* s */ rhughes@241: RPMTAG_GIF = 1012, /* x */ rhughes@241: RPMTAG_XPM = 1013, /* x */ rhughes@241: RPMTAG_LICENSE = 1014, /* s */ rhughes@241: RPMTAG_PACKAGER = 1015, /* s */ rhughes@241: RPMTAG_GROUP = 1016, /* s{} */ rhughes@241: RPMTAG_CHANGELOG = 1017, /*!< s[] internal */ rhughes@241: RPMTAG_SOURCE = 1018, /* s[] */ rhughes@241: RPMTAG_PATCH = 1019, /* s[] */ rhughes@241: RPMTAG_URL = 1020, /* s */ rhughes@241: RPMTAG_OS = 1021, /* s legacy used int */ rhughes@241: RPMTAG_ARCH = 1022, /* s legacy used int */ rhughes@241: RPMTAG_PREIN = 1023, /* s */ rhughes@241: RPMTAG_POSTIN = 1024, /* s */ rhughes@241: RPMTAG_PREUN = 1025, /* s */ rhughes@241: RPMTAG_POSTUN = 1026, /* s */ rhughes@241: RPMTAG_OLDFILENAMES = 1027, /* s[] obsolete */ rhughes@241: RPMTAG_FILESIZES = 1028, /* i */ rhughes@241: RPMTAG_FILESTATES = 1029, /* c */ rhughes@241: RPMTAG_FILEMODES = 1030, /* h */ rhughes@241: RPMTAG_FILEUIDS = 1031, /*!< internal */ rhughes@241: RPMTAG_FILEGIDS = 1032, /*!< internal */ rhughes@241: RPMTAG_FILERDEVS = 1033, /* h */ rhughes@241: RPMTAG_FILEMTIMES = 1034, /* i */ rhughes@241: RPMTAG_FILEMD5S = 1035, /* s[] */ rhughes@241: RPMTAG_FILELINKTOS = 1036, /* s[] */ rhughes@241: RPMTAG_FILEFLAGS = 1037, /* i */ rhughes@241: RPMTAG_ROOT = 1038, /*!< internal - obsolete */ rhughes@241: RPMTAG_FILEUSERNAME = 1039, /* s[] */ rhughes@241: RPMTAG_FILEGROUPNAME = 1040, /* s[] */ rhughes@241: RPMTAG_EXCLUDE = 1041, /*!< internal - obsolete */ rhughes@241: RPMTAG_EXCLUSIVE = 1042, /*!< internal - obsolete */ rhughes@241: RPMTAG_ICON = 1043, rhughes@241: RPMTAG_SOURCERPM = 1044, /* s */ rhughes@241: RPMTAG_FILEVERIFYFLAGS = 1045, /* i */ rhughes@241: RPMTAG_ARCHIVESIZE = 1046, /* i */ rhughes@241: RPMTAG_PROVIDENAME = 1047, /* s[] */ rhughes@241: RPMTAG_REQUIREFLAGS = 1048, /* i */ rhughes@241: RPMTAG_REQUIRENAME = 1049, /* s[] */ rhughes@241: RPMTAG_REQUIREVERSION = 1050, /* s[] */ rhughes@241: RPMTAG_NOSOURCE = 1051, /*!< internal */ rhughes@241: RPMTAG_NOPATCH = 1052, /*!< internal */ rhughes@241: RPMTAG_CONFLICTFLAGS = 1053, /* i */ rhughes@241: RPMTAG_CONFLICTNAME = 1054, /* s[] */ rhughes@241: RPMTAG_CONFLICTVERSION = 1055, /* s[] */ rhughes@241: RPMTAG_DEFAULTPREFIX = 1056, /*!< internal - deprecated */ rhughes@241: RPMTAG_BUILDROOT = 1057, /*!< internal */ rhughes@241: RPMTAG_INSTALLPREFIX = 1058, /*!< internal - deprecated */ rhughes@241: RPMTAG_EXCLUDEARCH = 1059, rhughes@241: RPMTAG_EXCLUDEOS = 1060, rhughes@241: RPMTAG_EXCLUSIVEARCH = 1061, rhughes@241: RPMTAG_EXCLUSIVEOS = 1062, rhughes@241: RPMTAG_AUTOREQPROV = 1063, /*!< internal */ rhughes@241: RPMTAG_RPMVERSION = 1064, /* s */ rhughes@241: RPMTAG_TRIGGERSCRIPTS = 1065, /* s[] */ rhughes@241: RPMTAG_TRIGGERNAME = 1066, /* s[] */ rhughes@241: RPMTAG_TRIGGERVERSION = 1067, /* s[] */ rhughes@241: RPMTAG_TRIGGERFLAGS = 1068, /* i */ rhughes@241: RPMTAG_TRIGGERINDEX = 1069, /* i */ rhughes@241: RPMTAG_VERIFYSCRIPT = 1079, /* s */ rhughes@241: RPMTAG_CHANGELOGTIME = 1080, /* i */ rhughes@241: RPMTAG_CHANGELOGNAME = 1081, /* s[] */ rhughes@241: RPMTAG_CHANGELOGTEXT = 1082, /* s[] */ rhughes@241: RPMTAG_BROKENMD5 = 1083, /*!< internal - obsolete */ rhughes@241: RPMTAG_PREREQ = 1084, /*!< internal */ rhughes@241: RPMTAG_PREINPROG = 1085, /* s */ rhughes@241: RPMTAG_POSTINPROG = 1086, /* s */ rhughes@241: RPMTAG_PREUNPROG = 1087, /* s */ rhughes@241: RPMTAG_POSTUNPROG = 1088, /* s */ rhughes@241: RPMTAG_BUILDARCHS = 1089, rhughes@241: RPMTAG_OBSOLETENAME = 1090, /* s[] */ rhughes@241: RPMTAG_VERIFYSCRIPTPROG = 1091, /* s */ rhughes@241: RPMTAG_TRIGGERSCRIPTPROG = 1092, /* s */ rhughes@241: RPMTAG_DOCDIR = 1093, /*!< internal */ rhughes@241: RPMTAG_COOKIE = 1094, /* s */ rhughes@241: RPMTAG_FILEDEVICES = 1095, /* i */ rhughes@241: RPMTAG_FILEINODES = 1096, /* i */ rhughes@241: RPMTAG_FILELANGS = 1097, /* s[] */ rhughes@241: RPMTAG_PREFIXES = 1098, /* s[] */ rhughes@241: RPMTAG_INSTPREFIXES = 1099, /* s[] */ rhughes@241: RPMTAG_TRIGGERIN = 1100, /*!< internal */ rhughes@241: RPMTAG_TRIGGERUN = 1101, /*!< internal */ rhughes@241: RPMTAG_TRIGGERPOSTUN = 1102, /*!< internal */ rhughes@241: RPMTAG_AUTOREQ = 1103, /*!< internal */ rhughes@241: RPMTAG_AUTOPROV = 1104, /*!< internal */ rhughes@241: RPMTAG_CAPABILITY = 1105, /*!< internal - obsolete */ rhughes@241: RPMTAG_SOURCEPACKAGE = 1106, /*!< i src.rpm header marker */ rhughes@241: RPMTAG_OLDORIGFILENAMES = 1107, /*!< internal - obsolete */ rhughes@241: RPMTAG_BUILDPREREQ = 1108, /*!< internal */ rhughes@241: RPMTAG_BUILDREQUIRES = 1109, /*!< internal */ rhughes@241: RPMTAG_BUILDCONFLICTS = 1110, /*!< internal */ rhughes@241: RPMTAG_BUILDMACROS = 1111, /*!< internal - unused */ rhughes@241: RPMTAG_PROVIDEFLAGS = 1112, /* i */ rhughes@241: RPMTAG_PROVIDEVERSION = 1113, /* s[] */ rhughes@241: RPMTAG_OBSOLETEFLAGS = 1114, /* i */ rhughes@241: RPMTAG_OBSOLETEVERSION = 1115, /* s[] */ rhughes@241: RPMTAG_DIRINDEXES = 1116, /* i */ rhughes@241: RPMTAG_BASENAMES = 1117, /* s[] */ rhughes@241: RPMTAG_DIRNAMES = 1118, /* s[] */ rhughes@241: RPMTAG_ORIGDIRINDEXES = 1119, /*!< internal */ rhughes@241: RPMTAG_ORIGBASENAMES = 1120, /*!< internal */ rhughes@241: RPMTAG_ORIGDIRNAMES = 1121, /*!< internal */ rhughes@241: RPMTAG_OPTFLAGS = 1122, /* s */ rhughes@241: RPMTAG_DISTURL = 1123, /* s */ rhughes@241: RPMTAG_PAYLOADFORMAT = 1124, /* s */ rhughes@241: RPMTAG_PAYLOADCOMPRESSOR = 1125, /* s */ rhughes@241: RPMTAG_PAYLOADFLAGS = 1126, /* s */ rhughes@241: RPMTAG_INSTALLCOLOR = 1127, /*!< i transaction color when installed */ rhughes@241: RPMTAG_INSTALLTID = 1128, /* i */ rhughes@241: RPMTAG_REMOVETID = 1129, /* i */ rhughes@241: RPMTAG_SHA1RHN = 1130, /*!< internal - obsolete */ rhughes@241: RPMTAG_RHNPLATFORM = 1131, /* s */ rhughes@241: RPMTAG_PLATFORM = 1132, /* s */ rhughes@241: RPMTAG_PATCHESNAME = 1133, /*!< placeholder (SuSE) */ rhughes@241: RPMTAG_PATCHESFLAGS = 1134, /*!< placeholder (SuSE) */ rhughes@241: RPMTAG_PATCHESVERSION = 1135, /*!< placeholder (SuSE) */ rhughes@241: RPMTAG_CACHECTIME = 1136, /* i */ rhughes@241: RPMTAG_CACHEPKGPATH = 1137, /* s */ rhughes@241: RPMTAG_CACHEPKGSIZE = 1138, /* i */ rhughes@241: RPMTAG_CACHEPKGMTIME = 1139, /* i */ rhughes@241: RPMTAG_FILECOLORS = 1140, /* i */ rhughes@241: RPMTAG_FILECLASS = 1141, /* i */ rhughes@241: RPMTAG_CLASSDICT = 1142, /* s[] */ rhughes@241: RPMTAG_FILEDEPENDSX = 1143, /* i */ rhughes@241: RPMTAG_FILEDEPENDSN = 1144, /* i */ rhughes@241: RPMTAG_DEPENDSDICT = 1145, /* i */ rhughes@241: RPMTAG_SOURCEPKGID = 1146, /* x */ rhughes@241: RPMTAG_FILECONTEXTS = 1147, /* s[] */ rhughes@241: RPMTAG_FSCONTEXTS = 1148, /*!< s[] extension */ rhughes@241: RPMTAG_RECONTEXTS = 1149, /*!< s[] extension */ rhughes@241: RPMTAG_POLICIES = 1150, /*!< s[] selinux *.te policy file. */ rhughes@241: RPMTAG_PRETRANS = 1151, /* s */ rhughes@241: RPMTAG_POSTTRANS = 1152, /* s */ rhughes@241: RPMTAG_PRETRANSPROG = 1153, /* s */ rhughes@241: RPMTAG_POSTTRANSPROG = 1154, /* s */ rhughes@241: RPMTAG_DISTTAG = 1155, /* s */ rhughes@241: RPMTAG_SUGGESTSNAME = 1156, /* s[] extension placeholder */ rhughes@241: RPMTAG_SUGGESTSVERSION = 1157, /* s[] extension placeholder */ rhughes@241: RPMTAG_SUGGESTSFLAGS = 1158, /* i extension placeholder */ rhughes@241: RPMTAG_ENHANCESNAME = 1159, /* s[] extension placeholder */ rhughes@241: RPMTAG_ENHANCESVERSION = 1160, /* s[] extension placeholder */ rhughes@241: RPMTAG_ENHANCESFLAGS = 1161, /* i extension placeholder */ rhughes@241: RPMTAG_PRIORITY = 1162, /* i extension placeholder */ rhughes@241: RPMTAG_CVSID = 1163, /* s */ rhughes@241: RPMTAG_TRIGGERPREIN = 1171, /*!< internal */ rhughes@241: }; rhughes@241: rhughes@241: struct rpm_header { rhughes@241: unsigned char magic[4]; rhughes@241: unsigned char reserved[4]; rhughes@241: int nindex; rhughes@241: int hsize; rhughes@241: }; rhughes@241: rhughes@241: struct rpm_header_index { rhughes@241: int tag; rhughes@241: int type; rhughes@241: int offset; rhughes@241: int count; rhughes@241: }; rhughes@241: rhughes@241: struct razor_rpm { rhughes@241: struct rpm_header *signature; rhughes@241: struct rpm_header *header; rhughes@241: const char **dirs; ali@351: unsigned int n_prefixes; ali@351: const char **prefixes; rhughes@241: const char *pool; rhughes@241: void *map; rhughes@241: size_t size; rhughes@241: void *payload; ali@351: struct razor_relocations *relocations; ali@369: char *evr; rhughes@241: }; rhughes@241: ali@351: enum razor_relocation_flags { ali@351: RAZOR_RELOCATION_ACTIVE = 1 << 0, ali@351: }; ali@351: ali@351: struct razor_relocation { ali@351: enum razor_relocation_flags flags; ali@351: size_t oldlen; ali@351: size_t newlen; ali@351: char *oldpath; ali@351: char *newpath; ali@351: }; ali@351: ali@351: struct razor_relocations { ali@351: /* Ordered such that if oldpath 1 starts with oldpath 2, then ali@351: * oldpath 1 is listed first (ie., /usr/bin comes before /usr) ali@351: * and terminated with a NULL oldpath. ali@351: */ ali@351: struct razor_relocation *relocations; ali@351: int n_relocations; ali@351: char *path; ali@351: }; ali@351: ali@351: RAZOR_EXPORT struct razor_relocations *razor_relocations_create(void) ali@351: { ali@351: return calloc(1, sizeof(struct razor_relocations)); ali@351: } ali@351: ali@351: RAZOR_EXPORT void razor_relocations_add(struct razor_relocations *rr, ali@351: const char *oldpath, const char *newpath) ali@351: { ali@351: int i, found = 0; ali@351: size_t len; ali@351: ali@351: if (newpath && !strcmp(oldpath, newpath)) ali@351: newpath = NULL; ali@351: ali@351: for (i = 0; i < rr->n_relocations; i++) { ali@351: len = rr->relocations[i].oldlen; ali@351: if (!strncmp(rr->relocations[i].oldpath, oldpath, len)) { ali@351: found = !strcmp(rr->relocations[i].oldpath, oldpath); ali@351: break; ali@351: } ali@351: } ali@351: ali@351: if (!newpath) { ali@351: if (found) { ali@351: free(rr->relocations[i].oldpath); ali@351: free(rr->relocations[i].newpath); ali@351: do { ali@351: rr->relocations[i] = rr->relocations[i + 1]; ali@351: } while (rr->relocations[++i].oldpath); ali@351: } ali@351: return; ali@351: } ali@351: ali@351: if (found) { ali@351: free(rr->relocations[i].newpath); ali@351: rr->relocations[i].newpath = strdup(newpath); ali@351: rr->relocations[i].newlen = strlen(newpath); ali@351: return; ali@351: } ali@351: ali@351: if (!rr->n_relocations++) ali@351: rr->relocations = calloc(1, sizeof *rr->relocations); ali@351: else { ali@351: rr->relocations = realloc(rr->relocations, ali@351: rr->n_relocations * sizeof *rr->relocations); ali@351: memmove(rr->relocations + i + 1, rr->relocations + i, ali@351: (rr->n_relocations - i - 1) * sizeof *rr->relocations); ali@351: } ali@351: ali@351: rr->relocations[i].flags = 0; ali@351: rr->relocations[i].oldpath = strdup(oldpath); ali@351: rr->relocations[i].newpath = strdup(newpath); ali@351: rr->relocations[i].oldlen = strlen(oldpath); ali@351: rr->relocations[i].newlen = strlen(newpath); ali@351: } ali@351: ali@351: RAZOR_EXPORT void ali@351: razor_relocations_set_rpm(struct razor_relocations *rr, struct razor_rpm *rpm) ali@351: { ali@351: int i, j; ali@351: ali@351: for (i = 0; i < rr->n_relocations; i++) { ali@351: rr->relocations[i].flags &= ~RAZOR_RELOCATION_ACTIVE; ali@351: for (j = 0; j < rpm->n_prefixes; j++) ali@351: if (!strcmp(rpm->prefixes[j], ali@351: rr->relocations[i].oldpath)) { ali@351: rr->relocations[i].flags |= RAZOR_RELOCATION_ACTIVE; ali@351: break; ali@351: } ali@351: } ali@351: } ali@351: ali@351: RAZOR_EXPORT const char * ali@351: razor_relocations_apply(struct razor_relocations *rr, const char *path) ali@351: { ali@351: int i; ali@351: size_t len; ali@351: ali@351: for (i = 0; i < rr->n_relocations; i++) ali@351: if (rr->relocations[i].flags & RAZOR_RELOCATION_ACTIVE && ali@351: !strncmp(path, rr->relocations[i].oldpath, ali@351: rr->relocations[i].oldlen)) ali@351: break; ali@351: ali@351: if (i < rr->n_relocations) { ali@351: free(rr->path); ali@351: len = strlen(path + rr->relocations[i].oldlen) + ali@351: rr->relocations[i].newlen; ali@351: rr->path = malloc(len + 1); ali@351: memcpy(rr->path, rr->relocations[i].newpath, ali@351: rr->relocations[i].newlen); ali@351: strcpy(rr->path + rr->relocations[i].newlen, ali@351: path + rr->relocations[i].oldlen); ali@351: return rr->path; ali@351: } else ali@351: return path; ali@351: } ali@351: ali@351: RAZOR_EXPORT void razor_relocations_destroy(struct razor_relocations *rr) ali@351: { ali@351: free(rr->path); ali@351: free(rr->relocations); ali@351: free(rr); ali@351: } ali@351: rhughes@241: static struct rpm_header_index * rhughes@241: razor_rpm_get_header(struct razor_rpm *rpm, unsigned int tag) rhughes@241: { rhughes@241: struct rpm_header_index *index, *end; rhughes@241: rhughes@241: index = (struct rpm_header_index *) (rpm->header + 1); rhughes@241: end = index + ntohl(rpm->header->nindex); rhughes@241: while (index < end) { rhughes@241: if (ntohl(index->tag) == tag) rhughes@241: return index; rhughes@241: index++; rhughes@241: } rhughes@241: rhughes@241: return NULL; rhughes@241: } rhughes@241: rhughes@241: static const void * rhughes@241: razor_rpm_get_indirect(struct razor_rpm *rpm, rhughes@241: unsigned int tag, unsigned int *count) rhughes@241: { rhughes@241: struct rpm_header_index *index; rhughes@241: rhughes@241: index = razor_rpm_get_header(rpm, tag); rhughes@241: if (index != NULL) { rhughes@241: if (count) rhughes@241: *count = ntohl(index->count); rhughes@241: rhughes@241: return rpm->pool + ntohl(index->offset); rhughes@241: } rhughes@241: rhughes@241: return NULL; rhughes@241: } rhughes@241: krh@247: static uint32_t rhughes@241: rpm_to_razor_flags(uint32_t flags) rhughes@241: { krh@247: uint32_t razor_flags; rhughes@241: krh@247: razor_flags = 0; krh@247: if (flags & RPMSENSE_LESS) krh@247: razor_flags |= RAZOR_PROPERTY_LESS; krh@247: if (flags & RPMSENSE_EQUAL) krh@247: razor_flags |= RAZOR_PROPERTY_EQUAL; krh@247: if (flags & RPMSENSE_GREATER) krh@247: razor_flags |= RAZOR_PROPERTY_GREATER; krh@247: krh@247: if (flags & RPMSENSE_SCRIPT_PRE) krh@247: razor_flags |= RAZOR_PROPERTY_PRE; krh@247: if (flags & RPMSENSE_SCRIPT_POST) krh@247: razor_flags |= RAZOR_PROPERTY_POST; krh@247: if (flags & RPMSENSE_SCRIPT_PREUN) krh@247: razor_flags |= RAZOR_PROPERTY_PREUN; krh@247: if (flags & RPMSENSE_SCRIPT_POSTUN) krh@247: razor_flags |= RAZOR_PROPERTY_POSTUN; krh@247: krh@247: return razor_flags; rhughes@241: } rhughes@241: rhughes@241: static void krh@247: import_properties(struct razor_importer *importer, uint32_t type, rhughes@241: struct razor_rpm *rpm, rhughes@241: int name_tag, int version_tag, int flags_tag) rhughes@241: { rhughes@241: const char *name, *version; rhughes@241: const uint32_t *flags; rhughes@241: uint32_t f; rhughes@241: unsigned int i, count; rhughes@241: rhughes@241: name = razor_rpm_get_indirect(rpm, name_tag, &count); rhughes@241: if (name == NULL) rhughes@241: return; rhughes@241: rhughes@241: flags = razor_rpm_get_indirect(rpm, flags_tag, &count); rhughes@241: rhughes@241: version = razor_rpm_get_indirect(rpm, version_tag, &count); rhughes@241: for (i = 0; i < count; i++) { rhughes@241: f = rpm_to_razor_flags(ntohl(flags[i])); krh@247: razor_importer_add_property(importer, name, f | type, version); rhughes@241: name += strlen(name) + 1; rhughes@241: version += strlen(version) + 1; rhughes@241: } rhughes@241: } rhughes@241: rhughes@241: static void rhughes@241: import_files(struct razor_importer *importer, struct razor_rpm *rpm) rhughes@241: { rhughes@241: const char *name; rhughes@241: const uint32_t *index; rhughes@241: unsigned int i, count; rhughes@241: char buffer[256]; rhughes@241: krh@246: if (rpm->dirs == NULL) krh@246: return; krh@246: rhughes@241: /* assert: count is the same for all arrays */ rhughes@241: index = razor_rpm_get_indirect(rpm, RPMTAG_DIRINDEXES, &count); rhughes@241: name = razor_rpm_get_indirect(rpm, RPMTAG_BASENAMES, &count); rhughes@241: for (i = 0; i < count; i++) { rhughes@241: snprintf(buffer, sizeof buffer, rhughes@241: "%s%s", rpm->dirs[ntohl(*index)], name); rhughes@241: razor_importer_add_file(importer, buffer); rhughes@241: name += strlen(name) + 1; rhughes@241: index++; rhughes@241: } rhughes@241: } rhughes@241: ali@369: static void ali@369: razor_rpm_build_evr(struct razor_rpm *rpm) ali@369: { ali@369: const char *version, *release; ali@369: const uint32_t *epoch; ali@369: char evr[128], buf[16]; ali@369: ali@369: epoch = razor_rpm_get_indirect(rpm, RPMTAG_EPOCH, NULL); ali@369: version = razor_rpm_get_indirect(rpm, RPMTAG_VERSION, NULL); ali@369: release = razor_rpm_get_indirect(rpm, RPMTAG_RELEASE, NULL); ali@369: if (epoch) ali@369: snprintf(buf, sizeof buf, "%lu", (unsigned long)ntohl(*epoch)); ali@369: razor_build_evr(evr, sizeof evr, epoch ? buf : NULL, version, release); ali@369: rpm->evr = strdup(evr); ali@369: } ali@369: ali@369: static const char * ali@372: razor_rpm_get_details_string(struct razor_rpm *rpm, enum razor_detail_type type) ali@369: { ali@369: switch(type) { ali@369: case RAZOR_DETAIL_NAME: ali@369: return razor_rpm_get_indirect(rpm, RPMTAG_NAME, NULL); ali@369: ali@369: case RAZOR_DETAIL_VERSION: ali@369: if (!rpm->evr) ali@369: razor_rpm_build_evr(rpm); ali@369: return rpm->evr; ali@369: ali@369: case RAZOR_DETAIL_ARCH: ali@369: return razor_rpm_get_indirect(rpm, RPMTAG_ARCH, NULL); ali@369: ali@369: case RAZOR_DETAIL_SUMMARY: ali@369: return razor_rpm_get_indirect(rpm, RPMTAG_SUMMARY, NULL); ali@369: ali@369: case RAZOR_DETAIL_DESCRIPTION: ali@369: return razor_rpm_get_indirect(rpm, RPMTAG_DESCRIPTION, NULL); ali@369: ali@369: case RAZOR_DETAIL_URL: ali@369: return razor_rpm_get_indirect(rpm, RPMTAG_URL, NULL); ali@369: ali@369: case RAZOR_DETAIL_LICENSE: ali@369: return razor_rpm_get_indirect(rpm, RPMTAG_LICENSE, NULL); ali@369: ali@369: case RAZOR_DETAIL_PREUNPROG: ali@369: return razor_rpm_get_indirect(rpm, RPMTAG_PREUNPROG, NULL); ali@369: ali@369: case RAZOR_DETAIL_PREUN: ali@369: return razor_rpm_get_indirect(rpm, RPMTAG_PREUN, NULL); ali@369: ali@369: case RAZOR_DETAIL_POSTUNPROG: ali@369: return razor_rpm_get_indirect(rpm, RPMTAG_POSTUNPROG, NULL); ali@369: ali@369: case RAZOR_DETAIL_POSTUN: ali@369: return razor_rpm_get_indirect(rpm, RPMTAG_POSTUN, NULL); ali@369: ali@369: default: ali@369: fprintf(stderr, "type %u not found\n", type); ali@369: return NULL; ali@369: } ali@369: } ali@369: ali@372: static const char *const * ali@372: razor_rpm_get_details_array(struct razor_rpm *rpm, enum razor_detail_type type) ali@372: { ali@372: switch(type) { ali@372: case RAZOR_DETAIL_PREFIXES: ali@372: return rpm->prefixes; ali@372: ali@372: default: ali@372: /* Impossible */ ali@372: fprintf(stderr, "type %u not found\n", type); ali@372: return NULL; ali@372: } ali@372: } ali@372: ali@369: void ali@369: razor_rpm_get_details_varg(struct razor_rpm *rpm, va_list args) ali@369: { ali@369: int i; ali@369: enum razor_detail_type type; ali@372: const char **string; ali@372: const char *const **array; ali@369: ali@369: for (i = 0;; i += 2) { ali@369: type = va_arg(args, enum razor_detail_type); ali@369: if (type == RAZOR_DETAIL_LAST) ali@369: break; ali@372: if (type == RAZOR_DETAIL_PREFIXES) { ali@372: array = va_arg(args, const char *const **); ali@372: *array = razor_rpm_get_details_array(rpm, type); ali@372: } else { ali@372: string = va_arg(args, const char **); ali@372: *string = razor_rpm_get_details_string(rpm, type); ali@372: } ali@369: } ali@369: } ali@369: ali@369: RAZOR_EXPORT void ali@369: razor_rpm_get_details(struct razor_rpm *rpm, ...) ali@369: { ali@369: va_list args; ali@369: ali@369: assert(rpm != NULL); ali@369: ali@369: va_start(args, rpm); ali@369: razor_rpm_get_details_varg(rpm, args); ali@369: va_end(args); ali@369: } ali@369: krh@269: RAZOR_EXPORT struct razor_rpm * ali@403: razor_rpm_open(const char *filename, struct razor_atomic *atomic) rhughes@241: { rhughes@241: struct razor_rpm *rpm; rhughes@241: struct rpm_header_index *base, *index; rhughes@241: unsigned int count, i, nindex, hsize; ali@351: const char *name, *prefix; ali@403: char *s; rhughes@241: richard@301: assert (filename != NULL); richard@301: ali@403: rpm = zalloc(sizeof *rpm); ali@403: if (rpm == NULL) { ali@403: razor_atomic_abort(atomic, "Not enough memory"); krh@246: return NULL; ali@403: } rhughes@241: memset(rpm, 0, sizeof *rpm); rhughes@241: ali@322: rpm->map = razor_file_get_contents(filename, &rpm->size); ali@322: if (!rpm->map) { ali@403: s = razor_concat(filename, ": ", strerror(errno), NULL); ali@403: razor_atomic_abort(atomic, s); ali@403: free(s); ali@403: free(rpm); rhughes@241: return NULL; rhughes@241: } rhughes@241: rhughes@241: rpm->signature = rpm->map + RPM_LEAD_SIZE; rhughes@241: nindex = ntohl(rpm->signature->nindex); rhughes@241: hsize = ntohl(rpm->signature->hsize); rhughes@241: rpm->header = (void *) (rpm->signature + 1) + rhughes@241: ALIGN(nindex * sizeof *index + hsize, 8); rhughes@241: nindex = ntohl(rpm->header->nindex); rhughes@241: hsize = ntohl(rpm->header->hsize); rhughes@241: rpm->payload = (void *) (rpm->header + 1) + rhughes@241: nindex * sizeof *index + hsize; rhughes@241: rhughes@241: base = (struct rpm_header_index *) (rpm->header + 1); rhughes@241: rpm->pool = (void *) base + nindex * sizeof *index; rhughes@241: rhughes@241: /* Look up dir names now so we can index them directly. */ rhughes@241: name = razor_rpm_get_indirect(rpm, RPMTAG_DIRNAMES, &count); rhughes@241: if (name) { rhughes@241: rpm->dirs = calloc(count, sizeof *rpm->dirs); rhughes@241: for (i = 0; i < count; i++) { rhughes@241: rpm->dirs[i] = name; rhughes@241: name += strlen(name) + 1; rhughes@241: } rhughes@241: } else { rhughes@241: name = razor_rpm_get_indirect(rpm, RPMTAG_OLDFILENAMES, rhughes@241: &count); rhughes@241: if (name) { ali@403: razor_rpm_close(rpm); ali@403: s = razor_concat(filename, ali@403: ": Old filenames not supported", NULL); ali@403: razor_atomic_abort(atomic, s); ali@403: free(s); rhughes@241: return NULL; rhughes@241: } rhughes@241: } rhughes@241: ali@351: prefix = razor_rpm_get_indirect(rpm, RPMTAG_PREFIXES, &count); ali@351: if (prefix) { ali@372: rpm->prefixes = calloc(count + 1, sizeof *rpm->prefixes); ali@351: for (i = 0; i < count; i++) { ali@351: rpm->prefixes[i] = prefix; ali@351: prefix += strlen(prefix) + 1; ali@351: } ali@372: rpm->prefixes[i] = NULL; ali@351: rpm->n_prefixes = count; ali@351: } else { ali@351: prefix = razor_rpm_get_indirect(rpm, RPMTAG_DEFAULTPREFIX, ali@351: &count); ali@351: if (prefix) { ali@403: razor_rpm_close(rpm); ali@403: s = razor_concat(filename, ali@403: ": Default prefix not supported", ali@403: NULL); ali@403: razor_atomic_abort(atomic, s); ali@403: free(s); ali@351: return NULL; ali@351: } ali@351: } ali@351: rhughes@241: return rpm; rhughes@241: } rhughes@241: ali@351: RAZOR_EXPORT void razor_rpm_set_relocations(struct razor_rpm *rpm, ali@351: struct razor_relocations *rr) ali@351: { ali@351: assert (rpm != NULL); ali@351: ali@351: rpm->relocations = rr; ali@351: } ali@351: rhughes@241: struct cpio_file_header { rhughes@241: char magic[6]; rhughes@241: char inode[8]; rhughes@241: char mode[8]; rhughes@241: char uid[8]; rhughes@241: char gid[8]; rhughes@241: char nlink[8]; rhughes@241: char mtime[8]; rhughes@241: char filesize[8]; rhughes@241: char devmajor[8]; rhughes@241: char devminor[8]; rhughes@241: char rdevmajor[8]; rhughes@241: char rdevminor[8]; rhughes@241: char namesize[8]; rhughes@241: char checksum[8]; rhughes@241: char filename[0]; rhughes@241: }; rhughes@241: rhughes@241: /* gzip flags */ rhughes@241: #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ rhughes@241: #define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ rhughes@241: #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ rhughes@241: #define ORIG_NAME 0x08 /* bit 3 set: original file name present */ rhughes@241: #define COMMENT 0x10 /* bit 4 set: file comment present */ rhughes@241: #define RESERVED 0xE0 /* bits 5..7: reserved */ rhughes@241: rhughes@241: struct installer { rhughes@241: const char *root; rhughes@241: struct razor_rpm *rpm; ali@403: struct razor_atomic *atomic; rhughes@241: z_stream stream; rhughes@241: unsigned char buffer[32768]; rhughes@241: size_t rest, length; rhughes@241: }; rhughes@241: rhughes@241: static int rhughes@241: installer_inflate(struct installer *installer) rhughes@241: { rhughes@241: size_t length; rhughes@241: int err; rhughes@241: rhughes@241: if (installer->rest > sizeof installer->buffer) rhughes@241: length = sizeof installer->buffer; rhughes@241: else rhughes@241: length = installer->rest; rhughes@241: rhughes@241: installer->stream.next_out = installer->buffer; rhughes@241: installer->stream.avail_out = length; rhughes@241: err = inflate(&installer->stream, Z_SYNC_FLUSH); rhughes@241: if (err != Z_OK && err != Z_STREAM_END) { ali@403: razor_atomic_abort(installer->atomic, "Failed to inflate"); rhughes@241: return -1; rhughes@241: } rhughes@241: rhughes@241: installer->rest -= length; rhughes@241: installer->length = length; rhughes@241: rhughes@241: return 0; rhughes@241: } rhughes@241: rhughes@241: static int rhughes@241: installer_align(struct installer *installer, size_t size) rhughes@241: { rhughes@241: unsigned char buffer[4]; rhughes@241: int err; rhughes@241: rhughes@241: installer->stream.next_out = buffer; rhughes@241: installer->stream.avail_out = rhughes@241: (size - installer->stream.total_out) & (size - 1); rhughes@241: rhughes@241: if (installer->stream.avail_out == 0) rhughes@241: return 0; rhughes@241: rhughes@241: err = inflate(&installer->stream, Z_SYNC_FLUSH); rhughes@241: if (err != Z_OK && err != Z_STREAM_END) { ali@403: razor_atomic_abort(installer->atomic, "Failed to inflate"); rhughes@241: return -1; rhughes@241: } rhughes@241: rhughes@241: return 0; rhughes@241: } rhughes@241: rhughes@241: static int rhughes@241: create_path(struct installer *installer, const char *path, unsigned int mode) rhughes@241: { ali@403: char *s, *buffer; ali@403: int h, ret; rhughes@241: ali@403: if (razor_atomic_make_dirs(installer->atomic, installer->root, path)) rhughes@241: return -1; rhughes@241: ali@403: buffer = razor_concat(installer->root, path, NULL); rhughes@241: rhughes@241: switch (mode >> 12) { rhughes@241: case REG: rhughes@241: /* FIXME: handle the case where a file is already there. */ ali@403: h = razor_atomic_create_file(installer->atomic, buffer, mode); ali@403: free(buffer); ali@403: if (h < 0) rhughes@241: return -1; ali@403: while (installer->rest > 0) { ali@403: if (installer_inflate(installer)) ali@403: return -1; ali@403: if (razor_atomic_write(installer->atomic, h, ali@403: installer->buffer, ali@403: installer->length)) ali@403: return -1; rhughes@241: } ali@403: return razor_atomic_close(installer->atomic, h); rhughes@241: case XDIR: ali@403: ret = razor_atomic_create_dir(installer->atomic, buffer, mode); ali@403: free(buffer); ali@403: return ret; rhughes@241: case LINK: ali@327: #if HAVE_SYMLINK ali@403: if (installer_inflate(installer)) rhughes@241: return -1; rhughes@241: if (installer->length >= sizeof installer->buffer) { ali@403: razor_atomic_abort(installer->atomic, ali@403: "Link target too long"); rhughes@241: return -1; rhughes@241: } rhughes@241: installer->buffer[installer->length] = '\0'; ali@403: ret = razor_atomic_create_symlink(installer->atomic, ali@403: (const char *)installer->buffer, buffer); ali@403: free(buffer); ali@403: return ret; ali@327: #else ali@403: s = "Symbolic links"; ali@403: goto unsupported; ali@327: #endif ali@327: case PIPE: ali@403: s = "Named pipes"; ali@403: unsupported: ali@403: free(buffer); ali@403: buffer = razor_concat(s, " are not supported on this platform", ali@403: NULL); ali@403: razor_atomic_abort(installer->atomic, buffer); ali@403: free(buffer); ali@403: return -1; ali@327: case CDEV: ali@403: s = "Character devices"; ali@403: goto unsupported; ali@327: case BDEV: ali@403: s = "Block devices"; ali@403: goto unsupported; ali@327: case SOCK: ali@403: s = "Named sockets"; ali@403: goto unsupported; rhughes@241: default: ali@403: free(buffer); ali@403: razor_atomic_abort(installer->atomic, "Unknown file type"); ali@403: return -1; rhughes@241: } rhughes@241: } rhughes@241: ali@353: static int chroot_push(const char *root) ali@353: { ali@353: int fd; ali@353: #if HAVE_CHROOT ali@353: if (geteuid() == 0) { ali@353: fd = open("/", O_RDONLY, 0); ali@353: if (chroot(root) < 0) { ali@353: fprintf(stderr, "failed to chroot to %s: %s\n", ali@353: root, strerror(errno)); ali@353: exit(-1); ali@353: } ali@353: } else ali@353: #endif ali@353: fd = -1; ali@353: return fd; ali@353: } ali@353: ali@353: static void chroot_pop(int fd) rhughes@241: { ali@328: #if HAVE_CHROOT ali@353: if (fd >= 0) { ali@353: fchdir(fd); ali@353: close(fd); ali@353: chroot("."); ali@353: } ali@353: #endif ali@353: } ali@353: ali@353: static int ali@376: run_script_lua(const char *root, unsigned int script_tag, const char *script, ali@376: int arg1) ali@353: { ali@353: int root_fd, retval; ali@352: #if HAVE_LUA ali@353: const char *name; ali@353: ali@353: switch(script_tag) { ali@353: case RPMTAG_PREIN: ali@353: name = "%pre"; ali@353: break; ali@353: case RPMTAG_POSTIN: ali@353: name = "%post"; ali@353: break; ali@353: case RPMTAG_PREUN: ali@353: name = "%preun"; ali@353: break; ali@353: case RPMTAG_POSTUN: ali@353: name = "%postun"; ali@353: break; ali@353: default: ali@353: name = "script"; ali@353: break; ali@353: } ali@353: root_fd = chroot_push(root); ali@376: retval = run_lua_script(root_fd < 0 ? root : NULL, name, script, -1, ali@376: arg1); ali@353: chroot_pop(root_fd); ali@353: #else /* HAVE_LUA */ ali@353: fprintf(stderr, "lua not available to run script\n"); ali@353: retval = -1; ali@353: #endif /* HAVE_LUA */ ali@353: ali@353: return retval; ali@353: } ali@353: ali@353: static int ali@376: run_script_external(const char *root, const char *program, const char *script, ali@376: int arg1) ali@353: { ali@353: int root_fd, retval; ali@328: FILE *fp; ali@376: char buf[32], *command; rhughes@241: ali@353: if (program == NULL) { ali@328: #if MSWIN_API ali@328: program = getenv("COMSPEC"); ali@328: if (program) { ali@328: program = strchr(program, '='); ali@328: if (program) ali@328: program++; ali@328: } ali@328: if (!program) ali@328: program = "c:\\windows\\system32\\cmd.exe"; ali@328: #else rhughes@241: program = "/bin/sh"; ali@328: #endif rhughes@241: } rhughes@241: ali@353: root_fd = chroot_push(root); ali@376: if (arg1 >= 0) { ali@376: sprintf(buf, "%d", arg1); ali@376: command = malloc(strlen(program) + strlen(buf) + 2); ali@376: sprintf(command, "%s %s", program, buf); ali@376: } else ali@376: command = strdup(program); ali@376: fp = popen(command, "w"); ali@376: free(command); rhughes@241: ali@353: if (!fp) { ali@353: perror(program); ali@353: retval = -1; ali@370: } else if (script && fwrite(script, strlen(script), 1, fp) != 1) { ali@353: perror("failed to write script to program"); ali@353: retval = -1; ali@353: } else ali@353: retval = 0; ali@353: ali@353: if (fp) ali@353: pclose(fp); ali@353: chroot_pop(root_fd); ali@353: ali@353: return retval; ali@353: } ali@353: ali@353: static int ali@353: run_script(struct installer *installer, ali@376: unsigned int program_tag, unsigned int script_tag, int arg1) ali@353: { ali@362: int i, retval; ali@362: struct razor_rpm *rpm = installer->rpm; ali@362: const char *script = NULL, *program = NULL, *prefix; ali@376: char buf[32]; ali@372: struct environment env; ali@353: ali@362: program = razor_rpm_get_indirect(rpm, program_tag, NULL); ali@362: script = razor_rpm_get_indirect(rpm, script_tag, NULL); ali@353: if (program == NULL && script == NULL) ali@362: return 0; ali@362: ali@362: if (rpm->relocations) { ali@372: environment_init(&env); ali@362: for(i = 0; i < rpm->n_prefixes; i++) { ali@362: prefix = razor_relocations_apply(rpm->relocations, ali@362: rpm->prefixes[i]); ali@362: sprintf(buf, "RPM_INSTALL_PREFIX%d", i); ali@372: environment_add_variable(&env, buf, prefix); ali@362: } ali@372: environment_set(&env); ali@362: } ali@362: ali@369: if (program && strcmp(program, "") == 0) ali@376: retval = run_script_lua(installer->root, script_tag, script, ali@376: arg1); ali@353: else ali@376: retval = run_script_external(installer->root, program, script, ali@376: arg1); ali@353: ali@362: if (rpm->relocations) { ali@372: environment_unset(&env); ali@372: environment_release(&env); ali@362: } ali@362: ali@353: return retval; rhughes@241: } rhughes@241: ali@369: int ali@369: razor_run_script(const char *root, enum razor_property_flags script, ali@376: const char *program, const char *body, int arg1) ali@369: { ali@369: int retval; ali@369: unsigned int script_tag; ali@369: ali@369: if (program && !*program) ali@369: program = NULL; ali@369: if (body && !*body) ali@369: body = NULL; ali@369: if (program == NULL && body == NULL) ali@369: return 0; ali@369: ali@369: if (program && strcmp(program, "") == 0) ali@369: { ali@369: switch(script) { ali@369: case RAZOR_PROPERTY_PRE: ali@369: script_tag = RPMTAG_PREIN; ali@369: break; ali@369: case RAZOR_PROPERTY_POST: ali@369: script_tag = RPMTAG_POSTIN; ali@369: break; ali@369: case RAZOR_PROPERTY_PREUN: ali@369: script_tag = RPMTAG_PREUN; ali@369: break; ali@369: case RAZOR_PROPERTY_POSTUN: ali@369: script_tag = RPMTAG_POSTUN; ali@369: break; ali@369: default: ali@369: script_tag = 0; ali@369: break; ali@369: } ali@376: retval = run_script_lua(root, script_tag, body, arg1); ali@369: } ali@369: else ali@376: retval = run_script_external(root, program, body, arg1); ali@369: ali@369: return retval; ali@369: } ali@369: rhughes@241: static int rhughes@241: installer_init(struct installer *installer) rhughes@241: { rhughes@241: unsigned char *gz_header; rhughes@241: int method, flags, err; ali@403: char buffer[32], *s; rhughes@241: rhughes@241: gz_header = installer->rpm->payload; rhughes@241: if (gz_header[0] != 0x1f || gz_header[1] != 0x8b) { ali@403: razor_atomic_abort(installer->atomic, ali@403: "Payload section doesn't have gz header"); rhughes@241: return -1; rhughes@241: } rhughes@241: rhughes@241: method = gz_header[2]; rhughes@241: flags = gz_header[3]; rhughes@241: rhughes@241: if (method != Z_DEFLATED || flags != 0) { ali@403: razor_atomic_abort(installer->atomic, ali@403: "Unknown payload compression method or " ali@403: "flags set"); rhughes@241: return -1; rhughes@241: } rhughes@241: rhughes@241: installer->stream.zalloc = NULL; rhughes@241: installer->stream.zfree = NULL; rhughes@241: installer->stream.opaque = NULL; rhughes@241: rhughes@241: installer->stream.next_in = gz_header + 10; rhughes@241: installer->stream.avail_in = rhughes@241: (installer->rpm->map + installer->rpm->size) - rhughes@241: (void *) installer->stream.next_in; rhughes@241: installer->stream.next_out = NULL; rhughes@241: installer->stream.avail_out = 0; rhughes@241: rhughes@241: err = inflateInit2(&installer->stream, -MAX_WBITS); rhughes@241: if (err != Z_OK) { ali@403: sprintf(buffer, "%d", err); ali@403: s = razor_concat("inflateEnd error: ", s, NULL); ali@403: razor_atomic_abort(installer->atomic, s); ali@403: free(s); rhughes@241: return -1; rhughes@241: } rhughes@241: rhughes@241: return 0; rhughes@241: } rhughes@241: rhughes@241: static int rhughes@241: installer_finish(struct installer *installer) rhughes@241: { rhughes@241: int err; ali@403: char buffer[32], *s; rhughes@241: rhughes@241: err = inflateEnd(&installer->stream); rhughes@241: rhughes@241: if (err != Z_OK) { ali@403: sprintf(buffer, "%d", err); ali@403: s = razor_concat("inflateEnd error: ", s, NULL); ali@403: razor_atomic_abort(installer->atomic, s); ali@403: free(s); rhughes@241: } rhughes@241: ali@403: return razor_atomic_in_error_state(installer->atomic); rhughes@241: } rhughes@241: rhughes@241: static unsigned long rhughes@241: fixed_hex_to_ulong(const char *hex, int length) rhughes@241: { rhughes@241: long l; rhughes@241: int i; rhughes@241: rhughes@241: for (i = 0, l = 0; i < length; i++) { rhughes@241: if (hex[i] < 'a') rhughes@241: l = l * 16 + hex[i] - '0'; rhughes@241: else rhughes@241: l = l * 16 + hex[i] - 'a' + 10; rhughes@241: } rhughes@241: rhughes@241: return l; rhughes@241: } rhughes@241: krh@269: RAZOR_EXPORT int ali@403: razor_rpm_install(struct razor_rpm *rpm, struct razor_atomic *atomic, ali@403: const char *root, int install_count, ali@403: enum razor_stage_type stage) rhughes@241: { rhughes@241: struct installer installer; rhughes@241: struct cpio_file_header *header; rhughes@241: struct stat buf; rhughes@241: unsigned int mode; ali@403: const char *path, *name; rhughes@241: size_t filesize; ali@403: char *s; ali@422: int retval = 0; rhughes@241: richard@301: assert (rpm != NULL); richard@301: assert (root != NULL); richard@301: rhughes@241: installer.rpm = rpm; rhughes@241: installer.root = root; ali@403: installer.atomic = atomic; rhughes@241: rhughes@241: /* FIXME: Only do this before a transaction, not per rpm. */ ali@347: if (*root && (stat(root, &buf) < 0 || !S_ISDIR(buf.st_mode))) { ali@403: s = razor_concat(root, ": Directory does not exist", NULL); ali@403: razor_atomic_abort(stderr, s); ali@403: free(s); rhughes@241: return -1; rhughes@241: } rhughes@241: ali@351: if (rpm->relocations) ali@351: razor_relocations_set_rpm(rpm->relocations, rpm); ali@351: ali@403: if (stage & RAZOR_STAGE_SCRIPTS_PRE) ali@422: retval = run_script(&installer, RPMTAG_PREINPROG, RPMTAG_PREIN, ali@422: install_count); rhughes@241: ali@422: if (!retval && (stage & RAZOR_STAGE_FILES)) { ali@403: if (installer_init(&installer)) rhughes@241: return -1; rhughes@241: ali@403: while (installer.stream.avail_in > 0) { ali@403: installer.rest = sizeof *header; ali@403: if (installer_inflate(&installer)) ali@403: break; rhughes@241: ali@403: header = (struct cpio_file_header *) installer.buffer; ali@403: mode = fixed_hex_to_ulong(header->mode, ali@403: sizeof header->mode); ali@403: filesize = fixed_hex_to_ulong(header->filesize, ali@403: sizeof header->filesize); rhughes@241: ali@403: installer.rest = ali@403: fixed_hex_to_ulong(header->namesize, ali@403: sizeof header->namesize); rhughes@241: ali@403: if (installer_inflate(&installer) || ali@403: installer_align(&installer, 4)) ali@403: break; rhughes@241: ali@403: path = (const char *) installer.buffer; ali@403: /* This convention is so lame... */ ali@403: if (strcmp(path, "TRAILER!!!") == 0) ali@403: break; ali@403: ali@403: installer.rest = filesize; ali@403: path++; ali@403: if (rpm->relocations) ali@403: path = razor_relocations_apply(rpm->relocations, ali@403: path); ali@403: if (create_path(&installer, path, mode)) ali@403: break; ali@403: if (installer_align(&installer, 4)) ali@403: break; ali@403: } ali@403: ali@403: if (installer_finish(&installer)) rhughes@241: return -1; ali@422: ali@422: retval = razor_atomic_in_error_state(atomic); rhughes@241: } rhughes@241: ali@422: if (!retval && (stage & RAZOR_STAGE_SCRIPTS_POST)) ali@422: retval = run_script(&installer, RPMTAG_POSTINPROG, ali@422: RPMTAG_POSTIN, install_count); rhughes@241: ali@422: return retval; rhughes@241: } rhughes@241: krh@269: RAZOR_EXPORT int rhughes@241: razor_rpm_close(struct razor_rpm *rpm) rhughes@241: { rhughes@241: int err; rhughes@241: richard@301: assert (rpm != NULL); richard@301: rhughes@241: free(rpm->dirs); ali@351: free(rpm->prefixes); ali@322: err = razor_file_free_contents(rpm->map, rpm->size); ali@369: free(rpm->evr); rhughes@241: free(rpm); rhughes@241: rhughes@241: return err; rhughes@241: } rhughes@241: krh@269: RAZOR_EXPORT int rhughes@241: razor_importer_add_rpm(struct razor_importer *importer, struct razor_rpm *rpm) rhughes@241: { ali@369: const char *name, *version, *arch; jbowes@289: const char *summary, *description, *url, *license; rhughes@241: richard@301: assert (importer != NULL); richard@301: assert (rpm != NULL); richard@301: ali@369: razor_rpm_get_details(rpm, ali@369: RAZOR_DETAIL_NAME, &name, ali@369: RAZOR_DETAIL_VERSION, &version, ali@369: RAZOR_DETAIL_ARCH, &arch, ali@369: RAZOR_DETAIL_SUMMARY, &summary, ali@369: RAZOR_DETAIL_DESCRIPTION, &description, ali@369: RAZOR_DETAIL_URL, &url, ali@369: RAZOR_DETAIL_LICENSE, &license, ali@369: RAZOR_DETAIL_LAST); jbowes@289: ali@369: razor_importer_begin_package(importer, name, version, arch); rhughes@241: jbowes@289: razor_importer_add_details(importer, summary, description, url, jbowes@289: license); jbowes@289: rhughes@241: import_properties(importer, RAZOR_PROPERTY_REQUIRES, rpm, rhughes@241: RPMTAG_REQUIRENAME, rhughes@241: RPMTAG_REQUIREVERSION, rhughes@241: RPMTAG_REQUIREFLAGS); rhughes@241: rhughes@241: import_properties(importer, RAZOR_PROPERTY_PROVIDES, rpm, rhughes@241: RPMTAG_PROVIDENAME, rhughes@241: RPMTAG_PROVIDEVERSION, rhughes@241: RPMTAG_PROVIDEFLAGS); rhughes@241: rhughes@241: import_properties(importer, RAZOR_PROPERTY_OBSOLETES, rpm, rhughes@241: RPMTAG_OBSOLETENAME, rhughes@241: RPMTAG_OBSOLETEVERSION, rhughes@241: RPMTAG_OBSOLETEFLAGS); rhughes@241: rhughes@241: import_properties(importer, RAZOR_PROPERTY_CONFLICTS, rpm, rhughes@241: RPMTAG_CONFLICTNAME, rhughes@241: RPMTAG_CONFLICTVERSION, rhughes@241: RPMTAG_CONFLICTFLAGS); rhughes@241: rhughes@241: import_files(importer, rpm); rhughes@241: rhughes@241: razor_importer_finish_package(importer); rhughes@241: rhughes@241: return 0; rhughes@241: }