librazor/rpm.c
author J. Ali Harlow <ali@juiblex.co.uk>
Sat Aug 23 11:13:48 2014 +0100 (2014-08-23)
changeset 440 48204dea0b9f
parent 424 8cbc438cc298
child 442 c4bcba8023a9
permissions -rw-r--r--
Remove INTLLIBS from librazor_la_LIBADD.

This partially reverts 611c84a3f4b4538a65d186050608c17adbf17770.
It's not clear what motivated the initial inclusion of INTLLIBS
here since the net effect is only seen in librazor.la and not
in razor.pc and librazor.la is not normally packaged. Certainly
neither the static nor the dynamic versions of librazor currently
use libintl. At best this would cause the linker to search a
static libintl for undefined symbols without finding any; at worse
it causes a static build of plover using librazor.la to fail if
no static version of libintl is installed.
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@422
     4
 * Copyright (C) 2009, 2011, 2012  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;
ali@369
   259
	char *evr;
rhughes@241
   260
};
rhughes@241
   261
ali@351
   262
enum razor_relocation_flags {
ali@351
   263
	RAZOR_RELOCATION_ACTIVE		= 1 << 0,
ali@351
   264
};
ali@351
   265
ali@351
   266
struct razor_relocation {
ali@351
   267
	enum razor_relocation_flags flags;
ali@351
   268
	size_t oldlen;
ali@351
   269
	size_t newlen;
ali@351
   270
	char *oldpath;
ali@351
   271
	char *newpath;
ali@351
   272
};
ali@351
   273
ali@351
   274
struct razor_relocations {
ali@351
   275
	/* Ordered such that if oldpath 1 starts with oldpath 2, then
ali@351
   276
	 * oldpath 1 is listed first (ie., /usr/bin comes before /usr)
ali@351
   277
	 * and terminated with a NULL oldpath.
ali@351
   278
	 */
ali@351
   279
	struct razor_relocation *relocations;
ali@351
   280
	int n_relocations;
ali@351
   281
	char *path;
ali@351
   282
};
ali@351
   283
ali@351
   284
RAZOR_EXPORT struct razor_relocations *razor_relocations_create(void)
ali@351
   285
{
ali@351
   286
	return calloc(1, sizeof(struct razor_relocations));
ali@351
   287
}
ali@351
   288
ali@351
   289
RAZOR_EXPORT void razor_relocations_add(struct razor_relocations *rr,
ali@351
   290
			   const char *oldpath, const char *newpath)
ali@351
   291
{
ali@351
   292
	int i, found = 0;
ali@351
   293
	size_t len;
ali@351
   294
ali@351
   295
	if (newpath && !strcmp(oldpath, newpath))
ali@351
   296
		newpath = NULL;
ali@351
   297
ali@351
   298
	for (i = 0; i < rr->n_relocations; i++) {
ali@351
   299
		len = rr->relocations[i].oldlen;
ali@351
   300
		if (!strncmp(rr->relocations[i].oldpath, oldpath, len)) {
ali@351
   301
			found = !strcmp(rr->relocations[i].oldpath, oldpath);
ali@351
   302
			break;
ali@351
   303
		}
ali@351
   304
	}
ali@351
   305
ali@351
   306
	if (!newpath) {
ali@351
   307
		if (found) {
ali@351
   308
			free(rr->relocations[i].oldpath);
ali@351
   309
			free(rr->relocations[i].newpath);
ali@351
   310
			do {
ali@351
   311
				rr->relocations[i] = rr->relocations[i + 1];
ali@351
   312
			} while (rr->relocations[++i].oldpath);
ali@351
   313
		}
ali@351
   314
		return;
ali@351
   315
	}
ali@351
   316
ali@351
   317
	if (found) {
ali@351
   318
		free(rr->relocations[i].newpath);
ali@351
   319
		rr->relocations[i].newpath = strdup(newpath);
ali@351
   320
		rr->relocations[i].newlen = strlen(newpath);
ali@351
   321
		return;
ali@351
   322
	}
ali@351
   323
ali@351
   324
	if (!rr->n_relocations++)
ali@351
   325
		rr->relocations = calloc(1, sizeof *rr->relocations);
ali@351
   326
	else {
ali@351
   327
		rr->relocations = realloc(rr->relocations,
ali@351
   328
					  rr->n_relocations * sizeof *rr->relocations);
ali@351
   329
		memmove(rr->relocations + i + 1, rr->relocations + i,
ali@351
   330
			(rr->n_relocations - i - 1) * sizeof *rr->relocations);
ali@351
   331
	}
ali@351
   332
ali@351
   333
	rr->relocations[i].flags = 0;
ali@351
   334
	rr->relocations[i].oldpath = strdup(oldpath);
ali@351
   335
	rr->relocations[i].newpath = strdup(newpath);
ali@351
   336
	rr->relocations[i].oldlen = strlen(oldpath);
ali@351
   337
	rr->relocations[i].newlen = strlen(newpath);
ali@351
   338
}
ali@351
   339
ali@351
   340
RAZOR_EXPORT void
ali@351
   341
razor_relocations_set_rpm(struct razor_relocations *rr, struct razor_rpm *rpm)
ali@351
   342
{
ali@351
   343
	int i, j;
ali@351
   344
ali@351
   345
	for (i = 0; i < rr->n_relocations; i++) {
ali@351
   346
		rr->relocations[i].flags &= ~RAZOR_RELOCATION_ACTIVE;
ali@351
   347
		for (j = 0; j < rpm->n_prefixes; j++)
ali@351
   348
			if (!strcmp(rpm->prefixes[j],
ali@351
   349
				    rr->relocations[i].oldpath)) {
ali@351
   350
				rr->relocations[i].flags |= RAZOR_RELOCATION_ACTIVE;
ali@351
   351
				break;
ali@351
   352
			}
ali@351
   353
	}
ali@351
   354
}
ali@351
   355
ali@351
   356
RAZOR_EXPORT const char *
ali@351
   357
razor_relocations_apply(struct razor_relocations *rr, const char *path)
ali@351
   358
{
ali@351
   359
	int i;
ali@351
   360
	size_t len;
ali@351
   361
ali@351
   362
	for (i = 0; i < rr->n_relocations; i++)
ali@351
   363
		if (rr->relocations[i].flags & RAZOR_RELOCATION_ACTIVE &&
ali@351
   364
		    !strncmp(path, rr->relocations[i].oldpath,
ali@351
   365
			     rr->relocations[i].oldlen))
ali@351
   366
			break;
ali@351
   367
ali@351
   368
	if (i < rr->n_relocations) {
ali@351
   369
		free(rr->path);
ali@351
   370
		len = strlen(path + rr->relocations[i].oldlen) +
ali@351
   371
		      rr->relocations[i].newlen;
ali@351
   372
		rr->path = malloc(len + 1);
ali@351
   373
		memcpy(rr->path, rr->relocations[i].newpath,
ali@351
   374
		       rr->relocations[i].newlen);
ali@351
   375
		strcpy(rr->path + rr->relocations[i].newlen,
ali@351
   376
		       path + rr->relocations[i].oldlen);
ali@351
   377
		return rr->path;
ali@351
   378
	} else
ali@351
   379
		return path;
ali@351
   380
}
ali@351
   381
