librazor/rpm.c
author J. Ali Harlow <ali@juiblex.co.uk>
Wed Apr 29 17:00:01 2009 +0100 (2009-04-29)
changeset 361 2523d03a840e
parent 353 90b63682fdd7
child 362 cf88b5df2884
permissions -rw-r--r--
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).
rhughes@241
     1
/*
rhughes@241
     2
 * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
rhughes@241
     3
 * Copyright (C) 2008  Red Hat, Inc
ali@351
     4
 * Copyright (C) 2009  J. Ali Harlow <ali@juiblex.co.uk>
rhughes@241
     5
 *
rhughes@241
     6
 * This program is free software; you can redistribute it and/or modify
rhughes@241
     7
 * it under the terms of the GNU General Public License as published by
rhughes@241
     8
 * the Free Software Foundation; either version 2 of the License, or
rhughes@241
     9
 * (at your option) any later version.
rhughes@241
    10
 *
rhughes@241
    11
 * This program is distributed in the hope that it will be useful,
rhughes@241
    12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
rhughes@241
    13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
rhughes@241
    14
 * GNU General Public License for more details.
rhughes@241
    15
 *
rhughes@241
    16
 * You should have received a copy of the GNU General Public License along
rhughes@241
    17
 * with this program; if not, write to the Free Software Foundation, Inc.,
rhughes@241
    18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
rhughes@241
    19
 */
rhughes@241
    20
ali@327
    21
#include "config.h"
ali@327
    22
rhughes@241
    23
#include <stdio.h>
rhughes@241
    24
#include <stddef.h>
rhughes@241
    25
#include <stdlib.h>
rhughes@241
    26
#include <string.h>
rhughes@241
    27
#include <errno.h>
rhughes@241
    28
#include <sys/stat.h>
rhughes@241
    29
#include <sys/types.h>
ali@330
    30
#if HAVE_SYS_WAIT_H
rhughes@241
    31
#include <sys/wait.h>
ali@330
    32
#endif
rhughes@241
    33
#include <fcntl.h>
rhughes@241
    34
#include <dirent.h>
rhughes@241
    35
#include <unistd.h>
ali@329
    36
#if MSWIN_API
ali@335
    37
#include <winsock2.h>	/* For ntohl() */
ali@329
    38
#else
rhughes@241
    39
#include <arpa/inet.h>
ali@329
    40
#endif
ali@325
    41
#include <limits.h>
rhughes@241
    42
#include <zlib.h>
richard@301
    43
#include <assert.h>
rhughes@241
    44
rhughes@241
    45
#include "razor.h"
rhughes@241
    46
#include "razor-internal.h"
rhughes@241
    47
ali@345
    48
#ifndef O_BINARY
ali@345
    49
#define O_BINARY	0
ali@345
    50
#endif
ali@345
    51
rhughes@241
    52
#define	RPM_LEAD_SIZE 96
rhughes@241
    53
rhughes@241
    54
enum {
rhughes@241
    55
    PIPE	=  1,	/*!< pipe/fifo */
rhughes@241
    56
    CDEV	=  2,	/*!< character device */
rhughes@241
    57
    XDIR	=  4,	/*!< directory */
rhughes@241
    58
    BDEV	=  6,	/*!< block device */
rhughes@241
    59
    REG		=  8,	/*!< regular file */
rhughes@241
    60
    LINK	= 10,	/*!< hard link */
rhughes@241
    61
    SOCK	= 12	/*!< socket */
rhughes@241
    62
};
rhughes@241
    63
rhughes@241
    64
enum {
krh@247
    65
    RPMSENSE_LESS		= 1 << 1,
krh@247
    66
    RPMSENSE_GREATER		= 1 << 2,
krh@247
    67
    RPMSENSE_EQUAL		= 1 << 3,
krh@247
    68
    RPMSENSE_PREREQ		= 1 << 6,
krh@247
    69
    RPMSENSE_SCRIPT_PRE		= 1 << 9,
krh@247
    70
    RPMSENSE_SCRIPT_POST	= 1 << 10,
krh@247
    71
    RPMSENSE_SCRIPT_PREUN	= 1 << 11,
krh@247
    72
    RPMSENSE_SCRIPT_POSTUN	= 1 << 12,
rhughes@241
    73
};
rhughes@241
    74
rhughes@241
    75
