srchcfile.c revision 62224350e5355e6834f7deb9d8a7d062a50cb7c2
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * CDDL HEADER START
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * The contents of this file are subject to the terms of the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Common Development and Distribution License (the "License").
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * You may not use this file except in compliance with the License.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * or http://www.opensolaris.org/os/licensing.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * See the License for the specific language governing permissions
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * and limitations under the License.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * When distributing Covered Code, include this CDDL HEADER in each
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If applicable, add the following below this CDDL HEADER, with the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner]
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * CDDL HEADER END
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Use is subject to license terms.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* All Rights Reserved */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Forward declarations
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic int getstr(char **cp, int n, char *str, int separator[]);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint getnumvfp(char **cp, int base, long *d, long bad);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint getlnumvfp(char **cp, int base, fsblkcnt_t *d, long bad);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Module globals
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic char lpath[PATH_MAX]; /* for ept->path */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic char mylocal[PATH_MAX]; /* for ept->ainfo.local */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * These arrays must be indexable by an unsigned char.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: COPYPATH
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: copy path limiting size to destination capacity
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: DEST - (char []) - [RW]
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * SRC - (char *) - [RO, *RO]
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Pointer to first byte of path to copy
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * LEN - (int) - [RO]
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Number of bytes to copy
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* assure return path does not overflow */ \
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* copy return path to local storage */ \
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: srchcfile
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: search contents file looking for closest match to entry,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * creating a new contents file if output contents file specified
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: ept - (struct cfent *) - [RO, *RW]
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - contents file entry, describing last item found
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * path - (char *) - [RO, *RO]
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - path to search for in contents file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - If path is "*", then the next entry is returned;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the next entry always matches this path
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik * - our door to the database server.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: int
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * < 0 - error occurred
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - Use getErrstr to retrieve character-string describing
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the reason for failure
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == 0 - no match found
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - specified path not in the contents file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == 1 - exact match found
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - specified path found in contents file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - this value is always returned if path is "*" and the
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik * next entry is returned - 0 is returned when no more
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * entries are left to process
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Side Effects:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - The ept structure supplied is filled in with a description of
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the item that caused the search to terminate, except in the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * case of '0' in which case the contents of 'ept' is undefined.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - NOTE: the ept->path item points to a path that is statically
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * allocated and will be overwritten on the next call.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - NOTE: the ept->ainfo.local item points to a path that is
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * statically allocated and will be overwritten on the next call.
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Diksrchcfile(struct cfent *ept, char *path, PKGserver server)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * this code does not use nested subroutines because execution time
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * of this routine is especially critical to installation and upgrade
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* initialize local variables */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland setErrstr(NULL); /* no error message currently cached */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* initialize ept structure values */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strlcpy(ept->ainfo.group, BADGROUP, sizeof (ept->ainfo.group));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strlcpy(ept->ainfo.owner, BADOWNER, sizeof (ept->ainfo.owner));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strlcpy(ept->pkg_class, BADCLASS, sizeof (ept->pkg_class));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * populate decision tables that implement fast character checking;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * this is much faster than the equivalent strpbrk() call or a
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * while() loop checking for the characters. It is only faster if
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * there are at least 3 characters to scan for - when checking for
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * one or two characters (such as '\n' or '\0') its faster to do
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a simple while() loop.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * any chars listed stop scan;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * scan stops on first byte found that is set to '1' below
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Separators for normal words
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Separators for list of packages, includes \\ for
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * alternate ftype and : for classname
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland bzero(ISPKGNAMESEP, sizeof (ISPKGNAMESEP));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if the path to scan for is empty, act like no path was specified */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * if path to search for is "*", then we will return the first path
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * we encounter as a match, otherwise we return an error
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland setErrstr(pkg_gt(ERR_ILLEGAL_SEARCH_PATH));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* attempt to narrow down the search for the specified path */
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik /* determine first character of the next entry */
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik curbuf = pkggetentry_named(server, path, &linelen, &cpath_len);
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik curbuf = pkggetentry(server, &linelen, &cpath_len);
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik * current entry DOES start with absolute path
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik * set ept->path to point to lpath
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik * set cpath_start/cpath_len to point to the file name
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik /* copy first token into path element of passed structure */
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik /* copy path found to 'lpath' */
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik /* get first character following the end of the path */
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik * we want to return information about this path in
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik * the structure provided, so parse any local path
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik * and jump to code which parses rest of the input line
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik if (c == '=') {
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik /* parse local path specification */
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik if (getstr(&p, PATH_MAX, mylocal, ISWORDSEP)) {
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik * if an exact match and processing a new style entry, read the
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik * remaining information from the new style entry.
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik while (isspace((c = *p++)))
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik case '?': case 'f': case 'v': case 'e': case 'l':
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik case 's': case 'p': case 'c': case 'b': case 'd':
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik /* save ftype */
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik /* save class */
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik if (getstr(&p, CLSSIZ, ept->pkg_class, ISWORDSEP)) {
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik break; /* we already read the pathname */
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik /* end of line before new-line seen */
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik case '0': case '1': case '2': case '3': case '4':
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik case '5': case '6': case '7': case '8': case '9':
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik /* unknown ftype */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* link/symbolic link must have link destination */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (((ept->ftype == 's') || (ept->ftype == 'l')) &&
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* character/block devices have major/minor device numbers */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (((ept->ftype == 'c') || (ept->ftype == 'b'))) {
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik if (getnumvfp(&p, 10, (long *)&ept->ainfo.major, BADMAJOR) ||
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik getnumvfp(&p, 10, (long *)&ept->ainfo.minor, BADMINOR)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland setErrstr(pkg_gt(ERR_CANNOT_READ_MM_NUMS));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* most types have mode, owner, group identification components */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((ept->ftype == 'd') || (ept->ftype == 'x') || (ept->ftype == 'c') ||
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik (ept->ftype == 'b') || (ept->ftype == 'p') ||
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik (ept->ftype == 'f') || (ept->ftype == 'v') ||
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* mode, owner, group should be here */
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik if (getnumvfp(&p, 8, (long *)&ept->ainfo.mode, BADMODE) ||
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik getstr(&p, sizeof (ept->ainfo.owner), ept->ainfo.owner,
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik getstr(&p, sizeof (ept->ainfo.group), ept->ainfo.group,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* i/f/v/e have size, checksum, modification time components */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((ept->ftype == 'i') || (ept->ftype == 'f') ||
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik (ept->ftype == 'v') || (ept->ftype == 'e')) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* look for content description */
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik if (getlnumvfp(&p, 10, (fsblkcnt_t *)&ept->cinfo.size,
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik getnumvfp(&p, 10, (long *)&ept->cinfo.cksum, BADCONT) ||
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik getnumvfp(&p, 10, (long *)&ept->cinfo.modtime, BADCONT)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* i files processing is completed - return 'exact match found' */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * determine list of packages which reference this entry
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik while ((c = getstr(&p, sizeof (pkgname), pkgname, ISPKGNAMESEP)) <= 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if c < 0 the string was too long to fix in the buffer */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* a package is present - create and populate pinfo structure */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pinfo = (struct pinfo *)calloc(1, sizeof (struct pinfo));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((pkgname[0] == '-') || (pkgname[0] == '+') ||
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik (pkgname[0] == '*') || (pkgname[0] == '~') ||
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik (pkgname[0] == '!') || (pkgname[0] == '%')) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* pkg/[:[ftype][:class] */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (c == '\\') {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* get alternate ftype */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (c == ':') {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* get special classname */
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik (void) getstr(&p, sizeof (classname), classname,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* break out of while if at end of entry */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if package not separated by a space return an error */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * parsing of the entry is complete
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if not at the end of the entry, make it so */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandgetstr(char **cp, int n, char *str, int separator[])
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (*p == '\0') {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* leading white space ignored */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland while (((c = *p) != '\0') && (isspace(*p++)))
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* compute length based on delimiter found or not */
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik while (separator[(int)(*(unsigned char *)p1)] == 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if string will fit in result buffer copy string and return success */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* result buffer too small; copy partial string, return error */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if at end of buffer return no more characters left */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (*p == '\0') {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (n == 0) {