ali@351
   382
RAZOR_EXPORT void razor_relocations_destroy(struct razor_relocations *rr)
ali@351
   383
{
ali@351
   384
	free(rr->path);
ali@351
   385
	free(rr->relocations);
ali@351
   386
	free(rr);
ali@351
   387
}
ali@351
   388
rhughes@241
   389
static struct rpm_header_index *
rhughes@241
   390
razor_rpm_get_header(struct razor_rpm *rpm, unsigned int tag)
rhughes@241
   391
{
rhughes@241
   392
	struct rpm_header_index *index, *end;
rhughes@241
   393
rhughes@241
   394
	index = (struct rpm_header_index *) (rpm->header + 1);
rhughes@241
   395
	end = index + ntohl(rpm->header->nindex);
rhughes@241
   396
	while (index < end) {
rhughes@241
   397
		if (ntohl(index->tag) == tag)
rhughes@241
   398
			return index;
rhughes@241
   399
		index++;
rhughes@241
   400
	}
rhughes@241
   401
rhughes@241
   402
	return NULL;
rhughes@241
   403
}
rhughes@241
   404
rhughes@241
   405
static const void *
rhughes@241
   406
razor_rpm_get_indirect(struct razor_rpm *rpm,
rhughes@241
   407
		       unsigned int tag, unsigned int *count)
rhughes@241
   408
{
rhughes@241
   409
	struct rpm_header_index *index;
rhughes@241
   410
rhughes@241
   411
	index = razor_rpm_get_header(rpm, tag);
rhughes@241
   412
	if (index != NULL) {
rhughes@241
   413
		if (count)
rhughes@241
   414
			*count = ntohl(index->count);
rhughes@241
   415
rhughes@241
   416
		return rpm->pool + ntohl(index->offset);
rhughes@241
   417
	}
rhughes@241
   418
rhughes@241
   419
	return NULL;
rhughes@241
   420
}
rhughes@241
   421
krh@247
   422
static uint32_t
rhughes@241
   423
rpm_to_razor_flags(uint32_t flags)
rhughes@241
   424
{
krh@247
   425
	uint32_t razor_flags;
rhughes@241
   426
krh@247
   427
	razor_flags = 0;
krh@247
   428
	if (flags & RPMSENSE_LESS)
krh@247
   429
		razor_flags |= RAZOR_PROPERTY_LESS;
krh@247
   430
	if (flags & RPMSENSE_EQUAL)
krh@247
   431
		razor_flags |= RAZOR_PROPERTY_EQUAL;
krh@247
   432
	if (flags & RPMSENSE_GREATER)
krh@247
   433
		razor_flags |= RAZOR_PROPERTY_GREATER;
krh@247
   434
krh@247
   435
	if (flags & RPMSENSE_SCRIPT_PRE)
krh@247
   436
		razor_flags |= RAZOR_PROPERTY_PRE;
krh@247
   437
	if (flags & RPMSENSE_SCRIPT_POST)
krh@247
   438
		razor_flags |= RAZOR_PROPERTY_POST;
krh@247
   439
	if (flags & RPMSENSE_SCRIPT_PREUN)
krh@247
   440
		razor_flags |= RAZOR_PROPERTY_PREUN;
krh@247
   441
	if (flags & RPMSENSE_SCRIPT_POSTUN)
krh@247
   442
		razor_flags |= RAZOR_PROPERTY_POSTUN;
krh@247
   443
	
krh@247
   444
	return razor_flags;
rhughes@241
   445
}
rhughes@241
   446
rhughes@241
   447
static void
krh@247
   448
import_properties(struct razor_importer *importer, uint32_t type,
rhughes@241
   449
		  struct razor_rpm *rpm,
rhughes@241
   450
		  int name_tag, int version_tag, int flags_tag)
rhughes@241
   451
{
rhughes@241
   452
	const char *name, *version;
rhughes@241
   453
	const uint32_t *flags;
rhughes@241
   454
	uint32_t f;
rhughes@241
   455
	unsigned int i, count;
rhughes@241
   456
rhughes@241
   457
	name = razor_rpm_get_indirect(rpm, name_tag, &count);
rhughes@241
   458
	if (name == NULL)
rhughes@241
   459
		return;
rhughes@241
   460
rhughes@241
   461
	flags = razor_rpm_get_indirect(rpm, flags_tag, &count);
rhughes@241
   462
rhughes@241
   463
	version = razor_rpm_get_indirect(rpm, version_tag, &count);
rhughes@241
   464
	for (i = 0; i < count; i++) {
rhughes@241
   465
		f = rpm_to_razor_flags(ntohl(flags[i]));
krh@247
   466
		razor_importer_add_property(importer, name, f | type, version);
rhughes@241
   467
		name += strlen(name) + 1;
rhughes@241
   468
		version += strlen(version) + 1;
rhughes@241
   469
	}
rhughes@241
   470
}
rhughes@241
   471
rhughes@241
   472
static void
rhughes@241
   473
import_files(struct razor_importer *importer, struct razor_rpm *rpm)
rhughes@241
   474
{
rhughes@241
   475
	const char *name;
rhughes@241
   476
	const uint32_t *index;
rhughes@241
   477
	unsigned int i, count;
rhughes@241
   478
	char buffer[256];
rhughes@241
   479
krh@246
   480
	if (rpm->dirs == NULL)
krh@246
   481
		return;
krh@246
   482
rhughes@241
   483
	/* assert: count is the same for all arrays */
rhughes@241
   484
	index = razor_rpm_get_indirect(rpm, RPMTAG_DIRINDEXES, &count);
rhughes@241
   485
	name = razor_rpm_get_indirect(rpm, RPMTAG_BASENAMES, &count);
rhughes@241
   486
	for (i = 0; i < count; i++) {
rhughes@241
   487
		snprintf(buffer, sizeof buffer,
rhughes@241
   488
			 "%s%s", rpm->dirs[ntohl(*index)], name);
rhughes@241
   489
		razor_importer_add_file(importer, buffer);
rhughes@241
   490
		name += strlen(name) + 1;
rhughes@241
   491
		index++;
rhughes@241
   492
	}
rhughes@241
   493
}
rhughes@241
   494
