xref: /onnv-gate/usr/src/cmd/svr4pkg/libinst/procmap.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 2006 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 <limits.h>
33*9781SMoriah.Waterland@Sun.COM #include <stdlib.h>
34*9781SMoriah.Waterland@Sun.COM #include <unistd.h>
35*9781SMoriah.Waterland@Sun.COM #include <errno.h>
36*9781SMoriah.Waterland@Sun.COM #include <string.h>
37*9781SMoriah.Waterland@Sun.COM #include <sys/types.h>
38*9781SMoriah.Waterland@Sun.COM #include <pkgstrct.h>
39*9781SMoriah.Waterland@Sun.COM #include <locale.h>
40*9781SMoriah.Waterland@Sun.COM #include <libintl.h>
41*9781SMoriah.Waterland@Sun.COM #include <pkglib.h>
42*9781SMoriah.Waterland@Sun.COM #include <install.h>
43*9781SMoriah.Waterland@Sun.COM #include <libinst.h>
44*9781SMoriah.Waterland@Sun.COM 
45*9781SMoriah.Waterland@Sun.COM #define	ERR_MEMORY	"memory allocation failure"
46*9781SMoriah.Waterland@Sun.COM #define	ERR_DUPPATH	"duplicate pathname <%s>"
47*9781SMoriah.Waterland@Sun.COM 
48*9781SMoriah.Waterland@Sun.COM /* libpkg/gpkgmap */
49*9781SMoriah.Waterland@Sun.COM extern int	getmapmode(void);
50*9781SMoriah.Waterland@Sun.COM 
51*9781SMoriah.Waterland@Sun.COM #define	EPTMALLOC	512
52*9781SMoriah.Waterland@Sun.COM 
53*9781SMoriah.Waterland@Sun.COM static struct cfent **eptlist;
54*9781SMoriah.Waterland@Sun.COM 
55*9781SMoriah.Waterland@Sun.COM static int	eptnum;
56*9781SMoriah.Waterland@Sun.COM static int	errflg;
57*9781SMoriah.Waterland@Sun.COM static int	nparts;
58*9781SMoriah.Waterland@Sun.COM static int	space = -1;
59*9781SMoriah.Waterland@Sun.COM 
60*9781SMoriah.Waterland@Sun.COM static void	procinit(void);
61*9781SMoriah.Waterland@Sun.COM static int	procassign(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 
69*9781SMoriah.Waterland@Sun.COM static void
procinit(void)70*9781SMoriah.Waterland@Sun.COM procinit(void)
71*9781SMoriah.Waterland@Sun.COM {
72*9781SMoriah.Waterland@Sun.COM 	errflg = nparts = eptnum = 0;
73*9781SMoriah.Waterland@Sun.COM 
74*9781SMoriah.Waterland@Sun.COM 	if (space != -1) {
75*9781SMoriah.Waterland@Sun.COM 		ar_free(space);
76*9781SMoriah.Waterland@Sun.COM 		space = -1;
77*9781SMoriah.Waterland@Sun.COM 	}
78*9781SMoriah.Waterland@Sun.COM 
79*9781SMoriah.Waterland@Sun.COM 	/*
80*9781SMoriah.Waterland@Sun.COM 	 * initialize dynamic memory used to store
81*9781SMoriah.Waterland@Sun.COM 	 * path information which is read in
82*9781SMoriah.Waterland@Sun.COM 	 */
83*9781SMoriah.Waterland@Sun.COM 	(void) pathdup((char *)0);
84*9781SMoriah.Waterland@Sun.COM }
85*9781SMoriah.Waterland@Sun.COM 
86*9781SMoriah.Waterland@Sun.COM /*
87*9781SMoriah.Waterland@Sun.COM  * This function assigns appropriate values based upon the pkgmap entry
88*9781SMoriah.Waterland@Sun.COM  * in the cfent structure.
89*9781SMoriah.Waterland@Sun.COM  */
90*9781SMoriah.Waterland@Sun.COM static int
procassign(struct cfent * ept,char ** server_local,char ** client_local,char ** server_path,char ** client_path,char ** map_path,int mapflag,int nc)91*9781SMoriah.Waterland@Sun.COM procassign(struct cfent *ept, char **server_local, char **client_local,
92*9781SMoriah.Waterland@Sun.COM     char **server_path, char **client_path, char **map_path, int mapflag,
93*9781SMoriah.Waterland@Sun.COM     int nc)
94*9781SMoriah.Waterland@Sun.COM {
95*9781SMoriah.Waterland@Sun.COM 	int	path_duped = 0;
96*9781SMoriah.Waterland@Sun.COM 	int	local_duped = 0;
97*9781SMoriah.Waterland@Sun.COM 	char	source[PATH_MAX+1];
98*9781SMoriah.Waterland@Sun.COM 
99*9781SMoriah.Waterland@Sun.COM 	if (nc >= 0 && ept->ftype != 'i')
100*9781SMoriah.Waterland@Sun.COM 		if ((ept->pkg_class_idx = cl_idx(ept->pkg_class)) == -1)
101*9781SMoriah.Waterland@Sun.COM 			return (1);
102*9781SMoriah.Waterland@Sun.COM 
103*9781SMoriah.Waterland@Sun.COM 	if (ept->volno > nparts)
104*9781SMoriah.Waterland@Sun.COM 		nparts++;
105*9781SMoriah.Waterland@Sun.COM 
106*9781SMoriah.Waterland@Sun.COM 	/*
107*9781SMoriah.Waterland@Sun.COM 	 * Generate local (delivered source) paths for files
108*9781SMoriah.Waterland@Sun.COM 	 * which need them so that the install routine will know
109*9781SMoriah.Waterland@Sun.COM 	 * where to get the file from the package. Note that we
110*9781SMoriah.Waterland@Sun.COM 	 * do not resolve path environment variables here since
111*9781SMoriah.Waterland@Sun.COM 	 * they won't be resolved in the reloc directory.
112*9781SMoriah.Waterland@Sun.COM 	 */
113*9781SMoriah.Waterland@Sun.COM 	if ((mapflag > 1) && strchr("fve", ept->ftype)) {
114*9781SMoriah.Waterland@Sun.COM 		if (ept->ainfo.local == NULL) {
115*9781SMoriah.Waterland@Sun.COM 			source[0] = '~';
116*9781SMoriah.Waterland@Sun.COM 			(void) strcpy(&source[1], ept->path);
117*9781SMoriah.Waterland@Sun.COM 			ept->ainfo.local = pathdup(source);
118*9781SMoriah.Waterland@Sun.COM 			*server_local = ept->ainfo.local;
119*9781SMoriah.Waterland@Sun.COM 			*client_local = ept->ainfo.local;
120*9781SMoriah.Waterland@Sun.COM 
121*9781SMoriah.Waterland@Sun.COM 			local_duped = 1;
122*9781SMoriah.Waterland@Sun.COM 		}
123*9781SMoriah.Waterland@Sun.COM 	}
124*9781SMoriah.Waterland@Sun.COM 
125*9781SMoriah.Waterland@Sun.COM 	/*
126*9781SMoriah.Waterland@Sun.COM 	 * Evaluate the destination path based upon available
127*9781SMoriah.Waterland@Sun.COM 	 * environment, then produce a client-relative and
128*9781SMoriah.Waterland@Sun.COM 	 * server-relative canonized path.
129*9781SMoriah.Waterland@Sun.COM 	 */
130*9781SMoriah.Waterland@Sun.COM 	if (mapflag && (ept->ftype != 'i')) {
131*9781SMoriah.Waterland@Sun.COM 		mappath(getmapmode(), ept->path); /* evaluate variables */
132*9781SMoriah.Waterland@Sun.COM 		canonize(ept->path);	/* Fix path as necessary. */
133*9781SMoriah.Waterland@Sun.COM 
134*9781SMoriah.Waterland@Sun.COM 		(void) eval_path(server_path,
135*9781SMoriah.Waterland@Sun.COM 		    client_path,
136*9781SMoriah.Waterland@Sun.COM 		    map_path,
137*9781SMoriah.Waterland@Sun.COM 		    ept->path);
138*9781SMoriah.Waterland@Sun.COM 		path_duped = 1;	/* eval_path dup's it */
139*9781SMoriah.Waterland@Sun.COM 		ept->path = *server_path;	/* default */
140*9781SMoriah.Waterland@Sun.COM 	}
141*9781SMoriah.Waterland@Sun.COM 
142*9781SMoriah.Waterland@Sun.COM 	/*
143*9781SMoriah.Waterland@Sun.COM 	 * Deal with source for hard and soft links.
144*9781SMoriah.Waterland@Sun.COM 	 */
145*9781SMoriah.Waterland@Sun.COM 	if (strchr("sl", ept->ftype)) {
146*9781SMoriah.Waterland@Sun.COM 		if (mapflag) {
147*9781SMoriah.Waterland@Sun.COM 			mappath(getmapmode(), ept->ainfo.local);
148*9781SMoriah.Waterland@Sun.COM 			if (!RELATIVE(ept->ainfo.local)) {
149*9781SMoriah.Waterland@Sun.COM 				canonize(ept->ainfo.local);
150*9781SMoriah.Waterland@Sun.COM 
151*9781SMoriah.Waterland@Sun.COM 				/* check for hard link */
152*9781SMoriah.Waterland@Sun.COM 				if (ept->ftype == 'l') {
153*9781SMoriah.Waterland@Sun.COM 					(void) eval_path(
154*9781SMoriah.Waterland@Sun.COM 					    server_local,
155*9781SMoriah.Waterland@Sun.COM 					    client_local,
156*9781SMoriah.Waterland@Sun.COM 					    NULL,
157*9781SMoriah.Waterland@Sun.COM 					    ept->ainfo.local);
158*9781SMoriah.Waterland@Sun.COM 					local_duped = 1;
159*9781SMoriah.Waterland@Sun.COM 
160*9781SMoriah.Waterland@Sun.COM 					/* Default to server. */
161*9781SMoriah.Waterland@Sun.COM 					ept->ainfo.local = *server_local;
162*9781SMoriah.Waterland@Sun.COM 				}
163*9781SMoriah.Waterland@Sun.COM 			}
164*9781SMoriah.Waterland@Sun.COM 		}
165*9781SMoriah.Waterland@Sun.COM 	}
166*9781SMoriah.Waterland@Sun.COM 
167*9781SMoriah.Waterland@Sun.COM 	/*
168*9781SMoriah.Waterland@Sun.COM 	 * For the paths (both source and target) that were too mundane to
169*9781SMoriah.Waterland@Sun.COM 	 * have been copied into dup space yet, do that.
170*9781SMoriah.Waterland@Sun.COM 	 */
171*9781SMoriah.Waterland@Sun.COM 	if (!path_duped) {
172*9781SMoriah.Waterland@Sun.COM 		*server_path = pathdup(ept->path);
173*9781SMoriah.Waterland@Sun.COM 		*client_path = *server_path;
174*9781SMoriah.Waterland@Sun.COM 		ept->path = *server_path;
175*9781SMoriah.Waterland@Sun.COM 
176*9781SMoriah.Waterland@Sun.COM 		path_duped = 1;
177*9781SMoriah.Waterland@Sun.COM 	}
178*9781SMoriah.Waterland@Sun.COM 	if (ept->ainfo.local != NULL)
179*9781SMoriah.Waterland@Sun.COM 		if (!local_duped) {
180*9781SMoriah.Waterland@Sun.COM 			*server_local = pathdup(ept->ainfo.local);
181*9781SMoriah.Waterland@Sun.COM 			ept->ainfo.local = *server_local;
182*9781SMoriah.Waterland@Sun.COM 			*client_local = ept->ainfo.local;
183*9781SMoriah.Waterland@Sun.COM 
184*9781SMoriah.Waterland@Sun.COM 		local_duped = 1;
185*9781SMoriah.Waterland@Sun.COM 	}
186*9781SMoriah.Waterland@Sun.COM 
187*9781SMoriah.Waterland@Sun.COM 	return (0);
188*9781SMoriah.Waterland@Sun.COM }
189*9781SMoriah.Waterland@Sun.COM 
190*9781SMoriah.Waterland@Sun.COM /*
191*9781SMoriah.Waterland@Sun.COM  * This function reads the prototype file and returns a pointer to a list of
192*9781SMoriah.Waterland@Sun.COM  * struct cfent representing the contents of that file.
193*9781SMoriah.Waterland@Sun.COM  */
194*9781SMoriah.Waterland@Sun.COM /*ARGSUSED*/
195*9781SMoriah.Waterland@Sun.COM struct cfent **
procmap(VFP_T * vfp,int mapflag,char * ir)196*9781SMoriah.Waterland@Sun.COM procmap(VFP_T *vfp, int mapflag, char *ir)
197*9781SMoriah.Waterland@Sun.COM {
198*9781SMoriah.Waterland@Sun.COM 	struct cfent	*ept = (struct cfent *)NULL;
199*9781SMoriah.Waterland@Sun.COM 	struct cfent	map_entry;
200*9781SMoriah.Waterland@Sun.COM 	struct cfent	**ept_ptr;
201*9781SMoriah.Waterland@Sun.COM 	int	i;
202*9781SMoriah.Waterland@Sun.COM 	int	n;
203*9781SMoriah.Waterland@Sun.COM 	int	nc;
204*9781SMoriah.Waterland@Sun.COM 	static char *server_local, *client_local;
205*9781SMoriah.Waterland@Sun.COM 	static char *server_path, *client_path, *map_path;
206*9781SMoriah.Waterland@Sun.COM 
207*9781SMoriah.Waterland@Sun.COM 	procinit();
208*9781SMoriah.Waterland@Sun.COM 
209*9781SMoriah.Waterland@Sun.COM 	space = ar_create(EPTMALLOC, (unsigned)sizeof (struct cfent),
210*9781SMoriah.Waterland@Sun.COM 	    "prototype object");
211*9781SMoriah.Waterland@Sun.COM 	if (space == -1) {
212*9781SMoriah.Waterland@Sun.COM 		progerr(gettext(ERR_MEMORY));
213*9781SMoriah.Waterland@Sun.COM 		return (NULL);
214*9781SMoriah.Waterland@Sun.COM 	}
215*9781SMoriah.Waterland@Sun.COM 
216*9781SMoriah.Waterland@Sun.COM 	nc = cl_getn();
217*9781SMoriah.Waterland@Sun.COM 	for (;;) {
218*9781SMoriah.Waterland@Sun.COM 		/* Clear the buffer. */
219*9781SMoriah.Waterland@Sun.COM 		(void) memset(&map_entry, '\000', sizeof (struct cfent));
220*9781SMoriah.Waterland@Sun.COM 
221*9781SMoriah.Waterland@Sun.COM 		n = gpkgmapvfp(&map_entry, vfp);
222*9781SMoriah.Waterland@Sun.COM 
223*9781SMoriah.Waterland@Sun.COM 		if (n == 0)
224*9781SMoriah.Waterland@Sun.COM 			break; /* no more entries in pkgmap */
225*9781SMoriah.Waterland@Sun.COM 		else if (n < 0) {
226*9781SMoriah.Waterland@Sun.COM 			char	*errstr = getErrstr();
227*9781SMoriah.Waterland@Sun.COM 			progerr(gettext("bad entry read in pkgmap"));
228*9781SMoriah.Waterland@Sun.COM 			logerr(gettext("pathname=%s"),
229*9781SMoriah.Waterland@Sun.COM 				(ept && ept->path && *ept->path) ?
230*9781SMoriah.Waterland@Sun.COM 				ept->path : "Unknown");
231*9781SMoriah.Waterland@Sun.COM 			logerr(gettext("problem=%s"),
232*9781SMoriah.Waterland@Sun.COM 			    (errstr && *errstr) ? errstr : "Unknown");
233*9781SMoriah.Waterland@Sun.COM 			return (NULL);
234*9781SMoriah.Waterland@Sun.COM 		}
235*9781SMoriah.Waterland@Sun.COM 
236*9781SMoriah.Waterland@Sun.COM 		/*
237*9781SMoriah.Waterland@Sun.COM 		 * A valid entry was found in the map, so allocate an
238*9781SMoriah.Waterland@Sun.COM 		 * official record.
239*9781SMoriah.Waterland@Sun.COM 		 */
240*9781SMoriah.Waterland@Sun.COM 		ept_ptr = (struct cfent **)ar_next_avail(space);
241*9781SMoriah.Waterland@Sun.COM 		if (ept_ptr == NULL || *ept_ptr == NULL) {
242*9781SMoriah.Waterland@Sun.COM 			progerr(gettext(ERR_MEMORY));
243*9781SMoriah.Waterland@Sun.COM 			return (NULL);
244*9781SMoriah.Waterland@Sun.COM 		}
245*9781SMoriah.Waterland@Sun.COM 
246*9781SMoriah.Waterland@Sun.COM 		ept = *ept_ptr;
247*9781SMoriah.Waterland@Sun.COM 
248*9781SMoriah.Waterland@Sun.COM 		/* Transfer what we just read in. */
249*9781SMoriah.Waterland@Sun.COM 		(void) memcpy(ept, &map_entry, sizeof (struct cfent));
250*9781SMoriah.Waterland@Sun.COM 
251*9781SMoriah.Waterland@Sun.COM 		if (procassign(ept, &server_local, &client_local,
252*9781SMoriah.Waterland@Sun.COM 		    &server_path, &client_path, &map_path,
253*9781SMoriah.Waterland@Sun.COM 		    mapflag, nc)) {
254*9781SMoriah.Waterland@Sun.COM 			/* It didn't take. */
255*9781SMoriah.Waterland@Sun.COM 			(void) ar_delete(space, eptnum);
256*9781SMoriah.Waterland@Sun.COM 			continue;
257*9781SMoriah.Waterland@Sun.COM 		}
258*9781SMoriah.Waterland@Sun.COM 
259*9781SMoriah.Waterland@Sun.COM 		eptnum++;
260*9781SMoriah.Waterland@Sun.COM 	}
261*9781SMoriah.Waterland@Sun.COM 
262*9781SMoriah.Waterland@Sun.COM 	/* setup a pointer array to point to malloc'd entries space */
263*9781SMoriah.Waterland@Sun.COM 	eptlist = (struct cfent **)ar_get_head(space);
264*9781SMoriah.Waterland@Sun.COM 	if (eptlist == NULL) {
265*9781SMoriah.Waterland@Sun.COM 		progerr(gettext(ERR_MEMORY));
266*9781SMoriah.Waterland@Sun.COM 		return (NULL);
267*9781SMoriah.Waterland@Sun.COM 	}
268*9781SMoriah.Waterland@Sun.COM 
269*9781SMoriah.Waterland@Sun.COM 	(void) sortentry(-1);
270*9781SMoriah.Waterland@Sun.COM 	for (i = 0; i < eptnum; /* void */) {
271*9781SMoriah.Waterland@Sun.COM 		if (!sortentry(i))
272*9781SMoriah.Waterland@Sun.COM 			i++;
273*9781SMoriah.Waterland@Sun.COM 	}
274*9781SMoriah.Waterland@Sun.COM 	return (errflg ? NULL : eptlist);
275*9781SMoriah.Waterland@Sun.COM }
276*9781SMoriah.Waterland@Sun.COM 
277*9781SMoriah.Waterland@Sun.COM /*
278*9781SMoriah.Waterland@Sun.COM  * This function sorts the final list of cfent entries. If index = -1, the
279*9781SMoriah.Waterland@Sun.COM  * function is initialized. index = 0 doesn't get us anywhere because this
280*9781SMoriah.Waterland@Sun.COM  * sorts against index-1. Positive natural index values are compared and
281*9781SMoriah.Waterland@Sun.COM  * sorted into the array appropriately. Yes, it does seem we should use a
282*9781SMoriah.Waterland@Sun.COM  * quicksort on the whole array or something. The apparent reason for taking
283*9781SMoriah.Waterland@Sun.COM  * this approach is that there are enough special considerations to be
284*9781SMoriah.Waterland@Sun.COM  * applied to each package object that inserting them one-by-one doesn't cost
285*9781SMoriah.Waterland@Sun.COM  * that much.
286*9781SMoriah.Waterland@Sun.COM  */
287*9781SMoriah.Waterland@Sun.COM static int
sortentry(int index)288*9781SMoriah.Waterland@Sun.COM sortentry(int index)
289*9781SMoriah.Waterland@Sun.COM {
290*9781SMoriah.Waterland@Sun.COM 	struct cfent *ept, *ept_i;
291*9781SMoriah.Waterland@Sun.COM 	static int last = 0;
292*9781SMoriah.Waterland@Sun.COM 	int	i, n, j;
293*9781SMoriah.Waterland@Sun.COM 	int	upper, lower;
294*9781SMoriah.Waterland@Sun.COM 
295*9781SMoriah.Waterland@Sun.COM 	if (index == 0)
296*9781SMoriah.Waterland@Sun.COM 		return (0);
297*9781SMoriah.Waterland@Sun.COM 	else if (index < 0) {
298*9781SMoriah.Waterland@Sun.COM 		last = 0;
299*9781SMoriah.Waterland@Sun.COM 		return (0);
300*9781SMoriah.Waterland@Sun.COM 	}
301*9781SMoriah.Waterland@Sun.COM 
302*9781SMoriah.Waterland@Sun.COM 	/*
303*9781SMoriah.Waterland@Sun.COM 	 * Based on the index, this is the package object we're going to
304*9781SMoriah.Waterland@Sun.COM 	 * review. It may stay where it is or it may be repositioned in the
305*9781SMoriah.Waterland@Sun.COM 	 * array.
306*9781SMoriah.Waterland@Sun.COM 	 */
307*9781SMoriah.Waterland@Sun.COM 	ept = eptlist[index];
308*9781SMoriah.Waterland@Sun.COM 
309*9781SMoriah.Waterland@Sun.COM 	/* quick comparison optimization for pre-sorted arrays */
310*9781SMoriah.Waterland@Sun.COM 	if (strcmp(ept->path, eptlist[index-1]->path) > 0) {
311*9781SMoriah.Waterland@Sun.COM 		/* do nothing */
312*9781SMoriah.Waterland@Sun.COM 		last = index-1;
313*9781SMoriah.Waterland@Sun.COM 		return (0);
314*9781SMoriah.Waterland@Sun.COM 	}
315*9781SMoriah.Waterland@Sun.COM 
316*9781SMoriah.Waterland@Sun.COM 	lower = 0;		/* lower bound of the unsorted elements */
317*9781SMoriah.Waterland@Sun.COM 	upper = index;		/* upper bound */
318*9781SMoriah.Waterland@Sun.COM 	i = last;
319*9781SMoriah.Waterland@Sun.COM 	do {
320*9781SMoriah.Waterland@Sun.COM 		/*
321*9781SMoriah.Waterland@Sun.COM 		 * NOTE: This does a binary sort on path. There are lots of
322*9781SMoriah.Waterland@Sun.COM 		 * other worthy items in the array, but path is the key into
323*9781SMoriah.Waterland@Sun.COM 		 * the package database.
324*9781SMoriah.Waterland@Sun.COM 		 */
325*9781SMoriah.Waterland@Sun.COM 		ept_i = eptlist[i];
326*9781SMoriah.Waterland@Sun.COM 
327*9781SMoriah.Waterland@Sun.COM 		n = strcmp(ept->path, ept_i->path);
328*9781SMoriah.Waterland@Sun.COM 		if (n == 0) {
329*9781SMoriah.Waterland@Sun.COM 			if (!ckdup(ept, ept_i)) {
330*9781SMoriah.Waterland@Sun.COM 				progerr(gettext(ERR_DUPPATH),
331*9781SMoriah.Waterland@Sun.COM 				    ept->path);
332*9781SMoriah.Waterland@Sun.COM 				errflg++;
333*9781SMoriah.Waterland@Sun.COM 			}
334*9781SMoriah.Waterland@Sun.COM 			/* remove the entry at index */
335*9781SMoriah.Waterland@Sun.COM 			(void) ar_delete(space, index);
336*9781SMoriah.Waterland@Sun.COM 
337*9781SMoriah.Waterland@Sun.COM 			eptnum--;
338*9781SMoriah.Waterland@Sun.COM 			return (1);	/* Use this index again. */
339*9781SMoriah.Waterland@Sun.COM 		} else if (n < 0) {
340*9781SMoriah.Waterland@Sun.COM 			/*
341*9781SMoriah.Waterland@Sun.COM 			 * The path of interest is smaller than the path
342*9781SMoriah.Waterland@Sun.COM 			 * under test. Move down array using the method of
343*9781SMoriah.Waterland@Sun.COM 			 * division
344*9781SMoriah.Waterland@Sun.COM 			 */
345*9781SMoriah.Waterland@Sun.COM 			upper = i;
346*9781SMoriah.Waterland@Sun.COM 			i = lower + (upper-lower)/2;
347*9781SMoriah.Waterland@Sun.COM 		} else {
348*9781SMoriah.Waterland@Sun.COM 			/* Move up array */
349*9781SMoriah.Waterland@Sun.COM 			lower = i+1;
350*9781SMoriah.Waterland@Sun.COM 			i = upper - (upper-lower)/2 - 1;
351*9781SMoriah.Waterland@Sun.COM 		}
352*9781SMoriah.Waterland@Sun.COM 	} while (upper != lower);
353*9781SMoriah.Waterland@Sun.COM 	last = i = upper;
354*9781SMoriah.Waterland@Sun.COM 
355*9781SMoriah.Waterland@Sun.COM 	/* expand to insert at i */
356*9781SMoriah.Waterland@Sun.COM 	for (j = index; j > i; j--)
357*9781SMoriah.Waterland@Sun.COM 		eptlist[j] = eptlist[j-1];
358*9781SMoriah.Waterland@Sun.COM 
359*9781SMoriah.Waterland@Sun.COM 	eptlist[i] = ept;
360*9781SMoriah.Waterland@Sun.COM 
361*9781SMoriah.Waterland@Sun.COM 	return (0);
362*9781SMoriah.Waterland@Sun.COM }
363*9781SMoriah.Waterland@Sun.COM 
364*9781SMoriah.Waterland@Sun.COM /*
365*9781SMoriah.Waterland@Sun.COM  * Check duplicate entries in the package object list. If it's a directory,
366*9781SMoriah.Waterland@Sun.COM  * this just merges them, if not, it returns a 0 to force further processing.
367*9781SMoriah.Waterland@Sun.COM  */
368*9781SMoriah.Waterland@Sun.COM static int
ckdup(struct cfent * ept1,struct cfent * ept2)369*9781SMoriah.Waterland@Sun.COM ckdup(struct cfent *ept1, struct cfent *ept2)
370*9781SMoriah.Waterland@Sun.COM {
371*9781SMoriah.Waterland@Sun.COM 	/* ept2 will be modified to contain "merged" entries */
372*9781SMoriah.Waterland@Sun.COM 
373*9781SMoriah.Waterland@Sun.COM 	if (!strchr("?dx", ept1->ftype))
374*9781SMoriah.Waterland@Sun.COM 		return (0);
375*9781SMoriah.Waterland@Sun.COM 
376*9781SMoriah.Waterland@Sun.COM 	if (!strchr("?dx", ept2->ftype))
377*9781SMoriah.Waterland@Sun.COM 		return (0);
378*9781SMoriah.Waterland@Sun.COM 
379*9781SMoriah.Waterland@Sun.COM 	if (ept2->ainfo.mode == BADMODE)
380*9781SMoriah.Waterland@Sun.COM 		ept2->ainfo.mode = ept1->ainfo.mode;
381*9781SMoriah.Waterland@Sun.COM 	if ((ept1->ainfo.mode != ept2->ainfo.mode) &&
382*9781SMoriah.Waterland@Sun.COM 	    (ept1->ainfo.mode != BADMODE))
383*9781SMoriah.Waterland@Sun.COM 		return (0);
384*9781SMoriah.Waterland@Sun.COM 
385*9781SMoriah.Waterland@Sun.COM 	if (strcmp(ept2->ainfo.owner, "?") == 0)
386*9781SMoriah.Waterland@Sun.COM 		(void) strcpy(ept2->ainfo.owner, ept1->ainfo.owner);
387*9781SMoriah.Waterland@Sun.COM 	if (strcmp(ept1->ainfo.owner, ept2->ainfo.owner) &&
388*9781SMoriah.Waterland@Sun.COM 	    strcmp(ept1->ainfo.owner, "?"))
389*9781SMoriah.Waterland@Sun.COM 		return (0);
390*9781SMoriah.Waterland@Sun.COM 
391*9781SMoriah.Waterland@Sun.COM 	if (strcmp(ept2->ainfo.group, "?") == 0)
392*9781SMoriah.Waterland@Sun.COM 		(void) strcpy(ept2->ainfo.group, ept1->ainfo.group);
393*9781SMoriah.Waterland@Sun.COM 	if (strcmp(ept1->ainfo.group, ept2->ainfo.group) &&
394*9781SMoriah.Waterland@Sun.COM 	    strcmp(ept1->ainfo.group, "?"))
395*9781SMoriah.Waterland@Sun.COM 		return (0);
396*9781SMoriah.Waterland@Sun.COM 
397*9781SMoriah.Waterland@Sun.COM 	if (ept1->pinfo) {
398*9781SMoriah.Waterland@Sun.COM 		ept2->npkgs = ept1->npkgs;
399*9781SMoriah.Waterland@Sun.COM 		ept2->pinfo = ept1->pinfo;
400*9781SMoriah.Waterland@Sun.COM 	}
401*9781SMoriah.Waterland@Sun.COM 
402*9781SMoriah.Waterland@Sun.COM 	return (1);
403*9781SMoriah.Waterland@Sun.COM }
404