diff options
Diffstat (limited to 'usr/src/lib/libdscfg/common/cfg.c')
-rw-r--r-- | usr/src/lib/libdscfg/common/cfg.c | 3585 |
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); -} |