ali@369
   495
static void
ali@369
   496
razor_rpm_build_evr(struct razor_rpm *rpm)
ali@369
   497
{
ali@369
   498
	const char *version, *release;
ali@369
   499
	const uint32_t *epoch;
ali@369
   500
	char evr[128], buf[16];
ali@369
   501
ali@369
   502
	epoch = razor_rpm_get_indirect(rpm, RPMTAG_EPOCH, NULL);
ali@369
   503
	version = razor_rpm_get_indirect(rpm, RPMTAG_VERSION, NULL);
ali@369
   504
	release = razor_rpm_get_indirect(rpm, RPMTAG_RELEASE, NULL);
ali@369
   505
	if (epoch)
ali@369
   506
		snprintf(buf, sizeof buf, "%lu", (unsigned long)ntohl(*epoch));
ali@369
   507
	razor_build_evr(evr, sizeof evr, epoch ? buf : NULL, version, release);
ali@369
   508
	rpm->evr = strdup(evr);
ali@369
   509
}
ali@369
   510
ali@369
   511
static const char *
ali@372
   512
razor_rpm_get_details_string(struct razor_rpm *rpm, enum razor_detail_type type)
ali@369
   513
{
ali@369
   514
	switch(type) {
ali@369
   515
	case RAZOR_DETAIL_NAME:
ali@369
   516
		return razor_rpm_get_indirect(rpm, RPMTAG_NAME, NULL);
ali@369
   517
ali@369
   518
	case RAZOR_DETAIL_VERSION:
ali@369
   519
		if (!rpm->evr)
ali@369
   520
			razor_rpm_build_evr(rpm);
ali@369
   521
		return rpm->evr;
ali@369
   522
ali@369
   523
	case RAZOR_DETAIL_ARCH:
ali@369
   524
		return razor_rpm_get_indirect(rpm, RPMTAG_ARCH, NULL);
ali@369
   525
ali@369
   526
	case RAZOR_DETAIL_SUMMARY:
ali@369
   527
		return razor_rpm_get_indirect(rpm, RPMTAG_SUMMARY, NULL);
ali@369
   528
ali@369
   529
	case RAZOR_DETAIL_DESCRIPTION:
ali@369
   530
		return razor_rpm_get_indirect(rpm, RPMTAG_DESCRIPTION, NULL);
ali@369
   531
ali@369
   532
	case RAZOR_DETAIL_URL:
ali@369
   533
		return razor_rpm_get_indirect(rpm, RPMTAG_URL, NULL);
ali@369
   534
ali@369
   535
	case RAZOR_DETAIL_LICENSE:
ali@369
   536
		return razor_rpm_get_indirect(rpm, RPMTAG_LICENSE, NULL);
ali@369
   537
ali@369
   538
	case RAZOR_DETAIL_PREUNPROG:
ali@369
   539
		return razor_rpm_get_indirect(rpm, RPMTAG_PREUNPROG, NULL);
ali@369
   540
ali@369
   541
	case RAZOR_DETAIL_PREUN:
ali@369
   542
		return razor_rpm_get_indirect(rpm, RPMTAG_PREUN, NULL);
ali@369
   543
ali@369
   544
	case RAZOR_DETAIL_POSTUNPROG:
ali@369
   545
		return razor_rpm_get_indirect(rpm, RPMTAG_POSTUNPROG, NULL);
ali@369
   546
ali@369
   547
	case RAZOR_DETAIL_POSTUN:
ali@369
   548
		return razor_rpm_get_indirect(rpm, RPMTAG_POSTUN, NULL);
ali@369
   549
ali@369
   550
	default:
ali@369
   551
		fprintf(stderr, "type %u not found\n", type);
ali@369
   552
		return NULL;
ali@369
   553
	}
ali@369
   554
}
ali@369
   555
ali@372
   556
static const char *const *
ali@372
   557
razor_rpm_get_details_array(struct razor_rpm *rpm, enum razor_detail_type type)
ali@372
   558
{
ali@372
   559
	switch(type) {
ali@372
   560
	case RAZOR_DETAIL_PREFIXES:
ali@372
   561
		return rpm->prefixes;
ali@372
   562
ali@372
   563
	default:
ali@372
   564
		/* Impossible */
ali@372
   565
		fprintf(stderr, "type %u not found\n", type);
ali@372
   566
		return NULL;
ali@372
   567
	}
ali@372
   568
}
ali@372
   569
ali@369
   570
void
ali@369
   571
razor_rpm_get_details_varg(struct razor_rpm *rpm, va_list args)
ali@369
   572
{
ali@369
   573
	int i;
ali@369
   574
	enum razor_detail_type type;
ali@372
   575
	const char **string;
ali@372
   576
	const char *const **array;
ali@369
   577
ali@369
   578
	for (i = 0;; i += 2) {
ali@369
   579
		type = va_arg(args, enum razor_detail_type);
ali@369
   580
		if (type == RAZOR_DETAIL_LAST)
ali@369
   581
			break;
ali@372
   582
		if (type == RAZOR_DETAIL_PREFIXES) {
ali@372
   583
			array = va_arg(args, const char *const **);
ali@372
   584
			*array = razor_rpm_get_details_array(rpm, type);
ali@372
   585
		} else {
ali@372
   586
			string = va_arg(args, const char **);
ali@372
   587
			*string = razor_rpm_get_details_string(rpm, type);
ali@372
   588
		}
ali@369
   589
        }
ali@369
   590
}
ali@369
   591
ali@369
   592
RAZOR_EXPORT void
ali@369
   593
razor_rpm_get_details(struct razor_rpm *rpm, ...)
ali@369
   594
{
ali@369
   595
	va_list args;
ali@369
   596
ali@369
   597
	assert(rpm != NULL);
ali@369
   598
ali@369
   599
	va_start(args, rpm);
ali@369
   600
	razor_rpm_get_details_varg(rpm, args);
ali@369
   601
	va_end(args);
ali@369
   602
}
ali@369
   603
krh@269
   604
RAZOR_EXPORT struct razor_rpm *
ali@426
   605
