15c51f124SMoriah Waterland /*
25c51f124SMoriah Waterland  * CDDL HEADER START
35c51f124SMoriah Waterland  *
45c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
55c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
65c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
75c51f124SMoriah Waterland  *
85c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
105c51f124SMoriah Waterland  * See the License for the specific language governing permissions
115c51f124SMoriah Waterland  * and limitations under the License.
125c51f124SMoriah Waterland  *
135c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
145c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
165c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
175c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
185c51f124SMoriah Waterland  *
195c51f124SMoriah Waterland  * CDDL HEADER END
205c51f124SMoriah Waterland  */
215c51f124SMoriah Waterland 
225c51f124SMoriah Waterland /*
235c51f124SMoriah Waterland  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
245c51f124SMoriah Waterland  * Use is subject to license terms.
255c51f124SMoriah Waterland  */
265c51f124SMoriah Waterland 
275c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
285c51f124SMoriah Waterland /* All Rights Reserved */
295c51f124SMoriah Waterland 
305c51f124SMoriah Waterland 
315c51f124SMoriah Waterland #include <stdio.h>
325c51f124SMoriah Waterland #include <string.h>
335c51f124SMoriah Waterland #include <stdlib.h>
345c51f124SMoriah Waterland #include <unistd.h>
355c51f124SMoriah Waterland #include <dirent.h>
365c51f124SMoriah Waterland #include <locale.h>
375c51f124SMoriah Waterland #include <libintl.h>
385c51f124SMoriah Waterland #include <errno.h>
395c51f124SMoriah Waterland #include "pkglib.h"
405c51f124SMoriah Waterland #include "install.h"
415c51f124SMoriah Waterland #include "libadm.h"
425c51f124SMoriah Waterland #include "libinst.h"
435c51f124SMoriah Waterland #include "pkginstall.h"
445c51f124SMoriah Waterland #include "messages.h"
455c51f124SMoriah Waterland 
465c51f124SMoriah Waterland extern char	instdir[], pkgbin[], pkgloc[], savlog[], *pkginst, **environ;
475c51f124SMoriah Waterland extern char	saveSpoolInstallDir[];
485c51f124SMoriah Waterland extern char	pkgsav[];	/* pkginstall/main.c */
495c51f124SMoriah Waterland static char 	*infoloc;
505c51f124SMoriah Waterland 
515c51f124SMoriah Waterland /*
525c51f124SMoriah Waterland  * flag definitions for each entry in table
535c51f124SMoriah Waterland  */
545c51f124SMoriah Waterland 
555c51f124SMoriah Waterland typedef unsigned int TBL_FLAG_T;
565c51f124SMoriah Waterland 
575c51f124SMoriah Waterland /* no flag set */
585c51f124SMoriah Waterland #define	FLAG_NONE	((TBL_FLAG_T)0x0000)
595c51f124SMoriah Waterland 
605c51f124SMoriah Waterland /* exclude this attribute if found */
615c51f124SMoriah Waterland #define	FLAG_EXCLUDE	((TBL_FLAG_T)0x0001)
625c51f124SMoriah Waterland 
635c51f124SMoriah Waterland /* this attribute must not change if found */
645c51f124SMoriah Waterland #define	FLAG_IDENTICAL	((TBL_FLAG_T)0x0002)
655c51f124SMoriah Waterland 
665c51f124SMoriah Waterland /*
675c51f124SMoriah Waterland  * macro to generate an entry in the table:
685c51f124SMoriah Waterland  *	TBL_ENTRY("PKGINFO_ATTRIBUTE=", FLAG_XXX)
695c51f124SMoriah Waterland  * where:
705c51f124SMoriah Waterland  *	"PKGINFO_ATTRIBUTE=" is the attribute to look for
715c51f124SMoriah Waterland  *	FLAG_XXX is the action to perform when the attribute is found
725c51f124SMoriah Waterland  */
735c51f124SMoriah Waterland 
745c51f124SMoriah Waterland #define	TBL_ENTRY(_Y_, _F_)	{ (_Y_), ((sizeof ((_Y_)))-1), (_F_) }
755c51f124SMoriah Waterland 
765c51f124SMoriah Waterland /*
775c51f124SMoriah Waterland  * table containing attributes that require special handling
785c51f124SMoriah Waterland  */
795c51f124SMoriah Waterland 
805c51f124SMoriah Waterland struct _namelist {
815c51f124SMoriah Waterland 	char		*_nlName;	/* attribute name */
825c51f124SMoriah Waterland 	int		_nlLen;		/* attribute length */
835c51f124SMoriah Waterland 	TBL_FLAG_T	_nlFlag;	/* attribute disposition flag */
845c51f124SMoriah Waterland };
855c51f124SMoriah Waterland 
865c51f124SMoriah Waterland typedef struct _namelist NAMELIST_T;
875c51f124SMoriah Waterland 
885c51f124SMoriah Waterland /*
895c51f124SMoriah Waterland  * These are attributes to be acted on in some way when a pkginfo file is
905c51f124SMoriah Waterland  * merged. This table MUST be in alphabetical order because it is searched
915c51f124SMoriah Waterland  * using a binary search algorithm.
925c51f124SMoriah Waterland  */
935c51f124SMoriah Waterland 
945c51f124SMoriah Waterland static NAMELIST_T attrTbl[] = {
955c51f124SMoriah Waterland 	TBL_ENTRY("BASEDIR=",			FLAG_EXCLUDE),
965c51f124SMoriah Waterland 	TBL_ENTRY("CLASSES=",			FLAG_EXCLUDE),
975c51f124SMoriah Waterland 	TBL_ENTRY("CLIENT_BASEDIR=",		FLAG_EXCLUDE),
985c51f124SMoriah Waterland 	TBL_ENTRY("INST_DATADIR=",		FLAG_EXCLUDE),
995c51f124SMoriah Waterland 	TBL_ENTRY("PKG_CAS_PASSRELATIVE=",	FLAG_EXCLUDE),
1005c51f124SMoriah Waterland 	TBL_ENTRY("PKG_DST_QKVERIFY=",		FLAG_EXCLUDE),
1015c51f124SMoriah Waterland 	TBL_ENTRY("PKG_INIT_INSTALL=",		FLAG_EXCLUDE),
1025c51f124SMoriah Waterland 	TBL_ENTRY("PKG_INSTALL_ROOT=",		FLAG_EXCLUDE),
1035c51f124SMoriah Waterland 	TBL_ENTRY("PKG_SRC_NOVERIFY=",		FLAG_EXCLUDE),
1045c51f124SMoriah Waterland 	TBL_ENTRY("SUNW_PKGCOND_GLOBAL_DATA=",	FLAG_EXCLUDE),
1055c51f124SMoriah Waterland 	TBL_ENTRY("SUNW_PKG_ALLZONES=",		FLAG_IDENTICAL),
1065c51f124SMoriah Waterland 	TBL_ENTRY("SUNW_PKG_DIR=",		FLAG_EXCLUDE),
1075c51f124SMoriah Waterland 	TBL_ENTRY("SUNW_PKG_HOLLOW=",		FLAG_IDENTICAL),
1085c51f124SMoriah Waterland 	TBL_ENTRY("SUNW_PKG_INSTALL_ZONENAME=",	FLAG_EXCLUDE),
1095c51f124SMoriah Waterland 	TBL_ENTRY("SUNW_PKG_THISZONE=",		FLAG_IDENTICAL),
1105c51f124SMoriah Waterland };
1115c51f124SMoriah Waterland 
1125c51f124SMoriah Waterland #define	ATTRTBL_SIZE	(sizeof (attrTbl) / sizeof (NAMELIST_T))
1135c51f124SMoriah Waterland 
1145c51f124SMoriah Waterland /*
1155c51f124SMoriah Waterland  * While pkgsav has to be set up with reference to the server for package
1165c51f124SMoriah Waterland  * scripts, it has to be client-relative in the pkginfo file. This function
1175c51f124SMoriah Waterland  * is used to set the client-relative value for use in the pkginfo file.
1185c51f124SMoriah Waterland  */
1195c51f124SMoriah Waterland void
set_infoloc(char * path)1205c51f124SMoriah Waterland set_infoloc(char *path)
1215c51f124SMoriah Waterland {
1225c51f124SMoriah Waterland 	if (path && *path) {
1235c51f124SMoriah Waterland 		if (is_an_inst_root()) {
1245c51f124SMoriah Waterland 			/* Strip the server portion of the path. */
1255c51f124SMoriah Waterland 			infoloc = orig_path(path);
1265c51f124SMoriah Waterland 		} else {
1275c51f124SMoriah Waterland 			infoloc = strdup(path);
1285c51f124SMoriah Waterland 		}
1295c51f124SMoriah Waterland 	}
1305c51f124SMoriah Waterland }
1315c51f124SMoriah Waterland 
1325c51f124SMoriah Waterland void
merginfo(struct cl_attr ** pclass,int install_from_pspool)1335c51f124SMoriah Waterland merginfo(struct cl_attr **pclass, int install_from_pspool)
1345c51f124SMoriah Waterland {
1355c51f124SMoriah Waterland 	DIR		*pdirfp;
1365c51f124SMoriah Waterland 	FILE		*fp;
1375c51f124SMoriah Waterland 	FILE		*pkginfoFP;
1385c51f124SMoriah Waterland 	char		path[PATH_MAX];
1395c51f124SMoriah Waterland 	char		cmd[PATH_MAX];
1405c51f124SMoriah Waterland 	char		pkginfoPath[PATH_MAX];
1415c51f124SMoriah Waterland 	char		temp[PATH_MAX];
1425c51f124SMoriah Waterland 	int		i;
1435c51f124SMoriah Waterland 	int		nc;
1445c51f124SMoriah Waterland 	int		out;
1455c51f124SMoriah Waterland 
1465c51f124SMoriah Waterland 	/* remove savelog from previous attempts */
1475c51f124SMoriah Waterland 
1485c51f124SMoriah Waterland 	(void) unlink(savlog);
1495c51f124SMoriah Waterland 
1505c51f124SMoriah Waterland 	/*
1515c51f124SMoriah Waterland 	 * create path to appropriate pkginfo file for the package that is
1525c51f124SMoriah Waterland 	 * already installed - is_spool_create() will be set (!= 0) if the
1535c51f124SMoriah Waterland 	 * -t option is presented to pkginstall - the -t option is used to
1545c51f124SMoriah Waterland 	 * disable save spool area creation; do not spool any partial package
1555c51f124SMoriah Waterland 	 * contents, that is, suppress the creation and population of the
1565c51f124SMoriah Waterland 	 * package save spool area (var/sadm/pkg/PKG/save/pspool/PKG). This
1575c51f124SMoriah Waterland 	 * option is set only when a non-global zone is being created.
1585c51f124SMoriah Waterland 	 */
1595c51f124SMoriah Waterland 
1605c51f124SMoriah Waterland 	if (is_spool_create() == 0) {
1615c51f124SMoriah Waterland 		/*
1625c51f124SMoriah Waterland 		 * normal package install (not a non-global zone install);
1635c51f124SMoriah Waterland 		 * use the standard installed pkginfo file for this package:
1645c51f124SMoriah Waterland 		 * --> /var/sadm/pkg/PKGINST/pkginfo
1655c51f124SMoriah Waterland 		 * as the source pkginfo file to scan.
1665c51f124SMoriah Waterland 		 */
1675c51f124SMoriah Waterland 		i = snprintf(pkginfoPath, sizeof (pkginfoPath),
1685c51f124SMoriah Waterland 			"%s/var/sadm/pkg/%s/%s",
1695c51f124SMoriah Waterland 			((get_inst_root()) &&
1705c51f124SMoriah Waterland 			(strcmp(get_inst_root(), "/") != 0)) ?
1715c51f124SMoriah Waterland 			get_inst_root() : "", pkginst,
1725c51f124SMoriah Waterland 			PKGINFO);
1735c51f124SMoriah Waterland 		if (i > sizeof (pkginfoPath)) {
1745c51f124SMoriah Waterland 			progerr(ERR_CREATE_PATH_2,
1755c51f124SMoriah Waterland 				((get_inst_root()) &&
1765c51f124SMoriah Waterland 				(strcmp(get_inst_root(), "/") != 0)) ?
1775c51f124SMoriah Waterland 				get_inst_root() : "/",
1785c51f124SMoriah Waterland 				pkginst);
1795c51f124SMoriah Waterland 			quit(1);
1805c51f124SMoriah Waterland 		}
1815c51f124SMoriah Waterland 	} else {
1825c51f124SMoriah Waterland 		/*
1835c51f124SMoriah Waterland 		 * non-global zone installation - use the "saved" pspool
1845c51f124SMoriah Waterland 		 * pkginfo file in the global zone for this package:
1855c51f124SMoriah Waterland 		 * --> /var/sadm/install/PKG/save/pspool/PKG/pkginfo
1865c51f124SMoriah Waterland 		 * as the source pkginfo file to scan.
1875c51f124SMoriah Waterland 		 */
1885c51f124SMoriah Waterland 		i = snprintf(pkginfoPath, sizeof (pkginfoPath), "%s/%s",
1895c51f124SMoriah Waterland 			saveSpoolInstallDir, PKGINFO);
1905c51f124SMoriah Waterland 		if (i > sizeof (pkginfoPath)) {
1915c51f124SMoriah Waterland 			progerr(ERR_CREATE_PATH_2,
1925c51f124SMoriah Waterland 				saveSpoolInstallDir, PKGINFO);
1935c51f124SMoriah Waterland 			quit(1);
1945c51f124SMoriah Waterland 		}
1955c51f124SMoriah Waterland 	}
1965c51f124SMoriah Waterland 
1975c51f124SMoriah Waterland 	i = snprintf(path, PATH_MAX, "%s/%s", pkgloc, PKGINFO);
1985c51f124SMoriah Waterland 	if (i > PATH_MAX) {
1995c51f124SMoriah Waterland 		progerr(ERR_CREATE_PATH_2, pkgloc, PKGINFO);
2005c51f124SMoriah Waterland 		quit(1);
2015c51f124SMoriah Waterland 	}
2025c51f124SMoriah Waterland 
2035c51f124SMoriah Waterland 	/* entry debugging info */
2045c51f124SMoriah Waterland 
2055c51f124SMoriah Waterland 	echoDebug(DBG_MERGINFO_ENTRY,
2065c51f124SMoriah Waterland 		instdir ? instdir : "??",
2075c51f124SMoriah Waterland 		((get_inst_root()) &&
2085c51f124SMoriah Waterland 		(strcmp(get_inst_root(), "/") != 0)) ?
2095c51f124SMoriah Waterland 		get_inst_root() : "??",
2105c51f124SMoriah Waterland 		saveSpoolInstallDir ? saveSpoolInstallDir : "??",
2115c51f124SMoriah Waterland 		pkgloc ? pkgloc : "??",	is_spool_create(),
2125c51f124SMoriah Waterland 		get_info_basedir() ? get_info_basedir() : "??",
2135c51f124SMoriah Waterland 		pkginfoPath, path);
2145c51f124SMoriah Waterland 
2155c51f124SMoriah Waterland 	/*
2165c51f124SMoriah Waterland 	 * open the pkginfo file:
2175c51f124SMoriah Waterland 	 * if the source pkginfo file to check is the same as the merged one
2185c51f124SMoriah Waterland 	 * (e.g. /var/sadm/pkg/PKGINST/pkginfo) then do not open the source
2195c51f124SMoriah Waterland 	 * pkginfo file to "verify"
2205c51f124SMoriah Waterland 	 */
2215c51f124SMoriah Waterland 
2225c51f124SMoriah Waterland 	if (strcmp(pkginfoPath, path) == 0) {
2235c51f124SMoriah Waterland 		pkginfoFP = (FILE *)NULL;
2245c51f124SMoriah Waterland 		echoDebug(DBG_MERGINFO_SAME, path);
2255c51f124SMoriah Waterland 	} else {
2265c51f124SMoriah Waterland 		echoDebug(DBG_MERGINFO_DIFFERENT, pkginfoPath, path);
2275c51f124SMoriah Waterland 		pkginfoFP = fopen(pkginfoPath, "r");
2285c51f124SMoriah Waterland 
2295c51f124SMoriah Waterland 		if (pkginfoFP == (FILE *)NULL) {
2305c51f124SMoriah Waterland 			echoDebug(ERR_NO_PKG_INFOFILE, pkginst, pkginfoPath,
2315c51f124SMoriah Waterland 				strerror(errno));
2325c51f124SMoriah Waterland 		}
2335c51f124SMoriah Waterland 	}
2345c51f124SMoriah Waterland 
2355c51f124SMoriah Waterland 	/*
2365c51f124SMoriah Waterland 	 * output packaging environment to create a pkginfo file in pkgloc[]
2375c51f124SMoriah Waterland 	 */
2385c51f124SMoriah Waterland 
2395c51f124SMoriah Waterland 	if ((fp = fopen(path, "w")) == NULL) {
2405c51f124SMoriah Waterland 		progerr(ERR_CANNOT_OPEN_FOR_WRITING, path, strerror(errno));
2415c51f124SMoriah Waterland 		quit(99);
2425c51f124SMoriah Waterland 	}
2435c51f124SMoriah Waterland 
2445c51f124SMoriah Waterland 	/*
2455c51f124SMoriah Waterland 	 * output CLASSES attribute
2465c51f124SMoriah Waterland 	 */
2475c51f124SMoriah Waterland 
2485c51f124SMoriah Waterland 	out = 0;
2495c51f124SMoriah Waterland 	(void) fputs("CLASSES=", fp);
2505c51f124SMoriah Waterland 	if (pclass) {
2515c51f124SMoriah Waterland 		(void) fputs(pclass[0]->name, fp);
2525c51f124SMoriah Waterland 		out++;
2535c51f124SMoriah Waterland 		for (i = 1; pclass[i]; i++) {
2545c51f124SMoriah Waterland 			(void) putc(' ', fp);
2555c51f124SMoriah Waterland 			(void) fputs(pclass[i]->name, fp);
2565c51f124SMoriah Waterland 			out++;
2575c51f124SMoriah Waterland 		}
2585c51f124SMoriah Waterland 	}
2595c51f124SMoriah Waterland 	nc = cl_getn();
2605c51f124SMoriah Waterland 	for (i = 0; i < nc; i++) {
2615c51f124SMoriah Waterland 		int found = 0;
2625c51f124SMoriah Waterland 
2635c51f124SMoriah Waterland 		if (pclass) {
2645c51f124SMoriah Waterland 			int	j;
2655c51f124SMoriah Waterland 
2665c51f124SMoriah Waterland 			for (j = 0; pclass[j]; ++j) {
2675c51f124SMoriah Waterland 				if (cl_nam(i) != NULL &&
2685c51f124SMoriah Waterland 					strcmp(cl_nam(i),
2695c51f124SMoriah Waterland 					pclass[j]->name) == 0) {
2705c51f124SMoriah Waterland 					found++;
2715c51f124SMoriah Waterland 					break;
2725c51f124SMoriah Waterland 				}
2735c51f124SMoriah Waterland 			}
2745c51f124SMoriah Waterland 		}
2755c51f124SMoriah Waterland 		if (!found) {
2765c51f124SMoriah Waterland 			if (out > 0) {
2775c51f124SMoriah Waterland 				(void) putc(' ', fp);
2785c51f124SMoriah Waterland 			}
2795c51f124SMoriah Waterland 			(void) fputs(cl_nam(i), fp);
2805c51f124SMoriah Waterland 			out++;
2815c51f124SMoriah Waterland 		}
2825c51f124SMoriah Waterland 	}
2835c51f124SMoriah Waterland 	(void) putc('\n', fp);
2845c51f124SMoriah Waterland 
2855c51f124SMoriah Waterland 	/*
2865c51f124SMoriah Waterland 	 * NOTE : BASEDIR below is relative to the machine that
2875c51f124SMoriah Waterland 	 * *runs* the package. If there's an install root, this
2885c51f124SMoriah Waterland 	 * is actually the CLIENT_BASEDIR wrt the machine
2895c51f124SMoriah Waterland 	 * doing the pkgadd'ing here. -- JST
2905c51f124SMoriah Waterland 	 */
2915c51f124SMoriah Waterland 
2925c51f124SMoriah Waterland 	if (is_a_basedir()) {
2935c51f124SMoriah Waterland 		static char	*txs1 = "BASEDIR=";
2945c51f124SMoriah Waterland 
2955c51f124SMoriah Waterland 		(void) fputs(txs1, fp);
2965c51f124SMoriah Waterland 		(void) fputs(get_info_basedir(), fp);
2975c51f124SMoriah Waterland 		(void) putc('\n', fp);
2985c51f124SMoriah Waterland 	} else {
2995c51f124SMoriah Waterland 		(void) fputs("BASEDIR=/", fp);
3005c51f124SMoriah Waterland 		(void) putc('\n', fp);
3015c51f124SMoriah Waterland 	}
3025c51f124SMoriah Waterland 
3035c51f124SMoriah Waterland 	/*
3045c51f124SMoriah Waterland 	 * output all other environment attributes except those which
3055c51f124SMoriah Waterland 	 * are relevant only to install.
3065c51f124SMoriah Waterland 	 */
3075c51f124SMoriah Waterland 
3085c51f124SMoriah Waterland 	for (i = 0; environ[i] != (char *)NULL; i++) {
3095c51f124SMoriah Waterland 		char	*ep = environ[i];
3105c51f124SMoriah Waterland 		int	attrPos = -1;
3115c51f124SMoriah Waterland 		int	incr = (ATTRTBL_SIZE >> 1)+1;	/* searches possible */
3125c51f124SMoriah Waterland 		int	pos = ATTRTBL_SIZE >> 1;	/* start in middle */
3135c51f124SMoriah Waterland 		NAMELIST_T	*pp = (NAMELIST_T *)NULL;
3145c51f124SMoriah Waterland 
3155c51f124SMoriah Waterland 		/*
3165c51f124SMoriah Waterland 		 * find this attribute in the table - accept the attribute if it
3175c51f124SMoriah Waterland 		 * is outside of the bounds of the table; otherwise, do a binary
3185c51f124SMoriah Waterland 		 * search looking for this attribute.
3195c51f124SMoriah Waterland 		 */
3205c51f124SMoriah Waterland 
3215c51f124SMoriah Waterland 		if (strncmp(ep, attrTbl[0]._nlName, attrTbl[0]._nlLen) < 0) {
3225c51f124SMoriah Waterland 
3235c51f124SMoriah Waterland 			/* entry < first entry in attribute table */
3245c51f124SMoriah Waterland 
3255c51f124SMoriah Waterland 			echoDebug(DBG_MERGINFO_LESS_THAN, ep,
3265c51f124SMoriah Waterland 				attrTbl[0]._nlName);
3275c51f124SMoriah Waterland 
3285c51f124SMoriah Waterland 		} else if (strncmp(ep, attrTbl[ATTRTBL_SIZE-1]._nlName,
3295c51f124SMoriah Waterland 				attrTbl[ATTRTBL_SIZE-1]._nlLen) > 0) {
3305c51f124SMoriah Waterland 
3315c51f124SMoriah Waterland 			/* entry > last entry in attribute table */
3325c51f124SMoriah Waterland 
3335c51f124SMoriah Waterland 			echoDebug(DBG_MERGINFO_GREATER_THAN, ep,
3345c51f124SMoriah Waterland 				attrTbl[ATTRTBL_SIZE-1]._nlName);
3355c51f124SMoriah Waterland 
3365c51f124SMoriah Waterland 		} else {
3375c51f124SMoriah Waterland 			/* first entry < entry < last entry in table: search */
3385c51f124SMoriah Waterland 
3395c51f124SMoriah Waterland 			echoDebug(DBG_MERGINFO_SEARCHING, ep,
3405c51f124SMoriah Waterland 				attrTbl[0]._nlName,
3415c51f124SMoriah Waterland 				attrTbl[ATTRTBL_SIZE-1]._nlName);
3425c51f124SMoriah Waterland 
3435c51f124SMoriah Waterland 			while (incr > 0) {	/* while possible to divide */
3445c51f124SMoriah Waterland 				int	r;
3455c51f124SMoriah Waterland 
3465c51f124SMoriah Waterland 				pp = &attrTbl[pos];
3475c51f124SMoriah Waterland 
3485c51f124SMoriah Waterland 				/* compare current attr with this table entry */
3495c51f124SMoriah Waterland 				r = strncmp(pp->_nlName, ep, pp->_nlLen);
3505c51f124SMoriah Waterland 
3515c51f124SMoriah Waterland 				/* break out of loop if match */
3525c51f124SMoriah Waterland 				if (r == 0) {
3535c51f124SMoriah Waterland 					/* save location/break if match found */
3545c51f124SMoriah Waterland 					attrPos = pos;
3555c51f124SMoriah Waterland 					break;
3565c51f124SMoriah Waterland 				}
3575c51f124SMoriah Waterland 
3585c51f124SMoriah Waterland 				/* no match search to next/prev half */
3595c51f124SMoriah Waterland 				incr = incr >> 1;
3605c51f124SMoriah Waterland 				pos += (r < 0) ? incr : -incr;
3615c51f124SMoriah Waterland 				continue;
3625c51f124SMoriah Waterland 			}
3635c51f124SMoriah Waterland 		}
3645c51f124SMoriah Waterland 
3655c51f124SMoriah Waterland 		/* handle excluded attribute found */
3665c51f124SMoriah Waterland 
3675c51f124SMoriah Waterland 		if ((attrPos >= 0) && (pp->_nlFlag == FLAG_EXCLUDE)) {
3685c51f124SMoriah Waterland 			/* attribute is excluded */
3695c51f124SMoriah Waterland 			echoDebug(DBG_MERGINFO_EXCLUDING, ep);
3705c51f124SMoriah Waterland 			continue;
3715c51f124SMoriah Waterland 		}
3725c51f124SMoriah Waterland 
3735c51f124SMoriah Waterland 		/* handle fixed attribute found */
3745c51f124SMoriah Waterland 
3755c51f124SMoriah Waterland 		if ((pkginfoFP != (FILE *)NULL) && (attrPos >= 0) &&
3765c51f124SMoriah Waterland 			(pp->_nlFlag == FLAG_IDENTICAL)) {
3775c51f124SMoriah Waterland 			/* attribute must not change */
3785c51f124SMoriah Waterland 
3795c51f124SMoriah Waterland 			char	*src = ep+pp->_nlLen;
3805c51f124SMoriah Waterland 			char	*trg;
3815c51f124SMoriah Waterland 			char	theAttr[PATH_MAX+1];
3825c51f124SMoriah Waterland 
3835c51f124SMoriah Waterland 			/* isolate attribute name only without '=' at end */
3845c51f124SMoriah Waterland 
3855c51f124SMoriah Waterland 			(void) strncpy(theAttr, pp->_nlName, pp->_nlLen-1);
3865c51f124SMoriah Waterland 			theAttr[pp->_nlLen-1] = '\0';
3875c51f124SMoriah Waterland 
3885c51f124SMoriah Waterland 			/* lookup attribute in installed package pkginfo file */
3895c51f124SMoriah Waterland 
3905c51f124SMoriah Waterland 			rewind(pkginfoFP);
3915c51f124SMoriah Waterland 			trg = fpkgparam(pkginfoFP, theAttr);
3925c51f124SMoriah Waterland 
3935c51f124SMoriah Waterland 			echoDebug(DBG_MERGINFO_ATTRCOMP, theAttr,
3945c51f124SMoriah Waterland 				trg ? trg : "");
3955c51f124SMoriah Waterland 
3965c51f124SMoriah Waterland 			/* if target not found attribute is being added */
3975c51f124SMoriah Waterland 
3985c51f124SMoriah Waterland 			if (trg == (char *)NULL) {
3995c51f124SMoriah Waterland 				progerr(ERR_PKGINFO_ATTR_ADDED, pkginst, ep);
4005c51f124SMoriah Waterland 				quit(1);
4015c51f124SMoriah Waterland 			}
4025c51f124SMoriah Waterland 
4035c51f124SMoriah Waterland 			/* error if two values are not the same */
4045c51f124SMoriah Waterland 
4055c51f124SMoriah Waterland 			if (strcmp(src, trg) != 0) {
4065c51f124SMoriah Waterland 				progerr(ERR_PKGINFO_ATTR_CHANGED, pkginst,
4075c51f124SMoriah Waterland 					theAttr, src, trg);
4085c51f124SMoriah Waterland 				quit(1);
4095c51f124SMoriah Waterland 			}
4105c51f124SMoriah Waterland 		}
4115c51f124SMoriah Waterland 
4125c51f124SMoriah Waterland 		/* attribute not excluded/has not changed - process */
4135c51f124SMoriah Waterland 
4145c51f124SMoriah Waterland 		if ((strncmp(ep, "PKGSAV=", 7) == 0)) {
4155c51f124SMoriah Waterland 			(void) fputs("PKGSAV=", fp);
4165c51f124SMoriah Waterland 			(void) fputs(infoloc, fp);
4175c51f124SMoriah Waterland 			(void) putc('/', fp);
4185c51f124SMoriah Waterland 			(void) fputs(pkginst, fp);
4195c51f124SMoriah Waterland 			(void) fputs("/save\n", fp);
4205c51f124SMoriah Waterland 			continue;
4215c51f124SMoriah Waterland 		}
4225c51f124SMoriah Waterland 
4235c51f124SMoriah Waterland 		if ((strncmp(ep, "UPDATE=", 7) == 0) &&
424*4656d474SGarrett D'Amore 		    install_from_pspool != 0 &&
425*4656d474SGarrett D'Amore 		    !isUpdate()) {
4265c51f124SMoriah Waterland 			continue;
4275c51f124SMoriah Waterland 		}
4285c51f124SMoriah Waterland 
4295c51f124SMoriah Waterland 		echoDebug(DBG_MERGINFO_FINAL, ep);
4305c51f124SMoriah Waterland 
4315c51f124SMoriah Waterland 		(void) fputs(ep, fp);
4325c51f124SMoriah Waterland 		(void) putc('\n', fp);
4335c51f124SMoriah Waterland 	}
4345c51f124SMoriah Waterland 
4355c51f124SMoriah Waterland 	(void) fclose(fp);
4365c51f124SMoriah Waterland 	(void) fclose(pkginfoFP);
4375c51f124SMoriah Waterland 
4385c51f124SMoriah Waterland 	/*
4395c51f124SMoriah Waterland 	 * copy all packaging scripts to appropriate directory
4405c51f124SMoriah Waterland 	 */
4415c51f124SMoriah Waterland 
4425c51f124SMoriah Waterland 	i = snprintf(path, PATH_MAX, "%s/install", instdir);
4435c51f124SMoriah Waterland 	if (i > PATH_MAX) {
4445c51f124SMoriah Waterland 		progerr(ERR_CREATE_PATH_2, instdir, "/install");
4455c51f124SMoriah Waterland 		quit(1);
4465c51f124SMoriah Waterland 	}
4475c51f124SMoriah Waterland 
4485c51f124SMoriah Waterland 	if ((pdirfp = opendir(path)) != NULL) {
4495c51f124SMoriah Waterland 		struct dirent	*dp;
4505c51f124SMoriah Waterland 
4515c51f124SMoriah Waterland 		while ((dp = readdir(pdirfp)) != NULL) {
4525c51f124SMoriah Waterland 			if (dp->d_name[0] == '.')
4535c51f124SMoriah Waterland 				continue;
4545c51f124SMoriah Waterland 
4555c51f124SMoriah Waterland 			i = snprintf(path, PATH_MAX, "%s/install/%s",
4565c51f124SMoriah Waterland 					instdir, dp->d_name);
4575c51f124SMoriah Waterland 			if (i > PATH_MAX) {
4585c51f124SMoriah Waterland 				progerr(ERR_CREATE_PATH_3, instdir, "/install/",
4595c51f124SMoriah Waterland 					dp->d_name);
4605c51f124SMoriah Waterland 				quit(1);
4615c51f124SMoriah Waterland 			}
4625c51f124SMoriah Waterland 
4635c51f124SMoriah Waterland 			i = snprintf(temp, PATH_MAX, "%s/%s", pkgbin,
4645c51f124SMoriah Waterland 					dp->d_name);
4655c51f124SMoriah Waterland 			if (i > PATH_MAX) {
4665c51f124SMoriah Waterland 				progerr(ERR_CREATE_PATH_2, pkgbin, dp->d_name);
4675c51f124SMoriah Waterland 				quit(1);
4685c51f124SMoriah Waterland 			}
4695c51f124SMoriah Waterland 
4705c51f124SMoriah Waterland 			if (cppath(MODE_SRC|DIR_DISPLAY, path, temp, 0644)) {
4715c51f124SMoriah Waterland 			    progerr(ERR_CANNOT_COPY, dp->d_name, pkgbin);
4725c51f124SMoriah Waterland 				quit(99);
4735c51f124SMoriah Waterland 			}
4745c51f124SMoriah Waterland 		}
4755c51f124SMoriah Waterland 		(void) closedir(pdirfp);
4765c51f124SMoriah Waterland 	}
4775c51f124SMoriah Waterland 
4785c51f124SMoriah Waterland 	/*
4795c51f124SMoriah Waterland 	 * copy all packaging scripts to the partial spool directory
4805c51f124SMoriah Waterland 	 */
4815c51f124SMoriah Waterland 
4825c51f124SMoriah Waterland 	if (!is_spool_create()) {
4835c51f124SMoriah Waterland 		/* packages are being spooled to ../save/pspool/.. */
4845c51f124SMoriah Waterland 		i = snprintf(path, PATH_MAX, "%s/install", instdir);
4855c51f124SMoriah Waterland 		if (i > PATH_MAX) {
4865c51f124SMoriah Waterland 			progerr(ERR_CREATE_PATH_2, instdir, "/install");
4875c51f124SMoriah Waterland 			quit(1);
4885c51f124SMoriah Waterland 		}
4895c51f124SMoriah Waterland 
490*4656d474SGarrett D'Amore 		if ((pdirfp = opendir(path)) != NULL) {
4915c51f124SMoriah Waterland 			struct dirent	*dp;
4925c51f124SMoriah Waterland 
4935c51f124SMoriah Waterland 
4945c51f124SMoriah Waterland 			while ((dp = readdir(pdirfp)) != NULL) {
4955c51f124SMoriah Waterland 				if (dp->d_name[0] == '.')
4965c51f124SMoriah Waterland 					continue;
4975c51f124SMoriah Waterland 				/*
4985c51f124SMoriah Waterland 				 * Don't copy i.none since if it exists it
4995c51f124SMoriah Waterland 				 * contains Class Archive Format procedure
5005c51f124SMoriah Waterland 				 * for installing archives. Only Directory
5015c51f124SMoriah Waterland 				 * Format packages can exist
5025c51f124SMoriah Waterland 				 * in a global spooled area.
5035c51f124SMoriah Waterland 				 */
5045c51f124SMoriah Waterland 				if (strcmp(dp->d_name, "i.none") == 0)
5055c51f124SMoriah Waterland 					continue;
5065c51f124SMoriah Waterland 
5075c51f124SMoriah Waterland 				i = snprintf(path, PATH_MAX, "%s/install/%s",
5085c51f124SMoriah Waterland 						instdir, dp->d_name);
5095c51f124SMoriah Waterland 
5105c51f124SMoriah Waterland 				if (i > PATH_MAX) {
5115c51f124SMoriah Waterland 					progerr(ERR_CREATE_PATH_3, instdir,
5125c51f124SMoriah Waterland 						"/install/", dp->d_name);
5135c51f124SMoriah Waterland 					quit(1);
5145c51f124SMoriah Waterland 				}
5155c51f124SMoriah Waterland 
5165c51f124SMoriah Waterland 				i = snprintf(temp, PATH_MAX, "%s/install/%s",
5175c51f124SMoriah Waterland 						saveSpoolInstallDir,
5185c51f124SMoriah Waterland 						dp->d_name);
5195c51f124SMoriah Waterland 
5205c51f124SMoriah Waterland 				if (i > PATH_MAX) {
5215c51f124SMoriah Waterland 					progerr(ERR_CREATE_PATH_3,
5225c51f124SMoriah Waterland 						saveSpoolInstallDir,
5235c51f124SMoriah Waterland 						"/install/", dp->d_name);
5245c51f124SMoriah Waterland 					quit(1);
5255c51f124SMoriah Waterland 				}
5265c51f124SMoriah Waterland 
5275c51f124SMoriah Waterland 				if (cppath(MODE_SRC, path, temp, 0644)) {
5285c51f124SMoriah Waterland 					progerr(ERR_CANNOT_COPY, path, temp);
5295c51f124SMoriah Waterland 					(void) closedir(pdirfp);
5305c51f124SMoriah Waterland 					quit(99);
5315c51f124SMoriah Waterland 				}
5325c51f124SMoriah Waterland 			}
5335c51f124SMoriah Waterland 			(void) closedir(pdirfp);
5345c51f124SMoriah Waterland 		}
5355c51f124SMoriah Waterland 
5365c51f124SMoriah Waterland 		/*
5375c51f124SMoriah Waterland 		 * Now copy the original pkginfo and pkgmap files from the
5385c51f124SMoriah Waterland 		 * installing package to the spooled directory.
5395c51f124SMoriah Waterland 		 */
5405c51f124SMoriah Waterland 
5415c51f124SMoriah Waterland 		i = snprintf(path, sizeof (path), "%s/%s", instdir, PKGINFO);
5425c51f124SMoriah Waterland 		if (i > sizeof (path)) {
5435c51f124SMoriah Waterland 			progerr(ERR_CREATE_PATH_2, instdir, PKGINFO);
5445c51f124SMoriah Waterland 			quit(1);
5455c51f124SMoriah Waterland 		}
5465c51f124SMoriah Waterland 
5475c51f124SMoriah Waterland 		i = snprintf(temp, sizeof (temp), "%s/%s",
5485c51f124SMoriah Waterland 				saveSpoolInstallDir, PKGINFO);
5495c51f124SMoriah Waterland 		if (i > sizeof (temp)) {
5505c51f124SMoriah Waterland 			progerr(ERR_CREATE_PATH_2, saveSpoolInstallDir,
5515c51f124SMoriah Waterland 				PKGINFO);
5525c51f124SMoriah Waterland 			quit(1);
5535c51f124SMoriah Waterland 		}
5545c51f124SMoriah Waterland 
5555c51f124SMoriah Waterland 		if (cppath(MODE_SRC, path, temp, 0644)) {
5565c51f124SMoriah Waterland 			progerr(ERR_CANNOT_COPY, path, temp);
5575c51f124SMoriah Waterland 			quit(99);
5585c51f124SMoriah Waterland 		}
5595c51f124SMoriah Waterland 
560*4656d474SGarrett D'Amore 		i = snprintf(path, sizeof (path), "%s/pkgmap", instdir);
561*4656d474SGarrett D'Amore 		if (i > sizeof (path)) {
562*4656d474SGarrett D'Amore 			progerr(ERR_CREATE_PATH_2, instdir, "pkgmap");
563*4656d474SGarrett D'Amore 			quit(1);
564*4656d474SGarrett D'Amore 		}
5655c51f124SMoriah Waterland 
566*4656d474SGarrett D'Amore 		i = snprintf(temp, sizeof (temp), "%s/pkgmap",
567*4656d474SGarrett D'Amore 		    saveSpoolInstallDir);
568*4656d474SGarrett D'Amore 		if (i > sizeof (path)) {
569*4656d474SGarrett D'Amore 			progerr(ERR_CREATE_PATH_2, saveSpoolInstallDir,
570*4656d474SGarrett D'Amore 			    "pkgmap");
571*4656d474SGarrett D'Amore 			quit(1);
572*4656d474SGarrett D'Amore 		}
5735c51f124SMoriah Waterland 
574*4656d474SGarrett D'Amore 		if (cppath(MODE_SRC, path, temp, 0644)) {
575*4656d474SGarrett D'Amore 			progerr(ERR_CANNOT_COPY, path, temp);
576*4656d474SGarrett D'Amore 			quit(99);
5775c51f124SMoriah Waterland 		}
5785c51f124SMoriah Waterland 	}
5795c51f124SMoriah Waterland 
5805c51f124SMoriah Waterland 	/*
5815c51f124SMoriah Waterland 	 * If we are installing from a spool directory
5825c51f124SMoriah Waterland 	 * copy the save directory from it, it may have
5835c51f124SMoriah Waterland 	 * been patched. Duplicate it only if this
5845c51f124SMoriah Waterland 	 * installation isn't an update and is not to
5855c51f124SMoriah Waterland 	 * an alternate root.
5865c51f124SMoriah Waterland 	 */
5875c51f124SMoriah Waterland 	if (strstr(instdir, "pspool") != NULL) {
5885c51f124SMoriah Waterland 		struct stat status;
5895c51f124SMoriah Waterland 
5905c51f124SMoriah Waterland 		i = snprintf(path, sizeof (path), "%s/save", instdir);
5915c51f124SMoriah Waterland 		if (i > sizeof (path)) {
5925c51f124SMoriah Waterland 			progerr(ERR_CREATE_PATH_2, instdir, "save");
5935c51f124SMoriah Waterland 			quit(1);
5945c51f124SMoriah Waterland 		}
5955c51f124SMoriah Waterland 
596*4656d474SGarrett D'Amore 		if ((stat(path, &status) == 0) && (status.st_mode & S_IFDIR)) {
5975c51f124SMoriah Waterland 			i = snprintf(cmd, sizeof (cmd), "cp -pr %s/* %s",
598*4656d474SGarrett D'Amore 			    path, pkgsav);
5995c51f124SMoriah Waterland 			if (i > sizeof (cmd)) {
6005c51f124SMoriah Waterland 				progerr(ERR_SNPRINTF, "cp -pr %s/* %s");
6015c51f124SMoriah Waterland 				quit(1);
6025c51f124SMoriah Waterland 			}
6035c51f124SMoriah Waterland 
6045c51f124SMoriah Waterland 			if (system(cmd)) {
6055c51f124SMoriah Waterland 				progerr(ERR_PKGBINCP, path, pkgsav);
6065c51f124SMoriah Waterland 				quit(99);
6075c51f124SMoriah Waterland 			}
6085c51f124SMoriah Waterland 		}
6095c51f124SMoriah Waterland 	}
6105c51f124SMoriah Waterland }
611