xref: /titanic_44/usr/src/cmd/svr4pkg/libinst/pkgdbmerg.c (revision 5c51f1241dbbdf2656d0e10011981411ed0c9673)
1*5c51f124SMoriah Waterland /*
2*5c51f124SMoriah Waterland  * CDDL HEADER START
3*5c51f124SMoriah Waterland  *
4*5c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
5*5c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
6*5c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
7*5c51f124SMoriah Waterland  *
8*5c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
10*5c51f124SMoriah Waterland  * See the License for the specific language governing permissions
11*5c51f124SMoriah Waterland  * and limitations under the License.
12*5c51f124SMoriah Waterland  *
13*5c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
14*5c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
16*5c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
17*5c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5c51f124SMoriah Waterland  *
19*5c51f124SMoriah Waterland  * CDDL HEADER END
20*5c51f124SMoriah Waterland  */
21*5c51f124SMoriah Waterland 
22*5c51f124SMoriah Waterland /*
23*5c51f124SMoriah Waterland  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*5c51f124SMoriah Waterland  * Use is subject to license terms.
25*5c51f124SMoriah Waterland  */
26*5c51f124SMoriah Waterland 
27*5c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28*5c51f124SMoriah Waterland /* All Rights Reserved */
29*5c51f124SMoriah Waterland 
30*5c51f124SMoriah Waterland 
31*5c51f124SMoriah Waterland #include <stdio.h>
32*5c51f124SMoriah Waterland #include <signal.h>
33*5c51f124SMoriah Waterland #include <string.h>
34*5c51f124SMoriah Waterland #include <errno.h>
35*5c51f124SMoriah Waterland #include <unistd.h>
36*5c51f124SMoriah Waterland #include <stdlib.h>
37*5c51f124SMoriah Waterland #include <assert.h>
38*5c51f124SMoriah Waterland #include <pkgstrct.h>
39*5c51f124SMoriah Waterland #include <sys/stat.h>
40*5c51f124SMoriah Waterland #include <locale.h>
41*5c51f124SMoriah Waterland #include <libintl.h>
42*5c51f124SMoriah Waterland #include <pkginfo.h>
43*5c51f124SMoriah Waterland #include <instzones_api.h>
44*5c51f124SMoriah Waterland #include <pkglib.h>
45*5c51f124SMoriah Waterland #include <libinst.h>
46*5c51f124SMoriah Waterland #include <messages.h>
47*5c51f124SMoriah Waterland 
48*5c51f124SMoriah Waterland /* merg() return codes */
49*5c51f124SMoriah Waterland #define	MRG_SAME	0
50*5c51f124SMoriah Waterland #define	MRG_DIFFERENT	1
51*5c51f124SMoriah Waterland #define	MRG_REPLACE	2
52*5c51f124SMoriah Waterland 
53*5c51f124SMoriah Waterland /* typechg() return codes */
54*5c51f124SMoriah Waterland #define	TYPE_OK		0
55*5c51f124SMoriah Waterland #define	TYPE_WARNING	1
56*5c51f124SMoriah Waterland #define	TYPE_IGNORED	2
57*5c51f124SMoriah Waterland #define	TYPE_REPLACE	3
58*5c51f124SMoriah Waterland #define	TYPE_FATAL	4
59*5c51f124SMoriah Waterland 
60*5c51f124SMoriah Waterland /* message pool */
61*5c51f124SMoriah Waterland #define	ERR_OUTPUT	"unable to update package database"
62*5c51f124SMoriah Waterland #define	ERR_PINFO	"missing pinfo structure for <%s>"
63*5c51f124SMoriah Waterland #define	INFO_PROCESS	"   %2ld%% of information processed; continuing ..."
64*5c51f124SMoriah Waterland 
65*5c51f124SMoriah Waterland #define	WRN_NOTFILE	"WARNING: %s <no longer a regular file>"
66*5c51f124SMoriah Waterland #define	WRN_NOTSYMLN	"WARNING: %s <no longer a symbolic link>"
67*5c51f124SMoriah Waterland #define	WRN_NOTLINK	"WARNING: %s <no longer a linked file>"
68*5c51f124SMoriah Waterland #define	WRN_NOTDIR	"WARNING: %s <no longer a directory>"
69*5c51f124SMoriah Waterland #define	WRN_NOTCHAR	"WARNING: %s <no longer a character special device>"
70*5c51f124SMoriah Waterland #define	WRN_NOTBLOCK	"WARNING: %s <no longer a block special device>"
71*5c51f124SMoriah Waterland #define	WRN_NOTPIPE	"WARNING: %s <no longer a named pipe>"
72*5c51f124SMoriah Waterland #define	WRN_TOEXCL	"WARNING: cannot convert %s to an exclusive directory."
73*5c51f124SMoriah Waterland #define	WRN_ODDVERIFY	"WARNING: quick verify disabled for class %s."
74*5c51f124SMoriah Waterland 
75*5c51f124SMoriah Waterland #define	MSG_TYPIGN	"Object type change ignored."
76*5c51f124SMoriah Waterland #define	MSG_TYPE_ERR	"Package attempts fatal object type change."
77*5c51f124SMoriah Waterland 
78*5c51f124SMoriah Waterland extern char	*pkginst;
79*5c51f124SMoriah Waterland extern int	nosetuid, nocnflct, otherstoo;
80*5c51f124SMoriah Waterland 
81*5c51f124SMoriah Waterland /* pkgobjmap.c */
82*5c51f124SMoriah Waterland extern int	cp_cfent(struct cfent *cf_ent, struct cfextra *el_ent);
83*5c51f124SMoriah Waterland 
84*5c51f124SMoriah Waterland /* setlist.c */
85*5c51f124SMoriah Waterland extern void	cl_def_dverify(int idx);
86*5c51f124SMoriah Waterland 
87*5c51f124SMoriah Waterland char dbst = '\0';	/* usually set by installf() or removef() */
88*5c51f124SMoriah Waterland 
89*5c51f124SMoriah Waterland int files_installed(void);	/* return number of files installed. */
90*5c51f124SMoriah Waterland 
91*5c51f124SMoriah Waterland static int	errflg = 0;
92*5c51f124SMoriah Waterland static int	eptnum;
93*5c51f124SMoriah Waterland static VFP_T	*fpvfp = {(VFP_T *)NULL};
94*5c51f124SMoriah Waterland static long	sizetot;
95*5c51f124SMoriah Waterland static int	seconds;
96*5c51f124SMoriah Waterland static int	installed;	/* # of files, already properly installed. */
97*5c51f124SMoriah Waterland static struct	pinfo	*pkgpinfo = (struct pinfo *)0;
98*5c51f124SMoriah Waterland 
99*5c51f124SMoriah Waterland static int	is_setuid(struct cfent *ent);
100*5c51f124SMoriah Waterland static int	is_setgid(struct cfent *ent);
101*5c51f124SMoriah Waterland static int	merg(struct cfextra *el_ent, struct cfent *cf_ent);
102*5c51f124SMoriah Waterland static int	do_like_ent(VFP_T *vfpo, struct cfextra *el_ent,
103*5c51f124SMoriah Waterland 		    struct cfent *cf_ent, int ctrl);
104*5c51f124SMoriah Waterland static int	do_new_ent(VFP_T *vfpo, struct cfextra *el_ent, int ctrl);
105*5c51f124SMoriah Waterland static int	typechg(struct cfent *el_ent, struct cfent *cf_ent,
106*5c51f124SMoriah Waterland 		    struct mergstat *mstat);
107*5c51f124SMoriah Waterland 
108*5c51f124SMoriah Waterland static void	set_change(struct cfextra *el_ent);
109*5c51f124SMoriah Waterland static void	chgclass(struct cfent *cf_ent, struct pinfo *pinfo);
110*5c51f124SMoriah Waterland static void	output(VFP_T *vfpo, struct cfent *ent, struct pinfo *pinfo);
111*5c51f124SMoriah Waterland 
112*5c51f124SMoriah Waterland /* ARGSUNUSED */
113*5c51f124SMoriah Waterland void
114*5c51f124SMoriah Waterland notice(int n)
115*5c51f124SMoriah Waterland {
116*5c51f124SMoriah Waterland #ifdef lint
117*5c51f124SMoriah Waterland 	int i = n;
118*5c51f124SMoriah Waterland 	n = i;
119*5c51f124SMoriah Waterland #endif	/* lint */
120*5c51f124SMoriah Waterland 	(void) signal(SIGALRM, SIG_IGN);
121*5c51f124SMoriah Waterland 	if (sizetot != 0) {
122*5c51f124SMoriah Waterland 		echo(gettext(INFO_PROCESS),
123*5c51f124SMoriah Waterland 			vfpGetBytesRemaining(fpvfp) * 100L / sizetot);
124*5c51f124SMoriah Waterland 	}
125*5c51f124SMoriah Waterland 	(void) signal(SIGALRM, notice);
126*5c51f124SMoriah Waterland 	(void) alarm(seconds);
127*5c51f124SMoriah Waterland }
128*5c51f124SMoriah Waterland 
129*5c51f124SMoriah Waterland /* ARGSUSED */
130*5c51f124SMoriah Waterland 
131*5c51f124SMoriah Waterland /*
132*5c51f124SMoriah Waterland  * This scans the extlist (pkgmap) and the package database to the end,
133*5c51f124SMoriah Waterland  * copying out the merged contents to the file at tmpfp. It updates the mergstat
134*5c51f124SMoriah Waterland  * structures and deals with administrative defaults regarding setuid and
135*5c51f124SMoriah Waterland  * conflict.
136*5c51f124SMoriah Waterland  *
137*5c51f124SMoriah Waterland  * Since both the extlist and the package database entries are in numerical
138*5c51f124SMoriah Waterland  * order, they both scan unidirectionally. If the entry in the extlist is
139*5c51f124SMoriah Waterland  * found in the package database (by pathname) then do_like_ent() is called.
140*5c51f124SMoriah Waterland  * If the extlist entry is not found in the package database then
141*5c51f124SMoriah Waterland  * do_new_ent() is called. srchcfile() is responsible for copying out
142*5c51f124SMoriah Waterland  * non-matching package database entries. At package database EOF, the
143*5c51f124SMoriah Waterland  * eocontents flag is set and the rest of the extlist are assumed to be new
144*5c51f124SMoriah Waterland  * entries. At the end of the extlist, the eoextlist flag is set and the
145*5c51f124SMoriah Waterland  * remaining package database ends up copied out by srchcfile().
146*5c51f124SMoriah Waterland  */
147*5c51f124SMoriah Waterland 
148*5c51f124SMoriah Waterland int
149*5c51f124SMoriah Waterland pkgdbmerg(VFP_T *mapvfp, VFP_T *tmpvfp, struct cfextra **extlist, int notify)
150*5c51f124SMoriah Waterland {
151*5c51f124SMoriah Waterland 	static	struct	cfent	cf_ent;	/* scratch area */
152*5c51f124SMoriah Waterland 	struct	cfextra	*el_ent;	/* extlist entry under review */
153*5c51f124SMoriah Waterland 	int	eocontents = 0;
154*5c51f124SMoriah Waterland 	int	eoextlist = 0;
155*5c51f124SMoriah Waterland 	int	n;
156*5c51f124SMoriah Waterland 	int	changed;
157*5c51f124SMoriah Waterland 	int	assume_ok = 0;
158*5c51f124SMoriah Waterland 
159*5c51f124SMoriah Waterland 	cf_ent.pinfo = (NULL);
160*5c51f124SMoriah Waterland 	errflg = 0;
161*5c51f124SMoriah Waterland 	eptnum = 0;
162*5c51f124SMoriah Waterland 	installed = changed = 0;
163*5c51f124SMoriah Waterland 
164*5c51f124SMoriah Waterland 	fpvfp = mapvfp;	/* for notice function ...arg! */
165*5c51f124SMoriah Waterland 
166*5c51f124SMoriah Waterland 	if (notify) {
167*5c51f124SMoriah Waterland 		seconds = notify;
168*5c51f124SMoriah Waterland 		(void) signal(SIGALRM, notice);
169*5c51f124SMoriah Waterland 		(void) alarm(seconds);
170*5c51f124SMoriah Waterland 	}
171*5c51f124SMoriah Waterland 
172*5c51f124SMoriah Waterland 	(void) sighold(SIGALRM);
173*5c51f124SMoriah Waterland 
174*5c51f124SMoriah Waterland 	sizetot = (((ptrdiff_t)(mapvfp->_vfpEnd)) -
175*5c51f124SMoriah Waterland 				((ptrdiff_t)(mapvfp->_vfpStart)));
176*5c51f124SMoriah Waterland 	vfpRewind(mapvfp);
177*5c51f124SMoriah Waterland 	vfpRewind(tmpvfp);
178*5c51f124SMoriah Waterland 
179*5c51f124SMoriah Waterland 	(void) sigrelse(SIGALRM);
180*5c51f124SMoriah Waterland 
181*5c51f124SMoriah Waterland 	do {
182*5c51f124SMoriah Waterland 		(void) sighold(SIGALRM);
183*5c51f124SMoriah Waterland 
184*5c51f124SMoriah Waterland 		/*
185*5c51f124SMoriah Waterland 		 * If there's an entry in the extlist at this position,
186*5c51f124SMoriah Waterland 		 * process that entry.
187*5c51f124SMoriah Waterland 		 */
188*5c51f124SMoriah Waterland 		if (!eoextlist && (el_ent = extlist[eptnum])) {
189*5c51f124SMoriah Waterland 
190*5c51f124SMoriah Waterland 			/* Metafiles don't get merged. */
191*5c51f124SMoriah Waterland 			if ((el_ent->cf_ent.ftype == 'i') ||
192*5c51f124SMoriah Waterland 				(el_ent->cf_ent.ftype == 'n')) {
193*5c51f124SMoriah Waterland 				continue;
194*5c51f124SMoriah Waterland 			}
195*5c51f124SMoriah Waterland 
196*5c51f124SMoriah Waterland 			/*
197*5c51f124SMoriah Waterland 			 * Copy cfextra structure for duplicated paths.
198*5c51f124SMoriah Waterland 			 * This is not just an optimization, it is
199*5c51f124SMoriah Waterland 			 * necessary for correct operation of algorithm.
200*5c51f124SMoriah Waterland 			 */
201*5c51f124SMoriah Waterland 			if ((eptnum > 0) && (strncmp(el_ent->cf_ent.path,
202*5c51f124SMoriah Waterland 			    extlist[eptnum-1]->cf_ent.path, PATH_MAX) == 0)) {
203*5c51f124SMoriah Waterland 				memcpy(extlist[eptnum], extlist[eptnum-1],
204*5c51f124SMoriah Waterland 				    sizeof (struct cfextra));
205*5c51f124SMoriah Waterland 				continue;
206*5c51f124SMoriah Waterland 			}
207*5c51f124SMoriah Waterland 
208*5c51f124SMoriah Waterland 			/*
209*5c51f124SMoriah Waterland 			 * Normally dbst comes to us from installf() or
210*5c51f124SMoriah Waterland 			 * removef() in order to specify their special
211*5c51f124SMoriah Waterland 			 * database status codes. They cannot implement a
212*5c51f124SMoriah Waterland 			 * quick verify (it just doesn't make sense). For
213*5c51f124SMoriah Waterland 			 * that reason, we can test to see if we already have
214*5c51f124SMoriah Waterland 			 * a special database status. If we don't (it's from
215*5c51f124SMoriah Waterland 			 * pkgadd) then we can test to see if this is calling
216*5c51f124SMoriah Waterland 			 * for a quick verify wherein we assume the install
217*5c51f124SMoriah Waterland 			 * will work and fix it if it doesn't. In that case
218*5c51f124SMoriah Waterland 			 * we set our own dbst to be ENTRY_OK.
219*5c51f124SMoriah Waterland 			 */
220*5c51f124SMoriah Waterland 			if (dbst == '\0') {
221*5c51f124SMoriah Waterland 				if (cl_dvfy(el_ent->cf_ent.pkg_class_idx) ==
222*5c51f124SMoriah Waterland 				    QKVERIFY) {
223*5c51f124SMoriah Waterland 					assume_ok = 1;
224*5c51f124SMoriah Waterland 				}
225*5c51f124SMoriah Waterland 			} else {
226*5c51f124SMoriah Waterland 				/*
227*5c51f124SMoriah Waterland 				 * If we DO end up with an installf/quick
228*5c51f124SMoriah Waterland 				 * verify combination, we fix that by simply
229*5c51f124SMoriah Waterland 				 * denying the quick verify for this class.
230*5c51f124SMoriah Waterland 				 * This forces everything to come out alright
231*5c51f124SMoriah Waterland 				 * by forcing the standard assumptions as
232*5c51f124SMoriah Waterland 				 * regards package database for the rest of
233*5c51f124SMoriah Waterland 				 * the load.
234*5c51f124SMoriah Waterland 				 */
235*5c51f124SMoriah Waterland 				if (cl_dvfy(el_ent->cf_ent.pkg_class_idx) ==
236*5c51f124SMoriah Waterland 				    QKVERIFY) {
237*5c51f124SMoriah Waterland 					logerr(gettext(WRN_ODDVERIFY),
238*5c51f124SMoriah Waterland 					    cl_nam(
239*5c51f124SMoriah Waterland 					    el_ent->cf_ent.pkg_class_idx));
240*5c51f124SMoriah Waterland 					/*
241*5c51f124SMoriah Waterland 					 * Set destination verification to
242*5c51f124SMoriah Waterland 					 * default.
243*5c51f124SMoriah Waterland 					 */
244*5c51f124SMoriah Waterland 					cl_def_dverify(
245*5c51f124SMoriah Waterland 					    el_ent->cf_ent.pkg_class_idx);
246*5c51f124SMoriah Waterland 				}
247*5c51f124SMoriah Waterland 			}
248*5c51f124SMoriah Waterland 
249*5c51f124SMoriah Waterland 			/*
250*5c51f124SMoriah Waterland 			 * Comply with administrative requirements regarding
251*5c51f124SMoriah Waterland 			 * setuid/setgid processes.
252*5c51f124SMoriah Waterland 			 */
253*5c51f124SMoriah Waterland 			if (is_setuid(&(el_ent->cf_ent))) {
254*5c51f124SMoriah Waterland 				el_ent->mstat.setuid = 1;
255*5c51f124SMoriah Waterland 			}
256*5c51f124SMoriah Waterland 			if (is_setgid(&(el_ent->cf_ent))) {
257*5c51f124SMoriah Waterland 				el_ent->mstat.setgid = 1;
258*5c51f124SMoriah Waterland 			}
259*5c51f124SMoriah Waterland 
260*5c51f124SMoriah Waterland 			/*
261*5c51f124SMoriah Waterland 			 * If setuid/setgid processes are not allowed, reset
262*5c51f124SMoriah Waterland 			 * those bits.
263*5c51f124SMoriah Waterland 			 */
264*5c51f124SMoriah Waterland 			if (nosetuid && (el_ent->mstat.setgid ||
265*5c51f124SMoriah Waterland 			    el_ent->mstat.setuid)) {
266*5c51f124SMoriah Waterland 				el_ent->cf_ent.ainfo.mode &=
267*5c51f124SMoriah Waterland 				    ~(S_ISUID | S_ISGID);
268*5c51f124SMoriah Waterland 			}
269*5c51f124SMoriah Waterland 		} else {
270*5c51f124SMoriah Waterland 			eoextlist = 1;	/* end of extlist[] */
271*5c51f124SMoriah Waterland 		}
272*5c51f124SMoriah Waterland 
273*5c51f124SMoriah Waterland 		/*
274*5c51f124SMoriah Waterland 		 * If we're not at the end of the package database, get the
275*5c51f124SMoriah Waterland 		 * next entry for comparison.
276*5c51f124SMoriah Waterland 		 */
277*5c51f124SMoriah Waterland 		if (!eocontents) {
278*5c51f124SMoriah Waterland 
279*5c51f124SMoriah Waterland 			/* Search package database for this entry. */
280*5c51f124SMoriah Waterland 			n = srchcfile(&cf_ent, el_ent ?
281*5c51f124SMoriah Waterland 				el_ent->cf_ent.path : NULL,
282*5c51f124SMoriah Waterland 				mapvfp, tmpvfp);
283*5c51f124SMoriah Waterland 
284*5c51f124SMoriah Waterland 			/*
285*5c51f124SMoriah Waterland 			 * If there was an error, note it and return an error
286*5c51f124SMoriah Waterland 			 * flag.
287*5c51f124SMoriah Waterland 			 */
288*5c51f124SMoriah Waterland 			if (n < 0) {
289*5c51f124SMoriah Waterland 				char	*errstr = getErrstr();
290*5c51f124SMoriah Waterland 				logerr(gettext(
291*5c51f124SMoriah Waterland 				    "bad entry read from contents file"));
292*5c51f124SMoriah Waterland 				logerr(gettext("- pathname: %s"),
293*5c51f124SMoriah Waterland 				    (cf_ent.path && *cf_ent.path) ?
294*5c51f124SMoriah Waterland 				    cf_ent.path : "Unknown");
295*5c51f124SMoriah Waterland 				logerr(gettext("- problem: %s"),
296*5c51f124SMoriah Waterland 				    (errstr && *errstr) ? errstr : "Unknown");
297*5c51f124SMoriah Waterland 				return (-1);
298*5c51f124SMoriah Waterland 			/*
299*5c51f124SMoriah Waterland 			 * If there was a match, then merge them into a
300*5c51f124SMoriah Waterland 			 * single entry.
301*5c51f124SMoriah Waterland 			 */
302*5c51f124SMoriah Waterland 			} else if (n == 1) {
303*5c51f124SMoriah Waterland 				/*
304*5c51f124SMoriah Waterland 				 * If this package is overwriting a setuid or
305*5c51f124SMoriah Waterland 				 * setgid process, set the status bits so we
306*5c51f124SMoriah Waterland 				 * can inform the administrator.
307*5c51f124SMoriah Waterland 				 */
308*5c51f124SMoriah Waterland 				if (is_setuid(&cf_ent)) {
309*5c51f124SMoriah Waterland 					el_ent->mstat.osetuid = 1;
310*5c51f124SMoriah Waterland 				}
311*5c51f124SMoriah Waterland 
312*5c51f124SMoriah Waterland 				if (is_setgid(&cf_ent)) {
313*5c51f124SMoriah Waterland 					el_ent->mstat.osetgid = 1;
314*5c51f124SMoriah Waterland 				}
315*5c51f124SMoriah Waterland 				/*
316*5c51f124SMoriah Waterland 				 * Detect if a symlink has changed to directory
317*5c51f124SMoriah Waterland 				 * If so mark all the files/dir supposed to be
318*5c51f124SMoriah Waterland 				 * iniside this dir, so that they are not miss
319*5c51f124SMoriah Waterland 				 * understood by do_new_ent later as already
320*5c51f124SMoriah Waterland 				 * installed.
321*5c51f124SMoriah Waterland 				 */
322*5c51f124SMoriah Waterland 				if ((!eoextlist) && (cf_ent.ftype == 's') &&
323*5c51f124SMoriah Waterland 				    (el_ent->cf_ent.ftype == 'd')) {
324*5c51f124SMoriah Waterland 					int i;
325*5c51f124SMoriah Waterland 					int plen = strlen(el_ent->cf_ent.path);
326*5c51f124SMoriah Waterland 					for (i = eptnum + 1; extlist[i]; i++) {
327*5c51f124SMoriah Waterland 						if (strncmp(el_ent->cf_ent.path,
328*5c51f124SMoriah Waterland 						    extlist[i]->cf_ent.path,
329*5c51f124SMoriah Waterland 						    plen) != 0)
330*5c51f124SMoriah Waterland 							break;
331*5c51f124SMoriah Waterland 						extlist[i]->mstat.parentsyml2dir
332*5c51f124SMoriah Waterland 						    = 1;
333*5c51f124SMoriah Waterland 					}
334*5c51f124SMoriah Waterland 				}
335*5c51f124SMoriah Waterland 
336*5c51f124SMoriah Waterland 				if (do_like_ent(tmpvfp, el_ent, &cf_ent,
337*5c51f124SMoriah Waterland 				    assume_ok)) {
338*5c51f124SMoriah Waterland 					changed++;
339*5c51f124SMoriah Waterland 				}
340*5c51f124SMoriah Waterland 
341*5c51f124SMoriah Waterland 			/*
342*5c51f124SMoriah Waterland 			 * If the alphabetical position in the package
343*5c51f124SMoriah Waterland 			 * database is unfilled, then this will be a new
344*5c51f124SMoriah Waterland 			 * entry. If n == 0, then we're also at the end of
345*5c51f124SMoriah Waterland 			 * the contents file.
346*5c51f124SMoriah Waterland 			 */
347*5c51f124SMoriah Waterland 			} else {
348*5c51f124SMoriah Waterland 				if (n == 0) {
349*5c51f124SMoriah Waterland 					eocontents++;
350*5c51f124SMoriah Waterland 				}
351*5c51f124SMoriah Waterland 
352*5c51f124SMoriah Waterland 				/*
353*5c51f124SMoriah Waterland 				 * If there is an extlist entry in the
354*5c51f124SMoriah Waterland 				 * hopper, insert it at the end of the
355*5c51f124SMoriah Waterland 				 * package database.
356*5c51f124SMoriah Waterland 				 */
357*5c51f124SMoriah Waterland 				if (!eoextlist) {
358*5c51f124SMoriah Waterland 					if (do_new_ent(tmpvfp, el_ent,
359*5c51f124SMoriah Waterland 					    assume_ok)) {
360*5c51f124SMoriah Waterland 						changed++;
361*5c51f124SMoriah Waterland 					}
362*5c51f124SMoriah Waterland 				}
363*5c51f124SMoriah Waterland 			}
364*5c51f124SMoriah Waterland 		/*
365*5c51f124SMoriah Waterland 		 * We have passed the last entry in the package database,
366*5c51f124SMoriah Waterland 		 * tagging these extlist entries onto the end.
367*5c51f124SMoriah Waterland 		 */
368*5c51f124SMoriah Waterland 		} else if (!eoextlist) {
369*5c51f124SMoriah Waterland 			if (do_new_ent(tmpvfp, el_ent, assume_ok)) {
370*5c51f124SMoriah Waterland 				changed++;
371*5c51f124SMoriah Waterland 			}
372*5c51f124SMoriah Waterland 		}
373*5c51f124SMoriah Waterland 		/* Else, we'll drop out of the loop. */
374*5c51f124SMoriah Waterland 
375*5c51f124SMoriah Waterland 		(void) sigrelse(SIGALRM);
376*5c51f124SMoriah Waterland 	} while (eptnum++, (!eocontents || !eoextlist));
377*5c51f124SMoriah Waterland 
378*5c51f124SMoriah Waterland 	if (notify) {
379*5c51f124SMoriah Waterland 		(void) alarm(0);
380*5c51f124SMoriah Waterland 		(void) signal(SIGALRM, SIG_IGN);
381*5c51f124SMoriah Waterland 	}
382*5c51f124SMoriah Waterland 
383*5c51f124SMoriah Waterland 	return (errflg ? -1 : changed);
384*5c51f124SMoriah Waterland }
385*5c51f124SMoriah Waterland 
386*5c51f124SMoriah Waterland /*
387*5c51f124SMoriah Waterland  * Merge a new entry with an installed package object of the same name and
388*5c51f124SMoriah Waterland  * insert that object into the package database. Obey administrative defaults
389*5c51f124SMoriah Waterland  * as regards conflicting files.
390*5c51f124SMoriah Waterland  */
391*5c51f124SMoriah Waterland 
392*5c51f124SMoriah Waterland static int
393*5c51f124SMoriah Waterland do_like_ent(VFP_T *vfpo, struct cfextra *el_ent, struct cfent *cf_ent, int ctrl)
394*5c51f124SMoriah Waterland {
395*5c51f124SMoriah Waterland 	int	stflag, ignore, changed, mrg_result;
396*5c51f124SMoriah Waterland 
397*5c51f124SMoriah Waterland 	ignore = changed = 0;
398*5c51f124SMoriah Waterland 
399*5c51f124SMoriah Waterland 	/*
400*5c51f124SMoriah Waterland 	 * Construct the record defining the current package. If there are
401*5c51f124SMoriah Waterland 	 * other packages involved, this will be appended to the existing
402*5c51f124SMoriah Waterland 	 * list. If this is an update of the same package, it will get merged
403*5c51f124SMoriah Waterland 	 * with the existing record. If this is a preloaded record (like from
404*5c51f124SMoriah Waterland 	 * a dryrun file), it will keep it's current pinfo pointer and will
405*5c51f124SMoriah Waterland 	 * pass it on to the record from the contents file - because on the
406*5c51f124SMoriah Waterland 	 * final continuation, the contents file will be wrong.
407*5c51f124SMoriah Waterland 	 */
408*5c51f124SMoriah Waterland 	if (el_ent->mstat.preloaded) {
409*5c51f124SMoriah Waterland 		struct pinfo *pkginfo;
410*5c51f124SMoriah Waterland 
411*5c51f124SMoriah Waterland 		/* Contents file is not to be trusted for this list. */
412*5c51f124SMoriah Waterland 		pkginfo = cf_ent->pinfo;
413*5c51f124SMoriah Waterland 
414*5c51f124SMoriah Waterland 		/* Free the potentially bogus list. */
415*5c51f124SMoriah Waterland 		while (pkginfo) {
416*5c51f124SMoriah Waterland 			struct pinfo *next;
417*5c51f124SMoriah Waterland 			next = pkginfo->next;
418*5c51f124SMoriah Waterland 			free(pkginfo);
419*5c51f124SMoriah Waterland 			pkginfo = next;
420*5c51f124SMoriah Waterland 		}
421*5c51f124SMoriah Waterland 
422*5c51f124SMoriah Waterland 		cf_ent->pinfo = el_ent->cf_ent.pinfo;
423*5c51f124SMoriah Waterland 	}
424*5c51f124SMoriah Waterland 
425*5c51f124SMoriah Waterland 	pkgpinfo = eptstat(cf_ent, pkginst, DUP_ENTRY);
426*5c51f124SMoriah Waterland 
427*5c51f124SMoriah Waterland 	stflag = pkgpinfo->status;
428*5c51f124SMoriah Waterland 
429*5c51f124SMoriah Waterland 	if (otherstoo)
430*5c51f124SMoriah Waterland 		el_ent->mstat.shared = 1;
431*5c51f124SMoriah Waterland 
432*5c51f124SMoriah Waterland 	/* If it's marked for erasure, make it official */
433*5c51f124SMoriah Waterland 	if (el_ent->cf_ent.ftype == RM_RDY) {
434*5c51f124SMoriah Waterland 		if (!errflg) {
435*5c51f124SMoriah Waterland 			pkgpinfo = eptstat(cf_ent, pkginst, RM_RDY);
436*5c51f124SMoriah Waterland 
437*5c51f124SMoriah Waterland 			/*
438*5c51f124SMoriah Waterland 			 * Get copy of status character in case the object is
439*5c51f124SMoriah Waterland 			 * "shared" by a server, in which case we need to
440*5c51f124SMoriah Waterland 			 * maintain the shared status after the entry is
441*5c51f124SMoriah Waterland 			 * written to the package database with RM_RDY
442*5c51f124SMoriah Waterland 			 * status. This is needed to support the `removef'
443*5c51f124SMoriah Waterland 			 * command.
444*5c51f124SMoriah Waterland 			 */
445*5c51f124SMoriah Waterland 			stflag = pkgpinfo->status;
446*5c51f124SMoriah Waterland 			pkgpinfo->status = RM_RDY;
447*5c51f124SMoriah Waterland 
448*5c51f124SMoriah Waterland 			if (putcvfpfile(cf_ent, vfpo)) {
449*5c51f124SMoriah Waterland 				progerr(gettext(ERR_OUTPUT));
450*5c51f124SMoriah Waterland 				quit(99);
451*5c51f124SMoriah Waterland 			}
452*5c51f124SMoriah Waterland 
453*5c51f124SMoriah Waterland 			/*
454*5c51f124SMoriah Waterland 			 * If object is provided by a server, allocate an
455*5c51f124SMoriah Waterland 			 * info block and set the status to indicate this.
456*5c51f124SMoriah Waterland 			 * This is needed to support the `removef' command.
457*5c51f124SMoriah Waterland 			 */
458*5c51f124SMoriah Waterland 			if (stflag == SERVED_FILE) {
459*5c51f124SMoriah Waterland 				el_ent->cf_ent.pinfo =
460*5c51f124SMoriah Waterland 				    (struct pinfo *)calloc(1,
461*5c51f124SMoriah Waterland 				    sizeof (struct pinfo));
462*5c51f124SMoriah Waterland 				el_ent->cf_ent.pinfo->next = NULL;
463*5c51f124SMoriah Waterland 				el_ent->cf_ent.pinfo->status = SERVED_FILE;
464*5c51f124SMoriah Waterland 			}
465*5c51f124SMoriah Waterland 		}
466*5c51f124SMoriah Waterland 		return (1);
467*5c51f124SMoriah Waterland 	}
468*5c51f124SMoriah Waterland 
469*5c51f124SMoriah Waterland 	/*
470*5c51f124SMoriah Waterland 	 * If there is no package associated with it, there's something
471*5c51f124SMoriah Waterland 	 * very wrong.
472*5c51f124SMoriah Waterland 	 */
473*5c51f124SMoriah Waterland 	if (!pkgpinfo) {
474*5c51f124SMoriah Waterland 		progerr(gettext(ERR_PINFO), cf_ent->path);
475*5c51f124SMoriah Waterland 		quit(99);
476*5c51f124SMoriah Waterland 	}
477*5c51f124SMoriah Waterland 
478*5c51f124SMoriah Waterland 	/*
479*5c51f124SMoriah Waterland 	 * Do not allow installation if nocnflct is set and other packages
480*5c51f124SMoriah Waterland 	 * reference this pathname. The cp_cfent() function below writes the
481*5c51f124SMoriah Waterland 	 * information from the installed file over the new entry, so the
482*5c51f124SMoriah Waterland 	 * package database will be unchanged.
483*5c51f124SMoriah Waterland 	 *
484*5c51f124SMoriah Waterland 	 * By the way, ftype "e" is often shared and that's OK, so ftype
485*5c51f124SMoriah Waterland 	 * "e" doesn't count here.
486*5c51f124SMoriah Waterland 	 */
487*5c51f124SMoriah Waterland 	if ((nocnflct && el_ent->mstat.shared && el_ent->cf_ent.ftype != 'e')) {
488*5c51f124SMoriah Waterland 		/*
489*5c51f124SMoriah Waterland 		 * First set the attrchg and contchg entries for proper
490*5c51f124SMoriah Waterland 		 * messaging in the install phase.
491*5c51f124SMoriah Waterland 		 */
492*5c51f124SMoriah Waterland 		set_change(el_ent);
493*5c51f124SMoriah Waterland 
494*5c51f124SMoriah Waterland 		/*
495*5c51f124SMoriah Waterland 		 * Now overwrite the new entry with the entry for the
496*5c51f124SMoriah Waterland 		 * currently installed object.
497*5c51f124SMoriah Waterland 		 */
498*5c51f124SMoriah Waterland 		if (cp_cfent(cf_ent, el_ent) == 0)
499*5c51f124SMoriah Waterland 			quit(99);
500*5c51f124SMoriah Waterland 
501*5c51f124SMoriah Waterland 		ignore++;
502*5c51f124SMoriah Waterland 	} else {
503*5c51f124SMoriah Waterland 		mrg_result = merg(el_ent, cf_ent);
504*5c51f124SMoriah Waterland 
505*5c51f124SMoriah Waterland 		switch (mrg_result) {
506*5c51f124SMoriah Waterland 		    case MRG_SAME:
507*5c51f124SMoriah Waterland 			break;
508*5c51f124SMoriah Waterland 
509*5c51f124SMoriah Waterland 		    case MRG_DIFFERENT:
510*5c51f124SMoriah Waterland 			changed++;
511*5c51f124SMoriah Waterland 			break;
512*5c51f124SMoriah Waterland 
513*5c51f124SMoriah Waterland 		    case MRG_REPLACE:
514*5c51f124SMoriah Waterland 			/*
515*5c51f124SMoriah Waterland 			 * We'll pick one or the other later. For now, cf_ent
516*5c51f124SMoriah Waterland 			 * will have the fault value and el_ent will retain
517*5c51f124SMoriah Waterland 			 * the other value. This is the only state that allows
518*5c51f124SMoriah Waterland 			 * the database and the pkgmap to differ.
519*5c51f124SMoriah Waterland 			 */
520*5c51f124SMoriah Waterland 
521*5c51f124SMoriah Waterland 			el_ent->mstat.contchg = 1;	/* subject to change */
522*5c51f124SMoriah Waterland 			ignore++;
523*5c51f124SMoriah Waterland 			break;
524*5c51f124SMoriah Waterland 
525*5c51f124SMoriah Waterland 		    default:
526*5c51f124SMoriah Waterland 			break;
527*5c51f124SMoriah Waterland 		}
528*5c51f124SMoriah Waterland 	}
529*5c51f124SMoriah Waterland 
530*5c51f124SMoriah Waterland 	/* el_ent structure now contains updated entry */
531*5c51f124SMoriah Waterland 	if (!el_ent->mstat.contchg && !ignore) {
532*5c51f124SMoriah Waterland 		/*
533*5c51f124SMoriah Waterland 		 * We know the DB entry matches the pkgmap, so now we need to
534*5c51f124SMoriah Waterland 		 * see if the actual object matches the pkgmap.
535*5c51f124SMoriah Waterland 		 */
536*5c51f124SMoriah Waterland 		set_change(el_ent);
537*5c51f124SMoriah Waterland 	}
538*5c51f124SMoriah Waterland 
539*5c51f124SMoriah Waterland 	if (!errflg) {
540*5c51f124SMoriah Waterland 		if (ctrl == 1) {	/* quick verify assumes OK */
541*5c51f124SMoriah Waterland 			/*
542*5c51f124SMoriah Waterland 			 * The pkgpinfo entry is already correctly
543*5c51f124SMoriah Waterland 			 * constructed. Look into dropping this soon.
544*5c51f124SMoriah Waterland 			 */
545*5c51f124SMoriah Waterland 			pkgpinfo = eptstat(&(el_ent->cf_ent), pkginst,
546*5c51f124SMoriah Waterland 			    ENTRY_OK);
547*5c51f124SMoriah Waterland 
548*5c51f124SMoriah Waterland 			if (stflag != DUP_ENTRY) {
549*5c51f124SMoriah Waterland 				changed++;
550*5c51f124SMoriah Waterland 			}
551*5c51f124SMoriah Waterland 
552*5c51f124SMoriah Waterland 			/*
553*5c51f124SMoriah Waterland 			 * We could trust the prior pkginfo entry, but things
554*5c51f124SMoriah Waterland 			 * could have changed and  we need to update the
555*5c51f124SMoriah Waterland 			 * fs_tab[] anyway. We check for a server object
556*5c51f124SMoriah Waterland 			 * here.
557*5c51f124SMoriah Waterland 			 */
558*5c51f124SMoriah Waterland 			if (is_served(el_ent->server_path,
559*5c51f124SMoriah Waterland 			    &(el_ent->fsys_value)))
560*5c51f124SMoriah Waterland 				pkgpinfo->status = SERVED_FILE;
561*5c51f124SMoriah Waterland 		} else {
562*5c51f124SMoriah Waterland 			if (!ignore && el_ent->mstat.contchg) {
563*5c51f124SMoriah Waterland 				pkgpinfo =
564*5c51f124SMoriah Waterland 				    eptstat(&(el_ent->cf_ent), pkginst,
565*5c51f124SMoriah Waterland 				    (dbst ? dbst : CONFIRM_CONT));
566*5c51f124SMoriah Waterland 			} else if (!ignore && el_ent->mstat.attrchg) {
567*5c51f124SMoriah Waterland 				pkgpinfo =
568*5c51f124SMoriah Waterland 				    eptstat(&(el_ent->cf_ent), pkginst,
569*5c51f124SMoriah Waterland 				    (dbst ? dbst : CONFIRM_ATTR));
570*5c51f124SMoriah Waterland 			} else if (!ignore && el_ent->mstat.shared) {
571*5c51f124SMoriah Waterland 				pkgpinfo =
572*5c51f124SMoriah Waterland 				    eptstat(&(el_ent->cf_ent), pkginst,
573*5c51f124SMoriah Waterland 				    dbst);
574*5c51f124SMoriah Waterland 				changed++;
575*5c51f124SMoriah Waterland 			} else if (stflag != DUP_ENTRY) {
576*5c51f124SMoriah Waterland 				pkgpinfo = eptstat(&(el_ent->cf_ent),
577*5c51f124SMoriah Waterland 				    pkginst, '\0');
578*5c51f124SMoriah Waterland 				if (stflag != ENTRY_OK) {
579*5c51f124SMoriah Waterland 					changed++;
580*5c51f124SMoriah Waterland 				}
581*5c51f124SMoriah Waterland 			}
582*5c51f124SMoriah Waterland 		}
583*5c51f124SMoriah Waterland 
584*5c51f124SMoriah Waterland 		if (mrg_result == MRG_REPLACE) {
585*5c51f124SMoriah Waterland 			/*
586*5c51f124SMoriah Waterland 			 * Put the original package database entry back into
587*5c51f124SMoriah Waterland 			 * the package database for now.
588*5c51f124SMoriah Waterland 			 */
589*5c51f124SMoriah Waterland 			output(vfpo, cf_ent, pkgpinfo);
590*5c51f124SMoriah Waterland 		} else {
591*5c51f124SMoriah Waterland 			/* Put the merged entry into the package database. */
592*5c51f124SMoriah Waterland 			output(vfpo, &(el_ent->cf_ent), pkgpinfo);
593*5c51f124SMoriah Waterland 		}
594*5c51f124SMoriah Waterland 	}
595*5c51f124SMoriah Waterland 
596*5c51f124SMoriah Waterland 	if (pkgpinfo->aclass[0] != '\0') {
597*5c51f124SMoriah Waterland 		(void) strcpy(el_ent->cf_ent.pkg_class, pkgpinfo->aclass);
598*5c51f124SMoriah Waterland 	}
599*5c51f124SMoriah Waterland 
600*5c51f124SMoriah Waterland 	/*
601*5c51f124SMoriah Waterland 	 * If a sym link entry exists in the contents file and
602*5c51f124SMoriah Waterland 	 * and the destination of the link does not exist on the the system
603*5c51f124SMoriah Waterland 	 * then the contents file needs to be updated appropriately so a
604*5c51f124SMoriah Waterland 	 * subsequent invocation of "installf -f" will create the destination.
605*5c51f124SMoriah Waterland 	 */
606*5c51f124SMoriah Waterland 	if (el_ent->mstat.contchg && pkgpinfo->status == INST_RDY) {
607*5c51f124SMoriah Waterland 		changed++;
608*5c51f124SMoriah Waterland 	}
609*5c51f124SMoriah Waterland 
610*5c51f124SMoriah Waterland 	if (!(el_ent->mstat.preloaded))
611*5c51f124SMoriah Waterland 		el_ent->cf_ent.pinfo = NULL;
612*5c51f124SMoriah Waterland 
613*5c51f124SMoriah Waterland 	/*
614*5c51f124SMoriah Waterland 	 * If no change during the merg and we don't have a case where types
615*5c51f124SMoriah Waterland 	 * were different in odd ways, count this as installed.
616*5c51f124SMoriah Waterland 	 */
617*5c51f124SMoriah Waterland 	if (!el_ent->mstat.attrchg && !el_ent->mstat.contchg &&
618*5c51f124SMoriah Waterland 	    !el_ent->mstat.replace)
619*5c51f124SMoriah Waterland 		installed++;
620*5c51f124SMoriah Waterland 	return (changed);
621*5c51f124SMoriah Waterland }
622*5c51f124SMoriah Waterland 
623*5c51f124SMoriah Waterland /* Insert an entirely new entry into the package database. */
624*5c51f124SMoriah Waterland static int
625*5c51f124SMoriah Waterland do_new_ent(VFP_T *vfpo, struct cfextra *el_ent, int ctrl)
626*5c51f124SMoriah Waterland {
627*5c51f124SMoriah Waterland 	struct pinfo	*pinfo;
628*5c51f124SMoriah Waterland 	char		*tp;
629*5c51f124SMoriah Waterland 	int		changed = 0;
630*5c51f124SMoriah Waterland 
631*5c51f124SMoriah Waterland 	if (el_ent->cf_ent.ftype == RM_RDY) {
632*5c51f124SMoriah Waterland 		return (0);
633*5c51f124SMoriah Waterland 	}
634*5c51f124SMoriah Waterland 
635*5c51f124SMoriah Waterland 	tp = el_ent->server_path;
636*5c51f124SMoriah Waterland 	/*
637*5c51f124SMoriah Waterland 	 * Check the file/dir existence only if any of the parent directory
638*5c51f124SMoriah Waterland 	 * of the file/dir has not changed from symbolic link to directory.
639*5c51f124SMoriah Waterland 	 * At this time we are only doing a dry run, the symlink is not yet
640*5c51f124SMoriah Waterland 	 * replaced, so if this is done directly then access will result in
641*5c51f124SMoriah Waterland 	 * incorrect information in case a file with the same attr and cont
642*5c51f124SMoriah Waterland 	 * exists in the link target.
643*5c51f124SMoriah Waterland 	 */
644*5c51f124SMoriah Waterland 	if ((!el_ent->mstat.parentsyml2dir) && (access(tp, F_OK) == 0)) {
645*5c51f124SMoriah Waterland 		/*
646*5c51f124SMoriah Waterland 		 * Path exists, and although its not referenced by any
647*5c51f124SMoriah Waterland 		 * package we make it look like it is so it appears as a
648*5c51f124SMoriah Waterland 		 * conflicting file in case the user doesn't want it
649*5c51f124SMoriah Waterland 		 * installed. We set the rogue flag to distinguish this from
650*5c51f124SMoriah Waterland 		 * package object conflicts if the administrator is queried
651*5c51f124SMoriah Waterland 		 * about this later. Note that noconflict means NO conflict
652*5c51f124SMoriah Waterland 		 * at the file level. Even rogue files count.
653*5c51f124SMoriah Waterland 		 */
654*5c51f124SMoriah Waterland 		el_ent->mstat.shared = 1;
655*5c51f124SMoriah Waterland 		el_ent->mstat.rogue = 1;
656*5c51f124SMoriah Waterland 		set_change(el_ent);
657*5c51f124SMoriah Waterland 	} else {
658*5c51f124SMoriah Waterland 		/* since path doesn't exist, we're changing everything */
659*5c51f124SMoriah Waterland 		el_ent->mstat.rogue = 0;
660*5c51f124SMoriah Waterland 		el_ent->mstat.contchg = 1;
661*5c51f124SMoriah Waterland 		el_ent->mstat.attrchg = 1;
662*5c51f124SMoriah Waterland 	}
663*5c51f124SMoriah Waterland 
664*5c51f124SMoriah Waterland 	if (el_ent->cf_ent.ainfo.mode == WILDCARD) {
665*5c51f124SMoriah Waterland 		if (el_ent->cf_ent.ftype == 'd') {
666*5c51f124SMoriah Waterland 			el_ent->cf_ent.ainfo.mode = DEFAULT_MODE;
667*5c51f124SMoriah Waterland 		} else {
668*5c51f124SMoriah Waterland 			el_ent->cf_ent.ainfo.mode = DEFAULT_MODE_FILE;
669*5c51f124SMoriah Waterland 		}
670*5c51f124SMoriah Waterland 		logerr(WRN_SET_DEF_MODE, el_ent->cf_ent.path,
671*5c51f124SMoriah Waterland 		    (int)el_ent->cf_ent.ainfo.mode);
672*5c51f124SMoriah Waterland 	}
673*5c51f124SMoriah Waterland 
674*5c51f124SMoriah Waterland 	if (strcmp(el_ent->cf_ent.ainfo.owner, DB_UNDEFINED_ENTRY) == 0)
675*5c51f124SMoriah Waterland 		(void) strcpy(el_ent->cf_ent.ainfo.owner,
676*5c51f124SMoriah Waterland 				DEFAULT_OWNER);
677*5c51f124SMoriah Waterland 	if (strcmp(el_ent->cf_ent.ainfo.group, DB_UNDEFINED_ENTRY) == 0)
678*5c51f124SMoriah Waterland 		(void) strcpy(el_ent->cf_ent.ainfo.group,
679*5c51f124SMoriah Waterland 				DEFAULT_GROUP);
680*5c51f124SMoriah Waterland 
681*5c51f124SMoriah Waterland 	/*
682*5c51f124SMoriah Waterland 	 * Do not allow installation if nocnflct is set and this pathname is
683*5c51f124SMoriah Waterland 	 * already in place. Since this entry is new (not associated with a
684*5c51f124SMoriah Waterland 	 * package), we don't issue anything to the database we're building.
685*5c51f124SMoriah Waterland 	 */
686*5c51f124SMoriah Waterland 	if (nocnflct && el_ent->mstat.shared) {
687*5c51f124SMoriah Waterland 		return (0);
688*5c51f124SMoriah Waterland 	}
689*5c51f124SMoriah Waterland 
690*5c51f124SMoriah Waterland 	if (!errflg) {
691*5c51f124SMoriah Waterland 		if (el_ent->mstat.preloaded) {
692*5c51f124SMoriah Waterland 			/* Add this package to the already established list. */
693*5c51f124SMoriah Waterland 			pinfo = eptstat(&(el_ent->cf_ent), pkginst, DUP_ENTRY);
694*5c51f124SMoriah Waterland 		} else {
695*5c51f124SMoriah Waterland 			el_ent->cf_ent.npkgs = 1;
696*5c51f124SMoriah Waterland 			pinfo = (struct pinfo *)calloc(1,
697*5c51f124SMoriah Waterland 			    sizeof (struct pinfo));
698*5c51f124SMoriah Waterland 			if (!pinfo) {
699*5c51f124SMoriah Waterland 				progerr(gettext(ERR_MEMORY), errno);
700*5c51f124SMoriah Waterland 				quit(99);
701*5c51f124SMoriah Waterland 			}
702*5c51f124SMoriah Waterland 			el_ent->cf_ent.pinfo = pinfo;
703*5c51f124SMoriah Waterland 			(void) strcpy(pinfo->pkg, pkginst);
704*5c51f124SMoriah Waterland 		}
705*5c51f124SMoriah Waterland 
706*5c51f124SMoriah Waterland 		if (ctrl == 1) {	/* quick verify assumes OK */
707*5c51f124SMoriah Waterland 			pinfo->status = dbst ? dbst : ENTRY_OK;
708*5c51f124SMoriah Waterland 			/*
709*5c51f124SMoriah Waterland 			 * The entry won't be verified, but the entry in the
710*5c51f124SMoriah Waterland 			 * database isn't necessarily ENTRY_OK. If this is
711*5c51f124SMoriah Waterland 			 * coming from a server, we need to note that
712*5c51f124SMoriah Waterland 			 * instead.
713*5c51f124SMoriah Waterland 			 */
714*5c51f124SMoriah Waterland 			if (is_served(el_ent->server_path,
715*5c51f124SMoriah Waterland 			    &(el_ent->fsys_value)))
716*5c51f124SMoriah Waterland 				pinfo->status = SERVED_FILE;
717*5c51f124SMoriah Waterland 		} else {
718*5c51f124SMoriah Waterland 			pinfo->status = dbst ? dbst : CONFIRM_CONT;
719*5c51f124SMoriah Waterland 		}
720*5c51f124SMoriah Waterland 
721*5c51f124SMoriah Waterland 		output(vfpo, &(el_ent->cf_ent), pinfo);
722*5c51f124SMoriah Waterland 		changed++;
723*5c51f124SMoriah Waterland 
724*5c51f124SMoriah Waterland 		free(pinfo);
725*5c51f124SMoriah Waterland 		el_ent->cf_ent.pinfo = NULL;
726*5c51f124SMoriah Waterland 		}
727*5c51f124SMoriah Waterland 	if (!el_ent->mstat.attrchg && !el_ent->mstat.contchg) {
728*5c51f124SMoriah Waterland 		installed++;
729*5c51f124SMoriah Waterland 	}
730*5c51f124SMoriah Waterland 
731*5c51f124SMoriah Waterland 	return (changed);
732*5c51f124SMoriah Waterland }
733*5c51f124SMoriah Waterland 
734*5c51f124SMoriah Waterland int
735*5c51f124SMoriah Waterland files_installed(void)
736*5c51f124SMoriah Waterland {
737*5c51f124SMoriah Waterland 	return (installed);
738*5c51f124SMoriah Waterland }
739*5c51f124SMoriah Waterland 
740*5c51f124SMoriah Waterland /*
741*5c51f124SMoriah Waterland  * This function determines if there is a difference between the file on
742*5c51f124SMoriah Waterland  * the disk and the file to be laid down. It set's mstat flags attrchg
743*5c51f124SMoriah Waterland  * and contchg accordingly.
744*5c51f124SMoriah Waterland  */
745*5c51f124SMoriah Waterland static void
746*5c51f124SMoriah Waterland set_change(struct cfextra *el_ent)
747*5c51f124SMoriah Waterland {
748*5c51f124SMoriah Waterland 	int	n;
749*5c51f124SMoriah Waterland 	char 	*tp;
750*5c51f124SMoriah Waterland 
751*5c51f124SMoriah Waterland 	tp = el_ent->server_path;
752*5c51f124SMoriah Waterland 	if ((el_ent->cf_ent.ftype == 'f') || (el_ent->cf_ent.ftype == 'e') ||
753*5c51f124SMoriah Waterland 		(el_ent->cf_ent.ftype == 'v')) {
754*5c51f124SMoriah Waterland 		if (cverify(0, &(el_ent->cf_ent.ftype), tp,
755*5c51f124SMoriah Waterland 		    &(el_ent->cf_ent.cinfo), 1)) {
756*5c51f124SMoriah Waterland 			el_ent->mstat.contchg = 1;
757*5c51f124SMoriah Waterland 		} else if (!el_ent->mstat.contchg && !el_ent->mstat.attrchg) {
758*5c51f124SMoriah Waterland 			if (averify(0, &(el_ent->cf_ent.ftype), tp,
759*5c51f124SMoriah Waterland 			    &(el_ent->cf_ent.ainfo)))
760*5c51f124SMoriah Waterland 				el_ent->mstat.attrchg = 1;
761*5c51f124SMoriah Waterland 		}
762*5c51f124SMoriah Waterland 	} else if (!el_ent->mstat.attrchg &&
763*5c51f124SMoriah Waterland 		((el_ent->cf_ent.ftype == 'd') ||
764*5c51f124SMoriah Waterland 		(el_ent->cf_ent.ftype == 'x') ||
765*5c51f124SMoriah Waterland 		(el_ent->cf_ent.ftype == 'c') ||
766*5c51f124SMoriah Waterland 		(el_ent->cf_ent.ftype == 'b') ||
767*5c51f124SMoriah Waterland 		(el_ent->cf_ent.ftype == 'p'))) {
768*5c51f124SMoriah Waterland 		n = averify(0, &(el_ent->cf_ent.ftype), tp,
769*5c51f124SMoriah Waterland 		    &(el_ent->cf_ent.ainfo));
770*5c51f124SMoriah Waterland 		if (n == VE_ATTR)
771*5c51f124SMoriah Waterland 			el_ent->mstat.attrchg = 1;
772*5c51f124SMoriah Waterland 		else if (n && (n != VE_EXIST)) {
773*5c51f124SMoriah Waterland 			el_ent->mstat.contchg = 1;
774*5c51f124SMoriah Waterland 		}
775*5c51f124SMoriah Waterland 	} else if (!el_ent->mstat.attrchg &&
776*5c51f124SMoriah Waterland 		((el_ent->cf_ent.ftype == 's') ||
777*5c51f124SMoriah Waterland 		(el_ent->cf_ent.ftype == 'l'))) {
778*5c51f124SMoriah Waterland 		n = averify(0, &(el_ent->cf_ent.ftype), tp,
779*5c51f124SMoriah Waterland 		    &(el_ent->cf_ent.ainfo));
780*5c51f124SMoriah Waterland 		if (n == VE_ATTR)
781*5c51f124SMoriah Waterland 			el_ent->mstat.attrchg = 1;
782*5c51f124SMoriah Waterland 		else if (n && (n == VE_EXIST)) {
783*5c51f124SMoriah Waterland 			el_ent->mstat.contchg = 1;
784*5c51f124SMoriah Waterland 		}
785*5c51f124SMoriah Waterland 	}
786*5c51f124SMoriah Waterland }
787*5c51f124SMoriah Waterland 
788*5c51f124SMoriah Waterland static int
789*5c51f124SMoriah Waterland is_setuid(struct cfent *ent)
790*5c51f124SMoriah Waterland {
791*5c51f124SMoriah Waterland 	return (((ent->ftype == 'f') || (ent->ftype == 'v') ||
792*5c51f124SMoriah Waterland 		(ent->ftype == 'e')) &&
793*5c51f124SMoriah Waterland 		(ent->ainfo.mode != BADMODE) &&
794*5c51f124SMoriah Waterland 		(ent->ainfo.mode != WILDCARD) &&
795*5c51f124SMoriah Waterland 		(ent->ainfo.mode & S_ISUID));
796*5c51f124SMoriah Waterland }
797*5c51f124SMoriah Waterland 
798*5c51f124SMoriah Waterland static int
799*5c51f124SMoriah Waterland is_setgid(struct cfent *ent)
800*5c51f124SMoriah Waterland {
801*5c51f124SMoriah Waterland 	return (((ent->ftype == 'f') || (ent->ftype == 'v') ||
802*5c51f124SMoriah Waterland 		(ent->ftype == 'e')) && (ent->ainfo.mode != BADMODE) &&
803*5c51f124SMoriah Waterland 		(ent->ainfo.mode != WILDCARD) &&
804*5c51f124SMoriah Waterland 		(ent->ainfo.mode & S_ISGID) &&
805*5c51f124SMoriah Waterland 		(ent->ainfo.mode & (S_IEXEC|S_IXUSR|S_IXOTH)));
806*5c51f124SMoriah Waterland }
807*5c51f124SMoriah Waterland 
808*5c51f124SMoriah Waterland char *types[] = {
809*5c51f124SMoriah Waterland 	"fev",	/* type 1, regular files */
810*5c51f124SMoriah Waterland 	"s", 	/* type 2, symbolic links */
811*5c51f124SMoriah Waterland 	"l", 	/* type 3, linked files */
812*5c51f124SMoriah Waterland 	"dx", 	/* type 4, directories */
813*5c51f124SMoriah Waterland 	"c", 	/* type 5, character special devices */
814*5c51f124SMoriah Waterland 	"b", 	/* type 6, block special devices */
815*5c51f124SMoriah Waterland 	"p", 	/* type 7, named pipes */
816*5c51f124SMoriah Waterland 	NULL
817*5c51f124SMoriah Waterland };
818*5c51f124SMoriah Waterland 
819*5c51f124SMoriah Waterland /*
820*5c51f124SMoriah Waterland  * This determines if the ftype of the file on the disk and the file to be
821*5c51f124SMoriah Waterland  * laid down are close enough. If they aren't, this either returns an error
822*5c51f124SMoriah Waterland  * or displays a warning. This returns :
823*5c51f124SMoriah Waterland  *	TYPE_OK		they're identical or close enough
824*5c51f124SMoriah Waterland  *	TYPE_WARNING	they're pretty close (probably no problem)
825*5c51f124SMoriah Waterland  *	TYPE_IGNORED	the type change was not allowed
826*5c51f124SMoriah Waterland  *	TYPE_REPLACE	to be reviewed later - in endofclass() maybe
827*5c51f124SMoriah Waterland  *	TYPE_FATAL	something awful happened
828*5c51f124SMoriah Waterland  */
829*5c51f124SMoriah Waterland static int
830*5c51f124SMoriah Waterland typechg(struct cfent *el_ent, struct cfent *cf_ent, struct mergstat *mstat)
831*5c51f124SMoriah Waterland {
832*5c51f124SMoriah Waterland 	int	i, etype, itype, retcode;
833*5c51f124SMoriah Waterland 
834*5c51f124SMoriah Waterland 	/* If they are identical, return OK */
835*5c51f124SMoriah Waterland 	if (cf_ent->ftype == el_ent->ftype)
836*5c51f124SMoriah Waterland 		return (TYPE_OK);
837*5c51f124SMoriah Waterland 
838*5c51f124SMoriah Waterland 	/*
839*5c51f124SMoriah Waterland 	 * If package database entry is ambiguous, set it to the new entity's
840*5c51f124SMoriah Waterland 	 * ftype
841*5c51f124SMoriah Waterland 	 */
842*5c51f124SMoriah Waterland 	if (cf_ent->ftype == BADFTYPE) {
843*5c51f124SMoriah Waterland 		cf_ent->ftype = el_ent->ftype;
844*5c51f124SMoriah Waterland 		return (TYPE_OK); /* do nothing; not really different */
845*5c51f124SMoriah Waterland 	}
846*5c51f124SMoriah Waterland 
847*5c51f124SMoriah Waterland 	/* If the new entity is ambiguous, wait for the verify */
848*5c51f124SMoriah Waterland 	if (el_ent->ftype == BADFTYPE)
849*5c51f124SMoriah Waterland 		return (TYPE_OK);
850*5c51f124SMoriah Waterland 
851*5c51f124SMoriah Waterland 	/*
852*5c51f124SMoriah Waterland 	 * If we're trying to convert an existing regular directory to an
853*5c51f124SMoriah Waterland 	 * exclusive directory, this is very dangerous. We will continue, but
854*5c51f124SMoriah Waterland 	 * we will deny the conversion.
855*5c51f124SMoriah Waterland 	 */
856*5c51f124SMoriah Waterland 	if (el_ent->ftype == 'x' && cf_ent->ftype == 'd') {
857*5c51f124SMoriah Waterland 		logerr(gettext(WRN_TOEXCL), el_ent->path);
858*5c51f124SMoriah Waterland 		return (TYPE_IGNORED);
859*5c51f124SMoriah Waterland 	}
860*5c51f124SMoriah Waterland 
861*5c51f124SMoriah Waterland 	etype = itype = 0;
862*5c51f124SMoriah Waterland 
863*5c51f124SMoriah Waterland 	/* Set etype to that of the new entity */
864*5c51f124SMoriah Waterland 	for (i = 0; types[i]; ++i) {
865*5c51f124SMoriah Waterland 		if (strchr(types[i], el_ent->ftype)) {
866*5c51f124SMoriah Waterland 			etype = i+1;
867*5c51f124SMoriah Waterland 			break;
868*5c51f124SMoriah Waterland 		}
869*5c51f124SMoriah Waterland 	}
870*5c51f124SMoriah Waterland 
871*5c51f124SMoriah Waterland 	/* Set itype to that in the package database. */
872*5c51f124SMoriah Waterland 	for (i = 0; types[i]; ++i) {
873*5c51f124SMoriah Waterland 		if (strchr(types[i], cf_ent->ftype)) {
874*5c51f124SMoriah Waterland 			itype = i+1;
875*5c51f124SMoriah Waterland 			break;
876*5c51f124SMoriah Waterland 		}
877*5c51f124SMoriah Waterland 	}
878*5c51f124SMoriah Waterland 
879*5c51f124SMoriah Waterland 	if (itype == etype) {
880*5c51f124SMoriah Waterland 		/* same basic object type */
881*5c51f124SMoriah Waterland 		return (TYPE_OK);
882*5c51f124SMoriah Waterland 	}
883*5c51f124SMoriah Waterland 
884*5c51f124SMoriah Waterland 	retcode = TYPE_WARNING;
885*5c51f124SMoriah Waterland 
886*5c51f124SMoriah Waterland 	/*
887*5c51f124SMoriah Waterland 	 * If a simple object (like a file) is overwriting a directory, mark
888*5c51f124SMoriah Waterland 	 * it for full inspection during installation.
889*5c51f124SMoriah Waterland 	 */
890*5c51f124SMoriah Waterland 	if (etype != 4 && itype == 4) {
891*5c51f124SMoriah Waterland 		mstat->dir2nondir = 1;
892*5c51f124SMoriah Waterland 		retcode = TYPE_REPLACE;
893*5c51f124SMoriah Waterland 	}
894*5c51f124SMoriah Waterland 
895*5c51f124SMoriah Waterland 	/* allow change, but warn user of possible problems */
896*5c51f124SMoriah Waterland 	switch (itype) {
897*5c51f124SMoriah Waterland 	    case 1:
898*5c51f124SMoriah Waterland 		logerr(gettext(WRN_NOTFILE), el_ent->path);
899*5c51f124SMoriah Waterland 		break;
900*5c51f124SMoriah Waterland 
901*5c51f124SMoriah Waterland 	    case 2:
902*5c51f124SMoriah Waterland 		logerr(gettext(WRN_NOTSYMLN), el_ent->path);
903*5c51f124SMoriah Waterland 		break;
904*5c51f124SMoriah Waterland 
905*5c51f124SMoriah Waterland 	    case 3:
906*5c51f124SMoriah Waterland 		logerr(gettext(WRN_NOTLINK), el_ent->path);
907*5c51f124SMoriah Waterland 		break;
908*5c51f124SMoriah Waterland 
909*5c51f124SMoriah Waterland 	    case 4:
910*5c51f124SMoriah Waterland 		logerr(gettext(WRN_NOTDIR), el_ent->path);
911*5c51f124SMoriah Waterland 		break;
912*5c51f124SMoriah Waterland 
913*5c51f124SMoriah Waterland 	    case 5:
914*5c51f124SMoriah Waterland 		logerr(gettext(WRN_NOTCHAR), el_ent->path);
915*5c51f124SMoriah Waterland 		break;
916*5c51f124SMoriah Waterland 
917*5c51f124SMoriah Waterland 	    case 6:
918*5c51f124SMoriah Waterland 		logerr(gettext(WRN_NOTBLOCK), el_ent->path);
919*5c51f124SMoriah Waterland 		break;
920*5c51f124SMoriah Waterland 
921*5c51f124SMoriah Waterland 	    case 7:
922*5c51f124SMoriah Waterland 		logerr(gettext(WRN_NOTPIPE), el_ent->path);
923*5c51f124SMoriah Waterland 		break;
924*5c51f124SMoriah Waterland 
925*5c51f124SMoriah Waterland 	    default:
926*5c51f124SMoriah Waterland 		break;
927*5c51f124SMoriah Waterland 	}
928*5c51f124SMoriah Waterland 	return (retcode);
929*5c51f124SMoriah Waterland }
930*5c51f124SMoriah Waterland 
931*5c51f124SMoriah Waterland /*
932*5c51f124SMoriah Waterland  * This function takes el_ent (the entry from the pkgmap) and cf_ent (the
933*5c51f124SMoriah Waterland  * entry from the package database) and merge them into el_ent. The rules
934*5c51f124SMoriah Waterland  * are still being figured out, but the comments should make the approach
935*5c51f124SMoriah Waterland  * pretty clear.
936*5c51f124SMoriah Waterland  *
937*5c51f124SMoriah Waterland  * RETURN CODES:
938*5c51f124SMoriah Waterland  *	MRG_DIFFERENT	The two entries are different and el_ent now contains
939*5c51f124SMoriah Waterland  *			the intended new entry to be installed.
940*5c51f124SMoriah Waterland  *	MRG_SAME	The two entries were identical and the old database
941*5c51f124SMoriah Waterland  *			entry will be replaced unchanged.
942*5c51f124SMoriah Waterland  *	MRG_REPLACE	One or the other entry will be used but the decision
943*5c51f124SMoriah Waterland  *			has to be made at install time.
944*5c51f124SMoriah Waterland  */
945*5c51f124SMoriah Waterland static int
946*5c51f124SMoriah Waterland merg(struct cfextra *el_ent, struct cfent *cf_ent)
947*5c51f124SMoriah Waterland {
948*5c51f124SMoriah Waterland 	int	n, changed = 0;
949*5c51f124SMoriah Waterland 
950*5c51f124SMoriah Waterland 	/*
951*5c51f124SMoriah Waterland 	 * We need to change the original entry to make it look like the new
952*5c51f124SMoriah Waterland 	 * entry (the eptstat() routine has already added appropriate package
953*5c51f124SMoriah Waterland 	 * information, but not about 'aclass' which may represent a change
954*5c51f124SMoriah Waterland 	 * in class from the previous installation.
955*5c51f124SMoriah Waterland 	 *
956*5c51f124SMoriah Waterland 	 * NOTE: elent->cf_ent.pinfo (the list of associated packages) is NULL
957*5c51f124SMoriah Waterland 	 * upon entry to this function.
958*5c51f124SMoriah Waterland 	 */
959*5c51f124SMoriah Waterland 
960*5c51f124SMoriah Waterland 	el_ent->cf_ent.pinfo = cf_ent->pinfo;
961*5c51f124SMoriah Waterland 
962*5c51f124SMoriah Waterland 	if (dbst == INST_RDY && el_ent->cf_ent.ftype == '?') {
963*5c51f124SMoriah Waterland 		el_ent->cf_ent.ftype = cf_ent->ftype;
964*5c51f124SMoriah Waterland 	}
965*5c51f124SMoriah Waterland 
966*5c51f124SMoriah Waterland 	/*
967*5c51f124SMoriah Waterland 	 * Evaluate the ftype change. Usually the ftype won't change. If it
968*5c51f124SMoriah Waterland 	 * does it may be easy (s -> f), not allowed (d -> x), so complex we
969*5c51f124SMoriah Waterland 	 * can't figure it 'til later (d -> s) or fatal (a hook for later).
970*5c51f124SMoriah Waterland 	 */
971*5c51f124SMoriah Waterland 	if (cf_ent->ftype != el_ent->cf_ent.ftype) {
972*5c51f124SMoriah Waterland 		n = typechg(&(el_ent->cf_ent), cf_ent, &(el_ent->mstat));
973*5c51f124SMoriah Waterland 
974*5c51f124SMoriah Waterland 		switch (n) {
975*5c51f124SMoriah Waterland 		    case TYPE_OK:
976*5c51f124SMoriah Waterland 			break;
977*5c51f124SMoriah Waterland 
978*5c51f124SMoriah Waterland 		    /* This is an allowable change. */
979*5c51f124SMoriah Waterland 		    case TYPE_WARNING:
980*5c51f124SMoriah Waterland 			el_ent->mstat.contchg = 1;
981*5c51f124SMoriah Waterland 			break;
982*5c51f124SMoriah Waterland 
983*5c51f124SMoriah Waterland 		    /* Not allowed, but leaving it as is is OK. */
984*5c51f124SMoriah Waterland 		    case TYPE_IGNORED:
985*5c51f124SMoriah Waterland 			logerr(gettext(MSG_TYPIGN));
986*5c51f124SMoriah Waterland 			if (cp_cfent(cf_ent, el_ent) == 0)
987*5c51f124SMoriah Waterland 				quit(99);
988*5c51f124SMoriah Waterland 			return (MRG_SAME);
989*5c51f124SMoriah Waterland 
990*5c51f124SMoriah Waterland 		    /* Future analysis will reveal if this is OK. */
991*5c51f124SMoriah Waterland 		    case TYPE_REPLACE:
992*5c51f124SMoriah Waterland 			el_ent->mstat.replace = 1;
993*5c51f124SMoriah Waterland 			return (MRG_REPLACE);
994*5c51f124SMoriah Waterland 
995*5c51f124SMoriah Waterland 		    /* Kill it before it does any damage. */
996*5c51f124SMoriah Waterland 		    case TYPE_FATAL:
997*5c51f124SMoriah Waterland 			logerr(gettext(MSG_TYPE_ERR));
998*5c51f124SMoriah Waterland 			quit(99);
999*5c51f124SMoriah Waterland 
1000*5c51f124SMoriah Waterland 		    default:
1001*5c51f124SMoriah Waterland 			break;
1002*5c51f124SMoriah Waterland 		}
1003*5c51f124SMoriah Waterland 
1004*5c51f124SMoriah Waterland 		changed++;
1005*5c51f124SMoriah Waterland 	}
1006*5c51f124SMoriah Waterland 
1007*5c51f124SMoriah Waterland 	/* Evaluate and merge the class. */
1008*5c51f124SMoriah Waterland 	if (strcmp(cf_ent->pkg_class, el_ent->cf_ent.pkg_class)) {
1009*5c51f124SMoriah Waterland 		/*
1010*5c51f124SMoriah Waterland 		 * we always allow a class change as long as we have
1011*5c51f124SMoriah Waterland 		 * consistent ftypes, which at this point we must
1012*5c51f124SMoriah Waterland 		 */
1013*5c51f124SMoriah Waterland 		changed++;
1014*5c51f124SMoriah Waterland 		if (strcmp(cf_ent->pkg_class, "?")) {
1015*5c51f124SMoriah Waterland 			(void) strcpy(pkgpinfo->aclass,
1016*5c51f124SMoriah Waterland 			    el_ent->cf_ent.pkg_class);
1017*5c51f124SMoriah Waterland 			(void) strcpy(el_ent->cf_ent.pkg_class,
1018*5c51f124SMoriah Waterland 			    cf_ent->pkg_class);
1019*5c51f124SMoriah Waterland 			chgclass(&(el_ent->cf_ent), pkgpinfo);
1020*5c51f124SMoriah Waterland 		}
1021*5c51f124SMoriah Waterland 	}
1022*5c51f124SMoriah Waterland 
1023*5c51f124SMoriah Waterland 	/*
1024*5c51f124SMoriah Waterland 	 * Evaluate and merge based upon the ftype of the intended package
1025*5c51f124SMoriah Waterland 	 * database entry.
1026*5c51f124SMoriah Waterland 	 */
1027*5c51f124SMoriah Waterland 	if (((el_ent->cf_ent.ftype == 's') || (el_ent->cf_ent.ftype == 'l'))) {
1028*5c51f124SMoriah Waterland 
1029*5c51f124SMoriah Waterland 		/* If both have link sources, then they need to be merged. */
1030*5c51f124SMoriah Waterland 		if (cf_ent->ainfo.local && el_ent->cf_ent.ainfo.local) {
1031*5c51f124SMoriah Waterland 			/*
1032*5c51f124SMoriah Waterland 			 * If both sources are identical, the merge is
1033*5c51f124SMoriah Waterland 			 * already done.
1034*5c51f124SMoriah Waterland 			 */
1035*5c51f124SMoriah Waterland 			if (strcmp(cf_ent->ainfo.local,
1036*5c51f124SMoriah Waterland 			    el_ent->cf_ent.ainfo.local) != NULL) {
1037*5c51f124SMoriah Waterland 				changed++;
1038*5c51f124SMoriah Waterland 
1039*5c51f124SMoriah Waterland 				/*
1040*5c51f124SMoriah Waterland 				 * Otherwise, if the pkgmap entry is
1041*5c51f124SMoriah Waterland 				 * ambiguous, it will inherit the database
1042*5c51f124SMoriah Waterland 				 * entry.
1043*5c51f124SMoriah Waterland 				 */
1044*5c51f124SMoriah Waterland 				if (strcmp(el_ent->cf_ent.ainfo.local,
1045*5c51f124SMoriah Waterland 				    "?") == NULL) {
1046*5c51f124SMoriah Waterland 					(void) strlcpy(
1047*5c51f124SMoriah Waterland 						el_ent->cf_ent.ainfo.local,
1048*5c51f124SMoriah Waterland 						cf_ent->ainfo.local,
1049*5c51f124SMoriah Waterland 						PATH_MAX);
1050*5c51f124SMoriah Waterland 				} else {
1051*5c51f124SMoriah Waterland 					el_ent->mstat.contchg = 1;
1052*5c51f124SMoriah Waterland 				}
1053*5c51f124SMoriah Waterland 			}
1054*5c51f124SMoriah Waterland 		}
1055*5c51f124SMoriah Waterland 		return (changed ? MRG_DIFFERENT : MRG_SAME);
1056*5c51f124SMoriah Waterland 
1057*5c51f124SMoriah Waterland 	} else if (el_ent->cf_ent.ftype == 'e') {
1058*5c51f124SMoriah Waterland 
1059*5c51f124SMoriah Waterland 		/*
1060*5c51f124SMoriah Waterland 		 * The contents of edittable files are assumed to be changing
1061*5c51f124SMoriah Waterland 		 * since some class action script will be doing the work and
1062*5c51f124SMoriah Waterland 		 * we have no way of evaluating what it will actually do.
1063*5c51f124SMoriah Waterland 		 */
1064*5c51f124SMoriah Waterland 		el_ent->mstat.contchg = 1;
1065*5c51f124SMoriah Waterland 		changed++;
1066*5c51f124SMoriah Waterland 	} else if (((el_ent->cf_ent.ftype == 'f') ||
1067*5c51f124SMoriah Waterland 					(el_ent->cf_ent.ftype == 'v'))) {
1068*5c51f124SMoriah Waterland 		/*
1069*5c51f124SMoriah Waterland 		 * For regular files, Look at content information; a BADCONT
1070*5c51f124SMoriah Waterland 		 * in any el_ent field indicates the contents are unknown --
1071*5c51f124SMoriah Waterland 		 * since cf_ent is guaranteed to have a valid entry here (bad
1072*5c51f124SMoriah Waterland 		 * assumption?) this function will recognize this as a
1073*5c51f124SMoriah Waterland 		 * change. The ambiguous el_ent values will be evaluated and
1074*5c51f124SMoriah Waterland 		 * set later.
1075*5c51f124SMoriah Waterland 		 */
1076*5c51f124SMoriah Waterland 
1077*5c51f124SMoriah Waterland 		/*
1078*5c51f124SMoriah Waterland 		 * for type f/v files, if the file is in an area that is
1079*5c51f124SMoriah Waterland 		 * inherited from the global zone, that area is read only
1080*5c51f124SMoriah Waterland 		 * and the object cannot be changed - ignore any settings
1081*5c51f124SMoriah Waterland 		 * in the current package database that may be present for
1082*5c51f124SMoriah Waterland 		 * any existing object because they are irrelevant - since
1083*5c51f124SMoriah Waterland 		 * the object is in a read-only area shared from the global
1084*5c51f124SMoriah Waterland 		 * zone, accept that file's actual attributes as being correct.
1085*5c51f124SMoriah Waterland 		 */
1086*5c51f124SMoriah Waterland 
1087*5c51f124SMoriah Waterland 		if (z_path_is_inherited(el_ent->cf_ent.path,
1088*5c51f124SMoriah Waterland 			el_ent->cf_ent.ftype, get_inst_root()) == B_TRUE) {
1089*5c51f124SMoriah Waterland 			echoDebug(DBG_PKGDBMRG_INHERITED, el_ent->cf_ent.path);
1090*5c51f124SMoriah Waterland 		} else if (cf_ent->cinfo.size != el_ent->cf_ent.cinfo.size) {
1091*5c51f124SMoriah Waterland 			changed++;
1092*5c51f124SMoriah Waterland 			el_ent->mstat.contchg = 1;
1093*5c51f124SMoriah Waterland 		} else if (cf_ent->cinfo.modtime !=
1094*5c51f124SMoriah Waterland 		    el_ent->cf_ent.cinfo.modtime) {
1095*5c51f124SMoriah Waterland 			changed++;
1096*5c51f124SMoriah Waterland 			el_ent->mstat.contchg = 1;
1097*5c51f124SMoriah Waterland 		} else if (cf_ent->cinfo.cksum != el_ent->cf_ent.cinfo.cksum) {
1098*5c51f124SMoriah Waterland 			changed++;
1099*5c51f124SMoriah Waterland 			el_ent->mstat.contchg = 1;
1100*5c51f124SMoriah Waterland 		}
1101*5c51f124SMoriah Waterland 	} else if (((el_ent->cf_ent.ftype == 'c') ||
1102*5c51f124SMoriah Waterland 					(el_ent->cf_ent.ftype == 'b'))) {
1103*5c51f124SMoriah Waterland 		/*
1104*5c51f124SMoriah Waterland 		 * For devices, if major or minor numbers are identical the
1105*5c51f124SMoriah Waterland 		 * merge is trivial. If the el_ent value is ambiguous (BAD),
1106*5c51f124SMoriah Waterland 		 * the cf_ent value is inherited. Otherwise, the el_ent value
1107*5c51f124SMoriah Waterland 		 * is preserved.
1108*5c51f124SMoriah Waterland 		 */
1109*5c51f124SMoriah Waterland 		if (cf_ent->ainfo.major != el_ent->cf_ent.ainfo.major) {
1110*5c51f124SMoriah Waterland 			changed++;
1111*5c51f124SMoriah Waterland 			if (el_ent->cf_ent.ainfo.major == BADMAJOR) {
1112*5c51f124SMoriah Waterland 				el_ent->cf_ent.ainfo.major =
1113*5c51f124SMoriah Waterland 				    cf_ent->ainfo.major;
1114*5c51f124SMoriah Waterland 			} else {
1115*5c51f124SMoriah Waterland 				el_ent->mstat.contchg = 1;
1116*5c51f124SMoriah Waterland 			}
1117*5c51f124SMoriah Waterland 		}
1118*5c51f124SMoriah Waterland 		if (cf_ent->ainfo.minor != el_ent->cf_ent.ainfo.minor) {
1119*5c51f124SMoriah Waterland 			changed++;
1120*5c51f124SMoriah Waterland 			if (el_ent->cf_ent.ainfo.minor == BADMINOR)
1121*5c51f124SMoriah Waterland 				el_ent->cf_ent.ainfo.minor =
1122*5c51f124SMoriah Waterland 				    cf_ent->ainfo.minor;
1123*5c51f124SMoriah Waterland 			else
1124*5c51f124SMoriah Waterland 				el_ent->mstat.contchg = 1;
1125*5c51f124SMoriah Waterland 		}
1126*5c51f124SMoriah Waterland 	}
1127*5c51f124SMoriah Waterland 
1128*5c51f124SMoriah Waterland 	/*
1129*5c51f124SMoriah Waterland 	 * For mode, owner and group follow the same rules as above - if
1130*5c51f124SMoriah Waterland 	 * ambiguous, inherit, otherwise keep the new one.
1131*5c51f124SMoriah Waterland 	 */
1132*5c51f124SMoriah Waterland 	if (cf_ent->ainfo.mode != el_ent->cf_ent.ainfo.mode) {
1133*5c51f124SMoriah Waterland 		changed++;  /* attribute info is changing */
1134*5c51f124SMoriah Waterland 		if (el_ent->cf_ent.ainfo.mode == BADMODE) {
1135*5c51f124SMoriah Waterland 			el_ent->cf_ent.ainfo.mode = cf_ent->ainfo.mode;
1136*5c51f124SMoriah Waterland 		} else if (el_ent->cf_ent.ainfo.mode == WILDCARD) {
1137*5c51f124SMoriah Waterland 			/*
1138*5c51f124SMoriah Waterland 			 * If pkgmap has a '?' set for mode, use the mode from
1139*5c51f124SMoriah Waterland 			 * the pkg DB (contents file).
1140*5c51f124SMoriah Waterland 			 */
1141*5c51f124SMoriah Waterland 			el_ent->cf_ent.ainfo.mode = cf_ent->ainfo.mode;
1142*5c51f124SMoriah Waterland 			el_ent->mstat.attrchg = 0;
1143*5c51f124SMoriah Waterland 		} else {
1144*5c51f124SMoriah Waterland 			el_ent->mstat.attrchg = 1;
1145*5c51f124SMoriah Waterland 		}
1146*5c51f124SMoriah Waterland 	}
1147*5c51f124SMoriah Waterland 	if (strcmp(cf_ent->ainfo.owner, el_ent->cf_ent.ainfo.owner) != 0) {
1148*5c51f124SMoriah Waterland 		changed++;  /* attribute info is changing */
1149*5c51f124SMoriah Waterland 		if (strcmp(el_ent->cf_ent.ainfo.owner, BADOWNER) == 0)
1150*5c51f124SMoriah Waterland 			(void) strcpy(el_ent->cf_ent.ainfo.owner,
1151*5c51f124SMoriah Waterland 			    cf_ent->ainfo.owner);
1152*5c51f124SMoriah Waterland 		else
1153*5c51f124SMoriah Waterland 			el_ent->mstat.attrchg = 1;
1154*5c51f124SMoriah Waterland 	}
1155*5c51f124SMoriah Waterland 	if (strcmp(cf_ent->ainfo.group, el_ent->cf_ent.ainfo.group) != 0) {
1156*5c51f124SMoriah Waterland 		changed++;  /* attribute info is changing */
1157*5c51f124SMoriah Waterland 		if (strcmp(el_ent->cf_ent.ainfo.group, BADGROUP) == 0)
1158*5c51f124SMoriah Waterland 			(void) strcpy(el_ent->cf_ent.ainfo.group,
1159*5c51f124SMoriah Waterland 			    cf_ent->ainfo.group);
1160*5c51f124SMoriah Waterland 		else
1161*5c51f124SMoriah Waterland 			el_ent->mstat.attrchg = 1;
1162*5c51f124SMoriah Waterland 	}
1163*5c51f124SMoriah Waterland 	return (changed ? MRG_DIFFERENT : MRG_SAME);
1164*5c51f124SMoriah Waterland }
1165*5c51f124SMoriah Waterland 
1166*5c51f124SMoriah Waterland /*
1167*5c51f124SMoriah Waterland  * This puts the current entry into the package database in the appropriate
1168*5c51f124SMoriah Waterland  * intermediate format for this stage of the installation. This also assures
1169*5c51f124SMoriah Waterland  * the correct format for the various package object ftypes, stripping the
1170*5c51f124SMoriah Waterland  * link name before storing a regular file and stuff like that.
1171*5c51f124SMoriah Waterland  */
1172*5c51f124SMoriah Waterland 
1173*5c51f124SMoriah Waterland static void
1174*5c51f124SMoriah Waterland output(VFP_T *vfpo, struct cfent *ent, struct pinfo *pinfo)
1175*5c51f124SMoriah Waterland {
1176*5c51f124SMoriah Waterland 	short	svvolno;
1177*5c51f124SMoriah Waterland 	char	*svpt;
1178*5c51f124SMoriah Waterland 
1179*5c51f124SMoriah Waterland 	/* output without volume information */
1180*5c51f124SMoriah Waterland 	svvolno = ent->volno;
1181*5c51f124SMoriah Waterland 	ent->volno = 0;
1182*5c51f124SMoriah Waterland 
1183*5c51f124SMoriah Waterland 	pinfo->editflag = 0;
1184*5c51f124SMoriah Waterland 	if (((ent->ftype == 's') || (ent->ftype == 'l'))) {
1185*5c51f124SMoriah Waterland 		if (putcvfpfile(ent, vfpo)) {
1186*5c51f124SMoriah Waterland 			progerr(gettext(ERR_OUTPUT));
1187*5c51f124SMoriah Waterland 			quit(99);
1188*5c51f124SMoriah Waterland 		}
1189*5c51f124SMoriah Waterland 	} else {
1190*5c51f124SMoriah Waterland 
1191*5c51f124SMoriah Waterland 		/* output without local pathname */
1192*5c51f124SMoriah Waterland 		svpt = ent->ainfo.local;
1193*5c51f124SMoriah Waterland 		ent->ainfo.local = NULL;
1194*5c51f124SMoriah Waterland 		if (putcvfpfile(ent, vfpo)) {
1195*5c51f124SMoriah Waterland 			progerr(gettext(ERR_OUTPUT));
1196*5c51f124SMoriah Waterland 			quit(99);
1197*5c51f124SMoriah Waterland 		}
1198*5c51f124SMoriah Waterland 
1199*5c51f124SMoriah Waterland 		ent->ainfo.local = svpt;
1200*5c51f124SMoriah Waterland 		/*
1201*5c51f124SMoriah Waterland 		 * If this entry represents a file which is being edited, we
1202*5c51f124SMoriah Waterland 		 * need to store in memory the fact that it is an edittable
1203*5c51f124SMoriah Waterland 		 * file so that when we audit it after installation we do not
1204*5c51f124SMoriah Waterland 		 * worry about its contents; we do this by resetting the ftype
1205*5c51f124SMoriah Waterland 		 * to 'e' in the memory array which is later used to control
1206*5c51f124SMoriah Waterland 		 * the audit
1207*5c51f124SMoriah Waterland 		 */
1208*5c51f124SMoriah Waterland 		if (pinfo->editflag)
1209*5c51f124SMoriah Waterland 			ent->ftype = 'e';
1210*5c51f124SMoriah Waterland 	}
1211*5c51f124SMoriah Waterland 	/* restore volume information */
1212*5c51f124SMoriah Waterland 	ent->volno = svvolno;
1213*5c51f124SMoriah Waterland }
1214*5c51f124SMoriah Waterland 
1215*5c51f124SMoriah Waterland static void
1216*5c51f124SMoriah Waterland chgclass(struct cfent *cf_ent, struct pinfo *pinfo)
1217*5c51f124SMoriah Waterland {
1218*5c51f124SMoriah Waterland 	struct pinfo *pp;
1219*5c51f124SMoriah Waterland 	char	*oldclass, newclass[CLSSIZ+1];
1220*5c51f124SMoriah Waterland 	int	newcnt, oldcnt;
1221*5c51f124SMoriah Waterland 
1222*5c51f124SMoriah Waterland 	/*
1223*5c51f124SMoriah Waterland 	 * we use this routine to minimize the use of the aclass element by
1224*5c51f124SMoriah Waterland 	 * optimizing the use of the cf_ent->pkg_class element
1225*5c51f124SMoriah Waterland 	 */
1226*5c51f124SMoriah Waterland 
1227*5c51f124SMoriah Waterland 	(void) strlcpy(newclass, pinfo->aclass, sizeof (newclass));
1228*5c51f124SMoriah Waterland 	newcnt = 1;
1229*5c51f124SMoriah Waterland 
1230*5c51f124SMoriah Waterland 	oldclass = cf_ent->pkg_class;
1231*5c51f124SMoriah Waterland 	oldcnt = 0;
1232*5c51f124SMoriah Waterland 
1233*5c51f124SMoriah Waterland 	/*
1234*5c51f124SMoriah Waterland 	 * count the number of times the newclass will be used and see if it
1235*5c51f124SMoriah Waterland 	 * exceeds the number of times the oldclass is referenced
1236*5c51f124SMoriah Waterland 	 */
1237*5c51f124SMoriah Waterland 	pp = cf_ent->pinfo;
1238*5c51f124SMoriah Waterland 	while (pp) {
1239*5c51f124SMoriah Waterland 		if (pp->aclass[0] != '\0') {
1240*5c51f124SMoriah Waterland 			if (strcmp(pp->aclass, newclass) == 0)
1241*5c51f124SMoriah Waterland 				newcnt++;
1242*5c51f124SMoriah Waterland 			else if (strcmp(pp->aclass, oldclass) == 0)
1243*5c51f124SMoriah Waterland 				oldcnt++;
1244*5c51f124SMoriah Waterland 		}
1245*5c51f124SMoriah Waterland 		pp = pp->next;
1246*5c51f124SMoriah Waterland 	}
1247*5c51f124SMoriah Waterland 	if (newcnt > oldcnt) {
1248*5c51f124SMoriah Waterland 		pp = cf_ent->pinfo;
1249*5c51f124SMoriah Waterland 		while (pp) {
1250*5c51f124SMoriah Waterland 			if (pp->aclass[0] == '\0') {
1251*5c51f124SMoriah Waterland 				(void) strcpy(pp->aclass, oldclass);
1252*5c51f124SMoriah Waterland 			} else if (strcmp(pp->aclass, newclass) == 0) {
1253*5c51f124SMoriah Waterland 				pp->aclass[0] = '\0';
1254*5c51f124SMoriah Waterland 			}
1255*5c51f124SMoriah Waterland 			pp = pp->next;
1256*5c51f124SMoriah Waterland 		}
1257*5c51f124SMoriah Waterland 		(void) strcpy(cf_ent->pkg_class, newclass);
1258*5c51f124SMoriah Waterland 	}
1259*5c51f124SMoriah Waterland }
1260