razor_rpm_open(const char *filename, struct razor_error **error)
rhughes@241
   606
{
rhughes@241
   607
	struct razor_rpm *rpm;
rhughes@241
   608
	struct rpm_header_index *base, *index;
rhughes@241
   609
	unsigned int count, i, nindex, hsize;
ali@351
   610
	const char *name, *prefix;
rhughes@241
   611
richard@301
   612
	assert (filename != NULL);
richard@301
   613
ali@403
   614
	rpm = zalloc(sizeof *rpm);
ali@403
   615
	if (rpm == NULL) {
ali@426
   616
		razor_set_error(error, NULL, "Not enough memory");
krh@246
   617
		return NULL;
ali@403
   618
	}
rhughes@241
   619
	memset(rpm, 0, sizeof *rpm);
rhughes@241
   620
ali@426
   621
	rpm->map = razor_file_get_contents(filename, &rpm->size, 0, error);
ali@322
   622
	if (!rpm->map) {
ali@403
   623
		free(rpm);
rhughes@241
   624
		return NULL;
rhughes@241
   625
	}
rhughes@241
   626
rhughes@241
   627
	rpm->signature = rpm->map + RPM_LEAD_SIZE;
rhughes@241
   628
	nindex = ntohl(rpm->signature->nindex);
rhughes@241
   629
	hsize = ntohl(rpm->signature->hsize);
rhughes@241
   630
	rpm->header = (void *) (rpm->signature + 1) +
rhughes@241
   631
		ALIGN(nindex * sizeof *index + hsize, 8);
rhughes@241
   632
	nindex = ntohl(rpm->header->nindex);
rhughes@241
   633
	hsize = ntohl(rpm->header->hsize);
rhughes@241
   634
	rpm->payload = (void *) (rpm->header + 1) +
rhughes@241
   635
		nindex * sizeof *index + hsize;
rhughes@241
   636
rhughes@241
   637
	base = (struct rpm_header_index *) (rpm->header + 1);
rhughes@241
   638
	rpm->pool = (void *) base + nindex * sizeof *index;
rhughes@241
   639
rhughes@241
   640
	/* Look up dir names now so we can index them directly. */
rhughes@241
   641
	name = razor_rpm_get_indirect(rpm, RPMTAG_DIRNAMES, &count);
rhughes@241
   642
	if (name) {
rhughes@241
   643
		rpm->dirs = calloc(count, sizeof *rpm->dirs);
rhughes@241
   644
		for (i = 0; i < count; i++) {
rhughes@241
   645
			rpm->dirs[i] = name;
rhughes@241
   646
			name += strlen(name) + 1;
rhughes@241
   647
		}
rhughes@241
   648
	} else {
rhughes@241
   649
		name = razor_rpm_get_indirect(rpm, RPMTAG_OLDFILENAMES,
rhughes@241
   650
					      &count);
rhughes@241
   651
		if (name) {
ali@403
   652
			razor_rpm_close(rpm);
ali@426
   653
			razor_set_error(error, filename,
ali@426
   654
					"Old filenames not supported");
rhughes@241
   655
			return NULL;
rhughes@241
   656
		}
rhughes@241
   657
	}
rhughes@241
   658
ali@351
   659
	prefix = razor_rpm_get_indirect(rpm, RPMTAG_PREFIXES, &count);
ali@351
   660
	if (prefix) {
ali@372
   661
		rpm->prefixes = calloc(count + 1, sizeof *rpm->prefixes);
ali@351
   662
		for (i = 0; i < count; i++) {
ali@351
   663
			rpm->prefixes[i] = prefix;
ali@351
   664
			prefix += strlen(prefix) + 1;
ali@351
   665
		}
ali@372
   666
		rpm->prefixes[i] = NULL;
ali@351
   667
		rpm->n_prefixes = count;
ali@351
   668
	} else {
ali@351
   669
		prefix = razor_rpm_get_indirect(rpm, RPMTAG_DEFAULTPREFIX,
ali@351
   670
						&count);
ali@351
   671
		if (prefix) {
ali@403
   672
			razor_rpm_close(rpm);
ali@426
   673
			razor_set_error(error, filename,
ali@426
   674
					"Default prefix not supported");
ali@351
   675
			return NULL;
ali@351
   676
		}
ali@351
   677
	}
ali@351
   678
rhughes@241
   679
	return rpm;
rhughes@241
   680
}
rhughes@241
   681
ali@351
   682
RAZOR_EXPORT void razor_rpm_set_relocations(struct razor_rpm *rpm,
ali@351
   683
					    struct razor_relocations *rr)
ali@351
   684
{
ali@351
   685
	assert (rpm != NULL);
ali@351
   686
ali@351
   687
	rpm->relocations = rr;
ali@351
   688
}
ali@351
   689
rhughes@241
   690
struct cpio_file_header {
rhughes@241
   691
	char magic[6];
rhughes@241
   692
	char inode[8];
rhughes@241
   693
	char mode[8];
rhughes@241
   694
	char uid[8];
rhughes@241
   695
	char gid[8];
rhughes@241
   696
	char nlink[8];
rhughes@241
   697
	char mtime[8];
rhughes@241
   698
	char filesize[8];
rhughes@241
   699
	char devmajor[8];
rhughes@241
   700
	char devminor[8];
rhughes@241
   701
	char rdevmajor[8];
rhughes@241
   702
	char rdevminor[8];
rhughes@241
   703
	char namesize[8];
rhughes@241
   704
	char checksum[8];
rhughes@241
   705
	char filename[0];
rhughes@241
   706
};
rhughes@241
   707
rhughes@241
   708
/* gzip flags */
rhughes@241
   709
#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
rhughes@241
   710
#define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
rhughes@241
   711
#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
rhughes@241
   712
#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
rhughes@241
   713
#define COMMENT      0x10 /* bit 4 set: file comment present */
rhughes@241
   714
#define RESERVED     0xE0 /* bits 5..7: reserved */
rhughes@241
   715
rhughes@241
   716
struct installer {
rhughes@241
   717
	const char *root;
rhughes@241
   718
	struct razor_rpm *rpm;
ali@403
   719
	struct razor_atomic *atomic;
rhughes@241
   720
	z_stream stream;
rhughes@241
   721
	unsigned char buffer[32768];
rhughes@241
   722
	size_t rest, length;
rhughes@241
   723
};
rhughes@241
   724
rhughes@241
   725
static int
rhughes@241
   726
installer_inflate(struct installer *installer)
rhughes@241
   727
{
rhughes@241
   728
	size_t length;
rhughes@241
   729
	int err;
rhughes@241
   730
rhughes@241
   731
	if (installer->rest > sizeof installer->buffer)
rhughes@241
   732
		length = sizeof installer->buffer;
rhughes@241
   733
	else
rhughes@241
   734
		length = installer->rest;
rhughes@241
   735
rhughes@241
   736
	installer->stream.next_out = installer->buffer;
rhughes@241
   737
	installer->stream.avail_out = length;
rhughes@241
   738
	err = inflate(&installer->stream, Z_SYNC_FLUSH);
rhughes@241
   739
	if (err != Z_OK && err != Z_STREAM_END) {
ali@403
   740
		razor_atomic_abort(installer->atomic, "Failed to inflate");
rhughes@241
   741
		return -1;
rhughes@241
   742
	}
rhughes@241
   743
rhughes@241
   744
	installer->rest -= length;
rhughes@241
   745
	installer->length = length;
rhughes@241
   746
rhughes@241
   747
	return 0;
rhughes@241
   748
}
rhughes@241
   749
