Files
Arquivotheca.Solaris-2.5/lib/libpkg/srchcfile.c
seta75D 7c4988eac0 Init
2021-10-11 19:38:01 -03:00

442 lines
9.6 KiB
C
Executable File

/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
/*LINTLIBRARY*/
#ident "@(#)srchcfile.c 1.12 93/03/10 SMI" /* SVr4.0 1.7.1.1 */
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <pkglib.h>
#include <pkgstrct.h>
#include "pkglocale.h"
#define ERROR(s) \
{ \
errstr = pkg_gt(s); \
(void) getend(fpin); \
return (-1); \
}
static int eatwhite(FILE *fp);
static int getend(FILE *fp);
static int getnum(FILE *fp, int base, long *d, long bad);
static int getstr(FILE *fp, char *sep, int n, char *str);
static char mypath[PATH_MAX];
static char mylocal[PATH_MAX];
int
srchcfile(struct cfent *ept, char *path, FILE *fpin, FILE *fpout)
{
struct pinfo *pinfo, *lastpinfo;
long pos;
char *pt,
pkgname[PKGSIZ+1],
classname[CLSSIZ+1];
int c, n, rdpath, anypath;
/*
* this code uses goto's instead of nested subroutines because
* execution time of this routine is especially critical to
* installation
*/
errstr = NULL;
ept->volno = 0;
ept->ftype = BADFTYPE;
(void) strcpy(ept->pkg_class, BADCLASS);
ept->pkg_class_idx = -1;
ept->path = NULL;
ept->ainfo.local = NULL;
ept->ainfo.mode = BADMODE;
(void) strcpy(ept->ainfo.owner, BADOWNER);
(void) strcpy(ept->ainfo.group, BADGROUP);
ept->cinfo.size = ept->cinfo.cksum = ept->cinfo.modtime = BADCONT;
/* free up list of packages which reference this entry */
while (ept->pinfo) {
pinfo = ept->pinfo->next;
free(ept->pinfo);
ept->pinfo = pinfo;
}
ept->pinfo = NULL;
ept->npkgs = 0;
/*
* if path to search for is "*", then we will return the first path
* we encounter as a match, otherwise we return an error
*/
anypath = 0;
if (path && (path[0] != '/')) {
if (!strcmp(path, "*"))
anypath++;
else {
errstr = "illegal search path specified";
return (-1);
}
}
rdpath = 0;
for (;;) {
if (feof(fpin))
return (0); /* no more entries */
/* save current position in file */
pos = ftell(fpin);
/* grab path from first entry */
c = getc(fpin);
if (c != '/') {
/*
* we check for EOF inside this if statement to
* reduce normal execution time
*/
if (c == EOF)
return (0); /* no more entries */
else if (isspace(c) || (c == '#') || (c == ':')) {
/* line is a comment */
(void) getend(fpin);
continue;
}
/*
* we need to read this entry in the format which
* specifies
* ftype class path
* so we set the rdpath variable and immediately
* jump to the code which will parse this format.
* When done, that code will return to Path_Done below
*/
ungetc(c, fpin);
rdpath = 1;
break;
}
/* copy first token into path element of passed structure */
pt = mypath;
do {
if (strchr("= \t\n", c))
break;
*pt++ = (char) c;
} while ((c = getc(fpin)) != EOF);
*pt = '\0';
if (c == EOF)
ERROR("incomplete entry")
ept->path = mypath;
Path_Done:
/*
* determine if we have read the pathname which identifies
* the entry we are searching for
*/
if (anypath)
n = 0; /* any pathname will do */
else if (path)
n = strcmp(path, ept->path);
else
n = 1; /* no pathname will match */
if (n == 0) {
/*
* we want to return information about this path in
* the structure provided, so parse any local path
* and jump to code which parses rest of the input line
*/
if (c == '=') {
/* parse local path specification */
if (getstr(fpin, NULL, PATH_MAX, mylocal))
ERROR("unable to read local/link path")
ept->ainfo.local = mylocal;
}
break; /* scan into a structure */
} else if (n < 0) {
/*
* the entry we want would fit BEFORE the one we just
* read, so we need to unread what we've read by
* seeking back to the start of this entry
*/
if (fseek(fpin, pos, 0)) {
errstr = pkg_gt("failure attempting fseek");
return (-1);
}
return (2); /* path would insert here */
}
if (fpout) {
/*
* copy what we've read and the rest of this line
* onto the specified output stream
*/
(void) fprintf(fpout, "%s%c", ept->path, c);
if (rdpath) {
(void) fprintf(fpout, "%c %s", ept->ftype,
ept->pkg_class);
}
while ((c = getc(fpin)) != EOF) {
putc(c, fpout);
if (c == '\n')
break;
}
} else {
/*
* since this isn't the entry we want, just read the
* stream until we find the end of this entry and
* then start this search loop again
*/
while ((c = getc(fpin)) != EOF) {
if (c == '\n')
break;
}
if (c == EOF)
ERROR("missing newline at end of entry")
}
}
if (rdpath < 2) {
/*
* since we are processing an oldstyle entry and we have
* already read ftype, class, and path we just jump into
* reading the other info
*/
switch (c = eatwhite(fpin)) {
case EOF:
errstr = pkg_gt("incomplete entry");
return (-1);
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
ERROR("volume number not expected")
case 'i':
ERROR("ftype <i> not expected")
case '?':
case 'f':
case 'v':
case 'e':
case 'l':
case 's':
case 'p':
case 'c':
case 'b':
case 'd':
case 'x':
ept->ftype = (char) c;
if (getstr(fpin, NULL, CLSSIZ, ept->pkg_class))
ERROR("unable to read class token")
if (!rdpath)
break; /* we already read the pathname */
if (getstr(fpin, "=", PATH_MAX, mypath))
ERROR("unable to read pathname field")
ept->path = mypath;
c = getc(fpin);
rdpath++;
goto Path_Done;
default:
errstr = pkg_gt("unknown ftype");
Error:
(void) getend(fpin);
return (-1);
}
}
if (strchr("sl", ept->ftype) && (ept->ainfo.local == NULL))
ERROR("no link source specified");
if (strchr("cb", ept->ftype)) {
#ifdef SUNOS41
ept->ainfo.xmajor = BADMAJOR;
ept->ainfo.xminor = BADMINOR;
if (getnum(fpin, 10, (long *)&ept->ainfo.xmajor, BADMAJOR) ||
getnum(fpin, 10, (long *)&ept->ainfo.xminor, BADMINOR))
#else
ept->ainfo.major = BADMAJOR;
ept->ainfo.minor = BADMINOR;
if (getnum(fpin, 10, (long *)&ept->ainfo.major, BADMAJOR) ||
getnum(fpin, 10, (long *)&ept->ainfo.minor, BADMINOR))
#endif
ERROR("unable to read major/minor device numbers")
}
if (strchr("cbdxpfve", ept->ftype)) {
/* mode, owner, group should be here */
if (getnum(fpin, 8, (long *)&ept->ainfo.mode, BADMODE) ||
getstr(fpin, NULL, ATRSIZ, ept->ainfo.owner) ||
getstr(fpin, NULL, ATRSIZ, ept->ainfo.group))
ERROR("unable to read mode/owner/group")
}
if (strchr("ifve", ept->ftype)) {
/* look for content description */
if (getnum(fpin, 10, (long *)&ept->cinfo.size, BADCONT) ||
getnum(fpin, 10, (long *)&ept->cinfo.cksum, BADCONT) ||
getnum(fpin, 10, (long *)&ept->cinfo.modtime, BADCONT))
ERROR("unable to read content info")
}
if (ept->ftype == 'i') {
if (getend(fpin)) {
errstr = pkg_gt("extra tokens on input line");
return (-1);
}
return (1);
}
/* determine list of packages which reference this entry */
lastpinfo = (struct pinfo *)0;
while ((c = getstr(fpin, ":\\", PKGSIZ, pkgname)) <= 0) {
if (c < 0)
ERROR("package name too long")
else if (c == 0) {
/* a package was listed */
pinfo =
(struct pinfo *)calloc(1, sizeof (struct pinfo));
if (!pinfo)
ERROR("no memory for package information")
if (!lastpinfo)
ept->pinfo = pinfo; /* first one */
else
lastpinfo->next = pinfo; /* link list */
lastpinfo = pinfo;
if (strchr("-+*~!%", pkgname[0])) {
pinfo->status = pkgname[0];
(void) strcpy(pinfo->pkg, pkgname+1);
} else
(void) strcpy(pinfo->pkg, pkgname);
/* pkg/[:[ftype][:class] */
c = getc(fpin);
if (c == '\\') {
/* get alternate ftype */
pinfo->editflag++;
c = getc(fpin);
}
if (c == ':') {
/* get special classname */
(void) getstr(fpin, "", 12, classname);
(void) strcpy(pinfo->aclass, classname);
c = getc(fpin);
}
ept->npkgs++;
if ((c == '\n') || (c == EOF))
return (1);
else if (!isspace(c))
ERROR("bad end of entry")
}
}
if (getend(fpin) && ept->pinfo) {
errstr = pkg_gt("extra token(s) on input line");
return (-1);
}
return (1);
}
static int
getnum(FILE *fp, int base, long *d, long bad)
{
int c;
/* leading white space ignored */
c = eatwhite(fp);
if (c == '?') {
*d = bad;
return (0);
}
if ((c == EOF) || (c == '\n') || !isdigit(c)) {
(void) ungetc(c, fp);
return (1);
}
*d = 0;
while (isdigit(c)) {
*d = (*d * base) + (c & 017);
c = getc(fp);
}
(void) ungetc(c, fp);
return (0);
}
static int
getstr(FILE *fp, char *sep, int n, char *str)
{
int c;
/* leading white space ignored */
c = eatwhite(fp);
if ((c == EOF) || (c == '\n')) {
(void) ungetc(c, fp);
return (1); /* nothing there */
}
/* fill up string until space, tab, or separator */
while (!strchr(" \t", c) && (!sep || !strchr(sep, c))) {
if (n-- < 1) {
*str = '\0';
return (-1); /* too long */
}
*str++ = (char) c;
c = getc(fp);
if ((c == EOF) || (c == '\n'))
break; /* no more on this line */
}
*str = '\0';
(void) ungetc(c, fp);
return (0);
}
static int
getend(FILE *fp)
{
int c;
int n;
n = 0;
do {
if ((c = getc(fp)) == EOF)
return (n);
if (!isspace(c))
n++;
} while (c != '\n');
return (n);
}
static int
eatwhite(FILE *fp)
{
int c;
/* this test works around a side effect of getc() */
if (feof(fp))
return (EOF);
do
c = getc(fp);
while ((c == ' ') || (c == '\t'));
return (c);
}