enum {
rhughes@241
    76
    RPMTAG_NAME  		= 1000,	/* s */
rhughes@241
    77
    RPMTAG_VERSION		= 1001,	/* s */
rhughes@241
    78
    RPMTAG_RELEASE		= 1002,	/* s */
rhughes@241
    79
    RPMTAG_EPOCH   		= 1003,	/* i */
rhughes@241
    80
    RPMTAG_SUMMARY		= 1004,	/* s{} */
rhughes@241
    81
    RPMTAG_DESCRIPTION		= 1005,	/* s{} */
rhughes@241
    82
    RPMTAG_BUILDTIME		= 1006,	/* i */
rhughes@241
    83
    RPMTAG_BUILDHOST		= 1007,	/* s */
rhughes@241
    84
    RPMTAG_INSTALLTIME		= 1008,	/* i */
rhughes@241
    85
    RPMTAG_SIZE			= 1009,	/* i */
rhughes@241
    86
    RPMTAG_DISTRIBUTION		= 1010,	/* s */
rhughes@241
    87
    RPMTAG_VENDOR		= 1011,	/* s */
rhughes@241
    88
    RPMTAG_GIF			= 1012,	/* x */
rhughes@241
    89
    RPMTAG_XPM			= 1013,	/* x */
rhughes@241
    90
    RPMTAG_LICENSE		= 1014,	/* s */
rhughes@241
    91
    RPMTAG_PACKAGER		= 1015,	/* s */
rhughes@241
    92
    RPMTAG_GROUP		= 1016,	/* s{} */
rhughes@241
    93
    RPMTAG_CHANGELOG		= 1017, /*!< s[] internal */
rhughes@241
    94
    RPMTAG_SOURCE		= 1018,	/* s[] */
rhughes@241
    95
    RPMTAG_PATCH		= 1019,	/* s[] */
rhughes@241
    96
    RPMTAG_URL			= 1020,	/* s */
rhughes@241
    97
    RPMTAG_OS			= 1021,	/* s legacy used int */
rhughes@241
    98
    RPMTAG_ARCH			= 1022,	/* s legacy used int */
rhughes@241
    99
    RPMTAG_PREIN		= 1023,	/* s */
rhughes@241
   100
    RPMTAG_POSTIN		= 1024,	/* s */
rhughes@241
   101
    RPMTAG_PREUN		= 1025,	/* s */
rhughes@241
   102
    RPMTAG_POSTUN		= 1026,	/* s */
rhughes@241
   103
    RPMTAG_OLDFILENAMES		= 1027, /* s[] obsolete */
rhughes@241
   104
    RPMTAG_FILESIZES		= 1028,	/* i */
rhughes@241
   105
    RPMTAG_FILESTATES		= 1029, /* c */
rhughes@241
   106
    RPMTAG_FILEMODES		= 1030,	/* h */
rhughes@241
   107
    RPMTAG_FILEUIDS		= 1031, /*!< internal */
rhughes@241
   108
    RPMTAG_FILEGIDS		= 1032, /*!< internal */
rhughes@241
   109
    RPMTAG_FILERDEVS		= 1033,	/* h */
rhughes@241
   110
    RPMTAG_FILEMTIMES		= 1034, /* i */
rhughes@241
   111
    RPMTAG_FILEMD5S		= 1035,	/* s[] */
rhughes@241
   112
    RPMTAG_FILELINKTOS		= 1036,	/* s[] */
rhughes@241
   113
    RPMTAG_FILEFLAGS		= 1037,	/* i */
rhughes@241
   114
    RPMTAG_ROOT			= 1038, /*!< internal - obsolete */
rhughes@241
   115
    RPMTAG_FILEUSERNAME		= 1039,	/* s[] */
rhughes@241
   116
    RPMTAG_FILEGROUPNAME	= 1040,	/* s[] */
rhughes@241
   117
    RPMTAG_EXCLUDE		= 1041, /*!< internal - obsolete */
rhughes@241
   118
    RPMTAG_EXCLUSIVE		= 1042, /*!< internal - obsolete */
rhughes@241
   119
    RPMTAG_ICON			= 1043,
rhughes@241
   120
    RPMTAG_SOURCERPM		= 1044,	/* s */
rhughes@241
   121
    RPMTAG_FILEVERIFYFLAGS	= 1045,	/* i */
rhughes@241
   122
    RPMTAG_ARCHIVESIZE		= 1046,	/* i */
rhughes@241
   123
    RPMTAG_PROVIDENAME		= 1047,	/* s[] */
rhughes@241
   124
    RPMTAG_REQUIREFLAGS		= 1048,	/* i */
rhughes@241
   125
    RPMTAG_REQUIRENAME		= 1049,	/* s[] */
rhughes@241
   126
    RPMTAG_REQUIREVERSION	= 1050,	/* s[] */
rhughes@241
   127
    RPMTAG_NOSOURCE		= 1051, /*!< internal */
rhughes@241
   128
    RPMTAG_NOPATCH		= 1052, /*!< internal */
rhughes@241
   129
    RPMTAG_CONFLICTFLAGS	= 1053, /* i */
rhughes@241
   130
    RPMTAG_CONFLICTNAME		= 1054,	/* s[] */
rhughes@241
   131
    RPMTAG_CONFLICTVERSION	= 1055,	/* s[] */
rhughes@241
   132
    RPMTAG_DEFAULTPREFIX	= 1056, /*!< internal - deprecated */
rhughes@241
   133
    RPMTAG_BUILDROOT		= 1057, /*!< internal */
rhughes@241
   134
    RPMTAG_INSTALLPREFIX	= 1058, /*!< internal - deprecated */
rhughes@241
   135
    RPMTAG_EXCLUDEARCH		= 1059,
rhughes@241
   136
    RPMTAG_EXCLUDEOS		= 1060,
rhughes@241
   137
    RPMTAG_EXCLUSIVEARCH	= 1061,
rhughes@241
   138
    RPMTAG_EXCLUSIVEOS		= 1062,
rhughes@241
   139
    RPMTAG_AUTOREQPROV		= 1063, /*!< internal */
rhughes@241
   140
    RPMTAG_RPMVERSION		= 1064,	/* s */
rhughes@241
   141
    RPMTAG_TRIGGERSCRIPTS	= 1065,	/* s[] */
rhughes@241
   142
    RPMTAG_TRIGGERNAME		= 1066,	/* s[] */
rhughes@241
   143
    RPMTAG_TRIGGERVERSION	= 1067,	/* s[] */
rhughes@241
   144
    RPMTAG_TRIGGERFLAGS		= 1068,	/* i */
rhughes@241
   145
    RPMTAG_TRIGGERINDEX		= 1069,	/* i */
rhughes@241
   146
    RPMTAG_VERIFYSCRIPT		= 1079,	/* s */
rhughes@241
   147
    RPMTAG_CHANGELOGTIME	= 1080,	/* i */
rhughes@241
   148
    RPMTAG_CHANGELOGNAME	= 1081,	/* s[] */
rhughes@241
   149
    RPMTAG_CHANGELOGTEXT	= 1082,	/* s[] */
rhughes@241
   150
    RPMTAG_BROKENMD5		= 1083, /*!< internal - obsolete */
rhughes@241
   151
    RPMTAG_PREREQ		= 1084, /*!< internal */
rhughes@241
   152
    RPMTAG_PREINPROG		= 1085,	/* s */
rhughes@241
   153
    RPMTAG_POSTINPROG		= 1086,	/* s */
rhughes@241
   154
    RPMTAG_PREUNPROG		= 1087,	/* s */
rhughes@241
   155
    RPMTAG_POSTUNPROG		= 1088,	/* s */
rhughes@241
   156
    RPMTAG_BUILDARCHS		= 1089,
rhughes@241
   157
    RPMTAG_OBSOLETENAME		= 1090,	/* s[] */
rhughes@241
   158
    RPMTAG_VERIFYSCRIPTPROG	= 1091,	/* s */
rhughes@241
   159
    RPMTAG_TRIGGERSCRIPTPROG	= 1092,	/* s */
rhughes@241
   160
    RPMTAG_DOCDIR		= 1093, /*!< internal */
rhughes@241
   161
    RPMTAG_COOKIE		= 1094,	/* s */
rhughes@241
   162
    RPMTAG_FILEDEVICES		= 1095,	/* i */
rhughes@241
   163
    RPMTAG_FILEINODES		= 1096,	/* i */
rhughes@241
   164
    RPMTAG_FILELANGS		= 1097,	/* s[] */
rhughes@241
   165
    RPMTAG_PREFIXES		= 1098,	/* s[] */
rhughes@241
   166
    RPMTAG_INSTPREFIXES		= 1099,	/* s[] */
rhughes@241
   167
    RPMTAG_TRIGGERIN		= 1100, /*!< internal */
rhughes@241
   168
    RPMTAG_TRIGGERUN		= 1101, /*!< internal */
rhughes@241
   169
    RPMTAG_TRIGGERPOSTUN	= 1102, /*!< internal */
rhughes@241
   170
    RPMTAG_AUTOREQ		= 1103, /*!< internal */
rhughes@241
   171
    RPMTAG_AUTOPROV		= 1104, /*!< internal */
rhughes@241
   172
    RPMTAG_CAPABILITY		= 1105, /*!< internal - obsolete */
rhughes@241
   173
    RPMTAG_SOURCEPACKAGE	= 1106, /*!< i src.rpm header marker */
rhughes@241
   174
    RPMTAG_OLDORIGFILENAMES	= 1107, /*!< internal - obsolete */
rhughes@241
   175
    RPMTAG_BUILDPREREQ		= 1108, /*!< internal */
rhughes@241
   176
    RPMTAG_BUILDREQUIRES	= 1109, /*!< internal */
rhughes@241
   177
    RPMTAG_BUILDCONFLICTS	= 1110, /*!< internal */
rhughes@241
   178
    RPMTAG_BUILDMACROS		= 1111, /*!< internal - unused */
rhughes@241
   179
    RPMTAG_PROVIDEFLAGS		= 1112,	/* i */
rhughes@241
   180
    RPMTAG_PROVIDEVERSION	= 1113,	/* s[] */
rhughes@241
   181
    RPMTAG_OBSOLETEFLAGS	= 1114,	/* i */
rhughes@241
   182
    RPMTAG_OBSOLETEVERSION	= 1115,	/* s[] */
rhughes@241
   183
    RPMTAG_DIRINDEXES		= 1116,	/* i */
rhughes@241
   184
    RPMTAG_BASENAMES		= 1117,	/* s[] */
rhughes@241
   185
    RPMTAG_DIRNAMES		= 1118,	/* s[] */
rhughes@241
   186
    RPMTAG_ORIGDIRINDEXES	= 1119, /*!< internal */
rhughes@241
   187
    RPMTAG_ORIGBASENAMES	= 1120, /*!< internal */
rhughes@241
   188
    RPMTAG_ORIGDIRNAMES		= 1121, /*!< internal */
rhughes@241
   189
    RPMTAG_OPTFLAGS		= 1122,	/* s */
rhughes@241
   190
    RPMTAG_DISTURL		= 1123,	/* s */
rhughes@241
   191
    RPMTAG_PAYLOADFORMAT	= 1124,	/* s */
rhughes@241
   192
    RPMTAG_PAYLOADCOMPRESSOR	= 1125,	/* s */
rhughes@241
   193
    RPMTAG_PAYLOADFLAGS		= 1126,	/* s */
rhughes@241
   194
    RPMTAG_INSTALLCOLOR		= 1127, /*!< i transaction color when installed */
rhughes@241
   195
    RPMTAG_INSTALLTID		= 1128,	/* i */
rhughes@241
   196
    RPMTAG_REMOVETID		= 1129,	/* i */
rhughes@241
   197
    RPMTAG_SHA1RHN		= 1130, /*!< internal - obsolete */
rhughes@241
   198
    RPMTAG_RHNPLATFORM		= 1131,	/* s */
rhughes@241
   199
    RPMTAG_PLATFORM		= 1132,	/* s */
rhughes@241
   200
    RPMTAG_PATCHESNAME		= 1133, /*!< placeholder (SuSE) */
rhughes@241
   201
    RPMTAG_PATCHESFLAGS		= 1134, /*!< placeholder (SuSE) */
rhughes@241
   202
    RPMTAG_PATCHESVERSION	= 1135, /*!< placeholder (SuSE) */
rhughes@241
   203
    RPMTAG_CACHECTIME		= 1136,	/* i */
rhughes@241
   204
    RPMTAG_CACHEPKGPATH		= 1137,	/* s */
rhughes@241
   205
    RPMTAG_CACHEPKGSIZE		= 1138,	/* i */
rhughes@241
   206
    RPMTAG_CACHEPKGMTIME	= 1139,	/* i */
rhughes@241
   207
    RPMTAG_FILECOLORS		= 1140,	/* i */
rhughes@241
   208
    RPMTAG_FILECLASS		= 1141,	/* i */
rhughes@241
   209
    RPMTAG_CLASSDICT		= 1142,	/* s[] */
rhughes@241
   210
    RPMTAG_FILEDEPENDSX		= 1143,	/* i */
rhughes@241
   211
    RPMTAG_FILEDEPENDSN		= 1144,	/* i */
rhughes@241
   212
    RPMTAG_DEPENDSDICT		= 1145,	/* i */
rhughes@241
   213
    RPMTAG_SOURCEPKGID		= 1146,	/* x */
rhughes@241
   214
    RPMTAG_FILECONTEXTS		= 1147,	/* s[] */
rhughes@241
   215
    RPMTAG_FSCONTEXTS		= 1148,	/*!< s[] extension */
rhughes@241
   216
    RPMTAG_RECONTEXTS		= 1149,	/*!< s[] extension */
rhughes@241
   217
    RPMTAG_POLICIES		= 1150,	/*!< s[] selinux *.te policy file. */
rhughes@241
   218
    RPMTAG_PRETRANS		= 1151,	/* s */
rhughes@241
   219
    RPMTAG_POSTTRANS		= 1152,	/* s */
rhughes@241
   220
    RPMTAG_PRETRANSPROG		= 1153,	/* s */
rhughes@241
   221
    RPMTAG_POSTTRANSPROG	= 1154,	/* s */
rhughes@241
   222
    RPMTAG_DISTTAG		= 1155,	/* s */
rhughes@241
   223
    RPMTAG_SUGGESTSNAME		= 1156,	/* s[] extension placeholder */
rhughes@241
   224
    RPMTAG_SUGGESTSVERSION	= 1157,	/* s[] extension placeholder */
rhughes@241
   225
    RPMTAG_SUGGESTSFLAGS	= 1158,	/* i   extension placeholder */
rhughes@241
   226
    RPMTAG_ENHANCESNAME		= 1159,	/* s[] extension placeholder */
rhughes@241
   227
    RPMTAG_ENHANCESVERSION	= 1160,	/* s[] extension placeholder */
rhughes@241
   228
    RPMTAG_ENHANCESFLAGS	= 1161,	/* i   extension placeholder */
rhughes@241
   229
    RPMTAG_PRIORITY		= 1162, /* i   extension placeholder */
rhughes@241
   230
    RPMTAG_CVSID		= 1163, /* s */
rhughes@241
   231
    RPMTAG_TRIGGERPREIN		= 1171, /*!< internal */
rhughes@241
   232
};
rhughes@241
   233