rhughes@241
   750
static int
rhughes@241
   751
installer_align(struct installer *installer, size_t size)
rhughes@241
   752
{
rhughes@241
   753
	unsigned char buffer[4];
rhughes@241
   754
	int err;
rhughes@241
   755
rhughes@241
   756
	installer->stream.next_out = buffer;
rhughes@241
   757
	installer->stream.avail_out =
rhughes@241
   758
		(size - installer->stream.total_out) & (size - 1);
rhughes@241
   759
rhughes@241
   760
	if (installer->stream.avail_out == 0)
rhughes@241
   761
		return 0;
rhughes@241
   762
rhughes@241
   763
	err = inflate(&installer->stream, Z_SYNC_FLUSH);
rhughes@241
   764
	if (err != Z_OK && err != Z_STREAM_END) {
ali@403
   765
		razor_atomic_abort(installer->atomic, "Failed to inflate");
rhughes@241
   766
		return -1;
rhughes@241
   767
	}
rhughes@241
   768
rhughes@241
   769
	return 0;
rhughes@241
   770
}
rhughes@241
   771
rhughes@241
   772
static int
rhughes@241
   773
create_path(struct installer *installer, const char *path, unsigned int mode)
rhughes@241
   774
{
ali@403
   775
	char *s, *buffer;
ali@403
   776
	int h, ret;
rhughes@241
   777
ali@403
   778
	if (razor_atomic_make_dirs(installer->atomic, installer->root, path))
rhughes@241
   779
		return -1;
rhughes@241
   780
ali@403
   781
	buffer = razor_concat(installer->root, path, NULL);
rhughes@241
   782
rhughes@241
   783
	switch (mode >> 12) {
rhughes@241
   784
	case REG:
rhughes@241
   785
		/* FIXME: handle the case where a file is already there. */
ali@403
   786
		h = razor_atomic_create_file(installer->atomic, buffer, mode);
ali@403
   787
		free(buffer);
ali@403
   788
		if (h < 0)
rhughes@241
   789
			return -1;
ali@403
   790
		while (installer->rest > 0) {
ali@403
   791
			if (installer_inflate(installer))
ali@403
   792
				return -1;
ali@403
   793
			if (razor_atomic_write(installer->atomic, h,
ali@403
   794
					       installer->buffer,
ali@403
   795
					       installer->length))
ali@403
   796
				return -1;
rhughes@241
   797
		}
ali@403
   798
		return razor_atomic_close(installer->atomic, h);
rhughes@241
   799
	case XDIR:
ali@403
   800
		ret = razor_atomic_create_dir(installer->atomic, buffer, mode);
ali@403
   801
		free(buffer);
ali@403
   802
		return ret;
rhughes@241
   803
	case LINK:
ali@327
   804
#if HAVE_SYMLINK
ali@403
   805
		if (installer_inflate(installer))
rhughes@241
   806
			return -1;
rhughes@241
   807
		if (installer->length >= sizeof installer->buffer) {
ali@403
   808
			razor_atomic_abort(installer->atomic,
ali@403
   809
			  "Link target too long");
rhughes@241
   810
			return -1;
rhughes@241
   811
		}
rhughes@241
   812
		installer->buffer[installer->length] = '\0';
ali@403
   813
		ret = razor_atomic_create_symlink(installer->atomic,
ali@403
   814
		  (const char *)installer->buffer, buffer);
ali@403
   815
		free(buffer);
ali@403
   816
		return ret;
ali@327
   817
#else
ali@403
   818
		s = "Symbolic links";
ali@403
   819
		goto unsupported;
ali@327
   820
#endif
ali@327
   821
	case PIPE:
ali@403
   822
		s = "Named pipes";
ali@403
   823
unsupported:
ali@403
   824
		free(buffer);
ali@403
   825
		buffer = razor_concat(s, " are not supported on this platform",
ali@403
   826
		  NULL);
ali@403
   827
		razor_atomic_abort(installer->atomic, buffer);
ali@403
   828
		free(buffer);
ali@403
   829
		return -1;
ali@327
   830
	case CDEV:
ali@403
   831
		s = "Character devices";
ali@403
   832
		goto unsupported;
ali@327
   833
	case BDEV:
ali@403
   834
		s = "Block devices";
ali@403
   835
		goto unsupported;
ali@327
   836
	case SOCK:
ali@403
   837
		s = "Named sockets";
ali@403
   838
		goto unsupported;
rhughes@241
   839
	default:
ali@403
   840
		free(buffer);
ali@403
   841
		razor_atomic_abort(installer->atomic, "Unknown file type");
ali@403
   842
		return -1;
rhughes@241
   843
	}
rhughes@241
   844
}
rhughes@241
   845
ali@353
   846
static int chroot_push(const char *root)
ali@353
   847
{
ali@353
   848
	int fd;
ali@353
   849
#if HAVE_CHROOT
ali@353
   850
	if (geteuid() == 0) {
ali@353
   851
		fd = open("/", O_RDONLY, 0);
ali@353
   852
		if (chroot(root) < 0) {
ali@353
   853
			fprintf(stderr, "failed to chroot to %s: %s\n",
ali@353
   854
				root, strerror(errno));
ali@353
   855
			exit(-1);
ali@353
   856
		}
ali@353
   857
	} else
ali@353
   858
#endif
ali@353
   859
		fd = -1;
ali@353
   860
	return fd;
ali@353
   861
}
ali@353
   862
ali@353
   863
static void chroot_pop(int fd)
rhughes@241
   864
{
ali@328
   865
#if HAVE_CHROOT
ali@353
   866
	if (fd >= 0) {
ali@353
   867
		fchdir(fd);
ali@353
   868
		close(fd);
ali@353
   869
		chroot(".");
ali@353
   870
	}
ali@353
   871
#endif
ali@353
   872
}
ali@353
   873
ali@353
   874
static int
ali@376
   875
run_script_lua(const char *root, unsigned int script_tag, const char *script,
ali@376
   876
	       int arg1)
