xref: /titanic_51/usr/src/cmd/svr4pkg/libinst/pkgdbmerg.c (revision 6e1ae2a33c618c4c2b14aec7d2f21743ddea5837)
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 /*
23*6e1ae2a3SGary Pennington  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
245c51f124SMoriah Waterland  */
255c51f124SMoriah Waterland 
265c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
275c51f124SMoriah Waterland /* All Rights Reserved */
285c51f124SMoriah Waterland 
295c51f124SMoriah Waterland 
305c51f124SMoriah Waterland #include <stdio.h>
315c51f124SMoriah Waterland #include <signal.h>
325c51f124SMoriah Waterland #include <string.h>
335c51f124SMoriah Waterland #include <errno.h>
345c51f124SMoriah Waterland #include <unistd.h>
355c51f124SMoriah Waterland #include <stdlib.h>
365c51f124SMoriah Waterland #include <assert.h>
375c51f124SMoriah Waterland #include <pkgstrct.h>
385c51f124SMoriah Waterland #include <sys/stat.h>
395c51f124SMoriah Waterland #include <locale.h>
405c51f124SMoriah Waterland #include <libintl.h>
415c51f124SMoriah Waterland #include <pkginfo.h>
425c51f124SMoriah Waterland #include <instzones_api.h>
435c51f124SMoriah Waterland #include <pkglib.h>
445c51f124SMoriah Waterland #include <libinst.h>
455c51f124SMoriah Waterland #include <messages.h>
465c51f124SMoriah Waterland 
475c51f124SMoriah Waterland /* merg() return codes */
485c51f124SMoriah Waterland #define	MRG_SAME	0
495c51f124SMoriah Waterland #define	MRG_DIFFERENT	1
505c51f124SMoriah Waterland #define	MRG_REPLACE	2
515c51f124SMoriah Waterland 
525c51f124SMoriah Waterland /* typechg() return codes */
535c51f124SMoriah Waterland #define	TYPE_OK		0
545c51f124SMoriah Waterland #define	TYPE_WARNING	1
555c51f124SMoriah Waterland #define	TYPE_IGNORED	2
565c51f124SMoriah Waterland #define	TYPE_REPLACE	3
575c51f124SMoriah Waterland #define	TYPE_FATAL	4
585c51f124SMoriah Waterland 
595c51f124SMoriah Waterland /* message pool */
605c51f124SMoriah Waterland #define	ERR_OUTPUT	"unable to update package database"
615c51f124SMoriah Waterland #define	ERR_PINFO	"missing pinfo structure for <%s>"
625c51f124SMoriah Waterland #define	INFO_PROCESS	"   %2ld%% of information processed; continuing ..."
635c51f124SMoriah Waterland 
645c51f124SMoriah Waterland #define	WRN_NOTFILE	"WARNING: %s <no longer a regular file>"
655c51f124SMoriah Waterland #define	WRN_NOTSYMLN	"WARNING: %s <no longer a symbolic link>"
665c51f124SMoriah Waterland #define	WRN_NOTLINK	"WARNING: %s <no longer a linked file>"
675c51f124SMoriah Waterland #define	WRN_NOTDIR	"WARNING: %s <no longer a directory>"
685c51f124SMoriah Waterland #define	WRN_NOTCHAR	"WARNING: %s <no longer a character special device>"
695c51f124SMoriah Waterland #define	WRN_NOTBLOCK	"WARNING: %s <no longer a block special device>"
705c51f124SMoriah Waterland #define	WRN_NOTPIPE	"WARNING: %s <no longer a named pipe>"
715c51f124SMoriah Waterland #define	WRN_TOEXCL	"WARNING: cannot convert %s to an exclusive directory."
725c51f124SMoriah Waterland #define	WRN_ODDVERIFY	"WARNING: quick verify disabled for class %s."
735c51f124SMoriah Waterland 
745c51f124SMoriah Waterland #define	MSG_TYPIGN	"Object type change ignored."
755c51f124SMoriah Waterland #define	MSG_TYPE_ERR	"Package attempts fatal object type change."
765c51f124SMoriah Waterland 
775c51f124SMoriah Waterland extern char	*pkginst;
785c51f124SMoriah Waterland extern int	nosetuid, nocnflct, otherstoo;
795c51f124SMoriah Waterland 
805c51f124SMoriah Waterland /* pkgobjmap.c */
815c51f124SMoriah Waterland extern int	cp_cfent(struct cfent *cf_ent, struct cfextra *el_ent);
825c51f124SMoriah Waterland 
835c51f124SMoriah Waterland /* setlist.c */
845c51f124SMoriah Waterland extern void	cl_def_dverify(int idx);
855c51f124SMoriah Waterland 
865c51f124SMoriah Waterland char dbst = '\0';	/* usually set by installf() or removef() */
875c51f124SMoriah Waterland 
885c51f124SMoriah Waterland int files_installed(void);	/* return number of files installed. */
895c51f124SMoriah Waterland 
905c51f124SMoriah Waterland static int	errflg = 0;
915c51f124SMoriah Waterland static int	eptnum;
925c51f124SMoriah Waterland static int	installed;	/* # of files, already properly installed. */
935c51f124SMoriah Waterland static struct	pinfo	*pkgpinfo = (struct pinfo *)0;
945c51f124SMoriah Waterland 
955c51f124SMoriah Waterland static int	is_setuid(struct cfent *ent);
965c51f124SMoriah Waterland static int	is_setgid(struct cfent *ent);
975c51f124SMoriah Waterland static int	merg(struct cfextra *el_ent, struct cfent *cf_ent);
985c51f124SMoriah Waterland static int	do_like_ent(VFP_T *vfpo, struct cfextra *el_ent,
995c51f124SMoriah Waterland 		    struct cfent *cf_ent, int ctrl);
1005c51f124SMoriah Waterland static int	do_new_ent(VFP_T *vfpo, struct cfextra *el_ent, int ctrl);
101b46ec01aSok199659 static int	typechg(struct cfent *el_ent, struct cfent *cf_ent,
1025c51f124SMoriah Waterland 		    struct mergstat *mstat);
1035c51f124SMoriah Waterland 
1045c51f124SMoriah Waterland static void	set_change(struct cfextra *el_ent);
1055c51f124SMoriah Waterland static void	chgclass(struct cfent *cf_ent, struct pinfo *pinfo);
1065c51f124SMoriah Waterland static void	output(VFP_T *vfpo, struct cfent *ent, struct pinfo *pinfo);
1075c51f124SMoriah Waterland 
1085c51f124SMoriah Waterland /*
10962224350SCasper H.S. Dik  * This scans the extlist (pkgmap) and matches them to the database, copying
11062224350SCasper H.S. Dik  * out the modified contents to the file at tmpfp. It updates the mergstat
1115c51f124SMoriah Waterland  * structures and deals with administrative defaults regarding setuid and
1125c51f124SMoriah Waterland  * conflict.
1135c51f124SMoriah Waterland  */
1145c51f124SMoriah Waterland 
1155c51f124SMoriah Waterland int
11662224350SCasper H.S. Dik pkgdbmerg(PKGserver server, VFP_T *tmpvfp, struct cfextra **extlist)
1175c51f124SMoriah Waterland {
1185c51f124SMoriah Waterland 	static	struct	cfent	cf_ent;	/* scratch area */
1195c51f124SMoriah Waterland 	struct	cfextra	*el_ent;	/* extlist entry under review */
1205c51f124SMoriah Waterland 	int	n;
1215c51f124SMoriah Waterland 	int	changed;
1225c51f124SMoriah Waterland 	int	assume_ok = 0;
1235c51f124SMoriah Waterland 
1245c51f124SMoriah Waterland 	cf_ent.pinfo = (NULL);
1255c51f124SMoriah Waterland 	errflg = 0;
1265c51f124SMoriah Waterland 	installed = changed = 0;
1275c51f124SMoriah Waterland 
1285c51f124SMoriah Waterland 	vfpRewind(tmpvfp);
1295c51f124SMoriah Waterland 
13062224350SCasper H.S. Dik 	for (eptnum = 0; (el_ent = extlist[eptnum]) != NULL; eptnum++) {
1315c51f124SMoriah Waterland 		/*
1325c51f124SMoriah Waterland 		 * If there's an entry in the extlist at this position,
1335c51f124SMoriah Waterland 		 * process that entry.
1345c51f124SMoriah Waterland 		 */
1355c51f124SMoriah Waterland 		/* Metafiles don't get merged. */
1365c51f124SMoriah Waterland 		if ((el_ent->cf_ent.ftype == 'i') ||
1375c51f124SMoriah Waterland 			(el_ent->cf_ent.ftype == 'n')) {
1385c51f124SMoriah Waterland 			continue;
1395c51f124SMoriah Waterland 		}
1405c51f124SMoriah Waterland 
1415c51f124SMoriah Waterland 		/*
1425c51f124SMoriah Waterland 		 * Copy cfextra structure for duplicated paths.
1435c51f124SMoriah Waterland 		 * This is not just an optimization, it is
1445c51f124SMoriah Waterland 		 * necessary for correct operation of algorithm.
1455c51f124SMoriah Waterland 		 */
1465c51f124SMoriah Waterland 		if ((eptnum > 0) && (strncmp(el_ent->cf_ent.path,
1475c51f124SMoriah Waterland 		    extlist[eptnum-1]->cf_ent.path, PATH_MAX) == 0)) {
1485c51f124SMoriah Waterland 			memcpy(extlist[eptnum], extlist[eptnum-1],
1495c51f124SMoriah Waterland 			    sizeof (struct cfextra));
1505c51f124SMoriah Waterland 			continue;
1515c51f124SMoriah Waterland 		}
1525c51f124SMoriah Waterland 
1535c51f124SMoriah Waterland 		/*
1545c51f124SMoriah Waterland 		 * Normally dbst comes to us from installf() or
1555c51f124SMoriah Waterland 		 * removef() in order to specify their special
1565c51f124SMoriah Waterland 		 * database status codes. They cannot implement a
1575c51f124SMoriah Waterland 		 * quick verify (it just doesn't make sense). For
1585c51f124SMoriah Waterland 		 * that reason, we can test to see if we already have
1595c51f124SMoriah Waterland 		 * a special database status. If we don't (it's from
1605c51f124SMoriah Waterland 		 * pkgadd) then we can test to see if this is calling
1615c51f124SMoriah Waterland 		 * for a quick verify wherein we assume the install
1625c51f124SMoriah Waterland 		 * will work and fix it if it doesn't. In that case
1635c51f124SMoriah Waterland 		 * we set our own dbst to be ENTRY_OK.
1645c51f124SMoriah Waterland 		 */
1655c51f124SMoriah Waterland 		if (dbst == '\0') {
1665c51f124SMoriah Waterland 			if (cl_dvfy(el_ent->cf_ent.pkg_class_idx) ==
1675c51f124SMoriah Waterland 			    QKVERIFY) {
1685c51f124SMoriah Waterland 				assume_ok = 1;
1695c51f124SMoriah Waterland 			}
1705c51f124SMoriah Waterland 		} else {
1715c51f124SMoriah Waterland 			/*
1725c51f124SMoriah Waterland 			 * If we DO end up with an installf/quick
1735c51f124SMoriah Waterland 			 * verify combination, we fix that by simply
1745c51f124SMoriah Waterland 			 * denying the quick verify for this class.
1755c51f124SMoriah Waterland 			 * This forces everything to come out alright
1765c51f124SMoriah Waterland 			 * by forcing the standard assumptions as
1775c51f124SMoriah Waterland 			 * regards package database for the rest of
1785c51f124SMoriah Waterland 			 * the load.
1795c51f124SMoriah Waterland 			 */
1805c51f124SMoriah Waterland 			if (cl_dvfy(el_ent->cf_ent.pkg_class_idx) ==
1815c51f124SMoriah Waterland 			    QKVERIFY) {
1825c51f124SMoriah Waterland 				logerr(gettext(WRN_ODDVERIFY),
18362224350SCasper H.S. Dik 				    cl_nam(el_ent->cf_ent.pkg_class_idx));
1845c51f124SMoriah Waterland 				/*
1855c51f124SMoriah Waterland 				 * Set destination verification to
1865c51f124SMoriah Waterland 				 * default.
1875c51f124SMoriah Waterland 				 */
18862224350SCasper H.S. Dik 				cl_def_dverify(el_ent->cf_ent.pkg_class_idx);
1895c51f124SMoriah Waterland 			}
1905c51f124SMoriah Waterland 		}
1915c51f124SMoriah Waterland 
1925c51f124SMoriah Waterland 		/*
1935c51f124SMoriah Waterland 		 * Comply with administrative requirements regarding
1945c51f124SMoriah Waterland 		 * setuid/setgid processes.
1955c51f124SMoriah Waterland 		 */
1965c51f124SMoriah Waterland 		if (is_setuid(&(el_ent->cf_ent))) {
1975c51f124SMoriah Waterland 			el_ent->mstat.setuid = 1;
1985c51f124SMoriah Waterland 		}
1995c51f124SMoriah Waterland 		if (is_setgid(&(el_ent->cf_ent))) {
2005c51f124SMoriah Waterland 			el_ent->mstat.setgid = 1;
2015c51f124SMoriah Waterland 		}
2025c51f124SMoriah Waterland 
2035c51f124SMoriah Waterland 		/*
2045c51f124SMoriah Waterland 		 * If setuid/setgid processes are not allowed, reset
2055c51f124SMoriah Waterland 		 * those bits.
2065c51f124SMoriah Waterland 		 */
2075c51f124SMoriah Waterland 		if (nosetuid && (el_ent->mstat.setgid ||
2085c51f124SMoriah Waterland 		    el_ent->mstat.setuid)) {
20962224350SCasper H.S. Dik 			el_ent->cf_ent.ainfo.mode &= ~(S_ISUID | S_ISGID);
2105c51f124SMoriah Waterland 		}
2115c51f124SMoriah Waterland 
2125c51f124SMoriah Waterland 		/* Search package database for this entry. */
21362224350SCasper H.S. Dik 		n = srchcfile(&cf_ent, el_ent->cf_ent.path, server);
2145c51f124SMoriah Waterland 
2155c51f124SMoriah Waterland 		/*
2165c51f124SMoriah Waterland 		 * If there was an error, note it and return an error
2175c51f124SMoriah Waterland 		 * flag.
2185c51f124SMoriah Waterland 		 */
2195c51f124SMoriah Waterland 		if (n < 0) {
2205c51f124SMoriah Waterland 			char	*errstr = getErrstr();
22162224350SCasper H.S. Dik 			progerr(ERR_CFBAD);
22262224350SCasper H.S. Dik 			logerr(gettext("pathname: %s"),
2235c51f124SMoriah Waterland 			    (cf_ent.path && *cf_ent.path) ?
2245c51f124SMoriah Waterland 			    cf_ent.path : "Unknown");
22562224350SCasper H.S. Dik 			logerr(gettext("problem: %s"),
2265c51f124SMoriah Waterland 			    (errstr && *errstr) ? errstr : "Unknown");
2275c51f124SMoriah Waterland 			return (-1);
2285c51f124SMoriah Waterland 		/*
2295c51f124SMoriah Waterland 		 * If there was a match, then merge them into a
2305c51f124SMoriah Waterland 		 * single entry.
2315c51f124SMoriah Waterland 		 */
2325c51f124SMoriah Waterland 		} else if (n == 1) {
2335c51f124SMoriah Waterland 			/*
2345c51f124SMoriah Waterland 			 * If this package is overwriting a setuid or
2355c51f124SMoriah Waterland 			 * setgid process, set the status bits so we
2365c51f124SMoriah Waterland 			 * can inform the administrator.
2375c51f124SMoriah Waterland 			 */
2385c51f124SMoriah Waterland 			if (is_setuid(&cf_ent)) {
2395c51f124SMoriah Waterland 				el_ent->mstat.osetuid = 1;
2405c51f124SMoriah Waterland 			}
2415c51f124SMoriah Waterland 
2425c51f124SMoriah Waterland 			if (is_setgid(&cf_ent)) {
2435c51f124SMoriah Waterland 				el_ent->mstat.osetgid = 1;
2445c51f124SMoriah Waterland 			}
2455c51f124SMoriah Waterland 			/*
2465c51f124SMoriah Waterland 			 * Detect if a symlink has changed to directory
2475c51f124SMoriah Waterland 			 * If so mark all the files/dir supposed to be
2485c51f124SMoriah Waterland 			 * iniside this dir, so that they are not miss
2495c51f124SMoriah Waterland 			 * understood by do_new_ent later as already
2505c51f124SMoriah Waterland 			 * installed.
2515c51f124SMoriah Waterland 			 */
25262224350SCasper H.S. Dik 			if ((cf_ent.ftype == 's') &&
2535c51f124SMoriah Waterland 			    (el_ent->cf_ent.ftype == 'd')) {
2545c51f124SMoriah Waterland 				int i;
2555c51f124SMoriah Waterland 				int plen = strlen(el_ent->cf_ent.path);
2565c51f124SMoriah Waterland 				for (i = eptnum + 1; extlist[i]; i++) {
2575c51f124SMoriah Waterland 					if (strncmp(el_ent->cf_ent.path,
2585c51f124SMoriah Waterland 					    extlist[i]->cf_ent.path,
2595c51f124SMoriah Waterland 					    plen) != 0)
2605c51f124SMoriah Waterland 						break;
2615c51f124SMoriah Waterland 					extlist[i]->mstat.parentsyml2dir
2625c51f124SMoriah Waterland 					    = 1;
2635c51f124SMoriah Waterland 				}
2645c51f124SMoriah Waterland 			}
2655c51f124SMoriah Waterland 
26662224350SCasper H.S. Dik 			if (do_like_ent(tmpvfp, el_ent, &cf_ent, assume_ok)) {
2675c51f124SMoriah Waterland 				changed++;
2685c51f124SMoriah Waterland 			}
2695c51f124SMoriah Waterland 
2705c51f124SMoriah Waterland 		} else {
2715c51f124SMoriah Waterland 			/*
27262224350SCasper H.S. Dik 			 * The file doesn't exist in the database.
2735c51f124SMoriah Waterland 			 */
2745c51f124SMoriah Waterland 			if (do_new_ent(tmpvfp, el_ent, assume_ok)) {
2755c51f124SMoriah Waterland 				changed++;
2765c51f124SMoriah Waterland 			}
2775c51f124SMoriah Waterland 		}
2785c51f124SMoriah Waterland 	}
2795c51f124SMoriah Waterland 
2805c51f124SMoriah Waterland 	return (errflg ? -1 : changed);
2815c51f124SMoriah Waterland }
2825c51f124SMoriah Waterland 
2835c51f124SMoriah Waterland /*
2845c51f124SMoriah Waterland  * Merge a new entry with an installed package object of the same name and
2855c51f124SMoriah Waterland  * insert that object into the package database. Obey administrative defaults
2865c51f124SMoriah Waterland  * as regards conflicting files.
2875c51f124SMoriah Waterland  */
2885c51f124SMoriah Waterland 
2895c51f124SMoriah Waterland static int
2905c51f124SMoriah Waterland do_like_ent(VFP_T *vfpo, struct cfextra *el_ent, struct cfent *cf_ent, int ctrl)
2915c51f124SMoriah Waterland {
2925c51f124SMoriah Waterland 	int	stflag, ignore, changed, mrg_result;
2935c51f124SMoriah Waterland 
2945c51f124SMoriah Waterland 	ignore = changed = 0;
2955c51f124SMoriah Waterland 
2965c51f124SMoriah Waterland 	/*
2975c51f124SMoriah Waterland 	 * Construct the record defining the current package. If there are
2985c51f124SMoriah Waterland 	 * other packages involved, this will be appended to the existing
2995c51f124SMoriah Waterland 	 * list. If this is an update of the same package, it will get merged
3005c51f124SMoriah Waterland 	 * with the existing record. If this is a preloaded record (like from
3015c51f124SMoriah Waterland 	 * a dryrun file), it will keep it's current pinfo pointer and will
3025c51f124SMoriah Waterland 	 * pass it on to the record from the contents file - because on the
3035c51f124SMoriah Waterland 	 * final continuation, the contents file will be wrong.
3045c51f124SMoriah Waterland 	 */
3055c51f124SMoriah Waterland 	if (el_ent->mstat.preloaded) {
3065c51f124SMoriah Waterland 		struct pinfo *pkginfo;
3075c51f124SMoriah Waterland 
3085c51f124SMoriah Waterland 		/* Contents file is not to be trusted for this list. */
3095c51f124SMoriah Waterland 		pkginfo = cf_ent->pinfo;
3105c51f124SMoriah Waterland 
3115c51f124SMoriah Waterland 		/* Free the potentially bogus list. */
3125c51f124SMoriah Waterland 		while (pkginfo) {
3135c51f124SMoriah Waterland 			struct pinfo *next;
3145c51f124SMoriah Waterland 			next = pkginfo->next;
3155c51f124SMoriah Waterland 			free(pkginfo);
3165c51f124SMoriah Waterland 			pkginfo = next;
3175c51f124SMoriah Waterland 		}
3185c51f124SMoriah Waterland 
3195c51f124SMoriah Waterland 		cf_ent->pinfo = el_ent->cf_ent.pinfo;
3205c51f124SMoriah Waterland 	}
3215c51f124SMoriah Waterland 
3225c51f124SMoriah Waterland 	pkgpinfo = eptstat(cf_ent, pkginst, DUP_ENTRY);
3235c51f124SMoriah Waterland 
3245c51f124SMoriah Waterland 	stflag = pkgpinfo->status;
3255c51f124SMoriah Waterland 
3265c51f124SMoriah Waterland 	if (otherstoo)
3275c51f124SMoriah Waterland 		el_ent->mstat.shared = 1;
3285c51f124SMoriah Waterland 
3295c51f124SMoriah Waterland 	/* If it's marked for erasure, make it official */
3305c51f124SMoriah Waterland 	if (el_ent->cf_ent.ftype == RM_RDY) {
3315c51f124SMoriah Waterland 		if (!errflg) {
3325c51f124SMoriah Waterland 			pkgpinfo = eptstat(cf_ent, pkginst, RM_RDY);
3335c51f124SMoriah Waterland 
3345c51f124SMoriah Waterland 			/*
3355c51f124SMoriah Waterland 			 * Get copy of status character in case the object is
3365c51f124SMoriah Waterland 			 * "shared" by a server, in which case we need to
3375c51f124SMoriah Waterland 			 * maintain the shared status after the entry is
3385c51f124SMoriah Waterland 			 * written to the package database with RM_RDY
3395c51f124SMoriah Waterland 			 * status. This is needed to support the `removef'
3405c51f124SMoriah Waterland 			 * command.
3415c51f124SMoriah Waterland 			 */
3425c51f124SMoriah Waterland 			stflag = pkgpinfo->status;
3435c51f124SMoriah Waterland 			pkgpinfo->status = RM_RDY;
3445c51f124SMoriah Waterland 
3455c51f124SMoriah Waterland 			if (putcvfpfile(cf_ent, vfpo)) {
3465c51f124SMoriah Waterland 				progerr(gettext(ERR_OUTPUT));
3475c51f124SMoriah Waterland 				quit(99);
3485c51f124SMoriah Waterland 			}
3495c51f124SMoriah Waterland 
3505c51f124SMoriah Waterland 			/*
3515c51f124SMoriah Waterland 			 * If object is provided by a server, allocate an
3525c51f124SMoriah Waterland 			 * info block and set the status to indicate this.
3535c51f124SMoriah Waterland 			 * This is needed to support the `removef' command.
3545c51f124SMoriah Waterland 			 */
3555c51f124SMoriah Waterland 			if (stflag == SERVED_FILE) {
3565c51f124SMoriah Waterland 				el_ent->cf_ent.pinfo =
3575c51f124SMoriah Waterland 				    (struct pinfo *)calloc(1,
3585c51f124SMoriah Waterland 				    sizeof (struct pinfo));
3595c51f124SMoriah Waterland 				el_ent->cf_ent.pinfo->next = NULL;
3605c51f124SMoriah Waterland 				el_ent->cf_ent.pinfo->status = SERVED_FILE;
3615c51f124SMoriah Waterland 			}
3625c51f124SMoriah Waterland 		}
3635c51f124SMoriah Waterland 		return (1);
3645c51f124SMoriah Waterland 	}
3655c51f124SMoriah Waterland 
3665c51f124SMoriah Waterland 	/*
3675c51f124SMoriah Waterland 	 * If there is no package associated with it, there's something
3685c51f124SMoriah Waterland 	 * very wrong.
3695c51f124SMoriah Waterland 	 */
3705c51f124SMoriah Waterland 	if (!pkgpinfo) {
3715c51f124SMoriah Waterland 		progerr(gettext(ERR_PINFO), cf_ent->path);
3725c51f124SMoriah Waterland 		quit(99);
3735c51f124SMoriah Waterland 	}
3745c51f124SMoriah Waterland 
3755c51f124SMoriah Waterland 	/*
3765c51f124SMoriah Waterland 	 * Do not allow installation if nocnflct is set and other packages
3775c51f124SMoriah Waterland 	 * reference this pathname. The cp_cfent() function below writes the
3785c51f124SMoriah Waterland 	 * information from the installed file over the new entry, so the
3795c51f124SMoriah Waterland 	 * package database will be unchanged.
3805c51f124SMoriah Waterland 	 *
3815c51f124SMoriah Waterland 	 * By the way, ftype "e" is often shared and that's OK, so ftype
3825c51f124SMoriah Waterland 	 * "e" doesn't count here.
3835c51f124SMoriah Waterland 	 */
3845c51f124SMoriah Waterland 	if ((nocnflct && el_ent->mstat.shared && el_ent->cf_ent.ftype != 'e')) {
3855c51f124SMoriah Waterland 		/*
3865c51f124SMoriah Waterland 		 * First set the attrchg and contchg entries for proper
3875c51f124SMoriah Waterland 		 * messaging in the install phase.
3885c51f124SMoriah Waterland 		 */
3895c51f124SMoriah Waterland 		set_change(el_ent);
3905c51f124SMoriah Waterland 
3915c51f124SMoriah Waterland 		/*
3925c51f124SMoriah Waterland 		 * Now overwrite the new entry with the entry for the
3935c51f124SMoriah Waterland 		 * currently installed object.
3945c51f124SMoriah Waterland 		 */
3955c51f124SMoriah Waterland 		if (cp_cfent(cf_ent, el_ent) == 0)
3965c51f124SMoriah Waterland 			quit(99);
3975c51f124SMoriah Waterland 
3985c51f124SMoriah Waterland 		ignore++;
3995c51f124SMoriah Waterland 	} else {
4005c51f124SMoriah Waterland 		mrg_result = merg(el_ent, cf_ent);
4015c51f124SMoriah Waterland 
4025c51f124SMoriah Waterland 		switch (mrg_result) {
4035c51f124SMoriah Waterland 		    case MRG_SAME:
4045c51f124SMoriah Waterland 			break;
4055c51f124SMoriah Waterland 
4065c51f124SMoriah Waterland 		    case MRG_DIFFERENT:
4075c51f124SMoriah Waterland 			changed++;
4085c51f124SMoriah Waterland 			break;
4095c51f124SMoriah Waterland 
4105c51f124SMoriah Waterland 		    case MRG_REPLACE:
4115c51f124SMoriah Waterland 			/*
4125c51f124SMoriah Waterland 			 * We'll pick one or the other later. For now, cf_ent
4135c51f124SMoriah Waterland 			 * will have the fault value and el_ent will retain
4145c51f124SMoriah Waterland 			 * the other value. This is the only state that allows
4155c51f124SMoriah Waterland 			 * the database and the pkgmap to differ.
4165c51f124SMoriah Waterland 			 */
4175c51f124SMoriah Waterland 
4185c51f124SMoriah Waterland 			el_ent->mstat.contchg = 1;	/* subject to change */
4195c51f124SMoriah Waterland 			ignore++;
4205c51f124SMoriah Waterland 			break;
4215c51f124SMoriah Waterland 
4225c51f124SMoriah Waterland 		    default:
4235c51f124SMoriah Waterland 			break;
4245c51f124SMoriah Waterland 		}
4255c51f124SMoriah Waterland 	}
4265c51f124SMoriah Waterland 
4275c51f124SMoriah Waterland 	/* el_ent structure now contains updated entry */
4285c51f124SMoriah Waterland 	if (!el_ent->mstat.contchg && !ignore) {
4295c51f124SMoriah Waterland 		/*
4305c51f124SMoriah Waterland 		 * We know the DB entry matches the pkgmap, so now we need to
4315c51f124SMoriah Waterland 		 * see if the actual object matches the pkgmap.
4325c51f124SMoriah Waterland 		 */
4335c51f124SMoriah Waterland 		set_change(el_ent);
4345c51f124SMoriah Waterland 	}
4355c51f124SMoriah Waterland 
4365c51f124SMoriah Waterland 	if (!errflg) {
4375c51f124SMoriah Waterland 		if (ctrl == 1) {	/* quick verify assumes OK */
4385c51f124SMoriah Waterland 			/*
4395c51f124SMoriah Waterland 			 * The pkgpinfo entry is already correctly
4405c51f124SMoriah Waterland 			 * constructed. Look into dropping this soon.
4415c51f124SMoriah Waterland 			 */
4425c51f124SMoriah Waterland 			pkgpinfo = eptstat(&(el_ent->cf_ent), pkginst,
4435c51f124SMoriah Waterland 			    ENTRY_OK);
4445c51f124SMoriah Waterland 
4455c51f124SMoriah Waterland 			if (stflag != DUP_ENTRY) {
4465c51f124SMoriah Waterland 				changed++;
4475c51f124SMoriah Waterland 			}
4485c51f124SMoriah Waterland 
4495c51f124SMoriah Waterland 			/*
4505c51f124SMoriah Waterland 			 * We could trust the prior pkginfo entry, but things
4515c51f124SMoriah Waterland 			 * could have changed and  we need to update the
4525c51f124SMoriah Waterland 			 * fs_tab[] anyway. We check for a server object
4535c51f124SMoriah Waterland 			 * here.
4545c51f124SMoriah Waterland 			 */
4555c51f124SMoriah Waterland 			if (is_served(el_ent->server_path,
4565c51f124SMoriah Waterland 			    &(el_ent->fsys_value)))
4575c51f124SMoriah Waterland 				pkgpinfo->status = SERVED_FILE;
4585c51f124SMoriah Waterland 		} else {
4595c51f124SMoriah Waterland 			if (!ignore && el_ent->mstat.contchg) {
4605c51f124SMoriah Waterland 				pkgpinfo =
4615c51f124SMoriah Waterland 				    eptstat(&(el_ent->cf_ent), pkginst,
4625c51f124SMoriah Waterland 				    (dbst ? dbst : CONFIRM_CONT));
4635c51f124SMoriah Waterland 			} else if (!ignore && el_ent->mstat.attrchg) {
4645c51f124SMoriah Waterland 				pkgpinfo =
4655c51f124SMoriah Waterland 				    eptstat(&(el_ent->cf_ent), pkginst,
4665c51f124SMoriah Waterland 				    (dbst ? dbst : CONFIRM_ATTR));
4675c51f124SMoriah Waterland 			} else if (!ignore && el_ent->mstat.shared) {
4685c51f124SMoriah Waterland 				pkgpinfo =
4695c51f124SMoriah Waterland 				    eptstat(&(el_ent->cf_ent), pkginst,
4705c51f124SMoriah Waterland 				    dbst);
4715c51f124SMoriah Waterland 				changed++;
4725c51f124SMoriah Waterland 			} else if (stflag != DUP_ENTRY) {
4735c51f124SMoriah Waterland 				pkgpinfo = eptstat(&(el_ent->cf_ent),
4745c51f124SMoriah Waterland 				    pkginst, '\0');
4755c51f124SMoriah Waterland 				if (stflag != ENTRY_OK) {
4765c51f124SMoriah Waterland 					changed++;
4775c51f124SMoriah Waterland 				}
4785c51f124SMoriah Waterland 			}
4795c51f124SMoriah Waterland 		}
4805c51f124SMoriah Waterland 
4815c51f124SMoriah Waterland 		if (mrg_result == MRG_REPLACE) {
4825c51f124SMoriah Waterland 			/*
4835c51f124SMoriah Waterland 			 * Put the original package database entry back into
4845c51f124SMoriah Waterland 			 * the package database for now.
4855c51f124SMoriah Waterland 			 */
4865c51f124SMoriah Waterland 			output(vfpo, cf_ent, pkgpinfo);
4875c51f124SMoriah Waterland 		} else {
4885c51f124SMoriah Waterland 			/* Put the merged entry into the package database. */
4895c51f124SMoriah Waterland 			output(vfpo, &(el_ent->cf_ent), pkgpinfo);
4905c51f124SMoriah Waterland 		}
4915c51f124SMoriah Waterland 	}
4925c51f124SMoriah Waterland 
4935c51f124SMoriah Waterland 	if (pkgpinfo->aclass[0] != '\0') {
4945c51f124SMoriah Waterland 		(void) strcpy(el_ent->cf_ent.pkg_class, pkgpinfo->aclass);
4955c51f124SMoriah Waterland 	}
4965c51f124SMoriah Waterland 
4975c51f124SMoriah Waterland 	/*
4985c51f124SMoriah Waterland 	 * If a sym link entry exists in the contents file and
4995c51f124SMoriah Waterland 	 * and the destination of the link does not exist on the the system
5005c51f124SMoriah Waterland 	 * then the contents file needs to be updated appropriately so a
5015c51f124SMoriah Waterland 	 * subsequent invocation of "installf -f" will create the destination.
5025c51f124SMoriah Waterland 	 */
5035c51f124SMoriah Waterland 	if (el_ent->mstat.contchg && pkgpinfo->status == INST_RDY) {
5045c51f124SMoriah Waterland 		changed++;
5055c51f124SMoriah Waterland 	}
5065c51f124SMoriah Waterland 
5075c51f124SMoriah Waterland 	if (!(el_ent->mstat.preloaded))
5085c51f124SMoriah Waterland 		el_ent->cf_ent.pinfo = NULL;
5095c51f124SMoriah Waterland 
5105c51f124SMoriah Waterland 	/*
5115c51f124SMoriah Waterland 	 * If no change during the merg and we don't have a case where types
5125c51f124SMoriah Waterland 	 * were different in odd ways, count this as installed.
5135c51f124SMoriah Waterland 	 */
5145c51f124SMoriah Waterland 	if (!el_ent->mstat.attrchg && !el_ent->mstat.contchg &&
5155c51f124SMoriah Waterland 	    !el_ent->mstat.replace)
5165c51f124SMoriah Waterland 		installed++;
5175c51f124SMoriah Waterland 	return (changed);
5185c51f124SMoriah Waterland }
5195c51f124SMoriah Waterland 
5205c51f124SMoriah Waterland /* Insert an entirely new entry into the package database. */
5215c51f124SMoriah Waterland static int
5225c51f124SMoriah Waterland do_new_ent(VFP_T *vfpo, struct cfextra *el_ent, int ctrl)
5235c51f124SMoriah Waterland {
5245c51f124SMoriah Waterland 	struct pinfo	*pinfo;
5255c51f124SMoriah Waterland 	char		*tp;
5265c51f124SMoriah Waterland 	int		changed = 0;
5275c51f124SMoriah Waterland 
5285c51f124SMoriah Waterland 	if (el_ent->cf_ent.ftype == RM_RDY) {
5295c51f124SMoriah Waterland 		return (0);
5305c51f124SMoriah Waterland 	}
5315c51f124SMoriah Waterland 
5325c51f124SMoriah Waterland 	tp = el_ent->server_path;
5335c51f124SMoriah Waterland 	/*
5345c51f124SMoriah Waterland 	 * Check the file/dir existence only if any of the parent directory
5355c51f124SMoriah Waterland 	 * of the file/dir has not changed from symbolic link to directory.
5365c51f124SMoriah Waterland 	 * At this time we are only doing a dry run, the symlink is not yet
5375c51f124SMoriah Waterland 	 * replaced, so if this is done directly then access will result in
5385c51f124SMoriah Waterland 	 * incorrect information in case a file with the same attr and cont
5395c51f124SMoriah Waterland 	 * exists in the link target.
5405c51f124SMoriah Waterland 	 */
5415c51f124SMoriah Waterland 	if ((!el_ent->mstat.parentsyml2dir) && (access(tp, F_OK) == 0)) {
5425c51f124SMoriah Waterland 		/*
5435c51f124SMoriah Waterland 		 * Path exists, and although its not referenced by any
5445c51f124SMoriah Waterland 		 * package we make it look like it is so it appears as a
5455c51f124SMoriah Waterland 		 * conflicting file in case the user doesn't want it
5465c51f124SMoriah Waterland 		 * installed. We set the rogue flag to distinguish this from
5475c51f124SMoriah Waterland 		 * package object conflicts if the administrator is queried
5485c51f124SMoriah Waterland 		 * about this later. Note that noconflict means NO conflict
5495c51f124SMoriah Waterland 		 * at the file level. Even rogue files count.
5505c51f124SMoriah Waterland 		 */
5515c51f124SMoriah Waterland 		el_ent->mstat.shared = 1;
5525c51f124SMoriah Waterland 		el_ent->mstat.rogue = 1;
5535c51f124SMoriah Waterland 		set_change(el_ent);
5545c51f124SMoriah Waterland 	} else {
5555c51f124SMoriah Waterland 		/* since path doesn't exist, we're changing everything */
5565c51f124SMoriah Waterland 		el_ent->mstat.rogue = 0;
5575c51f124SMoriah Waterland 		el_ent->mstat.contchg = 1;
5585c51f124SMoriah Waterland 		el_ent->mstat.attrchg = 1;
5595c51f124SMoriah Waterland 	}
5605c51f124SMoriah Waterland 
5615c51f124SMoriah Waterland 	if (el_ent->cf_ent.ainfo.mode == WILDCARD) {
5625c51f124SMoriah Waterland 		if (el_ent->cf_ent.ftype == 'd') {
5635c51f124SMoriah Waterland 			el_ent->cf_ent.ainfo.mode = DEFAULT_MODE;
5645c51f124SMoriah Waterland 		} else {
5655c51f124SMoriah Waterland 			el_ent->cf_ent.ainfo.mode = DEFAULT_MODE_FILE;
5665c51f124SMoriah Waterland 		}
5675c51f124SMoriah Waterland 		logerr(WRN_SET_DEF_MODE, el_ent->cf_ent.path,
5685c51f124SMoriah Waterland 		    (int)el_ent->cf_ent.ainfo.mode);
5695c51f124SMoriah Waterland 	}
5705c51f124SMoriah Waterland 
5715c51f124SMoriah Waterland 	if (strcmp(el_ent->cf_ent.ainfo.owner, DB_UNDEFINED_ENTRY) == 0)
5725c51f124SMoriah Waterland 		(void) strcpy(el_ent->cf_ent.ainfo.owner,
5735c51f124SMoriah Waterland 				DEFAULT_OWNER);
5745c51f124SMoriah Waterland 	if (strcmp(el_ent->cf_ent.ainfo.group, DB_UNDEFINED_ENTRY) == 0)
5755c51f124SMoriah Waterland 		(void) strcpy(el_ent->cf_ent.ainfo.group,
5765c51f124SMoriah Waterland 				DEFAULT_GROUP);
5775c51f124SMoriah Waterland 
5785c51f124SMoriah Waterland 	/*
5795c51f124SMoriah Waterland 	 * Do not allow installation if nocnflct is set and this pathname is
5805c51f124SMoriah Waterland 	 * already in place. Since this entry is new (not associated with a
5815c51f124SMoriah Waterland 	 * package), we don't issue anything to the database we're building.
5825c51f124SMoriah Waterland 	 */
5835c51f124SMoriah Waterland 	if (nocnflct && el_ent->mstat.shared) {
5845c51f124SMoriah Waterland 		return (0);
5855c51f124SMoriah Waterland 	}
5865c51f124SMoriah Waterland 
5875c51f124SMoriah Waterland 	if (!errflg) {
5885c51f124SMoriah Waterland 		if (el_ent->mstat.preloaded) {
5895c51f124SMoriah Waterland 			/* Add this package to the already established list. */
5905c51f124SMoriah Waterland 			pinfo = eptstat(&(el_ent->cf_ent), pkginst, DUP_ENTRY);
5915c51f124SMoriah Waterland 		} else {
5925c51f124SMoriah Waterland 			el_ent->cf_ent.npkgs = 1;
5935c51f124SMoriah Waterland 			pinfo = (struct pinfo *)calloc(1,
5945c51f124SMoriah Waterland 			    sizeof (struct pinfo));
5955c51f124SMoriah Waterland 			if (!pinfo) {
5965c51f124SMoriah Waterland 				progerr(gettext(ERR_MEMORY), errno);
5975c51f124SMoriah Waterland 				quit(99);
5985c51f124SMoriah Waterland 			}
5995c51f124SMoriah Waterland 			el_ent->cf_ent.pinfo = pinfo;
6005c51f124SMoriah Waterland 			(void) strcpy(pinfo->pkg, pkginst);
6015c51f124SMoriah Waterland 		}
6025c51f124SMoriah Waterland 
6035c51f124SMoriah Waterland 		if (ctrl == 1) {	/* quick verify assumes OK */
6045c51f124SMoriah Waterland 			pinfo->status = dbst ? dbst : ENTRY_OK;
6055c51f124SMoriah Waterland 			/*
6065c51f124SMoriah Waterland 			 * The entry won't be verified, but the entry in the
6075c51f124SMoriah Waterland 			 * database isn't necessarily ENTRY_OK. If this is
6085c51f124SMoriah Waterland 			 * coming from a server, we need to note that
6095c51f124SMoriah Waterland 			 * instead.
6105c51f124SMoriah Waterland 			 */
6115c51f124SMoriah Waterland 			if (is_served(el_ent->server_path,
6125c51f124SMoriah Waterland 			    &(el_ent->fsys_value)))
6135c51f124SMoriah Waterland 				pinfo->status = SERVED_FILE;
6145c51f124SMoriah Waterland 		} else {
6155c51f124SMoriah Waterland 			pinfo->status = dbst ? dbst : CONFIRM_CONT;
6165c51f124SMoriah Waterland 		}
6175c51f124SMoriah Waterland 
6185c51f124SMoriah Waterland 		output(vfpo, &(el_ent->cf_ent), pinfo);
6195c51f124SMoriah Waterland 		changed++;
6205c51f124SMoriah Waterland 
6215c51f124SMoriah Waterland 		free(pinfo);
6225c51f124SMoriah Waterland 		el_ent->cf_ent.pinfo = NULL;
6235c51f124SMoriah Waterland 		}
6245c51f124SMoriah Waterland 	if (!el_ent->mstat.attrchg && !el_ent->mstat.contchg) {
6255c51f124SMoriah Waterland 		installed++;
6265c51f124SMoriah Waterland 	}
6275c51f124SMoriah Waterland 
6285c51f124SMoriah Waterland 	return (changed);
6295c51f124SMoriah Waterland }
6305c51f124SMoriah Waterland 
6315c51f124SMoriah Waterland int
6325c51f124SMoriah Waterland files_installed(void)
6335c51f124SMoriah Waterland {
6345c51f124SMoriah Waterland 	return (installed);
6355c51f124SMoriah Waterland }
6365c51f124SMoriah Waterland 
6375c51f124SMoriah Waterland /*
6385c51f124SMoriah Waterland  * This function determines if there is a difference between the file on
6395c51f124SMoriah Waterland  * the disk and the file to be laid down. It set's mstat flags attrchg
6405c51f124SMoriah Waterland  * and contchg accordingly.
6415c51f124SMoriah Waterland  */
6425c51f124SMoriah Waterland static void
6435c51f124SMoriah Waterland set_change(struct cfextra *el_ent)
6445c51f124SMoriah Waterland {
6455c51f124SMoriah Waterland 	int	n;
6465c51f124SMoriah Waterland 	char 	*tp;
6475c51f124SMoriah Waterland 
6485c51f124SMoriah Waterland 	tp = el_ent->server_path;
6495c51f124SMoriah Waterland 	if ((el_ent->cf_ent.ftype == 'f') || (el_ent->cf_ent.ftype == 'e') ||
6505c51f124SMoriah Waterland 		(el_ent->cf_ent.ftype == 'v')) {
6515c51f124SMoriah Waterland 		if (cverify(0, &(el_ent->cf_ent.ftype), tp,
6525c51f124SMoriah Waterland 		    &(el_ent->cf_ent.cinfo), 1)) {
6535c51f124SMoriah Waterland 			el_ent->mstat.contchg = 1;
6545c51f124SMoriah Waterland 		} else if (!el_ent->mstat.contchg && !el_ent->mstat.attrchg) {
6555c51f124SMoriah Waterland 			if (averify(0, &(el_ent->cf_ent.ftype), tp,
6565c51f124SMoriah Waterland 			    &(el_ent->cf_ent.ainfo)))
6575c51f124SMoriah Waterland 				el_ent->mstat.attrchg = 1;
6585c51f124SMoriah Waterland 		}
6595c51f124SMoriah Waterland 	} else if (!el_ent->mstat.attrchg &&
6605c51f124SMoriah Waterland 		((el_ent->cf_ent.ftype == 'd') ||
6615c51f124SMoriah Waterland 		(el_ent->cf_ent.ftype == 'x') ||
6625c51f124SMoriah Waterland 		(el_ent->cf_ent.ftype == 'c') ||
6635c51f124SMoriah Waterland 		(el_ent->cf_ent.ftype == 'b') ||
6645c51f124SMoriah Waterland 		(el_ent->cf_ent.ftype == 'p'))) {
6655c51f124SMoriah Waterland 		n = averify(0, &(el_ent->cf_ent.ftype), tp,
6665c51f124SMoriah Waterland 		    &(el_ent->cf_ent.ainfo));
6675c51f124SMoriah Waterland 		if (n == VE_ATTR)
6685c51f124SMoriah Waterland 			el_ent->mstat.attrchg = 1;
6695c51f124SMoriah Waterland 		else if (n && (n != VE_EXIST)) {
6705c51f124SMoriah Waterland 			el_ent->mstat.contchg = 1;
6715c51f124SMoriah Waterland 		}
6725c51f124SMoriah Waterland 	} else if (!el_ent->mstat.attrchg &&
6735c51f124SMoriah Waterland 		((el_ent->cf_ent.ftype == 's') ||
6745c51f124SMoriah Waterland 		(el_ent->cf_ent.ftype == 'l'))) {
6755c51f124SMoriah Waterland 		n = averify(0, &(el_ent->cf_ent.ftype), tp,
6765c51f124SMoriah Waterland 		    &(el_ent->cf_ent.ainfo));
6775c51f124SMoriah Waterland 		if (n == VE_ATTR)
6785c51f124SMoriah Waterland 			el_ent->mstat.attrchg = 1;
6795c51f124SMoriah Waterland 		else if (n && (n == VE_EXIST)) {
6805c51f124SMoriah Waterland 			el_ent->mstat.contchg = 1;
6815c51f124SMoriah Waterland 		}
6825c51f124SMoriah Waterland 	}
6835c51f124SMoriah Waterland }
6845c51f124SMoriah Waterland 
6855c51f124SMoriah Waterland static int
6865c51f124SMoriah Waterland is_setuid(struct cfent *ent)
6875c51f124SMoriah Waterland {
6885c51f124SMoriah Waterland 	return (((ent->ftype == 'f') || (ent->ftype == 'v') ||
6895c51f124SMoriah Waterland 		(ent->ftype == 'e')) &&
6905c51f124SMoriah Waterland 		(ent->ainfo.mode != BADMODE) &&
6915c51f124SMoriah Waterland 		(ent->ainfo.mode != WILDCARD) &&
6925c51f124SMoriah Waterland 		(ent->ainfo.mode & S_ISUID));
6935c51f124SMoriah Waterland }
6945c51f124SMoriah Waterland 
6955c51f124SMoriah Waterland static int
6965c51f124SMoriah Waterland is_setgid(struct cfent *ent)
6975c51f124SMoriah Waterland {
6985c51f124SMoriah Waterland 	return (((ent->ftype == 'f') || (ent->ftype == 'v') ||
6995c51f124SMoriah Waterland 		(ent->ftype == 'e')) && (ent->ainfo.mode != BADMODE) &&
7005c51f124SMoriah Waterland 		(ent->ainfo.mode != WILDCARD) &&
7015c51f124SMoriah Waterland 		(ent->ainfo.mode & S_ISGID) &&
7025c51f124SMoriah Waterland 		(ent->ainfo.mode & (S_IEXEC|S_IXUSR|S_IXOTH)));
7035c51f124SMoriah Waterland }
7045c51f124SMoriah Waterland 
7055c51f124SMoriah Waterland char *types[] = {
7065c51f124SMoriah Waterland 	"fev",	/* type 1, regular files */
7075c51f124SMoriah Waterland 	"s", 	/* type 2, symbolic links */
7085c51f124SMoriah Waterland 	"l", 	/* type 3, linked files */
7095c51f124SMoriah Waterland 	"dx", 	/* type 4, directories */
7105c51f124SMoriah Waterland 	"c", 	/* type 5, character special devices */
7115c51f124SMoriah Waterland 	"b", 	/* type 6, block special devices */
7125c51f124SMoriah Waterland 	"p", 	/* type 7, named pipes */
7135c51f124SMoriah Waterland 	NULL
7145c51f124SMoriah Waterland };
7155c51f124SMoriah Waterland 
7165c51f124SMoriah Waterland /*
7175c51f124SMoriah Waterland  * This determines if the ftype of the file on the disk and the file to be
7185c51f124SMoriah Waterland  * laid down are close enough. If they aren't, this either returns an error
7195c51f124SMoriah Waterland  * or displays a warning. This returns :
7205c51f124SMoriah Waterland  *	TYPE_OK		they're identical or close enough
7215c51f124SMoriah Waterland  *	TYPE_WARNING	they're pretty close (probably no problem)
7225c51f124SMoriah Waterland  *	TYPE_IGNORED	the type change was not allowed
7235c51f124SMoriah Waterland  *	TYPE_REPLACE	to be reviewed later - in endofclass() maybe
7245c51f124SMoriah Waterland  *	TYPE_FATAL	something awful happened
7255c51f124SMoriah Waterland  */
7265c51f124SMoriah Waterland static int
727b46ec01aSok199659 typechg(struct cfent *el_ent, struct cfent *cf_ent, struct mergstat *mstat)
7285c51f124SMoriah Waterland {
7295c51f124SMoriah Waterland 	int	i, etype, itype, retcode;
7305c51f124SMoriah Waterland 
7315c51f124SMoriah Waterland 	/* If they are identical, return OK */
732b46ec01aSok199659 	if (cf_ent->ftype == el_ent->ftype)
7335c51f124SMoriah Waterland 		return (TYPE_OK);
7345c51f124SMoriah Waterland 
7355c51f124SMoriah Waterland 	/*
7365c51f124SMoriah Waterland 	 * If package database entry is ambiguous, set it to the new entity's
7375c51f124SMoriah Waterland 	 * ftype
7385c51f124SMoriah Waterland 	 */
739b46ec01aSok199659 	if (cf_ent->ftype == BADFTYPE) {
740b46ec01aSok199659 		cf_ent->ftype = el_ent->ftype;
7415c51f124SMoriah Waterland 		return (TYPE_OK); /* do nothing; not really different */
7425c51f124SMoriah Waterland 	}
7435c51f124SMoriah Waterland 
7445c51f124SMoriah Waterland 	/* If the new entity is ambiguous, wait for the verify */
7455c51f124SMoriah Waterland 	if (el_ent->ftype == BADFTYPE)
7465c51f124SMoriah Waterland 		return (TYPE_OK);
7475c51f124SMoriah Waterland 
7485c51f124SMoriah Waterland 	/*
7495c51f124SMoriah Waterland 	 * If we're trying to convert an existing regular directory to an
7505c51f124SMoriah Waterland 	 * exclusive directory, this is very dangerous. We will continue, but
7515c51f124SMoriah Waterland 	 * we will deny the conversion.
7525c51f124SMoriah Waterland 	 */
753b46ec01aSok199659 	if (el_ent->ftype == 'x' && cf_ent->ftype == 'd') {
7545c51f124SMoriah Waterland 		logerr(gettext(WRN_TOEXCL), el_ent->path);
7555c51f124SMoriah Waterland 		return (TYPE_IGNORED);
7565c51f124SMoriah Waterland 	}
7575c51f124SMoriah Waterland 
7585c51f124SMoriah Waterland 	etype = itype = 0;
7595c51f124SMoriah Waterland 
7605c51f124SMoriah Waterland 	/* Set etype to that of the new entity */
7615c51f124SMoriah Waterland 	for (i = 0; types[i]; ++i) {
7625c51f124SMoriah Waterland 		if (strchr(types[i], el_ent->ftype)) {
7635c51f124SMoriah Waterland 			etype = i+1;
7645c51f124SMoriah Waterland 			break;
7655c51f124SMoriah Waterland 		}
7665c51f124SMoriah Waterland 	}
7675c51f124SMoriah Waterland 
7685c51f124SMoriah Waterland 	/* Set itype to that in the package database. */
7695c51f124SMoriah Waterland 	for (i = 0; types[i]; ++i) {
770b46ec01aSok199659 		if (strchr(types[i], cf_ent->ftype)) {
7715c51f124SMoriah Waterland 			itype = i+1;
7725c51f124SMoriah Waterland 			break;
7735c51f124SMoriah Waterland 		}
7745c51f124SMoriah Waterland 	}
7755c51f124SMoriah Waterland 
7765c51f124SMoriah Waterland 	if (itype == etype) {
7775c51f124SMoriah Waterland 		/* same basic object type */
7785c51f124SMoriah Waterland 		return (TYPE_OK);
7795c51f124SMoriah Waterland 	}
7805c51f124SMoriah Waterland 
7815c51f124SMoriah Waterland 	retcode = TYPE_WARNING;
7825c51f124SMoriah Waterland 
7835c51f124SMoriah Waterland 	/*
7845c51f124SMoriah Waterland 	 * If a simple object (like a file) is overwriting a directory, mark
7855c51f124SMoriah Waterland 	 * it for full inspection during installation.
7865c51f124SMoriah Waterland 	 */
7875c51f124SMoriah Waterland 	if (etype != 4 && itype == 4) {
7885c51f124SMoriah Waterland 		mstat->dir2nondir = 1;
7895c51f124SMoriah Waterland 		retcode = TYPE_REPLACE;
7905c51f124SMoriah Waterland 	}
7915c51f124SMoriah Waterland 
7925c51f124SMoriah Waterland 	/* allow change, but warn user of possible problems */
7935c51f124SMoriah Waterland 	switch (itype) {
7945c51f124SMoriah Waterland 	    case 1:
7955c51f124SMoriah Waterland 		logerr(gettext(WRN_NOTFILE), el_ent->path);
7965c51f124SMoriah Waterland 		break;
7975c51f124SMoriah Waterland 
7985c51f124SMoriah Waterland 	    case 2:
7995c51f124SMoriah Waterland 		logerr(gettext(WRN_NOTSYMLN), el_ent->path);
8005c51f124SMoriah Waterland 		break;
8015c51f124SMoriah Waterland 
8025c51f124SMoriah Waterland 	    case 3:
8035c51f124SMoriah Waterland 		logerr(gettext(WRN_NOTLINK), el_ent->path);
8045c51f124SMoriah Waterland 		break;
8055c51f124SMoriah Waterland 
8065c51f124SMoriah Waterland 	    case 4:
8075c51f124SMoriah Waterland 		logerr(gettext(WRN_NOTDIR), el_ent->path);
8085c51f124SMoriah Waterland 		break;
8095c51f124SMoriah Waterland 
8105c51f124SMoriah Waterland 	    case 5:
8115c51f124SMoriah Waterland 		logerr(gettext(WRN_NOTCHAR), el_ent->path);
8125c51f124SMoriah Waterland 		break;
8135c51f124SMoriah Waterland 
8145c51f124SMoriah Waterland 	    case 6:
8155c51f124SMoriah Waterland 		logerr(gettext(WRN_NOTBLOCK), el_ent->path);
8165c51f124SMoriah Waterland 		break;
8175c51f124SMoriah Waterland 
8185c51f124SMoriah Waterland 	    case 7:
8195c51f124SMoriah Waterland 		logerr(gettext(WRN_NOTPIPE), el_ent->path);
8205c51f124SMoriah Waterland 		break;
8215c51f124SMoriah Waterland 
8225c51f124SMoriah Waterland 	    default:
8235c51f124SMoriah Waterland 		break;
8245c51f124SMoriah Waterland 	}
8255c51f124SMoriah Waterland 	return (retcode);
8265c51f124SMoriah Waterland }
8275c51f124SMoriah Waterland 
8285c51f124SMoriah Waterland /*
8295c51f124SMoriah Waterland  * This function takes el_ent (the entry from the pkgmap) and cf_ent (the
8305c51f124SMoriah Waterland  * entry from the package database) and merge them into el_ent. The rules
8315c51f124SMoriah Waterland  * are still being figured out, but the comments should make the approach
8325c51f124SMoriah Waterland  * pretty clear.
8335c51f124SMoriah Waterland  *
8345c51f124SMoriah Waterland  * RETURN CODES:
8355c51f124SMoriah Waterland  *	MRG_DIFFERENT	The two entries are different and el_ent now contains
8365c51f124SMoriah Waterland  *			the intended new entry to be installed.
8375c51f124SMoriah Waterland  *	MRG_SAME	The two entries were identical and the old database
8385c51f124SMoriah Waterland  *			entry will be replaced unchanged.
8395c51f124SMoriah Waterland  *	MRG_REPLACE	One or the other entry will be used but the decision
8405c51f124SMoriah Waterland  *			has to be made at install time.
8415c51f124SMoriah Waterland  */
8425c51f124SMoriah Waterland static int
8435c51f124SMoriah Waterland merg(struct cfextra *el_ent, struct cfent *cf_ent)
8445c51f124SMoriah Waterland {
8455c51f124SMoriah Waterland 	int	n, changed = 0;
8465c51f124SMoriah Waterland 
8475c51f124SMoriah Waterland 	/*
8485c51f124SMoriah Waterland 	 * We need to change the original entry to make it look like the new
8495c51f124SMoriah Waterland 	 * entry (the eptstat() routine has already added appropriate package
8505c51f124SMoriah Waterland 	 * information, but not about 'aclass' which may represent a change
8515c51f124SMoriah Waterland 	 * in class from the previous installation.
8525c51f124SMoriah Waterland 	 *
8535c51f124SMoriah Waterland 	 * NOTE: elent->cf_ent.pinfo (the list of associated packages) is NULL
8545c51f124SMoriah Waterland 	 * upon entry to this function.
8555c51f124SMoriah Waterland 	 */
8565c51f124SMoriah Waterland 
8575c51f124SMoriah Waterland 	el_ent->cf_ent.pinfo = cf_ent->pinfo;
8585c51f124SMoriah Waterland 
8595c51f124SMoriah Waterland 	if (dbst == INST_RDY && el_ent->cf_ent.ftype == '?') {
8605c51f124SMoriah Waterland 		el_ent->cf_ent.ftype = cf_ent->ftype;
8615c51f124SMoriah Waterland 	}
8625c51f124SMoriah Waterland 
8635c51f124SMoriah Waterland 	/*
8645c51f124SMoriah Waterland 	 * Evaluate the ftype change. Usually the ftype won't change. If it
8655c51f124SMoriah Waterland 	 * does it may be easy (s -> f), not allowed (d -> x), so complex we
8665c51f124SMoriah Waterland 	 * can't figure it 'til later (d -> s) or fatal (a hook for later).
8675c51f124SMoriah Waterland 	 */
8685c51f124SMoriah Waterland 	if (cf_ent->ftype != el_ent->cf_ent.ftype) {
869b46ec01aSok199659 		n = typechg(&(el_ent->cf_ent), cf_ent, &(el_ent->mstat));
8705c51f124SMoriah Waterland 
8715c51f124SMoriah Waterland 		switch (n) {
8725c51f124SMoriah Waterland 		    case TYPE_OK:
8735c51f124SMoriah Waterland 			break;
8745c51f124SMoriah Waterland 
8755c51f124SMoriah Waterland 		    /* This is an allowable change. */
8765c51f124SMoriah Waterland 		    case TYPE_WARNING:
8775c51f124SMoriah Waterland 			el_ent->mstat.contchg = 1;
8785c51f124SMoriah Waterland 			break;
8795c51f124SMoriah Waterland 
8805c51f124SMoriah Waterland 		    /* Not allowed, but leaving it as is is OK. */
8815c51f124SMoriah Waterland 		    case TYPE_IGNORED:
8825c51f124SMoriah Waterland 			logerr(gettext(MSG_TYPIGN));
8835c51f124SMoriah Waterland 			if (cp_cfent(cf_ent, el_ent) == 0)
8845c51f124SMoriah Waterland 				quit(99);
8855c51f124SMoriah Waterland 			return (MRG_SAME);
8865c51f124SMoriah Waterland 
8875c51f124SMoriah Waterland 		    /* Future analysis will reveal if this is OK. */
8885c51f124SMoriah Waterland 		    case TYPE_REPLACE:
8895c51f124SMoriah Waterland 			el_ent->mstat.replace = 1;
8905c51f124SMoriah Waterland 			return (MRG_REPLACE);
8915c51f124SMoriah Waterland 
8925c51f124SMoriah Waterland 		    /* Kill it before it does any damage. */
8935c51f124SMoriah Waterland 		    case TYPE_FATAL:
8945c51f124SMoriah Waterland 			logerr(gettext(MSG_TYPE_ERR));
8955c51f124SMoriah Waterland 			quit(99);
8965c51f124SMoriah Waterland 
8975c51f124SMoriah Waterland 		    default:
8985c51f124SMoriah Waterland 			break;
8995c51f124SMoriah Waterland 		}
9005c51f124SMoriah Waterland 
9015c51f124SMoriah Waterland 		changed++;
9025c51f124SMoriah Waterland 	}
9035c51f124SMoriah Waterland 
9045c51f124SMoriah Waterland 	/* Evaluate and merge the class. */
9055c51f124SMoriah Waterland 	if (strcmp(cf_ent->pkg_class, el_ent->cf_ent.pkg_class)) {
9065c51f124SMoriah Waterland 		/*
9075c51f124SMoriah Waterland 		 * we always allow a class change as long as we have
9085c51f124SMoriah Waterland 		 * consistent ftypes, which at this point we must
9095c51f124SMoriah Waterland 		 */
9105c51f124SMoriah Waterland 		changed++;
9115c51f124SMoriah Waterland 		if (strcmp(cf_ent->pkg_class, "?")) {
9125c51f124SMoriah Waterland 			(void) strcpy(pkgpinfo->aclass,
9135c51f124SMoriah Waterland 			    el_ent->cf_ent.pkg_class);
9145c51f124SMoriah Waterland 			(void) strcpy(el_ent->cf_ent.pkg_class,
9155c51f124SMoriah Waterland 			    cf_ent->pkg_class);
9165c51f124SMoriah Waterland 			chgclass(&(el_ent->cf_ent), pkgpinfo);
9175c51f124SMoriah Waterland 		}
9185c51f124SMoriah Waterland 	}
9195c51f124SMoriah Waterland 
9205c51f124SMoriah Waterland 	/*
9215c51f124SMoriah Waterland 	 * Evaluate and merge based upon the ftype of the intended package
9225c51f124SMoriah Waterland 	 * database entry.
9235c51f124SMoriah Waterland 	 */
9245c51f124SMoriah Waterland 	if (((el_ent->cf_ent.ftype == 's') || (el_ent->cf_ent.ftype == 'l'))) {
9255c51f124SMoriah Waterland 
9265c51f124SMoriah Waterland 		/* If both have link sources, then they need to be merged. */
9275c51f124SMoriah Waterland 		if (cf_ent->ainfo.local && el_ent->cf_ent.ainfo.local) {
9285c51f124SMoriah Waterland 			/*
9295c51f124SMoriah Waterland 			 * If both sources are identical, the merge is
9305c51f124SMoriah Waterland 			 * already done.
9315c51f124SMoriah Waterland 			 */
9325c51f124SMoriah Waterland 			if (strcmp(cf_ent->ainfo.local,
9335c51f124SMoriah Waterland 			    el_ent->cf_ent.ainfo.local) != NULL) {
9345c51f124SMoriah Waterland 				changed++;
9355c51f124SMoriah Waterland 
9365c51f124SMoriah Waterland 				/*
9375c51f124SMoriah Waterland 				 * Otherwise, if the pkgmap entry is
9385c51f124SMoriah Waterland 				 * ambiguous, it will inherit the database
9395c51f124SMoriah Waterland 				 * entry.
9405c51f124SMoriah Waterland 				 */
9415c51f124SMoriah Waterland 				if (strcmp(el_ent->cf_ent.ainfo.local,
9425c51f124SMoriah Waterland 				    "?") == NULL) {
9435c51f124SMoriah Waterland 					(void) strlcpy(
9445c51f124SMoriah Waterland 						el_ent->cf_ent.ainfo.local,
9455c51f124SMoriah Waterland 						cf_ent->ainfo.local,
9465c51f124SMoriah Waterland 						PATH_MAX);
9475c51f124SMoriah Waterland 				} else {
9485c51f124SMoriah Waterland 					el_ent->mstat.contchg = 1;
9495c51f124SMoriah Waterland 				}
9505c51f124SMoriah Waterland 			}
9515c51f124SMoriah Waterland 		}
9525c51f124SMoriah Waterland 		return (changed ? MRG_DIFFERENT : MRG_SAME);
9535c51f124SMoriah Waterland 
9545c51f124SMoriah Waterland 	} else if (el_ent->cf_ent.ftype == 'e') {
9555c51f124SMoriah Waterland 
9565c51f124SMoriah Waterland 		/*
9575c51f124SMoriah Waterland 		 * The contents of edittable files are assumed to be changing
9585c51f124SMoriah Waterland 		 * since some class action script will be doing the work and
9595c51f124SMoriah Waterland 		 * we have no way of evaluating what it will actually do.
9605c51f124SMoriah Waterland 		 */
9615c51f124SMoriah Waterland 		el_ent->mstat.contchg = 1;
9625c51f124SMoriah Waterland 		changed++;
9635c51f124SMoriah Waterland 	} else if (((el_ent->cf_ent.ftype == 'f') ||
9645c51f124SMoriah Waterland 					(el_ent->cf_ent.ftype == 'v'))) {
9655c51f124SMoriah Waterland 		/*
9665c51f124SMoriah Waterland 		 * For regular files, Look at content information; a BADCONT
9675c51f124SMoriah Waterland 		 * in any el_ent field indicates the contents are unknown --
9685c51f124SMoriah Waterland 		 * since cf_ent is guaranteed to have a valid entry here (bad
9695c51f124SMoriah Waterland 		 * assumption?) this function will recognize this as a
9705c51f124SMoriah Waterland 		 * change. The ambiguous el_ent values will be evaluated and
9715c51f124SMoriah Waterland 		 * set later.
9725c51f124SMoriah Waterland 		 */
9735c51f124SMoriah Waterland 
974*6e1ae2a3SGary Pennington 		if (cf_ent->cinfo.size != el_ent->cf_ent.cinfo.size) {
9755c51f124SMoriah Waterland 			changed++;
9765c51f124SMoriah Waterland 			el_ent->mstat.contchg = 1;
9775c51f124SMoriah Waterland 		} else if (cf_ent->cinfo.modtime !=
9785c51f124SMoriah Waterland 		    el_ent->cf_ent.cinfo.modtime) {
9795c51f124SMoriah Waterland 			changed++;
9805c51f124SMoriah Waterland 			el_ent->mstat.contchg = 1;
9815c51f124SMoriah Waterland 		} else if (cf_ent->cinfo.cksum != el_ent->cf_ent.cinfo.cksum) {
9825c51f124SMoriah Waterland 			changed++;
9835c51f124SMoriah Waterland 			el_ent->mstat.contchg = 1;
9845c51f124SMoriah Waterland 		}
9855c51f124SMoriah Waterland 	} else if (((el_ent->cf_ent.ftype == 'c') ||
9865c51f124SMoriah Waterland 					(el_ent->cf_ent.ftype == 'b'))) {
9875c51f124SMoriah Waterland 		/*
9885c51f124SMoriah Waterland 		 * For devices, if major or minor numbers are identical the
9895c51f124SMoriah Waterland 		 * merge is trivial. If the el_ent value is ambiguous (BAD),
9905c51f124SMoriah Waterland 		 * the cf_ent value is inherited. Otherwise, the el_ent value
9915c51f124SMoriah Waterland 		 * is preserved.
9925c51f124SMoriah Waterland 		 */
9935c51f124SMoriah Waterland 		if (cf_ent->ainfo.major != el_ent->cf_ent.ainfo.major) {
9945c51f124SMoriah Waterland 			changed++;
9955c51f124SMoriah Waterland 			if (el_ent->cf_ent.ainfo.major == BADMAJOR) {
9965c51f124SMoriah Waterland 				el_ent->cf_ent.ainfo.major =
9975c51f124SMoriah Waterland 				    cf_ent->ainfo.major;
9985c51f124SMoriah Waterland 			} else {
9995c51f124SMoriah Waterland 				el_ent->mstat.contchg = 1;
10005c51f124SMoriah Waterland 			}
10015c51f124SMoriah Waterland 		}
10025c51f124SMoriah Waterland 		if (cf_ent->ainfo.minor != el_ent->cf_ent.ainfo.minor) {
10035c51f124SMoriah Waterland 			changed++;
10045c51f124SMoriah Waterland 			if (el_ent->cf_ent.ainfo.minor == BADMINOR)
10055c51f124SMoriah Waterland 				el_ent->cf_ent.ainfo.minor =
10065c51f124SMoriah Waterland 				    cf_ent->ainfo.minor;
10075c51f124SMoriah Waterland 			else
10085c51f124SMoriah Waterland 				el_ent->mstat.contchg = 1;
10095c51f124SMoriah Waterland 		}
10105c51f124SMoriah Waterland 	}
10115c51f124SMoriah Waterland 
10125c51f124SMoriah Waterland 	/*
10135c51f124SMoriah Waterland 	 * For mode, owner and group follow the same rules as above - if
10145c51f124SMoriah Waterland 	 * ambiguous, inherit, otherwise keep the new one.
10155c51f124SMoriah Waterland 	 */
10165c51f124SMoriah Waterland 	if (cf_ent->ainfo.mode != el_ent->cf_ent.ainfo.mode) {
10175c51f124SMoriah Waterland 		changed++;  /* attribute info is changing */
10185c51f124SMoriah Waterland 		if (el_ent->cf_ent.ainfo.mode == BADMODE) {
10195c51f124SMoriah Waterland 			el_ent->cf_ent.ainfo.mode = cf_ent->ainfo.mode;
10205c51f124SMoriah Waterland 		} else if (el_ent->cf_ent.ainfo.mode == WILDCARD) {
10215c51f124SMoriah Waterland 			/*
10225c51f124SMoriah Waterland 			 * If pkgmap has a '?' set for mode, use the mode from
10235c51f124SMoriah Waterland 			 * the pkg DB (contents file).
10245c51f124SMoriah Waterland 			 */
10255c51f124SMoriah Waterland 			el_ent->cf_ent.ainfo.mode = cf_ent->ainfo.mode;
10265c51f124SMoriah Waterland 			el_ent->mstat.attrchg = 0;
10275c51f124SMoriah Waterland 		} else {
10285c51f124SMoriah Waterland 			el_ent->mstat.attrchg = 1;
10295c51f124SMoriah Waterland 		}
10305c51f124SMoriah Waterland 	}
10315c51f124SMoriah Waterland 	if (strcmp(cf_ent->ainfo.owner, el_ent->cf_ent.ainfo.owner) != 0) {
10325c51f124SMoriah Waterland 		changed++;  /* attribute info is changing */
10335c51f124SMoriah Waterland 		if (strcmp(el_ent->cf_ent.ainfo.owner, BADOWNER) == 0)
10345c51f124SMoriah Waterland 			(void) strcpy(el_ent->cf_ent.ainfo.owner,
10355c51f124SMoriah Waterland 			    cf_ent->ainfo.owner);
10365c51f124SMoriah Waterland 		else
10375c51f124SMoriah Waterland 			el_ent->mstat.attrchg = 1;
10385c51f124SMoriah Waterland 	}
10395c51f124SMoriah Waterland 	if (strcmp(cf_ent->ainfo.group, el_ent->cf_ent.ainfo.group) != 0) {
10405c51f124SMoriah Waterland 		changed++;  /* attribute info is changing */
10415c51f124SMoriah Waterland 		if (strcmp(el_ent->cf_ent.ainfo.group, BADGROUP) == 0)
10425c51f124SMoriah Waterland 			(void) strcpy(el_ent->cf_ent.ainfo.group,
10435c51f124SMoriah Waterland 			    cf_ent->ainfo.group);
10445c51f124SMoriah Waterland 		else
10455c51f124SMoriah Waterland 			el_ent->mstat.attrchg = 1;
10465c51f124SMoriah Waterland 	}
10475c51f124SMoriah Waterland 	return (changed ? MRG_DIFFERENT : MRG_SAME);
10485c51f124SMoriah Waterland }
10495c51f124SMoriah Waterland 
10505c51f124SMoriah Waterland /*
10515c51f124SMoriah Waterland  * This puts the current entry into the package database in the appropriate
10525c51f124SMoriah Waterland  * intermediate format for this stage of the installation. This also assures
10535c51f124SMoriah Waterland  * the correct format for the various package object ftypes, stripping the
10545c51f124SMoriah Waterland  * link name before storing a regular file and stuff like that.
10555c51f124SMoriah Waterland  */
10565c51f124SMoriah Waterland 
10575c51f124SMoriah Waterland static void
10585c51f124SMoriah Waterland output(VFP_T *vfpo, struct cfent *ent, struct pinfo *pinfo)
10595c51f124SMoriah Waterland {
10605c51f124SMoriah Waterland 	short	svvolno;
10615c51f124SMoriah Waterland 	char	*svpt;
10625c51f124SMoriah Waterland 
10635c51f124SMoriah Waterland 	/* output without volume information */
10645c51f124SMoriah Waterland 	svvolno = ent->volno;
10655c51f124SMoriah Waterland 	ent->volno = 0;
10665c51f124SMoriah Waterland 
10675c51f124SMoriah Waterland 	pinfo->editflag = 0;
10685c51f124SMoriah Waterland 	if (((ent->ftype == 's') || (ent->ftype == 'l'))) {
10695c51f124SMoriah Waterland 		if (putcvfpfile(ent, vfpo)) {
10705c51f124SMoriah Waterland 			progerr(gettext(ERR_OUTPUT));
10715c51f124SMoriah Waterland 			quit(99);
10725c51f124SMoriah Waterland 		}
10735c51f124SMoriah Waterland 	} else {
10745c51f124SMoriah Waterland 
10755c51f124SMoriah Waterland 		/* output without local pathname */
10765c51f124SMoriah Waterland 		svpt = ent->ainfo.local;
10775c51f124SMoriah Waterland 		ent->ainfo.local = NULL;
10785c51f124SMoriah Waterland 		if (putcvfpfile(ent, vfpo)) {
10795c51f124SMoriah Waterland 			progerr(gettext(ERR_OUTPUT));
10805c51f124SMoriah Waterland 			quit(99);
10815c51f124SMoriah Waterland 		}
10825c51f124SMoriah Waterland 
10835c51f124SMoriah Waterland 		ent->ainfo.local = svpt;
10845c51f124SMoriah Waterland 		/*
10855c51f124SMoriah Waterland 		 * If this entry represents a file which is being edited, we
10865c51f124SMoriah Waterland 		 * need to store in memory the fact that it is an edittable
10875c51f124SMoriah Waterland 		 * file so that when we audit it after installation we do not
10885c51f124SMoriah Waterland 		 * worry about its contents; we do this by resetting the ftype
10895c51f124SMoriah Waterland 		 * to 'e' in the memory array which is later used to control
10905c51f124SMoriah Waterland 		 * the audit
10915c51f124SMoriah Waterland 		 */
10925c51f124SMoriah Waterland 		if (pinfo->editflag)
10935c51f124SMoriah Waterland 			ent->ftype = 'e';
10945c51f124SMoriah Waterland 	}
10955c51f124SMoriah Waterland 	/* restore volume information */
10965c51f124SMoriah Waterland 	ent->volno = svvolno;
10975c51f124SMoriah Waterland }
10985c51f124SMoriah Waterland 
10995c51f124SMoriah Waterland static void
11005c51f124SMoriah Waterland chgclass(struct cfent *cf_ent, struct pinfo *pinfo)
11015c51f124SMoriah Waterland {
11025c51f124SMoriah Waterland 	struct pinfo *pp;
11035c51f124SMoriah Waterland 	char	*oldclass, newclass[CLSSIZ+1];
11045c51f124SMoriah Waterland 	int	newcnt, oldcnt;
11055c51f124SMoriah Waterland 
11065c51f124SMoriah Waterland 	/*
11075c51f124SMoriah Waterland 	 * we use this routine to minimize the use of the aclass element by
11085c51f124SMoriah Waterland 	 * optimizing the use of the cf_ent->pkg_class element
11095c51f124SMoriah Waterland 	 */
11105c51f124SMoriah Waterland 
11115c51f124SMoriah Waterland 	(void) strlcpy(newclass, pinfo->aclass, sizeof (newclass));
11125c51f124SMoriah Waterland 	newcnt = 1;
11135c51f124SMoriah Waterland 
11145c51f124SMoriah Waterland 	oldclass = cf_ent->pkg_class;
11155c51f124SMoriah Waterland 	oldcnt = 0;
11165c51f124SMoriah Waterland 
11175c51f124SMoriah Waterland 	/*
11185c51f124SMoriah Waterland 	 * count the number of times the newclass will be used and see if it
11195c51f124SMoriah Waterland 	 * exceeds the number of times the oldclass is referenced
11205c51f124SMoriah Waterland 	 */
11215c51f124SMoriah Waterland 	pp = cf_ent->pinfo;
11225c51f124SMoriah Waterland 	while (pp) {
11235c51f124SMoriah Waterland 		if (pp->aclass[0] != '\0') {
11245c51f124SMoriah Waterland 			if (strcmp(pp->aclass, newclass) == 0)
11255c51f124SMoriah Waterland 				newcnt++;
11265c51f124SMoriah Waterland 			else if (strcmp(pp->aclass, oldclass) == 0)
11275c51f124SMoriah Waterland 				oldcnt++;
11285c51f124SMoriah Waterland 		}
11295c51f124SMoriah Waterland 		pp = pp->next;
11305c51f124SMoriah Waterland 	}
11315c51f124SMoriah Waterland 	if (newcnt > oldcnt) {
11325c51f124SMoriah Waterland 		pp = cf_ent->pinfo;
11335c51f124SMoriah Waterland 		while (pp) {
11345c51f124SMoriah Waterland 			if (pp->aclass[0] == '\0') {
11355c51f124SMoriah Waterland 				(void) strcpy(pp->aclass, oldclass);
11365c51f124SMoriah Waterland 			} else if (strcmp(pp->aclass, newclass) == 0) {
11375c51f124SMoriah Waterland 				pp->aclass[0] = '\0';
11385c51f124SMoriah Waterland 			}
11395c51f124SMoriah Waterland 			pp = pp->next;
11405c51f124SMoriah Waterland 		}
11415c51f124SMoriah Waterland 		(void) strcpy(cf_ent->pkg_class, newclass);
11425c51f124SMoriah Waterland 	}
11435c51f124SMoriah Waterland }
1144