rhughes@241
   234
struct rpm_header {
rhughes@241
   235
	unsigned char magic[4];
rhughes@241
   236
	unsigned char reserved[4];
rhughes@241
   237
	int nindex;
rhughes@241
   238
	int hsize;
rhughes@241
   239
};
rhughes@241
   240
rhughes@241
   241
struct rpm_header_index {
rhughes@241
   242
	int tag;
rhughes@241
   243
	int type;
rhughes@241
   244
	int offset;
rhughes@241
   245
	int count;
rhughes@241
   246
};
rhughes@241
   247
rhughes@241
   248
struct razor_rpm {
rhughes@241
   249
	struct rpm_header *signature;
rhughes@241
   250
	struct rpm_header *header;
rhughes@241
   251
	const char **dirs;
ali@351
   252
	unsigned int n_prefixes;
ali@351
   253
	const char **prefixes;
rhughes@241
   254
	const char *pool;
rhughes@241
   255
	void *map;
rhughes@241
   256
	size_t size;
rhughes@241
   257
	void *payload;
ali@351
   258
	struct razor_relocations *relocations;
rhughes@241
   259
};
rhughes@241
   260
ali@351
   261
enum razor_relocation_flags {
ali@351
   262
	RAZOR_RELOCATION_ACTIVE		= 1 << 0,
ali@351
   263
};
ali@351
   264
ali@351
   265
struct razor_relocation {
ali@351
   266
	enum razor_relocation_flags flags;
ali@351
   267
	size_t oldlen;
ali@351
   268
	size_t newlen;
ali@351
   269
	char *oldpath;
ali@351
   270
	char *newpath;
ali@351
   271
};
ali@351
   272
ali@351
   273
struct razor_relocations {
ali@351
   274
	/* Ordered such that if oldpath 1 starts with oldpath 2, then
ali@351
   275
	 * oldpath 1 is listed first (ie., /usr/bin comes before /usr)
ali@351
   276
	 * and terminated with a NULL oldpath.
ali@351
   277
	 */
ali@351
   278
	struct razor_relocation *relocations;
ali@351
   279
	int n_relocations;
ali@351
   280
	char *path;
ali@351
   281
};
ali@351
   282
ali@351
   283
RAZOR_EXPORT struct razor_relocations *razor_relocations_create(void)
ali@351
   284
{
ali@351
   285
	return calloc(1, sizeof(struct razor_relocations));
ali@351
   286
}
ali@351
   287
ali@351
   288
RAZOR_EXPORT void razor_relocations_add(struct razor_relocations *rr,
ali@351
   289
			   const char *oldpath, const char *newpath)
ali@351
   290
{
ali@351
   291
	int i, found = 0;
ali@351
   292
	size_t len;
ali@351
   293
ali@351
   294
	if (newpath && !strcmp(oldpath, newpath))
ali@351
   295
		newpath = NULL;
ali@351
   296
ali@351
   297
	for (i = 0; i < rr->n_relocations; i++) {
ali@351
   298
		len = rr->relocations[i].oldlen;
ali@351
   299
		if (!strncmp(rr->relocations[i].oldpath, oldpath, len)) {
ali@351
   300
			found = !strcmp(rr->relocations[i].oldpath, oldpath);
ali@351
   301
			break;
ali@351
   302
		}
ali@351
   303
	}
ali@351
   304
ali@351
   305
	if (!newpath) {
ali@351
   306
		if (found) {
ali@351
   307
			free(rr->relocations[i].oldpath);
ali@351
   308
			free(rr->relocations[i].newpath);
ali@351
   309
			do {
ali@351
   310
				rr->relocations[i] = rr->relocations[i + 1];
ali@351
   311
			} while (rr->relocations[++i].oldpath);
ali@351
   312
		}
ali@351
   313
		return;
ali@351
   314
	}
ali@351
   315
ali@351
   316
	if (found) {
ali@351
   317
		free(rr->relocations[i].newpath);
ali@351
   318
		rr->relocations[i].newpath = strdup(newpath);
ali@351
   319
		rr->relocations[i].newlen = strlen(newpath);
ali@351
   320
		return;
ali@351
   321
	}
ali@351
   322
ali@351
   323
	if (!rr->n_relocations++)
ali@351
   324
		rr->relocations = calloc(1, sizeof *rr->relocations);
ali@351
   325
	else {
ali@351
   326
		rr->relocations = realloc(rr->relocations,
ali@351
   327
					  rr->n_relocations * sizeof *rr->relocations);
ali@351
   328
		memmove(rr->relocations + i + 1, rr->relocations + i,
ali@351
   329
			(rr->n_relocations - i - 1) * sizeof *rr->relocations);
ali@351
   330
	}
ali@351
   331
ali@351
   332
	rr->relocations[i].flags = 0;
ali@351
   333
	rr->relocations[i].oldpath = strdup(oldpath);
ali@351
   334
	rr->relocations[i].newpath = strdup(newpath);
ali@351
   335
	rr->relocations[i].oldlen = strlen(oldpath);
ali@351
   336
	rr->relocations[i].newlen = strlen(newpath);
ali@351
   337
}
ali@351
   338
