/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include "pkgstrct.h"
#include "pkglib.h"
#include "pkglibmsgs.h"
#include "pkglocale.h"
"device numbers"
static void findendvfp(char **cp);
/*
* These determine how gpkgmap() deals with mode, owner and group defaults.
* It is assumed that the owner and group arguments represent static fields
* which will persist until attrdefault() is called.
*/
void
{
}
void
{
}
/*
* This determines how gpkgmap() deals with environment variables in the
* mode, owner and group. Path is evaluated at a higher level based upon
* other circumstances.
*/
void
{
maptype = " build";
else if (mode == MAPINSTALL)
maptype = " install";
else
maptype = "";
}
}
/* This is the external query interface for mapmode. */
int
getmapmode(void)
{
return (mapmode);
}
/*
* Unpack the pkgmap or the contents file or whatever file is in that format.
* Based upon mapmode, environment parameters will be resolved for mode,
* owner and group.
*/
int
{
int c;
/* default attributes were supplied, so don't reset */
if (!fp)
return (-1);
/*
* If the first character is not a digit, we assume that the
* volume number is 1.
*/
if (first_char && !isdigit(c)) {
}
switch (c) {
case EOF:
return (0);
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
goto error;
}
do {
} while (isdigit(c));
goto readline;
case ':':
case '#':
/*FALLTHRU*/
case '\n':
/*
* Since we are going to scan the next line,
* we need to reset volume number and first_char.
*/
first_char = B_TRUE;
goto readline;
case 'i':
/*FALLTHRU*/
case '.':
case '/':
goto error;
}
if (c == '=') {
goto error;
}
} else
/* content info might exist */
BADCONT) &&
BADCONT) ||
BADCONT))) {
goto error;
}
}
return (-1);
}
return (1);
case '?':
case 'f':
case 'v':
case 'e':
case 'l':
case 's':
case 'p':
case 'c':
case 'b':
case 'd':
case 'x':
goto error;
}
goto error;
}
if (c == '=') {
/* local path */
} else {
}
goto error;
}
if ((c != EOF) && (c != '\n'))
return (-1);
} else
break;
default:
return (-1);
}
goto error;
}
goto error;
}
}
/*
* Links and information files don't have attributes associated with
* them. The following either resolves potential variables or passes
* them through. Mode is tested for validity to some degree. BAD???
* is returned to indicate that no meaningful mode was provided. A
* higher authority will decide if that's OK or not. CUR??? means that
* the prototype file specifically requires a wildcard ('?') for
* that entry. We issue an error if attributes were entered wrong.
* We just return BAD??? if there was no entry at all.
*/
int retval;
goto end; /* nothing else on the line */
else if (retval == 2)
goto error; /* mode is too no good */
/* owner & group should be here */
goto end; /* no owner or group - warning */
if (retval == -1) {
goto error;
}
goto end; /* no group - warning */
if (retval == -1) {
goto error;
}
/* Resolve the parameters if required. */
(void) snprintf(getErrbufAddr(),
goto error;
}
(void) snprintf(getErrbufAddr(),
goto error;
}
}
}
/* look for content description */
goto error;
}
}
goto end;
end:
return (-1);
}
done:
return (1);
}
/*
* Get and validate the mode attribute. This returns an error if
* 1. the mode string is too long
* 2. the mode string includes alpha characters
* 3. the mode string is not octal
* 4. mode string is an install parameter
* 5. mode is an unresolved build parameter and MAPBUILD is
* in effect.
* If the mode is a build parameter, it is
* 1. returned as is if MAPNONE is in effect
* 2. evaluated if MAPBUILD is in effect
*
* NOTE : We use "mapmode!=MAPBUILD" to gather that it is install
* time. At install time we just fix a mode with bad bits set by
* setting it to CURMODE. This should be an error in a few releases
* (2.8 maybe) but faulty modes are so common in existing packages
* that this is a reasonable exception. -- JST 1994-11-9
*
* RETURNS
* 0 if mode is being returned as a valid value
* 1 if no attributes are present on the line
* 2 if there was a fundamental error
*/
static int
{
int retval;
return (1);
else if (retval == -1) {
return (2);
} else {
/*
* If it isn't a '?' (meaning go with whatever mode is
* there), validate the mode and convert it to a mode_t. The
* "bad" variable here is a misnomer. It doesn't necessarily
* mean bad.
*/
if (tempmode[0] == '?') {
*d = WILDCARD;
} else {
/*
* Mode may not be an install parameter or a
* non-build parameter.
*/
if (tempmode[0] == '$' &&
return (2);
}
(void) snprintf(getErrbufAddr(),
return (2);
}
if (tempmode[0] == '$') {
*d = BADMODE; /* may be a problem */
} else {
/*
* At this point it's supposed to be
* something we can convert to a number.
*/
int n = 0;
/*
* We reject it if it contains nonnumbers or
* it's not octal.
*/
return (2);
}
if (strchr("89abcdefABCDEF",
tempmode[n])) {
return (2);
}
n++;
}
/*
* We reject it if it contains inappropriate
* bits.
*/
if (tempmode_t & ~(S_IAMB |
tempmode_t = bad;
} else {
return (2);
}
}
*d = tempmode_t;
}
}
return (0);
}
}
static int
{
int c, b;
/* leading white space ignored */
if (c == '?') {
*d = bad;
return (0);
}
return (1);
}
*d = 0;
while (isdigit(c)) {
b = (c & 017);
if (b >= base)
return (2);
*d = (*d * base) + b;
}
return (0);
}
static int
{
int c, b;
/* leading white space ignored */
if (c == '?') {
*d = bad;
return (0);
}
return (1);
}
*d = 0;
while (isdigit(c)) {
b = (c & 017);
if (b >= base)
return (2);
*d = (*d * base) + b;
}
return (0);
}
/*
* Get a string from the file. Returns
* 0 if all OK
* 1 if nothing there
* -1 if string is too long
*/
static int
{
int c;
/* leading white space ignored */
if ((c == EOF) || (c == '\n')) {
return (1); /* nothing there */
}
/* fill up string until space, tab, or separator */
if (n-- < 1) {
*str = '\0';
return (-1); /* too long */
}
*str++ = (char)c;
if ((c == EOF) || (c == '\n'))
break; /* no more on this line */
}
*str = '\0';
return (0);
}
static int
{
int c;
int n;
n = 0;
do {
return (n);
if (!isspace(c))
n++;
} while (c != '\n');
return (n);
}
static int
{
int c;
/* this test works around a side effect of getc() */
return (EOF);
do
while ((c == ' ') || (c == '\t'));
return (c);
}
int
{
int c;
/* return error if no vfp specified */
return (-1);
}
;
/*
* If the first character is not a digit, we assume that the
* volume number is 1.
*/
if (first_char && !isdigit(c)) {
}
/*
* In case of hsfs the zero-padding of partial pages
* returned by mmap is not done properly. A separate bug has been filed
* on this.
*/
return (0);
}
switch (c) {
case '\0':
return (0);
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
goto error;
}
do {
} while (isdigit(c));
}
goto readline;
case ':':
case '#':
/*FALLTHRU*/
case '\n':
/*
* Since we are going to scan the next line,
* we need to reset volume number and first_char.
*/
first_char = B_TRUE;
goto readline;
case 'i':
;
/*FALLTHRU*/
case '.':
case '/':
goto error;
}
if (c == '=') {
mylocal)) {
goto error;
}
} else {
}
/* content info might exist */
goto error;
}
}
return (-1);
}
return (1);
case '?':
case 'f':
case 'v':
case 'e':
case 'l':
case 's':
case 'p':
case 'c':
case 'b':
case 'd':
case 'x':
goto error;
}
goto error;
}
if (c == '=') {
/* local path */
} else {
}
goto error;
}
if ((c != '\0') && (c != '\n'))
return (-1);
} else {
}
break;
default:
return (-1);
}
goto error;
}
goto error;
}
}
/*
* Links and information files don't have attributes associated with
* them. The following either resolves potential variables or passes
* them through. Mode is tested for validity to some degree. BAD???
* is returned to indicate that no meaningful mode was provided. A
* higher authority will decide if that's OK or not. CUR??? means that
* the prototype file specifically requires a wildcard ('?') for
* that entry. We issue an error if attributes were entered wrong.
* We just return BAD??? if there was no entry at all.
*/
int retval;
if (retval == 1) {
goto end; /* nothing else on the line */
} else if (retval == 2) {
goto error; /* mode is too no good */
}
/* owner & group should be here */
goto end; /* no owner or group - warning */
if (retval == -1) {
goto error;
}
goto end; /* no group - warning */
if (retval == -1) {
goto error;
}
/* Resolve the parameters if required. */
(void) snprintf(getErrbufAddr(),
goto error;
}
(void) snprintf(getErrbufAddr(),
goto error;
}
}
}
/* look for content description */
goto error;
}
}
goto end;
end:
return (-1);
}
done:
return (1);
}
/*
* Get and validate the mode attribute. This returns an error if
* 1. the mode string is too long
* 2. the mode string includes alpha characters
* 3. the mode string is not octal
* 4. mode string is an install parameter
* 5. mode is an unresolved build parameter and MAPBUILD is
* in effect.
* If the mode is a build parameter, it is
* 1. returned as is if MAPNONE is in effect
* 2. evaluated if MAPBUILD is in effect
*
* NOTE : We use "mapmode!=MAPBUILD" to gather that it is install
* time. At install time we just fix a mode with bad bits set by
* setting it to CURMODE. This should be an error in a few releases
* (2.8 maybe) but faulty modes are so common in existing packages
* that this is a reasonable exception. -- JST 1994-11-9
*
* RETURNS
* 0 if mode is being returned as a valid value
* 1 if no attributes are present on the line
* 2 if there was a fundamental error
*/
static int
{
int retval;
int n;
return (1);
} else if (retval == -1) {
return (2);
}
/*
* If it isn't a '?' (meaning go with whatever mode is
* there), validate the mode and convert it to a mode_t. The
* "bad" variable here is a misnomer. It doesn't necessarily
* mean bad.
*/
if (tempmode[0] == '?') {
*d = WILDCARD;
return (0);
}
/*
* Mode may not be an install parameter or a
* non-build parameter.
*/
if (tempmode[0] == '$' &&
return (2);
}
return (2);
}
if (tempmode[0] == '$') {
*d = BADMODE; /* may be a problem */
return (0);
}
/* it's supposed to be something we can convert to a number */
n = 0;
/* reject it if it contains nonnumbers or it's not octal */
return (2);
}
return (2);
}
n++;
}
/*
* We reject it if it contains inappropriate
* bits.
*/
return (2);
}
tempmode_t = bad;
}
*d = tempmode_t;
return (0);
}
int
{
int c;
char *p = *cp;
if (*p == '\0') {
return (0);
}
/* leading white space ignored */
while (((c = *p) != '\0') && (isspace(*p++)))
;
if (c == '?') {
*d = bad;
*cp = p;
return (0);
}
p--;
*cp = p;
return (1);
}
*d = 0;
while (isdigit(c)) {
*d = (*d * base) + (c & 017);
c = *p++;
}
p--;
*cp = p;
return (0);
}
int
{
int c;
char *p = *cp;
if (*p == '\0') {
return (0);
}
/* leading white space ignored */
while (((c = *p) != '\0') && (isspace(*p++)))
;
if (c == '?') {
*d = bad;
*cp = p;
return (0);
}
p--;
*cp = p;
return (1);
}
*d = 0;
while (isdigit(c)) {
*d = (*d * base) + (c & 017);
c = *p++;
}
p--;
*cp = p;
return (0);
}
static int
{
int c;
char *p = *cp;
char *p1;
if (*p == '\0') {
return (1);
}
/* leading white space ignored */
while (((c = *p) != '\0') && (isspace(*p++)))
;
if ((c == '\0') || (c == '\n')) {
p--;
*cp = p;
return (1); /* nothing there */
}
p--;
/* generate complete list of delimiters to scan for */
}
/* compute length based on delimiter found or not */
} else {
}
/* if string will fit in result buffer copy string and return success */
if (len < n) {
p += len;
*cp = p;
return (0);
}
/* result buffer too small; copy partial string, return error */
p += n;
*cp = p;
return (-1);
}
/*
* Name: getendvfp
* Description: Locate the end of the current line given a pointer into a buffer
* containing characters that is null terminated.
* Arguments: char **cp - pointer to pointer to null-terminated string buffer
* Returns: int == 0 -- no non-space characters preceeded the newline
* != 0 -- one or more non-space characters preceeded newline
* Effects: cp is updated to point to the first character PAST the first new
* line character found. If no newline character is found, cp is
* updated to point to the '\0' at the end of the buffer.
*/
static int
{
int n;
char *p = *cp;
n = 0;
/* if at end of buffer return no more characters left */
if (*p == '\0') {
return (0);
}
/* find the first null or end of line character */
while ((*p != '\0') && (*p != '\n')) {
if (n == 0) {
if (!isspace(*p)) {
n++;
}
}
p++;
}
/* if at newline, increment pointer to first character past newline */
if (*p == '\n') {
p++;
}
/* set return pointer to null or first character past newline */
*cp = p;
return (n);
}
/*
* Name: findendvfp
* Description: Locate the end of the current line given a pointer into a buffer
* containing characters that is null terminated.
* Arguments: char **cp - pointer to pointer to null-terminated string buffer
* Returns: none
* Effects: cp is updated to point to the first character PAST the first new
* line character found. If no newline character is found, cp is
* updated to point to the '\0' at the end of the buffer.
*/
static void
{
char *p1;
char *p = *cp;
/* if at end of buffer return no more characters left */
if (*p == '\0') {
return;
}
/* find the end of the line */
return;
}
/* no newline found - point to null terminator */
}