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