xref: /titanic_44/usr/src/cmd/svr4pkg/pkginstall/instvol.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 <string.h>
33*5c51f124SMoriah Waterland #include <locale.h>
34*5c51f124SMoriah Waterland #include <libintl.h>
35*5c51f124SMoriah Waterland #include <dirent.h>
36*5c51f124SMoriah Waterland #include <pkgstrct.h>
37*5c51f124SMoriah Waterland #include <pkgdev.h>
38*5c51f124SMoriah Waterland #include <pkglocs.h>
39*5c51f124SMoriah Waterland #include <archives.h>
40*5c51f124SMoriah Waterland #include <errno.h>
41*5c51f124SMoriah Waterland #include <fcntl.h>
42*5c51f124SMoriah Waterland #include <sys/stat.h>
43*5c51f124SMoriah Waterland #include <sys/param.h>
44*5c51f124SMoriah Waterland #include <stdlib.h>
45*5c51f124SMoriah Waterland #include <unistd.h>
46*5c51f124SMoriah Waterland #include <assert.h>
47*5c51f124SMoriah Waterland #include <wait.h>
48*5c51f124SMoriah Waterland 
49*5c51f124SMoriah Waterland /*
50*5c51f124SMoriah Waterland  * libinstzones includes
51*5c51f124SMoriah Waterland  */
52*5c51f124SMoriah Waterland 
53*5c51f124SMoriah Waterland #include <instzones_api.h>
54*5c51f124SMoriah Waterland 
55*5c51f124SMoriah Waterland /*
56*5c51f124SMoriah Waterland  * consolidation pkg command library includes
57*5c51f124SMoriah Waterland  */
58*5c51f124SMoriah Waterland 
59*5c51f124SMoriah Waterland #include <pkglib.h>
60*5c51f124SMoriah Waterland #include <pkgweb.h>
61*5c51f124SMoriah Waterland 
62*5c51f124SMoriah Waterland /*
63*5c51f124SMoriah Waterland  * local pkg command library includes
64*5c51f124SMoriah Waterland  */
65*5c51f124SMoriah Waterland 
66*5c51f124SMoriah Waterland #include <install.h>
67*5c51f124SMoriah Waterland #include <libinst.h>
68*5c51f124SMoriah Waterland #include <libadm.h>
69*5c51f124SMoriah Waterland #include <dryrun.h>
70*5c51f124SMoriah Waterland #include <messages.h>
71*5c51f124SMoriah Waterland 
72*5c51f124SMoriah Waterland /*
73*5c51f124SMoriah Waterland  * pkginstall local includes
74*5c51f124SMoriah Waterland  */
75*5c51f124SMoriah Waterland 
76*5c51f124SMoriah Waterland #include "pkginstall.h"
77*5c51f124SMoriah Waterland 
78*5c51f124SMoriah Waterland extern int		pkgverbose;
79*5c51f124SMoriah Waterland extern fsblkcnt_t	pkgmap_blks; 		/* main.c */
80*5c51f124SMoriah Waterland 
81*5c51f124SMoriah Waterland extern struct pkgdev pkgdev;
82*5c51f124SMoriah Waterland 
83*5c51f124SMoriah Waterland extern char	tmpdir[];
84*5c51f124SMoriah Waterland extern char	pkgbin[];
85*5c51f124SMoriah Waterland extern char	instdir[];
86*5c51f124SMoriah Waterland extern char	saveSpoolInstallDir[];
87*5c51f124SMoriah Waterland extern char	*pkginst;
88*5c51f124SMoriah Waterland 
89*5c51f124SMoriah Waterland extern int	dbchg;
90*5c51f124SMoriah Waterland extern int	nosetuid;
91*5c51f124SMoriah Waterland extern int	nocnflct;
92*5c51f124SMoriah Waterland extern int	warnflag;
93*5c51f124SMoriah Waterland 
94*5c51f124SMoriah Waterland #define	DMRG_DONE	-1
95*5c51f124SMoriah Waterland 
96*5c51f124SMoriah Waterland #define	ck_efile(s, p)	\
97*5c51f124SMoriah Waterland 		((p->cinfo.modtime >= 0) && \
98*5c51f124SMoriah Waterland 		p->ainfo.local && \
99*5c51f124SMoriah Waterland 		cverify(0, &p->ftype, s, &p->cinfo, 1))
100*5c51f124SMoriah Waterland 
101*5c51f124SMoriah Waterland static int	eocflag;
102*5c51f124SMoriah Waterland 
103*5c51f124SMoriah Waterland /*
104*5c51f124SMoriah Waterland  * The variable below indicates that fix_attributes() will be inadequate
105*5c51f124SMoriah Waterland  * because a replacement was permitted.
106*5c51f124SMoriah Waterland  */
107*5c51f124SMoriah Waterland static int	repl_permitted = 0;
108*5c51f124SMoriah Waterland 
109*5c51f124SMoriah Waterland static int	domerg(struct cfextra **extlist, int part, int nparts,
110*5c51f124SMoriah Waterland 			int myclass, char **srcp, char **dstp,
111*5c51f124SMoriah Waterland 			char **r_updated, char **r_skipped,
112*5c51f124SMoriah Waterland 			char **r_anyPathLocal);
113*5c51f124SMoriah Waterland static void	endofclass(struct cfextra **extlist, int myclass,
114*5c51f124SMoriah Waterland 			int ckflag, VFP_T **a_cfVfp, VFP_T **a_cfTmpVfp);
115*5c51f124SMoriah Waterland static int	fix_attributes(struct cfextra **, int);
116*5c51f124SMoriah Waterland static int	dir_is_populated(char *dirpath);
117*5c51f124SMoriah Waterland static boolean_t absolutepath(char *path);
118*5c51f124SMoriah Waterland static boolean_t parametricpath(char *path, char **relocpath);
119*5c51f124SMoriah Waterland 
120*5c51f124SMoriah Waterland /* Used to keep track of the entries in extlist that are regular files. */
121*5c51f124SMoriah Waterland struct reg_files {
122*5c51f124SMoriah Waterland 	struct reg_files *next;
123*5c51f124SMoriah Waterland 	int val;
124*5c51f124SMoriah Waterland };
125*5c51f124SMoriah Waterland static struct reg_files *regfiles_head = NULL;
126*5c51f124SMoriah Waterland 
127*5c51f124SMoriah Waterland /*
128*5c51f124SMoriah Waterland  * This is the function that actually installs one volume (usually that's
129*5c51f124SMoriah Waterland  * all there is). Upon entry, the extlist is entirely correct:
130*5c51f124SMoriah Waterland  *
131*5c51f124SMoriah Waterland  *	1. It contains only those files which are to be installed
132*5c51f124SMoriah Waterland  *	   from all volumes.
133*5c51f124SMoriah Waterland  *	2. The mode bits in the ainfo structure for each file are set
134*5c51f124SMoriah Waterland  *	   correctly in accordance with administrative defaults.
135*5c51f124SMoriah Waterland  *	3. mstat.setuid/setgid reflect what the status *was* before
136*5c51f124SMoriah Waterland  *	   pkgdbmerg() processed compliance.
137*5c51f124SMoriah Waterland  */
138*5c51f124SMoriah Waterland void
139*5c51f124SMoriah Waterland instvol(struct cfextra **extlist, char *srcinst, int part,
140*5c51f124SMoriah Waterland 	int nparts, VFP_T **a_cfVfp, VFP_T **a_cfTmpVfp,
141*5c51f124SMoriah Waterland 	char **r_updated, char **r_skipped,
142*5c51f124SMoriah Waterland 	char *a_zoneName)
143*5c51f124SMoriah Waterland {
144*5c51f124SMoriah Waterland 	FILE		*listfp;
145*5c51f124SMoriah Waterland 	char		*updated = (char *)NULL;
146*5c51f124SMoriah Waterland 	char		*skipped = (char *)NULL;
147*5c51f124SMoriah Waterland 	char		*anyPathLocal = (char *)NULL;
148*5c51f124SMoriah Waterland 	char		*relocpath = (char *)NULL;
149*5c51f124SMoriah Waterland 	char		*dstp;
150*5c51f124SMoriah Waterland 	char		*listfile;
151*5c51f124SMoriah Waterland 	char		*srcp;
152*5c51f124SMoriah Waterland 	char		*pspool_loc;
153*5c51f124SMoriah Waterland 	char		scrpt_dst[PATH_MAX];
154*5c51f124SMoriah Waterland 	int		count;
155*5c51f124SMoriah Waterland 	int		entryidx;	/* array of current package objects */
156*5c51f124SMoriah Waterland 	int		n;
157*5c51f124SMoriah Waterland 	int		nc = 0;
158*5c51f124SMoriah Waterland 	int		pass;		/* pass count through the for loop. */
159*5c51f124SMoriah Waterland 	int		tcount;
160*5c51f124SMoriah Waterland 	struct cfent	*ept;
161*5c51f124SMoriah Waterland 	struct cfextra	*ext;
162*5c51f124SMoriah Waterland 	struct mergstat	*mstat;
163*5c51f124SMoriah Waterland 	struct reg_files *rfp = NULL;
164*5c51f124SMoriah Waterland 
165*5c51f124SMoriah Waterland 	/*
166*5c51f124SMoriah Waterland 	 * r_updated and r_skipped are optional parameters that can be passed in
167*5c51f124SMoriah Waterland 	 * by the caller if the caller wants to know if any objects are either
168*5c51f124SMoriah Waterland 	 * updated or skipped. Do not initialize either r_updated or r_skipped;
169*5c51f124SMoriah Waterland 	 * the call to instvol could be cumulative and any previous update or
170*5c51f124SMoriah Waterland 	 * skipped indication must not be disturbed - these flags are only set,
171*5c51f124SMoriah Waterland 	 * they must never be reset. These flags are "char *" pointers so that
172*5c51f124SMoriah Waterland 	 * the object that was skipped or updated can be displayed in debugging
173*5c51f124SMoriah Waterland 	 * output.
174*5c51f124SMoriah Waterland 	 */
175*5c51f124SMoriah Waterland 
176*5c51f124SMoriah Waterland 	if (part == 1) {
177*5c51f124SMoriah Waterland 		pkgvolume(&pkgdev, srcinst, part, nparts);
178*5c51f124SMoriah Waterland 	}
179*5c51f124SMoriah Waterland 
180*5c51f124SMoriah Waterland 	tcount = 0;
181*5c51f124SMoriah Waterland 	nc = cl_getn();
182*5c51f124SMoriah Waterland 
183*5c51f124SMoriah Waterland 	/*
184*5c51f124SMoriah Waterland 	 * For each class in this volume, install those files.
185*5c51f124SMoriah Waterland 	 *
186*5c51f124SMoriah Waterland 	 * NOTE : This loop index may be decremented by code below forcing a
187*5c51f124SMoriah Waterland 	 * second trip through for the same class. This happens only when a
188*5c51f124SMoriah Waterland 	 * class is split between an archive and the tree. Examples would be
189*5c51f124SMoriah Waterland 	 * old WOS packages and the occasional class containing dynamic
190*5c51f124SMoriah Waterland 	 * libraries which require special treatment.
191*5c51f124SMoriah Waterland 	 */
192*5c51f124SMoriah Waterland 
193*5c51f124SMoriah Waterland 	if (is_depend_pkginfo_DB() == B_FALSE) {
194*5c51f124SMoriah Waterland 	    int		classidx;	/* the current class */
195*5c51f124SMoriah Waterland 
196*5c51f124SMoriah Waterland 	    for (classidx = 0; classidx < nc; classidx++) {
197*5c51f124SMoriah Waterland 		int pass_relative = 0;
198*5c51f124SMoriah Waterland 		int rel_init = 0;
199*5c51f124SMoriah Waterland 
200*5c51f124SMoriah Waterland 		eocflag = count = pass = 0;
201*5c51f124SMoriah Waterland 		listfp = (FILE *)0;
202*5c51f124SMoriah Waterland 		listfile = NULL;
203*5c51f124SMoriah Waterland 
204*5c51f124SMoriah Waterland 		/* Now what do we pass to the class action script */
205*5c51f124SMoriah Waterland 
206*5c51f124SMoriah Waterland 		if (cl_pthrel(classidx) == REL_2_CAS) {
207*5c51f124SMoriah Waterland 			pass_relative = 1;
208*5c51f124SMoriah Waterland 		}
209*5c51f124SMoriah Waterland 
210*5c51f124SMoriah Waterland 		for (;;) {
211*5c51f124SMoriah Waterland 			if (!tcount++) {
212*5c51f124SMoriah Waterland 				/* first file to install */
213*5c51f124SMoriah Waterland 				if (a_zoneName == (char *)NULL) {
214*5c51f124SMoriah Waterland 					echo(MSG_INS_N_N, part, nparts);
215*5c51f124SMoriah Waterland 				} else {
216*5c51f124SMoriah Waterland 					echo(MSG_INS_N_N_LZ, part, nparts,
217*5c51f124SMoriah Waterland 						a_zoneName);
218*5c51f124SMoriah Waterland 				}
219*5c51f124SMoriah Waterland 			}
220*5c51f124SMoriah Waterland 
221*5c51f124SMoriah Waterland 			/*
222*5c51f124SMoriah Waterland 			 * If there's an install class action script and no
223*5c51f124SMoriah Waterland 			 * list file has been created yet, create that file
224*5c51f124SMoriah Waterland 			 * and provide the pointer in listfp.
225*5c51f124SMoriah Waterland 			 */
226*5c51f124SMoriah Waterland 			if (cl_iscript(classidx) && !listfp) {
227*5c51f124SMoriah Waterland 				/* create list file */
228*5c51f124SMoriah Waterland 				putparam("TMPDIR", tmpdir);
229*5c51f124SMoriah Waterland 				listfile = tempnam(tmpdir, "list");
230*5c51f124SMoriah Waterland 				if ((listfp = fopen(listfile, "w")) == NULL) {
231*5c51f124SMoriah Waterland 					progerr(ERR_WTMPFILE, listfile);
232*5c51f124SMoriah Waterland 					quit(99);
233*5c51f124SMoriah Waterland 				}
234*5c51f124SMoriah Waterland 			}
235*5c51f124SMoriah Waterland 
236*5c51f124SMoriah Waterland 			/*
237*5c51f124SMoriah Waterland 			 * The following function goes through the package
238*5c51f124SMoriah Waterland 			 * object list returning the array index of the next
239*5c51f124SMoriah Waterland 			 * regular file. If it encounters a directory,
240*5c51f124SMoriah Waterland 			 * symlink, named pipe or device, it just creates it.
241*5c51f124SMoriah Waterland 			 */
242*5c51f124SMoriah Waterland 
243*5c51f124SMoriah Waterland 			entryidx = domerg(extlist, (pass++ ? 0 : part), nparts,
244*5c51f124SMoriah Waterland 				classidx, &srcp, &dstp, &updated, &skipped,
245*5c51f124SMoriah Waterland 				&anyPathLocal);
246*5c51f124SMoriah Waterland 
247*5c51f124SMoriah Waterland 			/* Evaluate the return code */
248*5c51f124SMoriah Waterland 			if (entryidx == DMRG_DONE) {
249*5c51f124SMoriah Waterland 				/*
250*5c51f124SMoriah Waterland 				 * Set ept to the first entry in extlist
251*5c51f124SMoriah Waterland 				 * which is guaranteed to exist so
252*5c51f124SMoriah Waterland 				 * later checks against ept->ftype are
253*5c51f124SMoriah Waterland 				 * not compared to NULL.
254*5c51f124SMoriah Waterland 				 */
255*5c51f124SMoriah Waterland 				ext = extlist[0];
256*5c51f124SMoriah Waterland 				ept = &(ext->cf_ent);
257*5c51f124SMoriah Waterland 				break; /* no more entries to process */
258*5c51f124SMoriah Waterland 			}
259*5c51f124SMoriah Waterland 
260*5c51f124SMoriah Waterland 			ext = extlist[entryidx];
261*5c51f124SMoriah Waterland 			ept = &(ext->cf_ent);
262*5c51f124SMoriah Waterland 			mstat = &(ext->mstat);
263*5c51f124SMoriah Waterland 
264*5c51f124SMoriah Waterland 			/*
265*5c51f124SMoriah Waterland 			 * If not installing from a partially spooled package
266*5c51f124SMoriah Waterland 			 * (the "save/pspool" area), and the file contents can
267*5c51f124SMoriah Waterland 			 * be changed (type is 'e' or 'v'), and the class is not
268*5c51f124SMoriah Waterland 			 * "none": copy the file from the package (in pristine
269*5c51f124SMoriah Waterland 			 * state with no actions performed) into the appropriate
270*5c51f124SMoriah Waterland 			 * location in the packages destination "save/pspool"
271*5c51f124SMoriah Waterland 			 * area.
272*5c51f124SMoriah Waterland 			 */
273*5c51f124SMoriah Waterland 
274*5c51f124SMoriah Waterland 			if ((!is_partial_inst()) &&
275*5c51f124SMoriah Waterland 				((ept->ftype == 'e') || (ept->ftype == 'v')) &&
276*5c51f124SMoriah Waterland 				(strcmp(ept->pkg_class, "none") != 0)) {
277*5c51f124SMoriah Waterland 
278*5c51f124SMoriah Waterland 				if (absolutepath(ext->map_path) == B_TRUE &&
279*5c51f124SMoriah Waterland 					parametricpath(ext->cf_ent.ainfo.local,
280*5c51f124SMoriah Waterland 						&relocpath) == B_FALSE) {
281*5c51f124SMoriah Waterland 					pspool_loc = ROOT;
282*5c51f124SMoriah Waterland 				} else {
283*5c51f124SMoriah Waterland 					pspool_loc = RELOC;
284*5c51f124SMoriah Waterland 				}
285*5c51f124SMoriah Waterland 
286*5c51f124SMoriah Waterland 				n = snprintf(scrpt_dst, PATH_MAX, "%s/%s/%s",
287*5c51f124SMoriah Waterland 					saveSpoolInstallDir, pspool_loc,
288*5c51f124SMoriah Waterland 					relocpath ? relocpath : ext->map_path);
289*5c51f124SMoriah Waterland 
290*5c51f124SMoriah Waterland 				if (n >= PATH_MAX) {
291*5c51f124SMoriah Waterland 					progerr(ERR_CREATE_PATH_2,
292*5c51f124SMoriah Waterland 						saveSpoolInstallDir,
293*5c51f124SMoriah Waterland 						ext->map_path);
294*5c51f124SMoriah Waterland 					quit(99);
295*5c51f124SMoriah Waterland 				}
296*5c51f124SMoriah Waterland 
297*5c51f124SMoriah Waterland 				/* copy, preserve source file mode */
298*5c51f124SMoriah Waterland 
299*5c51f124SMoriah Waterland 				if (cppath(MODE_SRC, srcp, scrpt_dst, 0644)) {
300*5c51f124SMoriah Waterland 					warnflag++;
301*5c51f124SMoriah Waterland 				}
302*5c51f124SMoriah Waterland 			}
303*5c51f124SMoriah Waterland 
304*5c51f124SMoriah Waterland 			/*
305*5c51f124SMoriah Waterland 			 * If this isn't writeable anyway, it's not going
306*5c51f124SMoriah Waterland 			 * into the list file. Only count it if it's going
307*5c51f124SMoriah Waterland 			 * into the list file.
308*5c51f124SMoriah Waterland 			 */
309*5c51f124SMoriah Waterland 			if (is_fs_writeable(ext->cf_ent.path,
310*5c51f124SMoriah Waterland 				&(ext->fsys_value)))
311*5c51f124SMoriah Waterland 				count++;
312*5c51f124SMoriah Waterland 
313*5c51f124SMoriah Waterland 			pkgvolume(&pkgdev, srcinst, part, nparts);
314*5c51f124SMoriah Waterland 
315*5c51f124SMoriah Waterland 			/*
316*5c51f124SMoriah Waterland 			 * If source verification is OK for this class, make
317*5c51f124SMoriah Waterland 			 * sure the source we're passing to the class action
318*5c51f124SMoriah Waterland 			 * script is useable.
319*5c51f124SMoriah Waterland 			 */
320*5c51f124SMoriah Waterland 			if (cl_svfy(classidx) != NOVERIFY) {
321*5c51f124SMoriah Waterland 				if (cl_iscript(classidx) ||
322*5c51f124SMoriah Waterland 					((ept->ftype == 'e') ||
323*5c51f124SMoriah Waterland 					(ept->ftype == 'n'))) {
324*5c51f124SMoriah Waterland 					if (ck_efile(srcp, ept)) {
325*5c51f124SMoriah Waterland 						progerr(ERR_CORRUPT,
326*5c51f124SMoriah Waterland 							srcp);
327*5c51f124SMoriah Waterland 						logerr(getErrbufAddr());
328*5c51f124SMoriah Waterland 						warnflag++;
329*5c51f124SMoriah Waterland 						continue;
330*5c51f124SMoriah Waterland 					}
331*5c51f124SMoriah Waterland 				}
332*5c51f124SMoriah Waterland 			}
333*5c51f124SMoriah Waterland 
334*5c51f124SMoriah Waterland 			/*
335*5c51f124SMoriah Waterland 			 * If there's a class action script for this class,
336*5c51f124SMoriah Waterland 			 * just collect names in a temporary file
337*5c51f124SMoriah Waterland 			 * that will be used as the stdin when the
338*5c51f124SMoriah Waterland 			 * class action script is invoked.
339*5c51f124SMoriah Waterland 			 */
340*5c51f124SMoriah Waterland 
341*5c51f124SMoriah Waterland 			if ((cl_iscript(classidx)) &&
342*5c51f124SMoriah Waterland 					((is_fs_writeable(ept->path,
343*5c51f124SMoriah Waterland 						&(ext->fsys_value))))) {
344*5c51f124SMoriah Waterland 				if (pass_relative) {
345*5c51f124SMoriah Waterland 					if (!rel_init) {
346*5c51f124SMoriah Waterland 						(void) fputs(instdir, listfp);
347*5c51f124SMoriah Waterland 						(void) putc('\n', listfp);
348*5c51f124SMoriah Waterland 						rel_init++;
349*5c51f124SMoriah Waterland 					}
350*5c51f124SMoriah Waterland 					(void) fputs(ext->map_path, listfp);
351*5c51f124SMoriah Waterland 					(void) putc('\n', listfp);
352*5c51f124SMoriah Waterland 				} else {
353*5c51f124SMoriah Waterland 					(void) fputs(srcp ?
354*5c51f124SMoriah Waterland 						srcp : "/dev/null", listfp);
355*5c51f124SMoriah Waterland 					(void) putc(' ', listfp);
356*5c51f124SMoriah Waterland 					(void) fputs(dstp, listfp);
357*5c51f124SMoriah Waterland 					(void) putc('\n', listfp);
358*5c51f124SMoriah Waterland 				}
359*5c51f124SMoriah Waterland 				/*
360*5c51f124SMoriah Waterland 				 * Note which entries in extlist are regular
361*5c51f124SMoriah Waterland 				 * files to be installed via the class action
362*5c51f124SMoriah Waterland 				 * script.
363*5c51f124SMoriah Waterland 				 */
364*5c51f124SMoriah Waterland 				if (regfiles_head == NULL) {
365*5c51f124SMoriah Waterland 					assert(rfp == NULL);
366*5c51f124SMoriah Waterland 					regfiles_head =
367*5c51f124SMoriah Waterland 					    malloc(sizeof (struct reg_files));
368*5c51f124SMoriah Waterland 					if (regfiles_head == NULL) {
369*5c51f124SMoriah Waterland 						progerr(ERR_MEMORY, errno);
370*5c51f124SMoriah Waterland 						quit(99);
371*5c51f124SMoriah Waterland 					}
372*5c51f124SMoriah Waterland 					regfiles_head->next = NULL;
373*5c51f124SMoriah Waterland 					regfiles_head->val = entryidx;
374*5c51f124SMoriah Waterland 					rfp = regfiles_head;
375*5c51f124SMoriah Waterland 				} else {
376*5c51f124SMoriah Waterland 					assert(rfp != NULL);
377*5c51f124SMoriah Waterland 					rfp->next =
378*5c51f124SMoriah Waterland 					    malloc(sizeof (struct reg_files));
379*5c51f124SMoriah Waterland 					if (rfp->next == NULL) {
380*5c51f124SMoriah Waterland 						progerr(ERR_MEMORY, errno);
381*5c51f124SMoriah Waterland 						quit(99);
382*5c51f124SMoriah Waterland 					}
383*5c51f124SMoriah Waterland 					rfp = rfp->next;
384*5c51f124SMoriah Waterland 					rfp->next = NULL;
385*5c51f124SMoriah Waterland 					rfp->val = entryidx;
386*5c51f124SMoriah Waterland 				}
387*5c51f124SMoriah Waterland 
388*5c51f124SMoriah Waterland 				/*
389*5c51f124SMoriah Waterland 				 * A warning message about unwritable targets
390*5c51f124SMoriah Waterland 				 * in a class may be appropriate here.
391*5c51f124SMoriah Waterland 				 */
392*5c51f124SMoriah Waterland 				continue;
393*5c51f124SMoriah Waterland 			}
394*5c51f124SMoriah Waterland 
395*5c51f124SMoriah Waterland 			/*
396*5c51f124SMoriah Waterland 			 * If not installing from a partially spooled package
397*5c51f124SMoriah Waterland 			 * (the "save/pspool" area), and the file contents can
398*5c51f124SMoriah Waterland 			 * be changed (type is 'e' or 'v') and the class
399*5c51f124SMoriah Waterland 			 * identifier is not "none": copy the file from the
400*5c51f124SMoriah Waterland 			 * package (in pristine state with no actions performed)
401*5c51f124SMoriah Waterland 			 * into the appropriate location in the packages
402*5c51f124SMoriah Waterland 			 * destination "save/pspool" area.
403*5c51f124SMoriah Waterland 			 */
404*5c51f124SMoriah Waterland 
405*5c51f124SMoriah Waterland 			if ((!is_partial_inst()) &&
406*5c51f124SMoriah Waterland 			    ((ept->ftype == 'e') || (ept->ftype == 'v') &&
407*5c51f124SMoriah Waterland 			    (strcmp(ept->pkg_class, "none") != 0))) {
408*5c51f124SMoriah Waterland 
409*5c51f124SMoriah Waterland 				if (absolutepath(ext->map_path) == B_TRUE &&
410*5c51f124SMoriah Waterland 					parametricpath(ext->cf_ent.ainfo.local,
411*5c51f124SMoriah Waterland 						&relocpath) == B_FALSE) {
412*5c51f124SMoriah Waterland 					pspool_loc = ROOT;
413*5c51f124SMoriah Waterland 				} else {
414*5c51f124SMoriah Waterland 					pspool_loc = RELOC;
415*5c51f124SMoriah Waterland 				}
416*5c51f124SMoriah Waterland 
417*5c51f124SMoriah Waterland 				n = snprintf(scrpt_dst, PATH_MAX, "%s/%s/%s",
418*5c51f124SMoriah Waterland 					saveSpoolInstallDir, pspool_loc,
419*5c51f124SMoriah Waterland 					relocpath ? relocpath : ext->map_path);
420*5c51f124SMoriah Waterland 
421*5c51f124SMoriah Waterland 				if (n >= PATH_MAX) {
422*5c51f124SMoriah Waterland 					progerr(ERR_CREATE_PATH_2,
423*5c51f124SMoriah Waterland 						saveSpoolInstallDir,
424*5c51f124SMoriah Waterland 						ext->map_path);
425*5c51f124SMoriah Waterland 					quit(99);
426*5c51f124SMoriah Waterland 				}
427*5c51f124SMoriah Waterland 
428*5c51f124SMoriah Waterland 				/* copy, preserve source file mode */
429*5c51f124SMoriah Waterland 
430*5c51f124SMoriah Waterland 				if (cppath(MODE_SRC, srcp, scrpt_dst, 0644)) {
431*5c51f124SMoriah Waterland 					warnflag++;
432*5c51f124SMoriah Waterland 				}
433*5c51f124SMoriah Waterland 			}
434*5c51f124SMoriah Waterland 
435*5c51f124SMoriah Waterland 			/*
436*5c51f124SMoriah Waterland 			 * There are several tests here to determine
437*5c51f124SMoriah Waterland 			 * how we're going to deal with objects
438*5c51f124SMoriah Waterland 			 * intended for remote read-only filesystems.
439*5c51f124SMoriah Waterland 			 * We don't use is_served() because this may be
440*5c51f124SMoriah Waterland 			 * a server. We're actually interested in if
441*5c51f124SMoriah Waterland 			 * it's *really* remote and *really* not
442*5c51f124SMoriah Waterland 			 * writeable.
443*5c51f124SMoriah Waterland 			 */
444*5c51f124SMoriah Waterland 
445*5c51f124SMoriah Waterland 			n = is_remote_fs(ept->path, &(ext->fsys_value));
446*5c51f124SMoriah Waterland 			if ((n != 0) &&
447*5c51f124SMoriah Waterland 				!is_fs_writeable(ept->path,
448*5c51f124SMoriah Waterland 				&(ext->fsys_value))) {
449*5c51f124SMoriah Waterland 
450*5c51f124SMoriah Waterland 				/*
451*5c51f124SMoriah Waterland 				 * Don't change the file, we can't write
452*5c51f124SMoriah Waterland 				 * to it anyway.
453*5c51f124SMoriah Waterland 				 */
454*5c51f124SMoriah Waterland 
455*5c51f124SMoriah Waterland 				mstat->attrchg = 0;
456*5c51f124SMoriah Waterland 				mstat->contchg = 0;
457*5c51f124SMoriah Waterland 
458*5c51f124SMoriah Waterland 				/*
459*5c51f124SMoriah Waterland 				 * If it's currently mounted, we can
460*5c51f124SMoriah Waterland 				 * at least test it for existence.
461*5c51f124SMoriah Waterland 				 */
462*5c51f124SMoriah Waterland 
463*5c51f124SMoriah Waterland 				if (is_mounted(ept->path, &(ext->fsys_value))) {
464*5c51f124SMoriah Waterland 					if (!isfile(NULL, dstp)) {
465*5c51f124SMoriah Waterland 						echo(MSG_IS_PRESENT, dstp);
466*5c51f124SMoriah Waterland 					} else {
467*5c51f124SMoriah Waterland 						echo(WRN_INSTVOL_NONE, dstp);
468*5c51f124SMoriah Waterland 					}
469*5c51f124SMoriah Waterland 				} else {
470*5c51f124SMoriah Waterland 					char *server_host;
471*5c51f124SMoriah Waterland 
472*5c51f124SMoriah Waterland 					server_host = get_server_host(
473*5c51f124SMoriah Waterland 						ext->fsys_value);
474*5c51f124SMoriah Waterland 
475*5c51f124SMoriah Waterland 					/* If not, we're just stuck. */
476*5c51f124SMoriah Waterland 					echo(WRN_INSTVOL_NOVERIFY,
477*5c51f124SMoriah Waterland 						dstp, server_host);
478*5c51f124SMoriah Waterland 				}
479*5c51f124SMoriah Waterland 
480*5c51f124SMoriah Waterland 				continue;
481*5c51f124SMoriah Waterland 			}
482*5c51f124SMoriah Waterland 
483*5c51f124SMoriah Waterland 			/* echo output destination name */
484*5c51f124SMoriah Waterland 
485*5c51f124SMoriah Waterland 			echo("%s", dstp);
486*5c51f124SMoriah Waterland 
487*5c51f124SMoriah Waterland 			/*
488*5c51f124SMoriah Waterland 			 * if no source then no need to copy/verify
489*5c51f124SMoriah Waterland 			 */
490*5c51f124SMoriah Waterland 
491*5c51f124SMoriah Waterland 			if (srcp == (char *)NULL) {
492*5c51f124SMoriah Waterland 				continue;
493*5c51f124SMoriah Waterland 			}
494*5c51f124SMoriah Waterland 
495*5c51f124SMoriah Waterland 			/*
496*5c51f124SMoriah Waterland 			 * If doing a partial installation (creating a
497*5c51f124SMoriah Waterland 			 * non-global zone), extra steps need to be taken:
498*5c51f124SMoriah Waterland 			 *
499*5c51f124SMoriah Waterland 			 * 1) if the file is not type 'e' and not type 'v' and
500*5c51f124SMoriah Waterland 			 * the class is "none": then the file must already
501*5c51f124SMoriah Waterland 			 * exist (as a result of the initial non-global zone
502*5c51f124SMoriah Waterland 			 * installation which caused all non-e/v files to be
503*5c51f124SMoriah Waterland 			 * copied from the global zone to the non-global
504*5c51f124SMoriah Waterland 			 * zone). If this is the case, verify that the file
505*5c51f124SMoriah Waterland 			 * exists and has the correct attributes.
506*5c51f124SMoriah Waterland 			 *
507*5c51f124SMoriah Waterland 			 * 2) if the file is not type 'e' and not type 'v'
508*5c51f124SMoriah Waterland 			 * and the class is NOT "none", *OR* if the file is
509*5c51f124SMoriah Waterland 			 * type 'e' or type 'v': then check to see if the
510*5c51f124SMoriah Waterland 			 * file is located in an area inherited from the
511*5c51f124SMoriah Waterland 			 * global zone. If so, then there is no ability to
512*5c51f124SMoriah Waterland 			 * change the file since inherited file systems are
513*5c51f124SMoriah Waterland 			 * "read only" - just verify that the file exists and
514*5c51f124SMoriah Waterland 			 * verify attributes only if not 'e' or 'v'.
515*5c51f124SMoriah Waterland 			 */
516*5c51f124SMoriah Waterland 
517*5c51f124SMoriah Waterland 			if (is_partial_inst() != 0) {
518*5c51f124SMoriah Waterland 
519*5c51f124SMoriah Waterland 				/*
520*5c51f124SMoriah Waterland 				 * determine if the destination package is in an
521*5c51f124SMoriah Waterland 				 * area inherited from the global zone
522*5c51f124SMoriah Waterland 				 */
523*5c51f124SMoriah Waterland 
524*5c51f124SMoriah Waterland 				n = pkgMatchInherited(srcp, dstp,
525*5c51f124SMoriah Waterland 					get_inst_root(), ept->ainfo.mode,
526*5c51f124SMoriah Waterland 					ept->cinfo.modtime, ept->ftype,
527*5c51f124SMoriah Waterland 					ept->cinfo.cksum);
528*5c51f124SMoriah Waterland 
529*5c51f124SMoriah Waterland 				echoDebug(DBG_INSTVOL_PARTIAL_INST,
530*5c51f124SMoriah Waterland 					srcp ? srcp : "", dstp ? dstp: "",
531*5c51f124SMoriah Waterland 					((get_inst_root()) &&
532*5c51f124SMoriah Waterland 					(strcmp(get_inst_root(), "/") != 0)) ?
533*5c51f124SMoriah Waterland 					get_inst_root() : "",
534*5c51f124SMoriah Waterland 					ept->ainfo.mode, ept->cinfo.modtime,
535*5c51f124SMoriah Waterland 					ept->ftype, ept->cinfo.cksum, n);
536*5c51f124SMoriah Waterland 
537*5c51f124SMoriah Waterland 				/*
538*5c51f124SMoriah Waterland 				 * if not type 'e|v' and class 'none', then the
539*5c51f124SMoriah Waterland 				 * file must already exist.
540*5c51f124SMoriah Waterland 				 */
541*5c51f124SMoriah Waterland 
542*5c51f124SMoriah Waterland 				if ((ept->ftype != 'e') &&
543*5c51f124SMoriah Waterland 					(ept->ftype != 'v') &&
544*5c51f124SMoriah Waterland 					(strcmp(cl_nam(ept->pkg_class_idx),
545*5c51f124SMoriah Waterland 								"none") == 0)) {
546*5c51f124SMoriah Waterland 
547*5c51f124SMoriah Waterland 					/*
548*5c51f124SMoriah Waterland 					 * if the file is in a space inherited
549*5c51f124SMoriah Waterland 					 * from the global zone, and if the
550*5c51f124SMoriah Waterland 					 * contents or attributes are incorrect,
551*5c51f124SMoriah Waterland 					 * then generate a warning that the
552*5c51f124SMoriah Waterland 					 * global zone file contents and/or file
553*5c51f124SMoriah Waterland 					 * attributes have been modified and
554*5c51f124SMoriah Waterland 					 * that the modifications are extended
555*5c51f124SMoriah Waterland 					 * to the non-global zone (inherited
556*5c51f124SMoriah Waterland 					 * from the global zone).
557*5c51f124SMoriah Waterland 					 */
558*5c51f124SMoriah Waterland 
559*5c51f124SMoriah Waterland 					if (n == 0) {
560*5c51f124SMoriah Waterland 						/* is file changed? */
561*5c51f124SMoriah Waterland 						n = finalck(ept, 1, 1, B_TRUE);
562*5c51f124SMoriah Waterland 
563*5c51f124SMoriah Waterland 						/* no - ok - continue */
564*5c51f124SMoriah Waterland 						if (n == 0) {
565*5c51f124SMoriah Waterland 							continue;
566*5c51f124SMoriah Waterland 						}
567*5c51f124SMoriah Waterland 
568*5c51f124SMoriah Waterland 						/* output warning message */
569*5c51f124SMoriah Waterland 						logerr(NOTE_INSTVOL_FINALCKFAIL,
570*5c51f124SMoriah Waterland 							pkginst, ext->map_path,
571*5c51f124SMoriah Waterland 							a_zoneName, ept->path);
572*5c51f124SMoriah Waterland 						continue;
573*5c51f124SMoriah Waterland 					} else if (!finalck(ept, 1, 1,
574*5c51f124SMoriah Waterland 								B_FALSE)) {
575*5c51f124SMoriah Waterland 						/*
576*5c51f124SMoriah Waterland 						 * non-e/v file of class "none"
577*5c51f124SMoriah Waterland 						 * not inherited from the global
578*5c51f124SMoriah Waterland 						 * zone: verify file already
579*5c51f124SMoriah Waterland 						 * exists:everything checks here
580*5c51f124SMoriah Waterland 						 */
581*5c51f124SMoriah Waterland 						mstat->attrchg = 0;
582*5c51f124SMoriah Waterland 						mstat->contchg = 0;
583*5c51f124SMoriah Waterland 					}
584*5c51f124SMoriah Waterland 					continue;
585*5c51f124SMoriah Waterland 				}
586*5c51f124SMoriah Waterland 
587*5c51f124SMoriah Waterland 				/*
588*5c51f124SMoriah Waterland 				 * non-e/v file with class action script, or
589*5c51f124SMoriah Waterland 				 * e/v file: if the file is in an area inherited
590*5c51f124SMoriah Waterland 				 * from the global zone, then no need (or the
591*5c51f124SMoriah Waterland 				 * ability) to update just accept the file as is
592*5c51f124SMoriah Waterland 				 */
593*5c51f124SMoriah Waterland 
594*5c51f124SMoriah Waterland 				if (n == B_TRUE) {
595*5c51f124SMoriah Waterland 					/*
596*5c51f124SMoriah Waterland 					 * the object is in an area inherited
597*5c51f124SMoriah Waterland 					 * from the global zone and the objects
598*5c51f124SMoriah Waterland 					 * attributes are verified
599*5c51f124SMoriah Waterland 					 */
600*5c51f124SMoriah Waterland 
601*5c51f124SMoriah Waterland 					mstat->attrchg = 0;
602*5c51f124SMoriah Waterland 					mstat->contchg = 0;
603*5c51f124SMoriah Waterland 
604*5c51f124SMoriah Waterland 					/* NOTE: package object skipped */
605*5c51f124SMoriah Waterland 
606*5c51f124SMoriah Waterland 					if (skipped == (char *)NULL) {
607*5c51f124SMoriah Waterland 						skipped = dstp;
608*5c51f124SMoriah Waterland 					echoDebug(DBG_INSTVOL_OBJ_SKIPPED,
609*5c51f124SMoriah Waterland 								skipped);
610*5c51f124SMoriah Waterland 					}
611*5c51f124SMoriah Waterland 					continue;
612*5c51f124SMoriah Waterland 				}
613*5c51f124SMoriah Waterland 			}
614*5c51f124SMoriah Waterland 
615*5c51f124SMoriah Waterland 			/*
616*5c51f124SMoriah Waterland 			 * Copy from source media to target path and fix file
617*5c51f124SMoriah Waterland 			 * mode and permission now in case installation halted.
618*5c51f124SMoriah Waterland 			 */
619*5c51f124SMoriah Waterland 
620*5c51f124SMoriah Waterland 			if (z_path_is_inherited(dstp, ept->ftype,
621*5c51f124SMoriah Waterland 			    get_inst_root()) == B_FALSE) {
622*5c51f124SMoriah Waterland 
623*5c51f124SMoriah Waterland 				/*
624*5c51f124SMoriah Waterland 				 * If the filesystem is read-only don't attempt
625*5c51f124SMoriah Waterland 				 * to copy a file. Just check that the content
626*5c51f124SMoriah Waterland 				 * and attributes of the file are correct.
627*5c51f124SMoriah Waterland 				 *
628*5c51f124SMoriah Waterland 				 * Normally this doesn't happen, because files,
629*5c51f124SMoriah Waterland 				 * which don't change, are not returned by
630*5c51f124SMoriah Waterland 				 * domerg(). However when installing a patch in
631*5c51f124SMoriah Waterland 				 * a sparse zone, which was already installed
632*5c51f124SMoriah Waterland 				 * in global zone with -G option, NGZ's
633*5c51f124SMoriah Waterland 				 * contents db still contains the old record
634*5c51f124SMoriah Waterland 				 * for this file and therefore domerg()
635*5c51f124SMoriah Waterland 				 * considers these files to be different even
636*5c51f124SMoriah Waterland 				 * though they are the same.
637*5c51f124SMoriah Waterland 				 */
638*5c51f124SMoriah Waterland 				n = 0;
639*5c51f124SMoriah Waterland 				if (is_fs_writeable(ept->path,
640*5c51f124SMoriah Waterland 				    &(ext->fsys_value)))
641*5c51f124SMoriah Waterland 					n = cppath(MODE_SET|DIR_DISPLAY, srcp,
642*5c51f124SMoriah Waterland 					    dstp, ept->ainfo.mode);
643*5c51f124SMoriah Waterland 
644*5c51f124SMoriah Waterland 				if (n != 0) {
645*5c51f124SMoriah Waterland 					warnflag++;
646*5c51f124SMoriah Waterland 				} else if (!finalck(ept, 1, 1, B_FALSE)) {
647*5c51f124SMoriah Waterland 					/*
648*5c51f124SMoriah Waterland 					 * everything checks here
649*5c51f124SMoriah Waterland 					 */
650*5c51f124SMoriah Waterland 					mstat->attrchg = 0;
651*5c51f124SMoriah Waterland 					mstat->contchg = 0;
652*5c51f124SMoriah Waterland 				}
653*5c51f124SMoriah Waterland 			}
654*5c51f124SMoriah Waterland 
655*5c51f124SMoriah Waterland 			/* NOTE: a package object was updated */
656*5c51f124SMoriah Waterland 
657*5c51f124SMoriah Waterland 			if (updated == (char *)NULL) {
658*5c51f124SMoriah Waterland 				echoDebug(DBG_INSTVOL_OBJ_UPDATED, dstp);
659*5c51f124SMoriah Waterland 				updated = dstp;
660*5c51f124SMoriah Waterland 			}
661*5c51f124SMoriah Waterland 		}
662*5c51f124SMoriah Waterland 
663*5c51f124SMoriah Waterland 		/*
664*5c51f124SMoriah Waterland 		 * We have now completed processing of all pathnames
665*5c51f124SMoriah Waterland 		 * associated with this volume and class.
666*5c51f124SMoriah Waterland 		 */
667*5c51f124SMoriah Waterland 		if (cl_iscript(classidx)) {
668*5c51f124SMoriah Waterland 			/*
669*5c51f124SMoriah Waterland 			 * Execute appropriate class action script
670*5c51f124SMoriah Waterland 			 * with list of source/destination pathnames
671*5c51f124SMoriah Waterland 			 * as the input to the script.
672*5c51f124SMoriah Waterland 			 */
673*5c51f124SMoriah Waterland 
674*5c51f124SMoriah Waterland 			if (chdir(pkgbin)) {
675*5c51f124SMoriah Waterland 				progerr(ERR_CHGDIR, pkgbin);
676*5c51f124SMoriah Waterland 				quit(99);
677*5c51f124SMoriah Waterland 			}
678*5c51f124SMoriah Waterland 
679*5c51f124SMoriah Waterland 			if (listfp) {
680*5c51f124SMoriah Waterland 				(void) fclose(listfp);
681*5c51f124SMoriah Waterland 			}
682*5c51f124SMoriah Waterland 
683*5c51f124SMoriah Waterland 			/*
684*5c51f124SMoriah Waterland 			 * if the object associated with the class action script
685*5c51f124SMoriah Waterland 			 * is in an area inherited from the global zone, then
686*5c51f124SMoriah Waterland 			 * there is no need to run the class action script -
687*5c51f124SMoriah Waterland 			 * assume that anything the script would do has already
688*5c51f124SMoriah Waterland 			 * been done in the area shared from the global zone.
689*5c51f124SMoriah Waterland 			 */
690*5c51f124SMoriah Waterland 
691*5c51f124SMoriah Waterland 			/* nothing updated, nothing skipped */
692*5c51f124SMoriah Waterland 
693*5c51f124SMoriah Waterland 			echoDebug(DBG_INSTVOL_CAS_INFO, is_partial_inst(),
694*5c51f124SMoriah Waterland 				updated ? updated : "",
695*5c51f124SMoriah Waterland 				skipped ? skipped : "",
696*5c51f124SMoriah Waterland 				anyPathLocal ? anyPathLocal : "");
697*5c51f124SMoriah Waterland 
698*5c51f124SMoriah Waterland 			if ((is_partial_inst() != 0) &&
699*5c51f124SMoriah Waterland 					(updated == (char *)NULL) &&
700*5c51f124SMoriah Waterland 					(anyPathLocal == (char *)NULL)) {
701*5c51f124SMoriah Waterland 
702*5c51f124SMoriah Waterland 				/*
703*5c51f124SMoriah Waterland 				 * installing in non-global zone, and no object
704*5c51f124SMoriah Waterland 				 * has been updated (installed/verified in non-
705*5c51f124SMoriah Waterland 				 * inherited area), and no path delivered by the
706*5c51f124SMoriah Waterland 				 * package is in an area not inherited from the
707*5c51f124SMoriah Waterland 				 * global zone (all paths delivered are in
708*5c51f124SMoriah Waterland 				 * areas inherited from the global zone): do not
709*5c51f124SMoriah Waterland 				 * run the class action script because the only
710*5c51f124SMoriah Waterland 				 * affected areas are inherited (read only).
711*5c51f124SMoriah Waterland 				 */
712*5c51f124SMoriah Waterland 
713*5c51f124SMoriah Waterland 				echoDebug(DBG_INSTVOL_NOT_RUNNING_CAS,
714*5c51f124SMoriah Waterland 					a_zoneName ? a_zoneName : "?",
715*5c51f124SMoriah Waterland 					eocflag ? "ENDOFCLASS" :
716*5c51f124SMoriah Waterland 							cl_iscript(classidx),
717*5c51f124SMoriah Waterland 					cl_nam(classidx),
718*5c51f124SMoriah Waterland 					cl_iscript(classidx));
719*5c51f124SMoriah Waterland 
720*5c51f124SMoriah Waterland 				if ((r_skipped != (char **)NULL) &&
721*5c51f124SMoriah Waterland 					(*r_skipped == (char *)NULL) &&
722*5c51f124SMoriah Waterland 					(skipped == (char *)NULL)) {
723*5c51f124SMoriah Waterland 					skipped = "postinstall";
724*5c51f124SMoriah Waterland 					echoDebug(DBG_INSTVOL_OBJ_SKIPPED,
725*5c51f124SMoriah Waterland 								skipped);
726*5c51f124SMoriah Waterland 				}
727*5c51f124SMoriah Waterland 			} else {
728*5c51f124SMoriah Waterland 				/* run the class action script */
729*5c51f124SMoriah Waterland 
730*5c51f124SMoriah Waterland 				echoDebug(DBG_INSTVOL_RUNNING_CAS,
731*5c51f124SMoriah Waterland 					a_zoneName ? a_zoneName : "?",
732*5c51f124SMoriah Waterland 					eocflag ? "ENDOFCLASS" :
733*5c51f124SMoriah Waterland 							cl_iscript(classidx),
734*5c51f124SMoriah Waterland 					cl_nam(classidx),
735*5c51f124SMoriah Waterland 					cl_iscript(classidx));
736*5c51f124SMoriah Waterland 
737*5c51f124SMoriah Waterland 				/* Use ULIMIT if supplied. */
738*5c51f124SMoriah Waterland 				set_ulimit(cl_iscript(classidx), ERR_CASFAIL);
739*5c51f124SMoriah Waterland 
740*5c51f124SMoriah Waterland 				if (eocflag) {
741*5c51f124SMoriah Waterland 					/*
742*5c51f124SMoriah Waterland 					 * end of class detected.
743*5c51f124SMoriah Waterland 					 * Since there are no more volumes which
744*5c51f124SMoriah Waterland 					 * contain pathnames associated with
745*5c51f124SMoriah Waterland 					 * this class, execute class action
746*5c51f124SMoriah Waterland 					 * script with the ENDOFCLASS argument;
747*5c51f124SMoriah Waterland 					 * we do this even if none of the path
748*5c51f124SMoriah Waterland 					 * names associated with this class and
749*5c51f124SMoriah Waterland 					 * volume needed installation to
750*5c51f124SMoriah Waterland 					 * guarantee the class action script is
751*5c51f124SMoriah Waterland 					 * executed at least once during package
752*5c51f124SMoriah Waterland 					 * installation.
753*5c51f124SMoriah Waterland 					 */
754*5c51f124SMoriah Waterland 					if (pkgverbose) {
755*5c51f124SMoriah Waterland 						n = pkgexecl((listfp ?
756*5c51f124SMoriah Waterland 							listfile : CAS_STDIN),
757*5c51f124SMoriah Waterland 							CAS_STDOUT,
758*5c51f124SMoriah Waterland 							CAS_USER, CAS_GRP,
759*5c51f124SMoriah Waterland 							SHELL, "-x",
760*5c51f124SMoriah Waterland 							cl_iscript(classidx),
761*5c51f124SMoriah Waterland 							"ENDOFCLASS", NULL);
762*5c51f124SMoriah Waterland 					} else {
763*5c51f124SMoriah Waterland 						n = pkgexecl(
764*5c51f124SMoriah Waterland 							(listfp ?
765*5c51f124SMoriah Waterland 							listfile : CAS_STDIN),
766*5c51f124SMoriah Waterland 							CAS_STDOUT, CAS_USER,
767*5c51f124SMoriah Waterland 							CAS_GRP, SHELL,
768*5c51f124SMoriah Waterland 							cl_iscript(classidx),
769*5c51f124SMoriah Waterland 							"ENDOFCLASS", NULL);
770*5c51f124SMoriah Waterland 					}
771*5c51f124SMoriah Waterland 					ckreturn(n, ERR_CASFAIL);
772*5c51f124SMoriah Waterland 				} else if (count) {
773*5c51f124SMoriah Waterland 					/* execute class action script */
774*5c51f124SMoriah Waterland 					if (pkgverbose) {
775*5c51f124SMoriah Waterland 						n = pkgexecl(listfile,
776*5c51f124SMoriah Waterland 							CAS_STDOUT, CAS_USER,
777*5c51f124SMoriah Waterland 							CAS_GRP, SHELL, "-x",
778*5c51f124SMoriah Waterland 							cl_iscript(classidx),
779*5c51f124SMoriah Waterland 							NULL);
780*5c51f124SMoriah Waterland 					} else {
781*5c51f124SMoriah Waterland 						n = pkgexecl(listfile,
782*5c51f124SMoriah Waterland 							CAS_STDOUT, CAS_USER,
783*5c51f124SMoriah Waterland 							CAS_GRP, SHELL,
784*5c51f124SMoriah Waterland 							cl_iscript(classidx),
785*5c51f124SMoriah Waterland 							NULL);
786*5c51f124SMoriah Waterland 					}
787*5c51f124SMoriah Waterland 					ckreturn(n, ERR_CASFAIL);
788*5c51f124SMoriah Waterland 				}
789*5c51f124SMoriah Waterland 
790*5c51f124SMoriah Waterland 				/*
791*5c51f124SMoriah Waterland 				 * Ensure the mod times on disk match those
792*5c51f124SMoriah Waterland 				 * in the pkgmap. In this case, call cverify
793*5c51f124SMoriah Waterland 				 * with checksumming disabled, since the only
794*5c51f124SMoriah Waterland 				 * action that needs to be done is to verify
795*5c51f124SMoriah Waterland 				 * that the attributes are correct.
796*5c51f124SMoriah Waterland 				 */
797*5c51f124SMoriah Waterland 
798*5c51f124SMoriah Waterland 				if ((rfp = regfiles_head) != NULL) {
799*5c51f124SMoriah Waterland 					while (rfp != NULL) {
800*5c51f124SMoriah Waterland 					    ept = &(extlist[rfp->val]->cf_ent);
801*5c51f124SMoriah Waterland 					    cverify(1, &ept->ftype, ept->path,
802*5c51f124SMoriah Waterland 						&ept->cinfo, 0);
803*5c51f124SMoriah Waterland 					    rfp = rfp->next;
804*5c51f124SMoriah Waterland 					}
805*5c51f124SMoriah Waterland 					regfiles_free();
806*5c51f124SMoriah Waterland 				}
807*5c51f124SMoriah Waterland 
808*5c51f124SMoriah Waterland 				clr_ulimit();
809*5c51f124SMoriah Waterland 
810*5c51f124SMoriah Waterland 				if ((r_updated != (char **)NULL) &&
811*5c51f124SMoriah Waterland 					(*r_updated == (char *)NULL) &&
812*5c51f124SMoriah Waterland 					(updated == (char *)NULL)) {
813*5c51f124SMoriah Waterland 					updated = "postinstall";
814*5c51f124SMoriah Waterland 					echoDebug(DBG_INSTVOL_OBJ_UPDATED,
815*5c51f124SMoriah Waterland 								updated);
816*5c51f124SMoriah Waterland 				}
817*5c51f124SMoriah Waterland 			}
818*5c51f124SMoriah Waterland 			if (listfile) {
819*5c51f124SMoriah Waterland 				(void) remove(listfile);
820*5c51f124SMoriah Waterland 			}
821*5c51f124SMoriah Waterland 		}
822*5c51f124SMoriah Waterland 
823*5c51f124SMoriah Waterland 		if (eocflag && (!is_partial_inst() || (is_partial_inst() &&
824*5c51f124SMoriah Waterland 			strcmp(cl_nam(classidx), "none") != 0))) {
825*5c51f124SMoriah Waterland 			if (cl_dvfy(classidx) == QKVERIFY && !repl_permitted) {
826*5c51f124SMoriah Waterland 				/*
827*5c51f124SMoriah Waterland 				 * The quick verify just fixes everything.
828*5c51f124SMoriah Waterland 				 * If it returns 0, all is well. If it
829*5c51f124SMoriah Waterland 				 * returns 1, then the class installation
830*5c51f124SMoriah Waterland 				 * was incomplete and we retry on the
831*5c51f124SMoriah Waterland 				 * stuff that failed in the conventional
832*5c51f124SMoriah Waterland 				 * way (without a CAS). this is primarily
833*5c51f124SMoriah Waterland 				 * to accomodate old archives such as are
834*5c51f124SMoriah Waterland 				 * found in pre-2.5 WOS; but, it is also
835*5c51f124SMoriah Waterland 				 * used when a critical dynamic library
836*5c51f124SMoriah Waterland 				 * is not archived with its class.
837*5c51f124SMoriah Waterland 				 */
838*5c51f124SMoriah Waterland 				if (!fix_attributes(extlist, classidx)) {
839*5c51f124SMoriah Waterland 					/*
840*5c51f124SMoriah Waterland 					 * Reset the CAS pointer. If the
841*5c51f124SMoriah Waterland 					 * function returns 0 then there
842*5c51f124SMoriah Waterland 					 * was no script there in the first
843*5c51f124SMoriah Waterland 					 * place and we'll just have to
844*5c51f124SMoriah Waterland 					 * call this a miss.
845*5c51f124SMoriah Waterland 					 */
846*5c51f124SMoriah Waterland 					if (cl_deliscript(classidx))
847*5c51f124SMoriah Waterland 						/*
848*5c51f124SMoriah Waterland 						 * Decrement classidx for
849*5c51f124SMoriah Waterland 						 * next pass.
850*5c51f124SMoriah Waterland 						 */
851*5c51f124SMoriah Waterland 						classidx--;
852*5c51f124SMoriah Waterland 				}
853*5c51f124SMoriah Waterland 			} else {
854*5c51f124SMoriah Waterland 				/*
855*5c51f124SMoriah Waterland 				 * Finalize merge. This checks to make sure
856*5c51f124SMoriah Waterland 				 * file attributes are correct and any links
857*5c51f124SMoriah Waterland 				 * specified are created.
858*5c51f124SMoriah Waterland 				 */
859*5c51f124SMoriah Waterland 				(void) endofclass(extlist, classidx,
860*5c51f124SMoriah Waterland 					(cl_iscript(classidx) ? 0 : 1),
861*5c51f124SMoriah Waterland 					a_cfVfp, a_cfTmpVfp);
862*5c51f124SMoriah Waterland 			}
863*5c51f124SMoriah Waterland 		}
864*5c51f124SMoriah Waterland 	    }
865*5c51f124SMoriah Waterland 	}
866*5c51f124SMoriah Waterland 
867*5c51f124SMoriah Waterland 	/*
868*5c51f124SMoriah Waterland 	 * Instead of creating links back to the GZ files the logic is
869*5c51f124SMoriah Waterland 	 * to let zdo recreate the files from the GZ then invoke pkgadd to
870*5c51f124SMoriah Waterland 	 * install the editable files and skip over any 'f'type files.
871*5c51f124SMoriah Waterland 	 * The commented out block is to create the links which should be
872*5c51f124SMoriah Waterland 	 * removed once the current code is tested to be correct.
873*5c51f124SMoriah Waterland 	 */
874*5c51f124SMoriah Waterland 
875*5c51f124SMoriah Waterland 	/*
876*5c51f124SMoriah Waterland 	 * Go through extlist creating links for 'f'type files
877*5c51f124SMoriah Waterland 	 * if we're in a global zone. Note that this code lies
878*5c51f124SMoriah Waterland 	 * here instead of in the main loop to support CAF packages.
879*5c51f124SMoriah Waterland 	 * In a CAF package the files are installed by the i.none script
880*5c51f124SMoriah Waterland 	 * and don't exist until all files are done being processed, thus
881*5c51f124SMoriah Waterland 	 * the additional loop through extlist.
882*5c51f124SMoriah Waterland 	 */
883*5c51f124SMoriah Waterland 
884*5c51f124SMoriah Waterland 	/*
885*5c51f124SMoriah Waterland 	 * output appropriate completion message
886*5c51f124SMoriah Waterland 	 */
887*5c51f124SMoriah Waterland 
888*5c51f124SMoriah Waterland 	if (is_depend_pkginfo_DB() == B_TRUE) {
889*5c51f124SMoriah Waterland 		/* updating database only (hollow package) */
890*5c51f124SMoriah Waterland 		if (a_zoneName == (char *)NULL) {
891*5c51f124SMoriah Waterland 			echo(MSG_DBUPD_N_N, part, nparts);
892*5c51f124SMoriah Waterland 		} else {
893*5c51f124SMoriah Waterland 			echo(MSG_DBUPD_N_N_LZ, part, nparts, a_zoneName);
894*5c51f124SMoriah Waterland 		}
895*5c51f124SMoriah Waterland 	} else if (tcount == 0) {
896*5c51f124SMoriah Waterland 		/* updating package (non-hollow package) */
897*5c51f124SMoriah Waterland 		if (a_zoneName == (char *)NULL) {
898*5c51f124SMoriah Waterland 			echo(MSG_INST_N_N, part, nparts);
899*5c51f124SMoriah Waterland 		} else {
900*5c51f124SMoriah Waterland 			echo(MSG_INST_N_N_LZ, part, nparts, a_zoneName);
901*5c51f124SMoriah Waterland 		}
902*5c51f124SMoriah Waterland 	}
903*5c51f124SMoriah Waterland 
904*5c51f124SMoriah Waterland 	/*
905*5c51f124SMoriah Waterland 	 * if any package objects were updated (not inherited from the
906*5c51f124SMoriah Waterland 	 * global zone or otherwise already in existence), set the updated
907*5c51f124SMoriah Waterland 	 * flag as appropriate
908*5c51f124SMoriah Waterland 	 */
909*5c51f124SMoriah Waterland 
910*5c51f124SMoriah Waterland 	if (updated != (char *)NULL) {
911*5c51f124SMoriah Waterland 		echoDebug(DBG_INSTVOL_OBJ_UPDATED, updated);
912*5c51f124SMoriah Waterland 		if (r_updated != (char **)NULL) {
913*5c51f124SMoriah Waterland 			*r_updated = updated;
914*5c51f124SMoriah Waterland 		}
915*5c51f124SMoriah Waterland 	}
916*5c51f124SMoriah Waterland 
917*5c51f124SMoriah Waterland 	/*
918*5c51f124SMoriah Waterland 	 * if any package objects were skipped (verified inherited from the
919*5c51f124SMoriah Waterland 	 * global zone), set the skipped flag as appropriate
920*5c51f124SMoriah Waterland 	 */
921*5c51f124SMoriah Waterland 
922*5c51f124SMoriah Waterland 	if (skipped != (char *)NULL) {
923*5c51f124SMoriah Waterland 		echoDebug(DBG_INSTVOL_OBJ_SKIPPED, skipped);
924*5c51f124SMoriah Waterland 		if (r_skipped != (char **)NULL) {
925*5c51f124SMoriah Waterland 			*r_skipped = skipped;
926*5c51f124SMoriah Waterland 		}
927*5c51f124SMoriah Waterland 	}
928*5c51f124SMoriah Waterland }
929*5c51f124SMoriah Waterland 
930*5c51f124SMoriah Waterland /*
931*5c51f124SMoriah Waterland  * Name:	domerg
932*5c51f124SMoriah Waterland  * Description: For the specified class, review each entry and return the array
933*5c51f124SMoriah Waterland  *		index number of the next regular file to process. Hard links are
934*5c51f124SMoriah Waterland  *		skipped (they are created in endofclass() and directories,
935*5c51f124SMoriah Waterland  *		symlinks, pipes and devices are created here, as well as any
936*5c51f124SMoriah Waterland  *		file that already exists and has the correct attributes.
937*5c51f124SMoriah Waterland  * Arguments:	struct cfextra **extlist - [RO, *RW]
938*5c51f124SMoriah Waterland  *			- Pointer to list of cfextra structures representing
939*5c51f124SMoriah Waterland  *			  the pkgmap of the package to be installed
940*5c51f124SMoriah Waterland  *		int part - [RO, *RO]
941*5c51f124SMoriah Waterland  *			- the part of the package currently being processed;
942*5c51f124SMoriah Waterland  *			  packages begin with part "1" and proceed for the
943*5c51f124SMoriah Waterland  *			  number (nparts) that comprise the package (volume).
944*5c51f124SMoriah Waterland  *		int nparts - [RO, *RO]
945*5c51f124SMoriah Waterland  *			- the number of parts the package is divided into
946*5c51f124SMoriah Waterland  *		int myclass - [RO, *RO]
947*5c51f124SMoriah Waterland  *			- index into class array of the current class
948*5c51f124SMoriah Waterland  *		char **srcp - [RW, *RW]
949*5c51f124SMoriah Waterland  *			- pointer to pointer to string representing the source
950*5c51f124SMoriah Waterland  *			  path for the next package to process - if this
951*5c51f124SMoriah Waterland  *			  function returns != DMRG_DONE then this pointer is
952*5c51f124SMoriah Waterland  *			  set to a pointer to a string representing the source
953*5c51f124SMoriah Waterland  *			  path for the next object from the package to process
954*5c51f124SMoriah Waterland  *		char **dstp - [RW, *RW]
955*5c51f124SMoriah Waterland  *			- pointer to pointer to string representing the target
956*5c51f124SMoriah Waterland  *			  path for the next package to process - if this
957*5c51f124SMoriah Waterland  *			  function returns != DMRG_DONE then this pointer is
958*5c51f124SMoriah Waterland  *			  set to a pointer to a string representing the target
959*5c51f124SMoriah Waterland  *			  path for the next object from the package to process
960*5c51f124SMoriah Waterland  *		char **r_updated - [RO, *RW]
961*5c51f124SMoriah Waterland  *			- pointer to pointer to string - set if the last path
962*5c51f124SMoriah Waterland  *			  returned exists or does not need updating and the
963*5c51f124SMoriah Waterland  *			  object is NOT located in an area inherited from the
964*5c51f124SMoriah Waterland  *			  global zone. This is used to determine if the last
965*5c51f124SMoriah Waterland  *			  path object returned DOES exist in an area that is
966*5c51f124SMoriah Waterland  *			  inherited from the global zone. If no paths are
967*5c51f124SMoriah Waterland  *			  inherited from the global zone, this is always set
968*5c51f124SMoriah Waterland  *			  when a path to be installed exists and has the
969*5c51f124SMoriah Waterland  *			  correct contents.
970*5c51f124SMoriah Waterland  *		char **r_skipped - [RO, *RW]
971*5c51f124SMoriah Waterland  *			- pointer to pointer to string - set if the last path
972*5c51f124SMoriah Waterland  *			  returned exists or does not need updating and the
973*5c51f124SMoriah Waterland  *			  object IS located in an area inherited from the
974*5c51f124SMoriah Waterland  *			  global zone. This is used to determine if the last
975*5c51f124SMoriah Waterland  *			  path object returned does NOT exist in an area that
976*5c51f124SMoriah Waterland  *			  is inherited from the global zone. If no paths are
977*5c51f124SMoriah Waterland  *			  inherited from the global zone, this is never set.
978*5c51f124SMoriah Waterland  *		char **r_anyPathLocal - [RO, *RW]
979*5c51f124SMoriah Waterland  *			- pointer to pointer to string - set if any object
980*5c51f124SMoriah Waterland  *			  belonging to the package is NOT located in an area
981*5c51f124SMoriah Waterland  *			  inherited from the global zone. This is used to
982*5c51f124SMoriah Waterland  *			  determine if the package references ANY objects that
983*5c51f124SMoriah Waterland  *			  are NOT located in an area inherited from the global
984*5c51f124SMoriah Waterland  *			  zone - regardless of whether or not they need to be
985*5c51f124SMoriah Waterland  *			  updated (installed/copied). If no paths are inherited
986*5c51f124SMoriah Waterland  *			  from the global zone, this is always set when a path
987*5c51f124SMoriah Waterland  *			  to be installed already exists and has the correct
988*5c51f124SMoriah Waterland  *			  contents.
989*5c51f124SMoriah Waterland  * Returns:	int
990*5c51f124SMoriah Waterland  *			!= DMRG_DONE - index into extlist of the next path to
991*5c51f124SMoriah Waterland  *				be processed - that needs to be installed/copied
992*5c51f124SMoriah Waterland  *			== DMRG_DONE - all entries processed
993*5c51f124SMoriah Waterland  */
994*5c51f124SMoriah Waterland 
995*5c51f124SMoriah Waterland static int
996*5c51f124SMoriah Waterland domerg(struct cfextra **extlist, int part, int nparts,
997*5c51f124SMoriah Waterland 	int myclass, char **srcp, char **dstp,
998*5c51f124SMoriah Waterland 	char **r_updated, char **r_skipped,
999*5c51f124SMoriah Waterland 	char **r_anyPathLocal)
1000*5c51f124SMoriah Waterland {
1001*5c51f124SMoriah Waterland 	boolean_t	stateFlag = B_FALSE;
1002*5c51f124SMoriah Waterland 	int		i;
1003*5c51f124SMoriah Waterland 	int		msg_ugid;
1004*5c51f124SMoriah Waterland 	static int	maxvol = 0;
1005*5c51f124SMoriah Waterland 	static int	svindx = 0;
1006*5c51f124SMoriah Waterland 	static int	svpart = 0;
1007*5c51f124SMoriah Waterland 	struct cfent	*ept = (struct cfent *)NULL;
1008*5c51f124SMoriah Waterland 	struct mergstat *mstat = (struct mergstat *)NULL;
1009*5c51f124SMoriah Waterland 
1010*5c51f124SMoriah Waterland 	/* reset returned path pointers */
1011*5c51f124SMoriah Waterland 
1012*5c51f124SMoriah Waterland 	*dstp = (char *)NULL;
1013*5c51f124SMoriah Waterland 	*srcp = (char *)NULL;
1014*5c51f124SMoriah Waterland 
1015*5c51f124SMoriah Waterland 	/* set to start or continue based on which part being processed */
1016*5c51f124SMoriah Waterland 
1017*5c51f124SMoriah Waterland 	if (part != 0) {
1018*5c51f124SMoriah Waterland 		maxvol = 0;
1019*5c51f124SMoriah Waterland 		svindx = 0;
1020*5c51f124SMoriah Waterland 		svpart = part;
1021*5c51f124SMoriah Waterland 	} else {
1022*5c51f124SMoriah Waterland 		i = svindx;
1023*5c51f124SMoriah Waterland 		part = svpart;
1024*5c51f124SMoriah Waterland 	}
1025*5c51f124SMoriah Waterland 
1026*5c51f124SMoriah Waterland 	/*
1027*5c51f124SMoriah Waterland 	 * This goes through the pkgmap entries one by one testing them
1028*5c51f124SMoriah Waterland 	 * for inclusion in the package database as well as for validity
1029*5c51f124SMoriah Waterland 	 * against existing files.
1030*5c51f124SMoriah Waterland 	 */
1031*5c51f124SMoriah Waterland 	for (i = svindx; extlist[i]; i++) {
1032*5c51f124SMoriah Waterland 		ept = &(extlist[i]->cf_ent);
1033*5c51f124SMoriah Waterland 		mstat = &(extlist[i]->mstat);
1034*5c51f124SMoriah Waterland 
1035*5c51f124SMoriah Waterland 		/*
1036*5c51f124SMoriah Waterland 		 * as paths are processed, if the "anyPathLocal" flag has not
1037*5c51f124SMoriah Waterland 		 * been set, if the object is not of type 'i' (package script),
1038*5c51f124SMoriah Waterland 		 * check to see if the object is in an area inherited from the
1039*5c51f124SMoriah Waterland 		 * global zone - if not, set "anyPathLocal" to the path found,
1040*5c51f124SMoriah Waterland 		 * indicating that at least one path is in an area that is not
1041*5c51f124SMoriah Waterland 		 * inherited from the global zone.
1042*5c51f124SMoriah Waterland 		 */
1043*5c51f124SMoriah Waterland 
1044*5c51f124SMoriah Waterland 		if ((r_anyPathLocal != (char **)NULL) &&
1045*5c51f124SMoriah Waterland 			(*r_anyPathLocal == (char *)NULL) &&
1046*5c51f124SMoriah Waterland 			(ept->ftype != 'i') &&
1047*5c51f124SMoriah Waterland 			(z_path_is_inherited(ept->path, ept->ftype,
1048*5c51f124SMoriah Waterland 						get_inst_root()) == B_FALSE)) {
1049*5c51f124SMoriah Waterland 			echoDebug(DBG_INSTVOL_OBJ_LOCAL, ept->path);
1050*5c51f124SMoriah Waterland 			*r_anyPathLocal = ept->path;
1051*5c51f124SMoriah Waterland 		}
1052*5c51f124SMoriah Waterland 
1053*5c51f124SMoriah Waterland 		/* if this isn't the class of current interest, skip it */
1054*5c51f124SMoriah Waterland 
1055*5c51f124SMoriah Waterland 		if (myclass != ept->pkg_class_idx) {
1056*5c51f124SMoriah Waterland 			continue;
1057*5c51f124SMoriah Waterland 		}
1058*5c51f124SMoriah Waterland 
1059*5c51f124SMoriah Waterland 		/* if the class is invalid, announce it & exit */
1060*5c51f124SMoriah Waterland 		if (ept->pkg_class_idx == -1) {
1061*5c51f124SMoriah Waterland 			progerr(ERR_CLIDX, ept->pkg_class_idx,
1062*5c51f124SMoriah Waterland 			    (ept->path && *ept->path) ? ept->path : "unknown");
1063*5c51f124SMoriah Waterland 			logerr(gettext("pathname=%s\n"),
1064*5c51f124SMoriah Waterland 			    (ept->path && *ept->path) ? ept->path : "unknown");
1065*5c51f124SMoriah Waterland 			logerr(gettext("class=<%s>\n"),
1066*5c51f124SMoriah Waterland 			    (ept->pkg_class && *ept->pkg_class) ?
1067*5c51f124SMoriah Waterland 			    ept->pkg_class : "Unknown");
1068*5c51f124SMoriah Waterland 			logerr(gettext("CLASSES=<%s>\n"),
1069*5c51f124SMoriah Waterland 			    getenv("CLASSES") ? getenv("CLASSES") : "Not Set");
1070*5c51f124SMoriah Waterland 			quit(99);
1071*5c51f124SMoriah Waterland 		}
1072*5c51f124SMoriah Waterland 
1073*5c51f124SMoriah Waterland 		/*
1074*5c51f124SMoriah Waterland 		 * Next check to see if we are going to try to delete a
1075*5c51f124SMoriah Waterland 		 * populated directory in some distressing way.
1076*5c51f124SMoriah Waterland 		 */
1077*5c51f124SMoriah Waterland 		if (mstat->dir2nondir)
1078*5c51f124SMoriah Waterland 			if (dir_is_populated(ept->path)) {
1079*5c51f124SMoriah Waterland 				logerr(WRN_INSTVOL_NOTDIR, ept->path);
1080*5c51f124SMoriah Waterland 				warnflag++;
1081*5c51f124SMoriah Waterland 				mstat->denied = 1;	/* install denied! */
1082*5c51f124SMoriah Waterland 				continue;
1083*5c51f124SMoriah Waterland 			} else {	/* Replace is OK. */
1084*5c51f124SMoriah Waterland 				/*
1085*5c51f124SMoriah Waterland 				 * Remove this directory, so it won't
1086*5c51f124SMoriah Waterland 				 * interfere with creation of the new object.
1087*5c51f124SMoriah Waterland 				 */
1088*5c51f124SMoriah Waterland 				if (rmdir(ept->path)) {
1089*5c51f124SMoriah Waterland 					/*
1090*5c51f124SMoriah Waterland 					 * If it didn't work, there's nothing
1091*5c51f124SMoriah Waterland 					 * we can do. To continue would
1092*5c51f124SMoriah Waterland 					 * likely corrupt the filesystem
1093*5c51f124SMoriah Waterland 					 * which is unacceptable.
1094*5c51f124SMoriah Waterland 					 */
1095*5c51f124SMoriah Waterland 					progerr(ERR_RMDIR, ept->path);
1096*5c51f124SMoriah Waterland 					quit(99);
1097*5c51f124SMoriah Waterland 				}
1098*5c51f124SMoriah Waterland 
1099*5c51f124SMoriah Waterland 				repl_permitted = 1;	/* flag it */
1100*5c51f124SMoriah Waterland 			}
1101*5c51f124SMoriah Waterland 
1102*5c51f124SMoriah Waterland 		/* adjust the max volume number appropriately */
1103*5c51f124SMoriah Waterland 
1104*5c51f124SMoriah Waterland 		if (ept->volno > maxvol) {
1105*5c51f124SMoriah Waterland 			maxvol = ept->volno;
1106*5c51f124SMoriah Waterland 		}
1107*5c51f124SMoriah Waterland 
1108*5c51f124SMoriah Waterland 		/* if this part goes into another volume, skip it */
1109*5c51f124SMoriah Waterland 
1110*5c51f124SMoriah Waterland 		if (part != ept->volno) {
1111*5c51f124SMoriah Waterland 			continue;
1112*5c51f124SMoriah Waterland 		}
1113*5c51f124SMoriah Waterland 
1114*5c51f124SMoriah Waterland 		/*
1115*5c51f124SMoriah Waterland 		 * If it's a conflicting file and it's not supposed to be
1116*5c51f124SMoriah Waterland 		 * installed, note it and skip.
1117*5c51f124SMoriah Waterland 		 */
1118*5c51f124SMoriah Waterland 		if (nocnflct && mstat->shared && ept->ftype != 'e') {
1119*5c51f124SMoriah Waterland 			if (mstat->contchg || mstat->attrchg) {
1120*5c51f124SMoriah Waterland 				echo(MSG_SHIGN, ept->path);
1121*5c51f124SMoriah Waterland 			}
1122*5c51f124SMoriah Waterland 			continue;
1123*5c51f124SMoriah Waterland 		}
1124*5c51f124SMoriah Waterland 
1125*5c51f124SMoriah Waterland 		/*
1126*5c51f124SMoriah Waterland 		 * If we want to set uid or gid but user says no, note it.
1127*5c51f124SMoriah Waterland 		 * Remember that the actual mode bits in the structure have
1128*5c51f124SMoriah Waterland 		 * already been adjusted and the mstat flag is telling us
1129*5c51f124SMoriah Waterland 		 * about the original mode.
1130*5c51f124SMoriah Waterland 		 */
1131*5c51f124SMoriah Waterland 		if (nosetuid && (mstat->setuid || mstat->setgid)) {
1132*5c51f124SMoriah Waterland 			msg_ugid = 1;	/* don't repeat attribute message. */
1133*5c51f124SMoriah Waterland 			if (is_fs_writeable(ept->path,
1134*5c51f124SMoriah Waterland 				&(extlist[i]->fsys_value))) {
1135*5c51f124SMoriah Waterland 				if (!(mstat->contchg) && mstat->attrchg) {
1136*5c51f124SMoriah Waterland 					echo(MSG_UGMOD, ept->path);
1137*5c51f124SMoriah Waterland 				} else {
1138*5c51f124SMoriah Waterland 					echo(MSG_UGID, ept->path);
1139*5c51f124SMoriah Waterland 				}
1140*5c51f124SMoriah Waterland 			}
1141*5c51f124SMoriah Waterland 		} else {
1142*5c51f124SMoriah Waterland 			msg_ugid = 0;
1143*5c51f124SMoriah Waterland 		}
1144*5c51f124SMoriah Waterland 
1145*5c51f124SMoriah Waterland 		switch (ept->ftype) {
1146*5c51f124SMoriah Waterland 			case 'l':	/* hard link */
1147*5c51f124SMoriah Waterland 				/* links treated as object "update/skip" */
1148*5c51f124SMoriah Waterland 				stateFlag = B_TRUE;
1149*5c51f124SMoriah Waterland 				continue; /* defer to final proc */
1150*5c51f124SMoriah Waterland 
1151*5c51f124SMoriah Waterland 			case 's': /* for symlink, verify without fix first */
1152*5c51f124SMoriah Waterland 				/* links treated as object "update/skip" */
1153*5c51f124SMoriah Waterland 				stateFlag = B_TRUE;
1154*5c51f124SMoriah Waterland 
1155*5c51f124SMoriah Waterland 				/* Do this only for default verify */
1156*5c51f124SMoriah Waterland 				if (cl_dvfy(myclass) == DEFAULT) {
1157*5c51f124SMoriah Waterland 					if (averify(0, &ept->ftype,
1158*5c51f124SMoriah Waterland 						ept->path, &ept->ainfo))
1159*5c51f124SMoriah Waterland 						echo(MSG_SLINK, ept->path);
1160*5c51f124SMoriah Waterland 				}
1161*5c51f124SMoriah Waterland 
1162*5c51f124SMoriah Waterland 				/*FALLTHRU*/
1163*5c51f124SMoriah Waterland 
1164*5c51f124SMoriah Waterland 			case 'd':	/* directory */
1165*5c51f124SMoriah Waterland 			case 'x':	/* exclusive directory */
1166*5c51f124SMoriah Waterland 			case 'c':	/* character special device */
1167*5c51f124SMoriah Waterland 			case 'b':	/* block special device */
1168*5c51f124SMoriah Waterland 			case 'p':	/* named pipe */
1169*5c51f124SMoriah Waterland 				/* these NOT treated as object "update/skip" */
1170*5c51f124SMoriah Waterland 				stateFlag = B_FALSE;
1171*5c51f124SMoriah Waterland 
1172*5c51f124SMoriah Waterland 				/*
1173*5c51f124SMoriah Waterland 				 * If we can't get to it for legitimate reasons,
1174*5c51f124SMoriah Waterland 				 * don't try to verify it.
1175*5c51f124SMoriah Waterland 				 */
1176*5c51f124SMoriah Waterland 				if ((z_path_is_inherited(ept->path, ept->ftype,
1177*5c51f124SMoriah Waterland 				    get_inst_root())) ||
1178*5c51f124SMoriah Waterland 				    is_remote_fs(ept->path,
1179*5c51f124SMoriah Waterland 				    &(extlist[i]->fsys_value)) &&
1180*5c51f124SMoriah Waterland 				    !is_fs_writeable(ept->path,
1181*5c51f124SMoriah Waterland 				    &(extlist[i]->fsys_value))) {
1182*5c51f124SMoriah Waterland 					mstat->attrchg = 0;
1183*5c51f124SMoriah Waterland 					mstat->contchg = 0;
1184*5c51f124SMoriah Waterland 					break;
1185*5c51f124SMoriah Waterland 				}
1186*5c51f124SMoriah Waterland 
1187*5c51f124SMoriah Waterland 				if (averify(1, &ept->ftype, ept->path,
1188*5c51f124SMoriah Waterland 							&ept->ainfo) == 0) {
1189*5c51f124SMoriah Waterland 					mstat->contchg = mstat->attrchg = 0;
1190*5c51f124SMoriah Waterland 				} else {
1191*5c51f124SMoriah Waterland 					progerr(ERR_CREATE_PKGOBJ, ept->path);
1192*5c51f124SMoriah Waterland 					logerr(getErrbufAddr());
1193*5c51f124SMoriah Waterland 					warnflag++;
1194*5c51f124SMoriah Waterland 				}
1195*5c51f124SMoriah Waterland 
1196*5c51f124SMoriah Waterland 				break;
1197*5c51f124SMoriah Waterland 
1198*5c51f124SMoriah Waterland 			case 'i':	/* information file */
1199*5c51f124SMoriah Waterland 				/* not treated as object "update/skip" */
1200*5c51f124SMoriah Waterland 				stateFlag = B_FALSE;
1201*5c51f124SMoriah Waterland 				break;
1202*5c51f124SMoriah Waterland 
1203*5c51f124SMoriah Waterland 			default:
1204*5c51f124SMoriah Waterland 				/* all files treated as object "update/skip" */
1205*5c51f124SMoriah Waterland 				stateFlag = B_TRUE;
1206*5c51f124SMoriah Waterland 				break;
1207*5c51f124SMoriah Waterland 		}
1208*5c51f124SMoriah Waterland 
1209*5c51f124SMoriah Waterland 		/*
1210*5c51f124SMoriah Waterland 		 * Both contchg and shared flags have to be taken into
1211*5c51f124SMoriah Waterland 		 * account. contchg is set if the file is already present
1212*5c51f124SMoriah Waterland 		 * in the package database, if it does not exist or if it
1213*5c51f124SMoriah Waterland 		 * exists and is modified.
1214*5c51f124SMoriah Waterland 		 * The shared flag is set when 'e' or 'v' file is not
1215*5c51f124SMoriah Waterland 		 * present in the package database, exists and is not
1216*5c51f124SMoriah Waterland 		 * modified. It also has to be checked here.
1217*5c51f124SMoriah Waterland 		 * Shared flag is also set when file is present in package
1218*5c51f124SMoriah Waterland 		 * database and owned by more than one package, but for
1219*5c51f124SMoriah Waterland 		 * this case contchg has already been set.
1220*5c51f124SMoriah Waterland 		 */
1221*5c51f124SMoriah Waterland 		if (mstat->contchg || (mstat->shared &&
1222*5c51f124SMoriah Waterland 		    ((ept->ftype == 'e') || (ept->ftype == 'v')))) {
1223*5c51f124SMoriah Waterland 			*dstp = ept->path;
1224*5c51f124SMoriah Waterland 			if ((ept->ftype == 'f') || (ept->ftype == 'e') ||
1225*5c51f124SMoriah Waterland 				(ept->ftype == 'v')) {
1226*5c51f124SMoriah Waterland 				*srcp = ept->ainfo.local;
1227*5c51f124SMoriah Waterland 				if (is_partial_inst() != 0) {
1228*5c51f124SMoriah Waterland 					if (*srcp[0] == '~') {
1229*5c51f124SMoriah Waterland 						/* translate source pathname */
1230*5c51f124SMoriah Waterland 						*srcp = srcpath(instdir,
1231*5c51f124SMoriah Waterland 							extlist[i]->map_path,
1232*5c51f124SMoriah Waterland 							part, nparts);
1233*5c51f124SMoriah Waterland 					} else {
1234*5c51f124SMoriah Waterland 						*srcp = extlist[i]->map_path;
1235*5c51f124SMoriah Waterland 					}
1236*5c51f124SMoriah Waterland 				} else {
1237*5c51f124SMoriah Waterland 					if (*srcp[0] == '~') {
1238*5c51f124SMoriah Waterland 						/* translate source pathname */
1239*5c51f124SMoriah Waterland 						*srcp = srcpath(instdir,
1240*5c51f124SMoriah Waterland 						    &(ept->ainfo.local[1]),
1241*5c51f124SMoriah Waterland 						    part, nparts);
1242*5c51f124SMoriah Waterland 					}
1243*5c51f124SMoriah Waterland 				}
1244*5c51f124SMoriah Waterland 
1245*5c51f124SMoriah Waterland 				echoDebug(DBG_DOMERG_NO_SUCH_FILE,
1246*5c51f124SMoriah Waterland 					ept->ftype, cl_nam(ept->pkg_class_idx),
1247*5c51f124SMoriah Waterland 					ept->path);
1248*5c51f124SMoriah Waterland 			} else {
1249*5c51f124SMoriah Waterland 				/*
1250*5c51f124SMoriah Waterland 				 * At this point, we're returning a non-file
1251*5c51f124SMoriah Waterland 				 * that couldn't be created in the standard
1252*5c51f124SMoriah Waterland 				 * way. If it refers to a filesystem that is
1253*5c51f124SMoriah Waterland 				 * not writeable by us, don't waste the
1254*5c51f124SMoriah Waterland 				 * calling process's time.
1255*5c51f124SMoriah Waterland 				 */
1256*5c51f124SMoriah Waterland 				if (!is_fs_writeable(ept->path,
1257*5c51f124SMoriah Waterland 					&(extlist[i]->fsys_value))) {
1258*5c51f124SMoriah Waterland 					echoDebug(DBG_DOMERG_NOT_WRITABLE,
1259*5c51f124SMoriah Waterland 						ept->ftype,
1260*5c51f124SMoriah Waterland 						cl_nam(ept->pkg_class_idx),
1261*5c51f124SMoriah Waterland 						ept->path);
1262*5c51f124SMoriah Waterland 					continue;
1263*5c51f124SMoriah Waterland 				}
1264*5c51f124SMoriah Waterland 
1265*5c51f124SMoriah Waterland 				*srcp = NULL;
1266*5c51f124SMoriah Waterland 				echoDebug(DBG_DOMERG_NOT_THERE,
1267*5c51f124SMoriah Waterland 					ept->ftype, cl_nam(ept->pkg_class_idx),
1268*5c51f124SMoriah Waterland 					ept->path);
1269*5c51f124SMoriah Waterland 			}
1270*5c51f124SMoriah Waterland 
1271*5c51f124SMoriah Waterland 			svindx = i+1;
1272*5c51f124SMoriah Waterland 			backup(*dstp, 1);
1273*5c51f124SMoriah Waterland 			return (i);
1274*5c51f124SMoriah Waterland 		}
1275*5c51f124SMoriah Waterland 
1276*5c51f124SMoriah Waterland 		if (mstat->attrchg) {
1277*5c51f124SMoriah Waterland 			backup(ept->path, 0);
1278*5c51f124SMoriah Waterland 			if (!msg_ugid)
1279*5c51f124SMoriah Waterland 				echo(MSG_ATTRIB, ept->path);
1280*5c51f124SMoriah Waterland 
1281*5c51f124SMoriah Waterland 			/* fix the attributes now for robustness sake */
1282*5c51f124SMoriah Waterland 			if (averify(1, &ept->ftype,
1283*5c51f124SMoriah Waterland 				ept->path,
1284*5c51f124SMoriah Waterland 				&ept->ainfo) == 0) {
1285*5c51f124SMoriah Waterland 				mstat->attrchg = 0;
1286*5c51f124SMoriah Waterland 			}
1287*5c51f124SMoriah Waterland 		}
1288*5c51f124SMoriah Waterland 
1289*5c51f124SMoriah Waterland 		/*
1290*5c51f124SMoriah Waterland 		 * package object exists, or does not need updating: if the path
1291*5c51f124SMoriah Waterland 		 * is in an area inherited from the global zone, then treat
1292*5c51f124SMoriah Waterland 		 * the object as if it were "skipped" - if the path is not in an
1293*5c51f124SMoriah Waterland 		 * area inherited from the global zone, then treat the object as
1294*5c51f124SMoriah Waterland 		 * if it were "updated"
1295*5c51f124SMoriah Waterland 		 */
1296*5c51f124SMoriah Waterland 
1297*5c51f124SMoriah Waterland 		/* LINTED warning: statement has no consequent: if */
1298*5c51f124SMoriah Waterland 		if ((stateFlag == B_FALSE) || (ept == (struct cfent *)NULL)) {
1299*5c51f124SMoriah Waterland 			/*
1300*5c51f124SMoriah Waterland 			 * the object in question is a directory or special
1301*5c51f124SMoriah Waterland 			 * file - the fact that this type of object already
1302*5c51f124SMoriah Waterland 			 * exists or does not need updating must not trigger
1303*5c51f124SMoriah Waterland 			 * the object updated/object skipped indication -
1304*5c51f124SMoriah Waterland 			 * that would cause class action scripts to be run
1305*5c51f124SMoriah Waterland 			 * when installing a new non-global zone - that action
1306*5c51f124SMoriah Waterland 			 * must only be done when a file object that is in
1307*5c51f124SMoriah Waterland 			 * an area inherited from the global zone is present.
1308*5c51f124SMoriah Waterland 			 */
1309*5c51f124SMoriah Waterland 		} else if (z_path_is_inherited(ept->path, ept->ftype,
1310*5c51f124SMoriah Waterland 						get_inst_root()) == B_TRUE) {
1311*5c51f124SMoriah Waterland 			if (r_skipped != (char **)NULL) {
1312*5c51f124SMoriah Waterland 				if (*r_skipped == (char *)NULL) {
1313*5c51f124SMoriah Waterland 					echoDebug(DBG_INSTVOL_OBJ_SKIPPED,
1314*5c51f124SMoriah Waterland 								ept->path);
1315*5c51f124SMoriah Waterland 					*r_skipped = ept->path;
1316*5c51f124SMoriah Waterland 				}
1317*5c51f124SMoriah Waterland 			}
1318*5c51f124SMoriah Waterland 		} else {
1319*5c51f124SMoriah Waterland 			if (r_updated != (char **)NULL) {
1320*5c51f124SMoriah Waterland 				if (*r_updated == (char *)NULL) {
1321*5c51f124SMoriah Waterland 					echoDebug(DBG_INSTVOL_OBJ_UPDATED,
1322*5c51f124SMoriah Waterland 								ept->path);
1323*5c51f124SMoriah Waterland 				}
1324*5c51f124SMoriah Waterland 				*r_updated = ept->path;
1325*5c51f124SMoriah Waterland 			}
1326*5c51f124SMoriah Waterland 		}
1327*5c51f124SMoriah Waterland 	}
1328*5c51f124SMoriah Waterland 
1329*5c51f124SMoriah Waterland 	if (maxvol == part) {
1330*5c51f124SMoriah Waterland 		eocflag++;	/* endofclass */
1331*5c51f124SMoriah Waterland 	}
1332*5c51f124SMoriah Waterland 
1333*5c51f124SMoriah Waterland 	return (DMRG_DONE);	/* no remaining entries on this volume */
1334*5c51f124SMoriah Waterland }
1335*5c51f124SMoriah Waterland 
1336*5c51f124SMoriah Waterland /*
1337*5c51f124SMoriah Waterland  * Determine if the provided directory is populated. Return 0 if so and 1 if
1338*5c51f124SMoriah Waterland  * not. This also returns 0 if the dirpath is not a directory or if it does
1339*5c51f124SMoriah Waterland  * not exist.
1340*5c51f124SMoriah Waterland  */
1341*5c51f124SMoriah Waterland static int
1342*5c51f124SMoriah Waterland dir_is_populated(char *dirpath) {
1343*5c51f124SMoriah Waterland 	DIR	*dirfp;
1344*5c51f124SMoriah Waterland 	struct	dirent *drp;
1345*5c51f124SMoriah Waterland 	int	retcode = 0;
1346*5c51f124SMoriah Waterland 
1347*5c51f124SMoriah Waterland 	if ((dirfp = opendir(dirpath)) != NULL) {
1348*5c51f124SMoriah Waterland 		while ((drp = readdir(dirfp)) != NULL) {
1349*5c51f124SMoriah Waterland 			if (strcmp(drp->d_name, ".") == 0) {
1350*5c51f124SMoriah Waterland 				continue;
1351*5c51f124SMoriah Waterland 			}
1352*5c51f124SMoriah Waterland 			if (strcmp(drp->d_name, "..") == 0) {
1353*5c51f124SMoriah Waterland 				continue;
1354*5c51f124SMoriah Waterland 			}
1355*5c51f124SMoriah Waterland 			/*
1356*5c51f124SMoriah Waterland 			 * If we get here, there's a real file in the
1357*5c51f124SMoriah Waterland 			 * directory
1358*5c51f124SMoriah Waterland 			 */
1359*5c51f124SMoriah Waterland 			retcode = 1;
1360*5c51f124SMoriah Waterland 			break;
1361*5c51f124SMoriah Waterland 		}
1362*5c51f124SMoriah Waterland 		(void) closedir(dirfp);
1363*5c51f124SMoriah Waterland 	}
1364*5c51f124SMoriah Waterland 
1365*5c51f124SMoriah Waterland 	return (retcode);
1366*5c51f124SMoriah Waterland }
1367*5c51f124SMoriah Waterland 
1368*5c51f124SMoriah Waterland /*
1369*5c51f124SMoriah Waterland  * This is the function that cleans up the installation of this class.
1370*5c51f124SMoriah Waterland  * This is where hard links get put in since the stuff they're linking
1371*5c51f124SMoriah Waterland  * probably exists by now.
1372*5c51f124SMoriah Waterland  */
1373*5c51f124SMoriah Waterland static void
1374*5c51f124SMoriah Waterland endofclass(struct cfextra **extlist, int myclass, int ckflag,
1375*5c51f124SMoriah Waterland 	VFP_T **a_cfVfp, VFP_T **a_cfTmpVfp)
1376*5c51f124SMoriah Waterland {
1377*5c51f124SMoriah Waterland 	char		*temppath;
1378*5c51f124SMoriah Waterland 	char 		*pspool_loc;
1379*5c51f124SMoriah Waterland 	char 		*relocpath = (char *)NULL;
1380*5c51f124SMoriah Waterland 	char 		scrpt_dst[PATH_MAX];
1381*5c51f124SMoriah Waterland 	int		flag;
1382*5c51f124SMoriah Waterland 	int		idx;
1383*5c51f124SMoriah Waterland 	int		n;
1384*5c51f124SMoriah Waterland 	struct cfent	*ept;	/* entry from the internal list */
1385*5c51f124SMoriah Waterland 	struct cfextra	entry;	/* entry from the package database */
1386*5c51f124SMoriah Waterland 	struct mergstat	*mstat;	/* merge status */
1387*5c51f124SMoriah Waterland 	struct pinfo	*pinfo;
1388*5c51f124SMoriah Waterland 
1389*5c51f124SMoriah Waterland 	/* open the package database (contents) file */
1390*5c51f124SMoriah Waterland 
1391*5c51f124SMoriah Waterland 	if (!ocfile(a_cfVfp, a_cfTmpVfp, pkgmap_blks)) {
1392*5c51f124SMoriah Waterland 		quit(99);
1393*5c51f124SMoriah Waterland 	}
1394*5c51f124SMoriah Waterland 
1395*5c51f124SMoriah Waterland 	echo(MSG_VERIFYING_CLASS, cl_nam(myclass));
1396*5c51f124SMoriah Waterland 
1397*5c51f124SMoriah Waterland 	for (idx = 0; /* void */; idx++) {
1398*5c51f124SMoriah Waterland 		/* find next package object in this class */
1399*5c51f124SMoriah Waterland 		while (extlist[idx]) {
1400*5c51f124SMoriah Waterland 			if ((extlist[idx]->cf_ent.ftype != 'i') &&
1401*5c51f124SMoriah Waterland 				extlist[idx]->cf_ent.pkg_class_idx == myclass) {
1402*5c51f124SMoriah Waterland 				break;
1403*5c51f124SMoriah Waterland 			}
1404*5c51f124SMoriah Waterland 			idx++;
1405*5c51f124SMoriah Waterland 		}
1406*5c51f124SMoriah Waterland 
1407*5c51f124SMoriah Waterland 		if (extlist[idx] == NULL) {
1408*5c51f124SMoriah Waterland 			/* finish copying contents file and exit loop */
1409*5c51f124SMoriah Waterland 			(void) srchcfile(&(entry.cf_ent), NULL,
1410*5c51f124SMoriah Waterland 					*a_cfVfp, *a_cfTmpVfp);
1411*5c51f124SMoriah Waterland 			break;
1412*5c51f124SMoriah Waterland 		}
1413*5c51f124SMoriah Waterland 
1414*5c51f124SMoriah Waterland 		ept = &(extlist[idx]->cf_ent);
1415*5c51f124SMoriah Waterland 		mstat = &(extlist[idx]->mstat);
1416*5c51f124SMoriah Waterland 
1417*5c51f124SMoriah Waterland 		temppath =
1418*5c51f124SMoriah Waterland 			extlist[idx] ? extlist[idx]->client_path :
1419*5c51f124SMoriah Waterland 			NULL;
1420*5c51f124SMoriah Waterland 
1421*5c51f124SMoriah Waterland 		/*
1422*5c51f124SMoriah Waterland 		 * At this point  the only difference between the entry
1423*5c51f124SMoriah Waterland 		 * in the contents file and the entry in extlist[] is
1424*5c51f124SMoriah Waterland 		 * that the status indicator contains CONFIRM_CONT.
1425*5c51f124SMoriah Waterland 		 * So for the new DB we use this knowledge and just
1426*5c51f124SMoriah Waterland 		 * verify everything in accordance with extlist without
1427*5c51f124SMoriah Waterland 		 * trying to retrieve the entry from the DB.
1428*5c51f124SMoriah Waterland 		 */
1429*5c51f124SMoriah Waterland 
1430*5c51f124SMoriah Waterland 		n = srchcfile(&(entry.cf_ent),
1431*5c51f124SMoriah Waterland 			(ept ? temppath : NULL), *a_cfVfp, *a_cfTmpVfp);
1432*5c51f124SMoriah Waterland 
1433*5c51f124SMoriah Waterland 		if (n == 0) {
1434*5c51f124SMoriah Waterland 			break;
1435*5c51f124SMoriah Waterland 		} else if (n < 0) {
1436*5c51f124SMoriah Waterland 			char	*errstr = getErrstr();
1437*5c51f124SMoriah Waterland 			progerr(ERR_CFBAD);
1438*5c51f124SMoriah Waterland 			logerr(gettext("pathname=%s\n"),
1439*5c51f124SMoriah Waterland 				entry.cf_ent.path && *entry.cf_ent.path ?
1440*5c51f124SMoriah Waterland 				entry.cf_ent.path : "Unknown");
1441*5c51f124SMoriah Waterland 			logerr(gettext("problem=%s\n"),
1442*5c51f124SMoriah Waterland 				(errstr && *errstr) ? errstr : "Unknown");
1443*5c51f124SMoriah Waterland 			quit(99);
1444*5c51f124SMoriah Waterland 		} else if (n != 1) {
1445*5c51f124SMoriah Waterland 			/*
1446*5c51f124SMoriah Waterland 			 * Check if path should be in the package
1447*5c51f124SMoriah Waterland 			 * database.
1448*5c51f124SMoriah Waterland 			 */
1449*5c51f124SMoriah Waterland 			if ((mstat->shared && nocnflct)) {
1450*5c51f124SMoriah Waterland 				continue;
1451*5c51f124SMoriah Waterland 			}
1452*5c51f124SMoriah Waterland 			progerr(ERR_CFMISSING, ept->path);
1453*5c51f124SMoriah Waterland 			quit(99);
1454*5c51f124SMoriah Waterland 		}
1455*5c51f124SMoriah Waterland 
1456*5c51f124SMoriah Waterland 		/*
1457*5c51f124SMoriah Waterland 		 * If merge was not appropriate for this object, now is the
1458*5c51f124SMoriah Waterland 		 * time to choose one or the other.
1459*5c51f124SMoriah Waterland 		 */
1460*5c51f124SMoriah Waterland 		if (mstat->denied) {
1461*5c51f124SMoriah Waterland 			/*
1462*5c51f124SMoriah Waterland 			 * If installation was denied AFTER the package
1463*5c51f124SMoriah Waterland 			 * database was updated, skip this. We've already
1464*5c51f124SMoriah Waterland 			 * announced the discrepancy and the verifications
1465*5c51f124SMoriah Waterland 			 * that follow will make faulty decisions based on
1466*5c51f124SMoriah Waterland 			 * the ftype, which may not be correct.
1467*5c51f124SMoriah Waterland 			 */
1468*5c51f124SMoriah Waterland 			progerr(ERR_COULD_NOT_INSTALL, ept->path);
1469*5c51f124SMoriah Waterland 			warnflag++;
1470*5c51f124SMoriah Waterland 		} else {
1471*5c51f124SMoriah Waterland 			if (mstat->replace)
1472*5c51f124SMoriah Waterland 				/*
1473*5c51f124SMoriah Waterland 				 * This replaces the old entry with the new
1474*5c51f124SMoriah Waterland 				 * one. This should never happen in the new
1475*5c51f124SMoriah Waterland 				 * DB since the entries are already identical.
1476*5c51f124SMoriah Waterland 				 */
1477*5c51f124SMoriah Waterland 				repl_cfent(ept, &(entry.cf_ent));
1478*5c51f124SMoriah Waterland 
1479*5c51f124SMoriah Waterland 			/*
1480*5c51f124SMoriah Waterland 			 * Validate this entry and change the status flag in
1481*5c51f124SMoriah Waterland 			 * the package database.
1482*5c51f124SMoriah Waterland 			 */
1483*5c51f124SMoriah Waterland 			if (ept->ftype == RM_RDY) {
1484*5c51f124SMoriah Waterland 				(void) eptstat(&(entry.cf_ent), pkginst,
1485*5c51f124SMoriah Waterland 					STAT_NEXT);
1486*5c51f124SMoriah Waterland 			} else {
1487*5c51f124SMoriah Waterland 				/* check the hard link now. */
1488*5c51f124SMoriah Waterland 				if (ept->ftype == 'l') {
1489*5c51f124SMoriah Waterland 					if (averify(0, &ept->ftype,
1490*5c51f124SMoriah Waterland 						ept->path, &ept->ainfo)) {
1491*5c51f124SMoriah Waterland 						echo(MSG_HRDLINK,
1492*5c51f124SMoriah Waterland 							ept->path);
1493*5c51f124SMoriah Waterland 						mstat->attrchg++;
1494*5c51f124SMoriah Waterland 					}
1495*5c51f124SMoriah Waterland 				}
1496*5c51f124SMoriah Waterland 
1497*5c51f124SMoriah Waterland 				/*
1498*5c51f124SMoriah Waterland 				 * Don't install or verify objects for
1499*5c51f124SMoriah Waterland 				 * remote, read-only filesystems.  We need
1500*5c51f124SMoriah Waterland 				 * only flag them as shared from some server.
1501*5c51f124SMoriah Waterland 				 * Otherwise, ok to do final check.
1502*5c51f124SMoriah Waterland 				 */
1503*5c51f124SMoriah Waterland 				if (is_remote_fs(ept->path,
1504*5c51f124SMoriah Waterland 					&(extlist[idx]->fsys_value)) &&
1505*5c51f124SMoriah Waterland 					!is_fs_writeable(ept->path,
1506*5c51f124SMoriah Waterland 					&(extlist[idx]->fsys_value))) {
1507*5c51f124SMoriah Waterland 					flag = -1;
1508*5c51f124SMoriah Waterland 				} else {
1509*5c51f124SMoriah Waterland 					boolean_t inheritedFlag;
1510*5c51f124SMoriah Waterland 					inheritedFlag =
1511*5c51f124SMoriah Waterland 					    z_path_is_inherited(ept->path,
1512*5c51f124SMoriah Waterland 						ept->ftype, get_inst_root());
1513*5c51f124SMoriah Waterland 					flag = finalck(ept, mstat->attrchg,
1514*5c51f124SMoriah Waterland 						(ckflag ? mstat->contchg :
1515*5c51f124SMoriah Waterland 						(-1)), inheritedFlag);
1516*5c51f124SMoriah Waterland 				}
1517*5c51f124SMoriah Waterland 
1518*5c51f124SMoriah Waterland 				pinfo = entry.cf_ent.pinfo;
1519*5c51f124SMoriah Waterland 
1520*5c51f124SMoriah Waterland 				/* Find this package in the list. */
1521*5c51f124SMoriah Waterland 				while (pinfo) {
1522*5c51f124SMoriah Waterland 					if (strcmp(pkginst, pinfo->pkg) == 0) {
1523*5c51f124SMoriah Waterland 						break;
1524*5c51f124SMoriah Waterland 					}
1525*5c51f124SMoriah Waterland 					pinfo = pinfo->next;
1526*5c51f124SMoriah Waterland 				}
1527*5c51f124SMoriah Waterland 
1528*5c51f124SMoriah Waterland 				/*
1529*5c51f124SMoriah Waterland 				 * If this package owns this file, then store
1530*5c51f124SMoriah Waterland 				 * it in the database with the appropriate
1531*5c51f124SMoriah Waterland 				 * status. Need to check pinfo in case it
1532*5c51f124SMoriah Waterland 				 * points to NULL which could happen if
1533*5c51f124SMoriah Waterland 				 * pinfo->next = NULL above.
1534*5c51f124SMoriah Waterland 				 */
1535*5c51f124SMoriah Waterland 				if (pinfo) {
1536*5c51f124SMoriah Waterland 					if (flag < 0 || is_served(ept->path,
1537*5c51f124SMoriah Waterland 						&(extlist[idx]->fsys_value))) {
1538*5c51f124SMoriah Waterland 						/*
1539*5c51f124SMoriah Waterland 						 * This is provided to
1540*5c51f124SMoriah Waterland 						 * clients by a server.
1541*5c51f124SMoriah Waterland 						 */
1542*5c51f124SMoriah Waterland 						pinfo->status = SERVED_FILE;
1543*5c51f124SMoriah Waterland 					} else {
1544*5c51f124SMoriah Waterland 						/*
1545*5c51f124SMoriah Waterland 						 * It's either there or it's
1546*5c51f124SMoriah Waterland 						 * not.
1547*5c51f124SMoriah Waterland 						 */
1548*5c51f124SMoriah Waterland 						pinfo->status = (flag ?
1549*5c51f124SMoriah Waterland 							NOT_FND : ENTRY_OK);
1550*5c51f124SMoriah Waterland 					}
1551*5c51f124SMoriah Waterland 				}
1552*5c51f124SMoriah Waterland 			}
1553*5c51f124SMoriah Waterland 		}
1554*5c51f124SMoriah Waterland 
1555*5c51f124SMoriah Waterland 		/*
1556*5c51f124SMoriah Waterland 		 * If not installing from a partially spooled package, the
1557*5c51f124SMoriah Waterland 		 * "save/pspool" area, and the file contents can be
1558*5c51f124SMoriah Waterland 		 * changed (type is 'e' or 'v'), and the class IS "none":
1559*5c51f124SMoriah Waterland 		 * copy the installed volatile file into the appropriate
1560*5c51f124SMoriah Waterland 		 * location in the packages destination "save/pspool" area.
1561*5c51f124SMoriah Waterland 		 */
1562*5c51f124SMoriah Waterland 
1563*5c51f124SMoriah Waterland 		if ((!is_partial_inst()) &&
1564*5c51f124SMoriah Waterland 			((ept->ftype == 'e') || (ept->ftype == 'v')) &&
1565*5c51f124SMoriah Waterland 			(strcmp(ept->pkg_class, "none") == 0)) {
1566*5c51f124SMoriah Waterland 
1567*5c51f124SMoriah Waterland 			if (absolutepath(extlist[idx]->map_path) == B_TRUE &&
1568*5c51f124SMoriah Waterland 				parametricpath(extlist[idx]->cf_ent.ainfo.local,
1569*5c51f124SMoriah Waterland 					&relocpath) == B_FALSE) {
1570*5c51f124SMoriah Waterland 				pspool_loc = ROOT;
1571*5c51f124SMoriah Waterland 			} else {
1572*5c51f124SMoriah Waterland 				pspool_loc = RELOC;
1573*5c51f124SMoriah Waterland 			}
1574*5c51f124SMoriah Waterland 
1575*5c51f124SMoriah Waterland 			n = snprintf(scrpt_dst, PATH_MAX, "%s/%s/%s",
1576*5c51f124SMoriah Waterland 				saveSpoolInstallDir, pspool_loc,
1577*5c51f124SMoriah Waterland 				relocpath ? relocpath : extlist[idx]->map_path);
1578*5c51f124SMoriah Waterland 
1579*5c51f124SMoriah Waterland 			if (n >= PATH_MAX) {
1580*5c51f124SMoriah Waterland 				progerr(ERR_CREATE_PATH_2,
1581*5c51f124SMoriah Waterland 					saveSpoolInstallDir,
1582*5c51f124SMoriah Waterland 					extlist[idx]->map_path);
1583*5c51f124SMoriah Waterland 				quit(99);
1584*5c51f124SMoriah Waterland 			}
1585*5c51f124SMoriah Waterland 
1586*5c51f124SMoriah Waterland 			/* copy, preserve source file mode */
1587*5c51f124SMoriah Waterland 
1588*5c51f124SMoriah Waterland 			if (cppath(MODE_SRC, ept->path, scrpt_dst, 0644)) {
1589*5c51f124SMoriah Waterland 				warnflag++;
1590*5c51f124SMoriah Waterland 			}
1591*5c51f124SMoriah Waterland 		}
1592*5c51f124SMoriah Waterland 
1593*5c51f124SMoriah Waterland 		/*
1594*5c51f124SMoriah Waterland 		 * Now insert this potentially changed package database
1595*5c51f124SMoriah Waterland 		 * entry.
1596*5c51f124SMoriah Waterland 		 */
1597*5c51f124SMoriah Waterland 		if (entry.cf_ent.npkgs) {
1598*5c51f124SMoriah Waterland 			if (putcvfpfile(&(entry.cf_ent), *a_cfTmpVfp)) {
1599*5c51f124SMoriah Waterland 				quit(99);
1600*5c51f124SMoriah Waterland 			}
1601*5c51f124SMoriah Waterland 		}
1602*5c51f124SMoriah Waterland 	}
1603*5c51f124SMoriah Waterland 
1604*5c51f124SMoriah Waterland 	n = swapcfile(a_cfVfp, a_cfTmpVfp, pkginst, dbchg);
1605*5c51f124SMoriah Waterland 	if (n == RESULT_WRN) {
1606*5c51f124SMoriah Waterland 		warnflag++;
1607*5c51f124SMoriah Waterland 	} else if (n == RESULT_ERR) {
1608*5c51f124SMoriah Waterland 		quit(99);
1609*5c51f124SMoriah Waterland 	}
1610*5c51f124SMoriah Waterland }
1611*5c51f124SMoriah Waterland 
1612*5c51f124SMoriah Waterland /*
1613*5c51f124SMoriah Waterland  * This function goes through and fixes all the attributes. This is called
1614*5c51f124SMoriah Waterland  * out by using DST_QKVERIFY=this_class in the pkginfo file. The primary
1615*5c51f124SMoriah Waterland  * use for this is to fix up files installed by a class action script
1616*5c51f124SMoriah Waterland  * which is time-critical and reliable enough to assume likely success.
1617*5c51f124SMoriah Waterland  * The first such format was for WOS compressed-cpio'd file sets.
1618*5c51f124SMoriah Waterland  * The second format is the Class Archive Format.
1619*5c51f124SMoriah Waterland  */
1620*5c51f124SMoriah Waterland static int
1621*5c51f124SMoriah Waterland fix_attributes(struct cfextra **extlist, int idx)
1622*5c51f124SMoriah Waterland {
1623*5c51f124SMoriah Waterland 	struct	cfextra *ext;
1624*5c51f124SMoriah Waterland 	int	i, retval = 1;
1625*5c51f124SMoriah Waterland 	int 	nc = cl_getn();
1626*5c51f124SMoriah Waterland 	int	n;
1627*5c51f124SMoriah Waterland 	struct cfent *ept;
1628*5c51f124SMoriah Waterland 	struct mergstat *mstat;
1629*5c51f124SMoriah Waterland 	char scrpt_dst[PATH_MAX];
1630*5c51f124SMoriah Waterland 	char *pspool_loc;
1631*5c51f124SMoriah Waterland 	char *relocpath = (char *)NULL;
1632*5c51f124SMoriah Waterland 
1633*5c51f124SMoriah Waterland 	for (i = 0; extlist[i]; i++) {
1634*5c51f124SMoriah Waterland 		ext = extlist[i];
1635*5c51f124SMoriah Waterland 		ept = &(extlist[i]->cf_ent);
1636*5c51f124SMoriah Waterland 		mstat = &(extlist[i]->mstat);
1637*5c51f124SMoriah Waterland 
1638*5c51f124SMoriah Waterland 		/*
1639*5c51f124SMoriah Waterland 		 * We don't care about 'i'nfo files because, they
1640*5c51f124SMoriah Waterland 		 * aren't laid down, 'e'ditable files can change
1641*5c51f124SMoriah Waterland 		 * anyway, so who cares and 's'ymlinks were already
1642*5c51f124SMoriah Waterland 		 * fixed in domerg(); however, certain old WOS
1643*5c51f124SMoriah Waterland 		 * package symlinks depend on a bug in the old
1644*5c51f124SMoriah Waterland 		 * pkgadd which has recently been expunged. For
1645*5c51f124SMoriah Waterland 		 * those packages in 2.2, we repeat the verification
1646*5c51f124SMoriah Waterland 		 * of symlinks.
1647*5c51f124SMoriah Waterland 		 *
1648*5c51f124SMoriah Waterland 		 * By 2.6 or so, ftype == 's' should be added to this.
1649*5c51f124SMoriah Waterland 		 */
1650*5c51f124SMoriah Waterland 		if (ept->ftype == 'i' || ept->ftype == 'e' ||
1651*5c51f124SMoriah Waterland 			(mstat->shared && nocnflct))
1652*5c51f124SMoriah Waterland 			continue;
1653*5c51f124SMoriah Waterland 
1654*5c51f124SMoriah Waterland 		if (mstat->denied) {
1655*5c51f124SMoriah Waterland 			progerr(ERR_COULD_NOT_INSTALL, ept->path);
1656*5c51f124SMoriah Waterland 			warnflag++;
1657*5c51f124SMoriah Waterland 			continue;
1658*5c51f124SMoriah Waterland 		}
1659*5c51f124SMoriah Waterland 
1660*5c51f124SMoriah Waterland 		if (ept->pkg_class_idx < 0 || ept->pkg_class_idx > nc) {
1661*5c51f124SMoriah Waterland 			progerr(ERR_CLIDX, ept->pkg_class_idx,
1662*5c51f124SMoriah Waterland 			    (ept->path && *ept->path) ? ept->path : "unknown");
1663*5c51f124SMoriah Waterland 			continue;
1664*5c51f124SMoriah Waterland 		}
1665*5c51f124SMoriah Waterland 
1666*5c51f124SMoriah Waterland 		/* If this is the right class, do the fast verify. */
1667*5c51f124SMoriah Waterland 		if (ept->pkg_class_idx == idx) {
1668*5c51f124SMoriah Waterland 			if (fverify(1, &ept->ftype, ept->path,
1669*5c51f124SMoriah Waterland 				&ept->ainfo, &ept->cinfo) == 0) {
1670*5c51f124SMoriah Waterland 				mstat->attrchg = 0;
1671*5c51f124SMoriah Waterland 				mstat->contchg =  0;
1672*5c51f124SMoriah Waterland 			} else	/* We'll try full verify later */
1673*5c51f124SMoriah Waterland 				retval = 0;
1674*5c51f124SMoriah Waterland 		}
1675*5c51f124SMoriah Waterland 		/*
1676*5c51f124SMoriah Waterland 		 * Need to copy the installed volitale file back to the
1677*5c51f124SMoriah Waterland 		 * partial spooled area if we are installing to a local zone
1678*5c51f124SMoriah Waterland 		 * or similar installation method.
1679*5c51f124SMoriah Waterland 		 */
1680*5c51f124SMoriah Waterland 
1681*5c51f124SMoriah Waterland 		if ((!is_partial_inst()) &&
1682*5c51f124SMoriah Waterland 			((ept->ftype == 'e') || (ept->ftype == 'v')) &&
1683*5c51f124SMoriah Waterland 			(strcmp(ept->pkg_class, "none") == 0)) {
1684*5c51f124SMoriah Waterland 
1685*5c51f124SMoriah Waterland 			if (absolutepath(ext->map_path) == B_TRUE &&
1686*5c51f124SMoriah Waterland 				parametricpath(ext->cf_ent.ainfo.local,
1687*5c51f124SMoriah Waterland 					&relocpath) == B_FALSE) {
1688*5c51f124SMoriah Waterland 				pspool_loc = ROOT;
1689*5c51f124SMoriah Waterland 			} else {
1690*5c51f124SMoriah Waterland 				pspool_loc = RELOC;
1691*5c51f124SMoriah Waterland 			}
1692*5c51f124SMoriah Waterland 
1693*5c51f124SMoriah Waterland 			n = snprintf(scrpt_dst, PATH_MAX, "%s/%s/%s",
1694*5c51f124SMoriah Waterland 				saveSpoolInstallDir, pspool_loc,
1695*5c51f124SMoriah Waterland 				relocpath ? relocpath : ext->map_path);
1696*5c51f124SMoriah Waterland 
1697*5c51f124SMoriah Waterland 			if (n >= PATH_MAX) {
1698*5c51f124SMoriah Waterland 				progerr(ERR_CREATE_PATH_2,
1699*5c51f124SMoriah Waterland 					saveSpoolInstallDir,
1700*5c51f124SMoriah Waterland 					ext->map_path);
1701*5c51f124SMoriah Waterland 				quit(99);
1702*5c51f124SMoriah Waterland 			}
1703*5c51f124SMoriah Waterland 
1704*5c51f124SMoriah Waterland 			/* copy, preserve source file mode */
1705*5c51f124SMoriah Waterland 
1706*5c51f124SMoriah Waterland 			if (cppath(MODE_SRC, ept->path, scrpt_dst, 0644)) {
1707*5c51f124SMoriah Waterland 				warnflag++;
1708*5c51f124SMoriah Waterland 			}
1709*5c51f124SMoriah Waterland 		}
1710*5c51f124SMoriah Waterland 	}
1711*5c51f124SMoriah Waterland 
1712*5c51f124SMoriah Waterland 	return (retval);
1713*5c51f124SMoriah Waterland }
1714*5c51f124SMoriah Waterland 
1715*5c51f124SMoriah Waterland /*
1716*5c51f124SMoriah Waterland  * Check to see if first charcter in path is a '/'.
1717*5c51f124SMoriah Waterland  *
1718*5c51f124SMoriah Waterland  * Return:
1719*5c51f124SMoriah Waterland  * 			B_TRUE - if path is prepended with '/'
1720*5c51f124SMoriah Waterland  * 			B_FALSE - if not
1721*5c51f124SMoriah Waterland  */
1722*5c51f124SMoriah Waterland static boolean_t
1723*5c51f124SMoriah Waterland absolutepath(char *path)
1724*5c51f124SMoriah Waterland {
1725*5c51f124SMoriah Waterland 	assert(path != NULL);
1726*5c51f124SMoriah Waterland 	assert(path[0] != '\0');
1727*5c51f124SMoriah Waterland 
1728*5c51f124SMoriah Waterland 	return (path[0] == '/' ? B_TRUE : B_FALSE);
1729*5c51f124SMoriah Waterland }
1730*5c51f124SMoriah Waterland 
1731*5c51f124SMoriah Waterland /*
1732*5c51f124SMoriah Waterland  * Check to see if path contains a '$' which makes it
1733*5c51f124SMoriah Waterland  * a parametric path and therefore relocatable.
1734*5c51f124SMoriah Waterland  *
1735*5c51f124SMoriah Waterland  * Parameters:
1736*5c51f124SMoriah Waterland  *             path - The path to determine if it is absolute
1737*5c51f124SMoriah Waterland  *             relocpath - The value of the unconditioned path
1738*5c51f124SMoriah Waterland  *                         i.e. $OPTDIR/usr/ls
1739*5c51f124SMoriah Waterland  * Return:
1740*5c51f124SMoriah Waterland  * 			B_TRUE - if path is a parametric path
1741*5c51f124SMoriah Waterland  * 			B_FALSE - if not
1742*5c51f124SMoriah Waterland  */
1743*5c51f124SMoriah Waterland static boolean_t
1744*5c51f124SMoriah Waterland parametricpath(char *path, char **relocpath)
1745*5c51f124SMoriah Waterland {
1746*5c51f124SMoriah Waterland 	assert(path != NULL);
1747*5c51f124SMoriah Waterland 	assert(path[0] != '\0');
1748*5c51f124SMoriah Waterland 
1749*5c51f124SMoriah Waterland 	/*
1750*5c51f124SMoriah Waterland 	 * If this is a valid parametric path then a '$' MUST occur at the
1751*5c51f124SMoriah Waterland 	 * first or second character.
1752*5c51f124SMoriah Waterland 	 */
1753*5c51f124SMoriah Waterland 
1754*5c51f124SMoriah Waterland 	if (path[0] == '$' || path[1] == '$') {
1755*5c51f124SMoriah Waterland 		/*
1756*5c51f124SMoriah Waterland 		 * If a parametric path exists then when copying the
1757*5c51f124SMoriah Waterland 		 * path to the pspool directoy from the installing
1758*5c51f124SMoriah Waterland 		 * pkgs reloc directory we want to use the uncononditional
1759*5c51f124SMoriah Waterland 		 * varaiable path.
1760*5c51f124SMoriah Waterland 		 */
1761*5c51f124SMoriah Waterland 		*relocpath = (path + 1);
1762*5c51f124SMoriah Waterland 		return (B_TRUE);
1763*5c51f124SMoriah Waterland 	}
1764*5c51f124SMoriah Waterland 	return (B_FALSE);
1765*5c51f124SMoriah Waterland }
1766*5c51f124SMoriah Waterland 
1767*5c51f124SMoriah Waterland void
1768*5c51f124SMoriah Waterland regfiles_free()
1769*5c51f124SMoriah Waterland {
1770*5c51f124SMoriah Waterland 	if (regfiles_head != NULL) {
1771*5c51f124SMoriah Waterland 		struct reg_files *rfp = regfiles_head->next;
1772*5c51f124SMoriah Waterland 
1773*5c51f124SMoriah Waterland 		while (rfp != NULL) {
1774*5c51f124SMoriah Waterland 			free(regfiles_head);
1775*5c51f124SMoriah Waterland 			regfiles_head = rfp;
1776*5c51f124SMoriah Waterland 			rfp = regfiles_head->next;
1777*5c51f124SMoriah Waterland 		}
1778*5c51f124SMoriah Waterland 		free(regfiles_head);
1779*5c51f124SMoriah Waterland 		regfiles_head = NULL;
1780*5c51f124SMoriah Waterland 	}
1781*5c51f124SMoriah Waterland }
1782