xref: /titanic_44/usr/src/lib/libpkg/common/srchcfile.c (revision 5c51f1241dbbdf2656d0e10011981411ed0c9673)
1*5c51f124SMoriah Waterland /*
2*5c51f124SMoriah Waterland  * CDDL HEADER START
3*5c51f124SMoriah Waterland  *
4*5c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
5*5c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
6*5c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
7*5c51f124SMoriah Waterland  *
8*5c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
10*5c51f124SMoriah Waterland  * See the License for the specific language governing permissions
11*5c51f124SMoriah Waterland  * and limitations under the License.
12*5c51f124SMoriah Waterland  *
13*5c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
14*5c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
16*5c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
17*5c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5c51f124SMoriah Waterland  *
19*5c51f124SMoriah Waterland  * CDDL HEADER END
20*5c51f124SMoriah Waterland  */
21*5c51f124SMoriah Waterland 
22*5c51f124SMoriah Waterland /*
23*5c51f124SMoriah Waterland  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*5c51f124SMoriah Waterland  * Use is subject to license terms.
25*5c51f124SMoriah Waterland  */
26*5c51f124SMoriah Waterland 
27*5c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28*5c51f124SMoriah Waterland /* All Rights Reserved */
29*5c51f124SMoriah Waterland 
30*5c51f124SMoriah Waterland 
31*5c51f124SMoriah Waterland 
32*5c51f124SMoriah Waterland #include <stdio.h>
33*5c51f124SMoriah Waterland #include <limits.h>
34*5c51f124SMoriah Waterland #include <stdlib.h>
35*5c51f124SMoriah Waterland #include <string.h>
36*5c51f124SMoriah Waterland #include <strings.h>
37*5c51f124SMoriah Waterland #include <ctype.h>
38*5c51f124SMoriah Waterland #include <sys/types.h>
39*5c51f124SMoriah Waterland #include <libintl.h>
40*5c51f124SMoriah Waterland #include "pkglib.h"
41*5c51f124SMoriah Waterland #include "pkgstrct.h"
42*5c51f124SMoriah Waterland #include "pkglocale.h"
43*5c51f124SMoriah Waterland #include "pkglibmsgs.h"
44*5c51f124SMoriah Waterland 
45*5c51f124SMoriah Waterland /*
46*5c51f124SMoriah Waterland  * Forward declarations
47*5c51f124SMoriah Waterland  */
48*5c51f124SMoriah Waterland 
49*5c51f124SMoriah Waterland static void	findend(char **cp);
50*5c51f124SMoriah Waterland static int	getend(char **cp);
51*5c51f124SMoriah Waterland static int	getstr(char **cp, int n, char *str, int separator[]);
52*5c51f124SMoriah Waterland 
53*5c51f124SMoriah Waterland /* from gpkgmap.c */
54*5c51f124SMoriah Waterland int	getnumvfp(char **cp, int base, long *d, long bad);
55*5c51f124SMoriah Waterland int	getlnumvfp(char **cp, int base, fsblkcnt_t *d, long bad);
56*5c51f124SMoriah Waterland 
57*5c51f124SMoriah Waterland /*
58*5c51f124SMoriah Waterland  * Module globals
59*5c51f124SMoriah Waterland  */
60*5c51f124SMoriah Waterland 
61*5c51f124SMoriah Waterland static char	lpath[PATH_MAX];	/* for ept->path */
62*5c51f124SMoriah Waterland static char	mylocal[PATH_MAX];	/* for ept->ainfo.local */
63*5c51f124SMoriah Waterland static int	decisionTableInit = 0;
64*5c51f124SMoriah Waterland 
65*5c51f124SMoriah Waterland /*
66*5c51f124SMoriah Waterland  * These arrays must be indexable by an unsigned char.
67*5c51f124SMoriah Waterland  */
68*5c51f124SMoriah Waterland 
69*5c51f124SMoriah Waterland static int	ISPKGPATHSEP[UCHAR_MAX+1];
70*5c51f124SMoriah Waterland static int	ISWORDSEP[UCHAR_MAX+1];
71*5c51f124SMoriah Waterland static int	ISPKGNAMESEP[UCHAR_MAX+1];
72*5c51f124SMoriah Waterland 
73*5c51f124SMoriah Waterland /*
74*5c51f124SMoriah Waterland  * Name:	WRITEDATA
75*5c51f124SMoriah Waterland  * Description:	write out data to VFP_T given start and end pointers
76*5c51f124SMoriah Waterland  * Arguments:	VFP - (VFP_T *) - [RO, *RW]
77*5c51f124SMoriah Waterland  *			Contents file VFP to narrow search on
78*5c51f124SMoriah Waterland  *		FIRSTPOS - (char *) - [RO, *RO]
79*5c51f124SMoriah Waterland  *			Pointer to first byte to write out
80*5c51f124SMoriah Waterland  *		LASTPOS - (char *) - [RO, *RO]
81*5c51f124SMoriah Waterland  *			Pointer to last byte to write out
82*5c51f124SMoriah Waterland  */
83*5c51f124SMoriah Waterland 
84*5c51f124SMoriah Waterland #define	WRITEDATA(VFP, FIRSTPOS, LASTPOS)				\
85*5c51f124SMoriah Waterland 	{								\
86*5c51f124SMoriah Waterland 		ssize_t XXlenXX;					\
87*5c51f124SMoriah Waterland 		/* compute number of bytes skipped */			\
88*5c51f124SMoriah Waterland 		XXlenXX = (ptrdiff_t)(LASTPOS) - (ptrdiff_t)(FIRSTPOS);	\
89*5c51f124SMoriah Waterland 		/* write the bytes out */				\
90*5c51f124SMoriah Waterland 		vfpPutBytes((VFP), (FIRSTPOS), XXlenXX);		\
91*5c51f124SMoriah Waterland 	}
92*5c51f124SMoriah Waterland 
93*5c51f124SMoriah Waterland /*
94*5c51f124SMoriah Waterland  * Name:	COPYPATH
95*5c51f124SMoriah Waterland  * Description:	copy path limiting size to destination capacity
96*5c51f124SMoriah Waterland  * Arguments:	DEST - (char []) - [RW]
97*5c51f124SMoriah Waterland  *		SRC - (char *) - [RO, *RO]
98*5c51f124SMoriah Waterland  *			Pointer to first byte of path to copy
99*5c51f124SMoriah Waterland  *		LEN - (int) - [RO]
100*5c51f124SMoriah Waterland  *			Number of bytes to copy
101*5c51f124SMoriah Waterland  */
102*5c51f124SMoriah Waterland 
103*5c51f124SMoriah Waterland #define	COPYPATH(DEST, SRC, LEN)					\
104*5c51f124SMoriah Waterland 	{								\
105*5c51f124SMoriah Waterland 		/* assure return path does not overflow */		\
106*5c51f124SMoriah Waterland 		if ((LEN) > sizeof ((DEST))) {				\
107*5c51f124SMoriah Waterland 			(LEN) = sizeof ((DEST))-1;			\
108*5c51f124SMoriah Waterland 		}							\
109*5c51f124SMoriah Waterland 		/* copy return path to local storage */			\
110*5c51f124SMoriah Waterland 		(void) memcpy((DEST), (SRC), (LEN));			\
111*5c51f124SMoriah Waterland 		(DEST)[(LEN)] = '\0';					\
112*5c51f124SMoriah Waterland 	}
113*5c51f124SMoriah Waterland 
114*5c51f124SMoriah Waterland /*
115*5c51f124SMoriah Waterland  * Name:	narrowSearch
116*5c51f124SMoriah Waterland  * Description:	narrow the search location for a specified path
117*5c51f124SMoriah Waterland  *		The contents and package map files are always sorted by path.
118*5c51f124SMoriah Waterland  *		This function is given a target path to search for given the
119*5c51f124SMoriah Waterland  *		current location in a contents file. It is assured that the
120*5c51f124SMoriah Waterland  *		target path has not been searched for yet in the contents file
121*5c51f124SMoriah Waterland  *		so the current location in the contents file is guaranteed to
122*5c51f124SMoriah Waterland  *		be less than the location of the target path (if present).
123*5c51f124SMoriah Waterland  *		Given this employ a binary search to speed up the search for
124*5c51f124SMoriah Waterland  *		the path nearest to a specified target path.
125*5c51f124SMoriah Waterland  * Arguments:	a_vfp - (VFP_T *) - [RO, *RW]
126*5c51f124SMoriah Waterland  *			Contents file VFP to narrow search on
127*5c51f124SMoriah Waterland  *		a_path - (char *) - [RO, *RO]
128*5c51f124SMoriah Waterland  *			Pointer to path to search for
129*5c51f124SMoriah Waterland  *		a_pathLen - (size_t) - [RO]
130*5c51f124SMoriah Waterland  *			Length of string (a_path)
131*5c51f124SMoriah Waterland  * Returns:	char *	- pointer to first byte of entry in contents file that
132*5c51f124SMoriah Waterland  *			is guaranteed to be the closest match to the specified
133*5c51f124SMoriah Waterland  *			a_path without being "greater than" the path.
134*5c51f124SMoriah Waterland  *			== (char *)NULL if no entry found
135*5c51f124SMoriah Waterland  */
136*5c51f124SMoriah Waterland 
137*5c51f124SMoriah Waterland static char *
138*5c51f124SMoriah Waterland narrowSearch(VFP_T *a_vfp, char *a_path, size_t a_pathLen)
139*5c51f124SMoriah Waterland {
140*5c51f124SMoriah Waterland 	char	*phigh;
141*5c51f124SMoriah Waterland 	char	*plow;
142*5c51f124SMoriah Waterland 	char	*pmid;
143*5c51f124SMoriah Waterland 	int	n;
144*5c51f124SMoriah Waterland 	size_t	plen;
145*5c51f124SMoriah Waterland 
146*5c51f124SMoriah Waterland 	/* if no path to compare, start at beginning */
147*5c51f124SMoriah Waterland 
148*5c51f124SMoriah Waterland 	if ((a_path == (char *)NULL) || (*a_path == '\0')) {
149*5c51f124SMoriah Waterland 		return ((char *)NULL);
150*5c51f124SMoriah Waterland 	}
151*5c51f124SMoriah Waterland 
152*5c51f124SMoriah Waterland 	/* if the contents file is empty, resort to sequential search */
153*5c51f124SMoriah Waterland 
154*5c51f124SMoriah Waterland 	if (vfpGetBytesRemaining(a_vfp) <= 1) {
155*5c51f124SMoriah Waterland 		return ((char *)NULL);
156*5c51f124SMoriah Waterland 	}
157*5c51f124SMoriah Waterland 
158*5c51f124SMoriah Waterland 	/*
159*5c51f124SMoriah Waterland 	 * test against first path - if the path specified is less than the
160*5c51f124SMoriah Waterland 	 * first path in the contents file, then the path can be inserted
161*5c51f124SMoriah Waterland 	 * before the first entry in the contents file.
162*5c51f124SMoriah Waterland 	 */
163*5c51f124SMoriah Waterland 
164*5c51f124SMoriah Waterland 	/* locate start of first line */
165*5c51f124SMoriah Waterland 
166*5c51f124SMoriah Waterland 	plow = vfpGetCurrCharPtr(a_vfp);
167*5c51f124SMoriah Waterland 	pmid = plow;
168*5c51f124SMoriah Waterland 
169*5c51f124SMoriah Waterland 	/* if first path not absolute, resort to sequential search */
170*5c51f124SMoriah Waterland 
171*5c51f124SMoriah Waterland 	if (*pmid != '/') {
172*5c51f124SMoriah Waterland 		return ((char *)NULL);
173*5c51f124SMoriah Waterland 	}
174*5c51f124SMoriah Waterland 
175*5c51f124SMoriah Waterland 	/* find end of path */
176*5c51f124SMoriah Waterland 
177*5c51f124SMoriah Waterland 	while (ISPKGPATHSEP[(int)*pmid] == 0) {
178*5c51f124SMoriah Waterland 		pmid++;
179*5c51f124SMoriah Waterland 	}
180*5c51f124SMoriah Waterland 
181*5c51f124SMoriah Waterland 	/* determine length of path */
182*5c51f124SMoriah Waterland 
183*5c51f124SMoriah Waterland 	plen = (ptrdiff_t)pmid - (ptrdiff_t)plow;
184*5c51f124SMoriah Waterland 
185*5c51f124SMoriah Waterland 	/* compare target path with current path */
186*5c51f124SMoriah Waterland 
187*5c51f124SMoriah Waterland 	n = strncmp(a_path, plow, plen);
188*5c51f124SMoriah Waterland 	if (n == 0) {
189*5c51f124SMoriah Waterland 		/* if lengths same exact match return position found */
190*5c51f124SMoriah Waterland 		if (a_pathLen == plen) {
191*5c51f124SMoriah Waterland 			return (plow);
192*5c51f124SMoriah Waterland 		}
193*5c51f124SMoriah Waterland 		/* not exact match - a_path > pm */
194*5c51f124SMoriah Waterland 		n = a_pathLen;
195*5c51f124SMoriah Waterland 	}
196*5c51f124SMoriah Waterland 
197*5c51f124SMoriah Waterland 	/* return if target is less than or equal to first entry */
198*5c51f124SMoriah Waterland 
199*5c51f124SMoriah Waterland 	if (n <= 0) {
200*5c51f124SMoriah Waterland 		return (plow);
201*5c51f124SMoriah Waterland 	}
202*5c51f124SMoriah Waterland 
203*5c51f124SMoriah Waterland 	/*
204*5c51f124SMoriah Waterland 	 * test against last path - if the path specified is greater than the
205*5c51f124SMoriah Waterland 	 * last path in the contents file, then the path can be appended after
206*5c51f124SMoriah Waterland 	 * the last entry in the contents file.
207*5c51f124SMoriah Waterland 	 */
208*5c51f124SMoriah Waterland 
209*5c51f124SMoriah Waterland 	/* locate start of last line */
210*5c51f124SMoriah Waterland 
211*5c51f124SMoriah Waterland 	plow = vfpGetCurrCharPtr(a_vfp);
212*5c51f124SMoriah Waterland 	pmid = vfpGetLastCharPtr(a_vfp);
213*5c51f124SMoriah Waterland 
214*5c51f124SMoriah Waterland 	while ((pmid > plow) && (!((pmid[0] == '/') && (pmid[-1] == '\n')))) {
215*5c51f124SMoriah Waterland 		pmid--;
216*5c51f124SMoriah Waterland 	}
217*5c51f124SMoriah Waterland 
218*5c51f124SMoriah Waterland 	/* if absolute path, do comparison */
219*5c51f124SMoriah Waterland 
220*5c51f124SMoriah Waterland 	if ((pmid > plow) && (*pmid == '/')) {
221*5c51f124SMoriah Waterland 		plow = pmid;
222*5c51f124SMoriah Waterland 
223*5c51f124SMoriah Waterland 		/* find end of path */
224*5c51f124SMoriah Waterland 
225*5c51f124SMoriah Waterland 		while (ISPKGPATHSEP[(int)*pmid] == 0) {
226*5c51f124SMoriah Waterland 			pmid++;
227*5c51f124SMoriah Waterland 		}
228*5c51f124SMoriah Waterland 
229*5c51f124SMoriah Waterland 		/* determine length of path */
230*5c51f124SMoriah Waterland 
231*5c51f124SMoriah Waterland 		plen = (ptrdiff_t)pmid - (ptrdiff_t)plow;
232*5c51f124SMoriah Waterland 
233*5c51f124SMoriah Waterland 		/* compare target path with current path */
234*5c51f124SMoriah Waterland 
235*5c51f124SMoriah Waterland 		n = strncmp(a_path, plow, plen);
236*5c51f124SMoriah Waterland 		if (n == 0) {
237*5c51f124SMoriah Waterland 			/* if lengths same exact match return position found */
238*5c51f124SMoriah Waterland 			if (a_pathLen == plen) {
239*5c51f124SMoriah Waterland 				return (plow);
240*5c51f124SMoriah Waterland 			}
241*5c51f124SMoriah Waterland 			/* not exact match - a_path > pm */
242*5c51f124SMoriah Waterland 			n = a_pathLen;
243*5c51f124SMoriah Waterland 		}
244*5c51f124SMoriah Waterland 
245*5c51f124SMoriah Waterland 		/* return if target is greater than or equal to entry */
246*5c51f124SMoriah Waterland 
247*5c51f124SMoriah Waterland 		if (n >= 0) {
248*5c51f124SMoriah Waterland 			return (plow);
249*5c51f124SMoriah Waterland 		}
250*5c51f124SMoriah Waterland 	}
251*5c51f124SMoriah Waterland 	/*
252*5c51f124SMoriah Waterland 	 * firstPath < targetpath < lastPath:
253*5c51f124SMoriah Waterland 	 * binary search looking for closest "less than" match
254*5c51f124SMoriah Waterland 	 */
255*5c51f124SMoriah Waterland 
256*5c51f124SMoriah Waterland 	plow = vfpGetCurrCharPtr(a_vfp);
257*5c51f124SMoriah Waterland 	phigh = vfpGetLastCharPtr(a_vfp);
258*5c51f124SMoriah Waterland 
259*5c51f124SMoriah Waterland 	for (;;) {
260*5c51f124SMoriah Waterland 		char	*pm;
261*5c51f124SMoriah Waterland 
262*5c51f124SMoriah Waterland 		/* determine number of bytes left in search area */
263*5c51f124SMoriah Waterland 
264*5c51f124SMoriah Waterland 		plen = (ptrdiff_t)phigh - (ptrdiff_t)plow;
265*5c51f124SMoriah Waterland 
266*5c51f124SMoriah Waterland 		/* calculate mid point between current low and high points */
267*5c51f124SMoriah Waterland 
268*5c51f124SMoriah Waterland 		pmid = plow + (plen >> 1);
269*5c51f124SMoriah Waterland 
270*5c51f124SMoriah Waterland 		/* backup and find first "\n/" -or- start of buffer */
271*5c51f124SMoriah Waterland 
272*5c51f124SMoriah Waterland 		while ((pmid > plow) &&
273*5c51f124SMoriah Waterland 				(!((pmid[0] == '/') && (pmid[-1] == '\n')))) {
274*5c51f124SMoriah Waterland 			pmid--;
275*5c51f124SMoriah Waterland 		}
276*5c51f124SMoriah Waterland 
277*5c51f124SMoriah Waterland 		/* return lowest line found if current line not past that */
278*5c51f124SMoriah Waterland 
279*5c51f124SMoriah Waterland 		if (pmid <= plow) {
280*5c51f124SMoriah Waterland 			return (plow);
281*5c51f124SMoriah Waterland 		}
282*5c51f124SMoriah Waterland 
283*5c51f124SMoriah Waterland 		/* remember start of this line */
284*5c51f124SMoriah Waterland 
285*5c51f124SMoriah Waterland 		pm = pmid;
286*5c51f124SMoriah Waterland 
287*5c51f124SMoriah Waterland 		/* find end of path */
288*5c51f124SMoriah Waterland 
289*5c51f124SMoriah Waterland 		while (ISPKGPATHSEP[(int)*pmid] == 0) {
290*5c51f124SMoriah Waterland 			pmid++;
291*5c51f124SMoriah Waterland 		}
292*5c51f124SMoriah Waterland 
293*5c51f124SMoriah Waterland 		/* determine length of path */
294*5c51f124SMoriah Waterland 
295*5c51f124SMoriah Waterland 		plen = (ptrdiff_t)pmid - (ptrdiff_t)pm;
296*5c51f124SMoriah Waterland 
297*5c51f124SMoriah Waterland 		/* compare target path with current path */
298*5c51f124SMoriah Waterland 
299*5c51f124SMoriah Waterland 		n = strncmp(a_path, pm, plen);
300*5c51f124SMoriah Waterland 
301*5c51f124SMoriah Waterland 		if (n == 0) {
302*5c51f124SMoriah Waterland 			/* if lengths same exact match return position found */
303*5c51f124SMoriah Waterland 			if (a_pathLen == plen) {
304*5c51f124SMoriah Waterland 				return (pm);
305*5c51f124SMoriah Waterland 			}
306*5c51f124SMoriah Waterland 			/* not exact match - a_path > pm */
307*5c51f124SMoriah Waterland 			n = a_pathLen;
308*5c51f124SMoriah Waterland 		}
309*5c51f124SMoriah Waterland 
310*5c51f124SMoriah Waterland 
311*5c51f124SMoriah Waterland 		/* not exact match - determine which watermark to split */
312*5c51f124SMoriah Waterland 
313*5c51f124SMoriah Waterland 		if (n > 0) {	/* a_path > pm */
314*5c51f124SMoriah Waterland 			plow = pm;
315*5c51f124SMoriah Waterland 		} else {	/* a_path < pm */
316*5c51f124SMoriah Waterland 			phigh = pm;
317*5c51f124SMoriah Waterland 		}
318*5c51f124SMoriah Waterland 	}
319*5c51f124SMoriah Waterland 	/*NOTREACHED*/
320*5c51f124SMoriah Waterland }
321*5c51f124SMoriah Waterland 
322*5c51f124SMoriah Waterland /*
323*5c51f124SMoriah Waterland  * Name:	srchcfile
324*5c51f124SMoriah Waterland  * Description:	search contents file looking for closest match to entry,
325*5c51f124SMoriah Waterland  *		creating a new contents file if output contents file specified
326*5c51f124SMoriah Waterland  * Arguments:	ept - (struct cfent *) - [RO, *RW]
327*5c51f124SMoriah Waterland  *			- contents file entry, describing last item found
328*5c51f124SMoriah Waterland  *		path - (char *) - [RO, *RO]
329*5c51f124SMoriah Waterland  *			- path to search for in contents file
330*5c51f124SMoriah Waterland  *			- If path is "*", then the next entry is returned;
331*5c51f124SMoriah Waterland  *				the next entry always matches this path
332*5c51f124SMoriah Waterland  *			- If the path is (char *)NULL or "", then all remaining
333*5c51f124SMoriah Waterland  *				entries are processed and copied out to the
334*5c51f124SMoriah Waterland  *				file specified by cfTmpVFp
335*5c51f124SMoriah Waterland  *		cfVfp - (VFP_T *) - [RO, *RW]
336*5c51f124SMoriah Waterland  *			- VFP_T open on contents file to search
337*5c51f124SMoriah Waterland  *		cfTmpVfp - (VFP_T *) - [RO, *RW]
338*5c51f124SMoriah Waterland  *			- VFP_T open on temporary contents file to populate
339*5c51f124SMoriah Waterland  * Returns:	int
340*5c51f124SMoriah Waterland  *		< 0 - error occurred
341*5c51f124SMoriah Waterland  *			- Use getErrstr to retrieve character-string describing
342*5c51f124SMoriah Waterland  *			  the reason for failure
343*5c51f124SMoriah Waterland  *		== 0 - no match found
344*5c51f124SMoriah Waterland  *			- specified path not in the contents file
345*5c51f124SMoriah Waterland  *			- all contents of cfVfp copied to cfTmpVfp
346*5c51f124SMoriah Waterland  *			- current character of cfVfp is at end of file
347*5c51f124SMoriah Waterland  *		== 1 - exact match found
348*5c51f124SMoriah Waterland  *			- specified path found in contents file
349*5c51f124SMoriah Waterland  *			- contents of cfVfp up to entry found copied to cfTmpVfp
350*5c51f124SMoriah Waterland  *			- current character of cfVfp is first character of
351*5c51f124SMoriah Waterland  *				entry found
352*5c51f124SMoriah Waterland  *			- this value is always returned if path is "*" and the
353*5c51f124SMoriah Waterland  *			  next entry is returned - -1 is returned when no more
354*5c51f124SMoriah Waterland  *			  entries are left to process
355*5c51f124SMoriah Waterland  *		== 2 - entry found which is GREATER than path specified
356*5c51f124SMoriah Waterland  *			- specified path would fit BEFORE entry found
357*5c51f124SMoriah Waterland  *			- contents of cfVfp up to entry found copied to cfTmpVfp
358*5c51f124SMoriah Waterland  *			- current character of cfVfp is first character of
359*5c51f124SMoriah Waterland  *				entry found
360*5c51f124SMoriah Waterland  * Side Effects:
361*5c51f124SMoriah Waterland  *		- The ept structure supplied is filled in with a description of
362*5c51f124SMoriah Waterland  *		  the item that caused the search to terminate, except in the
363*5c51f124SMoriah Waterland  *		  case of '0' in which case the contents of 'ept' is undefined.
364*5c51f124SMoriah Waterland  *		- NOTE: the ept->path item points to a path that is statically
365*5c51f124SMoriah Waterland  *		  allocated and will be overwritten on the next call.
366*5c51f124SMoriah Waterland  *		- NOTE: the ept->ainfo.local item points to a path that is
367*5c51f124SMoriah Waterland  *		  statically allocated and will be overwritten on the next call.
368*5c51f124SMoriah Waterland  */
369*5c51f124SMoriah Waterland 
370*5c51f124SMoriah Waterland int
371*5c51f124SMoriah Waterland srchcfile(struct cfent *ept, char *path, VFP_T *cfVfp, VFP_T *cfTmpVfp)
372*5c51f124SMoriah Waterland {
373*5c51f124SMoriah Waterland 	char		*cpath_start = (char *)NULL;
374*5c51f124SMoriah Waterland 	char		*firstPos = vfpGetCurrCharPtr(cfVfp);
375*5c51f124SMoriah Waterland 	char		*lastPos = NULL;
376*5c51f124SMoriah Waterland 	char		*pos;
377*5c51f124SMoriah Waterland 	char		classname[CLSSIZ+1];
378*5c51f124SMoriah Waterland 	char		pkgname[PKGSIZ+1];
379*5c51f124SMoriah Waterland 	int		anypath = 0;
380*5c51f124SMoriah Waterland 	int		c;
381*5c51f124SMoriah Waterland 	int		dataSkipped = 0;
382*5c51f124SMoriah Waterland 	int		n;
383*5c51f124SMoriah Waterland 	int		rdpath;
384*5c51f124SMoriah Waterland 	size_t		cpath_len = 0;
385*5c51f124SMoriah Waterland 	size_t		pathLength;
386*5c51f124SMoriah Waterland 	struct pinfo	*lastpinfo;
387*5c51f124SMoriah Waterland 	struct pinfo	*pinfo;
388*5c51f124SMoriah Waterland 
389*5c51f124SMoriah Waterland 	/*
390*5c51f124SMoriah Waterland 	 * this code does not use nested subroutines because execution time
391*5c51f124SMoriah Waterland 	 * of this routine is especially critical to installation and upgrade
392*5c51f124SMoriah Waterland 	 */
393*5c51f124SMoriah Waterland 
394*5c51f124SMoriah Waterland 	/* initialize local variables */
395*5c51f124SMoriah Waterland 
396*5c51f124SMoriah Waterland 	setErrstr(NULL);	/* no error message currently cached */
397*5c51f124SMoriah Waterland 	pathLength = (path == (char *)NULL ? 0 : strlen(path));
398*5c51f124SMoriah Waterland 	lpath[0] = '\0';
399*5c51f124SMoriah Waterland 	lpath[sizeof (lpath)-1] = '\0';
400*5c51f124SMoriah Waterland 
401*5c51f124SMoriah Waterland 	/* initialize ept structure values */
402*5c51f124SMoriah Waterland 
403*5c51f124SMoriah Waterland 	(void) strlcpy(ept->ainfo.group, BADGROUP, sizeof (ept->ainfo.group));
404*5c51f124SMoriah Waterland 	(void) strlcpy(ept->ainfo.owner, BADOWNER, sizeof (ept->ainfo.owner));
405*5c51f124SMoriah Waterland 	(void) strlcpy(ept->pkg_class, BADCLASS,  sizeof (ept->pkg_class));
406*5c51f124SMoriah Waterland 	ept->ainfo.local = (char *)NULL;
407*5c51f124SMoriah Waterland 	ept->ainfo.mode = BADMODE;
408*5c51f124SMoriah Waterland 	ept->cinfo.cksum = BADCONT;
409*5c51f124SMoriah Waterland 	ept->cinfo.modtime = BADCONT;
410*5c51f124SMoriah Waterland 	ept->cinfo.size = (fsblkcnt_t)BADCONT;
411*5c51f124SMoriah Waterland 	ept->ftype = BADFTYPE;
412*5c51f124SMoriah Waterland 	ept->npkgs = 0;
413*5c51f124SMoriah Waterland 	ept->path = (char *)NULL;
414*5c51f124SMoriah Waterland 	ept->pinfo = (struct pinfo *)NULL;
415*5c51f124SMoriah Waterland 	ept->pkg_class_idx = -1;
416*5c51f124SMoriah Waterland 	ept->volno = 0;
417*5c51f124SMoriah Waterland 
418*5c51f124SMoriah Waterland 	/*
419*5c51f124SMoriah Waterland 	 * populate decision tables that implement fast character checking;
420*5c51f124SMoriah Waterland 	 * this is much faster than the equivalent strpbrk() call or a
421*5c51f124SMoriah Waterland 	 * while() loop checking for the characters. It is only faster if
422*5c51f124SMoriah Waterland 	 * there are at least 3 characters to scan for - when checking for
423*5c51f124SMoriah Waterland 	 * one or two characters (such as '\n' or '\0') its faster to do
424*5c51f124SMoriah Waterland 	 * a simple while() loop.
425*5c51f124SMoriah Waterland 	 */
426*5c51f124SMoriah Waterland 
427*5c51f124SMoriah Waterland 	if (decisionTableInit == 0) {
428*5c51f124SMoriah Waterland 		/*
429*5c51f124SMoriah Waterland 		 * any chars listed stop scan;
430*5c51f124SMoriah Waterland 		 * scan stops on first byte found that is set to '1' below
431*5c51f124SMoriah Waterland 		 */
432*5c51f124SMoriah Waterland 
433*5c51f124SMoriah Waterland 		/*
434*5c51f124SMoriah Waterland 		 * Separators for path names, normal space and =
435*5c51f124SMoriah Waterland 		 * for linked filenames
436*5c51f124SMoriah Waterland 		 */
437*5c51f124SMoriah Waterland 		bzero(ISPKGPATHSEP, sizeof (ISPKGPATHSEP));
438*5c51f124SMoriah Waterland 		ISPKGPATHSEP['='] = 1;		/* = */
439*5c51f124SMoriah Waterland 		ISPKGPATHSEP[' '] = 1;		/* space */
440*5c51f124SMoriah Waterland 		ISPKGPATHSEP['\t'] = 1;		/* horizontal-tab */
441*5c51f124SMoriah Waterland 		ISPKGPATHSEP['\n'] = 1;		/* new-line */
442*5c51f124SMoriah Waterland 		ISPKGPATHSEP['\0'] = 1;		/* NULL character */
443*5c51f124SMoriah Waterland 
444*5c51f124SMoriah Waterland 		/*
445*5c51f124SMoriah Waterland 		 * Separators for normal words
446*5c51f124SMoriah Waterland 		 */
447*5c51f124SMoriah Waterland 		bzero(ISWORDSEP, sizeof (ISWORDSEP));
448*5c51f124SMoriah Waterland 		ISWORDSEP[' '] = 1;
449*5c51f124SMoriah Waterland 		ISWORDSEP['\t'] = 1;
450*5c51f124SMoriah Waterland 		ISWORDSEP['\n'] = 1;
451*5c51f124SMoriah Waterland 		ISWORDSEP['\0'] = 1;
452*5c51f124SMoriah Waterland 
453*5c51f124SMoriah Waterland 		/*
454*5c51f124SMoriah Waterland 		 * Separators for list of packages, includes \\ for
455*5c51f124SMoriah Waterland 		 * alternate ftype and : for classname
456*5c51f124SMoriah Waterland 		 */
457*5c51f124SMoriah Waterland 		bzero(ISPKGNAMESEP, sizeof (ISPKGNAMESEP));
458*5c51f124SMoriah Waterland 		ISPKGNAMESEP[' '] = 1;
459*5c51f124SMoriah Waterland 		ISPKGNAMESEP['\t'] = 1;
460*5c51f124SMoriah Waterland 		ISPKGNAMESEP['\n'] = 1;
461*5c51f124SMoriah Waterland 		ISPKGNAMESEP[':'] = 1;
462*5c51f124SMoriah Waterland 		ISPKGNAMESEP['\\'] = 1;
463*5c51f124SMoriah Waterland 		ISPKGNAMESEP['\0'] = 1;
464*5c51f124SMoriah Waterland 
465*5c51f124SMoriah Waterland 		decisionTableInit = 1;
466*5c51f124SMoriah Waterland 	}
467*5c51f124SMoriah Waterland 
468*5c51f124SMoriah Waterland 	/* if no bytes in contents file, return 0 */
469*5c51f124SMoriah Waterland 
470*5c51f124SMoriah Waterland 	if (vfpGetBytesRemaining(cfVfp) <= 1) {
471*5c51f124SMoriah Waterland 		return (0);
472*5c51f124SMoriah Waterland 	}
473*5c51f124SMoriah Waterland 
474*5c51f124SMoriah Waterland 	/* if the path to scan for is empty, act like no path was specified */
475*5c51f124SMoriah Waterland 
476*5c51f124SMoriah Waterland 	if ((path != (char *)NULL) && (*path == '\0')) {
477*5c51f124SMoriah Waterland 		path = (char *)NULL;
478*5c51f124SMoriah Waterland 	}
479*5c51f124SMoriah Waterland 
480*5c51f124SMoriah Waterland 	/*
481*5c51f124SMoriah Waterland 	 * if path to search for is "*", then we will return the first path
482*5c51f124SMoriah Waterland 	 * we encounter as a match, otherwise we return an error
483*5c51f124SMoriah Waterland 	 */
484*5c51f124SMoriah Waterland 
485*5c51f124SMoriah Waterland 	if ((path != (char *)NULL) && (path[0] != '/')) {
486*5c51f124SMoriah Waterland 		if (strcmp(path, "*") != 0) {
487*5c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_ILLEGAL_SEARCH_PATH));
488*5c51f124SMoriah Waterland 			return (-1);
489*5c51f124SMoriah Waterland 		}
490*5c51f124SMoriah Waterland 		anypath = 1;
491*5c51f124SMoriah Waterland 	}
492*5c51f124SMoriah Waterland 
493*5c51f124SMoriah Waterland 	/* attempt to narrow down the search for the specified path */
494*5c51f124SMoriah Waterland 
495*5c51f124SMoriah Waterland 	if (anypath == 0) {
496*5c51f124SMoriah Waterland 		char	*np;
497*5c51f124SMoriah Waterland 
498*5c51f124SMoriah Waterland 		np = narrowSearch(cfVfp, path, pathLength);
499*5c51f124SMoriah Waterland 		if (np != (char *)NULL) {
500*5c51f124SMoriah Waterland 			dataSkipped = 1;
501*5c51f124SMoriah Waterland 			lastPos = np;
502*5c51f124SMoriah Waterland 			vfpSetCurrCharPtr(cfVfp, np);
503*5c51f124SMoriah Waterland 		}
504*5c51f124SMoriah Waterland 	}
505*5c51f124SMoriah Waterland 
506*5c51f124SMoriah Waterland 	/*
507*5c51f124SMoriah Waterland 	 * If the path to search for in the source contents file is NULL, then
508*5c51f124SMoriah Waterland 	 * this is a request to scan to the end of the source contents file. If
509*5c51f124SMoriah Waterland 	 * there is a temporary contents file to copy entries to, all that needs
510*5c51f124SMoriah Waterland 	 * to be done is to copy the data remaining from the current location in
511*5c51f124SMoriah Waterland 	 * the source contents file to the end of the temporary contents file.
512*5c51f124SMoriah Waterland 	 * if there is no temporary contents file to copy to, then all that
513*5c51f124SMoriah Waterland 	 * needs to be done is to seek to the end of the source contents file.
514*5c51f124SMoriah Waterland 	 */
515*5c51f124SMoriah Waterland 
516*5c51f124SMoriah Waterland 	if ((anypath == 0) && (path == (char *)NULL)) {
517*5c51f124SMoriah Waterland 		if (cfTmpVfp != (VFP_T *)NULL) {
518*5c51f124SMoriah Waterland 			if (vfpGetBytesRemaining(cfVfp) > 0) {
519*5c51f124SMoriah Waterland 				WRITEDATA(cfTmpVfp, firstPos,
520*5c51f124SMoriah Waterland 					vfpGetLastCharPtr(cfVfp)+1);
521*5c51f124SMoriah Waterland 			}
522*5c51f124SMoriah Waterland 			*vfpGetLastCharPtr(cfTmpVfp) = '\0';
523*5c51f124SMoriah Waterland 		}
524*5c51f124SMoriah Waterland 		vfpSeekToEnd(cfVfp);
525*5c51f124SMoriah Waterland 		return (0);
526*5c51f124SMoriah Waterland 	}
527*5c51f124SMoriah Waterland 
528*5c51f124SMoriah Waterland 	/*
529*5c51f124SMoriah Waterland 	 * *********************************************************************
530*5c51f124SMoriah Waterland 	 * main loop processing entries from the contents file looking for
531*5c51f124SMoriah Waterland 	 * the specified path
532*5c51f124SMoriah Waterland 	 * *********************************************************************
533*5c51f124SMoriah Waterland 	 */
534*5c51f124SMoriah Waterland 
535*5c51f124SMoriah Waterland 	for (;;) {
536*5c51f124SMoriah Waterland 		char	*p;
537*5c51f124SMoriah Waterland 
538*5c51f124SMoriah Waterland 		/* not reading old style entry */
539*5c51f124SMoriah Waterland 
540*5c51f124SMoriah Waterland 		rdpath = 0;
541*5c51f124SMoriah Waterland 
542*5c51f124SMoriah Waterland 		/* determine first character of the next entry */
543*5c51f124SMoriah Waterland 
544*5c51f124SMoriah Waterland 		if (vfpGetBytesRemaining(cfVfp) <= 0) {
545*5c51f124SMoriah Waterland 			/* no bytes in contents file current char is NULL */
546*5c51f124SMoriah Waterland 
547*5c51f124SMoriah Waterland 			c = '\0';
548*5c51f124SMoriah Waterland 		} else {
549*5c51f124SMoriah Waterland 			/* grab path from first entry */
550*5c51f124SMoriah Waterland 
551*5c51f124SMoriah Waterland 			c = vfpGetcNoInc(cfVfp);
552*5c51f124SMoriah Waterland 		}
553*5c51f124SMoriah Waterland 
554*5c51f124SMoriah Waterland 		/* save current position in file */
555*5c51f124SMoriah Waterland 
556*5c51f124SMoriah Waterland 		pos = vfpGetCurrCharPtr(cfVfp);
557*5c51f124SMoriah Waterland 
558*5c51f124SMoriah Waterland 		/*
559*5c51f124SMoriah Waterland 		 * =============================================================
560*5c51f124SMoriah Waterland 		 * at the first character of the next entry in the contents file
561*5c51f124SMoriah Waterland 		 * if not absolute path check for exceptions and old style entry
562*5c51f124SMoriah Waterland 		 * --> if end of contents file write out skipped data and return
563*5c51f124SMoriah Waterland 		 * --> if comment character skip to end of line and restart loop
564*5c51f124SMoriah Waterland 		 * --> else process "old style entry: ftype class path"
565*5c51f124SMoriah Waterland 		 * =============================================================
566*5c51f124SMoriah Waterland 		 */
567*5c51f124SMoriah Waterland 
568*5c51f124SMoriah Waterland 		if (c != '/') {
569*5c51f124SMoriah Waterland 			/* if NULL character then end of contents file found */
570*5c51f124SMoriah Waterland 
571*5c51f124SMoriah Waterland 			if (c == '\0') {
572*5c51f124SMoriah Waterland 				/* write out skipped data before returning */
573*5c51f124SMoriah Waterland 				if (dataSkipped &&
574*5c51f124SMoriah Waterland 						(cfTmpVfp != (VFP_T *)NULL)) {
575*5c51f124SMoriah Waterland 					WRITEDATA(cfTmpVfp, firstPos, lastPos);
576*5c51f124SMoriah Waterland 					*vfpGetLastCharPtr(cfTmpVfp) = '\0';
577*5c51f124SMoriah Waterland 				}
578*5c51f124SMoriah Waterland 
579*5c51f124SMoriah Waterland 				return (0); /* no more entries */
580*5c51f124SMoriah Waterland 			}
581*5c51f124SMoriah Waterland 
582*5c51f124SMoriah Waterland 			/* ignore lines that begin with #, : or a "space" */
583*5c51f124SMoriah Waterland 
584*5c51f124SMoriah Waterland 			if ((isspace(c) != 0) || (c == '#') || (c == ':')) {
585*5c51f124SMoriah Waterland 				/* line is a comment */
586*5c51f124SMoriah Waterland 				findend(&vfpGetCurrCharPtr(cfVfp));
587*5c51f124SMoriah Waterland 				continue;
588*5c51f124SMoriah Waterland 			}
589*5c51f124SMoriah Waterland 
590*5c51f124SMoriah Waterland 			/*
591*5c51f124SMoriah Waterland 			 * old style entry - format is:
592*5c51f124SMoriah Waterland 			 *	ftype class path
593*5c51f124SMoriah Waterland 			 * set ept->ftype to the type
594*5c51f124SMoriah Waterland 			 * set ept->class to the class
595*5c51f124SMoriah Waterland 			 * set ept->path to point to lpath
596*5c51f124SMoriah Waterland 			 * set cpath_start/cpath_len to point to the file name
597*5c51f124SMoriah Waterland 			 * set rdpath to '1' to indicate old style entry parsed
598*5c51f124SMoriah Waterland 			 */
599*5c51f124SMoriah Waterland 
600*5c51f124SMoriah Waterland 			while (isspace((c = vfpGetc(cfVfp))))
601*5c51f124SMoriah Waterland 				;
602*5c51f124SMoriah Waterland 
603*5c51f124SMoriah Waterland 			switch (c) {
604*5c51f124SMoriah Waterland 			case '?': case 'f': case 'v': case 'e': case 'l':
605*5c51f124SMoriah Waterland 			case 's': case 'p': case 'c': case 'b': case 'd':
606*5c51f124SMoriah Waterland 			case 'x':
607*5c51f124SMoriah Waterland 				/* save ftype */
608*5c51f124SMoriah Waterland 				ept->ftype = (char)c;
609*5c51f124SMoriah Waterland 
610*5c51f124SMoriah Waterland 				/* save class */
611*5c51f124SMoriah Waterland 				if (getstr(&vfpGetCurrCharPtr(cfVfp), CLSSIZ,
612*5c51f124SMoriah Waterland 						ept->pkg_class, ISWORDSEP)) {
613*5c51f124SMoriah Waterland 					setErrstr(ERR_CANNOT_READ_CLASS_TOKEN);
614*5c51f124SMoriah Waterland 					findend(&vfpGetCurrCharPtr(cfVfp));
615*5c51f124SMoriah Waterland 					return (-1);
616*5c51f124SMoriah Waterland 				}
617*5c51f124SMoriah Waterland 
618*5c51f124SMoriah Waterland 				/*
619*5c51f124SMoriah Waterland 				 * locate file name up to "=", set cpath_start
620*5c51f124SMoriah Waterland 				 * and cpath_len to point to the file name
621*5c51f124SMoriah Waterland 				 */
622*5c51f124SMoriah Waterland 				cpath_start = vfpGetCurrCharPtr(cfVfp);
623*5c51f124SMoriah Waterland 				p = vfpGetCurrCharPtr(cfVfp);
624*5c51f124SMoriah Waterland 
625*5c51f124SMoriah Waterland 				/*
626*5c51f124SMoriah Waterland 				 * skip past all bytes until first '= \t\n\0':
627*5c51f124SMoriah Waterland 				 */
628*5c51f124SMoriah Waterland 				while (ISPKGPATHSEP[(int)*p] == 0) {
629*5c51f124SMoriah Waterland 					p++;
630*5c51f124SMoriah Waterland 				}
631*5c51f124SMoriah Waterland 
632*5c51f124SMoriah Waterland 				cpath_len = vfpGetCurrPtrDelta(cfVfp, p);
633*5c51f124SMoriah Waterland 
634*5c51f124SMoriah Waterland 				/*
635*5c51f124SMoriah Waterland 				 * if the path is zero bytes, line is corrupted
636*5c51f124SMoriah Waterland 				 */
637*5c51f124SMoriah Waterland 
638*5c51f124SMoriah Waterland 				if (cpath_len < 1) {
639*5c51f124SMoriah Waterland 					setErrstr(ERR_CANNOT_READ_PATHNAME_FLD);
640*5c51f124SMoriah Waterland 					findend(&vfpGetCurrCharPtr(cfVfp));
641*5c51f124SMoriah Waterland 					return (-1);
642*5c51f124SMoriah Waterland 				}
643*5c51f124SMoriah Waterland 
644*5c51f124SMoriah Waterland 				vfpIncCurrPtrBy(cfVfp, cpath_len);
645*5c51f124SMoriah Waterland 
646*5c51f124SMoriah Waterland 				/* set path to point to local path cache */
647*5c51f124SMoriah Waterland 				ept->path = lpath;
648*5c51f124SMoriah Waterland 
649*5c51f124SMoriah Waterland 				/* set flag indicating path already parsed */
650*5c51f124SMoriah Waterland 				rdpath = 1;
651*5c51f124SMoriah Waterland 				break;
652*5c51f124SMoriah Waterland 
653*5c51f124SMoriah Waterland 			case '\0':
654*5c51f124SMoriah Waterland 				/* end of line before new-line seen */
655*5c51f124SMoriah Waterland 				vfpDecCurrPtr(cfVfp);
656*5c51f124SMoriah Waterland 				setErrstr(ERR_INCOMPLETE_ENTRY);
657*5c51f124SMoriah Waterland 				return (-1);
658*5c51f124SMoriah Waterland 
659*5c51f124SMoriah Waterland 			case '0': case '1': case '2': case '3': case '4':
660*5c51f124SMoriah Waterland 			case '5': case '6': case '7': case '8': case '9':
661*5c51f124SMoriah Waterland 				/* volume number seen */
662*5c51f124SMoriah Waterland 				setErrstr(ERR_VOLUMENO_UNEXPECTED);
663*5c51f124SMoriah Waterland 				findend(&vfpGetCurrCharPtr(cfVfp));
664*5c51f124SMoriah Waterland 				return (-1);
665*5c51f124SMoriah Waterland 
666*5c51f124SMoriah Waterland 			case 'i':
667*5c51f124SMoriah Waterland 				/* type i files are not cataloged */
668*5c51f124SMoriah Waterland 				setErrstr(ERR_FTYPE_I_UNEXPECTED);
669*5c51f124SMoriah Waterland 				findend(&vfpGetCurrCharPtr(cfVfp));
670*5c51f124SMoriah Waterland 				return (-1);
671*5c51f124SMoriah Waterland 
672*5c51f124SMoriah Waterland 			default:
673*5c51f124SMoriah Waterland 				/* unknown ftype */
674*5c51f124SMoriah Waterland 				setErrstr(ERR_UNKNOWN_FTYPE);
675*5c51f124SMoriah Waterland 				findend(&vfpGetCurrCharPtr(cfVfp));
676*5c51f124SMoriah Waterland 				return (-1);
677*5c51f124SMoriah Waterland 			}
678*5c51f124SMoriah Waterland 		} else {
679*5c51f124SMoriah Waterland 			/*
680*5c51f124SMoriah Waterland 			 * current entry DOES start with absolute path
681*5c51f124SMoriah Waterland 			 * set ept->path to point to lpath
682*5c51f124SMoriah Waterland 			 * set cpath_start/cpath_len to point to the file name
683*5c51f124SMoriah Waterland 			 */
684*5c51f124SMoriah Waterland 		/* copy first token into path element of passed structure */
685*5c51f124SMoriah Waterland 
686*5c51f124SMoriah Waterland 			cpath_start = vfpGetCurrCharPtr(cfVfp);
687*5c51f124SMoriah Waterland 
688*5c51f124SMoriah Waterland 			p = cpath_start;
689*5c51f124SMoriah Waterland 
690*5c51f124SMoriah Waterland 			/*
691*5c51f124SMoriah Waterland 			 * skip past all bytes until first from '= \t\n\0':
692*5c51f124SMoriah Waterland 			 */
693*5c51f124SMoriah Waterland 
694*5c51f124SMoriah Waterland 			while (ISPKGPATHSEP[(int)*p] == 0) {
695*5c51f124SMoriah Waterland 				p++;
696*5c51f124SMoriah Waterland 			}
697*5c51f124SMoriah Waterland 
698*5c51f124SMoriah Waterland 			cpath_len = vfpGetCurrPtrDelta(cfVfp, p);
699*5c51f124SMoriah Waterland 
700*5c51f124SMoriah Waterland 			vfpIncCurrPtrBy(cfVfp, cpath_len);
701*5c51f124SMoriah Waterland 
702*5c51f124SMoriah Waterland 			if (vfpGetcNoInc(cfVfp) == '\0') {
703*5c51f124SMoriah Waterland 				setErrstr(ERR_INCOMPLETE_ENTRY);
704*5c51f124SMoriah Waterland 				findend(&vfpGetCurrCharPtr(cfVfp));
705*5c51f124SMoriah Waterland 				return (-1);
706*5c51f124SMoriah Waterland 			}
707*5c51f124SMoriah Waterland 
708*5c51f124SMoriah Waterland 			ept->path = lpath;
709*5c51f124SMoriah Waterland 		}
710*5c51f124SMoriah Waterland 
711*5c51f124SMoriah Waterland 		/*
712*5c51f124SMoriah Waterland 		 * =============================================================
713*5c51f124SMoriah Waterland 		 * if absolute path then the path is collected and we are at the
714*5c51f124SMoriah Waterland 		 * first byte following the absolute path name;
715*5c51f124SMoriah Waterland 		 * if not an absolute path then an old style entry, ept has been
716*5c51f124SMoriah Waterland 		 * filled with the type and class and path name.
717*5c51f124SMoriah Waterland 		 * determine if we have read the pathname which identifies
718*5c51f124SMoriah Waterland 		 * the entry we are searching for
719*5c51f124SMoriah Waterland 		 * =============================================================
720*5c51f124SMoriah Waterland 		 */
721*5c51f124SMoriah Waterland 
722*5c51f124SMoriah Waterland 		if (anypath != 0) {
723*5c51f124SMoriah Waterland 			n = 0;	/* next entry is "equal to" */
724*5c51f124SMoriah Waterland 		} else if (path == (char *)NULL) {
725*5c51f124SMoriah Waterland 			n = 1;	/* next entry is "greater than" */
726*5c51f124SMoriah Waterland 		} else {
727*5c51f124SMoriah Waterland 			n = strncmp(path, cpath_start, cpath_len);
728*5c51f124SMoriah Waterland 			if ((n == 0) && (cpath_len != pathLength)) {
729*5c51f124SMoriah Waterland 				n = cpath_len;
730*5c51f124SMoriah Waterland 			}
731*5c51f124SMoriah Waterland 		}
732*5c51f124SMoriah Waterland 
733*5c51f124SMoriah Waterland 		/* get first character following the end of the path */
734*5c51f124SMoriah Waterland 
735*5c51f124SMoriah Waterland 		c = vfpGetc(cfVfp);
736*5c51f124SMoriah Waterland 
737*5c51f124SMoriah Waterland 		/*
738*5c51f124SMoriah Waterland 		 * if an exact match, always parse out the local path
739*5c51f124SMoriah Waterland 		 */
740*5c51f124SMoriah Waterland 
741*5c51f124SMoriah Waterland 		if (n == 0) {
742*5c51f124SMoriah Waterland 			/*
743*5c51f124SMoriah Waterland 			 * we want to return information about this path in
744*5c51f124SMoriah Waterland 			 * the structure provided, so parse any local path
745*5c51f124SMoriah Waterland 			 * and jump to code which parses rest of the input line
746*5c51f124SMoriah Waterland 			 */
747*5c51f124SMoriah Waterland 			if (c == '=') {
748*5c51f124SMoriah Waterland 				/* parse local path specification */
749*5c51f124SMoriah Waterland 				if (getstr(&vfpGetCurrCharPtr(cfVfp), PATH_MAX,
750*5c51f124SMoriah Waterland 						mylocal, ISWORDSEP)) {
751*5c51f124SMoriah Waterland 
752*5c51f124SMoriah Waterland 					/* copy path found to 'lpath' */
753*5c51f124SMoriah Waterland 					COPYPATH(lpath, cpath_start, cpath_len);
754*5c51f124SMoriah Waterland 
755*5c51f124SMoriah Waterland 					setErrstr(ERR_CANNOT_READ_LL_PATH);
756*5c51f124SMoriah Waterland 					findend(&vfpGetCurrCharPtr(cfVfp));
757*5c51f124SMoriah Waterland 					return (-1);
758*5c51f124SMoriah Waterland 				}
759*5c51f124SMoriah Waterland 				ept->ainfo.local = mylocal;
760*5c51f124SMoriah Waterland 			}
761*5c51f124SMoriah Waterland 		}
762*5c51f124SMoriah Waterland 
763*5c51f124SMoriah Waterland 		/*
764*5c51f124SMoriah Waterland 		 * if an exact match and processing a new style entry, read the
765*5c51f124SMoriah Waterland 		 * remaining information from the new style entry - if this is
766*5c51f124SMoriah Waterland 		 * an old style entry (rdpath != 0) then the existing info has
767*5c51f124SMoriah Waterland 		 * already been processed as it exists before the pathname and
768*5c51f124SMoriah Waterland 		 * not after like a new style entry
769*5c51f124SMoriah Waterland 		 */
770*5c51f124SMoriah Waterland 
771*5c51f124SMoriah Waterland 		if (n == 0 && rdpath == 0) {
772*5c51f124SMoriah Waterland 			while (isspace((c = vfpGetc(cfVfp))))
773*5c51f124SMoriah Waterland 				;
774*5c51f124SMoriah Waterland 
775*5c51f124SMoriah Waterland 			switch (c) {
776*5c51f124SMoriah Waterland 			case '?': case 'f': case 'v': case 'e': case 'l':
777*5c51f124SMoriah Waterland 			case 's': case 'p': case 'c': case 'b': case 'd':
778*5c51f124SMoriah Waterland 			case 'x':
779*5c51f124SMoriah Waterland 				/* save ftype */
780*5c51f124SMoriah Waterland 				ept->ftype = (char)c;
781*5c51f124SMoriah Waterland 
782*5c51f124SMoriah Waterland 				/* save class */
783*5c51f124SMoriah Waterland 				if (getstr(&vfpGetCurrCharPtr(cfVfp), CLSSIZ,
784*5c51f124SMoriah Waterland 						ept->pkg_class, ISWORDSEP)) {
785*5c51f124SMoriah Waterland 
786*5c51f124SMoriah Waterland 					/* copy path found to 'lpath' */
787*5c51f124SMoriah Waterland 					COPYPATH(lpath, cpath_start, cpath_len);
788*5c51f124SMoriah Waterland 
789*5c51f124SMoriah Waterland 					setErrstr(ERR_CANNOT_READ_CLASS_TOKEN);
790*5c51f124SMoriah Waterland 					findend(&vfpGetCurrCharPtr(cfVfp));
791*5c51f124SMoriah Waterland 					return (-1);
792*5c51f124SMoriah Waterland 				}
793*5c51f124SMoriah Waterland 				break; /* we already read the pathname */
794*5c51f124SMoriah Waterland 
795*5c51f124SMoriah Waterland 			case '\0':
796*5c51f124SMoriah Waterland 				/* end of line before new-line seen */
797*5c51f124SMoriah Waterland 				vfpDecCurrPtr(cfVfp);
798*5c51f124SMoriah Waterland 
799*5c51f124SMoriah Waterland 				/* copy path found to 'lpath' */
800*5c51f124SMoriah Waterland 				COPYPATH(lpath, cpath_start, cpath_len);
801*5c51f124SMoriah Waterland 
802*5c51f124SMoriah Waterland 				setErrstr(ERR_INCOMPLETE_ENTRY);
803*5c51f124SMoriah Waterland 				return (-1);
804*5c51f124SMoriah Waterland 
805*5c51f124SMoriah Waterland 			case '0': case '1': case '2': case '3': case '4':
806*5c51f124SMoriah Waterland 			case '5': case '6': case '7': case '8': case '9':
807*5c51f124SMoriah Waterland 
808*5c51f124SMoriah Waterland 				/* copy path found to 'lpath' */
809*5c51f124SMoriah Waterland 				COPYPATH(lpath, cpath_start, cpath_len);
810*5c51f124SMoriah Waterland 
811*5c51f124SMoriah Waterland 				setErrstr(ERR_VOLUMENO_UNEXPECTED);
812*5c51f124SMoriah Waterland 				findend(&vfpGetCurrCharPtr(cfVfp));
813*5c51f124SMoriah Waterland 				return (-1);
814*5c51f124SMoriah Waterland 
815*5c51f124SMoriah Waterland 			case 'i':
816*5c51f124SMoriah Waterland 
817*5c51f124SMoriah Waterland 				/* copy path found to 'lpath' */
818*5c51f124SMoriah Waterland 				COPYPATH(lpath, cpath_start, cpath_len);
819*5c51f124SMoriah Waterland 
820*5c51f124SMoriah Waterland 				setErrstr(ERR_FTYPE_I_UNEXPECTED);
821*5c51f124SMoriah Waterland 				findend(&vfpGetCurrCharPtr(cfVfp));
822*5c51f124SMoriah Waterland 				return (-1);
823*5c51f124SMoriah Waterland 
824*5c51f124SMoriah Waterland 			default:
825*5c51f124SMoriah Waterland 				/* unknown ftype */
826*5c51f124SMoriah Waterland 
827*5c51f124SMoriah Waterland 				/* copy path found to 'lpath' */
828*5c51f124SMoriah Waterland 				COPYPATH(lpath, cpath_start, cpath_len);
829*5c51f124SMoriah Waterland 
830*5c51f124SMoriah Waterland 				setErrstr(ERR_UNKNOWN_FTYPE);
831*5c51f124SMoriah Waterland 				findend(&vfpGetCurrCharPtr(cfVfp));
832*5c51f124SMoriah Waterland 				return (-1);
833*5c51f124SMoriah Waterland 			}
834*5c51f124SMoriah Waterland 		}
835*5c51f124SMoriah Waterland 
836*5c51f124SMoriah Waterland 		/*
837*5c51f124SMoriah Waterland 		 * if an exact match all processing is completed; break out of
838*5c51f124SMoriah Waterland 		 * the main processing loop and finish processing this entry
839*5c51f124SMoriah Waterland 		 * prior to returning to the caller.
840*5c51f124SMoriah Waterland 		 */
841*5c51f124SMoriah Waterland 
842*5c51f124SMoriah Waterland 		if (n == 0) {
843*5c51f124SMoriah Waterland 			break;
844*5c51f124SMoriah Waterland 		}
845*5c51f124SMoriah Waterland 
846*5c51f124SMoriah Waterland 		/*
847*5c51f124SMoriah Waterland 		 * this entry is not an exact match for the path being searched
848*5c51f124SMoriah Waterland 		 * for - if this entry is GREATER THAN the path being searched
849*5c51f124SMoriah Waterland 		 * for then finish processing and return GREATER THAN result
850*5c51f124SMoriah Waterland 		 * to the caller so the entry for the path being searched for
851*5c51f124SMoriah Waterland 		 * can be added to the contents file.
852*5c51f124SMoriah Waterland 		 */
853*5c51f124SMoriah Waterland 
854*5c51f124SMoriah Waterland 		if (n < 0) {
855*5c51f124SMoriah Waterland 			/*
856*5c51f124SMoriah Waterland 			 * the entry we want would fit BEFORE the one we just
857*5c51f124SMoriah Waterland 			 * read, so we need to unread what we've read by
858*5c51f124SMoriah Waterland 			 * seeking back to the start of this entry
859*5c51f124SMoriah Waterland 			 */
860*5c51f124SMoriah Waterland 
861*5c51f124SMoriah Waterland 			vfpSetCurrCharPtr(cfVfp, pos);
862*5c51f124SMoriah Waterland 
863*5c51f124SMoriah Waterland 			/* copy path found to 'lpath' */
864*5c51f124SMoriah Waterland 			COPYPATH(lpath, cpath_start, cpath_len);
865*5c51f124SMoriah Waterland 
866*5c51f124SMoriah Waterland 			/* write out any skipped data before returning */
867*5c51f124SMoriah Waterland 			if (dataSkipped && (cfTmpVfp != (VFP_T *)NULL)) {
868*5c51f124SMoriah Waterland 				WRITEDATA(cfTmpVfp, firstPos, lastPos);
869*5c51f124SMoriah Waterland 			}
870*5c51f124SMoriah Waterland 
871*5c51f124SMoriah Waterland 			return (2); /* path would insert here */
872*5c51f124SMoriah Waterland 		}
873*5c51f124SMoriah Waterland 
874*5c51f124SMoriah Waterland 		/*
875*5c51f124SMoriah Waterland 		 * This entry is "LESS THAN" the specified path to search for
876*5c51f124SMoriah Waterland 		 * need to process the next entry from the contents file. First,
877*5c51f124SMoriah Waterland 		 * if writing to new contents file, update new contents file if
878*5c51f124SMoriah Waterland 		 * processing old style entry; otherwise, update skipped data
879*5c51f124SMoriah Waterland 		 * information to remember current last byte of skipped data.
880*5c51f124SMoriah Waterland 		 */
881*5c51f124SMoriah Waterland 
882*5c51f124SMoriah Waterland 		if (cfTmpVfp != (VFP_T *)NULL) {
883*5c51f124SMoriah Waterland 			char	*px;
884*5c51f124SMoriah Waterland 			ssize_t	len;
885*5c51f124SMoriah Waterland 
886*5c51f124SMoriah Waterland 			if (rdpath != 0) {
887*5c51f124SMoriah Waterland 				/* modify record: write out any skipped data */
888*5c51f124SMoriah Waterland 				if (dataSkipped) {
889*5c51f124SMoriah Waterland 					WRITEDATA(cfTmpVfp, firstPos, lastPos);
890*5c51f124SMoriah Waterland 				}
891*5c51f124SMoriah Waterland 
892*5c51f124SMoriah Waterland 				/*
893*5c51f124SMoriah Waterland 				 * copy what we've read and the rest of this
894*5c51f124SMoriah Waterland 				 * line onto the specified output stream
895*5c51f124SMoriah Waterland 				 */
896*5c51f124SMoriah Waterland 				vfpPutBytes(cfTmpVfp, cpath_start, cpath_len);
897*5c51f124SMoriah Waterland 				vfpPutc(cfTmpVfp, c);
898*5c51f124SMoriah Waterland 				vfpPutc(cfTmpVfp, ept->ftype);
899*5c51f124SMoriah Waterland 				vfpPutc(cfTmpVfp, ' ');
900*5c51f124SMoriah Waterland 				vfpPuts(cfTmpVfp, ept->pkg_class);
901*5c51f124SMoriah Waterland 
902*5c51f124SMoriah Waterland 				px = strchr(vfpGetCurrCharPtr(cfVfp), '\n');
903*5c51f124SMoriah Waterland 
904*5c51f124SMoriah Waterland 				if (px == (char *)NULL) {
905*5c51f124SMoriah Waterland 					len = vfpGetBytesRemaining(cfVfp);
906*5c51f124SMoriah Waterland 					vfpPutBytes(cfTmpVfp,
907*5c51f124SMoriah Waterland 						vfpGetCurrCharPtr(cfVfp), len);
908*5c51f124SMoriah Waterland 					vfpPutc(cfTmpVfp, '\n');
909*5c51f124SMoriah Waterland 					vfpSeekToEnd(cfVfp);
910*5c51f124SMoriah Waterland 				} else {
911*5c51f124SMoriah Waterland 					len = vfpGetCurrPtrDelta(cfVfp, px);
912*5c51f124SMoriah Waterland 					vfpPutBytes(cfTmpVfp,
913*5c51f124SMoriah Waterland 						vfpGetCurrCharPtr(cfVfp), len);
914*5c51f124SMoriah Waterland 					vfpIncCurrPtrBy(cfVfp, len);
915*5c51f124SMoriah Waterland 				}
916*5c51f124SMoriah Waterland 
917*5c51f124SMoriah Waterland 				/* reset skiped bytes if any data skipped */
918*5c51f124SMoriah Waterland 				if (dataSkipped) {
919*5c51f124SMoriah Waterland 					dataSkipped = 0;
920*5c51f124SMoriah Waterland 					lastPos = (char *)NULL;
921*5c51f124SMoriah Waterland 					firstPos = vfpGetCurrCharPtr(cfVfp);
922*5c51f124SMoriah Waterland 				}
923*5c51f124SMoriah Waterland 			} else {
924*5c51f124SMoriah Waterland 				/* skip data */
925*5c51f124SMoriah Waterland 				dataSkipped = 1;
926*5c51f124SMoriah Waterland 
927*5c51f124SMoriah Waterland 				px = strchr(vfpGetCurrCharPtr(cfVfp), '\n');
928*5c51f124SMoriah Waterland 
929*5c51f124SMoriah Waterland 				if (px == (char *)NULL) {
930*5c51f124SMoriah Waterland 					vfpSeekToEnd(cfVfp);
931*5c51f124SMoriah Waterland 				} else {
932*5c51f124SMoriah Waterland 					len = vfpGetCurrPtrDelta(cfVfp, px)+1;
933*5c51f124SMoriah Waterland 					vfpIncCurrPtrBy(cfVfp, len);
934*5c51f124SMoriah Waterland 				}
935*5c51f124SMoriah Waterland 				lastPos = vfpGetCurrCharPtr(cfVfp);
936*5c51f124SMoriah Waterland 			}
937*5c51f124SMoriah Waterland 		} else {
938*5c51f124SMoriah Waterland 			/*
939*5c51f124SMoriah Waterland 			 * since this isn't the entry we want, just read the
940*5c51f124SMoriah Waterland 			 * stream until we find the end of this entry and
941*5c51f124SMoriah Waterland 			 * then start this search loop again
942*5c51f124SMoriah Waterland 			 */
943*5c51f124SMoriah Waterland 			char	*px;
944*5c51f124SMoriah Waterland 
945*5c51f124SMoriah Waterland 			px = strchr(vfpGetCurrCharPtr(cfVfp), '\n');
946*5c51f124SMoriah Waterland 
947*5c51f124SMoriah Waterland 			if (px == (char *)NULL) {
948*5c51f124SMoriah Waterland 				vfpSeekToEnd(cfVfp);
949*5c51f124SMoriah Waterland 
950*5c51f124SMoriah Waterland 				/* copy path found to 'lpath' */
951*5c51f124SMoriah Waterland 				COPYPATH(lpath, cpath_start, cpath_len);
952*5c51f124SMoriah Waterland 
953*5c51f124SMoriah Waterland 				setErrstr(pkg_gt(ERR_MISSING_NEWLINE));
954*5c51f124SMoriah Waterland 				findend(&vfpGetCurrCharPtr(cfVfp));
955*5c51f124SMoriah Waterland 				return (-1);
956*5c51f124SMoriah Waterland 			} else {
957*5c51f124SMoriah Waterland 				ssize_t	len;
958*5c51f124SMoriah Waterland 
959*5c51f124SMoriah Waterland 				len = vfpGetCurrPtrDelta(cfVfp, px)+1;
960*5c51f124SMoriah Waterland 				vfpIncCurrPtrBy(cfVfp, len);
961*5c51f124SMoriah Waterland 			}
962*5c51f124SMoriah Waterland 		}
963*5c51f124SMoriah Waterland 	}
964*5c51f124SMoriah Waterland 
965*5c51f124SMoriah Waterland 	/*
966*5c51f124SMoriah Waterland 	 * *********************************************************************
967*5c51f124SMoriah Waterland 	 * end of main loop processing entries from contents file
968*5c51f124SMoriah Waterland 	 * the loop is broken out of when an exact match for the
969*5c51f124SMoriah Waterland 	 * path being searched for has been found and the type is one of:
970*5c51f124SMoriah Waterland 	 *   - ?fvelspcbdx
971*5c51f124SMoriah Waterland 	 * at this point parsing is at the first character past the full path
972*5c51f124SMoriah Waterland 	 * name on an exact match for the path being looked for - parse the
973*5c51f124SMoriah Waterland 	 * remainder of the entries information into the ept structure.
974*5c51f124SMoriah Waterland 	 * *********************************************************************
975*5c51f124SMoriah Waterland 	 */
976*5c51f124SMoriah Waterland 
977*5c51f124SMoriah Waterland 	/* link/symbolic link must have link destination */
978*5c51f124SMoriah Waterland 
979*5c51f124SMoriah Waterland 	if (((ept->ftype == 's') || (ept->ftype == 'l')) &&
980*5c51f124SMoriah Waterland 					(ept->ainfo.local == NULL)) {
981*5c51f124SMoriah Waterland 		/* copy path found to 'lpath' */
982*5c51f124SMoriah Waterland 		COPYPATH(lpath, cpath_start, cpath_len);
983*5c51f124SMoriah Waterland 
984*5c51f124SMoriah Waterland 		setErrstr(ERR_NO_LINK_SOURCE_SPECIFIED);
985*5c51f124SMoriah Waterland 		findend(&vfpGetCurrCharPtr(cfVfp));
986*5c51f124SMoriah Waterland 		return (-1);
987*5c51f124SMoriah Waterland 	}
988*5c51f124SMoriah Waterland 
989*5c51f124SMoriah Waterland 	/* character/block devices have major/minor device numbers */
990*5c51f124SMoriah Waterland 
991*5c51f124SMoriah Waterland 	if (((ept->ftype == 'c') || (ept->ftype == 'b'))) {
992*5c51f124SMoriah Waterland 		ept->ainfo.major = BADMAJOR;
993*5c51f124SMoriah Waterland 		ept->ainfo.minor = BADMINOR;
994*5c51f124SMoriah Waterland 		if (getnumvfp(&vfpGetCurrCharPtr(cfVfp), 10,
995*5c51f124SMoriah Waterland 				(long *)&ept->ainfo.major, BADMAJOR) ||
996*5c51f124SMoriah Waterland 		    getnumvfp(&vfpGetCurrCharPtr(cfVfp), 10,
997*5c51f124SMoriah Waterland 				(long *)&ept->ainfo.minor, BADMINOR)) {
998*5c51f124SMoriah Waterland 			/* copy path found to 'lpath' */
999*5c51f124SMoriah Waterland 			COPYPATH(lpath, cpath_start, cpath_len);
1000*5c51f124SMoriah Waterland 
1001*5c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_CANNOT_READ_MM_NUMS));
1002*5c51f124SMoriah Waterland 			findend(&vfpGetCurrCharPtr(cfVfp));
1003*5c51f124SMoriah Waterland 			return (-1);
1004*5c51f124SMoriah Waterland 		}
1005*5c51f124SMoriah Waterland 	}
1006*5c51f124SMoriah Waterland 
1007*5c51f124SMoriah Waterland 	/* most types have mode, owner, group identification components */
1008*5c51f124SMoriah Waterland 
1009*5c51f124SMoriah Waterland 	if ((ept->ftype == 'd') || (ept->ftype == 'x') || (ept->ftype == 'c') ||
1010*5c51f124SMoriah Waterland 		(ept->ftype == 'b') || (ept->ftype == 'p') ||
1011*5c51f124SMoriah Waterland 		(ept->ftype == 'f') || (ept->ftype == 'v') ||
1012*5c51f124SMoriah Waterland 		(ept->ftype == 'e')) {
1013*5c51f124SMoriah Waterland 		/* mode, owner, group should be here */
1014*5c51f124SMoriah Waterland 		if (getnumvfp(&vfpGetCurrCharPtr(cfVfp), 8,
1015*5c51f124SMoriah Waterland 				(long *)&ept->ainfo.mode, BADMODE) ||
1016*5c51f124SMoriah Waterland 		    getstr(&vfpGetCurrCharPtr(cfVfp), sizeof (ept->ainfo.owner),
1017*5c51f124SMoriah Waterland 				ept->ainfo.owner, ISWORDSEP) ||
1018*5c51f124SMoriah Waterland 		    getstr(&vfpGetCurrCharPtr(cfVfp), sizeof (ept->ainfo.group),
1019*5c51f124SMoriah Waterland 				ept->ainfo.group, ISWORDSEP)) {
1020*5c51f124SMoriah Waterland 			/* copy path found to 'lpath' */
1021*5c51f124SMoriah Waterland 			COPYPATH(lpath, cpath_start, cpath_len);
1022*5c51f124SMoriah Waterland 
1023*5c51f124SMoriah Waterland 			setErrstr(ERR_CANNOT_READ_MOG);
1024*5c51f124SMoriah Waterland 			findend(&vfpGetCurrCharPtr(cfVfp));
1025*5c51f124SMoriah Waterland 			return (-1);
1026*5c51f124SMoriah Waterland 		}
1027*5c51f124SMoriah Waterland 	}
1028*5c51f124SMoriah Waterland 
1029*5c51f124SMoriah Waterland 	/* i/f/v/e have size, checksum, modification time components */
1030*5c51f124SMoriah Waterland 
1031*5c51f124SMoriah Waterland 	if ((ept->ftype == 'i') || (ept->ftype == 'f') ||
1032*5c51f124SMoriah Waterland 			(ept->ftype == 'v') || (ept->ftype == 'e')) {
1033*5c51f124SMoriah Waterland 		/* look for content description */
1034*5c51f124SMoriah Waterland 		if (getlnumvfp(&vfpGetCurrCharPtr(cfVfp), 10,
1035*5c51f124SMoriah Waterland 				(fsblkcnt_t *)&ept->cinfo.size, BADCONT) ||
1036*5c51f124SMoriah Waterland 		    getnumvfp(&vfpGetCurrCharPtr(cfVfp), 10,
1037*5c51f124SMoriah Waterland 				(long *)&ept->cinfo.cksum, BADCONT) ||
1038*5c51f124SMoriah Waterland 		    getnumvfp(&vfpGetCurrCharPtr(cfVfp), 10,
1039*5c51f124SMoriah Waterland 				(long *)&ept->cinfo.modtime, BADCONT)) {
1040*5c51f124SMoriah Waterland 			/* copy path found to 'lpath' */
1041*5c51f124SMoriah Waterland 			COPYPATH(lpath, cpath_start, cpath_len);
1042*5c51f124SMoriah Waterland 
1043*5c51f124SMoriah Waterland 			setErrstr(ERR_CANNOT_READ_CONTENT_INFO);
1044*5c51f124SMoriah Waterland 			findend(&vfpGetCurrCharPtr(cfVfp));
1045*5c51f124SMoriah Waterland 			return (-1);
1046*5c51f124SMoriah Waterland 		}
1047*5c51f124SMoriah Waterland 	}
1048*5c51f124SMoriah Waterland 
1049*5c51f124SMoriah Waterland 	/* i files processing is completed - return 'exact match found' */
1050*5c51f124SMoriah Waterland 
1051*5c51f124SMoriah Waterland 	if (ept->ftype == 'i') {
1052*5c51f124SMoriah Waterland 		/* copy path found to 'lpath' */
1053*5c51f124SMoriah Waterland 		COPYPATH(lpath, cpath_start, cpath_len);
1054*5c51f124SMoriah Waterland 
1055*5c51f124SMoriah Waterland 		if (getend(&vfpGetCurrCharPtr(cfVfp))) {
1056*5c51f124SMoriah Waterland 			/* copy path found to 'lpath' */
1057*5c51f124SMoriah Waterland 			COPYPATH(lpath, cpath_start, cpath_len);
1058*5c51f124SMoriah Waterland 
1059*5c51f124SMoriah Waterland 			setErrstr(ERR_EXTRA_TOKENS);
1060*5c51f124SMoriah Waterland 			return (-1);
1061*5c51f124SMoriah Waterland 		}
1062*5c51f124SMoriah Waterland 
1063*5c51f124SMoriah Waterland 		/* write out any skipped data before returning */
1064*5c51f124SMoriah Waterland 		if (dataSkipped && (cfTmpVfp != (VFP_T *)NULL)) {
1065*5c51f124SMoriah Waterland 			WRITEDATA(cfTmpVfp, firstPos, lastPos);
1066*5c51f124SMoriah Waterland 		}
1067*5c51f124SMoriah Waterland 
1068*5c51f124SMoriah Waterland 		return (1);
1069*5c51f124SMoriah Waterland 	}
1070*5c51f124SMoriah Waterland 
1071*5c51f124SMoriah Waterland 	/*
1072*5c51f124SMoriah Waterland 	 * determine list of packages which reference this entry
1073*5c51f124SMoriah Waterland 	 */
1074*5c51f124SMoriah Waterland 
1075*5c51f124SMoriah Waterland 	lastpinfo = (struct pinfo *)NULL;
1076*5c51f124SMoriah Waterland 	while ((c = getstr(&vfpGetCurrCharPtr(cfVfp), sizeof (pkgname),
1077*5c51f124SMoriah Waterland 						pkgname, ISPKGNAMESEP)) <= 0) {
1078*5c51f124SMoriah Waterland 		/* if c < 0 the string was too long to fix in the buffer */
1079*5c51f124SMoriah Waterland 
1080*5c51f124SMoriah Waterland 		if (c < 0) {
1081*5c51f124SMoriah Waterland 			/* copy path found to 'lpath' */
1082*5c51f124SMoriah Waterland 			COPYPATH(lpath, cpath_start, cpath_len);
1083*5c51f124SMoriah Waterland 
1084*5c51f124SMoriah Waterland 			setErrstr(ERR_PACKAGE_NAME_TOO_LONG);
1085*5c51f124SMoriah Waterland 			findend(&vfpGetCurrCharPtr(cfVfp));
1086*5c51f124SMoriah Waterland 			return (-1);
1087*5c51f124SMoriah Waterland 		}
1088*5c51f124SMoriah Waterland 
1089*5c51f124SMoriah Waterland 		/* a package is present - create and populate pinfo structure */
1090*5c51f124SMoriah Waterland 
1091*5c51f124SMoriah Waterland 		pinfo = (struct pinfo *)calloc(1, sizeof (struct pinfo));
1092*5c51f124SMoriah Waterland 		if (!pinfo) {
1093*5c51f124SMoriah Waterland 			/* copy path found to 'lpath' */
1094*5c51f124SMoriah Waterland 			COPYPATH(lpath, cpath_start, cpath_len);
1095*5c51f124SMoriah Waterland 
1096*5c51f124SMoriah Waterland 			setErrstr(ERR_NO_MEMORY);
1097*5c51f124SMoriah Waterland 			findend(&vfpGetCurrCharPtr(cfVfp));
1098*5c51f124SMoriah Waterland 			return (-1);
1099*5c51f124SMoriah Waterland 		}
1100*5c51f124SMoriah Waterland 		if (!lastpinfo) {
1101*5c51f124SMoriah Waterland 			ept->pinfo = pinfo; /* first one */
1102*5c51f124SMoriah Waterland 		} else {
1103*5c51f124SMoriah Waterland 			lastpinfo->next = pinfo; /* link list */
1104*5c51f124SMoriah Waterland 		}
1105*5c51f124SMoriah Waterland 		lastpinfo = pinfo;
1106*5c51f124SMoriah Waterland 
1107*5c51f124SMoriah Waterland 		if ((pkgname[0] == '-') || (pkgname[0] == '+') ||
1108*5c51f124SMoriah Waterland 			(pkgname[0] == '*') || (pkgname[0] == '~') ||
1109*5c51f124SMoriah Waterland 			(pkgname[0] == '!') || (pkgname[0] == '%')) {
1110*5c51f124SMoriah Waterland 			pinfo->status = pkgname[0];
1111*5c51f124SMoriah Waterland 			(void) strlcpy(pinfo->pkg, pkgname+1,
1112*5c51f124SMoriah Waterland 							sizeof (pinfo->pkg));
1113*5c51f124SMoriah Waterland 		} else {
1114*5c51f124SMoriah Waterland 			(void) strlcpy(pinfo->pkg, pkgname,
1115*5c51f124SMoriah Waterland 							sizeof (pinfo->pkg));
1116*5c51f124SMoriah Waterland 		}
1117*5c51f124SMoriah Waterland 
1118*5c51f124SMoriah Waterland 		/* pkg/[:[ftype][:class] */
1119*5c51f124SMoriah Waterland 		c = (vfpGetc(cfVfp));
1120*5c51f124SMoriah Waterland 		if (c == '\\') {
1121*5c51f124SMoriah Waterland 			/* get alternate ftype */
1122*5c51f124SMoriah Waterland 			pinfo->editflag++;
1123*5c51f124SMoriah Waterland 			c = (vfpGetc(cfVfp));
1124*5c51f124SMoriah Waterland 		}
1125*5c51f124SMoriah Waterland 
1126*5c51f124SMoriah Waterland 		if (c == ':') {
1127*5c51f124SMoriah Waterland 			/* get special classname */
1128*5c51f124SMoriah Waterland 			(void) getstr(&vfpGetCurrCharPtr(cfVfp),
1129*5c51f124SMoriah Waterland 				sizeof (classname), classname, ISWORDSEP);
1130*5c51f124SMoriah Waterland 			(void) strlcpy(pinfo->aclass, classname,
1131*5c51f124SMoriah Waterland 							sizeof (pinfo->aclass));
1132*5c51f124SMoriah Waterland 			c = (vfpGetc(cfVfp));
1133*5c51f124SMoriah Waterland 		}
1134*5c51f124SMoriah Waterland 		ept->npkgs++;
1135*5c51f124SMoriah Waterland 
1136*5c51f124SMoriah Waterland 		/* break out of while if at end of entry */
1137*5c51f124SMoriah Waterland 
1138*5c51f124SMoriah Waterland 		if ((c == '\n') || (c == '\0')) {
1139*5c51f124SMoriah Waterland 			break;
1140*5c51f124SMoriah Waterland 		}
1141*5c51f124SMoriah Waterland 
1142*5c51f124SMoriah Waterland 		/* if package not separated by a space return an error */
1143*5c51f124SMoriah Waterland 
1144*5c51f124SMoriah Waterland 		if (!isspace(c)) {
1145*5c51f124SMoriah Waterland 			/* copy path found to 'lpath' */
1146*5c51f124SMoriah Waterland 			COPYPATH(lpath, cpath_start, cpath_len);
1147*5c51f124SMoriah Waterland 
1148*5c51f124SMoriah Waterland 			setErrstr(ERR_BAD_ENTRY_END);
1149*5c51f124SMoriah Waterland 			findend(&vfpGetCurrCharPtr(cfVfp));
1150*5c51f124SMoriah Waterland 			return (-1);
1151*5c51f124SMoriah Waterland 		}
1152*5c51f124SMoriah Waterland 	}
1153*5c51f124SMoriah Waterland 
1154*5c51f124SMoriah Waterland 	/*
1155*5c51f124SMoriah Waterland 	 * parsing of the entry is complete
1156*5c51f124SMoriah Waterland 	 */
1157*5c51f124SMoriah Waterland 
1158*5c51f124SMoriah Waterland 	/* copy path found to 'lpath' */
1159*5c51f124SMoriah Waterland 	COPYPATH(lpath, cpath_start, cpath_len);
1160*5c51f124SMoriah Waterland 
1161*5c51f124SMoriah Waterland 	/* write out any skipped data before returning */
1162*5c51f124SMoriah Waterland 	if (dataSkipped && (cfTmpVfp != (VFP_T *)NULL)) {
1163*5c51f124SMoriah Waterland 		WRITEDATA(cfTmpVfp, firstPos, lastPos);
1164*5c51f124SMoriah Waterland 	}
1165*5c51f124SMoriah Waterland 
1166*5c51f124SMoriah Waterland 	/* if not at the end of the entry, make it so */
1167*5c51f124SMoriah Waterland 
1168*5c51f124SMoriah Waterland 	if ((c != '\n') && (c != '\0')) {
1169*5c51f124SMoriah Waterland 		if (getend(&vfpGetCurrCharPtr(cfVfp)) && ept->pinfo) {
1170*5c51f124SMoriah Waterland 			setErrstr(ERR_EXTRA_TOKENS);
1171*5c51f124SMoriah Waterland 			return (-1);
1172*5c51f124SMoriah Waterland 		}
1173*5c51f124SMoriah Waterland 	}
1174*5c51f124SMoriah Waterland 
1175*5c51f124SMoriah Waterland 	return (1);
1176*5c51f124SMoriah Waterland }
1177*5c51f124SMoriah Waterland 
1178*5c51f124SMoriah Waterland static int
1179*5c51f124SMoriah Waterland getstr(char **cp, int n, char *str, int separator[])
1180*5c51f124SMoriah Waterland {
1181*5c51f124SMoriah Waterland 	int	c;
1182*5c51f124SMoriah Waterland 	char	*p = *cp;
1183*5c51f124SMoriah Waterland 	char	*p1;
1184*5c51f124SMoriah Waterland 	size_t	len;
1185*5c51f124SMoriah Waterland 
1186*5c51f124SMoriah Waterland 	if (*p == '\0') {
1187*5c51f124SMoriah Waterland 		return (1);
1188*5c51f124SMoriah Waterland 	}
1189*5c51f124SMoriah Waterland 
1190*5c51f124SMoriah Waterland 	/* leading white space ignored */
1191*5c51f124SMoriah Waterland 
1192*5c51f124SMoriah Waterland 	while (((c = *p) != '\0') && (isspace(*p++)))
1193*5c51f124SMoriah Waterland 		;
1194*5c51f124SMoriah Waterland 	if ((c == '\0') || (c == '\n')) {
1195*5c51f124SMoriah Waterland 		p--;
1196*5c51f124SMoriah Waterland 		*cp = p;
1197*5c51f124SMoriah Waterland 		return (1); /* nothing there */
1198*5c51f124SMoriah Waterland 	}
1199*5c51f124SMoriah Waterland 
1200*5c51f124SMoriah Waterland 	p--;
1201*5c51f124SMoriah Waterland 
1202*5c51f124SMoriah Waterland 	/* compute length based on delimiter found or not */
1203*5c51f124SMoriah Waterland 
1204*5c51f124SMoriah Waterland 	p1 = p;
1205*5c51f124SMoriah Waterland 	while (separator[(int)*p1] == 0) {
1206*5c51f124SMoriah Waterland 		p1++;
1207*5c51f124SMoriah Waterland 	}
1208*5c51f124SMoriah Waterland 
1209*5c51f124SMoriah Waterland 	len = (ptrdiff_t)p1 - (ptrdiff_t)p;
1210*5c51f124SMoriah Waterland 
1211*5c51f124SMoriah Waterland 	/* if string will fit in result buffer copy string and return success */
1212*5c51f124SMoriah Waterland 
1213*5c51f124SMoriah Waterland 	if (len < n) {
1214*5c51f124SMoriah Waterland 		(void) memcpy(str, p, len);
1215*5c51f124SMoriah Waterland 		str[len] = '\0';
1216*5c51f124SMoriah Waterland 		p += len;
1217*5c51f124SMoriah Waterland 		*cp = p;
1218*5c51f124SMoriah Waterland 		return (0);
1219*5c51f124SMoriah Waterland 	}
1220*5c51f124SMoriah Waterland 
1221*5c51f124SMoriah Waterland 	/* result buffer too small; copy partial string, return error */
1222*5c51f124SMoriah Waterland 	(void) memcpy(str, p, n-1);
1223*5c51f124SMoriah Waterland 	str[n-1] = '\0';
1224*5c51f124SMoriah Waterland 	p += n;
1225*5c51f124SMoriah Waterland 	*cp = p;
1226*5c51f124SMoriah Waterland 	return (-1);
1227*5c51f124SMoriah Waterland }
1228*5c51f124SMoriah Waterland 
1229*5c51f124SMoriah Waterland static int
1230*5c51f124SMoriah Waterland getend(char **cp)
1231*5c51f124SMoriah Waterland {
1232*5c51f124SMoriah Waterland 	int	n;
1233*5c51f124SMoriah Waterland 	char	*p = *cp;
1234*5c51f124SMoriah Waterland 
1235*5c51f124SMoriah Waterland 	n = 0;
1236*5c51f124SMoriah Waterland 
1237*5c51f124SMoriah Waterland 	/* if at end of buffer return no more characters left */
1238*5c51f124SMoriah Waterland 
1239*5c51f124SMoriah Waterland 	if (*p == '\0') {
1240*5c51f124SMoriah Waterland 		return (0);
1241*5c51f124SMoriah Waterland 	}
1242*5c51f124SMoriah Waterland 
1243*5c51f124SMoriah Waterland 	while ((*p != '\0') && (*p != '\n')) {
1244*5c51f124SMoriah Waterland 		if (n == 0) {
1245*5c51f124SMoriah Waterland 			if (!isspace(*p)) {
1246*5c51f124SMoriah Waterland 				n++;
1247*5c51f124SMoriah Waterland 			}
1248*5c51f124SMoriah Waterland 		}
1249*5c51f124SMoriah Waterland 		p++;
1250*5c51f124SMoriah Waterland 	}
1251*5c51f124SMoriah Waterland 
1252*5c51f124SMoriah Waterland 	*cp = ++p;
1253*5c51f124SMoriah Waterland 	return (n);
1254*5c51f124SMoriah Waterland }
1255*5c51f124SMoriah Waterland 
1256*5c51f124SMoriah Waterland static void
1257*5c51f124SMoriah Waterland findend(char **cp)
1258*5c51f124SMoriah Waterland {
1259*5c51f124SMoriah Waterland 	char	*p1;
1260*5c51f124SMoriah Waterland 	char	*p = *cp;
1261*5c51f124SMoriah Waterland 
1262*5c51f124SMoriah Waterland 	/* if at end of buffer return no more characters left */
1263*5c51f124SMoriah Waterland 
1264*5c51f124SMoriah Waterland 	if (*p == '\0') {
1265*5c51f124SMoriah Waterland 		return;
1266*5c51f124SMoriah Waterland 	}
1267*5c51f124SMoriah Waterland 
1268*5c51f124SMoriah Waterland 	/* find the end of the line */
1269*5c51f124SMoriah Waterland 
1270*5c51f124SMoriah Waterland 	p1 = strchr(p, '\n');
1271*5c51f124SMoriah Waterland 
1272*5c51f124SMoriah Waterland 	if (p1 != (char *)NULL) {
1273*5c51f124SMoriah Waterland 		*cp = ++p1;
1274*5c51f124SMoriah Waterland 		return;
1275*5c51f124SMoriah Waterland 	}
1276*5c51f124SMoriah Waterland 
1277*5c51f124SMoriah Waterland 	*cp = strchr(p, '\0');
1278*5c51f124SMoriah Waterland }
1279