ali@353
   877
{
ali@353
   878
	int root_fd, retval;
ali@352
   879
#if HAVE_LUA
ali@353
   880
	const char *name;
ali@353
   881
ali@353
   882
	switch(script_tag) {
ali@353
   883
		case RPMTAG_PREIN:
ali@353
   884
			name = "%pre";
ali@353
   885
			break;
ali@353
   886
		case RPMTAG_POSTIN:
ali@353
   887
			name = "%post";
ali@353
   888
			break;
ali@353
   889
		case RPMTAG_PREUN:
ali@353
   890
			name = "%preun";
ali@353
   891
			break;
ali@353
   892
		case RPMTAG_POSTUN:
ali@353
   893
			name = "%postun";
ali@353
   894
			break;
ali@353
   895
		default:
ali@353
   896
			name = "script";
ali@353
   897
			break;
ali@353
   898
	}
ali@353
   899
	root_fd = chroot_push(root);
ali@376
   900
	retval = run_lua_script(root_fd < 0 ? root : NULL, name, script, -1,
ali@376
   901
				arg1);
ali@353
   902
	chroot_pop(root_fd);
ali@353
   903
#else	/* HAVE_LUA */
ali@353
   904
	fprintf(stderr, "lua not available to run script\n");
ali@353
   905
	retval = -1;
ali@353
   906
#endif	/* HAVE_LUA */
ali@353
   907
ali@353
   908
	return retval;
ali@353
   909
}
ali@353
   910
ali@353
   911
static int
ali@376
   912
run_script_external(const char *root, const char *program, const char *script,
ali@376
   913
		    int arg1)
ali@353
   914
{
ali@353
   915
	int root_fd, retval;
ali@328
   916
	FILE *fp;
ali@376
   917
	char buf[32], *command;
rhughes@241
   918
ali@353
   919
	if (program == NULL) {
ali@328
   920
#if MSWIN_API
ali@328
   921
		program = getenv("COMSPEC");
ali@328
   922
		if (program) {
ali@328
   923
			program = strchr(program, '=');
ali@328
   924
			if (program)
ali@328
   925
				program++;
ali@328
   926
		}
ali@328
   927
		if (!program)
ali@328
   928
			program = "c:\\windows\\system32\\cmd.exe";
ali@328
   929
#else
rhughes@241
   930
		program = "/bin/sh";
ali@328
   931
#endif
rhughes@241
   932
	}
rhughes@241
   933
ali@353
   934
	root_fd = chroot_push(root);
ali@376
   935
	if (arg1 >= 0) {
ali@376
   936
		sprintf(buf, "%d", arg1);
ali@376
   937
		command = malloc(strlen(program) + strlen(buf) + 2);
ali@376
   938
		sprintf(command, "%s %s", program, buf);
ali@376
   939
	} else
ali@376
   940
		command = strdup(program);
ali@376
   941
	fp = popen(command, "w");
ali@376
   942
	free(command);
rhughes@241
   943
ali@353
   944
	if (!fp) {
ali@353
   945
		perror(program);
ali@353
   946
		retval = -1;
ali@370
   947
	} else if (script && fwrite(script, strlen(script), 1, fp) != 1) {
ali@353
   948
		perror("failed to write script to program");
ali@353
   949
		retval = -1;
ali@353
   950
	} else
ali@353
   951
		retval = 0;
ali@353
   952
ali@353
   953
	if (fp)
ali@353
   954
		pclose(fp);
ali@353
   955
	chroot_pop(root_fd);
ali@353
   956
ali@353
   957
	return retval;
ali@353
   958
}
ali@353
   959
ali@353
   960
static int
ali@353
   961
run_script(struct installer *installer,
ali@376
   962
	   unsigned int program_tag, unsigned int script_tag, int arg1)
ali@353
   963
{
ali@362
   964
	int i, retval;
ali@362
   965
	struct razor_rpm *rpm = installer->rpm;
ali@362
   966
	const char *script = NULL, *program = NULL, *prefix;
ali@376
   967
	char buf[32];
ali@372
   968
	struct environment env;
ali@353
   969
ali@362
   970
	program = razor_rpm_get_indirect(rpm, program_tag, NULL);
ali@362
   971
	script = razor_rpm_get_indirect(rpm, script_tag, NULL);
ali@353
   972
	if (program == NULL && script == NULL)
ali@362
   973
		return 0;
ali@362
   974
ali@362
   975
	if (rpm->relocations) {
ali@372
   976
		environment_init(&env);
ali@362
   977
		for(i = 0; i < rpm->n_prefixes; i++) {
ali@362
   978
			prefix = razor_relocations_apply(rpm->relocations,
ali@362
   979
							 rpm->prefixes[i]);
ali@362
   980
			sprintf(buf, "RPM_INSTALL_PREFIX%d", i);
ali@372
   981
			environment_add_variable(&env, buf, prefix);
ali@362
   982
		}
ali@372
   983
		environment_set(&env);
ali@362
   984
	}
ali@362
   985
ali@369
   986
	if (program && strcmp(program, "<lua>") == 0)
ali@376
   987
		retval = run_script_lua(installer->root, script_tag, script,
ali@376
   988
					arg1);
ali@353
   989
	else
ali@376
   990
		retval = run_script_external(installer->root, program, script,
ali@376
   991
					     arg1);
ali@353
   992
ali@362
   993
	if (rpm->relocations) {
ali@372
   994
		environment_unset(&env);
ali@372
   995
		environment_release(&env);
ali@362
   996
	}
ali@362
   997
ali@353
   998
	return retval;
rhughes@241
   999
}
rhughes@241
  1000
ali@369
  1001
int
ali@369
  1002
razor_run_script(const char *root, enum razor_property_flags script,
ali@376
  1003
		 const char *program, const char *body, int arg1)
ali@369
  1004
{
ali@369
  1005
	int retval;
ali@369
  1006
	unsigned int script_tag;
ali@369
  1007
ali@369
  1008
	if (program && !*program)
ali@369
  1009
		program = NULL;
ali@369
  1010
	if (body && !*body)
ali@369
  1011
		body = NULL;
ali@369
  1012
	if (program == NULL && body == NULL)
ali@369
  1013
		return 0;
ali@369
  1014
ali@369
  1015
	if (program && strcmp(program, "<lua>") == 0)
ali@369
  1016
	{
ali@369
  1017
		switch(script) {
ali@369
  1018
		case RAZOR_PROPERTY_PRE:
ali@369
  1019
			script_tag = RPMTAG_PREIN;
ali@369
  1020
			break;
ali@369
  1021
		case RAZOR_PROPERTY_POST:
ali@369
  1022
			script_tag = RPMTAG_POSTIN;
ali@369
  1023
			break;
ali@369
  1024
		case RAZOR_PROPERTY_PREUN:
ali@369
  1025
			script_tag = RPMTAG_PREUN;
ali@369
  1026
			break;
ali@369
  1027
		case RAZOR_PROPERTY_POSTUN:
ali@369
  1028
			script_tag = RPMTAG_POSTUN;
ali@369
  1029
			break;
ali@369
  1030
		default:
ali@369
  1031
			script_tag = 0;
ali@369
  1032
			break;
ali@369
  1033
		}
ali@376
  1034
		retval = run_script_lua(root, script_tag, body, arg1);
ali@369
  1035
	}
ali@369
  1036
	else
ali@376
  1037
		retval = run_script_external(root, program, body, arg1);
ali@369
  1038
ali@369
  1039
	return retval;
ali@369
  1040
}
ali@369
  1041
