xref: /onnv-gate/usr/src/lib/libpkg/common/srchcfile.c (revision 9869:9bff8d14ecc3)
19781SMoriah.Waterland@Sun.COM /*
29781SMoriah.Waterland@Sun.COM  * CDDL HEADER START
39781SMoriah.Waterland@Sun.COM  *
49781SMoriah.Waterland@Sun.COM  * The contents of this file are subject to the terms of the
59781SMoriah.Waterland@Sun.COM  * Common Development and Distribution License (the "License").
69781SMoriah.Waterland@Sun.COM  * You may not use this file except in compliance with the License.
79781SMoriah.Waterland@Sun.COM  *
89781SMoriah.Waterland@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99781SMoriah.Waterland@Sun.COM  * or http://www.opensolaris.org/os/licensing.
109781SMoriah.Waterland@Sun.COM  * See the License for the specific language governing permissions
119781SMoriah.Waterland@Sun.COM  * and limitations under the License.
129781SMoriah.Waterland@Sun.COM  *
139781SMoriah.Waterland@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
149781SMoriah.Waterland@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159781SMoriah.Waterland@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
169781SMoriah.Waterland@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
179781SMoriah.Waterland@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
189781SMoriah.Waterland@Sun.COM  *
199781SMoriah.Waterland@Sun.COM  * CDDL HEADER END
209781SMoriah.Waterland@Sun.COM  */
219781SMoriah.Waterland@Sun.COM 
229781SMoriah.Waterland@Sun.COM /*
239781SMoriah.Waterland@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
249781SMoriah.Waterland@Sun.COM  * Use is subject to license terms.
259781SMoriah.Waterland@Sun.COM  */
269781SMoriah.Waterland@Sun.COM 
279781SMoriah.Waterland@Sun.COM /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
289781SMoriah.Waterland@Sun.COM /* All Rights Reserved */
299781SMoriah.Waterland@Sun.COM 
309781SMoriah.Waterland@Sun.COM #include <stdio.h>
319781SMoriah.Waterland@Sun.COM #include <limits.h>
329781SMoriah.Waterland@Sun.COM #include <stdlib.h>
339781SMoriah.Waterland@Sun.COM #include <string.h>
349781SMoriah.Waterland@Sun.COM #include <strings.h>
359781SMoriah.Waterland@Sun.COM #include <ctype.h>
369781SMoriah.Waterland@Sun.COM #include <sys/types.h>
379781SMoriah.Waterland@Sun.COM #include <libintl.h>
389781SMoriah.Waterland@Sun.COM #include "pkglib.h"
399781SMoriah.Waterland@Sun.COM #include "pkgstrct.h"
409781SMoriah.Waterland@Sun.COM #include "pkglocale.h"
419781SMoriah.Waterland@Sun.COM #include "pkglibmsgs.h"
429781SMoriah.Waterland@Sun.COM 
439781SMoriah.Waterland@Sun.COM /*
449781SMoriah.Waterland@Sun.COM  * Forward declarations
459781SMoriah.Waterland@Sun.COM  */
469781SMoriah.Waterland@Sun.COM 
479781SMoriah.Waterland@Sun.COM static int	getend(char **cp);
489781SMoriah.Waterland@Sun.COM static int	getstr(char **cp, int n, char *str, int separator[]);
499781SMoriah.Waterland@Sun.COM 
509781SMoriah.Waterland@Sun.COM /* from gpkgmap.c */
519781SMoriah.Waterland@Sun.COM int	getnumvfp(char **cp, int base, long *d, long bad);
529781SMoriah.Waterland@Sun.COM int	getlnumvfp(char **cp, int base, fsblkcnt_t *d, long bad);
539781SMoriah.Waterland@Sun.COM 
549781SMoriah.Waterland@Sun.COM /*
559781SMoriah.Waterland@Sun.COM  * Module globals
569781SMoriah.Waterland@Sun.COM  */
579781SMoriah.Waterland@Sun.COM 
589781SMoriah.Waterland@Sun.COM static char	lpath[PATH_MAX];	/* for ept->path */
599781SMoriah.Waterland@Sun.COM static char	mylocal[PATH_MAX];	/* for ept->ainfo.local */
609781SMoriah.Waterland@Sun.COM static int	decisionTableInit = 0;
619781SMoriah.Waterland@Sun.COM 
629781SMoriah.Waterland@Sun.COM /*
639781SMoriah.Waterland@Sun.COM  * These arrays must be indexable by an unsigned char.
649781SMoriah.Waterland@Sun.COM  */
659781SMoriah.Waterland@Sun.COM 
669781SMoriah.Waterland@Sun.COM static int	ISWORDSEP[UCHAR_MAX+1];
679781SMoriah.Waterland@Sun.COM static int	ISPKGNAMESEP[UCHAR_MAX+1];
689781SMoriah.Waterland@Sun.COM 
699781SMoriah.Waterland@Sun.COM /*
709781SMoriah.Waterland@Sun.COM  * Name:	COPYPATH
719781SMoriah.Waterland@Sun.COM  * Description:	copy path limiting size to destination capacity
729781SMoriah.Waterland@Sun.COM  * Arguments:	DEST - (char []) - [RW]
739781SMoriah.Waterland@Sun.COM  *		SRC - (char *) - [RO, *RO]
749781SMoriah.Waterland@Sun.COM  *			Pointer to first byte of path to copy
759781SMoriah.Waterland@Sun.COM  *		LEN - (int) - [RO]
769781SMoriah.Waterland@Sun.COM  *			Number of bytes to copy
779781SMoriah.Waterland@Sun.COM  */
789781SMoriah.Waterland@Sun.COM 
799781SMoriah.Waterland@Sun.COM #define	COPYPATH(DEST, SRC, LEN)					\
809781SMoriah.Waterland@Sun.COM 	{								\
819781SMoriah.Waterland@Sun.COM 		/* assure return path does not overflow */		\
829781SMoriah.Waterland@Sun.COM 		if ((LEN) > sizeof ((DEST))) {				\
839781SMoriah.Waterland@Sun.COM 			(LEN) = sizeof ((DEST))-1;			\
849781SMoriah.Waterland@Sun.COM 		}							\
859781SMoriah.Waterland@Sun.COM 		/* copy return path to local storage */			\
869781SMoriah.Waterland@Sun.COM 		(void) memcpy((DEST), (SRC), (LEN));			\
879781SMoriah.Waterland@Sun.COM 		(DEST)[(LEN)] = '\0';					\
889781SMoriah.Waterland@Sun.COM 	}
899781SMoriah.Waterland@Sun.COM 
909781SMoriah.Waterland@Sun.COM /*
919781SMoriah.Waterland@Sun.COM  * Name:	srchcfile
929781SMoriah.Waterland@Sun.COM  * Description:	search contents file looking for closest match to entry,
939781SMoriah.Waterland@Sun.COM  *		creating a new contents file if output contents file specified
949781SMoriah.Waterland@Sun.COM  * Arguments:	ept - (struct cfent *) - [RO, *RW]
959781SMoriah.Waterland@Sun.COM  *			- contents file entry, describing last item found
969781SMoriah.Waterland@Sun.COM  *		path - (char *) - [RO, *RO]
979781SMoriah.Waterland@Sun.COM  *			- path to search for in contents file
989781SMoriah.Waterland@Sun.COM  *			- If path is "*", then the next entry is returned;
999781SMoriah.Waterland@Sun.COM  *				the next entry always matches this path
100*9869SCasper.Dik@Sun.COM  *		PKGserver
101*9869SCasper.Dik@Sun.COM  *			- our door to the database server.
102*9869SCasper.Dik@Sun.COM  *
1039781SMoriah.Waterland@Sun.COM  * Returns:	int
1049781SMoriah.Waterland@Sun.COM  *		< 0 - error occurred
1059781SMoriah.Waterland@Sun.COM  *			- Use getErrstr to retrieve character-string describing
1069781SMoriah.Waterland@Sun.COM  *			  the reason for failure
1079781SMoriah.Waterland@Sun.COM  *		== 0 - no match found
1089781SMoriah.Waterland@Sun.COM  *			- specified path not in the contents file
1099781SMoriah.Waterland@Sun.COM  *		== 1 - exact match found
1109781SMoriah.Waterland@Sun.COM  *			- specified path found in contents file
1119781SMoriah.Waterland@Sun.COM  *			- this value is always returned if path is "*" and the
112*9869SCasper.Dik@Sun.COM  *			  next entry is returned - 0 is returned when no more
1139781SMoriah.Waterland@Sun.COM  *			  entries are left to process
1149781SMoriah.Waterland@Sun.COM  * Side Effects:
1159781SMoriah.Waterland@Sun.COM  *		- The ept structure supplied is filled in with a description of
1169781SMoriah.Waterland@Sun.COM  *		  the item that caused the search to terminate, except in the
1179781SMoriah.Waterland@Sun.COM  *		  case of '0' in which case the contents of 'ept' is undefined.
1189781SMoriah.Waterland@Sun.COM  *		- NOTE: the ept->path item points to a path that is statically
1199781SMoriah.Waterland@Sun.COM  *		  allocated and will be overwritten on the next call.
1209781SMoriah.Waterland@Sun.COM  *		- NOTE: the ept->ainfo.local item points to a path that is
1219781SMoriah.Waterland@Sun.COM  *		  statically allocated and will be overwritten on the next call.
1229781SMoriah.Waterland@Sun.COM  */
1239781SMoriah.Waterland@Sun.COM 
1249781SMoriah.Waterland@Sun.COM int
srchcfile(struct cfent * ept,char * path,PKGserver server)125*9869SCasper.Dik@Sun.COM srchcfile(struct cfent *ept, char *path, PKGserver server)
1269781SMoriah.Waterland@Sun.COM {
127*9869SCasper.Dik@Sun.COM 	char		*cpath_start = NULL;
1289781SMoriah.Waterland@Sun.COM 	char		classname[CLSSIZ+1];
1299781SMoriah.Waterland@Sun.COM 	char		pkgname[PKGSIZ+1];
1309781SMoriah.Waterland@Sun.COM 	int		anypath = 0;
1319781SMoriah.Waterland@Sun.COM 	int		c;
132*9869SCasper.Dik@Sun.COM 	int		cpath_len = 0;
1339781SMoriah.Waterland@Sun.COM 	struct pinfo	*lastpinfo;
1349781SMoriah.Waterland@Sun.COM 	struct pinfo	*pinfo;
135*9869SCasper.Dik@Sun.COM 	char		*p;
136*9869SCasper.Dik@Sun.COM 	char		*curbuf;
137*9869SCasper.Dik@Sun.COM 	int		linelen;	/* includes NUL */
1389781SMoriah.Waterland@Sun.COM 
1399781SMoriah.Waterland@Sun.COM 	/*
1409781SMoriah.Waterland@Sun.COM 	 * this code does not use nested subroutines because execution time
1419781SMoriah.Waterland@Sun.COM 	 * of this routine is especially critical to installation and upgrade
1429781SMoriah.Waterland@Sun.COM 	 */
1439781SMoriah.Waterland@Sun.COM 
1449781SMoriah.Waterland@Sun.COM 	/* initialize local variables */
1459781SMoriah.Waterland@Sun.COM 
1469781SMoriah.Waterland@Sun.COM 	setErrstr(NULL);	/* no error message currently cached */
1479781SMoriah.Waterland@Sun.COM 	lpath[0] = '\0';
1489781SMoriah.Waterland@Sun.COM 	lpath[sizeof (lpath)-1] = '\0';
1499781SMoriah.Waterland@Sun.COM 
1509781SMoriah.Waterland@Sun.COM 	/* initialize ept structure values */
1519781SMoriah.Waterland@Sun.COM 
1529781SMoriah.Waterland@Sun.COM 	(void) strlcpy(ept->ainfo.group, BADGROUP, sizeof (ept->ainfo.group));
1539781SMoriah.Waterland@Sun.COM 	(void) strlcpy(ept->ainfo.owner, BADOWNER, sizeof (ept->ainfo.owner));
1549781SMoriah.Waterland@Sun.COM 	(void) strlcpy(ept->pkg_class, BADCLASS,  sizeof (ept->pkg_class));
1559781SMoriah.Waterland@Sun.COM 	ept->ainfo.local = (char *)NULL;
1569781SMoriah.Waterland@Sun.COM 	ept->ainfo.mode = BADMODE;
1579781SMoriah.Waterland@Sun.COM 	ept->cinfo.cksum = BADCONT;
1589781SMoriah.Waterland@Sun.COM 	ept->cinfo.modtime = BADCONT;
1599781SMoriah.Waterland@Sun.COM 	ept->cinfo.size = (fsblkcnt_t)BADCONT;
1609781SMoriah.Waterland@Sun.COM 	ept->ftype = BADFTYPE;
1619781SMoriah.Waterland@Sun.COM 	ept->npkgs = 0;
1629781SMoriah.Waterland@Sun.COM 	ept->path = (char *)NULL;
1639781SMoriah.Waterland@Sun.COM 	ept->pinfo = (struct pinfo *)NULL;
1649781SMoriah.Waterland@Sun.COM 	ept->pkg_class_idx = -1;
1659781SMoriah.Waterland@Sun.COM 	ept->volno = 0;
1669781SMoriah.Waterland@Sun.COM 
1679781SMoriah.Waterland@Sun.COM 	/*
1689781SMoriah.Waterland@Sun.COM 	 * populate decision tables that implement fast character checking;
1699781SMoriah.Waterland@Sun.COM 	 * this is much faster than the equivalent strpbrk() call or a
1709781SMoriah.Waterland@Sun.COM 	 * while() loop checking for the characters. It is only faster if
1719781SMoriah.Waterland@Sun.COM 	 * there are at least 3 characters to scan for - when checking for
1729781SMoriah.Waterland@Sun.COM 	 * one or two characters (such as '\n' or '\0') its faster to do
1739781SMoriah.Waterland@Sun.COM 	 * a simple while() loop.
1749781SMoriah.Waterland@Sun.COM 	 */
1759781SMoriah.Waterland@Sun.COM 
1769781SMoriah.Waterland@Sun.COM 	if (decisionTableInit == 0) {
1779781SMoriah.Waterland@Sun.COM 		/*
1789781SMoriah.Waterland@Sun.COM 		 * any chars listed stop scan;
1799781SMoriah.Waterland@Sun.COM 		 * scan stops on first byte found that is set to '1' below
1809781SMoriah.Waterland@Sun.COM 		 */
1819781SMoriah.Waterland@Sun.COM 
1829781SMoriah.Waterland@Sun.COM 		/*
1839781SMoriah.Waterland@Sun.COM 		 * Separators for normal words
1849781SMoriah.Waterland@Sun.COM 		 */
1859781SMoriah.Waterland@Sun.COM 		bzero(ISWORDSEP, sizeof (ISWORDSEP));
1869781SMoriah.Waterland@Sun.COM 		ISWORDSEP[' '] = 1;
1879781SMoriah.Waterland@Sun.COM 		ISWORDSEP['\t'] = 1;
1889781SMoriah.Waterland@Sun.COM 		ISWORDSEP['\n'] = 1;
1899781SMoriah.Waterland@Sun.COM 		ISWORDSEP['\0'] = 1;
1909781SMoriah.Waterland@Sun.COM 
1919781SMoriah.Waterland@Sun.COM 		/*
1929781SMoriah.Waterland@Sun.COM 		 * Separators for list of packages, includes \\ for
1939781SMoriah.Waterland@Sun.COM 		 * alternate ftype and : for classname
1949781SMoriah.Waterland@Sun.COM 		 */
1959781SMoriah.Waterland@Sun.COM 		bzero(ISPKGNAMESEP, sizeof (ISPKGNAMESEP));
1969781SMoriah.Waterland@Sun.COM 		ISPKGNAMESEP[' '] = 1;
1979781SMoriah.Waterland@Sun.COM 		ISPKGNAMESEP['\t'] = 1;
1989781SMoriah.Waterland@Sun.COM 		ISPKGNAMESEP['\n'] = 1;
1999781SMoriah.Waterland@Sun.COM 		ISPKGNAMESEP[':'] = 1;
2009781SMoriah.Waterland@Sun.COM 		ISPKGNAMESEP['\\'] = 1;
2019781SMoriah.Waterland@Sun.COM 		ISPKGNAMESEP['\0'] = 1;
2029781SMoriah.Waterland@Sun.COM 
2039781SMoriah.Waterland@Sun.COM 		decisionTableInit = 1;
2049781SMoriah.Waterland@Sun.COM 	}
2059781SMoriah.Waterland@Sun.COM 
2069781SMoriah.Waterland@Sun.COM 	/* if the path to scan for is empty, act like no path was specified */
2079781SMoriah.Waterland@Sun.COM 
208*9869SCasper.Dik@Sun.COM 	if ((path != NULL) && (*path == '\0')) {
209*9869SCasper.Dik@Sun.COM 		path = NULL;
2109781SMoriah.Waterland@Sun.COM 	}
2119781SMoriah.Waterland@Sun.COM 
2129781SMoriah.Waterland@Sun.COM 	/*
2139781SMoriah.Waterland@Sun.COM 	 * if path to search for is "*", then we will return the first path
2149781SMoriah.Waterland@Sun.COM 	 * we encounter as a match, otherwise we return an error
2159781SMoriah.Waterland@Sun.COM 	 */
2169781SMoriah.Waterland@Sun.COM 
217*9869SCasper.Dik@Sun.COM 	if ((path != NULL) && (path[0] != '/')) {
2189781SMoriah.Waterland@Sun.COM 		if (strcmp(path, "*") != 0) {
2199781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_ILLEGAL_SEARCH_PATH));
2209781SMoriah.Waterland@Sun.COM 			return (-1);
2219781SMoriah.Waterland@Sun.COM 		}
2229781SMoriah.Waterland@Sun.COM 		anypath = 1;
2239781SMoriah.Waterland@Sun.COM 	}
2249781SMoriah.Waterland@Sun.COM 
2259781SMoriah.Waterland@Sun.COM 	/* attempt to narrow down the search for the specified path */
2269781SMoriah.Waterland@Sun.COM 
227*9869SCasper.Dik@Sun.COM 	if (anypath == 0 && path == NULL)
228*9869SCasper.Dik@Sun.COM 		return (0);
2299781SMoriah.Waterland@Sun.COM 
230*9869SCasper.Dik@Sun.COM 	/* determine first character of the next entry */
231*9869SCasper.Dik@Sun.COM 	if (anypath == 0)
232*9869SCasper.Dik@Sun.COM 		curbuf = pkggetentry_named(server, path, &linelen, &cpath_len);
233*9869SCasper.Dik@Sun.COM 	else
234*9869SCasper.Dik@Sun.COM 		curbuf = pkggetentry(server, &linelen, &cpath_len);
235*9869SCasper.Dik@Sun.COM 
236*9869SCasper.Dik@Sun.COM 	if (curbuf == NULL)
237*9869SCasper.Dik@Sun.COM 		return (0);
2389781SMoriah.Waterland@Sun.COM 
2399781SMoriah.Waterland@Sun.COM 	/*
240*9869SCasper.Dik@Sun.COM 	 * current entry DOES start with absolute path
241*9869SCasper.Dik@Sun.COM 	 * set ept->path to point to lpath
242*9869SCasper.Dik@Sun.COM 	 * set cpath_start/cpath_len to point to the file name
2439781SMoriah.Waterland@Sun.COM 	 */
2449781SMoriah.Waterland@Sun.COM 
245*9869SCasper.Dik@Sun.COM 	/* copy first token into path element of passed structure */
246*9869SCasper.Dik@Sun.COM 
247*9869SCasper.Dik@Sun.COM 	cpath_start = curbuf;
248*9869SCasper.Dik@Sun.COM 
249*9869SCasper.Dik@Sun.COM 	p = cpath_start + cpath_len;
250*9869SCasper.Dik@Sun.COM 
251*9869SCasper.Dik@Sun.COM 	ept->path = lpath;
252*9869SCasper.Dik@Sun.COM 
253*9869SCasper.Dik@Sun.COM 	/* copy path found to 'lpath' */
254*9869SCasper.Dik@Sun.COM 	COPYPATH(lpath, cpath_start, cpath_len);
255*9869SCasper.Dik@Sun.COM 
256*9869SCasper.Dik@Sun.COM 	/* get first character following the end of the path */
257*9869SCasper.Dik@Sun.COM 
258*9869SCasper.Dik@Sun.COM 	c = *p++;
259*9869SCasper.Dik@Sun.COM 
260*9869SCasper.Dik@Sun.COM 	/*
261*9869SCasper.Dik@Sun.COM 	 * we want to return information about this path in
262*9869SCasper.Dik@Sun.COM 	 * the structure provided, so parse any local path
263*9869SCasper.Dik@Sun.COM 	 * and jump to code which parses rest of the input line
264*9869SCasper.Dik@Sun.COM 	 */
265*9869SCasper.Dik@Sun.COM 	if (c == '=') {
266*9869SCasper.Dik@Sun.COM 		/* parse local path specification */
267*9869SCasper.Dik@Sun.COM 		if (getstr(&p, PATH_MAX, mylocal, ISWORDSEP)) {
268*9869SCasper.Dik@Sun.COM 			setErrstr(ERR_CANNOT_READ_LL_PATH);
269*9869SCasper.Dik@Sun.COM 			return (-1);
2709781SMoriah.Waterland@Sun.COM 		}
271*9869SCasper.Dik@Sun.COM 		ept->ainfo.local = mylocal;
2729781SMoriah.Waterland@Sun.COM 	}
2739781SMoriah.Waterland@Sun.COM 
2749781SMoriah.Waterland@Sun.COM 	/*
275*9869SCasper.Dik@Sun.COM 	 * if an exact match and processing a new style entry, read the
276*9869SCasper.Dik@Sun.COM 	 * remaining information from the new style entry.
2779781SMoriah.Waterland@Sun.COM 	 */
2789781SMoriah.Waterland@Sun.COM 
279*9869SCasper.Dik@Sun.COM 	while (isspace((c = *p++)))
280*9869SCasper.Dik@Sun.COM 		;
2819781SMoriah.Waterland@Sun.COM 
282*9869SCasper.Dik@Sun.COM 	switch (c) {
283*9869SCasper.Dik@Sun.COM 	case '?': case 'f': case 'v': case 'e': case 'l':
284*9869SCasper.Dik@Sun.COM 	case 's': case 'p': case 'c': case 'b': case 'd':
285*9869SCasper.Dik@Sun.COM 	case 'x':
286*9869SCasper.Dik@Sun.COM 		/* save ftype */
287*9869SCasper.Dik@Sun.COM 		ept->ftype = (char)c;
2889781SMoriah.Waterland@Sun.COM 
289*9869SCasper.Dik@Sun.COM 		/* save class */
290*9869SCasper.Dik@Sun.COM 		if (getstr(&p, CLSSIZ, ept->pkg_class, ISWORDSEP)) {
291*9869SCasper.Dik@Sun.COM 			setErrstr(ERR_CANNOT_READ_CLASS_TOKEN);
292*9869SCasper.Dik@Sun.COM 			return (-1);
2939781SMoriah.Waterland@Sun.COM 		}
294*9869SCasper.Dik@Sun.COM 		break; /* we already read the pathname */
2959781SMoriah.Waterland@Sun.COM 
296*9869SCasper.Dik@Sun.COM 	case '\0':
297*9869SCasper.Dik@Sun.COM 		/* end of line before new-line seen */
298*9869SCasper.Dik@Sun.COM 		setErrstr(ERR_INCOMPLETE_ENTRY);
299*9869SCasper.Dik@Sun.COM 		return (-1);
3009781SMoriah.Waterland@Sun.COM 
301*9869SCasper.Dik@Sun.COM 	case '0': case '1': case '2': case '3': case '4':
302*9869SCasper.Dik@Sun.COM 	case '5': case '6': case '7': case '8': case '9':
303*9869SCasper.Dik@Sun.COM 		setErrstr(ERR_VOLUMENO_UNEXPECTED);
304*9869SCasper.Dik@Sun.COM 		return (-1);
3059781SMoriah.Waterland@Sun.COM 
306*9869SCasper.Dik@Sun.COM 	case 'i':
307*9869SCasper.Dik@Sun.COM 		setErrstr(ERR_FTYPE_I_UNEXPECTED);
308*9869SCasper.Dik@Sun.COM 		return (-1);
3099781SMoriah.Waterland@Sun.COM 
310*9869SCasper.Dik@Sun.COM 	default:
311*9869SCasper.Dik@Sun.COM 		/* unknown ftype */
312*9869SCasper.Dik@Sun.COM 		setErrstr(ERR_UNKNOWN_FTYPE);
313*9869SCasper.Dik@Sun.COM 		return (-1);
3149781SMoriah.Waterland@Sun.COM 	}
3159781SMoriah.Waterland@Sun.COM 
3169781SMoriah.Waterland@Sun.COM 	/* link/symbolic link must have link destination */
3179781SMoriah.Waterland@Sun.COM 
3189781SMoriah.Waterland@Sun.COM 	if (((ept->ftype == 's') || (ept->ftype == 'l')) &&
319*9869SCasper.Dik@Sun.COM 	    (ept->ainfo.local == NULL)) {
3209781SMoriah.Waterland@Sun.COM 		setErrstr(ERR_NO_LINK_SOURCE_SPECIFIED);
3219781SMoriah.Waterland@Sun.COM 		return (-1);
3229781SMoriah.Waterland@Sun.COM 	}
3239781SMoriah.Waterland@Sun.COM 
3249781SMoriah.Waterland@Sun.COM 	/* character/block devices have major/minor device numbers */
3259781SMoriah.Waterland@Sun.COM 
3269781SMoriah.Waterland@Sun.COM 	if (((ept->ftype == 'c') || (ept->ftype == 'b'))) {
3279781SMoriah.Waterland@Sun.COM 		ept->ainfo.major = BADMAJOR;
3289781SMoriah.Waterland@Sun.COM 		ept->ainfo.minor = BADMINOR;
329*9869SCasper.Dik@Sun.COM 		if (getnumvfp(&p, 10, (long *)&ept->ainfo.major, BADMAJOR) ||
330*9869SCasper.Dik@Sun.COM 		    getnumvfp(&p, 10, (long *)&ept->ainfo.minor, BADMINOR)) {
3319781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_CANNOT_READ_MM_NUMS));
3329781SMoriah.Waterland@Sun.COM 			return (-1);
3339781SMoriah.Waterland@Sun.COM 		}
3349781SMoriah.Waterland@Sun.COM 	}
3359781SMoriah.Waterland@Sun.COM 
3369781SMoriah.Waterland@Sun.COM 	/* most types have mode, owner, group identification components */
3379781SMoriah.Waterland@Sun.COM 
3389781SMoriah.Waterland@Sun.COM 	if ((ept->ftype == 'd') || (ept->ftype == 'x') || (ept->ftype == 'c') ||
339*9869SCasper.Dik@Sun.COM 	    (ept->ftype == 'b') || (ept->ftype == 'p') ||
340*9869SCasper.Dik@Sun.COM 	    (ept->ftype == 'f') || (ept->ftype == 'v') ||
341*9869SCasper.Dik@Sun.COM 	    (ept->ftype == 'e')) {
3429781SMoriah.Waterland@Sun.COM 		/* mode, owner, group should be here */
343*9869SCasper.Dik@Sun.COM 		if (getnumvfp(&p, 8, (long *)&ept->ainfo.mode, BADMODE) ||
344*9869SCasper.Dik@Sun.COM 		    getstr(&p, sizeof (ept->ainfo.owner), ept->ainfo.owner,
345*9869SCasper.Dik@Sun.COM 		    ISWORDSEP) ||
346*9869SCasper.Dik@Sun.COM 		    getstr(&p, sizeof (ept->ainfo.group), ept->ainfo.group,
347*9869SCasper.Dik@Sun.COM 		    ISWORDSEP)) {
3489781SMoriah.Waterland@Sun.COM 			setErrstr(ERR_CANNOT_READ_MOG);
3499781SMoriah.Waterland@Sun.COM 			return (-1);
3509781SMoriah.Waterland@Sun.COM 		}
3519781SMoriah.Waterland@Sun.COM 	}
3529781SMoriah.Waterland@Sun.COM 
3539781SMoriah.Waterland@Sun.COM 	/* i/f/v/e have size, checksum, modification time components */
3549781SMoriah.Waterland@Sun.COM 
3559781SMoriah.Waterland@Sun.COM 	if ((ept->ftype == 'i') || (ept->ftype == 'f') ||
356*9869SCasper.Dik@Sun.COM 	    (ept->ftype == 'v') || (ept->ftype == 'e')) {
3579781SMoriah.Waterland@Sun.COM 		/* look for content description */
358*9869SCasper.Dik@Sun.COM 		if (getlnumvfp(&p, 10, (fsblkcnt_t *)&ept->cinfo.size,
359*9869SCasper.Dik@Sun.COM 		    BADCONT) ||
360*9869SCasper.Dik@Sun.COM 		    getnumvfp(&p, 10, (long *)&ept->cinfo.cksum, BADCONT) ||
361*9869SCasper.Dik@Sun.COM 		    getnumvfp(&p, 10, (long *)&ept->cinfo.modtime, BADCONT)) {
3629781SMoriah.Waterland@Sun.COM 			setErrstr(ERR_CANNOT_READ_CONTENT_INFO);
3639781SMoriah.Waterland@Sun.COM 			return (-1);
3649781SMoriah.Waterland@Sun.COM 		}
3659781SMoriah.Waterland@Sun.COM 	}
3669781SMoriah.Waterland@Sun.COM 
3679781SMoriah.Waterland@Sun.COM 	/* i files processing is completed - return 'exact match found' */
3689781SMoriah.Waterland@Sun.COM 
3699781SMoriah.Waterland@Sun.COM 	if (ept->ftype == 'i') {
3709781SMoriah.Waterland@Sun.COM 		return (1);
3719781SMoriah.Waterland@Sun.COM 	}
3729781SMoriah.Waterland@Sun.COM 
3739781SMoriah.Waterland@Sun.COM 	/*
3749781SMoriah.Waterland@Sun.COM 	 * determine list of packages which reference this entry
3759781SMoriah.Waterland@Sun.COM 	 */
3769781SMoriah.Waterland@Sun.COM 
3779781SMoriah.Waterland@Sun.COM 	lastpinfo = (struct pinfo *)NULL;
378*9869SCasper.Dik@Sun.COM 	while ((c = getstr(&p, sizeof (pkgname), pkgname, ISPKGNAMESEP)) <= 0) {
3799781SMoriah.Waterland@Sun.COM 		/* if c < 0 the string was too long to fix in the buffer */
3809781SMoriah.Waterland@Sun.COM 
3819781SMoriah.Waterland@Sun.COM 		if (c < 0) {
3829781SMoriah.Waterland@Sun.COM 			setErrstr(ERR_PACKAGE_NAME_TOO_LONG);
3839781SMoriah.Waterland@Sun.COM 			return (-1);
3849781SMoriah.Waterland@Sun.COM 		}
3859781SMoriah.Waterland@Sun.COM 
3869781SMoriah.Waterland@Sun.COM 		/* a package is present - create and populate pinfo structure */
3879781SMoriah.Waterland@Sun.COM 
3889781SMoriah.Waterland@Sun.COM 		pinfo = (struct pinfo *)calloc(1, sizeof (struct pinfo));
3899781SMoriah.Waterland@Sun.COM 		if (!pinfo) {
3909781SMoriah.Waterland@Sun.COM 			setErrstr(ERR_NO_MEMORY);
3919781SMoriah.Waterland@Sun.COM 			return (-1);
3929781SMoriah.Waterland@Sun.COM 		}
3939781SMoriah.Waterland@Sun.COM 		if (!lastpinfo) {
3949781SMoriah.Waterland@Sun.COM 			ept->pinfo = pinfo; /* first one */
3959781SMoriah.Waterland@Sun.COM 		} else {
3969781SMoriah.Waterland@Sun.COM 			lastpinfo->next = pinfo; /* link list */
3979781SMoriah.Waterland@Sun.COM 		}
3989781SMoriah.Waterland@Sun.COM 		lastpinfo = pinfo;
3999781SMoriah.Waterland@Sun.COM 
4009781SMoriah.Waterland@Sun.COM 		if ((pkgname[0] == '-') || (pkgname[0] == '+') ||
401*9869SCasper.Dik@Sun.COM 		    (pkgname[0] == '*') || (pkgname[0] == '~') ||
402*9869SCasper.Dik@Sun.COM 		    (pkgname[0] == '!') || (pkgname[0] == '%')) {
4039781SMoriah.Waterland@Sun.COM 			pinfo->status = pkgname[0];
4049781SMoriah.Waterland@Sun.COM 			(void) strlcpy(pinfo->pkg, pkgname+1,
405*9869SCasper.Dik@Sun.COM 			    sizeof (pinfo->pkg));
4069781SMoriah.Waterland@Sun.COM 		} else {
4079781SMoriah.Waterland@Sun.COM 			(void) strlcpy(pinfo->pkg, pkgname,
408*9869SCasper.Dik@Sun.COM 			    sizeof (pinfo->pkg));
4099781SMoriah.Waterland@Sun.COM 		}
4109781SMoriah.Waterland@Sun.COM 
4119781SMoriah.Waterland@Sun.COM 		/* pkg/[:[ftype][:class] */
412*9869SCasper.Dik@Sun.COM 		c = *p++;
4139781SMoriah.Waterland@Sun.COM 		if (c == '\\') {
4149781SMoriah.Waterland@Sun.COM 			/* get alternate ftype */
4159781SMoriah.Waterland@Sun.COM 			pinfo->editflag++;
416*9869SCasper.Dik@Sun.COM 			c = *p++;
4179781SMoriah.Waterland@Sun.COM 		}
4189781SMoriah.Waterland@Sun.COM 
4199781SMoriah.Waterland@Sun.COM 		if (c == ':') {
4209781SMoriah.Waterland@Sun.COM 			/* get special classname */
421*9869SCasper.Dik@Sun.COM 			(void) getstr(&p, sizeof (classname), classname,
422*9869SCasper.Dik@Sun.COM 			    ISWORDSEP);
4239781SMoriah.Waterland@Sun.COM 			(void) strlcpy(pinfo->aclass, classname,
424*9869SCasper.Dik@Sun.COM 			    sizeof (pinfo->aclass));
425*9869SCasper.Dik@Sun.COM 			c = *p++;
4269781SMoriah.Waterland@Sun.COM 		}
4279781SMoriah.Waterland@Sun.COM 		ept->npkgs++;
4289781SMoriah.Waterland@Sun.COM 
4299781SMoriah.Waterland@Sun.COM 		/* break out of while if at end of entry */
4309781SMoriah.Waterland@Sun.COM 
4319781SMoriah.Waterland@Sun.COM 		if ((c == '\n') || (c == '\0')) {
4329781SMoriah.Waterland@Sun.COM 			break;
4339781SMoriah.Waterland@Sun.COM 		}
4349781SMoriah.Waterland@Sun.COM 
4359781SMoriah.Waterland@Sun.COM 		/* if package not separated by a space return an error */
4369781SMoriah.Waterland@Sun.COM 
4379781SMoriah.Waterland@Sun.COM 		if (!isspace(c)) {
4389781SMoriah.Waterland@Sun.COM 			setErrstr(ERR_BAD_ENTRY_END);
4399781SMoriah.Waterland@Sun.COM 			return (-1);
4409781SMoriah.Waterland@Sun.COM 		}
4419781SMoriah.Waterland@Sun.COM 	}
4429781SMoriah.Waterland@Sun.COM 
4439781SMoriah.Waterland@Sun.COM 	/*
4449781SMoriah.Waterland@Sun.COM 	 * parsing of the entry is complete
4459781SMoriah.Waterland@Sun.COM 	 */
4469781SMoriah.Waterland@Sun.COM 
4479781SMoriah.Waterland@Sun.COM 	/* if not at the end of the entry, make it so */
4489781SMoriah.Waterland@Sun.COM 
4499781SMoriah.Waterland@Sun.COM 	if ((c != '\n') && (c != '\0')) {
450*9869SCasper.Dik@Sun.COM 		if (getend(&p) && ept->pinfo) {
4519781SMoriah.Waterland@Sun.COM 			setErrstr(ERR_EXTRA_TOKENS);
4529781SMoriah.Waterland@Sun.COM 			return (-1);
4539781SMoriah.Waterland@Sun.COM 		}
4549781SMoriah.Waterland@Sun.COM 	}
4559781SMoriah.Waterland@Sun.COM 
4569781SMoriah.Waterland@Sun.COM 	return (1);
4579781SMoriah.Waterland@Sun.COM }
4589781SMoriah.Waterland@Sun.COM 
4599781SMoriah.Waterland@Sun.COM static int
getstr(char ** cp,int n,char * str,int separator[])4609781SMoriah.Waterland@Sun.COM getstr(char **cp, int n, char *str, int separator[])
4619781SMoriah.Waterland@Sun.COM {
4629781SMoriah.Waterland@Sun.COM 	int	c;
4639781SMoriah.Waterland@Sun.COM 	char	*p = *cp;
4649781SMoriah.Waterland@Sun.COM 	char	*p1;
4659781SMoriah.Waterland@Sun.COM 	size_t	len;
4669781SMoriah.Waterland@Sun.COM 
4679781SMoriah.Waterland@Sun.COM 	if (*p == '\0') {
4689781SMoriah.Waterland@Sun.COM 		return (1);
4699781SMoriah.Waterland@Sun.COM 	}
4709781SMoriah.Waterland@Sun.COM 
4719781SMoriah.Waterland@Sun.COM 	/* leading white space ignored */
4729781SMoriah.Waterland@Sun.COM 
4739781SMoriah.Waterland@Sun.COM 	while (((c = *p) != '\0') && (isspace(*p++)))
4749781SMoriah.Waterland@Sun.COM 		;
4759781SMoriah.Waterland@Sun.COM 	if ((c == '\0') || (c == '\n')) {
4769781SMoriah.Waterland@Sun.COM 		p--;
4779781SMoriah.Waterland@Sun.COM 		*cp = p;
4789781SMoriah.Waterland@Sun.COM 		return (1); /* nothing there */
4799781SMoriah.Waterland@Sun.COM 	}
4809781SMoriah.Waterland@Sun.COM 
4819781SMoriah.Waterland@Sun.COM 	p--;
4829781SMoriah.Waterland@Sun.COM 
4839781SMoriah.Waterland@Sun.COM 	/* compute length based on delimiter found or not */
4849781SMoriah.Waterland@Sun.COM 
4859781SMoriah.Waterland@Sun.COM 	p1 = p;
486*9869SCasper.Dik@Sun.COM 	while (separator[(int)(*(unsigned char *)p1)] == 0) {
4879781SMoriah.Waterland@Sun.COM 		p1++;
4889781SMoriah.Waterland@Sun.COM 	}
4899781SMoriah.Waterland@Sun.COM 
4909781SMoriah.Waterland@Sun.COM 	len = (ptrdiff_t)p1 - (ptrdiff_t)p;
4919781SMoriah.Waterland@Sun.COM 
4929781SMoriah.Waterland@Sun.COM 	/* if string will fit in result buffer copy string and return success */
4939781SMoriah.Waterland@Sun.COM 
4949781SMoriah.Waterland@Sun.COM 	if (len < n) {
4959781SMoriah.Waterland@Sun.COM 		(void) memcpy(str, p, len);
4969781SMoriah.Waterland@Sun.COM 		str[len] = '\0';
4979781SMoriah.Waterland@Sun.COM 		p += len;
4989781SMoriah.Waterland@Sun.COM 		*cp = p;
4999781SMoriah.Waterland@Sun.COM 		return (0);
5009781SMoriah.Waterland@Sun.COM 	}
5019781SMoriah.Waterland@Sun.COM 
5029781SMoriah.Waterland@Sun.COM 	/* result buffer too small; copy partial string, return error */
5039781SMoriah.Waterland@Sun.COM 	(void) memcpy(str, p, n-1);
5049781SMoriah.Waterland@Sun.COM 	str[n-1] = '\0';
5059781SMoriah.Waterland@Sun.COM 	p += n;
5069781SMoriah.Waterland@Sun.COM 	*cp = p;
5079781SMoriah.Waterland@Sun.COM 	return (-1);
5089781SMoriah.Waterland@Sun.COM }
5099781SMoriah.Waterland@Sun.COM 
5109781SMoriah.Waterland@Sun.COM static int
getend(char ** cp)5119781SMoriah.Waterland@Sun.COM getend(char **cp)
5129781SMoriah.Waterland@Sun.COM {
5139781SMoriah.Waterland@Sun.COM 	int	n;
5149781SMoriah.Waterland@Sun.COM 	char	*p = *cp;
5159781SMoriah.Waterland@Sun.COM 
5169781SMoriah.Waterland@Sun.COM 	n = 0;
5179781SMoriah.Waterland@Sun.COM 
5189781SMoriah.Waterland@Sun.COM 	/* if at end of buffer return no more characters left */
5199781SMoriah.Waterland@Sun.COM 
5209781SMoriah.Waterland@Sun.COM 	if (*p == '\0') {
5219781SMoriah.Waterland@Sun.COM 		return (0);
5229781SMoriah.Waterland@Sun.COM 	}
5239781SMoriah.Waterland@Sun.COM 
5249781SMoriah.Waterland@Sun.COM 	while ((*p != '\0') && (*p != '\n')) {
5259781SMoriah.Waterland@Sun.COM 		if (n == 0) {
5269781SMoriah.Waterland@Sun.COM 			if (!isspace(*p)) {
5279781SMoriah.Waterland@Sun.COM 				n++;
5289781SMoriah.Waterland@Sun.COM 			}
5299781SMoriah.Waterland@Sun.COM 		}
5309781SMoriah.Waterland@Sun.COM 		p++;
5319781SMoriah.Waterland@Sun.COM 	}
5329781SMoriah.Waterland@Sun.COM 
5339781SMoriah.Waterland@Sun.COM 	*cp = ++p;
5349781SMoriah.Waterland@Sun.COM 	return (n);
5359781SMoriah.Waterland@Sun.COM }
536