xref: /onnv-gate/usr/src/cmd/svr4pkg/libinst/pkgobjmap.c (revision 9781:ccf49524d5dc)
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 2008 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 
28*9781SMoriah.Waterland@Sun.COM #include <stdio.h>
29*9781SMoriah.Waterland@Sun.COM #include <limits.h>
30*9781SMoriah.Waterland@Sun.COM #include <stdlib.h>
31*9781SMoriah.Waterland@Sun.COM #include <unistd.h>
32*9781SMoriah.Waterland@Sun.COM #include <errno.h>
33*9781SMoriah.Waterland@Sun.COM #include <string.h>
34*9781SMoriah.Waterland@Sun.COM #include <sys/types.h>
35*9781SMoriah.Waterland@Sun.COM #include <pkgstrct.h>
36*9781SMoriah.Waterland@Sun.COM #include <locale.h>
37*9781SMoriah.Waterland@Sun.COM #include <libintl.h>
38*9781SMoriah.Waterland@Sun.COM #include <pkglib.h>
39*9781SMoriah.Waterland@Sun.COM #include <install.h>
40*9781SMoriah.Waterland@Sun.COM #include <libinst.h>
41*9781SMoriah.Waterland@Sun.COM 
42*9781SMoriah.Waterland@Sun.COM #define	WRN_NOPKGOBJ	"WARNING: no package objects found"
43*9781SMoriah.Waterland@Sun.COM 
44*9781SMoriah.Waterland@Sun.COM #define	ERR_MEMORY	"memory allocation failure"
45*9781SMoriah.Waterland@Sun.COM #define	ERR_DUPPATH	"duplicate pathname <%s>"
46*9781SMoriah.Waterland@Sun.COM 
47*9781SMoriah.Waterland@Sun.COM /* libpkg/gpkgmap */
48*9781SMoriah.Waterland@Sun.COM extern int	getmapmode(void);
49*9781SMoriah.Waterland@Sun.COM 
50*9781SMoriah.Waterland@Sun.COM #define	EPTMALLOC	512
51*9781SMoriah.Waterland@Sun.COM 
52*9781SMoriah.Waterland@Sun.COM static struct cfextra **extlist;
53*9781SMoriah.Waterland@Sun.COM 
54*9781SMoriah.Waterland@Sun.COM int	eptnum;
55*9781SMoriah.Waterland@Sun.COM static int	array_preloaded = 0;
56*9781SMoriah.Waterland@Sun.COM static int	errflg;
57*9781SMoriah.Waterland@Sun.COM static int	nparts;
58*9781SMoriah.Waterland@Sun.COM static int	xspace = -1;
59*9781SMoriah.Waterland@Sun.COM 
60*9781SMoriah.Waterland@Sun.COM void	pkgobjinit(void);
61*9781SMoriah.Waterland@Sun.COM static int	pkgobjassign(struct cfent *ept, char **server_local,
62*9781SMoriah.Waterland@Sun.COM 		    char **client_local, char **server_path,
63*9781SMoriah.Waterland@Sun.COM 		    char **client_path, char **map_path, int mapflag,
64*9781SMoriah.Waterland@Sun.COM 		    int nc);
65*9781SMoriah.Waterland@Sun.COM 
66*9781SMoriah.Waterland@Sun.COM static int	ckdup(struct cfent *ept1, struct cfent *ept2);
67*9781SMoriah.Waterland@Sun.COM static int	sortentry(int index);
68*9781SMoriah.Waterland@Sun.COM static int	dup_merg(struct cfextra *ext1, struct cfextra *ext2);
69*9781SMoriah.Waterland@Sun.COM 
70*9781SMoriah.Waterland@Sun.COM void
pkgobjinit(void)71*9781SMoriah.Waterland@Sun.COM pkgobjinit(void)
72*9781SMoriah.Waterland@Sun.COM {
73*9781SMoriah.Waterland@Sun.COM 	if (array_preloaded)	/* Already done. */
74*9781SMoriah.Waterland@Sun.COM 		return;
75*9781SMoriah.Waterland@Sun.COM 
76*9781SMoriah.Waterland@Sun.COM 	errflg = nparts = eptnum = 0;
77*9781SMoriah.Waterland@Sun.COM 
78*9781SMoriah.Waterland@Sun.COM 	if (xspace != -1) {
79*9781SMoriah.Waterland@Sun.COM 		ar_free(xspace);
80*9781SMoriah.Waterland@Sun.COM 		xspace = -1;
81*9781SMoriah.Waterland@Sun.COM 	}
82*9781SMoriah.Waterland@Sun.COM 
83*9781SMoriah.Waterland@Sun.COM 	/*
84*9781SMoriah.Waterland@Sun.COM 	 * initialize dynamic memory used to store
85*9781SMoriah.Waterland@Sun.COM 	 * path information which is read in
86*9781SMoriah.Waterland@Sun.COM 	 */
87*9781SMoriah.Waterland@Sun.COM 	(void) pathdup((char *)0);
88*9781SMoriah.Waterland@Sun.COM }
89*9781SMoriah.Waterland@Sun.COM 
90*9781SMoriah.Waterland@Sun.COM /*
91*9781SMoriah.Waterland@Sun.COM  * This function assigns appropriate values based upon the pkgmap entry
92*9781SMoriah.Waterland@Sun.COM  * in the cfent structure.
93*9781SMoriah.Waterland@Sun.COM  */
94*9781SMoriah.Waterland@Sun.COM static int
pkgobjassign(struct cfent * ept,char ** server_local,char ** client_local,char ** server_path,char ** client_path,char ** map_path,int mapflag,int nc)95*9781SMoriah.Waterland@Sun.COM pkgobjassign(struct cfent *ept, char **server_local, char **client_local,
96*9781SMoriah.Waterland@Sun.COM     char **server_path, char **client_path, char **map_path, int mapflag,
97*9781SMoriah.Waterland@Sun.COM     int nc)
98*9781SMoriah.Waterland@Sun.COM {
99*9781SMoriah.Waterland@Sun.COM 	int	path_duped = 0;
100*9781SMoriah.Waterland@Sun.COM 	int	local_duped = 0;
101*9781SMoriah.Waterland@Sun.COM 	char	source[PATH_MAX+1];
102*9781SMoriah.Waterland@Sun.COM 
103*9781SMoriah.Waterland@Sun.COM 	if (nc >= 0 && ept->ftype != 'i')
104*9781SMoriah.Waterland@Sun.COM 		if ((ept->pkg_class_idx = cl_idx(ept->pkg_class)) == -1)
105*9781SMoriah.Waterland@Sun.COM 			return (1);
106*9781SMoriah.Waterland@Sun.COM 
107*9781SMoriah.Waterland@Sun.COM 	if (ept->volno > nparts)
108*9781SMoriah.Waterland@Sun.COM 		nparts++;
109*9781SMoriah.Waterland@Sun.COM 
110*9781SMoriah.Waterland@Sun.COM 	/*
111*9781SMoriah.Waterland@Sun.COM 	 * Generate local (delivered source) paths for files
112*9781SMoriah.Waterland@Sun.COM 	 * which need them so that the install routine will know
113*9781SMoriah.Waterland@Sun.COM 	 * where to get the file from the package. Note that we
114*9781SMoriah.Waterland@Sun.COM 	 * do not resolve path environment variables here since
115*9781SMoriah.Waterland@Sun.COM 	 * they won't be resolved in the reloc directory.
116*9781SMoriah.Waterland@Sun.COM 	 */
117*9781SMoriah.Waterland@Sun.COM 	if ((mapflag > 1) && strchr("fve", ept->ftype)) {
118*9781SMoriah.Waterland@Sun.COM 		if (ept->ainfo.local == NULL) {
119*9781SMoriah.Waterland@Sun.COM 			source[0] = '~';
120*9781SMoriah.Waterland@Sun.COM 			(void) strlcpy(&source[1], ept->path,
121*9781SMoriah.Waterland@Sun.COM 						sizeof (source)-1);
122*9781SMoriah.Waterland@Sun.COM 			ept->ainfo.local = pathdup(source);
123*9781SMoriah.Waterland@Sun.COM 			*server_local = ept->ainfo.local;
124*9781SMoriah.Waterland@Sun.COM 			*client_local = ept->ainfo.local;
125*9781SMoriah.Waterland@Sun.COM 
126*9781SMoriah.Waterland@Sun.COM 			local_duped = 1;
127*9781SMoriah.Waterland@Sun.COM 		}
128*9781SMoriah.Waterland@Sun.COM 	}
129*9781SMoriah.Waterland@Sun.COM 
130*9781SMoriah.Waterland@Sun.COM 	/*
131*9781SMoriah.Waterland@Sun.COM 	 * Evaluate the destination path based upon available
132*9781SMoriah.Waterland@Sun.COM 	 * environment, then produce a client-relative and
133*9781SMoriah.Waterland@Sun.COM 	 * server-relative canonized path.
134*9781SMoriah.Waterland@Sun.COM 	 */
135*9781SMoriah.Waterland@Sun.COM 	if (mapflag && (ept->ftype != 'i')) {
136*9781SMoriah.Waterland@Sun.COM 		mappath(getmapmode(), ept->path); /* evaluate variables */
137*9781SMoriah.Waterland@Sun.COM 		canonize(ept->path);	/* Fix path as necessary. */
138*9781SMoriah.Waterland@Sun.COM 
139*9781SMoriah.Waterland@Sun.COM 		(void) eval_path(server_path,
140*9781SMoriah.Waterland@Sun.COM 		    client_path,
141*9781SMoriah.Waterland@Sun.COM 		    map_path,
142*9781SMoriah.Waterland@Sun.COM 		    ept->path);
143*9781SMoriah.Waterland@Sun.COM 		path_duped = 1;	/* eval_path dup's it */
144*9781SMoriah.Waterland@Sun.COM 		ept->path = *server_path;	/* default */
145*9781SMoriah.Waterland@Sun.COM 	}
146*9781SMoriah.Waterland@Sun.COM 
147*9781SMoriah.Waterland@Sun.COM 	/*
148*9781SMoriah.Waterland@Sun.COM 	 * Deal with source for hard and soft links.
149*9781SMoriah.Waterland@Sun.COM 	 */
150*9781SMoriah.Waterland@Sun.COM 	if (strchr("sl", ept->ftype)) {
151*9781SMoriah.Waterland@Sun.COM 		if (mapflag) {
152*9781SMoriah.Waterland@Sun.COM 			mappath(getmapmode(), ept->ainfo.local);
153*9781SMoriah.Waterland@Sun.COM 			if (!RELATIVE(ept->ainfo.local)) {
154*9781SMoriah.Waterland@Sun.COM 				canonize(ept->ainfo.local);
155*9781SMoriah.Waterland@Sun.COM 
156*9781SMoriah.Waterland@Sun.COM 				/* check for hard link */
157*9781SMoriah.Waterland@Sun.COM 				if (ept->ftype == 'l') {
158*9781SMoriah.Waterland@Sun.COM 					(void) eval_path(
159*9781SMoriah.Waterland@Sun.COM 					    server_local,
160*9781SMoriah.Waterland@Sun.COM 					    client_local,
161*9781SMoriah.Waterland@Sun.COM 					    NULL,
162*9781SMoriah.Waterland@Sun.COM 					    ept->ainfo.local);
163*9781SMoriah.Waterland@Sun.COM 					local_duped = 1;
164*9781SMoriah.Waterland@Sun.COM 
165*9781SMoriah.Waterland@Sun.COM 					/* Default to server. */
166*9781SMoriah.Waterland@Sun.COM 					ept->ainfo.local = *server_local;
167*9781SMoriah.Waterland@Sun.COM 				}
168*9781SMoriah.Waterland@Sun.COM 			}
169*9781SMoriah.Waterland@Sun.COM 		}
170*9781SMoriah.Waterland@Sun.COM 	}
171*9781SMoriah.Waterland@Sun.COM 
172*9781SMoriah.Waterland@Sun.COM 	/*
173*9781SMoriah.Waterland@Sun.COM 	 * For the paths (both source and target) that were too mundane to
174*9781SMoriah.Waterland@Sun.COM 	 * have been copied into dup space yet, do that.
175*9781SMoriah.Waterland@Sun.COM 	 */
176*9781SMoriah.Waterland@Sun.COM 	if (!path_duped) {
177*9781SMoriah.Waterland@Sun.COM 		*server_path = pathdup(ept->path);
178*9781SMoriah.Waterland@Sun.COM 		*client_path = *server_path;
179*9781SMoriah.Waterland@Sun.COM 		ept->path = *server_path;
180*9781SMoriah.Waterland@Sun.COM 
181*9781SMoriah.Waterland@Sun.COM 		path_duped = 1;
182*9781SMoriah.Waterland@Sun.COM 	}
183*9781SMoriah.Waterland@Sun.COM 	if (ept->ainfo.local != NULL)
184*9781SMoriah.Waterland@Sun.COM 		if (!local_duped) {
185*9781SMoriah.Waterland@Sun.COM 			*server_local = pathdup(ept->ainfo.local);
186*9781SMoriah.Waterland@Sun.COM 			ept->ainfo.local = *server_local;
187*9781SMoriah.Waterland@Sun.COM 			*client_local = ept->ainfo.local;
188*9781SMoriah.Waterland@Sun.COM 
189*9781SMoriah.Waterland@Sun.COM 		local_duped = 1;
190*9781SMoriah.Waterland@Sun.COM 	}
191*9781SMoriah.Waterland@Sun.COM 
192*9781SMoriah.Waterland@Sun.COM 	return (0);
193*9781SMoriah.Waterland@Sun.COM }
194*9781SMoriah.Waterland@Sun.COM 
195*9781SMoriah.Waterland@Sun.COM /* This initializes the package object array. */
196*9781SMoriah.Waterland@Sun.COM int
init_pkgobjspace(void)197*9781SMoriah.Waterland@Sun.COM init_pkgobjspace(void)
198*9781SMoriah.Waterland@Sun.COM {
199*9781SMoriah.Waterland@Sun.COM 	if (array_preloaded)	/* Already done. */
200*9781SMoriah.Waterland@Sun.COM 		return (1);
201*9781SMoriah.Waterland@Sun.COM 
202*9781SMoriah.Waterland@Sun.COM 	if (xspace == -1) {
203*9781SMoriah.Waterland@Sun.COM 		xspace = ar_create(EPTMALLOC, sizeof (struct cfextra),
204*9781SMoriah.Waterland@Sun.COM 		    "package object");
205*9781SMoriah.Waterland@Sun.COM 		if (xspace == -1) {
206*9781SMoriah.Waterland@Sun.COM 			progerr(gettext(ERR_MEMORY));
207*9781SMoriah.Waterland@Sun.COM 			return (0);
208*9781SMoriah.Waterland@Sun.COM 		}
209*9781SMoriah.Waterland@Sun.COM 	}
210*9781SMoriah.Waterland@Sun.COM 
211*9781SMoriah.Waterland@Sun.COM 	return (1);
212*9781SMoriah.Waterland@Sun.COM }
213*9781SMoriah.Waterland@Sun.COM 
214*9781SMoriah.Waterland@Sun.COM int
seed_pkgobjmap(struct cfextra * ext_entry,char * path,char * local)215*9781SMoriah.Waterland@Sun.COM seed_pkgobjmap(struct cfextra *ext_entry, char *path, char *local)
216*9781SMoriah.Waterland@Sun.COM {
217*9781SMoriah.Waterland@Sun.COM 	struct cfextra *ext, **ext_ptr;
218*9781SMoriah.Waterland@Sun.COM 
219*9781SMoriah.Waterland@Sun.COM 	/* offsets for the various path images. */
220*9781SMoriah.Waterland@Sun.COM 	int client_path_os;
221*9781SMoriah.Waterland@Sun.COM 	int server_path_os;
222*9781SMoriah.Waterland@Sun.COM 	int map_path_os;
223*9781SMoriah.Waterland@Sun.COM 	int client_local_os;
224*9781SMoriah.Waterland@Sun.COM 	int server_local_os;
225*9781SMoriah.Waterland@Sun.COM 
226*9781SMoriah.Waterland@Sun.COM 	ext_ptr = (struct cfextra **)ar_next_avail(xspace);
227*9781SMoriah.Waterland@Sun.COM 
228*9781SMoriah.Waterland@Sun.COM 	if (ext_ptr == NULL || *ext_ptr == NULL) {
229*9781SMoriah.Waterland@Sun.COM 		progerr(gettext(ERR_MEMORY));
230*9781SMoriah.Waterland@Sun.COM 		return (NULL);
231*9781SMoriah.Waterland@Sun.COM 	}
232*9781SMoriah.Waterland@Sun.COM 
233*9781SMoriah.Waterland@Sun.COM 	ext = *ext_ptr;
234*9781SMoriah.Waterland@Sun.COM 
235*9781SMoriah.Waterland@Sun.COM 	(void) memcpy(ext, ext_entry, sizeof (struct cfextra));
236*9781SMoriah.Waterland@Sun.COM 
237*9781SMoriah.Waterland@Sun.COM 	/* Figure out all of the offsets. */
238*9781SMoriah.Waterland@Sun.COM 	client_path_os = ((ptrdiff_t)ext->client_path -
239*9781SMoriah.Waterland@Sun.COM 			(ptrdiff_t)ext->cf_ent.path);
240*9781SMoriah.Waterland@Sun.COM 	server_path_os = ((ptrdiff_t)ext->server_path -
241*9781SMoriah.Waterland@Sun.COM 			(ptrdiff_t)ext->cf_ent.path);
242*9781SMoriah.Waterland@Sun.COM 	map_path_os = ((ptrdiff_t)ext->map_path -
243*9781SMoriah.Waterland@Sun.COM 			(ptrdiff_t)ext->cf_ent.path);
244*9781SMoriah.Waterland@Sun.COM 	client_local_os = ((ptrdiff_t)ext->client_local -
245*9781SMoriah.Waterland@Sun.COM 			(ptrdiff_t)ext->cf_ent.ainfo.local);
246*9781SMoriah.Waterland@Sun.COM 	server_local_os = ((ptrdiff_t)ext->server_local -
247*9781SMoriah.Waterland@Sun.COM 			(ptrdiff_t)ext->cf_ent.ainfo.local);
248*9781SMoriah.Waterland@Sun.COM 
249*9781SMoriah.Waterland@Sun.COM 	/* Allocate and store the path name. */
250*9781SMoriah.Waterland@Sun.COM 	ext->cf_ent.path = pathdup(path);
251*9781SMoriah.Waterland@Sun.COM 
252*9781SMoriah.Waterland@Sun.COM 	/* Assign the path substring pointers. */
253*9781SMoriah.Waterland@Sun.COM 	ext->client_path = (ext->cf_ent.path + client_path_os);
254*9781SMoriah.Waterland@Sun.COM 	ext->server_path = (ext->cf_ent.path + server_path_os);
255*9781SMoriah.Waterland@Sun.COM 	ext->map_path = (ext->cf_ent.path + map_path_os);
256*9781SMoriah.Waterland@Sun.COM 
257*9781SMoriah.Waterland@Sun.COM 	/* If there's a local entry, allocate and store it as well. */
258*9781SMoriah.Waterland@Sun.COM 	if (local) {
259*9781SMoriah.Waterland@Sun.COM 		ext->cf_ent.ainfo.local = pathdup(local);
260*9781SMoriah.Waterland@Sun.COM 
261*9781SMoriah.Waterland@Sun.COM 		ext->client_local = (ext->cf_ent.ainfo.local + client_local_os);
262*9781SMoriah.Waterland@Sun.COM 		ext->server_local = (ext->cf_ent.ainfo.local + server_local_os);
263*9781SMoriah.Waterland@Sun.COM 	} else {
264*9781SMoriah.Waterland@Sun.COM 		ext->cf_ent.ainfo.local = NULL;
265*9781SMoriah.Waterland@Sun.COM 		ext->client_local = NULL;
266*9781SMoriah.Waterland@Sun.COM 		ext->server_local = NULL;
267*9781SMoriah.Waterland@Sun.COM 	}
268*9781SMoriah.Waterland@Sun.COM 
269*9781SMoriah.Waterland@Sun.COM 	eptnum++;
270*9781SMoriah.Waterland@Sun.COM 	array_preloaded = 1;
271*9781SMoriah.Waterland@Sun.COM 
272*9781SMoriah.Waterland@Sun.COM 	return (0);
273*9781SMoriah.Waterland@Sun.COM }
274*9781SMoriah.Waterland@Sun.COM 
275*9781SMoriah.Waterland@Sun.COM /*
276*9781SMoriah.Waterland@Sun.COM  * This function reads the pkgmap (or any file similarly formatted) and
277*9781SMoriah.Waterland@Sun.COM  * returns a pointer to a list of struct cfextra (each of which
278*9781SMoriah.Waterland@Sun.COM  * contains a struct cfent) representing the contents of that file.
279*9781SMoriah.Waterland@Sun.COM  */
280*9781SMoriah.Waterland@Sun.COM 
281*9781SMoriah.Waterland@Sun.COM /* ARGSUSED ir in pkgobjmap */
282*9781SMoriah.Waterland@Sun.COM struct cfextra **
pkgobjmap(VFP_T * vfp,int mapflag,char * ir)283*9781SMoriah.Waterland@Sun.COM pkgobjmap(VFP_T *vfp, int mapflag, char *ir)
284*9781SMoriah.Waterland@Sun.COM {
285*9781SMoriah.Waterland@Sun.COM 	struct	cfextra *ext, **ext_ptr;
286*9781SMoriah.Waterland@Sun.COM 	struct	cfent *ept, map_entry;
287*9781SMoriah.Waterland@Sun.COM 	int	i;
288*9781SMoriah.Waterland@Sun.COM 	int	n;
289*9781SMoriah.Waterland@Sun.COM 	int	nc;
290*9781SMoriah.Waterland@Sun.COM 
291*9781SMoriah.Waterland@Sun.COM 	pkgobjinit();
292*9781SMoriah.Waterland@Sun.COM 	if (!init_pkgobjspace())
293*9781SMoriah.Waterland@Sun.COM 		quit(99);
294*9781SMoriah.Waterland@Sun.COM 
295*9781SMoriah.Waterland@Sun.COM 	nc = cl_getn();
296*9781SMoriah.Waterland@Sun.COM 	for (;;) {
297*9781SMoriah.Waterland@Sun.COM 		/* Clear the buffer. */
298*9781SMoriah.Waterland@Sun.COM 		(void) memset(&map_entry, '\000', sizeof (struct cfent));
299*9781SMoriah.Waterland@Sun.COM 
300*9781SMoriah.Waterland@Sun.COM 		/*
301*9781SMoriah.Waterland@Sun.COM 		 * Fill in a cfent structure in a very preliminary fashion.
302*9781SMoriah.Waterland@Sun.COM 		 * ept->path and ept->ainfo.local point to static memory
303*9781SMoriah.Waterland@Sun.COM 		 * areas of size PATH_MAX. These are manipulated and
304*9781SMoriah.Waterland@Sun.COM 		 * then provided their own allocations later in this function.
305*9781SMoriah.Waterland@Sun.COM 		 */
306*9781SMoriah.Waterland@Sun.COM 		n = gpkgmapvfp(&map_entry, vfp);
307*9781SMoriah.Waterland@Sun.COM 
308*9781SMoriah.Waterland@Sun.COM 		if (n == 0)
309*9781SMoriah.Waterland@Sun.COM 			break; /* no more entries in pkgmap */
310*9781SMoriah.Waterland@Sun.COM 		else if (n < 0) {
311*9781SMoriah.Waterland@Sun.COM 			char	*errstr = getErrstr();
312*9781SMoriah.Waterland@Sun.COM 			progerr(gettext("bad entry read in pkgmap"));
313*9781SMoriah.Waterland@Sun.COM 			logerr(gettext("pathname=%s"),
314*9781SMoriah.Waterland@Sun.COM 			    (map_entry.path && *map_entry.path) ?
315*9781SMoriah.Waterland@Sun.COM 			    map_entry.path : "Unknown");
316*9781SMoriah.Waterland@Sun.COM 			logerr(gettext("problem=%s"),
317*9781SMoriah.Waterland@Sun.COM 			    (errstr && *errstr) ? errstr : "Unknown");
318*9781SMoriah.Waterland@Sun.COM 			return (NULL);
319*9781SMoriah.Waterland@Sun.COM 		}
320*9781SMoriah.Waterland@Sun.COM 
321*9781SMoriah.Waterland@Sun.COM 		/*
322*9781SMoriah.Waterland@Sun.COM 		 * A valid entry was found in the map, so allocate an
323*9781SMoriah.Waterland@Sun.COM 		 * official record.
324*9781SMoriah.Waterland@Sun.COM 		 */
325*9781SMoriah.Waterland@Sun.COM 		ext_ptr = (struct cfextra **)ar_next_avail(xspace);
326*9781SMoriah.Waterland@Sun.COM 		if (ext_ptr == NULL || *ext_ptr == NULL) {
327*9781SMoriah.Waterland@Sun.COM 			progerr(gettext(ERR_MEMORY));
328*9781SMoriah.Waterland@Sun.COM 			return (NULL);
329*9781SMoriah.Waterland@Sun.COM 		}
330*9781SMoriah.Waterland@Sun.COM 
331*9781SMoriah.Waterland@Sun.COM 		ext = *ext_ptr;
332*9781SMoriah.Waterland@Sun.COM 		ept = &(ext->cf_ent);
333*9781SMoriah.Waterland@Sun.COM 
334*9781SMoriah.Waterland@Sun.COM 		/* Transfer what we just read in. */
335*9781SMoriah.Waterland@Sun.COM 		(void) memcpy(ept, &map_entry, sizeof (struct cfent));
336*9781SMoriah.Waterland@Sun.COM 
337*9781SMoriah.Waterland@Sun.COM 		/* And process it into the cfextra structure. */
338*9781SMoriah.Waterland@Sun.COM 		if (pkgobjassign(ept,
339*9781SMoriah.Waterland@Sun.COM 		    &(ext->server_local),
340*9781SMoriah.Waterland@Sun.COM 		    &(ext->client_local),
341*9781SMoriah.Waterland@Sun.COM 		    &(ext->server_path),
342*9781SMoriah.Waterland@Sun.COM 		    &(ext->client_path),
343*9781SMoriah.Waterland@Sun.COM 		    &(ext->map_path),
344*9781SMoriah.Waterland@Sun.COM 		    mapflag, nc)) {
345*9781SMoriah.Waterland@Sun.COM 			/* It didn't take. */
346*9781SMoriah.Waterland@Sun.COM 			(void) ar_delete(xspace, eptnum);
347*9781SMoriah.Waterland@Sun.COM 			continue;
348*9781SMoriah.Waterland@Sun.COM 		}
349*9781SMoriah.Waterland@Sun.COM 
350*9781SMoriah.Waterland@Sun.COM 		eptnum++;
351*9781SMoriah.Waterland@Sun.COM 		ext->fsys_value = BADFSYS;	/* No file system data yet */
352*9781SMoriah.Waterland@Sun.COM 		ext->fsys_base = BADFSYS;
353*9781SMoriah.Waterland@Sun.COM 	}
354*9781SMoriah.Waterland@Sun.COM 
355*9781SMoriah.Waterland@Sun.COM 	if (eptnum == 0) {
356*9781SMoriah.Waterland@Sun.COM 		logerr(gettext(WRN_NOPKGOBJ));
357*9781SMoriah.Waterland@Sun.COM 		return (NULL);
358*9781SMoriah.Waterland@Sun.COM 	}
359*9781SMoriah.Waterland@Sun.COM 
360*9781SMoriah.Waterland@Sun.COM 	/* setup a pointer array to point to malloc'd entries space */
361*9781SMoriah.Waterland@Sun.COM 	extlist = (struct cfextra **)ar_get_head(xspace);
362*9781SMoriah.Waterland@Sun.COM 	if (extlist == NULL) {
363*9781SMoriah.Waterland@Sun.COM 		progerr(gettext(ERR_MEMORY));
364*9781SMoriah.Waterland@Sun.COM 		return (NULL);
365*9781SMoriah.Waterland@Sun.COM 	}
366*9781SMoriah.Waterland@Sun.COM 
367*9781SMoriah.Waterland@Sun.COM 	(void) sortentry(-1);
368*9781SMoriah.Waterland@Sun.COM 	for (i = 0; i < eptnum; /* void */) {
369*9781SMoriah.Waterland@Sun.COM 		if (!sortentry(i))
370*9781SMoriah.Waterland@Sun.COM 			i++;
371*9781SMoriah.Waterland@Sun.COM 	}
372*9781SMoriah.Waterland@Sun.COM 
373*9781SMoriah.Waterland@Sun.COM 	return (errflg ? NULL : extlist);
374*9781SMoriah.Waterland@Sun.COM }
375*9781SMoriah.Waterland@Sun.COM 
376*9781SMoriah.Waterland@Sun.COM /*
377*9781SMoriah.Waterland@Sun.COM  * This function sorts the final list of cfextra entries. If index = -1, the
378*9781SMoriah.Waterland@Sun.COM  * function is initialized. index = 0 doesn't get us anywhere because this
379*9781SMoriah.Waterland@Sun.COM  * sorts against index-1. Positive natural index values are compared and
380*9781SMoriah.Waterland@Sun.COM  * sorted into the array appropriately. Yes, it does seem we should use a
381*9781SMoriah.Waterland@Sun.COM  * quicksort on the whole array or something. The apparent reason for taking
382*9781SMoriah.Waterland@Sun.COM  * this approach is that there are enough special considerations to be
383*9781SMoriah.Waterland@Sun.COM  * applied to each package object that inserting them one-by-one doesn't cost
384*9781SMoriah.Waterland@Sun.COM  * that much.
385*9781SMoriah.Waterland@Sun.COM  */
386*9781SMoriah.Waterland@Sun.COM static int
sortentry(int index)387*9781SMoriah.Waterland@Sun.COM sortentry(int index)
388*9781SMoriah.Waterland@Sun.COM {
389*9781SMoriah.Waterland@Sun.COM 	struct cfextra *ext;
390*9781SMoriah.Waterland@Sun.COM 	struct cfent *ept, *ept_i;
391*9781SMoriah.Waterland@Sun.COM 	static int last = 0;
392*9781SMoriah.Waterland@Sun.COM 	int	i, n, j;
393*9781SMoriah.Waterland@Sun.COM 	int	upper, lower;
394*9781SMoriah.Waterland@Sun.COM 
395*9781SMoriah.Waterland@Sun.COM 	if (index == 0)
396*9781SMoriah.Waterland@Sun.COM 		return (0);
397*9781SMoriah.Waterland@Sun.COM 	else if (index < 0) {
398*9781SMoriah.Waterland@Sun.COM 		last = 0;
399*9781SMoriah.Waterland@Sun.COM 		return (0);
400*9781SMoriah.Waterland@Sun.COM 	}
401*9781SMoriah.Waterland@Sun.COM 
402*9781SMoriah.Waterland@Sun.COM 	/*
403*9781SMoriah.Waterland@Sun.COM 	 * Based on the index, this is the package object we're going to
404*9781SMoriah.Waterland@Sun.COM 	 * review. It may stay where it is or it may be repositioned in the
405*9781SMoriah.Waterland@Sun.COM 	 * array.
406*9781SMoriah.Waterland@Sun.COM 	 */
407*9781SMoriah.Waterland@Sun.COM 	ext = extlist[index];
408*9781SMoriah.Waterland@Sun.COM 	ept = &(ext->cf_ent);
409*9781SMoriah.Waterland@Sun.COM 
410*9781SMoriah.Waterland@Sun.COM 	/* quick comparison optimization for pre-sorted arrays */
411*9781SMoriah.Waterland@Sun.COM 	if (strcmp(ept->path, extlist[index-1]->cf_ent.path) > 0) {
412*9781SMoriah.Waterland@Sun.COM 		/* do nothing */
413*9781SMoriah.Waterland@Sun.COM 		last = index-1;
414*9781SMoriah.Waterland@Sun.COM 		return (0);
415*9781SMoriah.Waterland@Sun.COM 	}
416*9781SMoriah.Waterland@Sun.COM 
417*9781SMoriah.Waterland@Sun.COM 	lower = 0;		/* lower bound of the unsorted elements */
418*9781SMoriah.Waterland@Sun.COM 	upper = index;		/* upper bound */
419*9781SMoriah.Waterland@Sun.COM 	i = last;
420*9781SMoriah.Waterland@Sun.COM 	do {
421*9781SMoriah.Waterland@Sun.COM 		/*
422*9781SMoriah.Waterland@Sun.COM 		 * NOTE: This does a binary sort on path. There are lots of
423*9781SMoriah.Waterland@Sun.COM 		 * other worthy items in the array, but path is the key into
424*9781SMoriah.Waterland@Sun.COM 		 * the package database.
425*9781SMoriah.Waterland@Sun.COM 		 */
426*9781SMoriah.Waterland@Sun.COM 		ept_i = &(extlist[i]->cf_ent);
427*9781SMoriah.Waterland@Sun.COM 
428*9781SMoriah.Waterland@Sun.COM 		n = strcmp(ept->path, ept_i->path);
429*9781SMoriah.Waterland@Sun.COM 		if (n == 0) {
430*9781SMoriah.Waterland@Sun.COM 			if (!ckdup(ept, ept_i)) {
431*9781SMoriah.Waterland@Sun.COM 				/*
432*9781SMoriah.Waterland@Sun.COM 				 * If the array was seeded then there are
433*9781SMoriah.Waterland@Sun.COM 				 * bound to be occasional duplicates.
434*9781SMoriah.Waterland@Sun.COM 				 * Otherwise, duplicates are definitely a
435*9781SMoriah.Waterland@Sun.COM 				 * sign of major damage.
436*9781SMoriah.Waterland@Sun.COM 				 */
437*9781SMoriah.Waterland@Sun.COM 				if (array_preloaded) {
438*9781SMoriah.Waterland@Sun.COM 					if (!dup_merg(ext, extlist[i])) {
439*9781SMoriah.Waterland@Sun.COM 						progerr(gettext(ERR_DUPPATH),
440*9781SMoriah.Waterland@Sun.COM 						    ept->path);
441*9781SMoriah.Waterland@Sun.COM 						errflg++;
442*9781SMoriah.Waterland@Sun.COM 					}
443*9781SMoriah.Waterland@Sun.COM 				} else {
444*9781SMoriah.Waterland@Sun.COM 					progerr(gettext(ERR_DUPPATH),
445*9781SMoriah.Waterland@Sun.COM 					    ept->path);
446*9781SMoriah.Waterland@Sun.COM 					errflg++;
447*9781SMoriah.Waterland@Sun.COM 				}
448*9781SMoriah.Waterland@Sun.COM 			}
449*9781SMoriah.Waterland@Sun.COM 			/* remove the entry at index */
450*9781SMoriah.Waterland@Sun.COM 			(void) ar_delete(xspace, index);
451*9781SMoriah.Waterland@Sun.COM 
452*9781SMoriah.Waterland@Sun.COM 			eptnum--;
453*9781SMoriah.Waterland@Sun.COM 			return (1);	/* Use this index again. */
454*9781SMoriah.Waterland@Sun.COM 		} else if (n < 0) {
455*9781SMoriah.Waterland@Sun.COM 			/*
456*9781SMoriah.Waterland@Sun.COM 			 * The path of interest is smaller than the path
457*9781SMoriah.Waterland@Sun.COM 			 * under test. Move down array using the method of
458*9781SMoriah.Waterland@Sun.COM 			 * division
459*9781SMoriah.Waterland@Sun.COM 			 */
460*9781SMoriah.Waterland@Sun.COM 			upper = i;
461*9781SMoriah.Waterland@Sun.COM 			i = lower + (upper-lower)/2;
462*9781SMoriah.Waterland@Sun.COM 		} else {
463*9781SMoriah.Waterland@Sun.COM 			/* Move up array */
464*9781SMoriah.Waterland@Sun.COM 			lower = i+1;
465*9781SMoriah.Waterland@Sun.COM 			i = upper - (upper-lower)/2 - 1;
466*9781SMoriah.Waterland@Sun.COM 		}
467*9781SMoriah.Waterland@Sun.COM 	} while (upper != lower);
468*9781SMoriah.Waterland@Sun.COM 	last = i = upper;
469*9781SMoriah.Waterland@Sun.COM 
470*9781SMoriah.Waterland@Sun.COM 	/* expand to insert at i */
471*9781SMoriah.Waterland@Sun.COM 	for (j = index; j > i; j--)
472*9781SMoriah.Waterland@Sun.COM 		extlist[j] = extlist[j-1];
473*9781SMoriah.Waterland@Sun.COM 
474*9781SMoriah.Waterland@Sun.COM 	extlist[i] = ext;
475*9781SMoriah.Waterland@Sun.COM 
476*9781SMoriah.Waterland@Sun.COM 	return (0);
477*9781SMoriah.Waterland@Sun.COM }
478*9781SMoriah.Waterland@Sun.COM 
479*9781SMoriah.Waterland@Sun.COM /* Return the number of blocks required by the package object provided. */
480*9781SMoriah.Waterland@Sun.COM static fsblkcnt_t
nblks(short fsys_entry,struct cfextra * ext)481*9781SMoriah.Waterland@Sun.COM nblks(short fsys_entry, struct cfextra *ext)
482*9781SMoriah.Waterland@Sun.COM {
483*9781SMoriah.Waterland@Sun.COM 	fsblkcnt_t blk;
484*9781SMoriah.Waterland@Sun.COM 	ulong_t block_size;
485*9781SMoriah.Waterland@Sun.COM 	ulong_t frag_size;
486*9781SMoriah.Waterland@Sun.COM 
487*9781SMoriah.Waterland@Sun.COM 	block_size = (ulong_t)get_blk_size_n(fsys_entry);
488*9781SMoriah.Waterland@Sun.COM 	frag_size = (ulong_t)get_frag_size_n(fsys_entry);
489*9781SMoriah.Waterland@Sun.COM 
490*9781SMoriah.Waterland@Sun.COM 	if (strchr("dxs", ext->cf_ent.ftype))
491*9781SMoriah.Waterland@Sun.COM 		blk =
492*9781SMoriah.Waterland@Sun.COM 		    nblk(block_size, block_size, frag_size);
493*9781SMoriah.Waterland@Sun.COM 	else if (ext->cf_ent.cinfo.size != BADCONT)
494*9781SMoriah.Waterland@Sun.COM 		blk = nblk(ext->cf_ent.cinfo.size, block_size,
495*9781SMoriah.Waterland@Sun.COM 		    frag_size);
496*9781SMoriah.Waterland@Sun.COM 	else
497*9781SMoriah.Waterland@Sun.COM 		blk = 0;
498*9781SMoriah.Waterland@Sun.COM 
499*9781SMoriah.Waterland@Sun.COM 	return (blk);
500*9781SMoriah.Waterland@Sun.COM }
501*9781SMoriah.Waterland@Sun.COM 
502*9781SMoriah.Waterland@Sun.COM /* Remove ext1 from the filesystem size calculations and add ext2. */
503*9781SMoriah.Waterland@Sun.COM static void
size_xchng(struct cfextra * ext1,struct cfextra * ext2)504*9781SMoriah.Waterland@Sun.COM size_xchng(struct cfextra *ext1, struct cfextra *ext2)
505*9781SMoriah.Waterland@Sun.COM {
506*9781SMoriah.Waterland@Sun.COM 	fsblkcnt_t bused;
507*9781SMoriah.Waterland@Sun.COM 	ulong_t block_size;
508*9781SMoriah.Waterland@Sun.COM 	ulong_t frag_size;
509*9781SMoriah.Waterland@Sun.COM 	fsblkcnt_t	blks1, blks2;
510*9781SMoriah.Waterland@Sun.COM 	short	fsys_entry;
511*9781SMoriah.Waterland@Sun.COM 
512*9781SMoriah.Waterland@Sun.COM 	/*
513*9781SMoriah.Waterland@Sun.COM 	 * Since these are on the same filesystem, either one will yield the
514*9781SMoriah.Waterland@Sun.COM 	 * correct block and fragment size.
515*9781SMoriah.Waterland@Sun.COM 	 */
516*9781SMoriah.Waterland@Sun.COM 	fsys_entry = ext1->fsys_base;
517*9781SMoriah.Waterland@Sun.COM 	block_size = (ulong_t)get_blk_size_n(fsys_entry);
518*9781SMoriah.Waterland@Sun.COM 	frag_size = (ulong_t)get_frag_size_n(fsys_entry);
519*9781SMoriah.Waterland@Sun.COM 
520*9781SMoriah.Waterland@Sun.COM 	blks1 = nblk(ext1->cf_ent.cinfo.size, block_size, frag_size);
521*9781SMoriah.Waterland@Sun.COM 	blks2 = nblk(ext2->cf_ent.cinfo.size, block_size, frag_size);
522*9781SMoriah.Waterland@Sun.COM 
523*9781SMoriah.Waterland@Sun.COM 	if (blks1 != blks2) {
524*9781SMoriah.Waterland@Sun.COM 		/* First, lose the old size, then add the new size. */
525*9781SMoriah.Waterland@Sun.COM 		bused = get_blk_used_n(fsys_entry);
526*9781SMoriah.Waterland@Sun.COM 		bused -= nblks(fsys_entry, ext1);
527*9781SMoriah.Waterland@Sun.COM 		bused += nblks(fsys_entry, ext2);
528*9781SMoriah.Waterland@Sun.COM 
529*9781SMoriah.Waterland@Sun.COM 		set_blk_used_n(fsys_entry, bused);
530*9781SMoriah.Waterland@Sun.COM 	}
531*9781SMoriah.Waterland@Sun.COM }
532*9781SMoriah.Waterland@Sun.COM 
533*9781SMoriah.Waterland@Sun.COM /*
534*9781SMoriah.Waterland@Sun.COM  * This function merges duplicate non-directory entries resulting from a
535*9781SMoriah.Waterland@Sun.COM  * dryrun or other procedure which preloads the extlist. It uses an odd
536*9781SMoriah.Waterland@Sun.COM  * heuristic to determine which package object is newest: only package
537*9781SMoriah.Waterland@Sun.COM  * objects from the dryrun file will have pinfo pointers. Therefore, the
538*9781SMoriah.Waterland@Sun.COM  * object with a pinfo pointer is from the dryrun file and it will be
539*9781SMoriah.Waterland@Sun.COM  * overwritten by the object being installed by this package.
540*9781SMoriah.Waterland@Sun.COM  *
541*9781SMoriah.Waterland@Sun.COM  * Assumptions:
542*9781SMoriah.Waterland@Sun.COM  *	1. The newer object will be overwriting the older object.
543*9781SMoriah.Waterland@Sun.COM  *	2. The two objects are close enough to the same size that
544*9781SMoriah.Waterland@Sun.COM  *	   the sizing is still OK.
545*9781SMoriah.Waterland@Sun.COM  *
546*9781SMoriah.Waterland@Sun.COM  * The calling routine will overwrite ept1, so this must return ept2 with
547*9781SMoriah.Waterland@Sun.COM  * the correct data to keep. There being only one logical outcome of a
548*9781SMoriah.Waterland@Sun.COM  * failure, this returns 1 for OK and 0 for FAIL.
549*9781SMoriah.Waterland@Sun.COM  */
550*9781SMoriah.Waterland@Sun.COM static int
dup_merg(struct cfextra * ext1,struct cfextra * ext2)551*9781SMoriah.Waterland@Sun.COM dup_merg(struct cfextra *ext1, struct cfextra *ext2)
552*9781SMoriah.Waterland@Sun.COM {
553*9781SMoriah.Waterland@Sun.COM 	struct cfent *ept1, *ept2;
554*9781SMoriah.Waterland@Sun.COM 
555*9781SMoriah.Waterland@Sun.COM 	ept1 = &(ext1->cf_ent);
556*9781SMoriah.Waterland@Sun.COM 	ept2 = &(ext2->cf_ent);
557*9781SMoriah.Waterland@Sun.COM 
558*9781SMoriah.Waterland@Sun.COM 	if (strchr("?dx", ept1->ftype))
559*9781SMoriah.Waterland@Sun.COM 		return (0);
560*9781SMoriah.Waterland@Sun.COM 
561*9781SMoriah.Waterland@Sun.COM 	if (strchr("?dx", ept2->ftype))
562*9781SMoriah.Waterland@Sun.COM 		return (0);
563*9781SMoriah.Waterland@Sun.COM 
564*9781SMoriah.Waterland@Sun.COM 	/* First, which is the eldest? */
565*9781SMoriah.Waterland@Sun.COM 	if (ext2->mstat.preloaded) {
566*9781SMoriah.Waterland@Sun.COM 		/*
567*9781SMoriah.Waterland@Sun.COM 		 * While ept2 has the correct pinfo list (it was preloaded into
568*9781SMoriah.Waterland@Sun.COM 		 * the array before the pkgmap was read), ept1 has everything
569*9781SMoriah.Waterland@Sun.COM 		 * else. Here we copy the guts of ept1 into ept2.
570*9781SMoriah.Waterland@Sun.COM 		 *
571*9781SMoriah.Waterland@Sun.COM 		 * Start by grabbing the pointers to the ext2 items that we
572*9781SMoriah.Waterland@Sun.COM 		 * need to either restore or free.
573*9781SMoriah.Waterland@Sun.COM 		 */
574*9781SMoriah.Waterland@Sun.COM 		/* to free() */
575*9781SMoriah.Waterland@Sun.COM 		char *path = ept2->path;
576*9781SMoriah.Waterland@Sun.COM 		char *local = ept2->ainfo.local;
577*9781SMoriah.Waterland@Sun.COM 
578*9781SMoriah.Waterland@Sun.COM 		/* to preserve */
579*9781SMoriah.Waterland@Sun.COM 		short npkgs = ept2->npkgs;
580*9781SMoriah.Waterland@Sun.COM 		struct pinfo *pinfo = ept2->pinfo;
581*9781SMoriah.Waterland@Sun.COM 
582*9781SMoriah.Waterland@Sun.COM 		/* Copy everything from the new entry to the old */
583*9781SMoriah.Waterland@Sun.COM 		(void) memcpy(ept2, ept1, sizeof (struct cfent));
584*9781SMoriah.Waterland@Sun.COM 
585*9781SMoriah.Waterland@Sun.COM 		/* Now restore the original stuff.. */
586*9781SMoriah.Waterland@Sun.COM 		ept2->path = path;
587*9781SMoriah.Waterland@Sun.COM 		ept2->ainfo.local = local;
588*9781SMoriah.Waterland@Sun.COM 		ept2->npkgs = npkgs;
589*9781SMoriah.Waterland@Sun.COM 		ept2->pinfo = pinfo;
590*9781SMoriah.Waterland@Sun.COM 
591*9781SMoriah.Waterland@Sun.COM 		size_xchng(ext2, ext1);
592*9781SMoriah.Waterland@Sun.COM 	} else if (ext1->mstat.preloaded) {
593*9781SMoriah.Waterland@Sun.COM 		/*
594*9781SMoriah.Waterland@Sun.COM 		 * ept2 is already the one we will keep. All we have to do is
595*9781SMoriah.Waterland@Sun.COM 		 * copy over the pinfo pointer.
596*9781SMoriah.Waterland@Sun.COM 		 */
597*9781SMoriah.Waterland@Sun.COM 		ept2->pinfo = ept1->pinfo;
598*9781SMoriah.Waterland@Sun.COM 		size_xchng(ext1, ext2);
599*9781SMoriah.Waterland@Sun.COM 	} else
600*9781SMoriah.Waterland@Sun.COM 		return (0);
601*9781SMoriah.Waterland@Sun.COM 
602*9781SMoriah.Waterland@Sun.COM 	return (1);
603*9781SMoriah.Waterland@Sun.COM }
604*9781SMoriah.Waterland@Sun.COM 
605*9781SMoriah.Waterland@Sun.COM /*
606*9781SMoriah.Waterland@Sun.COM  * Check duplicate entries in the package object list. If it's a directory,
607*9781SMoriah.Waterland@Sun.COM  * this just merges them, if not, it returns a 0 to force further processing.
608*9781SMoriah.Waterland@Sun.COM  */
609*9781SMoriah.Waterland@Sun.COM static int
ckdup(struct cfent * ept1,struct cfent * ept2)610*9781SMoriah.Waterland@Sun.COM ckdup(struct cfent *ept1, struct cfent *ept2)
611*9781SMoriah.Waterland@Sun.COM {
612*9781SMoriah.Waterland@Sun.COM 	/* ept2 will be modified to contain "merged" entries */
613*9781SMoriah.Waterland@Sun.COM 
614*9781SMoriah.Waterland@Sun.COM 	if (!strchr("?dx", ept1->ftype))
615*9781SMoriah.Waterland@Sun.COM 		return (0);
616*9781SMoriah.Waterland@Sun.COM 
617*9781SMoriah.Waterland@Sun.COM 	if (!strchr("?dx", ept2->ftype))
618*9781SMoriah.Waterland@Sun.COM 		return (0);
619*9781SMoriah.Waterland@Sun.COM 
620*9781SMoriah.Waterland@Sun.COM 	if (ept2->ainfo.mode == BADMODE)
621*9781SMoriah.Waterland@Sun.COM 		ept2->ainfo.mode = ept1->ainfo.mode;
622*9781SMoriah.Waterland@Sun.COM 	if ((ept1->ainfo.mode != ept2->ainfo.mode) &&
623*9781SMoriah.Waterland@Sun.COM 	    (ept1->ainfo.mode != BADMODE))
624*9781SMoriah.Waterland@Sun.COM 		return (0);
625*9781SMoriah.Waterland@Sun.COM 
626*9781SMoriah.Waterland@Sun.COM 	if (strcmp(ept2->ainfo.owner, "?") == 0)
627*9781SMoriah.Waterland@Sun.COM 		(void) strlcpy(ept2->ainfo.owner, ept1->ainfo.owner,
628*9781SMoriah.Waterland@Sun.COM 			sizeof (ept2->ainfo.owner));
629*9781SMoriah.Waterland@Sun.COM 	if (strcmp(ept1->ainfo.owner, ept2->ainfo.owner) &&
630*9781SMoriah.Waterland@Sun.COM 	    strcmp(ept1->ainfo.owner, "?"))
631*9781SMoriah.Waterland@Sun.COM 		return (0);
632*9781SMoriah.Waterland@Sun.COM 
633*9781SMoriah.Waterland@Sun.COM 	if (strcmp(ept2->ainfo.group, "?") == 0)
634*9781SMoriah.Waterland@Sun.COM 		(void) strlcpy(ept2->ainfo.group, ept1->ainfo.group,
635*9781SMoriah.Waterland@Sun.COM 			sizeof (ept2->ainfo.group));
636*9781SMoriah.Waterland@Sun.COM 	if (strcmp(ept1->ainfo.group, ept2->ainfo.group) &&
637*9781SMoriah.Waterland@Sun.COM 	    strcmp(ept1->ainfo.group, "?"))
638*9781SMoriah.Waterland@Sun.COM 		return (0);
639*9781SMoriah.Waterland@Sun.COM 
640*9781SMoriah.Waterland@Sun.COM 	if (ept1->pinfo) {
641*9781SMoriah.Waterland@Sun.COM 		ept2->npkgs = ept1->npkgs;
642*9781SMoriah.Waterland@Sun.COM 		ept2->pinfo = ept1->pinfo;
643*9781SMoriah.Waterland@Sun.COM 	}
644*9781SMoriah.Waterland@Sun.COM 
645*9781SMoriah.Waterland@Sun.COM 	return (1);
646*9781SMoriah.Waterland@Sun.COM }
647*9781SMoriah.Waterland@Sun.COM 
648*9781SMoriah.Waterland@Sun.COM /*
649*9781SMoriah.Waterland@Sun.COM  * Replace the old package database entry with the new one preserving the
650*9781SMoriah.Waterland@Sun.COM  * data which remains constant across the replacement.
651*9781SMoriah.Waterland@Sun.COM  *	copied directly:
652*9781SMoriah.Waterland@Sun.COM  *		ftype, pkg_class
653*9781SMoriah.Waterland@Sun.COM  *
654*9781SMoriah.Waterland@Sun.COM  *	preserved from old:
655*9781SMoriah.Waterland@Sun.COM  *		path, npkgs, pinfo
656*9781SMoriah.Waterland@Sun.COM  */
657*9781SMoriah.Waterland@Sun.COM void
repl_cfent(struct cfent * new,struct cfent * old)658*9781SMoriah.Waterland@Sun.COM repl_cfent(struct cfent *new, struct cfent *old)
659*9781SMoriah.Waterland@Sun.COM {
660*9781SMoriah.Waterland@Sun.COM 	char *path = old->path;
661*9781SMoriah.Waterland@Sun.COM 	short npkgs = old->npkgs;
662*9781SMoriah.Waterland@Sun.COM 	struct pinfo *pinfo = old->pinfo;
663*9781SMoriah.Waterland@Sun.COM 
664*9781SMoriah.Waterland@Sun.COM 	/* Copy everything from the new entry over */
665*9781SMoriah.Waterland@Sun.COM 	(void) memcpy(old, new, sizeof (struct cfent));
666*9781SMoriah.Waterland@Sun.COM 
667*9781SMoriah.Waterland@Sun.COM 	if (strchr("sl", new->ftype) == NULL)
668*9781SMoriah.Waterland@Sun.COM 		old->ainfo.local = NULL;
669*9781SMoriah.Waterland@Sun.COM 
670*9781SMoriah.Waterland@Sun.COM 	old->path = path;
671*9781SMoriah.Waterland@Sun.COM 	old->npkgs = npkgs;
672*9781SMoriah.Waterland@Sun.COM 	old->pinfo = pinfo;
673*9781SMoriah.Waterland@Sun.COM 
674*9781SMoriah.Waterland@Sun.COM 	old->volno = 0;
675*9781SMoriah.Waterland@Sun.COM }
676*9781SMoriah.Waterland@Sun.COM 
677*9781SMoriah.Waterland@Sun.COM /*
678*9781SMoriah.Waterland@Sun.COM  * Copy critical portions of cf_ent (from the package database) and el_ent
679*9781SMoriah.Waterland@Sun.COM  * (constructed from the pkgmap) into a merged cfent structure, tp. Then copy
680*9781SMoriah.Waterland@Sun.COM  * that to the el_ent structure. The approach we take here is to copy over
681*9781SMoriah.Waterland@Sun.COM  * everything from the package database entry, condition the paths based upon
682*9781SMoriah.Waterland@Sun.COM  * the currently installed path and then insert the following entries from
683*9781SMoriah.Waterland@Sun.COM  * the new structure :
684*9781SMoriah.Waterland@Sun.COM  *	cfent.volno
685*9781SMoriah.Waterland@Sun.COM  *	pkg_class
686*9781SMoriah.Waterland@Sun.COM  *	pkg_class_idx
687*9781SMoriah.Waterland@Sun.COM  *
688*9781SMoriah.Waterland@Sun.COM  * The pinfo list is then copied from the cfent list. While
689*9781SMoriah.Waterland@Sun.COM  * fsys_value is also copied over, it hasn't been set yet. This function
690*9781SMoriah.Waterland@Sun.COM  * copies over whatever the default value is from the new structure.
691*9781SMoriah.Waterland@Sun.COM  *
692*9781SMoriah.Waterland@Sun.COM  * The copied entry is returned in the el_ent argument and the function
693*9781SMoriah.Waterland@Sun.COM  * value is 1 on success, 0 on failure. There is no recovery plan for
694*9781SMoriah.Waterland@Sun.COM  * failure.
695*9781SMoriah.Waterland@Sun.COM  */
696*9781SMoriah.Waterland@Sun.COM int
cp_cfent(struct cfent * cf_ent,struct cfextra * el_ent)697*9781SMoriah.Waterland@Sun.COM cp_cfent(struct cfent *cf_ent, struct cfextra *el_ent)
698*9781SMoriah.Waterland@Sun.COM {
699*9781SMoriah.Waterland@Sun.COM 	struct cfextra	*tp;
700*9781SMoriah.Waterland@Sun.COM 
701*9781SMoriah.Waterland@Sun.COM 	/* Allocate space for cfent copy */
702*9781SMoriah.Waterland@Sun.COM 	if ((tp = (struct cfextra *)calloc(1,
703*9781SMoriah.Waterland@Sun.COM 	    sizeof (struct cfextra))) == NULL) {
704*9781SMoriah.Waterland@Sun.COM 		progerr(gettext("cp_cfent: memory allocation error"));
705*9781SMoriah.Waterland@Sun.COM 		return (0);
706*9781SMoriah.Waterland@Sun.COM 	}
707*9781SMoriah.Waterland@Sun.COM 
708*9781SMoriah.Waterland@Sun.COM 	/* Copy everything from the package database over */
709*9781SMoriah.Waterland@Sun.COM 	(void) memcpy(&(tp->cf_ent), cf_ent, sizeof (struct cfent));
710*9781SMoriah.Waterland@Sun.COM 
711*9781SMoriah.Waterland@Sun.COM 	/* Now overlay new items from the pkgmap */
712*9781SMoriah.Waterland@Sun.COM 	tp->fsys_value = el_ent->fsys_value;
713*9781SMoriah.Waterland@Sun.COM 	tp->cf_ent.volno = el_ent->cf_ent.volno;
714*9781SMoriah.Waterland@Sun.COM 	(void) strlcpy(tp->cf_ent.pkg_class, el_ent->cf_ent.pkg_class,
715*9781SMoriah.Waterland@Sun.COM 			sizeof (tp->cf_ent.pkg_class));
716*9781SMoriah.Waterland@Sun.COM 	tp->cf_ent.pkg_class_idx = el_ent->cf_ent.pkg_class_idx;
717*9781SMoriah.Waterland@Sun.COM 	tp->cf_ent.pinfo = cf_ent->pinfo;
718*9781SMoriah.Waterland@Sun.COM 
719*9781SMoriah.Waterland@Sun.COM 	/*
720*9781SMoriah.Waterland@Sun.COM 	 * The paths are identical, so we get them from the new entry.  These
721*9781SMoriah.Waterland@Sun.COM 	 * are pointing to a malloc'd section of memory containing a string
722*9781SMoriah.Waterland@Sun.COM 	 * that we aren't moving in this operation, so everybody points to
723*9781SMoriah.Waterland@Sun.COM 	 * the same thing during these transfers.
724*9781SMoriah.Waterland@Sun.COM 	 */
725*9781SMoriah.Waterland@Sun.COM 	tp->cf_ent.path = el_ent->client_path;
726*9781SMoriah.Waterland@Sun.COM 	tp->server_path = el_ent->server_path;
727*9781SMoriah.Waterland@Sun.COM 	tp->client_path = el_ent->client_path;
728*9781SMoriah.Waterland@Sun.COM 	tp->map_path = el_ent->map_path;
729*9781SMoriah.Waterland@Sun.COM 
730*9781SMoriah.Waterland@Sun.COM 	/*
731*9781SMoriah.Waterland@Sun.COM 	 * Since instvol() expects to work with the *original* mstat data,
732*9781SMoriah.Waterland@Sun.COM 	 * mstat is just copied here. NOTE: mstat looks like a structure, but
733*9781SMoriah.Waterland@Sun.COM 	 * it's really a short bit array.
734*9781SMoriah.Waterland@Sun.COM 	 */
735*9781SMoriah.Waterland@Sun.COM 	tp->mstat = el_ent->mstat;
736*9781SMoriah.Waterland@Sun.COM 
737*9781SMoriah.Waterland@Sun.COM 	/* Copy everything from the temporary structure to the new entry */
738*9781SMoriah.Waterland@Sun.COM 	(void) memcpy(el_ent, tp, sizeof (struct cfextra));
739*9781SMoriah.Waterland@Sun.COM 	free(tp);
740*9781SMoriah.Waterland@Sun.COM 
741*9781SMoriah.Waterland@Sun.COM 	return (1);
742*9781SMoriah.Waterland@Sun.COM }
743