/*
* 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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <stdio.h>
#include <stdio.h>
#include <errno.h>
#include <limits.h>
#include <fcntl.h>
#include <string.h>
#include <stdarg.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <locale.h>
#include <langinfo.h>
#include <libintl.h>
#include <stdarg.h>
#include <netdb.h>
#include <ctype.h>
#include "cfg_impl.h"
#include "cfg.h"
#include "cfg_lockd.h"
#if 0
#define DEBUG_CFGLIST
#define DEBUG_EXTRA
#define DEBUG_LIB
#define DEBUG_NOISY
#define DEBUG_OUT
#endif
/* parser tree for config section */
static int chead_loaded = 0;
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
#define min(a, b) ((a) > (b) ? (b) : (a))
/* field to be sorted on in sorting routines */
static struct sortby_s {
int offset;
int comperror;
} sortby;
int cfg_severity = 0;
char *cfg_perror_str;
static void cfg_read_parser_config(cfp_t *);
static int cfg_rdlock(CFGFILE *);
static int cfg_wrlock(CFGFILE *);
static int cfg_lockd;
void cfg_replace_lists(cfp_t *);
void cfg_free_parser_tree();
void cfg_invalidate_hsizes(int, const char *);
int cfg_map_cfglists(cfp_t *);
int cfg_hdrcmp(cfp_t *);
void cfg_free_cfglist(cfp_t *);
extern cfg_io_t *cfg_block_io_provider(void);
extern cfg_io_t *cfg_raw_io_provider(void);
extern int cl_initialized;
#ifdef DEBUG_LIB
static void
{
"\tmagic: %x\tstate: %x\n"),
"Start: %x\tsize: %d\toffset: %d\n"),
"Start: %x\tsize:%d\tacsize: %d\n"),
printf("\n\tccopy1: %x\tccopy2: %x\n",
"\tseq1: %d\t\tseq2: %d\n"),
}
#endif /* DEBUG */
/*
* cfg_get_item
* return position from parser config given tag and field
*/
static int
{
int i;
struct lookup *p;
for (i = 0; i < MAX_CFG; i++) {
/* only as many lists as defined */
i = MAX_CFG;
break;
}
break;
}
/* Handle table size */
if (i < MAX_CFG) {
while (p) {
return (p->l_value);
p = p->l_next;
}
}
/* Handle failure */
return (-1);
}
/*
* cfg_get_num_flds
* return number of fields for given parser tag
*/
static int
{
int i;
int pos = 0;
struct lookup *p;
for (i = 0; i < MAX_CFG; i++) {
/* only as many lists as defined */
i = MAX_CFG;
break;
}
*table_index = i;
break;
}
}
/* Handle table size */
if (i < MAX_CFG) {
while (p) {
pos++;
p = p->l_next;
}
return (pos);
}
return (0);
}
/*
* count white space fields
*/
static int
{
char *ptr;
int flds = 0;
return (0);
while (ptr) {
flds++;
}
return (flds);
}
/*
* cfg_get_parser_offset
* returns the index for each
* section of the parser..
* ie. parser info for sndr is chead[3].tag.l_word
* this will help us find sndr quicker, as the
* the memory picture of the sets mimic this ordering
*/
static int
{
int i;
for (i = 0; i < MAX_CFG; i++) {
/* only as many lists as defined */
i = MAX_CFG;
break;
}
break;
}
/* Handle table size */
if (i < MAX_CFG)
return (i);
/* Handle failure */
"cfg_get_parser_offset: section not found");
return (-1);
}
/*
* cfg_fld_mov
* move fields from old buffer to new
* moving only specified fields
* concates newbuf
* returns fields moved
*/
static int
{
char *ptr;
int flds = 0;
return (0);
return (0);
}
return (-1);
while (ptr) {
flds++;
}
}
return (flds);
}
/*
* cfg_filter_node
* return indication if this raw buf should be returned
* checks cfg->cf_node for filtering
* We already know that this buf meets most of our criteria
* find the cnode field in the buf and see if it matches
* returns
* TRUE Good entry
* FALSE Don't use it
*/
static int
{
int i = 1;
int fld;
char *ptr;
return (TRUE);
if (fld < 0) /* no cnode field always good */
return (TRUE);
return (FALSE);
i++;
}
if (!ptr)
return (FALSE);
#ifdef DEBUG_EXTRA
#endif
return (TRUE);
return (FALSE);
}
/*
* cfg_insert_node
* insert resource in bufs which contain cnode parser field
*/
static void
{
int fld;
int nflds;
int table_index;
return;
else
}
/*
* cfg_is_cnode
* Parser current buffer to see if a non-empty " - " cnode exists
*/
/*ARGSUSED*/
static int
{
if (fld >= 0) {
tmpbuf[0] = '\0';
}
return (FALSE);
}
/*
* cfg_get_cstring
* key determines section and value
* special considerations:
* AA.BB.CC...
* AA = data service tag
* BB = set number relative to first set (1..n)
* CC = field of set or if absent, all
*/
int
{
char *section;
char *setp;
char *itemp;
char *p;
int setnum;
int relnum;
int secnum;
int numfound;
int needed;
int table_offset;
return (-1);
}
if (!cfg_rdlock(cfg)) {
return (-1);
}
#ifdef DEBUG_EXTRA
if (!itemp)
else
"cfg_get_cstring:section:%s setp=%s fld=%s\n",
#endif
return (-1);
}
/*
* we have to figure out where this set is
* in relation to other sets
*/
relnum = 1;
secnum = 0;
numfound = 0;
return (-1);
}
}
break;
}
numfound++;
break;
relnum++;
}
break;
}
/* Fail to find anything? */
return (-1);
}
if (buf) {
if (!itemp) {
return (0);
}
if (itemp) {
while (p) {
errno = 0;
if (*p == '-') {
return (0);
}
else
dgettext("cfg",
return (-1);
}
return (pos);
}
if (!p)
break;
pos++;
}
}
}
return (-1);
}
/*
* cfg_find_cstring()
* search for a string in the specified section
* in the specified field(s)
* if nfld is 0, then the string is searched for in
* every field of the entry
* the set number of the first occurence of target is returned
* that is, of course, if the correct field was searched on.
* -1 on error
*
*/
int
char *field, *p;
int i, j, rc;
int fieldnum;
int nflds;
int tbl_off;
return (-1);
}
if (numflds == 0) {
} else {
}
return (-1);
}
if (numflds == 0) { /* search the whole string */
for (i = 0; i < nflds; i++)
return (rc);
}
for (i = 0; i < rc; i++) {
while (p) {
for (j = 0; j < rc; j++)
for (j = 0; j < nflds; j++)
return (i + 1);
}
}
}
for (i = 0; i < nflds; i++)
for (i = 0; i < rc; i++)
return (0);
}
for (i = 0; i < nflds; i++)
return (rc);
}
for (i = 0; i < numflds; i++) {
}
for (j = 0; j < numflds; j++) {
for (i = 0; i < rc; i++) {
pos = 1;
pos++;
}
for (j = 0; j < numflds; j++)
for (j = 0; j < rc; j++)
return (-1);
}
for (j = 0; j < numflds; j++)
for (j = 0; j < rc; j++)
return (i + 1);
}
}
}
for (i = 0; i < nflds; i++)
for (i = 0; i < rc; i++)
return (0);
}
/*
* cfg_put_cstring
* modify entry or add an entry to configuration section
* Key syntax supported
* tag Add entry (in entirely) to config
* tag.setn Add entry to setn If it exists overwrite old entry
* tag.setn.field Change field in setn
* value
* string to change
* NULL delete specified key
*
*/
int
{
char *bufp;
char *section;
char *setp;
char *itemp;
int nofield = 0;
int noset = 0;
int fldnum;
int setnum = 0;
int relnum;
int secnum;
int numfound;
int table_index;
int table_offset;
return (-1);
}
if (!cfg_wrlock(cfg)) {
return (-1);
}
if (!key) {
return (-1);
}
return (-1);
}
if (!itemp)
nofield++;
if (!setp)
noset++;
else if (setp) {
return (-1);
}
}
/*
* we have to figure out where this set is
* in relation to other sets
*/
relnum = 1;
secnum = 0;
numfound = 0;
int rc;
int nflds;
int got;
/*
* Set specified but no field
*/
return (-1);
}
}
== NULL) {
break;
}
section))
numfound++;
break;
relnum++;
}
break;
}
/* Fail to find anything? */
return (-1);
}
/* Remove entry completely */
return (rc);
return (0);
}
return (-1);
}
return (-1);
} else {
/* got == nflds, so cnode was included */
addcnode = 0;
}
if (addcnode) {
}
return (TRUE);
}
/*
* Both Set and field are specified
* needs to get current whole entry and old requested field
* copy good fields to buf, replace new field in buf
* move everything depending of new size
* replace entry so set# does not change
*/
int rc;
int nflds;
int cnodepos;
return (-1);
}
}
== NULL) {
break;
}
section))
numfound++;
break;
relnum++;
}
break;
}
/* Fail to find anything? */
return (-1);
}
/* move good flds in */
if (rc < 0)
return (rc);
/* move new fld in */
/* move remaining flds in */
if (rc < 0)
return (rc);
/* add cnode if user didn't specify it */
}
return (TRUE);
}
if (noset) { /* blast entire thing in */
int nflds;
int got;
int cnodepos;
if (!value) { /* we shouldn't be here */
return (-1);
}
return (-1);
}
/* no cnode, or cnode was specified by caller */
addcnode = 0;
}
return (-1);
} else {
/* got == nflds, so cnode was included */
addcnode = 0;
}
if (addcnode) {
}
/* Make sure we put this entry in the right database */
else
return (-1);
}
}
return (-1);
}
return (TRUE);
}
return (-1);
}
/*
* cfg_encode_char
*
* Encode a single character into % + hex ascii value
*/
static void
{
*result++ = '%';
}
/*
* cfg_decode_char
*
* Reverses cfg_encode_char
*/
static char
{
char retval;
if (*code != '%') {
return ('\0');
}
++code;
return ('\0');
retval <<= 4;
++code;
return ('\0');
return (retval);
}
/*
* cfg_encode_option
*
* Transforms the key and value strings so that special characters
* can be used within the options field.
*
* Returns:
* Length of encoded string; -1 on failure
*/
static int
{
char *mem, *p, *q;
int curlen;
/* first, scan through the tag string converting %-signs */
p = str;
q = output;
curlen = 0;
if (*p == '%') {
return (-1);
}
cfg_encode_char(q, *p);
curlen += 3;
q += 3;
} else {
*q++ = *p;
++curlen;
}
++p;
}
*q = '\0';
/* now encode special characters */
q = output;
curlen = 0;
if (strchr(CHARS_TO_ENCODE, *p) != 0) {
return (-1);
}
cfg_encode_char(q, *p);
curlen += 3;
q += 3;
} else {
*q++ = *p;
++curlen;
}
++p;
}
*q = '\0';
/* LINTED possible ptrdiff_t overflow */
return (q - output);
}
/*
* cfg_decode_option
*
* Given a string, decodes any %-encodes on it.
*/
static void
{
char *p, *q;
int curlen;
p = str;
q = output;
curlen = 0;
if (*p == '%') {
if (!ch) {
*q++ = *p++;
++curlen;
} else {
*q++ = ch;
p += 3;
++curlen;
}
} else {
*q++ = *p++;
++curlen;
}
}
*q = '\0';
}
/*
* cfg_get_options
* return first options set from basekey
* Subsequent calls with basekey = NULL return next option if any
* into tag and val
* returns
* true success and more options data
* -1 no options data
*/
int
{
int rc;
return (-1);
}
if (basekey == 0) {
} else {
if (section == CFG_SEC_CONF) {
} else
return (-1);
if (rc < 0)
return (rc);
/* buf now contains raw options data */
}
return (-1);
return (-1);
}
errno = 0;
return (TRUE);
}
/*
* cfg_put_options
*
* Replaces existing tag with new val. If tag doesn't exist,
* then it adds a new tag with the specified val.
*
* Return:
* true success
* -1 incorrect section, or read error from cfg DB
*/
int
char *val)
{
char *p;
int enclen;
return (-1);
}
if (section != CFG_SEC_CONF) {
return (-1);
}
return (-1);
/* cfg severity & perror_str set up cfg_get_cstring() */
return (-1);
}
*encode_buf = ';';
return (-1);
}
/* check the start of the string */
/* locate the end of this option */
if (p && *(p + 1) != '\0') {
/* add the new tag to the end */
++p;
} else {
/* completely overwrite the existing tag */
p = buf;
}
return (-1);
}
strcat(p, encode_buf);
strcat(p, ";");
/* severity & perror_str set by cfg_put_cstring */
return (-1);
}
errno = 0;
return (TRUE);
}
/* it's hiding somewhere inside... */
if (p) {
/* delete the old value */
if (q) {
} else {
*p = '\0';
}
} else if (*buf) {
} else {
}
return (-1);
}
/* severity & perror_str set by cfg_put_cstring */
return (-1);
}
errno = 0;
return (TRUE);
}
/*
* cfg_get_single_option
*
* Scans the options string for the specified option and returns
* the decoded value
*
* Return:
* true success
* -1 incorrect section, or read error from cfg DB
*/
int
{
char *p, *q;
int enclen;
return (-1);
}
if (section != CFG_SEC_CONF) {
return (-1);
}
/* severity & perror_str set by cfg_get_cstring */
return (-1);
}
*encode_buf = ';';
return (-1);
}
/* check the start of the string */
if (!p) {
return (-1);
}
++p;
q = strchr(p, ';');
if (q) {
*q = '\0';
}
errno = 0;
return (TRUE);
}
/* it's hiding somewhere inside... */
if (p) {
p += enclen + 1;
q = strchr(p, ';');
if (q) {
*q = '\0';
}
errno = 0;
return (TRUE);
}
/* key not found */
return (-1);
}
/*
* cfg_del_option
*
* Removes a single key=val pair from the specified option field
*
* Return:
* true success
* -1 unable to update config
*/
int
{
char *p, *q;
return (-1);
}
if (section != CFG_SEC_CONF) {
return (-1);
}
/* severity & perror_str are set by cfg_get_cstring */
return (-1);
}
*encode_buf = ';';
return (-1);
}
/* check the start of the string */
if (p && (*(p + 1) != '\0')) {
} else {
}
/* severity & perror_str are set by cfg_put_cstring */
return (rc);
}
/* sigh */
if (!p) {
/* already removed */
return (TRUE);
}
/*
* Now the string looks like:
* | first few options | *p | option to remove | *q | rest | '\0'
*/
if (!q) {
/* hum... */
*p = '\0';
} else {
strcpy(p, q);
}
}
static void
{
#ifdef DEBUG_CFGLIST
#endif
}
/*
* cfg_init_header
* fill in default header info
*/
static void
{
/* parser config */
hd->h_parsesize = 0;
hd->h_parseoff = 0;
}
/*
* cfg_read
* read header and all sections of configuration file
* gets new data for incore copy
* removes invalid header state
* works even if config and persistent sections are empty
*
*/
static int
{
int rc;
int readsize = 0;
#ifdef DEBUG_CFGLIST
#endif
return (FALSE);
#ifdef DEBUG_HDR
#endif
}
#ifdef DEBUG_LIB
#endif
return (FALSE);
}
if (rc < 4) {
#ifdef DEBUG_LIB
#endif
return (FALSE);
}
#ifdef DEBUG_LIB
#endif
return (FALSE);
}
#ifdef DEBUG_LIB
#endif
return (FALSE);
}
#ifdef DEBUG_LIB
#endif
return (FALSE);
}
#ifdef DEBUG_CFGLIST
#endif
#ifdef DEBUG
#endif
return (FALSE);
}
#ifdef DEBUG_CFGLIST
#endif
if (rc < 0) {
/* don't fail just return */
#ifdef DEBUG
#endif
return (FALSE);
}
#ifdef DEBUG
#endif
return (FALSE);
}
#ifdef DEBUG_CFGLIST
#endif
if (rc < 0) {
/* don't fail just return */
#ifdef DEBUG
#endif
return (FALSE);
}
/* read the sizes of the lists from disk */
#ifdef DEBUG
#endif
return (FALSE);
}
#ifdef DEBUG_CFGLIST
#endif
if (rc < 0) {
#ifdef DEBUG
#endif
return (FALSE);
}
if (rc < 0) {
#ifdef DEBUG
#endif
return (FALSE);
}
/*
* If initial or invalid sequence, use first section
*/
}
} else {
}
#ifdef DEBUG_LIB
#endif
return (TRUE);
}
/*
* cfg_lock
* Read-write locking of the configuration
* reads into core all sections
* builds parser trees for each section
* Returns: TRUE if the lock was acquired, FALSE otherwise.
*/
int
{
int is_locked = 0;
int rc;
return (FALSE);
}
if (mode == CFG_UPGRADE) {
mode = CFG_WRLOCK;
}
goto fail;
}
/*
* if you don't even give me the right lock request,
* why should I give you one?
*/
goto fail;
if (cfg_lockd) {
if (mode == CFG_WRLOCK)
else
is_locked = 1;
} else {
#ifdef DEBUG_CFGLIST
#endif
/* Lock is always based on local file pointer */
(mode == CFG_RDLOCK))) {
goto fail;
}
}
/* Determine number of files open */
#ifdef DEBUG_HDR
"cfg header match, skipping re-read\n");
#endif
if (mode == CFG_WRLOCK)
continue;
}
#ifdef DEBUG_HDR
#endif
/*
* dump what we have, info is stale
*/
}
}
}
}
}
else
goto fail;
} else {
#ifdef DEBUG_CFGLIST
"reading parser config\n");
#endif
/* build parser trees */
}
}
if (mode == CFG_WRLOCK) {
#ifdef DEBUG_LIB
"cfg_lock: WRLOCK copying 1 to 2\n");
#endif
} else {
#ifdef DEBUG_LIB
"cfg_lock: WRLOCK copying 2 to 1\n");
#endif
}
}
if (cfg_map_cfglists(cfp) < 0) {
#ifdef DEBUG_LIB
#endif
goto fail;
}
#ifdef DEBUG_LIB
#endif
}
return (TRUE);
fail:
if (is_locked) {
}
return (FALSE);
}
/*
* Unlock the database
*/
void
{
#ifdef DEBUG_CFGLIST
#endif
if (cfg_lockd) {
} else {
}
}
}
void
{
return;
}
}
/*
* Test for a read lock, set errno if failed.
*/
static int
{
int rc;
return (FALSE);
}
/* Determine number of files open */
#ifdef DEBUG_LIB
#endif
/*
* 6335583, if header == NULL,
* we can't call cfg_read to fill the header again
* since it will change the lock state to
* CFG_HDR_WRLOCK and dscfg will be the processer
* that hold the lock,
* just returning a FALSE if the case,
* then retrieve the lock state from flock structure.
*/
break;
} else {
#ifdef DEBUG_LIB
#endif
== CFG_HDR_RDLOCK)
else {
break;
}
}
}
if (!rc)
return (rc);
}
/*
* Test for a write lock, set errno if failed.
*/
static int
{
int rc;
return (FALSE);
}
/* Determine number of files open */
#ifdef DEBUG_LIB
#endif
/*
* 6335583, see comments on cfg_rdlock
*/
break;
} else {
#ifdef DEBUG_LIB
#endif
== CFG_HDR_WRLOCK)
else {
break;
}
}
}
if (!rc)
return (rc);
}
/*
* cfg_get_lock
* Find lock status of CFG database.
* Returns: TRUE and sets lock and pid if the lock is held, FALSE otherwise.
*/
int
{
int rc;
return (FALSE);
}
if (cfg_lockd) {
switch (cfg_lockedby(pid)) {
case LOCK_READ:
*lock = CFG_RDLOCK;
return (TRUE);
case LOCK_WRITE:
*lock = CFG_WRLOCK;
return (TRUE);
case LOCK_NOTLOCKED:
default:
return (FALSE);
}
} else {
if (cfg_wrlock(cfg)) {
*lock = CFG_WRLOCK;
return (TRUE);
}
if (cfg_rdlock(cfg)) {
*lock = CFG_RDLOCK;
return (TRUE);
}
}
/* Lock is always based on local file pointer */
else {
else {
}
}
return (rc);
}
/*
* cfg_commit
* Write modified version of header, configuration and persistent
* data using 2 stage commit.
* If no valid data is found in header, it is assumed to be an initial
* write and we will create the default header (could be dangerous)
* another tricky part, if we are doing an upgrade we may be dealing
* with an old database. we need to take care seeking and writing
* until such time that it is upgraded.
*
* Mutual exclusion is checked using cfg_lock
*/
int
{
int rc;
int section;
return (FALSE);
}
if (!cfg_wrlock(cfg))
return (FALSE);
/* Determine number of files open */
/*
* lets put everything back into one char *
*/
#ifdef DEBUG_LIB
#endif
return (FALSE);
}
/* seeking into database */
return (FALSE);
else
section = 1;
} else {
else
section = 2;
}
#ifdef DEBUG_LIB
#endif
#ifdef DEBUG
if (rc < 0) {
"parse commit: rc %d h_parsesize %d\n",
}
#endif
if (section == 1) {
#ifdef DEBUG
if (rc < 0) {
"csection commit 1: rc %d h_csize %d\n",
}
#endif
return (FALSE);
/*
* limit the write to only what we need
*/
#ifdef DEBUG
if (rc < 0) {
"cfg: write list sizes1 failed rc\n");
}
#endif
} else {
CFG_DEFAULT_SSIZE, SEEK_CUR) < 0)
return (FALSE);
#ifdef DEBUG
if (rc < 0) {
"csection commit 2: rc %d h_csize %d\n",
}
#endif
SEEK_CUR) < 0)
return (FALSE);
/*
* limit the write to only what we need
*/
wrsize * sizeof (int));
#ifdef DEBUG
if (rc < 0) {
"cfg: write list sizes2 failed\n");
}
#endif
}
#ifdef DEBUG_CFGLIST
#endif
return (FALSE);
if (rc < 0) {
"cfg_commit: header write failed");
return (FALSE);
}
}
return (TRUE);
}
/*
* cfg_rewind
* rewind internal file pointer for specified section
* empty now, rewind not necessary. But don't break
* old code.
*/
/*ARGSUSED*/
void
{
switch (section) {
case CFG_SEC_CONF:
break;
case CFG_SEC_ALL:
break;
};
}
/*
* cfg_location
* set or return the default location file to
* determine the partition name of the configuration partition
* location is stored in well known file location
*/
char *
{
int fd;
int fmode;
int rc;
if (mode == CFG_LOC_GET_LOCAL) {
return (CFG_LOCAL_LOCATION);
} else if (mode == CFG_LOC_GET_CLUSTER) {
} else {
}
if (altroot) {
} else
if (fd < 0) {
return (NULL);
}
if (mode == CFG_LOC_SET_CLUSTER) {
"cfg_location: filename too big or missing");
return (NULL);
}
/*
* 5082142
* If we're in a cluster, make sure that the config location
* is a raw device. Using non-raw did devices in a cluster
* can result in data corruption, since inconsistent data
* may reside in the block cache on one node, but has not
* been flushed to disk.
*/
if (cfg_iscluster() > 0) {
"Unable to access dscfg location");
return (NULL);
}
"dscfg location must be a raw device");
return (NULL);
}
}
return (NULL);
if (rc < 0) {
"cfg_location: write to well known failed");
return (NULL);
}
}
return (NULL);
if (rc < 0) {
"cfg_location: read from well known failed");
return (NULL);
}
if (altroot) {
}
/*
* scan string out of config_file, to strip whitespace
*/
return (config_file);
}
/*
* cfg_update_parser_config
* If tag and key exist return -1
*
* XXX Currently does not append new field to existing parser rule
*/
int
{
int size;
errno = 0;
return (-1);
}
if (!cfg_wrlock(cfg))
return (-1);
if (section == CFG_PARSE_CONF) {
} else {
return (-1);
}
while (fld) {
/*
* Assure we are loading a clean table, with do duplicates
* based on our File Descriptor
*/
if (size <= 0)
return (-1);
} else {
if (size > 0)
return (-1);
}
}
#ifdef DEBUG_LIB
#endif
"cfg_update_parser_config: header overrun");
#ifdef DEBUG_LIB
"overrun siz %d poff %d parsesize %d\n",
#endif
return (-1);
}
}
return (TRUE);
}
/*
* cfg_read_parser_config
* reads parser config from file
* converts it to internal tree for parsing
* chead for configuration parser entries
*
*/
static
void
{
struct lookup *p, *q;
char *part;
char *key;
char *fld;
int fldnum;
char c;
int i = 0;
int n = 0;
/*CONSTCOND*/
while (TRUE) {
off = 0;
/* LINTED it assigns value to c */
if (c == '\n')
break;
}
if (!part)
break;
if (*part == 'C') {
n = i;
}
if (!key)
break;
fldnum = 1;
if (p == NULL) {
sizeof (struct lookup));
} else {
p = q;
p->l_next = q;
}
#ifdef DEBUG_EXTRA
"read parser: q: word %s value %d\n",
#endif
fldnum++;
}
if (*part == 'C')
i++;
}
/* All done, indicate parser table is loaded */
if (i && (chead_loaded == 0))
/*
* before I go and alloc, why am I here?
* do I need a bunch of cfglists, or do I just
* need to accommodate a just added parser entry
* if the latter, we already have a base, just set
* i to the index of the cfg which members need allocing
*/
sizeof (cfglist_t));
i = 0;
}
else
i = n;
#ifdef DEBUG_CFGLIST
#endif
calloc(DEFAULT_ENTRY_SIZE, sizeof (char));
calloc(DEFAULT_NENTRIES, sizeof (int));
" allocate cfglist members");
}
}
} else {
}
}
/*
* cfg_map_cfglists()
* go through list of list sizes in header
* and create separate lists
*/
int
{
int i;
int offset = 0;
int *ip;
int list_size = 0;
int slot_inc;
char *p;
/* get the first list size */
if (ch->h_cfgsizes[i] > 0) {
ch->h_cfgsizes[i] * sizeof (char));
/* set free to 0, we'll get more when we add */
} else
/* get lists and marry up to each cfgs structure */
ip++;
if (list_size > DEFAULT_NENTRIES) {
/*
* we're gonna need more slots
* we want to alloc on DEFAULT_NENTRIES
* boundry. ie. always a multiple of it
* later on, when we add to the list
* we can see if we need to add by mod'ding
* l_nentry and DEFAULT_NENTRIES and check for 0
*/
if (slot_inc == DEFAULT_NENTRIES)
slot_inc = 0; /* addcfline reallocs */
}
list_size * sizeof (int));
} else
continue;
#ifdef DEBUG_CFGLIST
#endif
p, ch->h_cfgsizes[i]);
} else {
#ifdef DEBUG_CFGLIST
#endif
return (-1);
}
}
return (1);
}
void
{
int i;
int offset = 0;
int size_offset = 0;
int section = 0;
return;
#ifdef DEBUG_CFGLIST
#endif
section = 1;
/*
* check to see if we are using copy1 or 2,
* grow or shrink the size, fix h_cparse reference
* in case realloc gave us a funky new address.
* put stuff in it.
*/
if (section == 1) {
/* we used copy1 */
} else
/*
* just because, we'll zero out h_csize and recalc
* after all, this is the number the next guy gets
*/
for (i = 0; i < MAX_CFG; i++) {
/* only as many lists as chead has */
break;
}
#ifdef DEBUG_CFGLIST
"copying list %d at %x size %d\n",
#endif
#ifdef DEBUG_CFGLIST
"cfl[%d].l_nentry %d cfl[%d].l_esiz[%d] %d"
" size offset %d\n",
#endif
/*
* first write the number of entries
* then copy over the array ie.
* a list with 5 elements would be copied
* as a 6 element array slot 0 being the
* number of elements
*/
}
}
}
void
{
int i;
return;
}
}
}
}
}
}
void
{
int i;
for (i = 0; i < MAX_CFG; i++) {
if (chead)
while (p) {
q = p->l_next;
if (p) {
free(p);
p = NULL;
}
p = q;
}
}
}
void
{
return;
}
/* Determine number of files open */
#ifdef DEBUG_CFGLIST
#endif
#ifdef DEBUG_CFGLIST
#endif
#ifdef DEBUG_CFGLIST
"freeing copy1, copy2, h_sizes and cf\n");
#endif
}
}
}
}
}
}
#ifdef DEBUG_CFGLIST
#endif
}
char *
{
return (NULL);
}
}
/*
* cfg_resource
*/
void
{
return;
}
#ifdef DEBUG_CFGLIST
"cfg_resource: changing node from %s to %s\n",
#endif
}
/*
* just in case someone passes in a non-NULL
* node, but has no valid value
*/
}
}
/*
* cfg_open
* Open the current configuration file
*/
CFGFILE *
{
long needed;
int rc;
#ifdef DEBUG_CFGLIST
#endif
cfg_severity = 0;
"cfg_open: malloc failed");
return (NULL);
}
#ifdef DEBUG
#endif
: cfg_raw_io_provider();
} else {
/* Handle cfg_open(""), which is an open from boot tools */
if (name)
cl_initialized = 1;
if (cfg_iscluster() > 0) {
}
}
}
/*
* Open one or two configuration files
*/
"cfg_open: unable to open configuration location");
break;
}
/* block device smaller than repository? */
"cfg_open: unable to read configuration header");
break;
}
"cfg_open: unable to seek configuration header");
break;
}
/*
* we can't enforce size rules on an old database
* so check the magic number before we test for size
*/
if (magic == CFG_NEW_MAGIC) {
(sizeof (struct cfgheader) + CFG_CONFIG_SIZE));
} else {
needed = 0;
}
"cfg_open: configuration file too small");
break;
}
"cfg_open: malloc failed");
break;
}
}
/* Processing errors, take care of one or more cfp pointers */
return (NULL);
}
cfg_lockd = cfg_lockd_init();
#ifdef DEBUG_CFGLIST
#endif
return (cfg);
}
void
int offset;
int hdrsz;
(sizeof (cfgheader_t) % 512);
(CFG_DEFAULT_SSIZE * 2);
offset += CFG_VTOC_SKIP;
if (rc < 0)
}
char *
{
*severity = cfg_severity;
}
/*
* cfg_cfg_isempty
*/
int
{
return (FALSE);
}
return (TRUE);
else
return (FALSE);
}
/*
* cfg_get_num_entries
* return the number of entries in a given section of database
* sndr, ii, ndr_ii...
*/
int
{
int count = 0;
int table_offset;
return (-1);
}
return (-1);
}
/* Determine number of files open */
return (count);
}
/*
* cfg_get_section
* all etries in a config file section is placed in
* buf, allocation is done inside
* freeing buf is responisbility of the caller
* number of entries in section is returned
* -1 on failure, errno is set
*/
int
{
int table_offset;
int i, count;
char *p = NULL;
char **buf;
return (FALSE);
}
return (-1);
}
/* Determine number of files open */
count = 0;
return (-1);
}
}
continue;
if (count == 0)
else
sizeof (char *));
return (-1);
} else {
}
return (-1);
}
}
}
return (count);
}
/*
* cluster upgrade helper functions. These support old database operations
* while upgrading nodes on a cluster.
*/
/*
* returns the list of configured tags
* return -1 on error, else the number
* of tags returned in taglist
* caller frees
*/
int
{
char **list;
int i = 0;
return (-1);
}
if (!cfg_rdlock(cfg)) {
return (-1);
}
return (-1);
}
for (/* CSTYLE */; i >= 0; i--) {
if (list[i])
}
return (-1);
}
i++;
}
return (i);
}
/*
* is this a database?
* check the header for the magic number
* 0 no match 1 match, -1 on error
*/
int
{
int rc;
return (-1);
}
if (magic == CFG_NEW_MAGIC)
return (1);
"configuration not initialized, bad magic");
return (0);
}
int
compare(const void* a, const void *b)
{
char *p;
char *pbuf;
char *q;
char *qbuf;
int needed;
int cmp;
int pos;
return (0);
pos = 1;
while (p) {
break;
}
if (!p)
break;
pos++;
}
pos = 1;
while (q) {
break;
}
if (!q)
break;
pos++;
}
if (!p || !q) {
return (0);
}
return (cmp);
}
/*
* cfg_get_srtdsec
* returns the section, sorted by supplied field
* caller frees mem
*/
int
const char *field)
{
char **buf;
char *tmplst;
char *p, *q;
int table_offset;
int count, i;
return (FALSE);
}
return (-1);
}
/*
* do essentially what get_section does,
* except stick entries in a static size
* buf to make things easier to qsort
*/
count = 0;
return (-1);
}
}
continue;
if (count == 0)
else
sizeof (char *));
"malloc failed");
return (-1);
} else {
}
/*
* allocate each line
*/
return (-1);
}
}
if (count == 0)
else
"malloc failed");
return (-1);
} else {
}
/*
* put the section in tmplst and sort
*/
p += CFG_MAX_BUF;
}
}
"comparison error");
return (-1);
}
p = tmplst;
for (i = 0; i < count; i++) {
p += CFG_MAX_BUF;
}
return (count);
}
/*
* free an array alloc'd by get_*section
* or some other array of size size
*/
void
{
int i;
for (i = 0; i < size; i++) {
if (secpp[i]) {
}
}
if (secpp) {
}
}
int
{
int slice;
int rfd;
char *p;
return (-1);
}
return (0);
return (-1);
return (1);
else
return (0);
}
if (p == NULL)
return (-1);
return (-1);
}
return (-1);
}
return (1);
else
return (0);
}
return (-1);
}
/*
* comapares incore header with one on disk
* returns 0 if equal, 1 if not, -1 error
*/
int
{
int rc;
}
return (-1);
}
if (rc < 0) {
return (-1);
}
rc = 0;
else
rc = 1;
return (rc);
}