ali@351
   339
RAZOR_EXPORT void
ali@351
   340
razor_relocations_set_rpm(struct razor_relocations *rr, struct razor_rpm *rpm)
ali@351
   341
{
ali@351
   342
	int i, j;
ali@351
   343
ali@351
   344
	for (i = 0; i < rr->n_relocations; i++) {
ali@351
   345
		rr->relocations[i].flags &= ~RAZOR_RELOCATION_ACTIVE;
ali@351
   346
		for (j = 0; j < rpm->n_prefixes; j++)
ali@351
   347
			if (!strcmp(rpm->prefixes[j],
ali@351
   348
				    rr->relocations[i].oldpath)) {
ali@351
   349
				rr->relocations[i].flags |= RAZOR_RELOCATION_ACTIVE;
ali@351
   350
				break;
ali@351
   351
			}
ali@351
   352
	}
ali@351
   353
}
ali@351
   354
ali@351
   355
RAZOR_EXPORT const char *
ali@351
   356
razor_relocations_apply(struct razor_relocations *rr, const char *path)
ali@351
   357
{
ali@351
   358
	int i;
ali@351
   359
	size_t len;
ali@351
   360
ali@351
   361
	for (i = 0; i < rr->n_relocations; i++)
ali@351
   362
		if (rr->relocations[i].flags & RAZOR_RELOCATION_ACTIVE &&
ali@351
   363
		    !strncmp(path, rr->relocations[i].oldpath,
ali@351
   364
			     rr->relocations[i].oldlen))
ali@351
   365
			break;
ali@351
   366
ali@351
   367
	if (i < rr->n_relocations) {
ali@351
   368
		free(rr->path);
ali@351
   369
		len = strlen(path + rr->relocations[i].oldlen) +
ali@351
   370
		      rr->relocations[i].newlen;
ali@351
   371
		rr->path = malloc(len + 1);
ali@351
   372
		memcpy(rr->path, rr->relocations[i].newpath,
ali@351
   373
		       rr->relocations[i].newlen);
ali@351
   374
		strcpy(rr->path + rr->relocations[i].newlen,
ali@351
   375
		       path + rr->relocations[i].oldlen);
ali@351
   376
		return rr->path;
ali@351
   377
	} else
ali@351
   378
		return path;
ali@351
   379
}
ali@351
   380
ali@351
   381
RAZOR_EXPORT void razor_relocations_destroy(struct razor_relocations *rr)
ali@351
   382
{
ali@351
   383
	free(rr->path);
ali@351
   384
	free(rr->relocations);
ali@351
   385
	free(rr);
ali@351
   386
}
ali@351
   387
rhughes@241
   388
static struct rpm_header_index *
rhughes@241
   389
razor_rpm_get_header(struct razor_rpm *rpm, unsigned int tag)
rhughes@241
   390
{
rhughes@241
   391
	struct rpm_header_index *index, *end;
rhughes@241
   392
rhughes@241
   393
	index = (struct rpm_header_index *) (rpm->header + 1);
rhughes@241
   394
	end = index + ntohl(rpm->header->nindex);
rhughes@241
   395
	while (index < end) {
rhughes@241
   396
		if (ntohl(index->tag) == tag)
rhughes@241
   397
			return index;
rhughes@241
   398
		index++;
rhughes@241
   399
	}
rhughes@241
   400
rhughes@241
   401
	return NULL;
rhughes@241
   402
}
rhughes@241
   403
rhughes@241
   404
static const void *
rhughes@241
   405
razor_rpm_get_indirect(struct razor_rpm *rpm,
rhughes@241
   406
		       unsigned int tag, unsigned int *count)
rhughes@241
   407
{
rhughes@241
   408
	struct rpm_header_index *index;
rhughes@241
   409
rhughes@241
   410
	index = razor_rpm_get_header(rpm, tag);
rhughes@241
   411
	if (index != NULL) {
rhughes@241
   412
		if (count)
rhughes@241
   413
			*count = ntohl(index->count);
rhughes@241
   414
rhughes@241
   415
		return rpm->pool + ntohl(index->offset);
rhughes@241
   416
	}
rhughes@241
   417
rhughes@241
   418
	return NULL;
rhughes@241
   419
}
rhughes@241
   420
krh@247
   421
static uint32_t
rhughes@241
   422
rpm_to_razor_flags(uint32_t flags)
rhughes@241
   423
{
krh@247
   424
	uint32_t razor_flags;
rhughes@241
   425
krh@247
   426
	razor_flags = 0;
krh@247
   427
	if (flags & RPMSENSE_LESS)
krh@247
   428
		razor_flags |= RAZOR_PROPERTY_LESS;
krh@247
   429
	if (flags & RPMSENSE_EQUAL)
krh@247
   430
		razor_flags |= RAZOR_PROPERTY_EQUAL;
krh@247
   431
	if (flags & RPMSENSE_GREATER)
krh@247
   432
		razor_flags |= RAZOR_PROPERTY_GREATER;
krh@247
   433
krh@247
   434
	if (flags & RPMSENSE_SCRIPT_PRE)
krh@247
   435
		razor_flags |= RAZOR_PROPERTY_PRE;
krh@247
   436
	if (flags & RPMSENSE_SCRIPT_POST)
krh@247
   437
		razor_flags |= RAZOR_PROPERTY_POST;
krh@247
   438
	if (flags & RPMSENSE_SCRIPT_PREUN)
krh@247
   439
		razor_flags |= RAZOR_PROPERTY_PREUN;
krh@247
   440
	if (flags & RPMSENSE_SCRIPT_POSTUN)
krh@247
   441
		razor_flags |= RAZOR_PROPERTY_POSTUN;
krh@247
   442
	
krh@247
   443
	return razor_flags;
rhughes@241
   444
}
rhughes@241
   445
rhughes@241
   446
static void
krh@247
   447
import_properties(struct razor_importer *importer, uint32_t type,
rhughes@241
   448
		  struct razor_rpm *rpm,
rhughes@241
   449
		  int name_tag, int version_tag, int flags_tag)
rhughes@241
   450
{
rhughes@241
   451
	const char *name, *version;
rhughes@241
   452
	const uint32_t *flags;
rhughes@241
   453
	uint32_t f;
rhughes@241
   454
	unsigned int i, count;
rhughes@241
   455
rhughes@241
   456
	name = razor_rpm_get_indirect(rpm, name_tag, &count);
rhughes@241
   457
	if (name == NULL)
rhughes@241
   458
		return;
rhughes@241
   459
rhughes@241
   460
	flags = razor_rpm_get_indirect(rpm, flags_tag, &count);
rhughes@241
   461
rhughes@241
   462
	version = razor_rpm_get_indirect(rpm, version_tag, &count);
rhughes@241
   463
	for (i = 0; i < count; i++) {
rhughes@241
   464
		f = rpm_to_razor_flags(ntohl(flags[i]));
krh@247
   465
		razor_importer_add_property(importer, name, f | type, version);
rhughes@241
   466
		name += strlen(name) + 1;
rhughes@241
   467
		version += strlen(version) + 1;
rhughes@241
   468
	}
rhughes@241
   469
}
rhughes@241
   470
