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