15c51f124SMoriah Waterland /*
25c51f124SMoriah Waterland  * CDDL HEADER START
35c51f124SMoriah Waterland  *
45c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
55c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
65c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
75c51f124SMoriah Waterland  *
85c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
105c51f124SMoriah Waterland  * See the License for the specific language governing permissions
115c51f124SMoriah Waterland  * and limitations under the License.
125c51f124SMoriah Waterland  *
135c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
145c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
165c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
175c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
185c51f124SMoriah Waterland  *
195c51f124SMoriah Waterland  * CDDL HEADER END
205c51f124SMoriah Waterland  */
215c51f124SMoriah Waterland 
225c51f124SMoriah Waterland /*
235c51f124SMoriah Waterland  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
245c51f124SMoriah Waterland  * Use is subject to license terms.
255c51f124SMoriah Waterland  */
265c51f124SMoriah Waterland 
275c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
285c51f124SMoriah Waterland /* All Rights Reserved */
295c51f124SMoriah Waterland 
305c51f124SMoriah Waterland #include <stdio.h>
315c51f124SMoriah Waterland #include <limits.h>
325c51f124SMoriah Waterland #include <stdlib.h>
335c51f124SMoriah Waterland #include <string.h>
345c51f124SMoriah Waterland #include <strings.h>
355c51f124SMoriah Waterland #include <ctype.h>
365c51f124SMoriah Waterland #include <sys/types.h>
375c51f124SMoriah Waterland #include <libintl.h>
385c51f124SMoriah Waterland #include "pkglib.h"
395c51f124SMoriah Waterland #include "pkgstrct.h"
405c51f124SMoriah Waterland #include "pkglocale.h"
415c51f124SMoriah Waterland #include "pkglibmsgs.h"
425c51f124SMoriah Waterland 
435c51f124SMoriah Waterland /*
445c51f124SMoriah Waterland  * Forward declarations
455c51f124SMoriah Waterland  */
465c51f124SMoriah Waterland 
475c51f124SMoriah Waterland static int	getend(char **cp);
485c51f124SMoriah Waterland static int	getstr(char **cp, int n, char *str, int separator[]);
495c51f124SMoriah Waterland 
505c51f124SMoriah Waterland /* from gpkgmap.c */
515c51f124SMoriah Waterland int	getnumvfp(char **cp, int base, long *d, long bad);
525c51f124SMoriah Waterland int	getlnumvfp(char **cp, int base, fsblkcnt_t *d, long bad);
535c51f124SMoriah Waterland 
545c51f124SMoriah Waterland /*
555c51f124SMoriah Waterland  * Module globals
565c51f124SMoriah Waterland  */
575c51f124SMoriah Waterland 
585c51f124SMoriah Waterland static char	lpath[PATH_MAX];	/* for ept->path */
595c51f124SMoriah Waterland static char	mylocal[PATH_MAX];	/* for ept->ainfo.local */
605c51f124SMoriah Waterland static int	decisionTableInit = 0;
615c51f124SMoriah Waterland 
625c51f124SMoriah Waterland /*
635c51f124SMoriah Waterland  * These arrays must be indexable by an unsigned char.
645c51f124SMoriah Waterland  */
655c51f124SMoriah Waterland 
665c51f124SMoriah Waterland static int	ISWORDSEP[UCHAR_MAX+1];
675c51f124SMoriah Waterland static int	ISPKGNAMESEP[UCHAR_MAX+1];
685c51f124SMoriah Waterland 
695c51f124SMoriah Waterland /*
705c51f124SMoriah Waterland  * Name:	COPYPATH
715c51f124SMoriah Waterland  * Description:	copy path limiting size to destination capacity
725c51f124SMoriah Waterland  * Arguments:	DEST - (char []) - [RW]
735c51f124SMoriah Waterland  *		SRC - (char *) - [RO, *RO]
745c51f124SMoriah Waterland  *			Pointer to first byte of path to copy
755c51f124SMoriah Waterland  *		LEN - (int) - [RO]
765c51f124SMoriah Waterland  *			Number of bytes to copy
775c51f124SMoriah Waterland  */
785c51f124SMoriah Waterland 
795c51f124SMoriah Waterland #define	COPYPATH(DEST, SRC, LEN)					\
805c51f124SMoriah Waterland 	{								\
815c51f124SMoriah Waterland 		/* assure return path does not overflow */		\
825c51f124SMoriah Waterland 		if ((LEN) > sizeof ((DEST))) {				\
835c51f124SMoriah Waterland 			(LEN) = sizeof ((DEST))-1;			\
845c51f124SMoriah Waterland 		}							\
855c51f124SMoriah Waterland 		/* copy return path to local storage */			\
865c51f124SMoriah Waterland 		(void) memcpy((DEST), (SRC), (LEN));			\
875c51f124SMoriah Waterland 		(DEST)[(LEN)] = '\0';					\
885c51f124SMoriah Waterland 	}
895c51f124SMoriah Waterland 
905c51f124SMoriah Waterland /*
915c51f124SMoriah Waterland  * Name:	srchcfile
925c51f124SMoriah Waterland  * Description:	search contents file looking for closest match to entry,
935c51f124SMoriah Waterland  *		creating a new contents file if output contents file specified
945c51f124SMoriah Waterland  * Arguments:	ept - (struct cfent *) - [RO, *RW]
955c51f124SMoriah Waterland  *			- contents file entry, describing last item found
965c51f124SMoriah Waterland  *		path - (char *) - [RO, *RO]
975c51f124SMoriah Waterland  *			- path to search for in contents file
985c51f124SMoriah Waterland  *			- If path is "*", then the next entry is returned;
995c51f124SMoriah Waterland  *				the next entry always matches this path
100*62224350SCasper H.S. Dik  *		PKGserver
101*62224350SCasper H.S. Dik  *			- our door to the database server.
102*62224350SCasper H.S. Dik  *
1035c51f124SMoriah Waterland  * Returns:	int
1045c51f124SMoriah Waterland  *		< 0 - error occurred
1055c51f124SMoriah Waterland  *			- Use getErrstr to retrieve character-string describing
1065c51f124SMoriah Waterland  *			  the reason for failure
1075c51f124SMoriah Waterland  *		== 0 - no match found
1085c51f124SMoriah Waterland  *			- specified path not in the contents file
1095c51f124SMoriah Waterland  *		== 1 - exact match found
1105c51f124SMoriah Waterland  *			- specified path found in contents file
1115c51f124SMoriah Waterland  *			- this value is always returned if path is "*" and the
112*62224350SCasper H.S. Dik  *			  next entry is returned - 0 is returned when no more
1135c51f124SMoriah Waterland  *			  entries are left to process
1145c51f124SMoriah Waterland  * Side Effects:
1155c51f124SMoriah Waterland  *		- The ept structure supplied is filled in with a description of
1165c51f124SMoriah Waterland  *		  the item that caused the search to terminate, except in the
1175c51f124SMoriah Waterland  *		  case of '0' in which case the contents of 'ept' is undefined.
1185c51f124SMoriah Waterland  *		- NOTE: the ept->path item points to a path that is statically
1195c51f124SMoriah Waterland  *		  allocated and will be overwritten on the next call.
1205c51f124SMoriah Waterland  *		- NOTE: the ept->ainfo.local item points to a path that is
1215c51f124SMoriah Waterland  *		  statically allocated and will be overwritten on the next call.
1225c51f124SMoriah Waterland  */
1235c51f124SMoriah Waterland 
1245c51f124SMoriah Waterland int
srchcfile(struct cfent * ept,char * path,PKGserver server)125*62224350SCasper H.S. Dik srchcfile(struct cfent *ept, char *path, PKGserver server)
1265c51f124SMoriah Waterland {
127*62224350SCasper H.S. Dik 	char		*cpath_start = NULL;
1285c51f124SMoriah Waterland 	char		classname[CLSSIZ+1];
1295c51f124SMoriah Waterland 	char		pkgname[PKGSIZ+1];
1305c51f124SMoriah Waterland 	int		anypath = 0;
1315c51f124SMoriah Waterland 	int		c;
132*62224350SCasper H.S. Dik 	int		cpath_len = 0;
1335c51f124SMoriah Waterland 	struct pinfo	*lastpinfo;
1345c51f124SMoriah Waterland 	struct pinfo	*pinfo;
135*62224350SCasper H.S. Dik 	char		*p;
136*62224350SCasper H.S. Dik 	char		*curbuf;
137*62224350SCasper H.S. Dik 	int		linelen;	/* includes NUL */
1385c51f124SMoriah Waterland 
1395c51f124SMoriah Waterland 	/*
1405c51f124SMoriah Waterland 	 * this code does not use nested subroutines because execution time
1415c51f124SMoriah Waterland 	 * of this routine is especially critical to installation and upgrade
1425c51f124SMoriah Waterland 	 */
1435c51f124SMoriah Waterland 
1445c51f124SMoriah Waterland 	/* initialize local variables */
1455c51f124SMoriah Waterland 
1465c51f124SMoriah Waterland 	setErrstr(NULL);	/* no error message currently cached */
1475c51f124SMoriah Waterland 	lpath[0] = '\0';
1485c51f124SMoriah Waterland 	lpath[sizeof (lpath)-1] = '\0';
1495c51f124SMoriah Waterland 
1505c51f124SMoriah Waterland 	/* initialize ept structure values */
1515c51f124SMoriah Waterland 
1525c51f124SMoriah Waterland 	(void) strlcpy(ept->ainfo.group, BADGROUP, sizeof (ept->ainfo.group));
1535c51f124SMoriah Waterland 	(void) strlcpy(ept->ainfo.owner, BADOWNER, sizeof (ept->ainfo.owner));
1545c51f124SMoriah Waterland 	(void) strlcpy(ept->pkg_class, BADCLASS,  sizeof (ept->pkg_class));
1555c51f124SMoriah Waterland 	ept->ainfo.local = (char *)NULL;
1565c51f124SMoriah Waterland 	ept->ainfo.mode = BADMODE;
1575c51f124SMoriah Waterland 	ept->cinfo.cksum = BADCONT;
1585c51f124SMoriah Waterland 	ept->cinfo.modtime = BADCONT;
1595c51f124SMoriah Waterland 	ept->cinfo.size = (fsblkcnt_t)BADCONT;
1605c51f124SMoriah Waterland 	ept->ftype = BADFTYPE;
1615c51f124SMoriah Waterland 	ept->npkgs = 0;
1625c51f124SMoriah Waterland 	ept->path = (char *)NULL;
1635c51f124SMoriah Waterland 	ept->pinfo = (struct pinfo *)NULL;
1645c51f124SMoriah Waterland 	ept->pkg_class_idx = -1;
1655c51f124SMoriah Waterland 	ept->volno = 0;
1665c51f124SMoriah Waterland 
1675c51f124SMoriah Waterland 	/*
1685c51f124SMoriah Waterland 	 * populate decision tables that implement fast character checking;
1695c51f124SMoriah Waterland 	 * this is much faster than the equivalent strpbrk() call or a
1705c51f124SMoriah Waterland 	 * while() loop checking for the characters. It is only faster if
1715c51f124SMoriah Waterland 	 * there are at least 3 characters to scan for - when checking for
1725c51f124SMoriah Waterland 	 * one or two characters (such as '\n' or '\0') its faster to do
1735c51f124SMoriah Waterland 	 * a simple while() loop.
1745c51f124SMoriah Waterland 	 */
1755c51f124SMoriah Waterland 
1765c51f124SMoriah Waterland 	if (decisionTableInit == 0) {
1775c51f124SMoriah Waterland 		/*
1785c51f124SMoriah Waterland 		 * any chars listed stop scan;
1795c51f124SMoriah Waterland 		 * scan stops on first byte found that is set to '1' below
1805c51f124SMoriah Waterland 		 */
1815c51f124SMoriah Waterland 
1825c51f124SMoriah Waterland 		/*
1835c51f124SMoriah Waterland 		 * Separators for normal words
1845c51f124SMoriah Waterland 		 */
1855c51f124SMoriah Waterland 		bzero(ISWORDSEP, sizeof (ISWORDSEP));
1865c51f124SMoriah Waterland 		ISWORDSEP[' '] = 1;
1875c51f124SMoriah Waterland 		ISWORDSEP['\t'] = 1;
1885c51f124SMoriah Waterland 		ISWORDSEP['\n'] = 1;
1895c51f124SMoriah Waterland 		ISWORDSEP['\0'] = 1;
1905c51f124SMoriah Waterland 
1915c51f124SMoriah Waterland 		/*
1925c51f124SMoriah Waterland 		 * Separators for list of packages, includes \\ for
1935c51f124SMoriah Waterland 		 * alternate ftype and : for classname
1945c51f124SMoriah Waterland 		 */
1955c51f124SMoriah Waterland 		bzero(ISPKGNAMESEP, sizeof (ISPKGNAMESEP));
1965c51f124SMoriah Waterland 		ISPKGNAMESEP[' '] = 1;
1975c51f124SMoriah Waterland 		ISPKGNAMESEP['\t'] = 1;
1985c51f124SMoriah Waterland 		ISPKGNAMESEP['\n'] = 1;
1995c51f124SMoriah Waterland 		ISPKGNAMESEP[':'] = 1;
2005c51f124SMoriah Waterland 		ISPKGNAMESEP['\\'] = 1;
2015c51f124SMoriah Waterland 		ISPKGNAMESEP['\0'] = 1;
2025c51f124SMoriah Waterland 
2035c51f124SMoriah Waterland 		decisionTableInit = 1;
2045c51f124SMoriah Waterland 	}
2055c51f124SMoriah Waterland 
2065c51f124SMoriah Waterland 	/* if the path to scan for is empty, act like no path was specified */
2075c51f124SMoriah Waterland 
208*62224350SCasper H.S. Dik 	if ((path != NULL) && (*path == '\0')) {
209*62224350SCasper H.S. Dik 		path = NULL;
2105c51f124SMoriah Waterland 	}
2115c51f124SMoriah Waterland 
2125c51f124SMoriah Waterland 	/*
2135c51f124SMoriah Waterland 	 * if path to search for is "*", then we will return the first path
2145c51f124SMoriah Waterland 	 * we encounter as a match, otherwise we return an error
2155c51f124SMoriah Waterland 	 */
2165c51f124SMoriah Waterland 
217*62224350SCasper H.S. Dik 	if ((path != NULL) && (path[0] != '/')) {
2185c51f124SMoriah Waterland 		if (strcmp(path, "*") != 0) {
2195c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_ILLEGAL_SEARCH_PATH));
2205c51f124SMoriah Waterland 			return (-1);
2215c51f124SMoriah Waterland 		}
2225c51f124SMoriah Waterland 		anypath = 1;
2235c51f124SMoriah Waterland 	}
2245c51f124SMoriah Waterland 
2255c51f124SMoriah Waterland 	/* attempt to narrow down the search for the specified path */
2265c51f124SMoriah Waterland 
227*62224350SCasper H.S. Dik 	if (anypath == 0 && path == NULL)
228*62224350SCasper H.S. Dik 		return (0);
2295c51f124SMoriah Waterland 
230*62224350SCasper H.S. Dik 	/* determine first character of the next entry */
231*62224350SCasper H.S. Dik 	if (anypath == 0)
232*62224350SCasper H.S. Dik 		curbuf = pkggetentry_named(server, path, &linelen, &cpath_len);
233*62224350SCasper H.S. Dik 	else
234*62224350SCasper H.S. Dik 		curbuf = pkggetentry(server, &linelen, &cpath_len);
2355c51f124SMoriah Waterland 
236*62224350SCasper H.S. Dik 	if (curbuf == NULL)
2375c51f124SMoriah Waterland 		return (0);
2385c51f124SMoriah Waterland 
2395c51f124SMoriah Waterland 	/*
240*62224350SCasper H.S. Dik 	 * current entry DOES start with absolute path
241*62224350SCasper H.S. Dik 	 * set ept->path to point to lpath
242*62224350SCasper H.S. Dik 	 * set cpath_start/cpath_len to point to the file name
2435c51f124SMoriah Waterland 	 */
2445c51f124SMoriah Waterland 
245*62224350SCasper H.S. Dik 	/* copy first token into path element of passed structure */
2465c51f124SMoriah Waterland 
247*62224350SCasper H.S. Dik 	cpath_start = curbuf;
2485c51f124SMoriah Waterland 
249*62224350SCasper H.S. Dik 	p = cpath_start + cpath_len;
2505c51f124SMoriah Waterland 
251*62224350SCasper H.S. Dik 	ept->path = lpath;
2525c51f124SMoriah Waterland 
253*62224350SCasper H.S. Dik 	/* copy path found to 'lpath' */
254*62224350SCasper H.S. Dik 	COPYPATH(lpath, cpath_start, cpath_len);
2555c51f124SMoriah Waterland 
256*62224350SCasper H.S. Dik 	/* get first character following the end of the path */
2575c51f124SMoriah Waterland 
258*62224350SCasper H.S. Dik 	c = *p++;
2595c51f124SMoriah Waterland 
260*62224350SCasper H.S. Dik 	/*
261*62224350SCasper H.S. Dik 	 * we want to return information about this path in
262*62224350SCasper H.S. Dik 	 * the structure provided, so parse any local path
263*62224350SCasper H.S. Dik 	 * and jump to code which parses rest of the input line
264*62224350SCasper H.S. Dik 	 */
265*62224350SCasper H.S. Dik 	if (c == '=') {
266*62224350SCasper H.S. Dik 		/* parse local path specification */
267*62224350SCasper H.S. Dik 		if (getstr(&p, PATH_MAX, mylocal, ISWORDSEP)) {
268*62224350SCasper H.S. Dik 			setErrstr(ERR_CANNOT_READ_LL_PATH);
269*62224350SCasper H.S. Dik 			return (-1);
2705c51f124SMoriah Waterland 		}
271*62224350SCasper H.S. Dik 		ept->ainfo.local = mylocal;
272*62224350SCasper H.S. Dik 	}
2735c51f124SMoriah Waterland 
274*62224350SCasper H.S. Dik 	/*
275*62224350SCasper H.S. Dik 	 * if an exact match and processing a new style entry, read the
276*62224350SCasper H.S. Dik 	 * remaining information from the new style entry.
277*62224350SCasper H.S. Dik 	 */
2785c51f124SMoriah Waterland 
279*62224350SCasper H.S. Dik 	while (isspace((c = *p++)))
280*62224350SCasper H.S. Dik 		;
2815c51f124SMoriah Waterland 
282*62224350SCasper H.S. Dik 	switch (c) {
283*62224350SCasper H.S. Dik 	case '?': case 'f': case 'v': case 'e': case 'l':
284*62224350SCasper H.S. Dik 	case 's': case 'p': case 'c': case 'b': case 'd':
285*62224350SCasper H.S. Dik 	case 'x':
286*62224350SCasper H.S. Dik 		/* save ftype */
287*62224350SCasper H.S. Dik 		ept->ftype = (char)c;
2885c51f124SMoriah Waterland 
289*62224350SCasper H.S. Dik 		/* save class */
290*62224350SCasper H.S. Dik 		if (getstr(&p, CLSSIZ, ept->pkg_class, ISWORDSEP)) {
291*62224350SCasper H.S. Dik 			setErrstr(ERR_CANNOT_READ_CLASS_TOKEN);
292*62224350SCasper H.S. Dik 			return (-1);
2935c51f124SMoriah Waterland 		}
294*62224350SCasper H.S. Dik 		break; /* we already read the pathname */
2955c51f124SMoriah Waterland 
296*62224350SCasper H.S. Dik 	case '\0':
297*62224350SCasper H.S. Dik 		/* end of line before new-line seen */
298*62224350SCasper H.S. Dik 		setErrstr(ERR_INCOMPLETE_ENTRY);
299*62224350SCasper H.S. Dik 		return (-1);
3005c51f124SMoriah Waterland 
301*62224350SCasper H.S. Dik 	case '0': case '1': case '2': case '3': case '4':
302*62224350SCasper H.S. Dik 	case '5': case '6': case '7': case '8': case '9':
303*62224350SCasper H.S. Dik 		setErrstr(ERR_VOLUMENO_UNEXPECTED);
304*62224350SCasper H.S. Dik 		return (-1);
3055c51f124SMoriah Waterland 
306*62224350SCasper H.S. Dik 	case 'i':
307*62224350SCasper H.S. Dik 		setErrstr(ERR_FTYPE_I_UNEXPECTED);
308*62224350SCasper H.S. Dik 		return (-1);
3095c51f124SMoriah Waterland 
310*62224350SCasper H.S. Dik 	default:
311*62224350SCasper H.S. Dik 		/* unknown ftype */
312*62224350SCasper H.S. Dik 		setErrstr(ERR_UNKNOWN_FTYPE);
313*62224350SCasper H.S. Dik 		return (-1);
3145c51f124SMoriah Waterland 	}
3155c51f124SMoriah Waterland 
3165c51f124SMoriah Waterland 	/* link/symbolic link must have link destination */
3175c51f124SMoriah Waterland 
3185c51f124SMoriah Waterland 	if (((ept->ftype == 's') || (ept->ftype == 'l')) &&
319*62224350SCasper H.S. Dik 	    (ept->ainfo.local == NULL)) {
3205c51f124SMoriah Waterland 		setErrstr(ERR_NO_LINK_SOURCE_SPECIFIED);
3215c51f124SMoriah Waterland 		return (-1);
3225c51f124SMoriah Waterland 	}
3235c51f124SMoriah Waterland 
3245c51f124SMoriah Waterland 	/* character/block devices have major/minor device numbers */
3255c51f124SMoriah Waterland 
3265c51f124SMoriah Waterland 	if (((ept->ftype == 'c') || (ept->ftype == 'b'))) {
3275c51f124SMoriah Waterland 		ept->ainfo.major = BADMAJOR;
3285c51f124SMoriah Waterland 		ept->ainfo.minor = BADMINOR;
329*62224350SCasper H.S. Dik 		if (getnumvfp(&p, 10, (long *)&ept->ainfo.major, BADMAJOR) ||
330*62224350SCasper H.S. Dik 		    getnumvfp(&p, 10, (long *)&ept->ainfo.minor, BADMINOR)) {
3315c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_CANNOT_READ_MM_NUMS));
3325c51f124SMoriah Waterland 			return (-1);
3335c51f124SMoriah Waterland 		}
3345c51f124SMoriah Waterland 	}
3355c51f124SMoriah Waterland 
3365c51f124SMoriah Waterland 	/* most types have mode, owner, group identification components */
3375c51f124SMoriah Waterland 
3385c51f124SMoriah Waterland 	if ((ept->ftype == 'd') || (ept->ftype == 'x') || (ept->ftype == 'c') ||
339*62224350SCasper H.S. Dik 	    (ept->ftype == 'b') || (ept->ftype == 'p') ||
340*62224350SCasper H.S. Dik 	    (ept->ftype == 'f') || (ept->ftype == 'v') ||
341*62224350SCasper H.S. Dik 	    (ept->ftype == 'e')) {
3425c51f124SMoriah Waterland 		/* mode, owner, group should be here */
343*62224350SCasper H.S. Dik 		if (getnumvfp(&p, 8, (long *)&ept->ainfo.mode, BADMODE) ||
344*62224350SCasper H.S. Dik 		    getstr(&p, sizeof (ept->ainfo.owner), ept->ainfo.owner,
345*62224350SCasper H.S. Dik 		    ISWORDSEP) ||
346*62224350SCasper H.S. Dik 		    getstr(&p, sizeof (ept->ainfo.group), ept->ainfo.group,
347*62224350SCasper H.S. Dik 		    ISWORDSEP)) {
3485c51f124SMoriah Waterland 			setErrstr(ERR_CANNOT_READ_MOG);
3495c51f124SMoriah Waterland 			return (-1);
3505c51f124SMoriah Waterland 		}
3515c51f124SMoriah Waterland 	}
3525c51f124SMoriah Waterland 
3535c51f124SMoriah Waterland 	/* i/f/v/e have size, checksum, modification time components */
3545c51f124SMoriah Waterland 
3555c51f124SMoriah Waterland 	if ((ept->ftype == 'i') || (ept->ftype == 'f') ||
356*62224350SCasper H.S. Dik 	    (ept->ftype == 'v') || (ept->ftype == 'e')) {
3575c51f124SMoriah Waterland 		/* look for content description */
358*62224350SCasper H.S. Dik 		if (getlnumvfp(&p, 10, (fsblkcnt_t *)&ept->cinfo.size,
359*62224350SCasper H.S. Dik 		    BADCONT) ||
360*62224350SCasper H.S. Dik 		    getnumvfp(&p, 10, (long *)&ept->cinfo.cksum, BADCONT) ||
361*62224350SCasper H.S. Dik 		    getnumvfp(&p, 10, (long *)&ept->cinfo.modtime, BADCONT)) {
3625c51f124SMoriah Waterland 			setErrstr(ERR_CANNOT_READ_CONTENT_INFO);
3635c51f124SMoriah Waterland 			return (-1);
3645c51f124SMoriah Waterland 		}
3655c51f124SMoriah Waterland 	}
3665c51f124SMoriah Waterland 
3675c51f124SMoriah Waterland 	/* i files processing is completed - return 'exact match found' */
3685c51f124SMoriah Waterland 
3695c51f124SMoriah Waterland 	if (ept->ftype == 'i') {
3705c51f124SMoriah Waterland 		return (1);
3715c51f124SMoriah Waterland 	}
3725c51f124SMoriah Waterland 
3735c51f124SMoriah Waterland 	/*
3745c51f124SMoriah Waterland 	 * determine list of packages which reference this entry
3755c51f124SMoriah Waterland 	 */
3765c51f124SMoriah Waterland 
3775c51f124SMoriah Waterland 	lastpinfo = (struct pinfo *)NULL;
378*62224350SCasper H.S. Dik 	while ((c = getstr(&p, sizeof (pkgname), pkgname, ISPKGNAMESEP)) <= 0) {
3795c51f124SMoriah Waterland 		/* if c < 0 the string was too long to fix in the buffer */
3805c51f124SMoriah Waterland 
3815c51f124SMoriah Waterland 		if (c < 0) {
3825c51f124SMoriah Waterland 			setErrstr(ERR_PACKAGE_NAME_TOO_LONG);
3835c51f124SMoriah Waterland 			return (-1);
3845c51f124SMoriah Waterland 		}
3855c51f124SMoriah Waterland 
3865c51f124SMoriah Waterland 		/* a package is present - create and populate pinfo structure */
3875c51f124SMoriah Waterland 
3885c51f124SMoriah Waterland 		pinfo = (struct pinfo *)calloc(1, sizeof (struct pinfo));
3895c51f124SMoriah Waterland 		if (!pinfo) {
3905c51f124SMoriah Waterland 			setErrstr(ERR_NO_MEMORY);
3915c51f124SMoriah Waterland 			return (-1);
3925c51f124SMoriah Waterland 		}
3935c51f124SMoriah Waterland 		if (!lastpinfo) {
3945c51f124SMoriah Waterland 			ept->pinfo = pinfo; /* first one */
3955c51f124SMoriah Waterland 		} else {
3965c51f124SMoriah Waterland 			lastpinfo->next = pinfo; /* link list */
3975c51f124SMoriah Waterland 		}
3985c51f124SMoriah Waterland 		lastpinfo = pinfo;
3995c51f124SMoriah Waterland 
4005c51f124SMoriah Waterland 		if ((pkgname[0] == '-') || (pkgname[0] == '+') ||
401*62224350SCasper H.S. Dik 		    (pkgname[0] == '*') || (pkgname[0] == '~') ||
402*62224350SCasper H.S. Dik 		    (pkgname[0] == '!') || (pkgname[0] == '%')) {
4035c51f124SMoriah Waterland 			pinfo->status = pkgname[0];
4045c51f124SMoriah Waterland 			(void) strlcpy(pinfo->pkg, pkgname+1,
405*62224350SCasper H.S. Dik 			    sizeof (pinfo->pkg));
4065c51f124SMoriah Waterland 		} else {
4075c51f124SMoriah Waterland 			(void) strlcpy(pinfo->pkg, pkgname,
408*62224350SCasper H.S. Dik 			    sizeof (pinfo->pkg));
4095c51f124SMoriah Waterland 		}
4105c51f124SMoriah Waterland 
4115c51f124SMoriah Waterland 		/* pkg/[:[ftype][:class] */
412*62224350SCasper H.S. Dik 		c = *p++;
4135c51f124SMoriah Waterland 		if (c == '\\') {
4145c51f124SMoriah Waterland 			/* get alternate ftype */
4155c51f124SMoriah Waterland 			pinfo->editflag++;
416*62224350SCasper H.S. Dik 			c = *p++;
4175c51f124SMoriah Waterland 		}
4185c51f124SMoriah Waterland 
4195c51f124SMoriah Waterland 		if (c == ':') {
4205c51f124SMoriah Waterland 			/* get special classname */
421*62224350SCasper H.S. Dik 			(void) getstr(&p, sizeof (classname), classname,
422*62224350SCasper H.S. Dik 			    ISWORDSEP);
4235c51f124SMoriah Waterland 			(void) strlcpy(pinfo->aclass, classname,
424*62224350SCasper H.S. Dik 			    sizeof (pinfo->aclass));
425*62224350SCasper H.S. Dik 			c = *p++;
4265c51f124SMoriah Waterland 		}
4275c51f124SMoriah Waterland 		ept->npkgs++;
4285c51f124SMoriah Waterland 
4295c51f124SMoriah Waterland 		/* break out of while if at end of entry */
4305c51f124SMoriah Waterland 
4315c51f124SMoriah Waterland 		if ((c == '\n') || (c == '\0')) {
4325c51f124SMoriah Waterland 			break;
4335c51f124SMoriah Waterland 		}
4345c51f124SMoriah Waterland 
4355c51f124SMoriah Waterland 		/* if package not separated by a space return an error */
4365c51f124SMoriah Waterland 
4375c51f124SMoriah Waterland 		if (!isspace(c)) {
4385c51f124SMoriah Waterland 			setErrstr(ERR_BAD_ENTRY_END);
4395c51f124SMoriah Waterland 			return (-1);
4405c51f124SMoriah Waterland 		}
4415c51f124SMoriah Waterland 	}
4425c51f124SMoriah Waterland 
4435c51f124SMoriah Waterland 	/*
4445c51f124SMoriah Waterland 	 * parsing of the entry is complete
4455c51f124SMoriah Waterland 	 */
4465c51f124SMoriah Waterland 
4475c51f124SMoriah Waterland 	/* if not at the end of the entry, make it so */
4485c51f124SMoriah Waterland 
4495c51f124SMoriah Waterland 	if ((c != '\n') && (c != '\0')) {
450*62224350SCasper H.S. Dik 		if (getend(&p) && ept->pinfo) {
4515c51f124SMoriah Waterland 			setErrstr(ERR_EXTRA_TOKENS);
4525c51f124SMoriah Waterland 			return (-1);
4535c51f124SMoriah Waterland 		}
4545c51f124SMoriah Waterland 	}
4555c51f124SMoriah Waterland 
4565c51f124SMoriah Waterland 	return (1);
4575c51f124SMoriah Waterland }
4585c51f124SMoriah Waterland 
4595c51f124SMoriah Waterland static int
getstr(char ** cp,int n,char * str,int separator[])4605c51f124SMoriah Waterland getstr(char **cp, int n, char *str, int separator[])
4615c51f124SMoriah Waterland {
4625c51f124SMoriah Waterland 	int	c;
4635c51f124SMoriah Waterland 	char	*p = *cp;
4645c51f124SMoriah Waterland 	char	*p1;
4655c51f124SMoriah Waterland 	size_t	len;
4665c51f124SMoriah Waterland 
4675c51f124SMoriah Waterland 	if (*p == '\0') {
4685c51f124SMoriah Waterland 		return (1);
4695c51f124SMoriah Waterland 	}
4705c51f124SMoriah Waterland 
4715c51f124SMoriah Waterland 	/* leading white space ignored */
4725c51f124SMoriah Waterland 
4735c51f124SMoriah Waterland 	while (((c = *p) != '\0') && (isspace(*p++)))
4745c51f124SMoriah Waterland 		;
4755c51f124SMoriah Waterland 	if ((c == '\0') || (c == '\n')) {
4765c51f124SMoriah Waterland 		p--;
4775c51f124SMoriah Waterland 		*cp = p;
4785c51f124SMoriah Waterland 		return (1); /* nothing there */
4795c51f124SMoriah Waterland 	}
4805c51f124SMoriah Waterland 
4815c51f124SMoriah Waterland 	p--;
4825c51f124SMoriah Waterland 
4835c51f124SMoriah Waterland 	/* compute length based on delimiter found or not */
4845c51f124SMoriah Waterland 
4855c51f124SMoriah Waterland 	p1 = p;
486*62224350SCasper H.S. Dik 	while (separator[(int)(*(unsigned char *)p1)] == 0) {
4875c51f124SMoriah Waterland 		p1++;
4885c51f124SMoriah Waterland 	}
4895c51f124SMoriah Waterland 
4905c51f124SMoriah Waterland 	len = (ptrdiff_t)p1 - (ptrdiff_t)p;
4915c51f124SMoriah Waterland 
4925c51f124SMoriah Waterland 	/* if string will fit in result buffer copy string and return success */
4935c51f124SMoriah Waterland 
4945c51f124SMoriah Waterland 	if (len < n) {
4955c51f124SMoriah Waterland 		(void) memcpy(str, p, len);
4965c51f124SMoriah Waterland 		str[len] = '\0';
4975c51f124SMoriah Waterland 		p += len;
4985c51f124SMoriah Waterland 		*cp = p;
4995c51f124SMoriah Waterland 		return (0);
5005c51f124SMoriah Waterland 	}
5015c51f124SMoriah Waterland 
5025c51f124SMoriah Waterland 	/* result buffer too small; copy partial string, return error */
5035c51f124SMoriah Waterland 	(void) memcpy(str, p, n-1);
5045c51f124SMoriah Waterland 	str[n-1] = '\0';
5055c51f124SMoriah Waterland 	p += n;
5065c51f124SMoriah Waterland 	*cp = p;
5075c51f124SMoriah Waterland 	return (-1);
5085c51f124SMoriah Waterland }
5095c51f124SMoriah Waterland 
5105c51f124SMoriah Waterland static int
getend(char ** cp)5115c51f124SMoriah Waterland getend(char **cp)
5125c51f124SMoriah Waterland {
5135c51f124SMoriah Waterland 	int	n;
5145c51f124SMoriah Waterland 	char	*p = *cp;
5155c51f124SMoriah Waterland 
5165c51f124SMoriah Waterland 	n = 0;
5175c51f124SMoriah Waterland 
5185c51f124SMoriah Waterland 	/* if at end of buffer return no more characters left */
5195c51f124SMoriah Waterland 
5205c51f124SMoriah Waterland 	if (*p == '\0') {
5215c51f124SMoriah Waterland 		return (0);
5225c51f124SMoriah Waterland 	}
5235c51f124SMoriah Waterland 
5245c51f124SMoriah Waterland 	while ((*p != '\0') && (*p != '\n')) {
5255c51f124SMoriah Waterland 		if (n == 0) {
5265c51f124SMoriah Waterland 			if (!isspace(*p)) {
5275c51f124SMoriah Waterland 				n++;
5285c51f124SMoriah Waterland 			}
5295c51f124SMoriah Waterland 		}
5305c51f124SMoriah Waterland 		p++;
5315c51f124SMoriah Waterland 	}
5325c51f124SMoriah Waterland 
5335c51f124SMoriah Waterland 	*cp = ++p;
5345c51f124SMoriah Waterland 	return (n);
5355c51f124SMoriah Waterland }