rhughes@241
   471
static void
rhughes@241
   472
import_files(struct razor_importer *importer, struct razor_rpm *rpm)
rhughes@241
   473
{
rhughes@241
   474
	const char *name;
rhughes@241
   475
	const uint32_t *index;
rhughes@241
   476
	unsigned int i, count;
rhughes@241
   477
	char buffer[256];
rhughes@241
   478
krh@246
   479
	if (rpm->dirs == NULL)
krh@246
   480
		return;
krh@246
   481
rhughes@241
   482
	/* assert: count is the same for all arrays */
rhughes@241
   483
	index = razor_rpm_get_indirect(rpm, RPMTAG_DIRINDEXES, &count);
rhughes@241
   484
	name = razor_rpm_get_indirect(rpm, RPMTAG_BASENAMES, &count);
rhughes@241
   485
	for (i = 0; i < count; i++) {
rhughes@241
   486
		snprintf(buffer, sizeof buffer,
rhughes@241
   487
			 "%s%s", rpm->dirs[ntohl(*index)], name);
rhughes@241
   488
		razor_importer_add_file(importer, buffer);
rhughes@241
   489
		name += strlen(name) + 1;
rhughes@241
   490
		index++;
rhughes@241
   491
	}
rhughes@241
   492
}
rhughes@241
   493
krh@269
   494
RAZOR_EXPORT struct razor_rpm *
rhughes@241
   495
razor_rpm_open(const char *filename)
rhughes@241
   496
{
rhughes@241
   497
	struct razor_rpm *rpm;
rhughes@241
   498
	struct rpm_header_index *base, *index;
rhughes@241
   499
	unsigned int count, i, nindex, hsize;
ali@351
   500
	const char *name, *prefix;
rhughes@241
   501
richard@301
   502
	assert (filename != NULL);
richard@301
   503
rhughes@241
   504
	rpm = malloc(sizeof *rpm);
krh@246
   505
	if (rpm == NULL)
krh@246
   506
		return NULL;
rhughes@241
   507
	memset(rpm, 0, sizeof *rpm);
rhughes@241
   508
ali@322
   509
	rpm->map = razor_file_get_contents(filename, &rpm->size);
ali@322
   510
	if (!rpm->map) {
ali@339
   511
		fprintf(stderr, "couldn't get contents of %s (%s)\n", filename,
ali@339
   512
			strerror(errno));
rhughes@241
   513
		return NULL;
rhughes@241
   514
	}
rhughes@241
   515
rhughes@241
   516
	rpm->signature = rpm->map + RPM_LEAD_SIZE;
rhughes@241
   517
	nindex = ntohl(rpm->signature->nindex);
rhughes@241
   518
	hsize = ntohl(rpm->signature->hsize);
rhughes@241
   519
	rpm->header = (void *) (rpm->signature + 1) +
rhughes@241
   520
		ALIGN(nindex * sizeof *index + hsize, 8);
rhughes@241
   521
	nindex = ntohl(rpm->header->nindex);
rhughes@241
   522
	hsize = ntohl(rpm->header->hsize);
rhughes@241
   523
	rpm->payload = (void *) (rpm->header + 1) +
rhughes@241
   524
		nindex * sizeof *index + hsize;
rhughes@241
   525
rhughes@241
   526
	base = (struct rpm_header_index *) (rpm->header + 1);
rhughes@241
   527
	rpm->pool = (void *) base + nindex * sizeof *index;
rhughes@241
   528
rhughes@241
   529
	/* Look up dir names now so we can index them directly. */
rhughes@241
   530
	name = razor_rpm_get_indirect(rpm, RPMTAG_DIRNAMES, &count);
rhughes@241
   531
	if (name) {
rhughes@241
   532
		rpm->dirs = calloc(count, sizeof *rpm->dirs);
rhughes@241
   533
		for (i = 0; i < count; i++) {
rhughes@241
   534
			rpm->dirs[i] = name;
rhughes@241
   535
			name += strlen(name) + 1;
rhughes@241
   536
		}
rhughes@241
   537
	} else {
rhughes@241
   538
		name = razor_rpm_get_indirect(rpm, RPMTAG_OLDFILENAMES,
rhughes@241
   539
					      &count);
rhughes@241
   540
		if (name) {
rhughes@241
   541
			fprintf(stderr, "old filenames not supported\n");
rhughes@241
   542
			return NULL;
rhughes@241
   543
		}
rhughes@241
   544
	}
rhughes@241
   545
ali@351
   546
	prefix = razor_rpm_get_indirect(rpm, RPMTAG_PREFIXES, &count);
ali@351
   547
	if (prefix) {
ali@351
   548
		rpm->prefixes = calloc(count, sizeof *rpm->prefixes);
ali@351
   549
		for (i = 0; i < count; i++) {
ali@351
   550
			rpm->prefixes[i] = prefix;
ali@351
   551
			prefix += strlen(prefix) + 1;
ali@351
   552
		}
ali@351
   553
		rpm->n_prefixes = count;
ali@351
   554
	} else {
ali@351
   555
		prefix = razor_rpm_get_indirect(rpm, RPMTAG_DEFAULTPREFIX,
ali@351
   556
						&count);
ali@351
   557
		if (prefix) {
ali@351
   558
			fprintf(stderr, "default prefix not supported\n");
ali@351
   559
			return NULL;
ali@351
   560
		}
ali@351
   561
	}
ali@351
   562
rhughes@241
   563
	return rpm;
rhughes@241
   564
}
rhughes@241
   565
ali@351
   566
RAZOR_EXPORT void razor_rpm_set_relocations(struct razor_rpm *rpm,
ali@351
   567
					    struct razor_relocations *rr)
ali@351
   568
{
ali@351
   569
	assert (rpm != NULL);
ali@351
   570
ali@351
   571
	rpm->relocations = rr;
ali@351
   572
}
ali@351
   573
rhughes@241
   574
struct cpio_file_header {
rhughes@241
   575
	char magic[6];
rhughes@241
   576
	char inode[8];
rhughes@241
   577
	char mode[8];
rhughes@241
   578
	char uid[8];
rhughes@241
   579
	char gid[8];
rhughes@241
   580
	char nlink[8];
rhughes@241
   581
	char mtime[8];
rhughes@241
   582
	char filesize[8];
rhughes@241
   583
	char devmajor[8];
rhughes@241
   584
	char devminor[8];
rhughes@241
   585
	char rdevmajor[8];
rhughes@241
   586
	char rdevminor[8];
rhughes@241
   587
	char namesize[8];
rhughes@241
   588
	char checksum[8];
rhughes@241
   589
	char filename[0];
rhughes@241
   590
};
rhughes@241
   591
rhughes@241
   592
/* gzip flags */
rhughes@241
   593
#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
rhughes@241
   594
#define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
rhughes@241
   595
#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
rhughes@241
   596
#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
rhughes@241
   597
#define COMMENT      0x10 /* bit 4 set: file comment present */
rhughes@241
   598
#define RESERVED     0xE0 /* bits 5..7: reserved */
rhughes@241
   599
rhughes@241
   600
struct installer {
rhughes@241
   601
	const char *root;
rhughes@241
   602
	struct razor_rpm *rpm;
rhughes@241
   603
	z_stream stream;
rhughes@241
   604
	unsigned char buffer[32768];
rhughes@241
   605
	size_t rest, length;
rhughes@241
   606
};
rhughes@241
   607
rhughes@241
   608
static int
rhughes@241
   609
