summaryrefslogtreecommitdiff
path: root/usr/src/lib/libdscfg/common/cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libdscfg/common/cfg.c')
-rw-r--r--usr/src/lib/libdscfg/common/cfg.c3585
1 files changed, 0 insertions, 3585 deletions
diff --git a/usr/src/lib/libdscfg/common/cfg.c b/usr/src/lib/libdscfg/common/cfg.c
deleted file mode 100644
index 17f668744a..0000000000
--- a/usr/src/lib/libdscfg/common/cfg.c
+++ /dev/null
@@ -1,3585 +0,0 @@
-/*
- * 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
- * or http://www.opensolaris.org/os/licensing.
- * 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 <sys/types.h>
-#include <sys/wait.h>
-#include <stdio.h>
-#include <sys/mnttab.h>
-#include <sys/vtoc.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 <sys/mman.h>
-#include <sys/stat.h>
-
-#include <locale.h>
-#include <langinfo.h>
-#include <libintl.h>
-#include <stdarg.h>
-#include <netdb.h>
-#include <ctype.h>
-#include <sys/stat.h>
-#include <sys/utsname.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
-
-#define MAX_CFG 16 /* Max. number of lines in /etc/dscfg_format */
-#define MAX_SET 12 /* number of chars in a set name */
-
-
-/* parser tree for config section */
-static struct parser chead[MAX_CFG] = { NULL };
-static int chead_loaded = 0;
-static char config_file[CFG_MAX_BUF];
-static char dectohex[] = { '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
-#define CHARS_TO_ENCODE "=;\t "
-#define min(a, b) ((a) > (b) ? (b) : (a))
-
-/* field to be sorted on in sorting routines */
-static struct sortby_s {
- char section[CFG_MAX_KEY];
- char field[CFG_MAX_KEY];
- int offset;
- int comperror;
-} sortby;
-
-int cfg_severity = 0;
-char *cfg_perror_str;
-static int cfg_read(cfp_t *);
-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
-dump_status(cfp_t *cfp, char *str)
-{
- printf("called from %s\n", str);
- printf(gettext("Header info:\n"
- "\tmagic: %x\tstate: %x\n"),
- cfp->cf_head->h_magic, cfp->cf_head->h_state);
- printf(gettext("Parser section:\n"
- "Start: %x\tsize: %d\toffset: %d\n"),
- cfp->cf_mapped, cfp->cf_head->h_parsesize,
- cfp->cf_head->h_parseoff);
- printf(gettext("Config section:\n"
- "Start: %x\tsize:%d\tacsize: %d\n"),
- cfp->cf_head->h_cparse, cfp->cf_head->h_csize,
- cfp->cf_head->h_acsize);
- printf("\n\tccopy1: %x\tccopy2: %x\n",
- cfp->cf_head->h_ccopy1, cfp->cf_head->h_ccopy2);
- printf(gettext("Sequence:\n"
- "\tseq1: %d\t\tseq2: %d\n"),
- cfp->cf_head->h_seq1, cfp->cf_head->h_seq2);
-}
-#endif /* DEBUG */
-
-/*
- * cfg_get_item
- * return position from parser config given tag and field
- */
-static int
-cfg_get_item(struct parser *tbl, const char *tag, const char *field)
-{
- int i;
- struct lookup *p;
-
- for (i = 0; i < MAX_CFG; i++) {
- /* only as many lists as defined */
- if (tbl[i].tag.l_word[0] == '\0') {
- i = MAX_CFG;
- break;
- }
- if (strcmp(tbl[i].tag.l_word, tag) == 0)
- break;
- }
-
- /* Handle table size */
- if (i < MAX_CFG) {
- p = tbl[i].fld;
- while (p) {
- if (strcmp(p->l_word, field) == 0)
- 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
-cfg_get_num_flds(struct parser *tbl, const char *tag, int *table_index)
-{
- int i;
- int pos = 0;
- struct lookup *p;
-
- for (i = 0; i < MAX_CFG; i++) {
- /* only as many lists as defined */
- if (tbl[i].tag.l_word[0] == '\0') {
- i = MAX_CFG;
- break;
- }
- if (strcmp(tbl[i].tag.l_word, tag) == 0) {
- *table_index = i;
- break;
- }
- }
-
- /* Handle table size */
- if (i < MAX_CFG) {
- p = tbl[i].fld;
- while (p) {
- pos++;
- p = p->l_next;
- }
- return (pos);
- }
-
- return (0);
-}
-
-/*
- * count white space fields
- */
-static int
-cfg_cnt_flds(char *value)
-{
- char *ptr;
- char buf[CFG_MAX_BUF];
- int flds = 0;
-
- if ((value == NULL) || (strlen(value) >= CFG_MAX_BUF))
- return (0);
-
- bzero(buf, CFG_MAX_BUF);
- strcpy(buf, value);
- ptr = strtok(buf, " ");
- while (ptr) {
- flds++;
- ptr = strtok(NULL, " ");
- }
- 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
-cfg_get_parser_offset(const char *section)
-{
- int i;
-
- for (i = 0; i < MAX_CFG; i++) {
- /* only as many lists as defined */
- if (chead[i].tag.l_word[0] == '\0') {
- i = MAX_CFG;
- break;
- }
- if (strcmp(chead[i].tag.l_word, section) == 0)
- break;
- }
-
- /* Handle table size */
- if (i < MAX_CFG)
- return (i);
-
- /* Handle failure */
- cfg_perror_str = dgettext("cfg",
- "cfg_get_parser_offset: section not found");
- cfg_severity = CFG_EFATAL;
- errno = ESRCH;
- return (-1);
-}
-
-/*
- * cfg_fld_mov
- * move fields from old buffer to new
- * moving only specified fields
- * concates newbuf
- * returns fields moved
- */
-static int
-cfg_fld_mov(char *newbuf, char *oldbuf, int start, int end)
-{
- char buf[CFG_MAX_BUF];
- char *ptr;
- int flds = 0;
-
- bzero(buf, CFG_MAX_BUF);
- if (oldbuf == NULL)
- return (0);
-
- if ((start > end) || (strlen(oldbuf) >= CFG_MAX_BUF)) {
- return (0);
- }
- if (!start || !end)
- return (-1);
- strcpy(buf, oldbuf);
- ptr = strtok(buf, " ");
- while (ptr) {
- flds++;
- if (flds >= start && flds <= end) {
- strcat(newbuf, ptr);
- strcat(newbuf, " ");
- }
- ptr = strtok(NULL, " ");
- }
-
- 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
-cfg_filter_node(CFGFILE *cfg, struct parser *tbl, char *buf, char *tag)
-{
- char tmpbuf[CFG_MAX_BUF];
- int i = 1;
- int fld;
- char *ptr;
-
- if (!cfg->cf_node) /* no filter always good */
- return (TRUE);
- bzero(tmpbuf, CFG_MAX_BUF);
- fld = cfg_get_item(tbl, tag, "cnode");
- if (fld < 0) /* no cnode field always good */
- return (TRUE);
- strncpy(tmpbuf, buf, CFG_MAX_BUF);
- if (tmpbuf[CFG_MAX_BUF - 1] != '\0')
- return (FALSE);
- ptr = strtok(tmpbuf, " ");
- while (ptr && (i < fld)) {
- ptr = strtok(NULL, " ");
- i++;
- }
- if (!ptr)
- return (FALSE);
-#ifdef DEBUG_EXTRA
- (void) fprintf(stderr, "cfg_filter_node: node=%s:%d cnode=%s:%d\n",
- cfg->cf_node, strlen(cfg->cf_node), ptr, strlen(ptr));
-#endif
- if (strcmp(ptr, cfg->cf_node) == 0)
- return (TRUE);
- return (FALSE);
-}
-/*
- * cfg_insert_node
- * insert resource in bufs which contain cnode parser field
- */
-static void
-cfg_insert_node(CFGFILE *cfg, struct parser *tbl, char *buf, char *tag)
-{
- char tmpbuf[CFG_MAX_BUF];
- int fld;
- int nflds;
- int table_index;
-
- bzero(tmpbuf, CFG_MAX_BUF);
- strcpy(tmpbuf, " ");
- fld = cfg_get_item(tbl, tag, "cnode");
- nflds = cfg_get_num_flds(tbl, tag, &table_index);
- if ((fld < 0) && !(cfg->cf_node)) /* no cnode field always good */
- return;
-
- cfg_fld_mov(tmpbuf, buf, 1, (fld - 1));
- if (cfg->cf_node)
- strcat(tmpbuf, cfg->cf_node);
- else
- strcat(tmpbuf, "-");
- strcat(tmpbuf, " ");
- cfg_fld_mov(tmpbuf, buf, (fld + 1), nflds);
- bcopy(tmpbuf, buf, strlen(tmpbuf) + 1);
-}
-
-/*
- * cfg_is_cnode
- * Parser current buffer to see if a non-empty " - " cnode exists
- */
-/*ARGSUSED*/
-static int
-cfg_is_cnode(CFGFILE *cfg, struct parser *tbl, char *buf, char *tag)
-{
- char tmpbuf[CFG_MAX_BUF];
- int fld = cfg_get_item(tbl, tag, "cnode");
-
- if (fld >= 0) {
- tmpbuf[0] = '\0';
- cfg_fld_mov(tmpbuf, buf, fld, fld);
- return (strcmp(tmpbuf, "- ") ? TRUE : FALSE);
- }
- 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
-cfg_get_cstring(CFGFILE *cfg, const char *key, void *value, int value_len)
-{
- cfp_t *cfp;
- char buf[CFG_MAX_BUF];
- char tmpkey[CFG_MAX_KEY];
- char *section;
- char set[MAX_SET];
- char *setp;
- char *itemp;
- char *p;
- int pos = 1;
- int setnum;
- int relnum;
- int secnum;
- int numfound;
- int needed;
- int table_offset;
-
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- return (-1);
- }
-
- if (!cfg_rdlock(cfg)) {
- cfg_perror_str = dgettext("cfg", CFG_NOTLOCKED);
- cfg_severity = CFG_EFATAL;
- return (-1);
- }
-
- bzero(buf, sizeof (buf));
- bzero(set, sizeof (set));
- bzero(tmpkey, sizeof (tmpkey));
- strcpy(tmpkey, key);
- section = strtok(tmpkey, ".");
- setp = strtok(NULL, ".");
- itemp = strtok(NULL, ".");
-
-#ifdef DEBUG_EXTRA
- if (!itemp)
- (void) fprintf(stderr, "cfg_get_cstring:section:%s setp=%s\n",
- section, setp);
- else
- (void) fprintf(stderr,
- "cfg_get_cstring:section:%s setp=%s fld=%s\n",
- section, setp, itemp);
-#endif
-
- table_offset = cfg_get_parser_offset(section);
- setnum = atoi(setp + 3);
- if ((setnum < 1) || (setnum > 0x7ffd)) {
- errno = EINVAL;
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_ENONFATAL;
- return (-1);
- }
-
- /*
- * we have to figure out where this set is
- * in relation to other sets
- */
- relnum = 1;
- secnum = 0;
- numfound = 0;
- for (cfp = &cfg->cf[0]; cfp <= &cfg->cf[1]; cfp++) {
- if (!cfp->cf_fd) continue;
- if (cfp->cf_head->h_state & CFG_HDR_INVALID) {
- if (!cfg_read(cfp)) {
- cfg_perror_str = dgettext("cfg", CFG_RDFAILED);
- cfg_severity = CFG_EFATAL;
- return (-1);
- }
- }
- while (numfound < setnum) {
- if ((*cfp->cf_pp->readcf)
- (cfp, buf, table_offset, relnum - secnum) == NULL) {
- secnum = relnum - 1;
- break;
- }
- if (cfg_filter_node(cfg, &chead[0], buf, section))
- numfound++;
-
- if (numfound == setnum)
- break;
-
- relnum++;
- }
- if (numfound == setnum)
- break;
- }
-
- /* Fail to find anything? */
- if (cfp >= &cfg->cf[2]) {
- errno = ESRCH;
- cfg_perror_str = dgettext("cfg", strerror(errno));
- cfg_severity = CFG_ENONFATAL;
- return (-1);
- }
-
- if (buf) {
- if (!itemp) {
- strncpy(value, buf, value_len);
- return (0);
- }
-
- if (itemp) {
- needed = cfg_get_item(&chead[0], section, itemp);
- p = strtok(buf, " ");
- while (p) {
- if (needed == pos) {
- errno = 0;
- if (*p == '-') {
- strcpy(value, "");
- return (0);
- } else {
- if (strlen(p) > value_len) {
- errno = E2BIG;
- cfg_perror_str =
- dgettext("cfg",
- strerror(errno));
- cfg_severity =
- CFG_ENONFATAL;
- return (-1);
- }
- }
- strncpy(value, p, value_len);
-
- return (pos);
- }
- p = strtok(NULL, " ");
- if (!p)
- break;
- pos++;
- }
- }
- }
- errno = ESRCH;
- cfg_perror_str = dgettext("cfg", strerror(errno));
- cfg_severity = CFG_ENONFATAL;
- 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
- * ie. if /dev/vx/rdsk/vol10 is found in sndr.set9, 9 will be returned
- * that is, of course, if the correct field was searched on.
- * -1 on error
- *
- */
-int
-cfg_find_cstring(CFGFILE *cfg, const char *target,
- const char *section, int numflds, ...)
-{
-
- char **list = NULL;
- va_list ap;
- char buf[CFG_MAX_BUF];
- char *field, *p;
- char **fldbuf = NULL;
- int i, j, rc;
- int pos = 1;
- int fieldnum;
- int nflds;
- int tbl_off;
-
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- return (-1);
- }
-
- if (numflds == 0) {
- nflds = cfg_get_num_flds(&chead[0], section, &tbl_off);
-
- } else {
- nflds = numflds;
- }
- if ((fldbuf = calloc(nflds, CFG_MAX_KEY)) == NULL) {
- cfg_perror_str = dgettext("cfg", strerror(errno));
- cfg_severity = CFG_EFATAL;
- return (-1);
- }
-
- if (numflds == 0) { /* search the whole string */
- if ((rc = cfg_get_section(cfg, &list, section)) <= 0) {
- for (i = 0; i < nflds; i++)
- free(fldbuf[i]);
- free(fldbuf);
- return (rc);
- }
- for (i = 0; i < rc; i++) {
- bzero(buf, sizeof (buf));
- strcpy(buf, list[i]);
- p = strtok(buf, " ");
- while (p) {
- if (strcmp(p, target) == 0) { /* we found it! */
- for (j = 0; j < rc; j++)
- free(list[j]);
- free(list);
- for (j = 0; j < nflds; j++)
- free(fldbuf[j]);
- free(fldbuf);
- return (i + 1);
- }
- p = strtok(NULL, " ");
- }
- }
- for (i = 0; i < nflds; i++)
- free(fldbuf[j]);
- for (i = 0; i < rc; i++)
- free(list[i]);
- free(fldbuf);
- free(list);
- return (0);
- }
-
- if ((rc = cfg_get_section(cfg, &list, section)) <= 0) {
- for (i = 0; i < nflds; i++)
- free(fldbuf[i]);
- free(fldbuf);
- return (rc);
- }
-
- va_start(ap, numflds);
- for (i = 0; i < numflds; i++) {
- fldbuf[i] = strdup(va_arg(ap, char *));
- }
-
- fldbuf[i] = NULL;
-
- for (j = 0; j < numflds; j++) {
- fieldnum = cfg_get_item(&chead[0], section, fldbuf[j]);
- for (i = 0; i < rc; i++) {
- bzero(buf, sizeof (buf));
- strcpy(buf, list[i]);
-
- field = strtok(buf, " ");
- pos = 1;
- while (pos < fieldnum) {
- field = strtok(NULL, " ");
- pos++;
- }
- if (field == NULL) {
- for (j = 0; j < numflds; j++)
- free(fldbuf[j]);
- for (j = 0; j < rc; j++)
- free(list[j]);
- free(fldbuf);
- free(list);
- return (-1);
- }
-
- if (strcmp(field, target) == 0) {
- for (j = 0; j < numflds; j++)
- free(fldbuf[j]);
- for (j = 0; j < rc; j++)
- free(list[j]);
- free(fldbuf);
- free(list);
-
- return (i + 1);
- }
-
- }
-
- }
- for (i = 0; i < nflds; i++)
- free(fldbuf[i]);
- for (i = 0; i < rc; i++)
- free(list[i]);
- free(fldbuf);
- free(list);
- 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
-cfg_put_cstring(CFGFILE *cfg, const char *key, void *value, int val_len)
-{
- cfp_t *cfp;
- char buf[CFG_MAX_BUF];
- char newbuf[CFG_MAX_BUF];
- char *bufp;
- char tmpkey[CFG_MAX_KEY];
- char *section;
- char *setp;
- char *itemp;
- int nofield = 0;
- int noset = 0;
- int fldnum;
- int setnum = 0;
- int relnum;
- int secnum;
- int numfound;
- int addcnode = 1;
- int table_index;
- int table_offset;
-
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- return (-1);
- }
-
- bzero(buf, sizeof (buf));
- strcpy(tmpkey, key);
- section = strtok(tmpkey, ".");
- setp = strtok(NULL, ".");
- itemp = strtok(NULL, ".");
-
- if (!cfg_wrlock(cfg)) {
- cfg_perror_str = dgettext("cfg", CFG_RDFAILED);
- cfg_severity = CFG_EFATAL;
- return (-1);
- }
-
- if (!key) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_ENONFATAL;
- return (-1);
- }
- if (value && val_len == 0) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_ENONFATAL;
- return (-1);
- }
- if (!itemp)
- nofield++;
- if (!setp)
- noset++;
- else if (setp) {
- setnum = atoi(setp + 3);
- if (setnum < 1 || setnum > 0x7ffd) {
- errno = EINVAL;
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_ENONFATAL;
- return (-1);
- }
- }
-
- table_offset = cfg_get_parser_offset(section);
-
- /*
- * we have to figure out where this set is
- * in relation to other sets
- */
- relnum = 1;
- secnum = 0;
- numfound = 0;
-
- if (setp && nofield) {
- char tmpbuf[CFG_MAX_BUF];
- int rc;
- int nflds;
- int got;
-
- /*
- * Set specified but no field
- */
- for (cfp = &cfg->cf[0]; cfp <= &cfg->cf[1]; cfp++) {
- if (!cfp->cf_fd) continue;
- if (cfp->cf_head->h_state & CFG_HDR_INVALID) {
- if (!cfg_read(cfp)) {
- cfg_perror_str =
- dgettext("cfg", CFG_RDFAILED);
- cfg_severity = CFG_EFATAL;
- return (-1);
- }
- }
- while (numfound < setnum) {
- if ((*cfp->cf_pp->readcf)
- (cfp, tmpbuf, table_offset, relnum - secnum)
- == NULL) {
- secnum = relnum - 1;
- break;
- }
- if (cfg_filter_node(cfg, &chead[0], tmpbuf,
- section))
- numfound++;
-
- if (numfound == setnum)
- break;
-
- relnum++;
- }
- if (numfound == setnum)
- break;
- }
-
- /* Fail to find anything? */
- if (cfp >= &cfg->cf[2]) {
- errno = ESRCH;
- cfg_perror_str = dgettext("cfg", strerror(errno));
- cfg_severity = CFG_ENONFATAL;
- return (-1);
- }
-
- nflds = cfg_get_num_flds(&chead[0], section, &table_index);
-
- if (value == NULL) {
- /* Remove entry completely */
-
- rc = (*cfp->cf_pp->remcf)(cfp, table_index,
- relnum - secnum);
- if (rc < 0)
- return (rc);
- return (0);
- }
-
- got = cfg_cnt_flds(value);
- bzero(buf, sizeof (buf));
-
- strncpy(buf, " ", 1);
- if (strlen(value) > sizeof (buf) - 2) {
- errno = E2BIG;
- cfg_perror_str = dgettext("cfg", strerror(errno));
- cfg_severity = CFG_ENONFATAL;
- return (-1);
- }
- strncat(buf, value, val_len);
- if (got < nflds) {
- for (/* CSTYLED */; got < nflds; got++)
- strncat(buf, " - ", 3);
- } else if (got > nflds) {
- return (-1);
- } else {
- /* got == nflds, so cnode was included */
- addcnode = 0;
- }
-
- bufp = buf;
- if (addcnode) {
- cfg_insert_node(cfg, &chead[0], buf, section);
- }
-
- (*cfp->cf_pp->replacecf)(cfp, bufp, table_index,
- relnum - secnum);
-
- 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
- */
- if (setp && itemp) {
- int rc;
- int nflds;
- int cnodepos;
-
- for (cfp = &cfg->cf[0]; cfp <= &cfg->cf[1]; cfp++) {
- if (!cfp->cf_fd) continue;
- if (cfp->cf_head->h_state & CFG_HDR_INVALID) {
- if (!cfg_read(cfp)) {
- cfg_perror_str =
- dgettext("cfg", CFG_RDFAILED);
- cfg_severity = CFG_EFATAL;
- return (-1);
- }
- }
- while (numfound < setnum) {
- if ((*cfp->cf_pp->readcf)
- (cfp, buf, table_offset, relnum - secnum)
- == NULL) {
- secnum = relnum - 1;
- break;
- }
- if (cfg_filter_node(cfg, &chead[0], buf,
- section))
- numfound++;
-
- if (numfound == setnum)
- break;
-
- relnum++;
- }
- if (numfound == setnum)
- break;
- }
-
- /* Fail to find anything? */
- if (cfp >= &cfg->cf[2]) {
- errno = ESRCH;
- cfg_perror_str = dgettext("cfg", strerror(errno));
- cfg_severity = CFG_ENONFATAL;
- return (-1);
- }
-
- nflds = cfg_get_num_flds(&chead[0], section, &table_index);
- fldnum = cfg_get_item(&chead[0], section, itemp);
- bzero(newbuf, sizeof (newbuf));
- strncpy(newbuf, " ", 1);
-
- /* move good flds in */
- rc = cfg_fld_mov(newbuf, buf, 1, fldnum - 1);
- if (rc < 0)
- return (rc);
-
- /* move new fld in */
- strncat(newbuf, value, strlen(value));
- strcat(newbuf, " ");
-
- /* move remaining flds in */
- rc = cfg_fld_mov(newbuf, buf, fldnum + 1, nflds);
- if (rc < 0)
- return (rc);
-
- cnodepos = cfg_get_item(&chead[0], section, "cnode");
- if ((cnodepos >= 0) && strcmp(itemp, "cnode") != 0) {
- /* add cnode if user didn't specify it */
- cfg_insert_node(cfg, &chead[0],
- newbuf, section);
- }
-
- (*cfp->cf_pp->replacecf)(cfp, newbuf, table_index,
- relnum - secnum);
-
- return (TRUE);
- }
-
- if (noset) { /* blast entire thing in */
- int nflds;
- int got;
- int cnodepos;
-
- bufp = buf;
- if (!value) { /* we shouldn't be here */
- errno = EINVAL;
- return (-1);
- }
- strncat(buf, " ", 1);
- if (strlen(value) > sizeof (buf) - 2) {
- errno = E2BIG;
- return (-1);
- }
-
- strncat(buf, value, val_len);
- nflds = cfg_get_num_flds(&chead[0], section, &table_index);
- got = cfg_cnt_flds(value);
-
- cnodepos = cfg_get_item(&chead[0], section, "cnode");
- if (cnodepos < 0 || got >= cnodepos) {
- /* no cnode, or cnode was specified by caller */
- addcnode = 0;
- }
-
- if (got < nflds) {
- for (/* CSTYLED */; got < nflds; got++)
- strncat(buf, " - ", 3);
- } else if (got > nflds) {
- errno = EINVAL; /* specified too many fields */
- return (-1);
- } else {
- /* got == nflds, so cnode was included */
- addcnode = 0;
- }
-
- if (addcnode) {
- cfg_insert_node(cfg, &chead[0], buf, section);
- }
-
- /* Make sure we put this entry in the right database */
- if (cfg_is_cnode(cfg, &chead[0], buf, section) &&
- cfg->cf[1].cf_fd)
- cfp = &cfg->cf[1];
- else
- cfp = &cfg->cf[0];
-
- if (cfp->cf_head->h_state & CFG_HDR_INVALID) {
- if (!cfg_read(cfp)) {
- cfg_perror_str = dgettext("cfg", CFG_RDFAILED);
- cfg_severity = CFG_EFATAL;
- return (-1);
- }
- }
- if (cfp->cf_head->h_csize + strlen(buf) > CFG_DEFAULT_SSIZE) {
- errno = ENOSPC;
- return (-1);
- }
-
- (*cfp->cf_pp->addcf)(cfp, bufp, table_index);
-
- return (TRUE);
- }
-
- errno = EINVAL;
- cfg_perror_str = strerror(errno);
- cfg_severity = CFG_ENONFATAL;
- return (-1);
-}
-
-/*
- * cfg_encode_char
- *
- * Encode a single character into % + hex ascii value
- */
-static void
-cfg_encode_char(char *result, char ch)
-{
- *result++ = '%';
- *result++ = dectohex[ (ch >> 4) & 0xf ];
- *result++ = dectohex[ ch & 0xf ];
-}
-
-/*
- * cfg_decode_char
- *
- * Reverses cfg_encode_char
- */
-static char
-cfg_decode_char(char *code)
-{
- char retval;
- if (*code != '%') {
- return ('\0');
- }
- ++code;
- if (!isxdigit(*code))
- return ('\0');
- retval = (isdigit(*code)? *code - '0' : *code - 'a' + 10);
- retval <<= 4;
- ++code;
- if (!isxdigit(*code))
- return ('\0');
- retval |= (isdigit(*code)? *code - '0' : *code - 'a' + 10);
-
- 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
-cfg_encode_string(char *str, char *output, int outlen)
-{
- char *mem, *p, *q;
- int curlen;
-
-
- /* first, scan through the tag string converting %-signs */
- p = str;
- q = output;
- curlen = 0;
- while (*p && curlen < outlen) {
- if (*p == '%') {
- if (curlen + 3 >= outlen) {
- return (-1);
- }
- cfg_encode_char(q, *p);
- curlen += 3;
- q += 3;
- } else {
- *q++ = *p;
- ++curlen;
- }
- ++p;
- }
- if (curlen < outlen)
- *q = '\0';
-
- /* now encode special characters */
- p = mem = strdup(output);
- q = output;
- curlen = 0;
- while (*p && curlen < outlen) {
- if (strchr(CHARS_TO_ENCODE, *p) != 0) {
- if (curlen + 3 >= outlen) {
- free(mem);
- return (-1);
- }
- cfg_encode_char(q, *p);
- curlen += 3;
- q += 3;
- } else {
- *q++ = *p;
- ++curlen;
- }
- ++p;
- }
- free(mem);
-
- if (curlen < outlen)
- *q = '\0';
- /* LINTED possible ptrdiff_t overflow */
- return (q - output);
-}
-
-/*
- * cfg_decode_option
- *
- * Given a string, decodes any %-encodes on it.
- */
-static void
-cfg_decode_string(char *str, char *output, int outlen)
-{
- char *p, *q;
- int curlen;
-
- p = str;
- q = output;
- curlen = 0;
- while (*p && curlen < outlen) {
- if (*p == '%') {
- char ch = cfg_decode_char(p);
- if (!ch) {
- *q++ = *p++;
- ++curlen;
- } else {
- *q++ = ch;
- p += 3;
- ++curlen;
- }
- } else {
- *q++ = *p++;
- ++curlen;
- }
- }
- if (curlen < outlen)
- *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
-cfg_get_options(CFGFILE *cfg, int section, const char *basekey, char *tag,
- int tag_len, char *val, int val_len)
-{
- static char buf[CFG_MAX_BUF];
- char decode_buf[CFG_MAX_BUF];
- int rc;
- char *ttag, *tval;
-
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- return (-1);
- }
-
- errno = ENOSYS;
- if (basekey == 0) {
- ttag = strtok(NULL, "=");
- } else {
- bzero(buf, CFG_MAX_BUF);
- if (section == CFG_SEC_CONF) {
- rc = cfg_get_cstring(cfg, basekey, buf, CFG_MAX_BUF);
- } else
- return (-1);
- if (rc < 0)
- return (rc);
- /* buf now contains raw options data */
- ttag = strtok(buf, "=");
- }
- tval = strtok(NULL, ";");
- if (!(tval) || !(ttag))
- return (-1);
- if ((strlen(tval) > val_len) || (strlen(ttag) > tag_len)) {
- errno = E2BIG;
- return (-1);
- }
- cfg_decode_string(tval, decode_buf, CFG_MAX_BUF);
- strncpy(val, decode_buf, val_len);
- cfg_decode_string(ttag, decode_buf, CFG_MAX_BUF);
- strncpy(tag, decode_buf, tag_len);
- 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
-cfg_put_options(CFGFILE *cfg, int section, const char *basekey, char *tag,
- char *val)
-{
- char buf[CFG_MAX_BUF];
- char encode_buf[CFG_MAX_BUF];
- char *p;
- int enclen;
-
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- return (-1);
- }
-
- errno = ENOSYS;
- bzero(buf, CFG_MAX_BUF);
- if (section != CFG_SEC_CONF) {
- cfg_severity = CFG_ENONFATAL;
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- return (-1);
- }
- if (!tag || !*tag || !val || !*val)
- return (-1);
- if (cfg_get_cstring(cfg, basekey, buf, CFG_MAX_BUF) < 0) {
- /* cfg severity & perror_str set up cfg_get_cstring() */
- return (-1);
- }
- *encode_buf = ';';
- enclen = cfg_encode_string(tag, &encode_buf[1], CFG_MAX_BUF - 1) + 1;
- if (enclen < 1 || (enclen + 1) >= CFG_MAX_BUF) {
- cfg_severity = CFG_ENONFATAL;
- cfg_perror_str = dgettext("cfg", "Buffer too small");
- return (-1);
- }
- encode_buf[enclen] = '=';
- encode_buf[enclen + 1] = '\0';
-
- /* check the start of the string */
- if (strncmp(buf, &encode_buf[1], enclen) == 0) {
- /* locate the end of this option */
- p = strchr(buf, ';');
- if (p && *(p + 1) != '\0') {
- /* add the new tag to the end */
- ++p;
- strcat(p, &encode_buf[1]);
- } else {
- /* completely overwrite the existing tag */
- p = buf;
- strcpy(p, &encode_buf[1]);
- }
- if (cfg_encode_string(val, encode_buf, CFG_MAX_BUF) < 0) {
- cfg_severity = CFG_ENONFATAL;
- cfg_perror_str = dgettext("cfg", "Buffer too small");
- return (-1);
- }
- strcat(p, encode_buf);
- strcat(p, ";");
- if (cfg_put_cstring(cfg, basekey, p, strlen(p)) < 0) {
- /* severity & perror_str set by cfg_put_cstring */
- return (-1);
- }
- errno = 0;
- return (TRUE);
- }
-
- /* it's hiding somewhere inside... */
- p = strstr(buf, encode_buf);
- if (p) {
- /* delete the old value */
- char *q = strchr(p + 1, ';');
- if (q) {
- strcpy(p + 1, q + 1);
- } else {
- *p = '\0';
- }
- strcat(buf, &encode_buf[1]);
- } else if (*buf) {
- strcat(buf, &encode_buf[1]);
- } else {
- strcpy(buf, &encode_buf[1]);
- }
- enclen = cfg_encode_string(val, encode_buf, CFG_MAX_BUF);
- if (enclen < 0 || (strlen(buf) + enclen) >= CFG_MAX_BUF) {
- cfg_severity = CFG_ENONFATAL;
- cfg_perror_str = dgettext("cfg", "Buffer too small");
- return (-1);
- }
- strcat(buf, encode_buf);
- strcat(buf, ";");
- if (cfg_put_cstring(cfg, basekey, buf, CFG_MAX_BUF) < 0) {
- /* 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
-cfg_get_single_option(CFGFILE *cfg, int section, const char *basekey, char *tag,
- char *val, int val_len)
-{
- char buf[CFG_MAX_BUF];
- char encode_buf[CFG_MAX_BUF];
- char *p, *q;
- int enclen;
-
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- return (-1);
- }
-
- errno = ENOSYS;
- bzero(buf, CFG_MAX_BUF);
- if (section != CFG_SEC_CONF) {
- cfg_severity = CFG_ENONFATAL;
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- return (-1);
- }
- if (cfg_get_cstring(cfg, basekey, buf, CFG_MAX_BUF) < 0) {
- /* severity & perror_str set by cfg_get_cstring */
- return (-1);
- }
-
- *encode_buf = ';';
- enclen = cfg_encode_string(tag, &encode_buf[1], CFG_MAX_BUF - 1) + 1;
- if (enclen < 1 || (enclen + 1) >= CFG_MAX_BUF) {
- cfg_severity = CFG_ENONFATAL;
- cfg_perror_str = dgettext("cfg", "Buffer too small");
- return (-1);
- }
- encode_buf[enclen] = '=';
- encode_buf[enclen + 1] = '\0';
-
- /* check the start of the string */
- if (strncmp(buf, &encode_buf[1], enclen) == 0) {
- p = strchr(buf, '=');
- if (!p) {
- cfg_severity = CFG_ENONFATAL;
- cfg_perror_str = dgettext("cfg", "Option not found");
- return (-1);
- }
- ++p;
- q = strchr(p, ';');
- if (q) {
- *q = '\0';
- }
- cfg_decode_string(p, val, val_len);
- errno = 0;
- return (TRUE);
- }
-
- /* it's hiding somewhere inside... */
- p = strstr(buf, encode_buf);
- if (p) {
- p += enclen + 1;
- q = strchr(p, ';');
- if (q) {
- *q = '\0';
- }
- cfg_decode_string(p, val, val_len);
- 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
-cfg_del_option(CFGFILE *cfg, int section, const char *basekey, char *tag)
-{
- char buf[CFG_MAX_BUF];
- char encode_buf[CFG_MAX_BUF];
- char *p, *q;
- int enclen, rc;
-
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- return (-1);
- }
-
- bzero(buf, CFG_MAX_BUF);
- if (section != CFG_SEC_CONF) {
- cfg_severity = CFG_ENONFATAL;
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- return (-1);
- }
- if (cfg_get_cstring(cfg, basekey, buf, CFG_MAX_BUF) < 0) {
- /* severity & perror_str are set by cfg_get_cstring */
- return (-1);
- }
-
- *encode_buf = ';';
- enclen = cfg_encode_string(tag, &encode_buf[1], CFG_MAX_BUF - 1) + 1;
- if (enclen < 1 || (enclen + 1) >= CFG_MAX_BUF) {
- cfg_severity = CFG_ENONFATAL;
- cfg_perror_str = dgettext("cfg", "Buffer too small");
- return (-1);
- }
- encode_buf[enclen] = '=';
- encode_buf[enclen + 1] = '\0';
-
- /* check the start of the string */
- if (strncmp(buf, &encode_buf[1], enclen) == 0) {
- p = strchr(buf, ';');
- if (p && (*(p + 1) != '\0')) {
- rc = cfg_put_cstring(cfg, basekey, p + 1,
- strlen(p + 1));
- } else {
- rc = cfg_put_cstring(cfg, basekey, "-", 1);
- }
- /* severity & perror_str are set by cfg_put_cstring */
- return (rc);
- }
-
- /* sigh */
- p = strstr(buf, encode_buf);
- if (!p) {
- /* already removed */
- return (TRUE);
- }
- q = strchr(p + 1, ';');
-
- /*
- * Now the string looks like:
- * | first few options | *p | option to remove | *q | rest | '\0'
- */
-
- if (!q) {
- /* hum... */
- *p = '\0';
- } else {
- strcpy(p, q);
- }
-
- return (cfg_put_cstring(cfg, basekey, buf, strlen(buf)));
-}
-
-static void
-cfg_set_memorymap(cfp_t *cfp)
-{
- cfgheader_t *hd = cfp->cf_head;
-
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr, "callocing %d for initial reads\n", hd->h_csize);
-#endif
-
- hd->h_ccopy1 = (char *)calloc(hd->h_csize, sizeof (char));
- hd->h_ccopy2 = (char *)calloc(hd->h_csize, sizeof (char));
- hd->h_sizes1 = (int *)calloc(CFG_DEFAULT_PSIZE, sizeof (int));
- hd->h_sizes2 = (int *)calloc(CFG_DEFAULT_PSIZE, sizeof (int));
-}
-
-/*
- * cfg_init_header
- * fill in default header info
- */
-static void
-cfg_init_header(cfp_t *cfp)
-{
- time_t tloc;
- cfgheader_t *hd = cfp->cf_head;
-
- hd->h_magic = (int32_t)CFG_NEW_MAGIC;
- hd->h_stamp = time(&tloc);
- hd->h_lock = 0;
- /* parser config */
- hd->h_parsesize = 0;
- hd->h_parseoff = 0;
- hd->h_csize = 0;
- hd->h_psize = 0;
- hd->h_cfgs = NULL;
- hd->h_ncfgs = 0;
- hd->h_seq1 = hd->h_seq2 = 1;
- bzero(hd->h_cfgsizes, MAX_CFG * sizeof (int));
-}
-/*
- * 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
-cfg_read(cfp_t *cfp)
-{
- int rc;
- cfgheader_t *hd;
- int readsize = 0;
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr, "cfg_read\n");
-#endif
-
- if (!cfp->cf_head) {
- if ((hd = calloc(1, sizeof (*hd))) == NULL)
- return (FALSE);
-#ifdef DEBUG_HDR
- (void) fprintf(stderr, "initial cfg header read\n");
-#endif
- cfp->cf_head = hd;
- }
-
- if ((*cfp->cf_pp->seek)(cfp, 0, SEEK_SET) < 0) {
-#ifdef DEBUG_LIB
- (void) fprintf(stderr, "cfg: seek header failed\n");
-#endif
- return (FALSE);
- }
-
- rc = (*cfp->cf_pp->read)(cfp, (char *)cfp->cf_head, 4);
- if (rc < 4) {
-#ifdef DEBUG_LIB
- (void) fprintf(stderr, "cfg: read magic number failed\n");
-#endif
- return (FALSE);
- }
-
- if ((*cfp->cf_pp->seek)(cfp, 0, SEEK_SET) < 0) {
-#ifdef DEBUG_LIB
- (void) fprintf(stderr, "cfg: seek header failed\n");
-#endif
- return (FALSE);
- }
-
- rc = (*cfp->cf_pp->read)(cfp, (char *)cfp->cf_head, sizeof (*hd));
- if (rc < sizeof (*hd)) {
-#ifdef DEBUG_LIB
- (void) fprintf(stderr, "cfg: read header failed\n");
-#endif
- return (FALSE);
- }
-
- cfp->cf_head->h_cfgs = NULL;
- cfg_set_memorymap(cfp);
- if (cfp->cf_head->h_magic != CFG_NEW_MAGIC) {
-#ifdef DEBUG_LIB
- (void) fprintf(stderr, "cfg_read: wrong MAGIC number %x\n",
- cfp->cf_head->h_magic);
-#endif
- return (FALSE);
- }
-
- cfp->cf_head->h_state &= ~(CFG_HDR_INVALID);
-
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr, "reading parser\n");
-#endif
- rc = (*cfp->cf_pp->read)(cfp, (char *)cfp->cf_mapped,
- CFG_DEFAULT_PARSE_SIZE);
- if (rc < sizeof (*hd)) {
-#ifdef DEBUG
- (void) fprintf(stderr, "cfg: read parse config failed\n");
-#endif
- return (FALSE);
- }
-
- readsize = cfp->cf_head->h_csize;
-
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr, "reading copy1 readsize = %d\n", readsize);
-#endif
- rc = (*cfp->cf_pp->read)(cfp, (char *)cfp->cf_head->h_ccopy1,
- readsize);
- if (rc < 0) {
- /* don't fail just return */
-#ifdef DEBUG
- (void) fprintf(stderr, "cfg: read ccopy1 section failed\n");
-#endif
- return (FALSE);
- }
-
- if ((*cfp->cf_pp->seek)
- (cfp, CFG_DEFAULT_SSIZE - rc, SEEK_CUR) < 0) {
-#ifdef DEBUG
- (void) fprintf(stderr, "cfg: seek (SEEK_CUR) failed\n");
-#endif
- return (FALSE);
- }
-
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr, "reading copy2 readsize = %d\n", readsize);
-#endif
-
- rc = (*cfp->cf_pp->read)(cfp, (char *)cfp->cf_head->h_ccopy2,
- readsize);
- if (rc < 0) {
- /* don't fail just return */
-#ifdef DEBUG
- (void) fprintf(stderr, "cfg: read ccopy2 section failed\n");
-#endif
- return (FALSE);
- }
-
- /* read the sizes of the lists from disk */
- if ((*cfp->cf_pp->seek)
- (cfp, CFG_DEFAULT_SSIZE - rc, SEEK_CUR) < 0) {
-#ifdef DEBUG
- (void) fprintf(stderr, "cfg: seek (SEEK_CUR) failed\n");
-#endif
- return (FALSE);
- }
-
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr, "reading sizes\n");
-#endif
- rc = (*cfp->cf_pp->read)(cfp, (int *)cfp->cf_head->h_sizes1,
- CFG_DEFAULT_PSIZE);
- if (rc < 0) {
-#ifdef DEBUG
- (void) fprintf(stderr, "cfg: read h_sizes1 failed\n");
-#endif
- return (FALSE);
- }
-
- rc = (*cfp->cf_pp->read)(cfp, (int *)cfp->cf_head->h_sizes2,
- CFG_DEFAULT_PSIZE);
- if (rc < 0) {
-#ifdef DEBUG
- (void) fprintf(stderr, "cfg: read h_sizes2 failed\n");
-#endif
- return (FALSE);
- }
-
- /*
- * If initial or invalid sequence, use first section
- */
- if ((cfp->cf_head->h_seq1 <= 0) && (cfp->cf_head->h_seq2 <= 0)) {
- cfp->cf_head->h_cparse = cfp->cf_head->h_ccopy1;
- cfp->cf_head->h_sizes = cfp->cf_head->h_sizes1;
- }
-
- if (cfp->cf_head->h_seq1 >= cfp->cf_head->h_seq2) {
- cfp->cf_head->h_cparse = cfp->cf_head->h_ccopy1;
- cfp->cf_head->h_sizes = cfp->cf_head->h_sizes1;
- } else {
- cfp->cf_head->h_cparse = cfp->cf_head->h_ccopy2;
- cfp->cf_head->h_sizes = cfp->cf_head->h_sizes2;
- }
-
-#ifdef DEBUG_LIB
- dump_status(cfp, "cfg_read");
-#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
-cfg_lock(CFGFILE *cfg, CFGLOCK mode)
-{
- cfp_t *cfp;
- int is_locked = 0;
- int rc;
-
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- return (FALSE);
- }
-
- if (mode == CFG_UPGRADE) {
- mode = CFG_WRLOCK;
- }
-
- if (mode == CFG_WRLOCK && (cfg->cf[0].cf_flag & CFG_RDONLY)) {
- goto fail;
- }
-
- /*
- * if you don't even give me the right lock request,
- * why should I give you one?
- */
- if (mode != CFG_RDLOCK && mode != CFG_WRLOCK)
- goto fail;
-
- if (cfg_lockd) {
- if (mode == CFG_WRLOCK)
- cfg_lockd_wrlock();
- else
- cfg_lockd_rdlock();
- is_locked = 1;
- } else {
-
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr, "cfg_lock\n");
-#endif
- /* Lock is always based on local file pointer */
- cfg->cf[1].cf_lock = cfg->cf[0].cf_lock = cfg->cf[0].cf_fd;
-
- if (!((cfg->cf[0].cf_flag & CFG_RDONLY) &&
- (mode == CFG_RDLOCK))) {
-
- struct flock lk = {0};
- lk.l_type = (mode == CFG_RDLOCK ? F_RDLCK : F_WRLCK);
- lk.l_whence = SEEK_SET;
- lk.l_start = (off_t)0;
- lk.l_len = (off_t)0;
-
- if (fcntl(cfg->cf[0].cf_lock, F_SETLKW, &lk) < 0)
- goto fail;
- }
- }
-
- /* Determine number of files open */
- for (cfp = &cfg->cf[0]; cfp <= &cfg->cf[1]; cfp++) {
- if (!cfp->cf_fd) continue;
- if ((cfp->cf_head) &&
- (cfp->cf_head->h_state & CFG_HDR_INVALID)) {
- if ((rc = cfg_hdrcmp(cfp)) == 0) {
-#ifdef DEBUG_HDR
- (void) fprintf(stderr,
- "cfg header match, skipping re-read\n");
-#endif
- cfp->cf_head->h_state |= CFG_HDR_RDLOCK;
- if (mode == CFG_WRLOCK)
- cfp->cf_head->h_state |= CFG_HDR_WRLOCK;
-
- cfp->cf_head->h_state &= ~(CFG_HDR_INVALID);
- continue;
- }
-#ifdef DEBUG_HDR
- (void) fprintf(stderr, "re-reading cfg, header mismatch\n");
-#endif
- /*
- * dump what we have, info is stale
- */
- cfg_free_cfglist(cfp);
- cfg_free_parser_tree();
-
- if (cfp->cf_head->h_ccopy1) {
- free(cfp->cf_head->h_ccopy1);
- cfp->cf_head->h_ccopy1 = NULL;
- }
- if (cfp->cf_head->h_ccopy2) {
- free(cfp->cf_head->h_ccopy2);
- cfp->cf_head->h_ccopy2 = NULL;
- }
- if (cfp->cf_head->h_sizes1) {
- free(cfp->cf_head->h_sizes1);
- cfp->cf_head->h_sizes1 = NULL;
- }
- if (cfp->cf_head->h_sizes2) {
- free(cfp->cf_head->h_sizes2);
- cfp->cf_head->h_sizes2 = NULL;
- }
-
- if (cfp->cf_head)
- free(cfp->cf_head);
- cfp->cf_head = NULL;
- }
-
- if (cfp->cf_head == NULL) {
- if (!cfg_read(cfp)) {
- if (cfp->cf_head != NULL)
- cfg_init_header(cfp);
- else
- goto fail;
- } else {
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr,
- "reading parser config\n");
-#endif
- /* build parser trees */
- cfg_read_parser_config(cfp);
- }
-
- }
- cfp->cf_head->h_state |= CFG_HDR_RDLOCK;
- if (mode == CFG_WRLOCK) {
- if (cfp->cf_head->h_seq1 >= cfp->cf_head->h_seq2) {
-#ifdef DEBUG_LIB
- (void) fprintf(stderr,
- "cfg_lock: WRLOCK copying 1 to 2\n");
-#endif
- memcpy(cfp->cf_head->h_ccopy2,
- cfp->cf_head->h_ccopy1,
- cfp->cf_head->h_csize);
- memcpy(cfp->cf_head->h_sizes2,
- cfp->cf_head->h_sizes1,
- CFG_DEFAULT_PSIZE);
-
- cfp->cf_head->h_cparse = cfp->cf_head->h_ccopy2;
- cfp->cf_head->h_sizes = cfp->cf_head->h_sizes2;
- } else {
-#ifdef DEBUG_LIB
- (void) fprintf(stderr,
- "cfg_lock: WRLOCK copying 2 to 1\n");
-#endif
- memcpy(cfp->cf_head->h_ccopy1,
- cfp->cf_head->h_ccopy2,
- cfp->cf_head->h_csize);
- memcpy(cfp->cf_head->h_sizes1,
- cfp->cf_head->h_sizes2,
- CFG_DEFAULT_PSIZE);
-
- cfp->cf_head->h_cparse = cfp->cf_head->h_ccopy1;
- cfp->cf_head->h_sizes = cfp->cf_head->h_sizes1;
- }
-
- cfp->cf_head->h_state |= CFG_HDR_WRLOCK;
- }
-
- if (cfg_map_cfglists(cfp) < 0) {
-#ifdef DEBUG_LIB
- (void) fprintf(stderr, "cfg: map_cfglists failed\n");
-#endif
- goto fail;
- }
-
-#ifdef DEBUG_LIB
- dump_status(cfp, "cfg_lock");
-#endif
- }
-
- return (TRUE);
-
-fail:
- if (is_locked) {
- cfg_lockd_unlock();
- }
- cfg_perror_str = dgettext("cfg", CFG_EGENERIC);
- cfg_severity = CFG_ENONFATAL;
- return (FALSE);
-}
-
-/*
- * Unlock the database
- */
-void
-cfp_unlock(cfp_t *cfp)
-{
-
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr, "cfg_unlock\n");
-#endif
- if (cfg_lockd) {
- cfg_lockd_unlock();
- } else {
- struct flock lk = {0};
- lk.l_type = F_UNLCK;
- lk.l_whence = SEEK_SET;
- lk.l_start = (off_t)0;
- lk.l_len = (off_t)0;
- (void) fcntl(cfp->cf_lock, F_SETLKW, &lk);
- }
-
- if (cfp->cf_head != NULL) {
- cfp->cf_head->h_state &= ~(CFG_HDR_RDLOCK|CFG_HDR_WRLOCK);
- cfp->cf_head->h_state |= CFG_HDR_INVALID;
- }
-}
-void
-cfg_unlock(CFGFILE *cfg)
-{
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- return;
- }
-
- cfp_unlock(&cfg->cf[0]);
- cfp_unlock(&cfg->cf[1]);
-}
-
-/*
- * Test for a read lock, set errno if failed.
- */
-static int
-cfg_rdlock(CFGFILE *cfg)
-{
- int rc;
- cfp_t *cfp;
-
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- return (FALSE);
- }
-
- /* Determine number of files open */
- for (cfp = &cfg->cf[0]; cfp <= &cfg->cf[1]; cfp++) {
- if (!cfp->cf_fd)
- continue;
- if (cfp->cf_head == NULL) {
-#ifdef DEBUG_LIB
- (void) fprintf(stderr, "cfg_rdlock: cf_head == NULL\n");
-#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.
- */
- rc = FALSE;
- break;
- } else {
-#ifdef DEBUG_LIB
- (void) fprintf(stderr, "cfg_rdlock: cf_head != NULL\n");
-#endif
- if ((cfp->cf_head->h_state & CFG_HDR_RDLOCK)
- == CFG_HDR_RDLOCK) {
- rc = TRUE;
- } else {
- rc = FALSE;
- break;
- }
- }
- }
-
- if (!rc)
- errno = EPERM;
-
- return (rc);
-}
-
-/*
- * Test for a write lock, set errno if failed.
- */
-static int
-cfg_wrlock(CFGFILE *cfg)
-{
- int rc;
- cfp_t *cfp;
-
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- return (FALSE);
- }
-
- /* Determine number of files open */
- for (cfp = &cfg->cf[0]; cfp <= &cfg->cf[1]; cfp++) {
- if (!cfp->cf_fd)
- continue;
- if (cfp->cf_head == NULL) {
-#ifdef DEBUG_LIB
- (void) fprintf(stderr, "cfg wrlock: cf_head == NULL\n");
-#endif
- /*
- * 6335583, see comments on cfg_rdlock
- */
- rc = FALSE;
- break;
- } else {
-#ifdef DEBUG_LIB
- (void) fprintf(stderr, "cfg wrlock: cf_head != NULL\n");
-#endif
- if ((cfp->cf_head->h_state & CFG_HDR_WRLOCK)
- == CFG_HDR_WRLOCK) {
- rc = TRUE;
- } else {
- rc = FALSE;
- break;
- }
- }
- }
-
- if (!rc)
- errno = EPERM;
-
- 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
-cfg_get_lock(CFGFILE *cfg, CFGLOCK *lock, pid_t *pid)
-{
- struct flock lk;
- int rc;
-
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- 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;
- *pid = getpid();
- return (TRUE);
- }
-
- if (cfg_rdlock(cfg)) {
- *lock = CFG_RDLOCK;
- *pid = getpid();
- return (TRUE);
- }
- }
- /* Lock is always based on local file pointer */
- cfg->cf[1].cf_lock = cfg->cf[0].cf_lock = cfg->cf[0].cf_fd;
-
- bzero(&lk, sizeof (lk));
- lk.l_type = F_WRLCK;
- lk.l_whence = SEEK_SET;
- lk.l_start = (off_t)0;
- lk.l_len = (off_t)0;
-
- if (fcntl(cfg->cf[0].cf_lock, F_GETLK, &lk) < 0)
- rc = FALSE;
- else {
- if (lk.l_type == F_UNLCK)
- rc = FALSE;
- else {
- rc = TRUE;
- *pid = lk.l_pid;
- *lock = lk.l_type == F_WRLCK ? CFG_WRLOCK : CFG_RDLOCK;
- }
- }
-
- 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
-cfg_commit(CFGFILE *cfg)
-{
- cfp_t *cfp;
- int rc;
- time_t tloc;
- int section;
- int wrsize, *ip;
-
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- return (FALSE);
- }
-
- if (!cfg_wrlock(cfg))
- return (FALSE);
-
- /* Determine number of files open */
- for (cfp = &cfg->cf[0]; cfp <= &cfg->cf[1]; cfp++) {
- if (!cfp->cf_fd)
- continue;
-
- /*
- * lets put everything back into one char *
- */
- cfg_replace_lists(cfp);
-
- if ((*cfp->cf_pp->seek)(cfp, 0, SEEK_SET) < 0) {
-#ifdef DEBUG_LIB
- (void) fprintf(stderr, "cfg: seek header failed\n");
-#endif
- return (FALSE);
- }
-
- cfp->cf_head->h_size = cfp->cf_head->h_parsesize
- + cfp->cf_head->h_csize + cfp->cf_head->h_psize;
- cfp->cf_head->h_stamp = time(&tloc);
-
- /* seeking into database */
- if ((*cfp->cf_pp->seek)(cfp, sizeof (cfgheader_t),
- SEEK_CUR) < 0)
- return (FALSE);
-
- if (cfp->cf_head->h_ccopy1 == cfp->cf_head->h_cparse) {
- if (cfp->cf_head->h_seq1 < 0)
- cfp->cf_head->h_seq1 = 1;
- else
- cfp->cf_head->h_seq1 = cfp->cf_head->h_seq2 + 1;
- section = 1;
- } else {
- if (cfp->cf_head->h_seq2 < 0)
- cfp->cf_head->h_seq2 = 1;
- else
- cfp->cf_head->h_seq2 = cfp->cf_head->h_seq1 + 1;
- section = 2;
- }
-#ifdef DEBUG_LIB
- dump_status(cfp, "cfg_commit");
-#endif
- rc = (*cfp->cf_pp->write)(cfp, cfp->cf_mapped,
- CFG_DEFAULT_PARSE_SIZE);
-#ifdef DEBUG
- if (rc < 0) {
- (void) fprintf(stderr,
- "parse commit: rc %d h_parsesize %d\n",
- rc, cfp->cf_head->h_parsesize);
- }
-#endif
- if (section == 1) {
- rc = (*cfp->cf_pp->write) (cfp, cfp->cf_head->h_ccopy1,
- cfp->cf_head->h_csize);
-#ifdef DEBUG
- if (rc < 0) {
- (void) fprintf(stderr,
- "csection commit 1: rc %d h_csize %d\n",
- rc, cfp->cf_head->h_csize);
- }
-#endif
- if ((*cfp->cf_pp->seek)
- (cfp, (2 * CFG_DEFAULT_SSIZE) - rc, SEEK_CUR) < 0)
- return (FALSE);
-
- /*
- * limit the write to only what we need
- */
- ip = cfp->cf_head->h_sizes1;
- for (wrsize = 0; *ip; ip += *ip + 1)
- wrsize += *ip + 1;
-
- rc = (*cfp->cf_pp->write)(cfp, cfp->cf_head->h_sizes1,
- wrsize * sizeof (int));
-#ifdef DEBUG
- if (rc < 0) {
- (void) fprintf(stderr,
- "cfg: write list sizes1 failed rc\n");
- }
-#endif
- } else {
- if ((*cfp->cf_pp->seek)(cfp, CFG_DEFAULT_SSIZE,
- SEEK_CUR) < 0)
- return (FALSE);
-
- rc = (*cfp->cf_pp->write)(cfp, cfp->cf_head->h_ccopy2,
- cfp->cf_head->h_csize);
-#ifdef DEBUG
- if (rc < 0) {
- (void) fprintf(stderr,
- "csection commit 2: rc %d h_csize %d\n",
- rc, cfp->cf_head->h_csize);
- }
-#endif
- if ((*cfp->cf_pp->seek)
- (cfp, (CFG_DEFAULT_SSIZE + CFG_DEFAULT_PSIZE) - rc,
- SEEK_CUR) < 0)
- return (FALSE);
-
- /*
- * limit the write to only what we need
- */
- ip = cfp->cf_head->h_sizes2;
- for (wrsize = 0; *ip; ip += *ip + 1)
- wrsize += *ip + 1;
-
- rc = (*cfp->cf_pp->write)(cfp, cfp->cf_head->h_sizes2,
- wrsize * sizeof (int));
-#ifdef DEBUG
- if (rc < 0) {
- (void) fprintf(stderr,
- "cfg: write list sizes2 failed\n");
- }
-#endif
-
- }
-
-
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr,
- "writing h_csize %d\n", cfp->cf_head->h_csize);
-#endif
- if ((*cfp->cf_pp->seek)(cfp, 0, SEEK_SET) < 0)
- return (FALSE);
-
- cfp->cf_head->h_size = cfp->cf_head->h_parsesize +
- cfp->cf_head->h_csize + cfp->cf_head->h_psize;
-
- rc = (*cfp->cf_pp->write)(cfp, cfp->cf_head,
- sizeof (cfgheader_t));
- if (rc < 0) {
- cfg_perror_str = dgettext("cfg",
- "cfg_commit: header write failed");
- cfg_severity = CFG_EFATAL;
- 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
-cfg_rewind(CFGFILE *cfg, int section)
-{
- 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 *
-cfg_location(char *location, int mode, char *altroot)
-{
- int fd;
- int fmode;
- int rc;
- char wellknown[NSC_MAXPATH];
- char loc[NSC_MAXPATH];
-
- if (mode == CFG_LOC_GET_LOCAL) {
- return (CFG_LOCAL_LOCATION);
- } else if (mode == CFG_LOC_GET_CLUSTER) {
- fmode = O_RDONLY;
- } else {
- fmode = O_RDWR | O_CREAT;
- }
-
- if (altroot) {
- strcpy(wellknown, altroot);
- strcat(wellknown, CFG_CLUSTER_LOCATION);
- } else
- strcpy(wellknown, CFG_CLUSTER_LOCATION);
-
- fd = open(wellknown, fmode, 0644);
- if (fd < 0) {
- cfg_perror_str = dgettext("cfg", strerror(errno));
- cfg_severity = CFG_ENONFATAL;
- return (NULL);
- }
-
- if (mode == CFG_LOC_SET_CLUSTER) {
- if (location == NULL || (strlen(location) > NSC_MAXPATH)) {
- cfg_perror_str = dgettext("cfg",
- "cfg_location: filename too big or missing");
- cfg_severity = CFG_EFATAL;
- 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) {
- struct stat dscfg_stat;
- if (stat(location, &dscfg_stat) != 0) {
- cfg_perror_str = dgettext("cfg",
- "Unable to access dscfg location");
- cfg_severity = CFG_EFATAL;
- return (NULL);
- }
- if (!S_ISCHR(dscfg_stat.st_mode)) {
- cfg_perror_str = dgettext("cfg",
- "dscfg location must be a raw device");
- cfg_severity = CFG_EFATAL;
- return (NULL);
- }
- }
-
- if (ftruncate(fd, 0) < 0)
- return (NULL);
-
- rc = write(fd, location, strlen(location));
- if (rc < 0) {
- cfg_perror_str = dgettext("cfg",
- "cfg_location: write to well known failed");
- cfg_severity = CFG_EFATAL;
- return (NULL);
- }
- bzero(config_file, sizeof (config_file));
- }
- if (lseek(fd, 0, SEEK_SET) < 0)
- return (NULL);
-
- bzero(config_file, sizeof (config_file));
- rc = read(fd, config_file, sizeof (config_file));
- if (rc < 0) {
- cfg_perror_str = dgettext("cfg",
- "cfg_location: read from well known failed");
- cfg_severity = CFG_EFATAL;
- return (NULL);
- }
- close(fd);
- if (altroot) {
- strcpy(loc, altroot);
- strcat(loc, config_file);
- bzero(config_file, sizeof (config_file));
- strcpy(config_file, loc);
- }
-
- /*
- * scan string out of config_file, to strip whitespace
- */
- sscanf(config_file, "%s", loc);
- strcpy(config_file, loc);
-
- 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
-cfg_update_parser_config(CFGFILE *cfg, const char *key, int section)
-{
- cfp_t *cfp;
- int size;
- char buf[CFG_MAX_BUF];
- struct parser *tbl;
- char tmpkey[CFG_MAX_KEY];
- char *ky, *fld;
- errno = 0;
-
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- return (-1);
- }
-
- cfp = FP_SUN_CLUSTER(cfg);
- if (!cfg_wrlock(cfg))
- return (-1);
-
- bzero(buf, CFG_MAX_BUF);
- bzero(tmpkey, sizeof (tmpkey));
- strcpy(tmpkey, key);
- if (section == CFG_PARSE_CONF) {
- strcat(buf, "C:");
- tbl = chead;
- } else {
- errno = EINVAL;
- return (-1);
- }
- ky = strtok(tmpkey, ".");
- fld = strtok(NULL, ".");
- while (fld) {
- size = cfg_get_item(tbl, ky, fld);
-
- /*
- * Assure we are loading a clean table, with do duplicates
- * based on our File Descriptor
- */
- if (chead_loaded && (chead_loaded != cfp->cf_fd)) {
- if (size <= 0)
- return (-1);
- } else {
- if (size > 0)
- return (-1);
- }
- fld = strtok(NULL, ".");
- }
- size = strlen(key) + 2;
- strncat(buf, key, size);
-#ifdef DEBUG_LIB
- (void) fprintf(stderr, "update parser config %s size %d\n", buf, size);
-#endif
- if ((size + cfp->cf_head->h_parseoff) > CFG_DEFAULT_PARSE_SIZE) {
- cfg_perror_str = dgettext("cfg",
- "cfg_update_parser_config: header overrun");
- cfg_severity = CFG_EFATAL;
-#ifdef DEBUG_LIB
- (void) fprintf(stderr, "update parser config: "
- "overrun siz %d poff %d parsesize %d\n",
- size, cfp->cf_head->h_parseoff, cfp->cf_head->h_parsesize);
-#endif
- errno = E2BIG;
- return (-1);
- }
- bcopy(buf, (cfp->cf_mapped + cfp->cf_head->h_parseoff), size);
- cfp->cf_head->h_parseoff += size;
- cfp->cf_head->h_state |= CFG_HDR_INVALID;
- if (cfp->cf_mapped[cfp->cf_head->h_parseoff - 1] != '\n') {
- cfp->cf_mapped[cfp->cf_head->h_parseoff] = '\n';
- cfp->cf_head->h_parseoff++;
- }
- cfp->cf_head->h_parsesize = cfp->cf_head->h_parseoff;
- cfg_read_parser_config(cfp);
- 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
-cfg_read_parser_config(cfp_t *cfp)
-{
- struct lookup *p, *q;
- struct parser *thead;
- int off, foff;
- char *part;
- char *key;
- char *fld;
- int fldnum;
- char c;
- char buf[CFG_MAX_BUF];
- int i = 0;
- int n = 0;
-
- off = foff = 0;
- /*CONSTCOND*/
- while (TRUE) {
- off = 0;
- bzero(buf, CFG_MAX_BUF);
- /* LINTED it assigns value to c */
- while (c = cfp->cf_mapped[foff++]) {
- if (c == '\n')
- break;
- buf[off++] = c;
- }
- part = strtok(buf, ":");
- if (!part)
- break;
- if (*part == 'C') {
- thead = chead;
- n = i;
- }
- key = strtok(NULL, ".");
- if (!key)
- break;
- strcpy(thead[n].tag.l_word, key);
- thead[n].tag.l_value = 0;
- thead[n].fld = NULL;
- fldnum = 1;
- while ((fld = strtok(NULL, ".")) != NULL) {
- p = thead[n].fld;
- if (p == NULL) {
- q = thead[n].fld = calloc(1,
- sizeof (struct lookup));
- } else {
- for (q = thead[n].fld; q; q = q->l_next)
- p = q;
- q = calloc(1, sizeof (struct lookup));
- p->l_next = q;
- }
- strcpy(q->l_word, fld);
- q->l_value = fldnum;
- q->l_next = NULL;
-#ifdef DEBUG_EXTRA
- (void) fprintf(stderr,
- "read parser: q: word %s value %d\n",
- q->l_word, q->l_value);
-#endif
- fldnum++;
- }
- if (*part == 'C')
- i++;
- }
-
- /* All done, indicate parser table is loaded */
- if (i && (chead_loaded == 0))
- chead_loaded = cfp->cf_fd;
-
- /*
- * 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
- */
- if ((cfp->cf_head->h_cfgs == NULL) ||
- (cfp->cf_head->h_cfgs[n-1].l_entry == NULL)) {
- cfp->cf_head->h_cfgs = (cfglist_t *)calloc(MAX_CFG,
- sizeof (cfglist_t));
- i = 0;
- }
- else
- i = n;
-
- if (cfp->cf_head->h_cfgs) {
-
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr, "alloced %d cfg lists \n", n + 1);
-#endif
- for (cfp->cf_head->h_ncfgs = n + 1;
- i < min(cfp->cf_head->h_ncfgs, MAX_CFG); i++) {
- cfp->cf_head->h_cfgs[i].l_name = '\0';
- cfp->cf_head->h_cfgs[i].l_name =
- strdup(chead[i].tag.l_word);
- cfp->cf_head->h_cfgs[i].l_index = i;
- cfp->cf_head->h_cfgs[i].l_entry =
- calloc(DEFAULT_ENTRY_SIZE, sizeof (char));
- cfp->cf_head->h_cfgs[i].l_nentry = 0;
- cfp->cf_head->h_cfgs[i].l_esiz =
- calloc(DEFAULT_NENTRIES, sizeof (int));
- cfp->cf_head->h_cfgs[i].l_size = 0;
- cfp->cf_head->h_cfgs[i].l_free = DEFAULT_ENTRY_SIZE;
- if ((cfp->cf_head->h_cfgs[i].l_entry == NULL) ||
- (cfp->cf_head->h_cfgs[i].l_esiz == NULL)) {
- cfg_perror_str = dgettext("cfg", "unable to"
- " allocate cfglist members");
- cfg_severity = CFG_EFATAL;
- }
- }
- } else {
- cfg_perror_str = dgettext("cfg", "unable to alloc cfglist");
- cfg_severity = CFG_EFATAL;
- }
-}
-
-/*
- * cfg_map_cfglists()
- * go through list of list sizes in header
- * and create separate lists
- */
-int
-cfg_map_cfglists(cfp_t *cfp)
-{
- int i;
- int offset = 0;
- int *ip;
- int list_size = 0;
- int slot_inc;
- char *p;
- cfgheader_t *ch;
-
- ch = cfp->cf_head;
- p = ch->h_cparse;
-
- /* get the first list size */
- ip = ch->h_sizes;
-
- for (i = 0; i < min(ch->h_ncfgs, MAX_CFG); i++) {
- if (ch->h_cfgsizes[i] > 0) {
- if (ch->h_cfgsizes[i] > DEFAULT_ENTRY_SIZE) {
-
- ch->h_cfgs[i].l_entry = (char *)
- realloc(ch->h_cfgs[i].l_entry,
- ch->h_cfgsizes[i] * sizeof (char));
- /* set free to 0, we'll get more when we add */
- ch->h_cfgs[i].l_free = 0;
-
- } else
- ch->h_cfgs[i].l_free -= ch->h_cfgsizes[i];
-
- /* get lists and marry up to each cfgs structure */
-
-
- list_size = *ip;
- 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
- */
- slot_inc = DEFAULT_NENTRIES -
- (list_size % DEFAULT_NENTRIES);
- if (slot_inc == DEFAULT_NENTRIES)
- slot_inc = 0; /* addcfline reallocs */
-
- ch->h_cfgs[i].l_esiz = (int *)realloc(
- ch->h_cfgs[i].l_esiz,
- (list_size + slot_inc) * sizeof (int));
- }
- memcpy(ch->h_cfgs[i].l_esiz, ip,
- list_size * sizeof (int));
-
- ch->h_cfgs[i].l_nentry = list_size;
-
- ip += list_size;
-
- } else
-
- continue;
-
- if (ch->h_cfgs[i].l_entry != NULL) {
- p = ch->h_cparse + offset;
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr, "mapping list %d size %d offset %d, addr 0x%x\n",
- i, ch->h_cfgsizes[i], offset, p);
-#endif
- memcpy(ch->h_cfgs[i].l_entry,
- p, ch->h_cfgsizes[i]);
- ch->h_cfgs[i].l_size = ch->h_cfgsizes[i];
- offset += ch->h_cfgsizes[i];
- } else {
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr, "NULL l_entry\n");
-#endif
- return (-1);
- }
- }
-
-
- return (1);
-
-}
-
-void
-cfg_replace_lists(cfp_t *cfp)
-{
- int i;
- int offset = 0;
- int size_offset = 0;
-
- int section = 0;
- cfgheader_t *cf;
- cfglist_t *cfl;
-
- cf = cfp->cf_head;
-
- if ((cfl = cfp->cf_head->h_cfgs) == NULL)
- return;
-
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr, "cfg_replace_lists\n");
-#endif
-
- if (cf->h_cparse == cf->h_ccopy1)
- 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.
- */
- cf->h_ccopy1 = (char *)
- realloc(cf->h_ccopy1, cf->h_csize * sizeof (char));
- cf->h_ccopy2 = (char *)
- realloc(cf->h_ccopy2, cf->h_csize * sizeof (char));
- if (section == 1) {
- /* we used copy1 */
- cf->h_cparse = cf->h_ccopy1;
- } else
- cf->h_cparse = cf->h_ccopy2;
-
- /*
- * just because, we'll zero out h_csize and recalc
- * after all, this is the number the next guy gets
- */
- cf->h_csize = cf->h_sizes[0] = 0;
- for (i = 0; i < MAX_CFG; i++) {
- /* only as many lists as chead has */
- if (chead[i].tag.l_word[0] == '\0') {
- break;
- }
- if (cfl[i].l_entry && cfl[i].l_entry[0] != '\0') {
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr,
- "copying list %d at %x size %d\n",
- i, cf->h_cparse + offset,
- cfl[i].l_size);
-#endif
- memcpy((cf->h_cparse + offset),
- cfl[i].l_entry, cfl[i].l_size);
- offset += cfl[i].l_size;
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr,
- "cfl[%d].l_nentry %d cfl[%d].l_esiz[%d] %d"
- " size offset %d\n",
- i, cfl[i].l_nentry, i, cfl[i].l_nentry - 1,
- cfl[i].l_esiz[cfl[i].l_nentry - 1], size_offset);
-#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
- */
- cf->h_sizes[size_offset++] = cfl[i].l_nentry;
- memcpy((cf->h_sizes + size_offset), cfl[i].l_esiz,
- cfl[i].l_nentry * sizeof (int));
- size_offset += cfl[i].l_nentry;
- cf->h_sizes[size_offset] = 0;
- }
- cf->h_csize += cfl[i].l_size;
- }
-}
-
-void
-cfg_free_cfglist(cfp_t *cfp)
-{
- int i;
-
- if (!cfp->cf_head || !cfp->cf_head->h_cfgs)
- return;
-
- for (i = 0; cfp->cf_head && i < MAX_CFG; i++) {
- if (cfp->cf_head->h_cfgs[i].l_entry) {
- free(cfp->cf_head->h_cfgs[i].l_entry);
- cfp->cf_head->h_cfgs[i].l_entry = NULL;
- }
-
- if (cfp->cf_head->h_cfgs[i].l_name) {
- free(cfp->cf_head->h_cfgs[i].l_name);
- cfp->cf_head->h_cfgs[i].l_entry = NULL;
- }
-
- if (cfp->cf_head->h_cfgs[i].l_esiz) {
- free(cfp->cf_head->h_cfgs[i].l_esiz);
- cfp->cf_head->h_cfgs[i].l_esiz = NULL;
- }
- }
-
- if (cfp->cf_head) {
- free(cfp->cf_head->h_cfgs);
- cfp->cf_head->h_cfgs = NULL;
- }
-}
-
-void
-cfg_free_parser_tree()
-{
- struct lookup *p = NULL;
- struct lookup *q = NULL;
- int i;
-
- for (i = 0; i < MAX_CFG; i++) {
- if (chead)
- p = chead[i].fld;
- while (p) {
- q = p->l_next;
- if (p) {
- free(p);
- p = NULL;
- }
- p = q;
- }
- }
- bzero(chead, MAX_CFG * sizeof (struct parser));
-}
-
-void
-cfg_close(CFGFILE *cfg)
-{
- cfp_t *cfp;
-
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- return;
- }
-
- /* Determine number of files open */
- for (cfp = &cfg->cf[0]; cfp <= &cfg->cf[1]; cfp++) {
- if (!cfp->cf_fd) continue;
-
- (*cfp->cf_pp->close)(cfp);
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr, "freeing cfglists\n");
-#endif
- cfg_free_cfglist(cfp);
-
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr, "freeing cfp->cf_mapped\n");
-#endif
- free(cfp->cf_mapped);
- cfp->cf_mapped = NULL;
-
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr,
- "freeing copy1, copy2, h_sizes and cf\n");
-#endif
- if (cfp->cf_head) {
- if (cfp->cf_head->h_ccopy1) {
- free(cfp->cf_head->h_ccopy1);
- cfp->cf_head->h_ccopy1 = NULL;
- }
- if (cfp->cf_head->h_ccopy2) {
- free(cfp->cf_head->h_ccopy2);
- cfp->cf_head->h_ccopy2 = NULL;
- }
- if (cfp->cf_head->h_sizes1) {
- free(cfp->cf_head->h_sizes1);
- cfp->cf_head->h_sizes1 = NULL;
- }
- if (cfp->cf_head->h_sizes2) {
- free(cfp->cf_head->h_sizes2);
- cfp->cf_head->h_sizes2 = NULL;
- }
-
- }
- if (cfp->cf_head)
- free(cfp->cf_head);
- }
-
- free(cfg);
- cfg = NULL;
- cfg_free_parser_tree();
-
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr, "cfg_close\n");
-#endif
-}
-
-
-char *
-cfg_get_resource(CFGFILE *cfg)
-{
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- return (NULL);
- }
-
- return (cfg->cf_node);
-}
-
-/*
- * cfg_resource
- * set or clear the cluster node filter for get/put
- */
-
-void
-cfg_resource(CFGFILE *cfg, const char *node)
-{
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- return;
- }
-
- if (cfg->cf_node) {
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr,
- "cfg_resource: changing node from %s to %s\n",
- cfg->cf_node, (node?node:"NULL"));
-#endif
- free(cfg->cf_node);
- cfg->cf_node = NULL;
- }
-
- /*
- * just in case someone passes in a non-NULL
- * node, but has no valid value
- */
- if ((node) && (node[0] != '\0')) {
- cfg->cf_node = strdup(node);
- }
-}
-
-/*
- * cfg_open
- * Open the current configuration file
- */
-CFGFILE *
-cfg_open(char *name)
-{
- CFGFILE *cfg;
- cfp_t *cfp;
- int32_t magic;
- long needed;
- int rc;
-
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr, "cfg_open\n");
-#endif
-
- cfg_severity = 0;
- if ((cfg = (CFGFILE *)calloc(1, sizeof (*cfg))) == NULL) {
- cfg_perror_str = dgettext("cfg",
- "cfg_open: malloc failed");
- cfg_severity = CFG_EFATAL;
- return (NULL);
- }
-
- cfp = &cfg->cf[0];
- if ((name) && strlen(name)) {
-#ifdef DEBUG
- (void) fprintf(stderr, "cfg_open: Using non-standard name\n");
-#endif
- cfp->cf_name = name;
- cfp->cf_pp = (strstr(cfp->cf_name, "/rdsk/") == NULL) ?
- cfg_block_io_provider() : cfg_raw_io_provider();
- } else {
- cfp->cf_name = cfg_location(NULL, CFG_LOC_GET_LOCAL, NULL);
- cfp->cf_pp = cfg_block_io_provider();
-
- /* Handle cfg_open(""), which is an open from boot tools */
- if (name)
- cl_initialized = 1;
- if (cfg_iscluster() > 0) {
- cfp = &cfg->cf[1];
- cfp->cf_name =
- cfg_location(NULL, CFG_LOC_GET_CLUSTER, NULL);
- if (cfp->cf_name) {
- cfp->cf_pp = cfg_raw_io_provider();
- }
- }
- }
-
- /*
- * Open one or two configuration files
- */
- for (cfp = &cfg->cf[0]; cfp->cf_name && (cfp <= &cfg->cf[1]); cfp++) {
- if ((*cfp->cf_pp->open)(cfp, cfp->cf_name) == NULL) {
- cfg_perror_str = dgettext("cfg",
- "cfg_open: unable to open configuration location");
- cfg_severity = CFG_EFATAL;
- break;
- }
-
- /* block device smaller than repository? */
- rc = (*cfp->cf_pp->read)(cfp, &magic, sizeof (magic));
- if (rc < sizeof (magic)) {
- cfg_perror_str = dgettext("cfg",
- "cfg_open: unable to read configuration header");
- cfg_severity = CFG_EFATAL;
- break;
- }
-
- if ((*cfp->cf_pp->seek)(cfp, 0, SEEK_SET) < 0) {
- cfg_perror_str = dgettext("cfg",
- "cfg_open: unable to seek configuration header");
- cfg_severity = CFG_EFATAL;
- 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) {
- needed = FBA_NUM(FBA_SIZE(1) - 1 +
- (sizeof (struct cfgheader) + CFG_CONFIG_SIZE));
- } else {
- needed = 0;
- }
-
- if (cfp->cf_size < needed) {
- cfg_perror_str = dgettext("cfg",
- "cfg_open: configuration file too small");
- cfg_severity = CFG_EFATAL;
- errno = ENOMEM;
- break;
- }
-
- cfp->cf_mapped = (char *)malloc(CFG_DEFAULT_PARSE_SIZE);
- if (cfp->cf_mapped == NULL) {
- cfg_perror_str = dgettext("cfg",
- "cfg_open: malloc failed");
- cfg_severity = CFG_EFATAL;
- break;
- }
-
- bzero(cfp->cf_mapped, CFG_DEFAULT_PARSE_SIZE);
- cfp->cf_lock = -1;
- }
-
- /* Processing errors, take care of one or more cfp pointers */
- if (cfg_severity && (cfp <= &cfg->cf[1])) {
- cfp = &cfg->cf[0];
- if (cfp->cf_fd)
- (*cfp->cf_pp->close)(cfp);
- cfp = &cfg->cf[1];
- if (cfp->cf_fd)
- (*cfp->cf_pp->close)(cfp);
- free(cfg);
- return (NULL);
- }
-
- cfg_lockd = cfg_lockd_init();
-
-
-#ifdef DEBUG_CFGLIST
- (void) fprintf(stderr, "cfg_open ok\n");
-#endif
- return (cfg);
-}
-
-void
-cfg_invalidate_hsizes(int fd, const char *loc)
-{
- int offset;
- int rc = -1;
- int hdrsz;
-
- char buf[2 * CFG_DEFAULT_PSIZE];
-
- hdrsz = sizeof (cfgheader_t) + 512 -
- (sizeof (cfgheader_t) % 512);
-
- offset = hdrsz + CFG_DEFAULT_PARSE_SIZE +
- (CFG_DEFAULT_SSIZE * 2);
-
- if (cfg_shldskip_vtoc(fd, loc) > 0)
- offset += CFG_VTOC_SKIP;
-
- bzero(buf, sizeof (buf));
-
- if (lseek(fd, offset, SEEK_SET) > 0)
- rc = write(fd, buf, sizeof (buf));
- if (rc < 0)
- (void) fprintf(stderr, "cfg: invalidate hsizes failed\n");
-
-}
-
-char *
-cfg_error(int *severity)
-{
- if (severity != NULL)
- *severity = cfg_severity;
- return (cfg_perror_str ? cfg_perror_str : CFG_EGENERIC);
-}
-/*
- * cfg_cfg_isempty
- */
-int
-cfg_cfg_isempty(CFGFILE *cfg)
-{
- cfp_t *cfp;
-
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- return (FALSE);
- }
-
- cfp = FP_SUN_CLUSTER(cfg);
- if (cfp->cf_head->h_csize == 0)
- 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
-cfg_get_num_entries(CFGFILE *cfg, char *section)
-{
- int count = 0;
- int table_offset;
- cfp_t *cfp;
-
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- return (-1);
- }
-
- if ((table_offset = cfg_get_parser_offset(section)) < 0) {
- errno = ESRCH;
- return (-1);
- }
-
- /* Determine number of files open */
- for (cfp = &cfg->cf[0]; cfp->cf_fd && (cfp <= &cfg->cf[1]); cfp++)
- count += cfp->cf_head->h_cfgs[table_offset].l_nentry;
-
- 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
-cfg_get_section(CFGFILE *cfg, char ***list, const char *section)
-{
- int table_offset;
- int i, count;
- cfglist_t *cfl;
- char *p = NULL;
- char **buf;
- cfp_t *cfp;
-
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- return (FALSE);
- }
-
- if ((table_offset = cfg_get_parser_offset(section)) < 0) {
- errno = ESRCH;
- return (-1);
- }
-
- /* Determine number of files open */
- count = 0;
- for (cfp = &cfg->cf[0]; cfp <= &cfg->cf[1]; cfp++) {
- if (!cfp->cf_fd) continue;
- if (cfp->cf_head->h_state & CFG_HDR_INVALID) {
- if (!cfg_read(cfp)) {
- cfg_perror_str = dgettext("cfg", CFG_RDFAILED);
- cfg_severity = CFG_EFATAL;
- return (-1);
- }
- }
-
- cfl = &cfp->cf_head->h_cfgs[table_offset];
- if (cfl->l_nentry == 0) /* empty list */
- continue;
-
- if (count == 0)
- buf = (char **)malloc(cfl->l_nentry * sizeof (char *));
- else
- buf = (char **)realloc(buf, (cfl->l_nentry + count) *
- sizeof (char *));
- if (buf == NULL) {
- errno = ENOMEM;
- return (-1);
- } else {
- bzero(&buf[count], cfl->l_nentry * sizeof (char *));
- }
-
- p = cfl->l_entry;
- for (i = 0; i < cfl->l_nentry; i++) {
- if ((buf[i + count] = strdup(p)) == NULL) {
- errno = ENOMEM;
- return (-1);
- }
- p += cfl->l_esiz[i];
- }
- count += cfl->l_nentry;
- }
-
- *list = buf;
- 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
-cfg_get_tags(CFGFILE *cfg, char ***taglist)
-{
- char **list;
- int i = 0;
-
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- return (-1);
- }
-
- if (!cfg_rdlock(cfg)) {
- return (-1);
- }
- list = calloc(1, MAX_CFG * sizeof (char *));
- if (list == NULL) {
- errno = ENOMEM;
- return (-1);
- }
-
- while ((i < MAX_CFG) && (chead[i].tag.l_word[0] != '\0')) {
- list[i] = strdup(chead[i].tag.l_word);
- if (list[i] == NULL) {
- for (/* CSTYLE */; i >= 0; i--) {
- if (list[i])
- free(list[i]);
- }
- free(list);
- errno = ENOMEM;
- return (-1);
- }
- i++;
- }
- *taglist = list;
- return (i);
-
-}
-
-/*
- * is this a database?
- * check the header for the magic number
- * 0 no match 1 match, -1 on error
- */
-int
-cfg_is_cfg(CFGFILE *cfg)
-{
- int32_t magic;
- int rc;
- cfp_t *cfp = FP_SUN_CLUSTER(cfg);
-
- rc = (cfp->cf_pp->read)(cfp, &magic, sizeof (magic));
- if (rc < sizeof (magic)) {
- cfg_perror_str = dgettext("cfg", "Fail to read configuration");
- cfg_severity = CFG_EFATAL;
- return (-1);
- }
-
- if (magic == CFG_NEW_MAGIC)
- return (1);
-
- cfg_perror_str = dgettext("cfg",
- "configuration not initialized, bad magic");
- cfg_severity = CFG_EFATAL;
-
- return (0);
-}
-
-int
-compare(const void* a, const void *b)
-{
- char *p;
- char *pbuf;
- char *q;
- char *qbuf;
- int needed;
- int cmp;
- int pos;
-
- pbuf = strdup(a);
- qbuf = strdup(b);
-
- if (!qbuf || !pbuf)
- return (0);
-
- pos = 1;
- needed = sortby.offset;
-
- p = strtok(pbuf, " ");
- while (p) {
- if (needed == pos) {
- break;
- }
- p = strtok(NULL, " ");
- if (!p)
- break;
- pos++;
- }
-
- pos = 1;
- q = strtok(qbuf, " ");
- while (q) {
- if (needed == pos) {
- break;
- }
- q = strtok(NULL, " ");
- if (!q)
- break;
- pos++;
- }
- if (!p || !q) {
- sortby.comperror++;
- free(pbuf);
- free(qbuf);
- return (0);
- }
- cmp = strcmp(p, q);
- free(pbuf);
- free(qbuf);
- return (cmp);
-
-
-}
-/*
- * cfg_get_srtdsec
- * returns the section, sorted by supplied field
- * caller frees mem
- */
-int
-cfg_get_srtdsec(CFGFILE *cfg, char ***list, const char *section,
- const char *field)
-{
- cfglist_t *cfl;
- cfp_t *cfp;
- char **buf;
- char *tmplst;
- char *p, *q;
- int table_offset;
- int count, i;
-
- if (cfg == NULL) {
- cfg_perror_str = dgettext("cfg", CFG_EINVAL);
- cfg_severity = CFG_EFATAL;
- return (FALSE);
- }
-
- if ((table_offset = cfg_get_parser_offset(section)) < 0) {
- cfg_perror_str = dgettext("cfg", CFG_RDFAILED);
- errno = ESRCH;
- return (-1);
- }
-
- /*
- * do essentially what get_section does,
- * except stick entries in a static size
- * buf to make things easier to qsort
- */
- count = 0;
- for (cfp = &cfg->cf[0]; cfp <= &cfg->cf[1]; cfp++) {
- if (!cfp->cf_fd) continue;
- if (cfp->cf_head->h_state & CFG_HDR_INVALID) {
- if (!cfg_read(cfp)) {
- cfg_perror_str = dgettext("cfg", CFG_RDFAILED);
- cfg_severity = CFG_EFATAL;
- return (-1);
- }
- }
-
- cfl = &cfp->cf_head->h_cfgs[table_offset];
- if (cfl->l_nentry == 0) /* empty list */
- continue;
-
- if (count == 0)
- buf = (char **)malloc(cfl->l_nentry * sizeof (char *));
- else
- buf = (char **)realloc(buf, (cfl->l_nentry + count) *
- sizeof (char *));
- if (buf == NULL) {
- errno = ENOMEM;
- cfg_perror_str = dgettext("cfg", "cfg_get_srtdsec: "
- "malloc failed");
- cfg_severity = CFG_EFATAL;
- return (-1);
- } else {
- bzero(&buf[count], cfl->l_nentry * sizeof (char *));
- }
-
- /*
- * allocate each line
- */
- for (i = count; i < cfl->l_nentry + count; i++) {
- buf[i] = calloc(1, CFG_MAX_BUF);
- if (buf[i] == NULL) {
- free(buf);
- errno = ENOMEM;
- return (-1);
- }
- }
-
- if (count == 0)
- tmplst = (char *)malloc(cfl->l_nentry * CFG_MAX_BUF);
- else
- tmplst = (char *)realloc(tmplst,
- (cfl->l_nentry + count) * CFG_MAX_BUF);
- if (tmplst == NULL) {
- cfg_perror_str = dgettext("cfg", "cfg_get_srtdsec: "
- "malloc failed");
- cfg_severity = CFG_EFATAL;
- free(buf);
- return (-1);
- } else {
- bzero(&tmplst[count], cfl->l_nentry * CFG_MAX_BUF);
- }
-
- /*
- * put the section in tmplst and sort
- */
- p = &tmplst[count];
- q = cfl->l_entry;
- for (i = 0; i < cfl->l_nentry; i++) {
- bcopy(q, p, cfl->l_esiz[i]);
- p += CFG_MAX_BUF;
- q += cfl->l_esiz[i];
- }
- count += cfl->l_nentry;
- }
-
- bzero(sortby.section, CFG_MAX_KEY);
- bzero(sortby.field, CFG_MAX_KEY);
-
- strcpy(sortby.section, section);
- strcpy(sortby.field, field);
- sortby.comperror = 0;
- sortby.offset = cfg_get_item(&chead[0], section, field);
-
- qsort(tmplst, count, CFG_MAX_BUF, compare);
-
- if (sortby.comperror) {
- sortby.comperror = 0;
- cfg_perror_str = dgettext("cfg", "cfg_get_srtdsec: "
- "comparison error");
- cfg_severity = CFG_ENONFATAL;
- cfg_free_section(&buf, cfl->l_nentry);
- free(tmplst);
- *list = NULL;
- return (-1);
- }
-
- p = tmplst;
- for (i = 0; i < count; i++) {
- bcopy(p, buf[i], CFG_MAX_BUF);
- p += CFG_MAX_BUF;
- }
-
- free(tmplst);
- *list = buf;
- return (count);
-}
-
-/*
- * free an array alloc'd by get_*section
- * or some other array of size size
- */
-
-void
-cfg_free_section(char ***section, int size)
-{
- int i;
- char **secpp = *section;
-
- for (i = 0; i < size; i++) {
- if (secpp[i]) {
- free(secpp[i]);
- secpp[i] = NULL;
- }
- }
- if (secpp) {
- free(secpp);
- secpp = NULL;
- }
- section = NULL;
-}
-
-
-int
-cfg_shldskip_vtoc(int fd, const char *loc)
-{
- struct vtoc vtoc;
- struct stat sb;
- int slice;
- int rfd;
- char char_name[PATH_MAX];
- char *p;
-
- if (fstat(fd, &sb) == -1) {
- cfg_perror_str = dgettext("cfg", "unable to stat config");
- cfg_severity = CFG_EFATAL;
- return (-1);
- }
- if (S_ISREG(sb.st_mode))
- return (0);
-
- if (S_ISCHR(sb.st_mode)) {
- if ((slice = read_vtoc(fd, &vtoc)) < 0)
- return (-1);
-
- if (vtoc.v_part[slice].p_start < CFG_VTOC_SIZE)
- return (1);
- else
- return (0);
- }
-
- if (S_ISBLK(sb.st_mode)) {
- p = strstr(loc, "/dsk/");
- if (p == NULL)
- return (-1);
- strcpy(char_name, loc);
- char_name[strlen(loc) - strlen(p)] = 0;
- strcat(char_name, "/rdsk/");
- strcat(char_name, p + 5);
-
- if ((rfd = open(char_name, O_RDONLY)) < 0) {
- return (-1);
- }
- if ((slice = read_vtoc(rfd, &vtoc)) < 0) {
- close(rfd);
- return (-1);
- }
- close(rfd);
- if (vtoc.v_part[slice].p_start < CFG_VTOC_SIZE)
- return (1);
- else
- return (0);
- }
-
- return (-1);
-}
-
-/*
- * comapares incore header with one on disk
- * returns 0 if equal, 1 if not, -1 error
- */
-int
-cfg_hdrcmp(cfp_t *cfp)
-{
- cfgheader_t *dskhdr, *memhdr;
- int rc;
-
- if ((dskhdr = calloc(1, sizeof (*dskhdr))) == NULL) {
- cfg_perror_str = dgettext("cfg", "cfg_hdrcmp: No memory");
- cfg_severity = CFG_ENONFATAL;
- }
-
- if ((*cfp->cf_pp->seek)(cfp, 0, SEEK_SET) < 0) {
- cfg_perror_str = dgettext("cfg", "cfg_hdrcmp: seek failed");
- cfg_severity = CFG_ENONFATAL;
- free(dskhdr);
- return (-1);
- }
-
- rc = (*cfp->cf_pp->read)(cfp, (char *)dskhdr, sizeof (*dskhdr));
- if (rc < 0) {
- cfg_perror_str = dgettext("cfg", "cfg_hdrcmp: read failed");
- cfg_severity = CFG_ENONFATAL;
- free(dskhdr);
- return (-1);
- }
-
- memhdr = cfp->cf_head;
-
- if ((memhdr->h_seq1 == dskhdr->h_seq1) &&
- (memhdr->h_seq2 == dskhdr->h_seq2))
- rc = 0;
- else
- rc = 1;
-
-
- free(dskhdr);
- return (rc);
-}