rhughes@241
  1042
static int
rhughes@241
  1043
installer_init(struct installer *installer)
rhughes@241
  1044
{
rhughes@241
  1045
	unsigned char *gz_header;
rhughes@241
  1046
	int method, flags, err;
ali@403
  1047
	char buffer[32], *s;
rhughes@241
  1048
rhughes@241
  1049
	gz_header = installer->rpm->payload;
rhughes@241
  1050
	if (gz_header[0] != 0x1f || gz_header[1] != 0x8b) {
ali@403
  1051
		razor_atomic_abort(installer->atomic, 
ali@403
  1052
				   "Payload section doesn't have gz header");
rhughes@241
  1053
		return -1;
rhughes@241
  1054
	}
rhughes@241
  1055
rhughes@241
  1056
	method = gz_header[2];
rhughes@241
  1057
	flags = gz_header[3];
rhughes@241
  1058
rhughes@241
  1059
	if (method != Z_DEFLATED || flags != 0) {
ali@403
  1060
		razor_atomic_abort(installer->atomic, 
ali@403
  1061
				   "Unknown payload compression method or "
ali@403
  1062
				   "flags set");
rhughes@241
  1063
		return -1;
rhughes@241
  1064
	}
rhughes@241
  1065
rhughes@241
  1066
	installer->stream.zalloc = NULL;
rhughes@241
  1067
	installer->stream.zfree = NULL;
rhughes@241
  1068
	installer->stream.opaque = NULL;
rhughes@241
  1069
rhughes@241
  1070
	installer->stream.next_in  = gz_header + 10;
rhughes@241
  1071
	installer->stream.avail_in =
rhughes@241
  1072
		(installer->rpm->map + installer->rpm->size) -
rhughes@241
  1073
		(void *) installer->stream.next_in;
rhughes@241
  1074
	installer->stream.next_out = NULL;
rhughes@241
  1075
	installer->stream.avail_out = 0;
rhughes@241
  1076
rhughes@241
  1077
	err = inflateInit2(&installer->stream, -MAX_WBITS);
rhughes@241
  1078
	if (err != Z_OK) {
ali@403
  1079
		sprintf(buffer, "%d", err);
ali@403
  1080
		s = razor_concat("inflateEnd error: ", s, NULL);
ali@403
  1081
		razor_atomic_abort(installer->atomic, s);
ali@403
  1082
		free(s);
rhughes@241
  1083
		return -1;
rhughes@241
  1084
	}
rhughes@241
  1085
rhughes@241
  1086
	return 0;
rhughes@241
  1087
}
rhughes@241
  1088
rhughes@241
  1089
static int
rhughes@241
  1090
installer_finish(struct installer *installer)
rhughes@241
  1091
{
rhughes@241
  1092
	int err;
ali@403
  1093
	char buffer[32], *s;
rhughes@241
  1094
rhughes@241
  1095
	err = inflateEnd(&installer->stream);
rhughes@241
  1096
rhughes@241
  1097
	if (err != Z_OK) {
ali@403
  1098
		sprintf(buffer, "%d", err);
ali@403
  1099
		s = razor_concat("inflateEnd error: ", s, NULL);
ali@403
  1100
		razor_atomic_abort(installer->atomic, s);
ali@403
  1101
		free(s);
rhughes@241
  1102
	}
rhughes@241
  1103
ali@403
  1104
	return razor_atomic_in_error_state(installer->atomic);
rhughes@241
  1105
}
rhughes@241
  1106
rhughes@241
  1107
static unsigned long
rhughes@241
  1108
fixed_hex_to_ulong(const char *hex, int length)
rhughes@241
  1109
{
rhughes@241
  1110
	long l;
rhughes@241
  1111
	int i;
rhughes@241
  1112
rhughes@241
  1113
	for (i = 0, l = 0; i < length; i++) {
rhughes@241
  1114
		if (hex[i] < 'a')
rhughes@241
  1115
			l = l * 16 + hex[i] - '0';
rhughes@241
  1116
		else
rhughes@241
  1117
			l = l * 16 + hex[i] - 'a' + 10;
rhughes@241
  1118
	}
rhughes@241
  1119
rhughes@241
  1120
	return l;
rhughes@241
  1121
}
rhughes@241
  1122
krh@269
  1123
RAZOR_EXPORT int
ali@403
  1124
razor_rpm_install(struct razor_rpm *rpm, struct razor_atomic *atomic,
ali@403
  1125
		  const char *root, int install_count,
ali@403
  1126
		  enum razor_stage_type stage)