installer_inflate(struct installer *installer)
rhughes@241
   610
{
rhughes@241
   611
	size_t length;
rhughes@241
   612
	int err;
rhughes@241
   613
rhughes@241
   614
	if (installer->rest > sizeof installer->buffer)
rhughes@241
   615
		length = sizeof installer->buffer;
rhughes@241
   616
	else
rhughes@241
   617
		length = installer->rest;
rhughes@241
   618
rhughes@241
   619
	installer->stream.next_out = installer->buffer;
rhughes@241
   620
	installer->stream.avail_out = length;
rhughes@241
   621
	err = inflate(&installer->stream, Z_SYNC_FLUSH);
rhughes@241
   622
	if (err != Z_OK && err != Z_STREAM_END) {
ali@339
   623
		fprintf(stderr, "inflate error: %d (%s)\n", err,
ali@339
   624
			strerror(errno));
rhughes@241
   625
		return -1;
rhughes@241
   626
	}
rhughes@241
   627
rhughes@241
   628
	installer->rest -= length;
rhughes@241
   629
	installer->length = length;
rhughes@241
   630
rhughes@241
   631
	return 0;
rhughes@241
   632
}
rhughes@241
   633
rhughes@241
   634
static int
rhughes@241
   635
installer_align(struct installer *installer, size_t size)
rhughes@241
   636
{
rhughes@241
   637
	unsigned char buffer[4];
rhughes@241
   638
	int err;
rhughes@241
   639
rhughes@241
   640
	installer->stream.next_out = buffer;
rhughes@241
   641
	installer->stream.avail_out =
rhughes@241
   642
		(size - installer->stream.total_out) & (size - 1);
rhughes@241
   643
rhughes@241
   644
	if (installer->stream.avail_out == 0)
rhughes@241
   645
		return 0;
rhughes@241
   646
rhughes@241
   647
	err = inflate(&installer->stream, Z_SYNC_FLUSH);
rhughes@241
   648
	if (err != Z_OK && err != Z_STREAM_END) {
ali@339
   649
		fprintf(stderr, "inflate error: %d (%s)\n", err,
ali@339
   650
			strerror(errno));
rhughes@241
   651
		return -1;
rhughes@241
   652
	}
rhughes@241
   653
rhughes@241
   654
	return 0;
rhughes@241
   655
}
rhughes@241
   656
rhughes@241
   657
static int
rhughes@241
   658
create_path(struct installer *installer, const char *path, unsigned int mode)
rhughes@241
   659
{
rhughes@241
   660
	char buffer[PATH_MAX];
rhughes@241
   661
	struct stat buf;
rhughes@241
   662
	int fd, ret;
rhughes@241
   663
rhughes@241
   664
	if (razor_create_dir(installer->root, path) < 0)
rhughes@241
   665
		return -1;
rhughes@241
   666
rhughes@241
   667
	snprintf(buffer, sizeof buffer, "%s%s", installer->root, path);
rhughes@241
   668
rhughes@241
   669
	switch (mode >> 12) {
rhughes@241
   670
	case REG:
rhughes@241
   671
		/* FIXME: handle the case where a file is already there. */
ali@345
   672
		fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
ali@345
   673
			  mode & 0x1ff);
rhughes@241
   674
		if (fd < 0){
rhughes@241
   675
			fprintf(stderr, "failed to create file %s\n", buffer);
rhughes@241
   676
			return -1;
rhughes@241
   677
		}
rhughes@241
   678
		while (installer->rest > 0) {
rhughes@241
   679
			if (installer_inflate(installer)) {
rhughes@241
   680
				fprintf(stderr, "failed to inflate\n");
rhughes@241
   681
				return -1;
rhughes@241
   682
			}
rhughes@241
   683
			if (razor_write(fd, installer->buffer,
rhughes@241
   684
					installer->length)) {
rhughes@241
   685
				fprintf(stderr, "failed to write payload\n");
rhughes@241
   686
				return -1;
rhughes@241
   687
			}
rhughes@241
   688
		}
rhughes@241
   689
		if (close(fd) < 0) {
ali@339
   690
			fprintf(stderr, "failed to close %s: %s\n", buffer,
ali@339
   691
				strerror(errno));
rhughes@241
   692
			return -1;
rhughes@241
   693
		}
rhughes@241
   694
		return 0;
rhughes@241
   695
	case XDIR:
rhughes@241
   696
		ret = mkdir(buffer, mode & 0x1ff);
rhughes@241
   697
		if (ret == 0 || errno != EEXIST)
rhughes@241
   698
			return ret;
rhughes@241
   699
		if (stat(buffer, &buf) || !S_ISDIR(buf.st_mode)) {
rhughes@241
   700
			/* FIXME: also check that mode match. */
rhughes@241
   701
			fprintf(stderr,
rhughes@241
   702
				"%s exists but is not a directory\n", buffer);
rhughes@241
   703
			return -1;
rhughes@241
   704
		}
rhughes@241
   705
		return 0;
rhughes@241
   706
	case LINK:
ali@327
   707
#if HAVE_SYMLINK
rhughes@241
   708
		if (installer_inflate(installer)) {
rhughes@241
   709
			fprintf(stderr, "failed to inflate\n");
rhughes@241
   710
			return -1;
rhughes@241
   711
		}
rhughes@241
   712
		if (installer->length >= sizeof installer->buffer) {
rhughes@241
   713
			fprintf(stderr, "link name too long\n");
rhughes@241
   714
			return -1;
rhughes@241
   715
		}
rhughes@241
   716
		installer->buffer[installer->length] = '\0';
rhughes@241
   717
		if (symlink((const char *) installer->buffer, buffer)) {
ali@339
   718
			perror("failed to create symlink");
rhughes@241
   719
			return -1;
rhughes@241
   720
		}
rhughes@241
   721
		return 0;
ali@327
   722
#else
ali@327
   723
		/* fall through */
ali@327
   724
#endif
ali@327
   725
	case PIPE:
ali@327
   726
	case CDEV:
ali@327
   727
	case BDEV:
ali@327
   728
	case SOCK:
ali@327
   729
		printf("%s: unhandled file type %d\n", buffer, mode >> 12);
ali@327
   730
		return 0;
rhughes@241
   731
	default:
rhughes@241
   732
		printf("%s: unknown file type %d\n", buffer, mode >> 12);
rhughes@241
   733
		return 0;
rhughes@241
   734
	}
rhughes@241
   735
}
rhughes@241
   736
ali@353
   737
static int chroot_push(const char *root)
ali@353
   738
{
ali@353
   739
	int fd;
ali@353
   740
#if HAVE_CHROOT
ali@353
   741
	if (geteuid() == 0) {
ali@353
   742
		fd = open("/", O_RDONLY, 0);
ali@353
   743
		if (chroot(root) < 0) {
ali@353
   744
			fprintf(stderr, "failed to chroot to %s: %s\n",
ali@353
   745
				root, strerror(errno));
ali@353
   746
			exit(-1);
ali@353
   747
		}
ali@353
   748
	} else
ali@353
   749
#endif
ali@353
   750
		fd = -1;
ali@353
   751
	return fd;
ali@353
   752
}
ali@353
   753
ali@353
   754
static void chroot_pop(int fd)
rhughes@241
   755
{
ali@328
   756
#if HAVE_CHROOT
ali@353
   757
	if (fd >= 0) {
ali@353
   758
		fchdir(fd);
ali@353
   759
		close(fd);
ali@353
   760
		chroot(".");
ali@353
   761
	}
ali@353
   762
#endif
ali@353
   763
}
ali@353
   764
ali@353
   765
static int
ali@353
   766
run_script_lua(const char *root, unsigned int script_tag, const char *script)
ali@353
   767
{
ali@353
   768
	int root_fd, retval;
ali@352
   769
#if HAVE_LUA
ali@353
   770
	const char *name;
ali@353
   771
ali@353
   772
	switch(script_tag) {
ali@353
   773
		case RPMTAG_PREIN:
ali@353
   774
			name = "%pre";
ali@353
   775
			break;
ali@353
   776
		case RPMTAG_POSTIN:
ali@353
   777
			name = "%post";
ali@353
   778
			break;
ali@353
   779
		case RPMTAG_PREUN:
ali@353
   780
			name = "%preun";
ali@353
   781
			break;
ali@353
   782
		case RPMTAG_POSTUN:
ali@353
   783
			name = "%postun";
ali@353
   784
			break;
ali@353
   785
		default:
ali@353
   786
			name = "script";
ali@353
   787
			break;
ali@353
   788
	}
ali@353
   789
	root_fd = chroot_push(root);
ali@353
   790
	retval = run_lua_script(root_fd < 0 ? root : NULL, name, script, -1);
ali@353
   791
	chroot_pop(root_fd);
ali@353
   792
#else	/* HAVE_LUA */
ali@353
   793
	fprintf(stderr, "lua not available to run script\n");
ali@353
   794
	retval = -1;
ali@353
   795
#endif	/* HAVE_LUA */
ali@353
   796
ali@353
   797
	return retval;
ali@353
   798
}
ali@353
   799
ali@353
   800
static int
ali@353
   801
run_script_external(const char *root, const char *program, const char *script)
ali@353
   802
{
ali@353
   803
	int root_fd, retval;
ali@328
   804
	FILE *fp;
rhughes@241
   805
ali@353
   806
	if (program == NULL) {
ali@328
   807
#if MSWIN_API
ali@328
   808
		program = getenv("COMSPEC");
ali@328
   809
		if (program) {
ali@328
   810
			program = strchr(program, '=');
ali@328
   811
			if (program)
ali@328
   812
				program++;
ali@328
   813
		}
ali@328
   814
		if (!program)
ali@328
   815
			program = "c:\\windows\\system32\\cmd.exe";
ali@328
   816
#else
rhughes@241
   817
		program = "/bin/sh";
ali@328
   818
#endif
rhughes@241
   819
	}
rhughes@241
   820
ali@353
   821
	root_fd = chroot_push(root);
ali@328
   822
	fp = popen(program, "w");
rhughes@241
   823
ali@353
   824
	if (!fp) {
ali@353
   825
		perror(program);
ali@353
   826
		retval = -1;
ali@353
   827
	} else if (fwrite(script, strlen(script), 1, fp) != 1) {
ali@353
   828
		perror("failed to write script to program");
ali@353
   829
		retval = -1;
ali@353
   830
	} else
ali@353
   831
		retval = 0;
ali@353
   832
ali@353
   833
	if (fp)
ali@353
   834
		pclose(fp);
ali@353
   835
	chroot_pop(root_fd);
ali@353
   836
ali@353
   837
	return retval;
ali@353
   838
}
ali@353
   839
ali@353
   840
static int
ali@353
   841
run_script(struct installer *installer,
ali@353
   842
	   unsigned int program_tag, unsigned int script_tag)
ali@353
   843
{
ali@353
   844
	int retval;
ali@353
   845
	const char *script = NULL, *program = NULL;
ali@353
   846
ali@353
   847
	program = razor_rpm_get_indirect(installer->rpm, program_tag, NULL);
ali@353
   848
	script = razor_rpm_get_indirect(installer->rpm, script_tag, NULL);
ali@353
   849
	if (program == NULL && script == NULL)
ali@353
   850
		retval = 0;
ali@353
   851
	else if (strcmp(program, "<lua>") == 0)
ali@353
   852
		retval = run_script_lua(installer->root, script_tag, script);
ali@353
   853
	else
ali@353
   854
		retval = run_script_external(installer->root, program, script);
ali@353
   855
ali@353
   856
	return retval;
rhughes@241
   857
}
rhughes@241
   858
rhughes@241
   859
static int
rhughes@241
   860
installer_init(struct installer *installer)
rhughes@241
   861
{
rhughes@241
   862
	unsigned char *gz_header;
rhughes@241
   863
	int method, flags, err;
rhughes@241
   864
rhughes@241
   865
	gz_header = installer->rpm->payload;
rhughes@241
   866
	if (gz_header[0] != 0x1f || gz_header[1] != 0x8b) {
rhughes@241
   867
		fprintf(stderr, "payload section doesn't have gz header\n");
rhughes@241
   868
		return -1;
rhughes@241
   869
	}
rhughes@241
   870
rhughes@241
   871
	method = gz_header[2];
rhughes@241
   872
	flags = gz_header[3];
rhughes@241
   873
rhughes@241
   874
	if (method != Z_DEFLATED || flags != 0) {
rhughes@241
   875
		fprintf(stderr,
rhughes@241
   876
			"unknown payload compression method or flags set\n");
rhughes@241
   877
		return -1;
rhughes@241
   878
	}
rhughes@241
   879
rhughes@241
   880
	installer->stream.zalloc = NULL;
rhughes@241
   881
	installer->stream.zfree = NULL;
rhughes@241
   882
	installer->stream.opaque = NULL;
rhughes@241
   883
rhughes@241
   884
	installer->stream.next_in  = gz_header + 10;
rhughes@241
   885
	installer->stream.avail_in =
rhughes@241
   886
		(installer->rpm->map + installer->rpm->size) -
rhughes@241
   887
		(void *) installer->stream.next_in;
rhughes@241
   888
	installer->stream.next_out = NULL;
rhughes@241
   889
	installer->stream.avail_out = 0;
rhughes@241
   890
rhughes@241
   891
	err = inflateInit2(&installer->stream, -MAX_WBITS);
rhughes@241
   892
	if (err != Z_OK) {
rhughes@241
   893
		fprintf(stderr, "inflateInit error: %d\n", err);
rhughes@241
   894
		return -1;
rhughes@241
   895
	}
rhughes@241
   896
rhughes@241
   897
	return 0;
rhughes@241
   898
}
rhughes@241
   899
rhughes@241
   900
static int
rhughes@241
   901
installer_finish(struct installer *installer)
rhughes@241
   902
{
rhughes@241
   903
	int err;
rhughes@241
   904
rhughes@241
   905
	err = inflateEnd(&installer->stream);
rhughes@241
   906
rhughes@241
   907
	if (err != Z_OK) {
rhughes@241
   908
		fprintf(stderr, "inflateEnd error: %d\n", err);
rhughes@241
   909
		return -1;
rhughes@241
   910
	}
rhughes@241
   911
rhughes@241
   912
	return 0;
rhughes@241
   913
}
rhughes@241
   914
rhughes@241
   915
static unsigned long
rhughes@241
   916
fixed_hex_to_ulong(const char *hex, int length)
rhughes@241
   917
{
rhughes@241
   918
	long l;
rhughes@241
   919
	int i;
rhughes@241
   920
rhughes@241
   921
	for (i = 0, l = 0; i < length; i++) {
rhughes@241
   922
		if (hex[i] < 'a')
rhughes@241
   923
			l = l * 16 + hex[i] - '0';
rhughes@241
   924
		else
rhughes@241
   925
			l = l * 16 + hex[i] - 'a' + 10;
rhughes@241
   926
	}
rhughes@241
   927
rhughes@241
   928
	return l;
rhughes@241
   929
}
rhughes@241
   930
krh@269
   931
RAZOR_EXPORT int
rhughes@241
   932