rhughes@241
  1127
{
rhughes@241
  1128
	struct installer installer;
rhughes@241
  1129
	struct cpio_file_header *header;
rhughes@241
  1130
	struct stat buf;
rhughes@241
  1131
	unsigned int mode;
ali@424
  1132
	const char *path;
rhughes@241
  1133
	size_t filesize;
ali@403
  1134
	char *s;
ali@422
  1135
	int retval = 0;
rhughes@241
  1136
richard@301
  1137
	assert (rpm != NULL);
richard@301
  1138
	assert (root != NULL);
richard@301
  1139
rhughes@241
  1140
	installer.rpm = rpm;
rhughes@241
  1141
	installer.root = root;
ali@403
  1142
	installer.atomic = atomic;
rhughes@241
  1143
rhughes@241
  1144
	/* FIXME: Only do this before a transaction, not per rpm. */
ali@347
  1145
	if (*root && (stat(root, &buf) < 0 || !S_ISDIR(buf.st_mode))) {
ali@403
  1146
		s = razor_concat(root, ": Directory does not exist", NULL);
ali@424
  1147
		razor_atomic_abort(atomic, s);
ali@403
  1148
		free(s);
rhughes@241
  1149
		return -1;
rhughes@241
  1150
	}
rhughes@241
  1151
ali@351
  1152
	if (rpm->relocations)
ali@351
  1153
		razor_relocations_set_rpm(rpm->relocations, rpm);
ali@351
  1154
ali@403
  1155
	if (stage & RAZOR_STAGE_SCRIPTS_PRE)
ali@422
  1156
		retval = run_script(&installer, RPMTAG_PREINPROG, RPMTAG_PREIN,
ali@422
  1157
				    install_count);
rhughes@241
  1158
ali@422
  1159
	if (!retval && (stage & RAZOR_STAGE_FILES)) {
ali@403
  1160
		if (installer_init(&installer))
rhughes@241
  1161
			return -1;
rhughes@241
  1162
ali@403
  1163
		while (installer.stream.avail_in > 0) {
ali@403
  1164
			installer.rest = sizeof *header;
ali@403
  1165
			if (installer_inflate(&installer))
ali@403
  1166
				break;
rhughes@241
  1167
ali@403
  1168
			header = (struct cpio_file_header *) installer.buffer;
ali@403
  1169
			mode = fixed_hex_to_ulong(header->mode,
ali@403
  1170
						  sizeof header->mode);
ali@403
  1171
			filesize = fixed_hex_to_ulong(header->filesize,
ali@403
  1172
						      sizeof header->filesize);
rhughes@241
  1173
ali@403
  1174
			installer.rest =
ali@403
  1175
			  fixed_hex_to_ulong(header->namesize,
ali@403
  1176
					     sizeof header->namesize);
rhughes@241
  1177
ali@403
  1178
			if (installer_inflate(&installer) ||
ali@403
  1179
			    installer_align(&installer, 4))
ali@403
  1180
				break;
rhughes@241
  1181
ali@403
  1182
			path = (const char *) installer.buffer;
ali@403
  1183
			/* This convention is so lame... */
ali@403
  1184
			if (strcmp(path, "TRAILER!!!") == 0)
ali@403
  1185
				break;
ali@403
  1186
ali@403
  1187
			installer.rest = filesize;
ali@403
  1188
			path++;
ali@403
  1189
			if (rpm->relocations)
ali@403
  1190
				path = razor_relocations_apply(rpm->relocations,
ali@403
  1191
							       path);
ali@403
  1192
			if (create_path(&installer, path, mode))
ali@403
  1193
				break;
ali@403
  1194
			if (installer_align(&installer, 4))
ali@403
  1195
				break;
ali@403
  1196
		}
ali@403
  1197
ali@403
  1198
		if (installer_finish(&installer))
rhughes@241
  1199
			return -1;
ali@422
  1200
ali@422
  1201
		retval = razor_atomic_in_error_state(atomic);
rhughes@241
  1202
	}
rhughes@241
  1203
ali@422
  1204
	if (!retval && (stage & RAZOR_STAGE_SCRIPTS_POST))
ali@422
  1205
		retval = run_script(&installer, RPMTAG_POSTINPROG,
ali@422
  1206
				    RPMTAG_POSTIN, install_count);
rhughes@241
  1207
ali@422
  1208
	return retval;
rhughes@241
  1209
}
rhughes@241
  1210
krh@269
  1211
RAZOR_EXPORT int
rhughes@241
  1212
razor_rpm_close(struct razor_rpm *rpm)
rhughes@241
  1213
{
rhughes@241
  1214
	int err;
rhughes@241
  1215
richard@301
  1216
	assert (rpm != NULL);
richard@301
  1217
rhughes@241
  1218
	free(rpm->dirs);
ali@351
  1219
	free(rpm->prefixes);
ali@322
  1220
	err = razor_file_free_contents(rpm->map, rpm->size);
ali@369
  1221
	free(rpm->evr);
rhughes@241
  1222
	free(rpm);
rhughes@241
  1223
rhughes@241
  1224
	return err;
rhughes@241
  1225
}
rhughes@241
  1226
krh@269
  1227
RAZOR_EXPORT int
rhughes@241
  1228
razor_importer_add_rpm(struct razor_importer *importer, struct razor_rpm *rpm)
rhughes@241
  1229
{
ali@369
  1230
	const char *name, *version, *arch;
jbowes@289
  1231
	const char *summary, *description, *url, *license;
rhughes@241
  1232
richard@301
  1233
	assert (importer != NULL);
richard@301
  1234
	assert (rpm != NULL);
richard@301
  1235
ali@369
  1236
	razor_rpm_get_details(rpm,
ali@369
  1237
			      RAZOR_DETAIL_NAME, &name,
ali@369
  1238
			      RAZOR_DETAIL_VERSION, &version,
ali@369
  1239
			      RAZOR_DETAIL_ARCH, &arch,
ali@369
  1240
			      RAZOR_DETAIL_SUMMARY, &summary,
ali@369
  1241
			      RAZOR_DETAIL_DESCRIPTION, &description,
ali@369
  1242
			      RAZOR_DETAIL_URL, &url,
ali@369
  1243
			      RAZOR_DETAIL_LICENSE, &license,
ali@369
  1244
			      RAZOR_DETAIL_LAST);
jbowes@289
  1245
ali@369
  1246
	razor_importer_begin_package(importer, name, version, arch);
rhughes@241
  1247
jbowes@289
  1248
	razor_importer_add_details(importer, summary, description, url,
jbowes@289
  1249
				   license);
jbowes@289
  1250
rhughes@241
  1251
	import_properties(importer, RAZOR_PROPERTY_REQUIRES, rpm,
rhughes@241
  1252
			  RPMTAG_REQUIRENAME,
rhughes@241
  1253
			  RPMTAG_REQUIREVERSION,
rhughes@241
  1254
			  RPMTAG_REQUIREFLAGS);
rhughes@241
  1255
rhughes@241
  1256
	import_properties(importer, RAZOR_PROPERTY_PROVIDES, rpm,
rhughes@241
  1257
			  RPMTAG_PROVIDENAME,
rhughes@241
  1258
			  RPMTAG_PROVIDEVERSION,
rhughes@241
  1259
			  RPMTAG_PROVIDEFLAGS);
rhughes@241
  1260
rhughes@241
  1261
	import_properties(importer, RAZOR_PROPERTY_OBSOLETES, rpm,
rhughes@241
  1262
			  RPMTAG_OBSOLETENAME,
rhughes@241
  1263
			  RPMTAG_OBSOLETEVERSION,
rhughes@241
  1264
			  RPMTAG_OBSOLETEFLAGS);
rhughes@241
  1265
rhughes@241
  1266
	import_properties(importer, RAZOR_PROPERTY_CONFLICTS, rpm,
rhughes@241
  1267
			  RPMTAG_CONFLICTNAME,
rhughes@241
  1268
			  RPMTAG_CONFLICTVERSION,
rhughes@241
  1269
			  RPMTAG_CONFLICTFLAGS);
rhughes@241
  1270
rhughes@241
  1271
	import_files(importer, rpm);
rhughes@241
  1272
rhughes@241
  1273
	razor_importer_finish_package(importer);
rhughes@241
  1274
rhughes@241
  1275
	return 0;
rhughes@241
  1276
}