razor_rpm_install(struct razor_rpm *rpm, const char *root)
rhughes@241
   933
{
rhughes@241
   934
	struct installer installer;
rhughes@241
   935
	struct cpio_file_header *header;
rhughes@241
   936
	struct stat buf;
rhughes@241
   937
	unsigned int mode;
ali@351
   938
	const char *path;
rhughes@241
   939
	size_t filesize;
rhughes@241
   940
richard@301
   941
	assert (rpm != NULL);
richard@301
   942
	assert (root != NULL);
richard@301
   943
rhughes@241
   944
	installer.rpm = rpm;
rhughes@241
   945
	installer.root = root;
rhughes@241
   946
rhughes@241
   947
	/* FIXME: Only do this before a transaction, not per rpm. */
ali@347
   948
	if (*root && (stat(root, &buf) < 0 || !S_ISDIR(buf.st_mode))) {
rhughes@241
   949
		fprintf(stderr,
rhughes@241
   950
			"root installation directory \"%s\" does not exist\n",
rhughes@241
   951
			root);
rhughes@241
   952
		return -1;
rhughes@241
   953
	}
rhughes@241
   954
ali@351
   955
	if (rpm->relocations)
ali@351
   956
		razor_relocations_set_rpm(rpm->relocations, rpm);
ali@351
   957
rhughes@241
   958
	if (installer_init(&installer))
rhughes@241
   959
		return -1;
rhughes@241
   960
rhughes@241
   961
	run_script(&installer, RPMTAG_PREINPROG, RPMTAG_PREIN);
rhughes@241
   962
rhughes@241
   963
	while (installer.stream.avail_in > 0) {
rhughes@241
   964
		installer.rest = sizeof *header;
rhughes@241
   965
		if (installer_inflate(&installer))
rhughes@241
   966
			return -1;
rhughes@241
   967
rhughes@241
   968
		header = (struct cpio_file_header *) installer.buffer;
rhughes@241
   969
		mode = fixed_hex_to_ulong(header->mode, sizeof header->mode);
rhughes@241
   970
		filesize = fixed_hex_to_ulong(header->filesize,
rhughes@241
   971
					      sizeof header->filesize);
rhughes@241
   972
rhughes@241
   973
		installer.rest = fixed_hex_to_ulong(header->namesize,
rhughes@241
   974
						    sizeof header->namesize);
rhughes@241
   975
rhughes@241
   976
		if (installer_inflate(&installer) ||
rhughes@241
   977
		    installer_align(&installer, 4))
rhughes@241
   978
			return -1;
rhughes@241
   979
ali@351
   980
		path = (const char *) installer.buffer;
rhughes@241
   981
		/* This convention is so lame... */
rhughes@241
   982
		if (strcmp(path, "TRAILER!!!") == 0)
rhughes@241
   983
			break;
rhughes@241
   984
rhughes@241
   985
		installer.rest = filesize;
ali@351
   986
		path++;
ali@351
   987
		if (rpm->relocations)
ali@351
   988
			path = razor_relocations_apply(rpm->relocations, path);
ali@351
   989
		if (create_path(&installer, path, mode) < 0)
rhughes@241
   990
			return -1;
rhughes@241
   991
		if (installer_align(&installer, 4))
rhughes@241
   992
			return -1;
rhughes@241
   993
	}
rhughes@241
   994
rhughes@241
   995
	if (installer_finish(&installer))
rhughes@241
   996
		return -1;
rhughes@241
   997
rhughes@241
   998
	run_script(&installer, RPMTAG_POSTINPROG, RPMTAG_POSTIN);
rhughes@241
   999
rhughes@241
  1000
	return 0;
rhughes@241
  1001
}
rhughes@241
  1002
krh@269
  1003
RAZOR_EXPORT int
rhughes@241
  1004
razor_rpm_close(struct razor_rpm *rpm)
rhughes@241
  1005
{
rhughes@241
  1006
	int err;
rhughes@241
  1007
richard@301
  1008
	assert (rpm != NULL);
richard@301
  1009
rhughes@241
  1010
	free(rpm->dirs);
ali@351
  1011
	free(rpm->prefixes);
ali@322
  1012
	err = razor_file_free_contents(rpm->map, rpm->size);
rhughes@241
  1013
	free(rpm);
rhughes@241
  1014
rhughes@241
  1015
	return err;
rhughes@241
  1016
}
rhughes@241
  1017
krh@269
  1018
RAZOR_EXPORT int
rhughes@241
  1019
razor_importer_add_rpm(struct razor_importer *importer, struct razor_rpm *rpm)
rhughes@241
  1020
{
jbowes@289
  1021
	const char *name, *version, *release, *arch;
jbowes@289
  1022
	const char *summary, *description, *url, *license;
rhughes@241
  1023
	const uint32_t *epoch;
rhughes@241
  1024
	char evr[128], buf[16];
rhughes@241
  1025
richard@301
  1026
	assert (importer != NULL);
richard@301
  1027
	assert (rpm != NULL);
richard@301
  1028
rhughes@241
  1029
	name = razor_rpm_get_indirect(rpm, RPMTAG_NAME, NULL);
rhughes@241
  1030
	epoch = razor_rpm_get_indirect(rpm, RPMTAG_EPOCH, NULL);
rhughes@241
  1031
	version = razor_rpm_get_indirect(rpm, RPMTAG_VERSION, NULL);
rhughes@241
  1032
	release = razor_rpm_get_indirect(rpm, RPMTAG_RELEASE, NULL);
rhughes@241
  1033
	arch = razor_rpm_get_indirect(rpm, RPMTAG_ARCH, NULL);
jbowes@289
  1034
jbowes@258
  1035
	summary = razor_rpm_get_indirect(rpm, RPMTAG_SUMMARY, NULL);
jbowes@289
  1036
	description = razor_rpm_get_indirect(rpm, RPMTAG_DESCRIPTION, NULL);
jbowes@289
  1037
	url = razor_rpm_get_indirect(rpm, RPMTAG_URL, NULL);
jbowes@289
  1038
	license = razor_rpm_get_indirect(rpm, RPMTAG_LICENSE, NULL);
rhughes@241
  1039
rhughes@241
  1040
	if (epoch) {
ali@329
  1041
		snprintf(buf, sizeof buf, "%lu", ntohl(*epoch));
rhughes@241
  1042
		razor_build_evr(evr, sizeof evr, buf, version, release);
rhughes@241
  1043
	} else {
rhughes@241
  1044
		razor_build_evr(evr, sizeof evr, NULL, version, release);
rhughes@241
  1045
	}
rhughes@241
  1046
	razor_importer_begin_package(importer, name, evr, arch);
rhughes@241
  1047
jbowes@289
  1048
	razor_importer_add_details(importer, summary, description, url,
jbowes@289
  1049
				   license);
jbowes@289
  1050
rhughes@241
  1051
	import_properties(importer, RAZOR_PROPERTY_REQUIRES, rpm,
rhughes@241
  1052
			  RPMTAG_REQUIRENAME,
rhughes@241
  1053
			  RPMTAG_REQUIREVERSION,
rhughes@241
  1054
			  RPMTAG_REQUIREFLAGS);
rhughes@241
  1055
rhughes@241
  1056
	import_properties(importer, RAZOR_PROPERTY_PROVIDES, rpm,
rhughes@241
  1057
			  RPMTAG_PROVIDENAME,
rhughes@241
  1058
			  RPMTAG_PROVIDEVERSION,
rhughes@241
  1059
			  RPMTAG_PROVIDEFLAGS);
rhughes@241
  1060
rhughes@241
  1061
	import_properties(importer, RAZOR_PROPERTY_OBSOLETES, rpm,
rhughes@241
  1062
			  RPMTAG_OBSOLETENAME,
rhughes@241
  1063
			  RPMTAG_OBSOLETEVERSION,
rhughes@241
  1064
			  RPMTAG_OBSOLETEFLAGS);
rhughes@241
  1065
rhughes@241
  1066
	import_properties(importer, RAZOR_PROPERTY_CONFLICTS, rpm,
rhughes@241
  1067
			  RPMTAG_CONFLICTNAME,
rhughes@241
  1068
			  RPMTAG_CONFLICTVERSION,
rhughes@241
  1069
			  RPMTAG_CONFLICTFLAGS);
rhughes@241
  1070
rhughes@241
  1071
	import_files(importer, rpm);
rhughes@241
  1072
rhughes@241
  1073
	razor_importer_finish_package(importer);
rhughes@241
  1074
rhughes@241
  1075
	return 0;
rhughes@241
  1076
}