diff options
author | Yuri Pankov <yuri.pankov@nexenta.com> | 2018-08-07 16:46:21 -0700 |
---|---|---|
committer | Joshua M. Clulow <josh@sysmgr.org> | 2018-08-07 16:46:22 -0700 |
commit | cb41b9c565d4eec9e1f06e24d429696f59f2f07d (patch) | |
tree | ee8675f196c2ea84b5ac5c6f0dff8c9e5305f0ee /usr/src/lib/libdscfg/common | |
parent | 0e986b9d87352cd82909c748e7f684afe0ed579f (diff) | |
download | illumos-joyent-cb41b9c565d4eec9e1f06e24d429696f59f2f07d.tar.gz |
9674 Let's scrap AVS/sdbc
Reviewed by: Dan McDonald <danmcd@joyent.com>
Reviewed by: Peter Tribble <peter.tribble@gmail.com>
Approved by: Joshua M. Clulow <josh@sysmgr.org>
Diffstat (limited to 'usr/src/lib/libdscfg/common')
-rw-r--r-- | usr/src/lib/libdscfg/common/cfg.c | 3585 | ||||
-rw-r--r-- | usr/src/lib/libdscfg/common/cfg.h | 180 | ||||
-rw-r--r-- | usr/src/lib/libdscfg/common/cfg_cluster.c | 582 | ||||
-rw-r--r-- | usr/src/lib/libdscfg/common/cfg_cluster.h | 344 | ||||
-rw-r--r-- | usr/src/lib/libdscfg/common/cfg_impl.h | 247 | ||||
-rw-r--r-- | usr/src/lib/libdscfg/common/cfg_local.c | 653 | ||||
-rw-r--r-- | usr/src/lib/libdscfg/common/cfg_local.h | 42 | ||||
-rw-r--r-- | usr/src/lib/libdscfg/common/cfg_lockd.h | 72 | ||||
-rw-r--r-- | usr/src/lib/libdscfg/common/cfg_lockdlck.c | 135 | ||||
-rw-r--r-- | usr/src/lib/libdscfg/common/cfg_lockdmsg.c | 324 | ||||
-rw-r--r-- | usr/src/lib/libdscfg/common/cfg_vols.c | 1286 | ||||
-rw-r--r-- | usr/src/lib/libdscfg/common/mapfile-vers | 100 |
12 files changed, 0 insertions, 7550 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); -} diff --git a/usr/src/lib/libdscfg/common/cfg.h b/usr/src/lib/libdscfg/common/cfg.h deleted file mode 100644 index 84e64b8ebe..0000000000 --- a/usr/src/lib/libdscfg/common/cfg.h +++ /dev/null @@ -1,180 +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. - */ - -#ifndef _CFG_H -#define _CFG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <sys/nsctl/nsctl.h> - -#define CFG_MAX_BUF 1024 /* maximum buffer size for cfg_get_?string() */ -#define CFG_MAX_KEY 256 /* maximum key size for cfg_get_?string() */ - -#ifndef _CFG_IMPL_H -/* - * These are really declared in cfg_impl.h, declare as dummy's here to - * allow clients to compile without including cfg_impl.h. - */ -typedef struct cfgfile CFGFILE; -typedef struct cfp cfp_t; - -#endif /* _CFG_IMPL_H */ - -int cfg_get_cstring(CFGFILE *cfg, const char *key, void *value, int value_len); -int cfg_put_cstring(CFGFILE *cfg, const char *key, void *value, int value_len); -int cfg_find_cstring(CFGFILE *cfg, const char *target, const char *section, - int numflds, ...); -int cfg_get_options(CFGFILE *cfg, int section, const char *basekey, - char *tag, int tag_len, char *val, int val_len); -int cfg_put_options(CFGFILE *cfg, int section, const char *basekey, - char *tag, char *val); -int cfg_get_single_option(CFGFILE *, int, const char *, char *, char *, int); -int cfg_del_option(CFGFILE *, int, const char *, char *); - -int cfg_get_num_entries(CFGFILE *cfg, char *section); - -int cfg_get_tags(CFGFILE *cfg, char ***taglist); - -int cfg_cfg_isempty(CFGFILE *cfg); -int cfg_get_section(CFGFILE *cfg, char ***buf, const char *section); -CFGFILE *cfg_open(char *filename); -void cfg_rewind(CFGFILE *cfg, int section); -int cfg_is_cfg(CFGFILE *cfg); -int cfg_shldskip_vtoc(int fd, const char *loc); -int cfg_get_srtdsec(CFGFILE *cfg, char ***list, - const char *sec, const char *field); -void cfg_free_section(char ***, int); - - -/* - * Handle cluster configuration - */ -#define FP_SUN_CLUSTER(x) \ - (((x->cf_node) && (x->cf[1].cf_fd)) ? &x->cf[1] : &x->cf[0]) - -/* - * rewind sections - */ -#define CFG_SEC_CONF 0 /* configuration section */ -#define CFG_SEC_PERS 1 /* persistent section */ -#define CFG_SEC_ALL 2 /* rewind both sections */ - -int cfg_update_parser_config(CFGFILE *, const char *key, int section); -/* - * parser sections - */ -#define CFG_PARSE_CONF 0 /* config section key */ -#define CFG_PARSE_PERS 1 /* persistent section key */ - -char *cfg_error(int *severity); -/* - * error codes - */ -#define CFG_ENONFATAL 0 /* non fatal error */ -#define CFG_EFATAL 1 /* fatal error exit */ - -/* - * some error strings - */ -#define CFG_NOTLOCKED "Configuration not locked" -#define CFG_RDFAILED "Unable to read configuration" -#define CFG_EINVAL "Invalid Argument" -#define CFG_EGENERIC "Generic cfg failure" - - -char *cfg_location(char *location, int mode, char *altroot); - -/* - * location modes - */ -#define CFG_LOC_SET_LOCAL 0 -#define CFG_LOC_GET_LOCAL 1 -#define CFG_LOC_SET_CLUSTER 2 -#define CFG_LOC_GET_CLUSTER 3 - -/* - * location strings - */ -#define CFG_LOCAL_LOCATION "/etc/dscfg_local" -#define CFG_CLUSTER_LOCATION "/etc/dscfg_cluster" - -void cfg_close(CFGFILE *); - -/* - * lock mode - */ -typedef enum { - CFG_RDLOCK, - CFG_WRLOCK, - CFG_UPGRADE -} CFGLOCK; - -int cfg_lock(CFGFILE *, CFGLOCK); /* lock the configuration */ -void cfp_unlock(cfp_t *); /* unlock the configuration */ -void cfg_unlock(CFGFILE *); -int cfg_get_lock(CFGFILE *, CFGLOCK *, pid_t *); /* get config lock */ - -int cfg_commit(CFGFILE *); -void cfg_resource(CFGFILE *, const char *); /* Set/clear cluster node */ -char *cfg_get_resource(CFGFILE *); /* get current cluster node */ -char *cfg_dgname(const char *, char *, size_t); /* parse dg from pathname */ -char *cfg_l_dgname(const char *, char *, size_t); /* parse dg from pathname */ -int cfg_dgname_islocal(char *, char **); /* find locality of dg */ -int cfg_iscluster(void); /* running in a cluster? */ -int cfg_issuncluster(void); /* running in a Sun Cluster? */ -void cfg_invalidate_sizes(int); - -/* - * add/rem result codes - */ -#define CFG_USER_ERR 1 -#define CFG_USER_OK 2 -#define CFG_USER_FIRST 3 -#define CFG_USER_LAST 4 -#define CFG_USER_GONE 5 -#define CFG_USER_REPEAT 6 - -int cfg_add_user(CFGFILE *, char *, char *, char *); /* add volume user */ -int cfg_rem_user(CFGFILE *, char *, char *, char *); /* remove vol user */ -int cfg_vol_enable(CFGFILE *, char *, char *, char *); /* enable volume */ -int cfg_vol_disable(CFGFILE *, char *, char *, char *); /* disable volume */ - -int cfg_load_dsvols(CFGFILE *); /* load dsvol: section */ -void cfg_unload_dsvols(); /* unload dsvol: section */ -int cfg_load_svols(CFGFILE *); /* load sv: section */ -void cfg_unload_svols(); /* unload sv: section */ -int cfg_load_shadows(CFGFILE *); /* load shadows & bitmaps from ii: */ -void cfg_unload_shadows(); /* unload ii: */ - -int cfg_get_canonical_name(CFGFILE *, const char *, char **); - -#ifdef __cplusplus -} -#endif - -#endif /* _CFG_H */ diff --git a/usr/src/lib/libdscfg/common/cfg_cluster.c b/usr/src/lib/libdscfg/common/cfg_cluster.c deleted file mode 100644 index c94b12c91e..0000000000 --- a/usr/src/lib/libdscfg/common/cfg_cluster.c +++ /dev/null @@ -1,582 +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. - */ - -/* - * This file contains the glue code that allows the NWS software to - * determine whether a cluster disk service is local to this node or - * not. - * - * See PSARC/1999/462 for more information on the interfaces from - * suncluster that are used here. - */ - -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/mkdev.h> -#include <sys/stat.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <strings.h> -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <dlfcn.h> - -#include <sys/ncall/ncall.h> -#include <sys/nsctl/nsc_hash.h> - -#include "cfg_cluster.h" -#include "cfg_impl.h" -#include "cfg.h" - -/* - * Static variables - */ - -static scconf_nodeid_t cl_nodeid = (uint_t)0xffff; -static char *cl_nodename = NULL; - -static void *libscstat; -static void *libscconf; - -static hash_node_t **schash; -static int init_sc_entry(); - -typedef struct hash_data_s { - scstat_node_name_t scstat_node_name; -} hash_data_t; - -/* - * Global variables - */ -int cl_initialized = 0; - - -/* - * Tell the linker to keep quiet. - */ - -#pragma weak scconf_get_nodename -#pragma weak scconf_strerr -#pragma weak scconf_get_ds_by_devt - -#pragma weak scstat_get_ds_status -#pragma weak scstat_free_ds_status -#pragma weak scstat_strerr - - -/* - * Initialise the library if we have not done so before. - * - * - IMPORTANT - - * - * This must -never- be called from any command that can be started - * from /usr/cluster/lib/sc/run_reserve (and hence - * /usr/cluster/sbin/reconfig) or the system will deadlock - * during switchover. This includes: - * - * - svadm (no options, "print") -- called during sv switchover - * - all boot commands - * - * - grab this node's cluster nodeid - * - attempt to dlopen() the suncluster shared libraries we need - * - grab this node's cluster nodename - * - * Returns: - * 0 - success - * -1 - error, errno is set - */ - -int -cfg_cluster_init(void) -{ - const char *scconf = "/usr/cluster/lib/libscconf.so.1"; - const char *scstat = "/usr/cluster/lib/libscstat.so.1"; -#ifdef DEBUG - char errbuf[SCCONF_MAXSTRINGLEN]; -#endif - scconf_nodeid_t id; - scconf_errno_t err; - char *name; - FILE *pipe; - int rc; - - /* - * First check to see if we really are a cluster as clinfo -n can lie - */ - if (cl_nodeid == 0xffff) { - rc = system("/usr/sbin/clinfo"); - if (rc != -1 && WEXITSTATUS(rc) == 1) { - /* not a cluster */ - cl_initialized = 1; - cl_nodeid = 0; - return (0); - } - - pipe = popen("/usr/sbin/clinfo -n 2>/dev/null || echo 0", "r"); - if (pipe == NULL) { -#ifdef DEBUG - fprintf(stderr, "unable to get nodeid: %s\n", - strerror(errno)); -#endif - return (-1); - } - - if ((rc = fscanf(pipe, "%d", &id)) != 1) { -#ifdef DEBUG - fprintf(stderr, "unable to get nodeid: %s\n", - strerror(errno)); -#endif - return (-1); - } - - pclose(pipe); - - cl_nodeid = id; - } - - /* Already loaded the Sun Cluster device tree */ - if (cl_initialized) - return (0); - - /* - * Try and dlopen the various libraries that we need - */ - - libscconf = dlopen(scconf, RTLD_LAZY | RTLD_GLOBAL); - if (libscconf == NULL) - goto error; - - libscstat = dlopen(scstat, RTLD_LAZY | RTLD_GLOBAL); - if (libscstat == NULL) - goto error; - - err = scconf_get_nodename(id, &name); - if (err == SCCONF_EPERM) { - cl_nodename = NULL; - } else if (err != SCCONF_NOERR) { -#ifdef DEBUG - scconf_strerr(errbuf, err); - fprintf(stderr, "scconf_get_nodename: %d: %s\n", err, errbuf); -#endif - goto error; - } else - cl_nodename = name; - - /* Load the Sun Cluster device tree */ - init_sc_entry(); - cl_initialized = 1; - return (0); - -error: /* error cleanup */ - if (libscconf) - dlclose(libscconf); - - if (libscstat) - dlclose(libscstat); - - libscconf = NULL; - libscstat = NULL; - - errno = ENOSYS; - return (-1); -} - - -/* - * cfg_issuncluster() - * - * Description: - * Return the SunCluster nodeid of this node. - * - * Returns: - * >0 - running in a SunCluster (value is nodeid of this node) - * 0 - not running in a cluster - * -1 - failure; errno is set - */ - -int -cfg_issuncluster() -{ - if (cfg_cluster_init() >= 0) - return ((int)cl_nodeid); - else - return (-1); -} -int -cfg_iscluster() -{ - return (cfg_issuncluster()); -} - -/* - * cfg_l_dgname_islocal() - * Check if disk group is local on a non-SunCluster. - * - * Returns as cfg_dgname_islocal(). - */ -#ifndef lint -static int -cfg_l_dgname_islocal(char *dgname, char **othernode) -{ - const char *metaset = "/usr/sbin/metaset -s %s -o > /dev/null 2>&1"; - char command[1024]; - int rc; - - if (snprintf(command, sizeof (command), metaset, dgname) >= - sizeof (command)) { - errno = ENOMEM; - return (-1); - } - - rc = system(command); - if (rc < 0) { - return (-1); - } - - if (WEXITSTATUS(rc) != 0) { - if (othernode) { - /* metaset doesn't tell us */ - *othernode = "unknown"; - } - - return (0); - } - - return (1); -} -#endif - -/* - * cfg_dgname_islocal(char *dgname, char **othernode) - * -- determine if the named disk service is mastered on this node - * - * If the disk service is mastered on another node, that nodename - * will be returned in othernode (if not NULL). It is up to the - * calling program to call free() on this value at a later time to - * free the memory allocated. - * - * Returns: - * 1 - disk service is mastered on this node - * 0 - disk service is not mastered on this node (*othernode set) - * -1 - error (errno will be set) - */ - -int -cfg_dgname_islocal(char *dgname, char **othernode) -{ - hash_data_t *data; - - if (dgname == NULL || *dgname == '\0' || othernode == NULL) { - errno = EINVAL; - return (-1); - } - - /* Handle non-cluster configurations */ - if (cfg_cluster_init() < 0) { - return (-1); - } else if (cl_nodeid == 0) { - /* it has to be local */ - return (1); - } - - /* - * lookup the current diskgroup name - */ - if (data = (hash_data_t *)nsc_lookup(schash, dgname)) { - if (strcmp(data->scstat_node_name, cl_nodename)) { - if (othernode) - *othernode = strdup(data->scstat_node_name); - return (0); - } else { - return (1); - } - } else { - errno = ENODEV; - return (-1); - } -} - -/* - * cfg_l_dgname() - * parse the disk group name from the a device pathname on a non-SunCluster. - * - * Returns as cfg_dgname(). - */ - -char * -cfg_l_dgname(const char *pathname, char *buffer, size_t buflen) -{ - const char *dev = "/dev/"; - const char *vx = "vx/"; - const char *md = "md/"; - const char *dsk = "dsk/"; - const char *start, *cp; - int ll, len, chkdsk; - - bzero(buffer, buflen); - chkdsk = 0; - - ll = strlen(dev); - if (strncmp(pathname, dev, ll) != 0) { - /* not a device pathname */ - errno = EINVAL; - return ((char *)NULL); - } - - start = pathname + ll; - - if (strncmp(start, vx, (ll = strlen(vx))) == 0) { - /* - * Veritas -- - * /dev/vx/{r}dsk/dgname/partition - */ - - start += ll; - - ll = strlen(dsk); - - if (*start == 'r' && strncmp((start + 1), dsk, ll) == 0) - start += ll + 1; - else if (strncmp(start, dsk, ll) == 0) - start += ll; - else { - /* no dgname */ - return (buffer); - } - } else { - /* no dgname */ - return (buffer); - } - - for (cp = start, len = 0; *cp != '\0' && *cp != '/'; cp++) - len++; /* count length of dgname */ - - if (*cp == '\0') { - /* no dgname */ - return (buffer); - } - -#ifdef DEBUG - if (*cp != '/') { - fprintf(stderr, - "cfg_dgname: parse error: *cp = '%c', expected '/'\n", *cp); - errno = EPROTO; - return ((char *)NULL); - } -#endif - - if (chkdsk) { - cp++; /* skip the NULL */ - - ll = strlen(dsk); - - if ((*cp != 'r' || strncmp((cp + 1), dsk, ll) != 0) && - strncmp(cp, dsk, ll) != 0) { - /* no dgname */ - return (buffer); - } - } - - if (len >= buflen) { - errno = E2BIG; - return ((char *)NULL); - } - - (void) strncpy(buffer, start, len); - return (buffer); -} - - -/* - * cfg_dgname() - * determine which cluster resource group the pathname belongs to, if any - * - * Returns: - * NULL - error (errno is set) - * ptr to NULL-string - no dgname - * pointer to string - dgname - */ - -char * -cfg_dgname(const char *pathname, char *buffer, size_t buflen) -{ - scconf_errno_t conferr; - char *dsname = NULL; - struct stat stb; -#ifdef DEBUG - char errbuf[SCCONF_MAXSTRINGLEN]; -#endif - - bzero(buffer, buflen); - - if (pathname == NULL || *pathname == '\0') { - errno = EINVAL; - return ((char *)NULL); - } - - /* Handle non-cluster configurations */ - if (cfg_cluster_init() < 0) { - errno = EINVAL; - return ((char *)NULL); - } else if (cl_nodeid == 0) { - /* must be local - return NULL-string dgname */ - return (buffer); - } - - if (stat(pathname, &stb) < 0) { - errno = EINVAL; - return ((char *)NULL); - } - - conferr = scconf_get_ds_by_devt(major(stb.st_rdev), - minor(stb.st_rdev), &dsname); - - if (conferr == SCCONF_ENOEXIST) { - return (buffer); - } else if (conferr != SCCONF_NOERR) { -#ifdef DEBUG - scconf_strerr(errbuf, conferr); - fprintf(stderr, - "scconf_get_ds_by_devt: %d: %s\n", conferr, errbuf); -#endif - errno = EINVAL; - return ((char *)NULL); - } - - strncpy(buffer, dsname, buflen); - free(dsname); - - return (buffer); -} - - -/* - * init_sc_entry - * - * Add an entry into the sclist and the schash for future lookups. - * - * - IMPORTANT - - * - * This must -never- be called from any command that can be started - * from /usr/cluster/lib/sc/run_reserve (and hence - * /usr/cluster/sbin/reconfig) or the system will deadlock - * during switchover. This includes: - * - * - svadm (no options, "print") -- called during sv switchover - * - all boot commands - * - * Return values: - * -1 An error occurred. - * 0 Entry added - * 1 Entry already exists. - */ -static int -init_sc_entry() -{ - scstat_ds_node_state_t *dsn; - scstat_ds_name_t dsname; - scstat_ds_t *dsstatus, *dsp; - scstat_errno_t err; -#ifdef DEBUG - char errbuf[SCCONF_MAXSTRINGLEN]; -#endif - - hash_data_t *hdp; - - /* - * Allocate a hash table - */ - if ((schash = nsc_create_hash()) == NULL) - return (-1); - - /* - * the API is broken here - the function is written to expect - * the first argument to be (scstat_ds_name_t), but the function - * declaration in scstat.h requires (scstat_ds_name_t *). - * - * We just cast it to get rid of the compiler warnings. - * If "dsname" is NULL, information for all device services is returned - */ - dsstatus = NULL; - dsname = NULL; - /* LINTED pointer alignment */ - err = scstat_get_ds_status((scstat_ds_name_t *)dsname, &dsstatus); - if (err != SCSTAT_ENOERR) { -#ifdef DEBUG - scstat_strerr(err, errbuf); - fprintf(stderr, "scstat_get_ds_status(): %d: %s\n", - err, errbuf); -#endif - errno = ENOSYS; - return (-1); - } - - if (dsstatus == NULL) { - errno = ENODEV; - return (-1); - } - - /* - * Traverse scstat_ds list, saving away resource in out hash table - */ - for (dsp = dsstatus; dsp; dsp = dsp->scstat_ds_next) { - - /* Skip over NULL scstat_ds_name's */ - if ((dsp->scstat_ds_name == NULL) || - (dsp->scstat_ds_name[0] == '\0')) - continue; - - /* See element exits already, error if so */ - if (nsc_lookup(schash, dsp->scstat_ds_name)) { - fprintf(stderr, "scstat_get_ds_status: duplicate %s", - dsp->scstat_ds_name); - errno = EEXIST; - return (-1); - } - - /* Traverse the node status list */ - for (dsn = dsp->scstat_node_state_list; dsn; - dsn = dsn->scstat_node_next) { - /* - * Only keep trace of primary nodes - */ - if (dsn->scstat_node_state != SCSTAT_PRIMARY) - continue; - - /* Create an element to insert */ - hdp = (hash_data_t *)malloc(sizeof (hash_data_t)); - hdp->scstat_node_name = strdup(dsn->scstat_node_name); - nsc_insert_node(schash, hdp, dsp->scstat_ds_name); - } - } - - /* - * Free up scstat resources - */ - scstat_free_ds_status(dsstatus); - return (0); -} diff --git a/usr/src/lib/libdscfg/common/cfg_cluster.h b/usr/src/lib/libdscfg/common/cfg_cluster.h deleted file mode 100644 index 56f07219f7..0000000000 --- a/usr/src/lib/libdscfg/common/cfg_cluster.h +++ /dev/null @@ -1,344 +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. - */ - -#ifndef _CFG_CLUSTER_H -#define _CFG_CLUSTER_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * This file is a combination of interfaces culled from scstat.h, - * scconf.h and the header files that they include. - * - * It exposes a subset of the interfaces defined in PSARC/2001/261 - * for use in NWS software. - */ - -#include <sys/errno.h> -#include <sys/types.h> - -/* - * From sc_syslog_msg.h - */ - -typedef enum sc_state_code_enum { - ONLINE = 1, /* resource is running */ - OFFLINE, /* resource is stopped due to user action */ - FAULTED, /* resource is stopped due to a failure */ - DEGRADED, /* resource is running but has a minor problem */ - WAIT, /* resource is in transition from a state to another */ - - /* - * resource is monitored but state of the resource is - * not known because either the monitor went down or - * the monitor cannot report resource state temporarily. - */ - UNKNOWN, - - NOT_MONITORED /* There is no monitor to check state of the resource */ -} sc_state_code_t; - -/* - * End sc_syslog_msg.h - */ - - -/* - * From scstat.h - */ - -#define SCSTAT_MAX_STRING_LEN 1024 - -/* Error codes returned by scstat functions. */ -/* This definition is covered by PSARC/2001/261. DO NOT change it. */ -typedef enum scstat_errno { - SCSTAT_ENOERR, /* normal return - no error */ - SCSTAT_EUSAGE, /* syntax error */ - SCSTAT_ENOMEM, /* not enough memory */ - SCSTAT_ENOTCLUSTER, /* not a cluster node */ - SCSTAT_ENOTCONFIGURED, /* not found in CCR */ - SCSTAT_ESERVICENAME, /* dcs: invalid service name */ - SCSTAT_EINVAL, /* scconf: invalid argument */ - SCSTAT_EPERM, /* not root */ - SCSTAT_ECLUSTERRECONFIG, /* cluster is reconfiguring */ - SCSTAT_ERGRECONFIG, /* RG is reconfiguring */ - SCSTAT_EOBSOLETE, /* Resource/RG has been updated */ - SCSTAT_EUNEXPECTED /* internal or unexpected error */ -} scstat_errno_t; - -/* States a resource can be in */ -/* This definition is covered by PSARC/2001/261. DO NOT change it. */ -typedef enum scstat_state_code { - SCSTAT_ONLINE = ONLINE, /* resource is running */ - SCSTAT_OFFLINE = OFFLINE, /* resource stopped due to user action */ - SCSTAT_FAULTED = FAULTED, /* resource stopped due to a failure */ - SCSTAT_DEGRADED = DEGRADED, /* resource running with a minor problem */ - SCSTAT_WAIT = WAIT, /* resource is in transition */ - SCSTAT_UNKNOWN = UNKNOWN, /* resource state is unknown */ - SCSTAT_NOTMONITORED = NOT_MONITORED /* resource is not monitored */ -} scstat_state_code_t; - -/* States a replica of a resource can be in */ -/* This definition is covered by PSARC/2001/261. DO NOT change it. */ -typedef enum scstat_node_pref { - SCSTAT_PRIMARY, /* replica is a primary */ - SCSTAT_SECONDARY, /* replica is a secondary */ - SCSTAT_SPARE, /* replica is a spare */ - SCSTAT_INACTIVE, /* replica is inactive */ - SCSTAT_TRANSITION, /* replica is changing state */ - SCSTAT_INVALID /* replica is in an invalid state */ -} scstat_node_pref_t; - -/* component name */ -typedef char *scstat_name_t; -typedef scstat_name_t scstat_cluster_name_t; /* cluster name */ -typedef scstat_name_t scstat_node_name_t; /* node name */ -typedef scstat_name_t scstat_adapter_name_t; /* adapter name */ -typedef scstat_name_t scstat_path_name_t; /* path name */ -typedef scstat_name_t scstat_ds_name_t; /* device service name */ -typedef scstat_name_t scstat_quorumdev_name_t; /* quorum device name */ -typedef scstat_name_t scstat_rs_name_t; /* resource name */ -typedef scstat_name_t scstat_rg_name_t; /* rg name */ - -/* status string */ -typedef char *scstat_statstr_t; -typedef scstat_statstr_t scstat_node_statstr_t; /* node status */ -typedef scstat_statstr_t scstat_path_statstr_t; /* path status */ -typedef scstat_statstr_t scstat_ds_statstr_t; /* DS status */ -typedef scstat_statstr_t scstat_node_quorum_statstr_t; /* node quorum status */ -typedef scstat_statstr_t scstat_quorumdev_statstr_t; /* quorum device stat */ - -/* ha device node status list */ -/* This definition is covered by PSARC/2001/261. DO NOT change it. */ -typedef struct scstat_ds_node_state_struct { - /* node name */ - scstat_node_name_t scstat_node_name; - /* node status */ - scstat_node_pref_t scstat_node_state; - /* next */ - struct scstat_ds_node_state_struct *scstat_node_next; -} scstat_ds_node_state_t; - -/* Cluster node status */ -/* This definition is covered by PSARC/2001/261. DO NOT change it. */ -typedef struct scstat_node_struct { - scstat_node_name_t scstat_node_name; /* node name */ - scstat_state_code_t scstat_node_status; /* cluster membership */ - scstat_node_statstr_t scstat_node_statstr; /* node status string */ - void *pad; /* Padding for */ - /* PSARC/2001/261. */ - struct scstat_node_struct *scstat_node_next; /* next */ -} scstat_node_t; - -/* Cluster ha device status */ -/* This definition is covered by PSARC/2001/261. DO NOT change it. */ -typedef struct scstat_ds_struct { - /* ha device name */ - scstat_ds_name_t scstat_ds_name; - /* ha device status */ - scstat_state_code_t scstat_ds_status; - /* ha device statstr */ - scstat_ds_statstr_t scstat_ds_statstr; - /* node preference list */ - scstat_ds_node_state_t *scstat_node_state_list; - /* next */ - struct scstat_ds_struct *scstat_ds_next; -} scstat_ds_t; - -/* - * scstat_strerr - * - * Map scstat_errno_t to a string. - * - * The supplied "errbuffer" should be of at least SCSTAT_MAX_STRING_LEN - * in length. - */ -/* This definition is covered by PSARC/2001/261. DO NOT change it. */ -void scstat_strerr(scstat_errno_t, char *); - -/* - * Upon success, a list of objects of scstat_node_t are returned. - * The caller is responsible for freeing the space. - * - * Possible return values: - * - * SCSTAT_NOERR - success - * SCSTAT_ENOMEM - not enough memory - * SCSTAT_EPERM - not root - * SCSTAT_ENOTCLUSTER - there is no cluster - * SCCONF_EINVAL - invalid argument - * SCSTAT_EUNEXPECTED - internal or unexpected error - */ -/* This definition is covered by PSARC/2001/261. DO NOT change it. */ -scstat_errno_t scstat_get_nodes(scstat_node_t **pplnodes); - -/* - * Free all memory associated with a scstat_node_t structure. - */ -/* This definition is covered by PSARC/2001/261. DO NOT change it. */ -void scstat_free_nodes(scstat_node_t *plnodes); - -/* - * If the device service name passed in is NULL, then this function returns - * the status of all device services, otherwise it returns the status of the - * device service specified. - * The caller is responsible for freeing the space. - * - * Possible return values: - * - * SCSTAT_ENOERR - success - * SCSTAT_ENOMEM - not enough memory - * SCSTAT_EPERM - not root - * SCSTAT_ENOTCLUSTER - there is no cluster - * SCCONF_EINVAL - invalid argument - * SCSTAT_ESERVICENAME - invalid device group name - * SCSTAT_EUNEXPECTED - internal or unexpected error - */ -/* This definition is covered by PSARC/2001/261. DO NOT change it. */ -scstat_errno_t scstat_get_ds_status(scstat_ds_name_t *dsname, - scstat_ds_t **dsstatus); - -/* - * Free memory associated with a scstat_ds_t structure. - */ -/* This definition is covered by PSARC/2001/261. DO NOT change it. */ -void scstat_free_ds_status(scstat_ds_t *dsstatus); - -/* - * End scstat.h - */ - -/* - * From scconf.h - */ - -/* Maximum message string length */ -#define SCCONF_MAXSTRINGLEN 1024 - -/* This definition is covered by PSARC/2001/261. DO NOT change it. */ -typedef enum scconf_errno { - SCCONF_NOERR = 0, /* normal return - no error */ - SCCONF_EPERM = 1, /* permission denied */ - SCCONF_EEXIST = 2, /* object already exists */ - SCCONF_ENOEXIST = 3, /* object does not exist */ - SCCONF_ESTALE = 4, /* object or handle is stale */ - SCCONF_EUNKNOWN = 5, /* unkown type */ - SCCONF_ENOCLUSTER = 6, /* cluster does not exist */ - SCCONF_ENODEID = 7, /* ID used in place of node name */ - SCCONF_EINVAL = 8, /* invalid argument */ - SCCONF_EUSAGE = 9, /* command usage error */ - SCCONF_ETIMEDOUT = 10, /* call timed out */ - SCCONF_EINUSE = 11, /* already in use */ - SCCONF_EBUSY = 12, /* busy, try again later */ - SCCONF_EINSTALLMODE = 13, /* install mode */ - SCCONF_ENOMEM = 14, /* not enough memory */ - SCCONF_ESETUP = 15, /* setup attempt failed */ - SCCONF_EUNEXPECTED = 16, /* internal or unexpected error */ - SCCONF_EBADVALUE = 17, /* bad ccr table value */ - SCCONF_EOVERFLOW = 18, /* message buffer overflow */ - SCCONF_EQUORUM = 19, /* operation would compromise quorum */ - SCCONF_TM_EBADOPTS = 20, /* bad transport TM "options" */ - SCCONF_TM_EINVAL = 21, /* other transport TM error */ - SCCONF_DS_ESUSPENDED = 22, /* Device service in suspended state */ - SCCONF_DS_ENODEINVAL = 23, /* Node specified is not in cluster */ - SCCONF_EAUTH = 24, /* authentication error */ - SCCONF_DS_EINVAL = 25, /* Device service in an invalid state */ - SCCONF_EIO = 26 /* IO error */ -} scconf_errno_t; - -/* IDs */ -/* This definition is covered by PSARC/2001/261. DO NOT change it. */ -typedef uint_t scconf_id_t; - -/* This definition is covered by PSARC/2001/261. DO NOT change it. */ -typedef scconf_id_t scconf_nodeid_t; /* node ID */ - -/* Cluster transport handle */ -/* This definition is covered by PSARC/2001/261. DO NOT change it. */ -typedef void * scconf_cltr_handle_t; - -/* This definition is covered by PSARC/2001/261. DO NOT change it. */ -extern scconf_errno_t scconf_get_nodeid(char *nodename, - scconf_nodeid_t *nodeidp); - -/* - * Get the name of a node from its "nodeid". Upon success, - * a pointer to the nodename is left in "nodenamep". - * - * It is the caller's responsibility to free memory allocated - * for "nodename" using free(3C). - * - * Possible return values: - * - * SCCONF_NOERR - success - * SCCONF_EPERM - not root - * SCCONF_ENOCLUSTER - there is no cluster - * SCCONF_ENOMEM - not enough memory - * SCCONF_EINVAL - invalid argument - * SCCONF_EUNEXPECTED - internal or unexpected error - */ -/* This definition is covered by PSARC/2001/261. DO NOT change it. */ -extern scconf_errno_t scconf_get_nodename(scconf_nodeid_t nodeid, - char **nodenamep); - -/* - * Map scconf_errno_t to a string. - * - * The supplied "errbuffer" should be of at least SCCONF_MAXSTRINGLEN - * in length. - */ -/* This definition is covered by PSARC/2001/261. DO NOT change it. */ -extern void scconf_strerr(char *errbuffer, scconf_errno_t err); - -/* - * Given a dev_t value, return the name of device service that contains this - * device. - * - * The caller is responsible for freeing the memory returned in "name". - * - * Possible return values: - * - * SCCONF_NOERR - success - * SCCONF_EPERM - not root - * SCCONF_ENOEXIST - the given device is not configured - * SCCONF_ENOMEM - not enough memory - * SCCONF_ENOCLUSTER - cluster config does not exist - * SCCONF_EUNEXPECTED - internal or unexpected error - */ -/* This definition is covered by PSARC/2001/261. DO NOT change it. */ -extern scconf_errno_t scconf_get_ds_by_devt(major_t maj, minor_t min, - char **dsname); - -/* - * End scconf.h - */ - -#ifdef __cplusplus -} -#endif - -#endif /* _CFG_CLUSTER_H */ diff --git a/usr/src/lib/libdscfg/common/cfg_impl.h b/usr/src/lib/libdscfg/common/cfg_impl.h deleted file mode 100644 index a972b2525f..0000000000 --- a/usr/src/lib/libdscfg/common/cfg_impl.h +++ /dev/null @@ -1,247 +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. - */ - -#ifndef _CFG_IMPL_H -#define _CFG_IMPL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define MAX_CFG 16 /* Max. number of lines in /etc/dscfg_format */ - -#define CFG_MAX_KEY 256 -#define CFG_MAX_BUF 1024 -#define CFG_BLOCK_SIZE 512 -#define CFG_VTOC_SIZE 16 -#define CFG_VTOC_SKIP CFG_VTOC_SIZE * CFG_BLOCK_SIZE - -/* - * Parser and file handling routines for Configuration parser. - * - * General layout on disk - * - * header cfgheader_t - * parser configuration tag.field1.field2\n - * configuration data copy1 freeform strings - * configuration data copy2 freeform strings - * - * Strings in freeform fields are seperated by whitespace. - * End of entry seperated by null. - */ - -struct lookup { - char l_word[CFG_MAX_KEY]; - int l_value; - struct lookup *l_next; -}; - -struct parser { - struct lookup tag; - struct lookup *fld; - struct parser *next; -}; - - -/* - * cfglist description - * - * ________ - * | | the header has (with other things) an array - * | header | of h_cfg[n].l_size entries. index 4 - * disk layout | | contains cfp->cf_head->h_cfg[4].l_size. - * |________| - * cfgfile-mapped->| | - * CFG_DEFAULT_PARSE_SIZE | parser | cache_hint.device.wrthru.nordcache.cnode - * | | - * |________| - * cfp->cf_head->h_ccopy1>| | - * CFG_DEFAULT_SSIZE | data | null terminated strings grouped together - * | copy 1 | in order of cfglist offset. ie data at - * |________| offset 0 is from h_cfgs[0].l_entry - * cfp->cf_head->h_ccopy2>| | - * CFG_DEFAULT_SSIZE | data | - * | copy 2 | same as above, used for two stage commit - * |________| - * cfp->cf_head->h_sizes1>| | here is where lists of sizes go for each - * CFG_DEFAULT_PSIZE | sizes | cfglist. each array is preceded by the num - * | copy 1 | of entries. |5|120|130|140|103|125|10|25 is - * |________| a list with 5 entries 120,130,140,103,125 - * cfp->cf_head->h_sizes2>| | these numbers are used to rebuild l_nentry - * CFG_DEFAULT_PSIZE | sizes | and l_esiz fields in h_cfg[n] - * | copy 2 | this list is done as a two stage commit - * |________| - * - * - * - * Data is read into cfp->cf_head->h_ccopy1 and cfp->cf_head->h_ccopy2 - * along with thier corresponding size metadata in cfp->cf_head->h_sizes1 - * and cfp->cf_head->h_sizes2. This infomation is used to rebuild the - * cfglist structures seen below. The data in the cfglist structure is then - * the ONLY valid data. Additions and/or deletions to the database is done - * by moving around the cfglists and doing the right things with the size - * arrays, the actual entries, total list sizes, the total of all the sizes of - * all the cfglists and memory allocation. After addition/deletions are done, - * and cfg_close is called, all of the lists are placed back into h_cparse - * (which is really h_ccopy1 or h_ccopy2) the persistent lists are placed - * into h_sizes (which is really h_sizes1 or h_sizes2). - * A copy of each cfglist[n].l_size is kept in the header - * (cfgheader->cfgsizes[n]). - * - * - * - * - * h_cfgs h_cfgs[3] - * head |-[0]- /|-l_name == sndr - * |- /|-[1]- / |-l_entry == host dev bmap host..ip sync '\0' ... - * file |- / |-[2]- / |-l_esiz[0..l_nentry - 1] == [130, 132, 135, 133,..] - * |--|---------|-[3]---- |-l_enabled[0..l_nentry - 1] == [1,0,0,1,1] - * |- \ |-[4]- \ |-l_nentry == 5 - * |- \|-[5]- \ |-l_index == 3 - * |-[n]- \|-l_free == 50537 - * |-l_size == 663 (130 + 132 + 135 + 133 + 133) - * - * - * - * l_name - is set when the parser is read. - * It is the first tag of a line of parser text. - * l_entry - is a pointer to the beginning of the null terminated string - * list that belongs to the cfglist tagged with l_name. - * l_esiz - is a list of sizes of the strings contained in l_entry. - * l_esiz[0] tells the size of the string at l_entry[0]. - * l_esiz[n] is the size of the string that begins - * at l_entry + l_esiz[0] + l_esiz[1]..+ l_esize[n - 1] - * l_enabled - is a list of ones and zeros telling if this entry is alive - * in the kernel. indexing is the same as l_esiz. (not implemented) - * l_index - is the index of the parser tree that corresponds to l_name - * and is set when the parser tree is built - * l_free - is how memory is managed. Memory is allocated on a - * DEFAULT_ENTRY_SIZE boundry. - * the size of the balance of available memory at the end of l_entry - * is kept here. when this number is lower than the string we need to add, - * another block of memory is allocated for l_entry and the balance of - * the size is added to l_free. - * l_size - is size of this list. It is the summation of l_esiz[0..n] - * - */ - -typedef struct cfglist { - char *l_name; /* name of list sndr, ii.. */ - char *l_entry; /* start of list */ - int *l_esiz; /* array of sizes of entries */ - int l_nentry; /* number of entries */ - int l_index; /* index in relation to parser position */ - uint_t l_free; /* num of characters available */ - int l_size; /* size of list */ -} cfglist_t; - -/* note: this does not imply DEFAULT_NENTRIES * DEFAULT_ENTRY_SIZE */ -#define DEFAULT_NENTRIES 100 /* value for l_esiz sizes array */ -#define DEFAULT_ENTRY_SIZE (50 * CFG_MAX_BUF) /* 50K for each l_entry */ - - -typedef struct cfgheader { - int32_t h_magic; - int h_state; /* State flag see below */ - time_t h_stamp; /* time stamp of last update */ - long h_lock; /* lock for update */ - long h_size; /* total file size */ - int h_parseoff; /* parser config offset */ - int h_parsesize; /* parser config size */ - char *h_cparse; /* start of configuration */ - int h_csize; /* size of config section */ - int h_acsize; /* size of alternate config section */ - int *h_sizes; /* sizes of lists */ - int h_psize; /* size of persistent section */ - int h_apsize; /* size of alternate persistent section */ - char *h_ccopy1; /* base of config section 1 */ - char *h_ccopy2; /* base of config section 2 */ - int *h_sizes1; /* sizes of lists on disk 1 */ - int *h_sizes2; /* sizes of lists on disk 2 */ - int h_seq1; /* Sequenece number copy 1 both sections */ - int h_seq2; /* Sequenece number copy 2 both sections */ - char h_ncfgs; /* number of cfgs */ - cfglist_t *h_cfgs; /* start of cfg lists */ - int h_cfgsizes[MAX_CFG]; /* Sizes of configs */ -} cfgheader_t; - -#define CFG_HDR_GOOD 0x1 -#define CFG_HDR_INVALID 0x2 -#define CFG_HDR_RDLOCK 0x4 -#define CFG_HDR_WRLOCK 0x8 - -struct cfg_io_s; /* forward reference */ -typedef struct cfp { - int cf_fd; /* file descriptor */ - int cf_flag; /* flags - see below */ - long cf_size; /* size of file in fbas */ - int cf_lock; /* lock file descriptor */ - char *cf_mapped; /* mapped location via mmap */ - char *cf_name; /* file name */ - cfgheader_t *cf_head; /* header */ - struct cfg_io_s *cf_pp; /* i/o provider */ -} cfp_t; - -typedef struct cfgfile { - void *cf_node; /* node filter */ - cfp_t cf[2]; /* local & optional cluster file */ -} CFGFILE; - -typedef struct cfg_io_s { - struct cfg_io_s *next; /* Link to next module */ - char *name; /* name of provider */ - cfp_t *(*open)(cfp_t *, char *); /* Open device */ - void (*close)(cfp_t *); /* Close device */ - int (*seek)(cfp_t *, int, int); /* Seek */ - int (*read)(cfp_t *, void *, int); /* read */ - int (*write)(cfp_t *, void *, int); /* write */ - char *(*readcf)(cfp_t *, char *, int, int); /* Read mem config */ - int (*addcf)(cfp_t *, char *, int); /* add to mem config */ - int (*remcf)(cfp_t *, int, int); /* remove an entry */ - int (*replacecf)(cfp_t *, char *, int, int); /* replace entry */ -} cfg_io_t; - -#define CFG_FILE 0x1 /* database is in a regular file */ -#define CFG_NOREWIND 0x4 /* don't rewind for each get_string */ -#define CFG_NOWRVTOC 0x8 /* sector starts in vtoc land, skip it */ -#define CFG_RDONLY 0x10 /* database is read only */ - -/* - * constants - */ -#define CFG_RDEV_LOCKFILE "/var/tmp/.dscfg.lck" -#define CFG_NEW_MAGIC 0x4d414749 /* MAGI */ -#define CFG_DEFAULT_PARSE_SIZE (16 * 1024) -#define CFG_DEFAULT_SSIZE (2 * 1024 * 1024) -#define CFG_DEFAULT_PSIZE (512 * 1024) -#define CFG_DEFAULT_OLDSIZE (96 * 1024) -#define CFG_CONFIG_SIZE (CFG_DEFAULT_PARSE_SIZE + \ - (2 * CFG_DEFAULT_SSIZE) + \ - (2 * CFG_DEFAULT_PSIZE)) -#ifdef __cplusplus -} -#endif - -#endif /* _CFG_IMPL_H */ diff --git a/usr/src/lib/libdscfg/common/cfg_local.c b/usr/src/lib/libdscfg/common/cfg_local.c deleted file mode 100644 index 1b243b1a6d..0000000000 --- a/usr/src/lib/libdscfg/common/cfg_local.c +++ /dev/null @@ -1,653 +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/vtoc.h> -#include <sys/wait.h> -#include <stdio.h> -#include <sys/mnttab.h> -#include <errno.h> -#include <limits.h> -#include <fcntl.h> -#include <string.h> -#include <strings.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/mman.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_local.h" - -#if 0 -#define DEBUG_CFGLIST -#define DEBUG_CFGLISTRM -#endif - -extern int cfg_severity; -extern char *cfg_perror_str; - -long -get_bsize(cfp_t *cfp, char *name) -{ - char char_name[PATH_MAX]; - char *rest; - struct vtoc vtoc; - int slice; - int fd; - - if (strlen(name) >= PATH_MAX - 1) - return (0); - - rest = strstr(name, "/dsk/"); - if (rest == NULL) { - if ((rest = strstr(name, "/rdsk/")) == NULL) - return (0); - strcpy(char_name, name); - goto do_open; - - } - strcpy(char_name, name); - char_name[strlen(name) - strlen(rest)] = 0; - strcat(char_name, "/rdsk/"); - strcat(char_name, rest + 5); - -do_open: - fd = open(char_name, O_RDONLY); - if (fd < 0) - return (0); - - slice = read_vtoc(fd, &vtoc); - if (slice < 0) { - (void) close(fd); - return (0); - } - - (void) close(fd); - if (vtoc.v_part[slice].p_start < CFG_VTOC_SIZE) - cfp->cf_flag |= CFG_NOWRVTOC; - - return (vtoc.v_part[slice].p_size); -} - -/* - * round up to the next block size - */ -int -get_block_size(int size) -{ - int ret; - - if (size % CFG_BLOCK_SIZE != 0) - ret = size + CFG_BLOCK_SIZE - (size % CFG_BLOCK_SIZE); - else - ret = size; - return (ret); -} - -/* - * get a chunk of mem rounded up to next block size - */ -char * -get_block_buf(int size) -{ - int blk_size; - char *blk_buf; - - blk_size = get_block_size(size); - - if ((blk_buf = (char *)calloc(blk_size, sizeof (char))) == NULL) { - cfg_severity = CFG_EFATAL; - cfg_perror_str = dgettext("cfg", strerror(errno)); - return (NULL); - } - return (blk_buf); -} - -void -free_block_buf(char *buf) -{ - if (buf) - free(buf); -} - -void -localcf_close(cfp_t *cfp) -{ - fsync(cfp->cf_fd); - cfp_unlock(cfp); - close(cfp->cf_fd); -} - - -/* - * cfg_open - * Open the current configuration file - * Sets file descriptor in cfp->cf_fd for use by other routines - */ -cfp_t * -localcf_open(cfp_t *cfp, char *name) -{ - struct stat sb; - int rc; - - - if (name == NULL) { - cfg_perror_str = dgettext("cfg", - "cfg_open: unable to open configuration location"); - cfg_severity = CFG_EFATAL; - return (NULL); - } - - cfp->cf_fd = open(name, O_RDWR|O_CREAT|O_DSYNC|O_RSYNC, 0640); - if (cfp->cf_fd == -1) { - if ((cfp->cf_fd = open(name, O_RDONLY, 0640)) == -1) { - cfg_perror_str = dgettext("cfg", - "cfg_open: unable to open configuration location"); - cfg_severity = CFG_EFATAL; - return (NULL); - } - cfp->cf_flag |= CFG_RDONLY; - } - - if (fstat(cfp->cf_fd, &sb) == -1) { - close(cfp->cf_fd); - cfg_perror_str = dgettext("cfg", - "cfg_open: unable to stat configuration location"); - cfg_severity = CFG_EFATAL; - return (NULL); - } - - - if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode)) { - cfp->cf_size = get_bsize(cfp, name); - - /* skip the vtoc if necessary */ - if (cfp->cf_flag & CFG_NOWRVTOC) { - do { - rc = lseek(cfp->cf_fd, CFG_VTOC_SKIP, SEEK_SET); - } while (rc == -1 && errno == EINTR); - - if (rc == -1) { - cfg_perror_str = dgettext("cfg", - strerror(errno)); - cfg_severity = CFG_EFATAL; - close(cfp->cf_fd); - return (NULL); - } - } - - } else if (S_ISREG(sb.st_mode)) { - cfp->cf_flag |= CFG_FILE; - cfp->cf_size = FBA_NUM(FBA_SIZE(1) - 1 + sb.st_size); - } else { - cfg_perror_str = dgettext("cfg", "cfg_open: unknown file type"); - cfg_severity = CFG_EFATAL; - close(cfp->cf_fd); - cfp->cf_fd = NULL; - return (NULL); - } - return (cfp); -} - -int -localcf_seekblk(cfp_t *cfp, int off, int mode) -{ - int rc; - - do { - rc = lseek(cfp->cf_fd, off, mode); - } while (rc == -1 && errno == EINTR); - - return (rc); -} - -int -localcf_readblk(cfp_t *cfp, void *buf, int size) -{ - int rc; - - do { - rc = read(cfp->cf_fd, buf, size); - } while (rc == -1 && errno == EINTR); - - return (rc); -} - -int -localcf_writeblk(cfp_t *cfp, void *buf, int size) -{ - int rc; - - do { - rc = write(cfp->cf_fd, buf, size); - } while (rc == -1 && errno == EINTR); - - return (rc); -} - -int -localcf_seek(cfp_t *cfp, int off, int mode) -{ - int rc; - int offset; - - offset = get_block_size(off); - - if ((mode == SEEK_SET) && (cfp->cf_flag & CFG_NOWRVTOC)) { - offset += CFG_VTOC_SKIP; - } - - do { - rc = lseek(cfp->cf_fd, offset, mode); - } while (rc == -1 && errno == EINTR); - - return (rc); -} - -int -localcf_read(cfp_t *cfp, void *buf, int size) -{ - int rc; - int blk_size; - char *blk_buf; - - blk_size = get_block_size(size); - if ((blk_buf = get_block_buf(size)) == NULL) - return (-1); - - do { - rc = read(cfp->cf_fd, blk_buf, blk_size); - } while (rc == -1 && errno == EINTR); - - bcopy(blk_buf, buf, size); - free_block_buf(blk_buf); - - return (rc); -} - -int -localcf_write(cfp_t *cfp, void *buf, int size) -{ - int rc; - int blk_size; - char *blk_buf; - - blk_size = get_block_size(size); - if ((blk_buf = get_block_buf(size)) == NULL) - return (-1); - - bcopy(buf, blk_buf, size); - - do { - rc = write(cfp->cf_fd, blk_buf, blk_size); - } while (rc == -1 && errno == EINTR); - - free_block_buf(blk_buf); - - return (rc); -} -/* - * Routines which operate on internal version of configuration - */ - -/* - * Add entry to end of configuration section - */ - -int -addcfline(cfp_t *cfp, char *line, int table_index) -{ - int len = strlen(line)+1; - int newsize = DEFAULT_ENTRY_SIZE / 2; - cfgheader_t *hd; - cfglist_t *cfl; - char *q; - -#ifdef DEBUG_CFGLIST - fprintf(stderr, "addcfline: pre l_size %d h_cfgsizes[%d]" - " %d l_free %u adding len %d\n", - cfp->cf_head->h_cfgs[table_index].l_size, table_index, - cfp->cf_head->h_cfgsizes[table_index], - cfp->cf_head->h_cfgs[table_index].l_free, len); -#endif - - hd = cfp->cf_head; - cfl = &cfp->cf_head->h_cfgs[table_index]; - if (cfl->l_free < len) { - -#ifdef DEBUG_CFGLIST - fprintf(stderr, "resizing l_entry from %d to %d\n", - cfl->l_size + cfl->l_free, cfl->l_size + - cfl->l_free + newsize); -#endif - cfl->l_entry = (char *)realloc(cfl->l_entry, (cfl->l_size + - cfl->l_free + newsize) * sizeof (char)); - if (cfl->l_entry == NULL) { - errno = ENOMEM; - return (-1); - } - cfl->l_free += newsize; - - } - cfl->l_free -= len; - - /* out of list slots, get some more */ - if (cfl->l_nentry % DEFAULT_NENTRIES == 0) { - /* - * first, figure out how much bigger, than realloc - */ - -#ifdef DEBUG_CFGLIST - fprintf(stderr, - "list %d getting more nentries, I have %d\n", - table_index, cfl->l_nentry); -#endif - cfl->l_esiz = (int *) - realloc(cfl->l_esiz, (cfl->l_nentry + DEFAULT_NENTRIES) * - sizeof (int)); - if (cfl->l_esiz == NULL) { - errno = ENOMEM; - return (-1); - } - } - - - cfl->l_esiz[cfl->l_nentry] = len; - cfl->l_nentry++; - - /* add line to end of list */ - q = cfl->l_entry + cfl->l_size; - - strcpy(q, line); - q += len; - - /* set sizes */ - hd->h_cfgs[table_index].l_size += len; - hd->h_cfgsizes[table_index] = cfl->l_size; - cfp->cf_head->h_csize += len; - -#ifdef DEBUG_CFGLIST - fprintf(stderr, "addcfline: post l_size %d h_cfgsizes[%d]" - " %d l_free %u\n h_csize %d\n", - cfp->cf_head->h_cfgs[table_index].l_size, - table_index, cfp->cf_head->h_cfgsizes[table_index], - cfp->cf_head->h_cfgs[table_index].l_free, cfp->cf_head->h_csize); -#endif - - return (1); -} - -/* - * remove entry from configuration section - */ -int -remcfline(cfp_t *cfp, int table_offset, int setnum) -{ - cfgheader_t *ch; - char *p, *q; - int len; - int copylen; - int i; - cfglist_t *cfl; - ch = cfp->cf_head; - - cfl = &cfp->cf_head->h_cfgs[table_offset]; - - q = cfl->l_entry; - - if (cfl->l_size == 0) { - /* list is empty */ - return (-1); - } - - if (!q) { /* somethings wrong here */ - return (-1); - } - - - for (i = 1; i < setnum; i++) { - q += cfl->l_esiz[i - 1]; - if (i >= cfl->l_nentry) { /* end of list */ - return (-1); - } - } - - if (q >= cfl->l_entry + cfl->l_size) - return (-1); - - len = cfl->l_esiz[i - 1]; - - -#ifdef DEBUG_CFGLISTRM - fprintf(stderr, "remcfline: pre: l_size %d h_cfgsizes[%d] %d free %d" - " removing len %d\n", - ch->h_cfgs[table_offset].l_size, table_offset, - ch->h_cfgsizes[table_offset], - ch->h_cfgs[table_offset].l_free, len); -#endif - - p = q + len; /* next string */ - - if (!(p >= cfl->l_entry + cfl->l_size)) { - /* if we didn't delete the last string in list */ - /* LINTED possible overflow */ - copylen = cfl->l_entry + cfl->l_size - p; - bcopy(p, q, copylen); - copylen = (cfl->l_nentry - i) * sizeof (int); - bcopy(&cfl->l_esiz[i], &cfl->l_esiz[i - 1], copylen); - } - - /* decrement the number of sets in this list */ - cfl->l_nentry--; - /* not really necessary, but.. */ - cfl->l_esiz[cfl->l_nentry] = 0; - - cfl->l_size -= len; - cfl->l_free += len; - - p = cfl->l_entry + cfl->l_size; - bzero(p, cfl->l_free); - - ch->h_cfgsizes[table_offset] = cfl->l_size; - ch->h_csize -= len; - - -#ifdef DEBUG_CFGLIST - fprintf(stderr, - "remcfline: post: l_size %d h_cfgsizes[%d] %d free %d\n ", - ch->h_cfgs[table_offset].l_size, table_offset, - ch->h_cfgsizes[table_offset], ch->h_cfgs[table_offset].l_free); -#endif - - return (0); - -} -/* - * Read entry from configuration section - */ -char * -readcfline(cfp_t *cfp, char *buf, int table_offset, int num) -{ - - char *q; - int i; - cfgheader_t *ch; - cfglist_t *cfl; - - /* this means they couldn't even find it in the parser tree */ - if (table_offset < 0) - return (NULL); - - ch = cfp->cf_head; - cfl = &ch->h_cfgs[table_offset]; - - q = cfl->l_entry; - - for (i = 1; i < num; i++) { - q += cfl->l_esiz[i - 1]; - if (i >= cfl->l_nentry) /* end of list */ - return (NULL); - } - - if (q >= cfl->l_entry + cfl->l_size) - return (NULL); - strcpy(buf, q); - return (q); -} - - -/* - * overwrite from current position with new value - */ -int -replacecfline(cfp_t *cfp, char *line, int table_offset, int num) -{ -/* - * take a table offset and a num to replace - * index in, bump the list up, leaving a hole big - * enough for the new string, or bcopying the rest of the list - * down only leaving a hole big enough. - * make sure not to overflow the - * allocated list size. - */ - cfgheader_t *ch; - cfglist_t *cfl; - char *p, *q; - int len = strlen(line) + 1; - int diff = 0; - int i; - int newsize = DEFAULT_ENTRY_SIZE / 2; - - - ch = cfp->cf_head; - cfl = &ch->h_cfgs[table_offset]; - - q = cfl->l_entry; - for (i = 1; i < num; i++) { - q += cfl->l_esiz[i - 1]; - if (i >= cfl->l_nentry) /* end of list */ - return (-1); - } - diff = len - cfl->l_esiz[i - 1]; - /* check for > 0, comparing uint to int */ - if ((diff > 0) && (diff > cfl->l_free)) { - /* - * we are going to overflow, get more mem, but only - * 1/2 as much as initial calloc, we don't need to be greedy - */ -#ifdef DEBUG_CFGLIST - fprintf(stderr, - "resizing at replacecfline from %d to %d \n", - cfl->l_size + cfl->l_free, cfl->l_size + - cfl->l_free + newsize); -#endif - cfl->l_entry = (char *)realloc(cfl->l_entry, - (cfl->l_size + cfl->l_free + newsize) * sizeof (char)); - if (cfl->l_entry == NULL) { - errno = ENOMEM; - return (-1); - } - cfl->l_free += (DEFAULT_ENTRY_SIZE / 2); - - /* re-find q, we could have a whole new chunk of memory here */ - q = cfl->l_entry; - for (i = 1; i < num; i++) { - q += cfl->l_esiz[i - 1]; - if (i >= cfl->l_nentry) /* end of list */ - return (-1); - } - } - - p = q + cfl->l_esiz[i - 1]; /* next string */ - cfl->l_esiz[i - 1] += diff; /* the new entry size */ - if (diff != 0) { /* move stuff over/back for correct fit */ - /* LINTED possible overflow */ - bcopy(p, p + diff, (cfl->l_entry + cfl->l_size - p)); - cfl->l_free -= diff; /* 0 - (-1) = 1 */ - cfl->l_size += diff; - - /* total of all h_cfgs[n].l_entry */ - cfp->cf_head->h_csize += diff; - cfp->cf_head->h_cfgsizes[table_offset] = cfl->l_size; /* disk */ - bzero((cfl->l_entry + cfl->l_size), cfl->l_free); - } - - strcpy(q, line); - return (1); - -} - -static cfg_io_t _cfg_raw_io_def = { - NULL, - "Local", - localcf_open, - localcf_close, - localcf_seek, - localcf_read, - localcf_write, - readcfline, - addcfline, - remcfline, - replacecfline, - -}; - -static cfg_io_t _cfg_block_io_def = { - NULL, - "Local", - localcf_open, - localcf_close, - localcf_seekblk, - localcf_readblk, - localcf_writeblk, - readcfline, - addcfline, - remcfline, - replacecfline, -}; - -cfg_io_t * -cfg_raw_io_provider(void) -{ - return (&_cfg_raw_io_def); -} - -cfg_io_t * -cfg_block_io_provider(void) -{ - return (&_cfg_block_io_def); -} diff --git a/usr/src/lib/libdscfg/common/cfg_local.h b/usr/src/lib/libdscfg/common/cfg_local.h deleted file mode 100644 index 5dff884baf..0000000000 --- a/usr/src/lib/libdscfg/common/cfg_local.h +++ /dev/null @@ -1,42 +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. - */ - -#ifndef _CFG_LOCAL_H -#define _CFG_LOCAL_H - -#ifdef __cplusplus -extern "C" { -#endif - -char *readcfline(cfp_t *cfp, char *buf, int table_index, int offset); -int addcfline(cfp_t *cfp, char *line, int table_index); -int replacecfline(cfp_t *cfp, char *line, int table_index, int offset); -int remcfline(cfp_t *cfp, int table_index, int offset); - -#ifdef __cplusplus -} -#endif - -#endif /* _CFG_LOCAL_H */ diff --git a/usr/src/lib/libdscfg/common/cfg_lockd.h b/usr/src/lib/libdscfg/common/cfg_lockd.h deleted file mode 100644 index 42fbc6d676..0000000000 --- a/usr/src/lib/libdscfg/common/cfg_lockd.h +++ /dev/null @@ -1,72 +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. - */ - -#ifndef _CFG_LOCKD_H -#define _CFG_LOCKD_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { LOCK_NOTLOCKED, /* Unlock message */ - LOCK_READ, /* ask for read lock */ - LOCK_WRITE, /* ask for write lock */ - LOCK_LOCKED, /* lock has been taken */ - LOCK_LOCKEDBY, /* who has lock? */ - LOCK_STAT, /* ask daemon to print its state */ - LOCK_ACK /* acknowledge a notlocked msg */ - } cfglockd_t; - -typedef struct sockaddr_in daemonaddr_t; - -struct lock_msg { - int32_t message; - pid_t pid; - int32_t order; - uint8_t seq; -}; - -#define CFG_PIDFILE "/var/tmp/.cfglockd.pid" -#define CFG_SERVER_PORT 50121u -#define CFG_LF_EOF -1 -#define CFG_LF_OKAY 1 -#define CFG_LF_AGAIN 0 -void cfg_lfinit(); -int cfg_filelock(int segment, int flag); -int cfg_fileunlock(int segment); -void cfg_readpid(int segment, pid_t *pidp); -void cfg_writepid(int segment, pid_t pid); -void cfg_enterpid(); -int cfg_lockd_init(); -cfglockd_t cfg_lockedby(pid_t *); -void cfg_lockd_rdlock(); -void cfg_lockd_wrlock(); -void cfg_lockd_unlock(); - -#ifdef __cplusplus -} -#endif - -#endif /* _CFG_LOCKD_H */ diff --git a/usr/src/lib/libdscfg/common/cfg_lockdlck.c b/usr/src/lib/libdscfg/common/cfg_lockdlck.c deleted file mode 100644 index 14f7cb4b1d..0000000000 --- a/usr/src/lib/libdscfg/common/cfg_lockdlck.c +++ /dev/null @@ -1,135 +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 <signal.h> -#include <sys/types.h> -#include <sys/time.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <stdio.h> -#include <unistd.h> -#include <strings.h> -#include <errno.h> -#include <assert.h> - -#include "cfg_impl.h" -#include "cfg_lockd.h" - - -#define segment_off(s) ((off_t)(s) * sizeof (pid_t)) - -static int local_lockfd; -static int local_lockfda; - -void -cfg_lfinit() -{ - local_lockfd = open(CFG_RDEV_LOCKFILE, O_RDWR|O_CREAT, 0644); - local_lockfda = open(CFG_RDEV_LOCKFILE, O_RDWR|O_APPEND, 0644); -} - -int -cfg_filelock(int segment, int flag) -{ - struct flock lk; - struct stat sb; - pid_t pid = 0; - off_t off = segment_off(segment); - int rc; - - while (fstat(local_lockfd, &sb) == -1 && errno == EINTR) - ; - if (sb.st_size < off + sizeof (pid_t)) { - if ((flag&O_CREAT) == 0) - return (CFG_LF_EOF); - write(local_lockfda, &pid, sizeof (pid_t)); - } - bzero(&lk, sizeof (lk)); - lk.l_type = F_WRLCK; - lk.l_whence = SEEK_SET; - lk.l_start = off; - lk.l_len = (off_t)sizeof (pid_t); - - while ((rc = fcntl(local_lockfd, F_SETLK, &lk)) < 0 && errno == EINTR) - ; - if (rc == -1 && errno == EAGAIN) - return (CFG_LF_AGAIN); - - return (CFG_LF_OKAY); -} - - -int -cfg_fileunlock(int segment) -{ - struct flock lk; - off_t off = segment_off(segment); - - bzero(&lk, sizeof (lk)); - lk.l_type = F_UNLCK; - lk.l_whence = SEEK_SET; - lk.l_start = off; - lk.l_len = (off_t)sizeof (pid_t); - - while (fcntl(local_lockfd, F_SETLK, &lk) < 0 && errno == EINTR) - ; - return (1); -} - -void -cfg_readpid(int segment, pid_t *pidp) -{ - off_t off = segment_off(segment); - lseek(local_lockfd, off, SEEK_SET); - read(local_lockfd, pidp, sizeof (pid_t)); -} - -void -cfg_writepid(int segment, pid_t pid) -{ - off_t off = segment_off(segment); - lseek(local_lockfd, off, SEEK_SET); - write(local_lockfd, &pid, sizeof (pid_t)); -} - -void -cfg_enterpid() -{ - int i; - pid_t pid; - - for (i = 0; ; i++) { - if (cfg_filelock(i, O_CREAT) == CFG_LF_OKAY) { - cfg_readpid(i, &pid); - if (pid != (pid_t)0) { - cfg_fileunlock(i); - continue; - } - pid = getpid(); - cfg_writepid(i, pid); - break; - } - } -} diff --git a/usr/src/lib/libdscfg/common/cfg_lockdmsg.c b/usr/src/lib/libdscfg/common/cfg_lockdmsg.c deleted file mode 100644 index 238c75967e..0000000000 --- a/usr/src/lib/libdscfg/common/cfg_lockdmsg.c +++ /dev/null @@ -1,324 +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 <signal.h> -#include <sys/types.h> -#include <sys/time.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <netdb.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <stdlib.h> -#include <errno.h> - -#include "cfg_lockd.h" - -static daemonaddr_t clientaddr; -static daemonaddr_t server; - -static unsigned short server_port = CFG_SERVER_PORT; -static int lock_soc = 0; -static int pf_inet = AF_INET; -static int locked; -static int initdone; -static int initresult; -static pid_t socket_pid; - -static void cfg_lockd_reinit(); - -static int last_cmd = -1; -static uint8_t seq = 0; - -static void -send_cmd(int cmd) -{ - struct lock_msg message_buf; - int rc; - - if (last_cmd == cmd) { - message_buf.seq = seq; - } else { - message_buf.seq = ++seq; - last_cmd = cmd; - } - message_buf.message = cmd; - if ((message_buf.pid = getpid()) != socket_pid) - cfg_lockd_reinit(); - - do { - rc = sendto(lock_soc, &message_buf, sizeof (message_buf), 0, - (struct sockaddr *)&server, sizeof (server)); - } while (rc == -1 && errno == EINTR); -#ifdef CFG_LOCKD_DEBUG - if (rc < 0) { - perror("send"); - } -#endif -} - -static void -read_msg(struct lock_msg *mp) -{ - struct sockaddr from; - int rc, len; - - /* wait for response */ - do { - struct pollfd fds; - - fds.fd = lock_soc; - fds.events = POLLIN; - fds.revents = 0; - - rc = poll(&fds, 1, 500); - if (!rc) { -#ifdef CFG_LOCKD_DEBUG - fprintf(stderr, "LOCKD: resending last command (%d)\n", - last_cmd); -#endif - send_cmd(last_cmd); - } - } while (rc == 0 || - (rc == -1 && errno == EINTR)); - - do { - len = sizeof (from); - rc = recvfrom(lock_soc, mp, sizeof (*mp), 0, - &from, &len); - } while (rc == -1 && errno == EINTR); -#ifdef CFG_LOCKD_DEBUG - if (rc < 0) { - perror("revcfrom"); - } -#endif -} - -static void -read_reply() -{ - struct lock_msg message_buf; - - do { - read_msg(&message_buf); - } while (message_buf.seq != seq || message_buf.message != LOCK_LOCKED); -} - -static void -read_ack() -{ - struct lock_msg message_buf; - - do { - read_msg(&message_buf); - } while (message_buf.seq != seq || message_buf.message != LOCK_ACK); -} - -void -cfg_lockd_rdlock() -{ -#ifdef CFG_LOCKD_DEBUG - FILE *fp; -#endif - - send_cmd(LOCK_READ); - locked = 1; - read_reply(); - -#ifdef CFG_LOCKD_DEBUG - fp = fopen("/tmp/locktag", "a"); - if (fp) { - time_t t = time(0); - fprintf(fp, "%19.19s read lock acquired\n", ctime(&t)); - fclose(fp); - } - sleep(3); -#endif -} - -void -cfg_lockd_wrlock() -{ -#ifdef CFG_LOCKD_DEBUG - FILE *fp; -#endif - - send_cmd(LOCK_WRITE); - locked = 1; - read_reply(); - -#ifdef CFG_LOCKD_DEBUG - fp = fopen("/tmp/locktag", "a"); - if (fp) { - time_t t = time(0); - fprintf(fp, "%19.19s write lock acquired\n", ctime(&t)); - fclose(fp); - } - sleep(3); -#endif -} - -void -cfg_lockd_unlock() -{ -#ifdef CFG_LOCKD_DEBUG - FILE *fp; -#endif - - send_cmd(LOCK_NOTLOCKED); - read_ack(); - locked = 0; - -#ifdef CFG_LOCKD_DEBUG - fp = fopen("/tmp/locktag", "a"); - if (fp) { - time_t t = time(0); - fprintf(fp, "%19.19s ----- lock released\n", ctime(&t)); - fclose(fp); - } - sleep(3); -#endif -} - -void -cfg_lockd_stat() -{ - send_cmd(LOCK_STAT); -} - -cfglockd_t -cfg_lockedby(pid_t *pidp) -{ - struct lock_msg message_buf; - send_cmd(LOCK_LOCKEDBY); - read_msg(&message_buf); - *pidp = message_buf.pid; - return ((cfglockd_t)message_buf.message); -} - -static void -cfg_atexit() -{ - if (locked) - cfg_lockd_unlock(); -} - -static int -cfg_lockd_socket() -{ - if ((lock_soc = socket(pf_inet, SOCK_DGRAM, 0)) < 0) { -#ifdef CFG_LOCKD_DEBUG - fprintf(stderr, "libcfg: failed to create socket\n"); - perror("socket"); -#endif - return (-1); - } - clientaddr.sin_family = AF_INET; - clientaddr.sin_addr.s_addr = INADDR_ANY; - clientaddr.sin_port = htons(0); - if (bind(lock_soc, (struct sockaddr *)&clientaddr, - sizeof (clientaddr)) < 0) { -#ifdef CFG_LOCKD_DEBUG - perror("bind"); -#endif - return (-1); - } - socket_pid = getpid(); - return (0); -} - -/* - * Re-initialise after a fork has been detected. - * - * Needs to create a new socket for new process to receive messages - * from the lock daemon and enter pid into lock file so that the daemon - * can detect new processes exit if it doesn't call unlock first. - */ - -static void -cfg_lockd_reinit() -{ - if (lock_soc) - close(lock_soc); - lock_soc = 0; - if (cfg_lockd_socket()) { - initresult = 0; - return; - } - cfg_enterpid(); - initresult = 1; -} - -int -cfg_lockd_init() -{ - struct hostent *hp; - FILE *fp; - int pid = 0x12345678; - - if (initdone) { - /* only perform reinit if init worked first time */ - if (getpid() != socket_pid && initresult != 0) - cfg_lockd_reinit(); - return (initresult); - } - - initdone = 1; - initresult = 0; - - /* check if there's a lock daemon out there */ - if ((fp = fopen(CFG_PIDFILE, "r")) == NULL) - return (0); - if (fscanf(fp, "%d\n", &pid) != 1) { - fclose(fp); - return (0); - } - fclose(fp); - if (kill((pid_t)pid, 0) != 0) - return (0); - - /* there is a lock daemon */ - cfg_lfinit(); - cfg_enterpid(); - if (cfg_lockd_socket()) - return (0); - - if ((hp = gethostbyname("localhost")) == NULL) { -#ifdef CFG_LOCKD_DEBUG - fprintf(stderr, "Can't find hostent for %s\n", "localhost"); -#endif - return (0); - } - (void) memcpy(&(server.sin_addr.s_addr), *(hp->h_addr_list), - sizeof (server.sin_addr)); - server.sin_port = htons(server_port); - server.sin_family = hp->h_addrtype; - endhostent(); - atexit(cfg_atexit); - initresult = 1; - return (1); -} diff --git a/usr/src/lib/libdscfg/common/cfg_vols.c b/usr/src/lib/libdscfg/common/cfg_vols.c deleted file mode 100644 index 6f0f8bb447..0000000000 --- a/usr/src/lib/libdscfg/common/cfg_vols.c +++ /dev/null @@ -1,1286 +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 <sys/types.h> -#include <stdio.h> -#include <fcntl.h> -#include <unistd.h> -#include <sys/stat.h> -#include <sys/mkdev.h> -#include <strings.h> -#include <stdarg.h> -#include <stdlib.h> -#include <locale.h> -#include <errno.h> - -#include <sys/nsctl/cfg.h> - -#include <sys/unistat/spcs_s.h> -#include <sys/unistat/spcs_s_u.h> -#include <sys/unistat/spcs_errors.h> -#include <sys/unistat/spcs_s_impl.h> - -#include <sys/nsctl/sv.h> -#include <sys/nsctl/nsc_hash.h> - -#define DEV_EXPAND 32 - -#define DO_DISABLE 0 -#define DO_ENABLE 1 - -/* - * Utility functions for iiadm and rdcadm/sndradm. - */ - -typedef struct hash_data_s { - union { - char *users; - char *mode; - } u; - char *path; - char *node; - int setno; -} hash_data_t; - -typedef struct { - dev_t rdev; - mode_t mode; - char *path; -} device_t; - -static hash_data_t *make_svol_data(char *, char *, char *, int); -static hash_data_t *make_dsvol_data(char *, char *, char *, int); -static void delete_svol_data(void *); -static void delete_dsvol_data(void *); -static int sv_action(char *, CFGFILE *, char *, int); - -static int add_dev_entry(const char *); -static int compare(const void *, const void *); -static char *find_devid(const char *); -static void free_dev_entries(); -static void rebuild_devhash(); - -static hash_node_t **dsvol; -static int dsvol_loaded = 0; - -static hash_node_t **svol; -static int svol_loaded = 0; - -static hash_node_t **shadowvol; - -static hash_node_t **devhash; -static device_t *devlist; -static int devcount = 0; -static int devalloc = 0; - -/* - * cfg_add_user - * - * Description: - * Adds the calling tool as a user of the volume. - * - * Inputs: - * char *path: The pathname of the volume to be enabled. - * char *cnode: The device group name, or NULL if -C local or not cluster - * CFGFILE *cfg: A pointer to the current config file, or NULL if this - * function is to open/write/commit/close the change itself. - * - * Return values: - * CFG_USER_FIRST: Indicates that this is the first user of this - * particular volume. - * CFG_USER_OK: Indicates that the volume has already been entered into - * the config file. - * CFG_USER_ERR: Indicates that some failure has occurred and no changes - * to the config file have been made. - * CFG_USER_REPEAT: Indicates that this user has already registered for - * the volume. - */ -int -cfg_add_user(CFGFILE* cfg, char *path, char *cnode, char *user) -{ - int self_open, self_loaded, change_made; - char *ctag, search_key[ CFG_MAX_KEY ], buf[ CFG_MAX_BUF ]; - int retval, rc; - hash_data_t *data; - - self_open = (cfg == NULL); - self_loaded = 0; - change_made = 0; - - if (self_open) { - cfg = cfg_open(NULL); - if (cfg == NULL) { - return (CFG_USER_ERR); - } - - if (!cfg_lock(cfg, CFG_WRLOCK)) { - /* oops */ - cfg_close(cfg); - return (CFG_USER_ERR); - } - } - - /* Check cnode */ - ctag = cfg_get_resource(cfg); - if (cnode) { - if (ctag) { - if (strcmp(cnode, ctag)) - return (CFG_USER_ERR); - } else - cfg_resource(cfg, cnode); - } else - cnode = ctag; - - if (!dsvol_loaded) { - if (cfg_load_dsvols(cfg) < 0) { - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - self_loaded = 1; - } - - /* find the volume */ - (void) snprintf(search_key, CFG_MAX_KEY, "%s:%s", path, cnode); - data = nsc_lookup(dsvol, search_key); - - if (!data) { - /* whoops, not found. Add as new user */ - cfg_rewind(cfg, CFG_SEC_CONF); - (void) snprintf(buf, CFG_MAX_BUF, "%s %s %s", path, cnode, - user); - rc = cfg_put_cstring(cfg, "dsvol", buf, strlen(buf)); - if (rc < 0) { - if (self_loaded) { - cfg_unload_dsvols(); - } - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - /* reload hash, if we need to */ - if (!self_loaded) { - cfg_unload_dsvols(); - if (cfg_load_dsvols(cfg) < 0) { - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - } - retval = CFG_USER_FIRST; - change_made = 1; - } else { - /* Check to ensure we're not already listed */ - char *p = strdup(data->u.users); - char *q = strtok(p, ","); - while (q && (strcmp(q, user) != 0)) { - q = strtok(0, ","); - } - free(p); /* not using data; only testing 'q' ptr */ - - if (!q) { - /* not listed as a user */ - cfg_rewind(cfg, CFG_SEC_CONF); - (void) snprintf(buf, CFG_MAX_BUF, "%s %s %s,%s", - data->path, data->node, data->u.users, user); - (void) snprintf(search_key, CFG_MAX_KEY, "dsvol.set%d", - data->setno); - if (cfg_put_cstring(cfg, search_key, buf, - strlen(buf)) < 0) { - if (self_loaded) { - cfg_unload_dsvols(); - } - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - - /* - * Since we deleted an entry from the config - * file, we don't know what all the new - * set numbers are. We need to reload - * everything - */ - if (!self_loaded) { - cfg_unload_dsvols(); - if (cfg_load_dsvols(cfg) < 0) { - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - } - change_made = 1; - retval = CFG_USER_OK; - } else { - retval = CFG_USER_REPEAT; - } - } - - if (self_loaded) { - cfg_unload_dsvols(); - } - - if (self_open) { - if (change_made) - (void) cfg_commit(cfg); - cfg_close(cfg); - } - - return (retval); -} - -/* - * cfg_rem_user - * - * Description: - * Removes a user from the config file. - * - * Inputs: - * char *path: The pathname of the volume to be enabled. - * char *cnode: The device group name, or NULL if -C local or not cluster - * char *user: The subsystem that is adding this tag (sv, ii, sndr) - * CFGFILE *cfg: A pointer to the current config file, or NULL if this - * function is to open/write/commit/close the change itself. - * Return values: - * CFG_USER_ERR: An error occurred during the processing of this - * directive. - * CFG_USER_OK: User successfully removed; volume in use by other(s). - * CFG_USER_LAST: User successfuly removed; no other users registered - * CFG_USER_GONE: The volume is no longer listed in the dsvol section, - * indicating some sort of application-level error. - * - */ -int -cfg_rem_user(CFGFILE *cfg, char *path, char *cnode, char *user) -{ - int self_open, self_loaded, change_made; - char *ctag, search_key[ CFG_MAX_KEY ], buf[ CFG_MAX_BUF ]; - char cfg_key[ CFG_MAX_KEY ]; - hash_data_t *data; - int retval; - int force_remove; - - self_open = (cfg == NULL); - self_loaded = 0; - change_made = 0; - force_remove = (strcmp(user, "sv") == 0); - - if ('-' == *user) { - ++user; - } - - /* Check cnode */ - ctag = cfg_get_resource(cfg); - if (cnode) { - if (ctag) { - if (strcmp(cnode, ctag)) - return (CFG_USER_ERR); - } else - cfg_resource(cfg, cnode); - } else - cnode = ctag; - - if (self_open) { - cfg = cfg_open(NULL); - if (cfg == NULL) { - return (CFG_USER_ERR); - } - - if (!cfg_lock(cfg, CFG_WRLOCK)) { - /* oops */ - cfg_close(cfg); - return (CFG_USER_ERR); - } - } - - - change_made = 0; - if (!dsvol_loaded) { - if (cfg_load_dsvols(cfg) < 0) { - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - self_loaded = 1; - } - - /* find the volume */ - (void) snprintf(search_key, CFG_MAX_KEY, "%s:%s", path, cnode); - data = nsc_lookup(dsvol, search_key); - - if (!data) { - /* yipes */ - retval = CFG_USER_GONE; - } else if (force_remove) { - retval = CFG_USER_LAST; - cfg_rewind(cfg, CFG_SEC_CONF); - (void) snprintf(cfg_key, CFG_MAX_KEY, "dsvol.set%d", - data->setno); - if (cfg_put_cstring(cfg, cfg_key, NULL, 0) < 0) { - if (self_loaded) { - cfg_unload_dsvols(); - } - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - if (!self_loaded) { - cfg_unload_dsvols(); - if (cfg_load_dsvols(cfg) < 0) { - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - } - } else { - char *p = strdup(data->u.users); - char *q = strtok(p, ","); - int appended = 0; - - (void) snprintf(buf, CFG_MAX_BUF, "%s %s ", data->path, - data->node); - while (q && (strcmp(q, user) != 0)) { - if (appended) { - strcat(buf, ","); - strcat(buf, q); - } else { - strcat(buf, q); - appended = 1; - } - q = strtok(0, ","); - } - - if (!q) { - /* uh-oh */ - retval = CFG_USER_GONE; - } else { - /* old user skipped; add in remaining users */ - while (q = strtok(0, ", ")) { - if (appended) { - strcat(buf, ","); - strcat(buf, q); - } else { - strcat(buf, q); - appended = 1; - } - } - - if (appended) { - retval = CFG_USER_OK; - cfg_rewind(cfg, CFG_SEC_CONF); - (void) snprintf(cfg_key, CFG_MAX_KEY, - "dsvol.set%d", data->setno); - if (cfg_put_cstring(cfg, cfg_key, buf, - strlen(buf)) < 0) { - if (self_loaded) { - cfg_unload_dsvols(); - } - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - if (!self_loaded) { - cfg_unload_dsvols(); - if (cfg_load_dsvols(cfg) < 0) { - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - } - } else { - retval = CFG_USER_LAST; - cfg_rewind(cfg, CFG_SEC_CONF); - (void) snprintf(cfg_key, CFG_MAX_KEY, - "dsvol.set%d", data->setno); - if (cfg_put_cstring(cfg, cfg_key, NULL, - 0) < 0) { - if (self_loaded) { - cfg_unload_dsvols(); - } - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - /* - * Since we deleted an entry from the config - * file, we don't know what all the new - * set numbers are. We need to reload - * everything - */ - if (!self_loaded) { - cfg_unload_dsvols(); - if (cfg_load_dsvols(cfg) < 0) { - if (self_open) { - cfg_close(cfg); - } - return (CFG_USER_ERR); - } - } - } - change_made = 1; - } - } - - if (self_loaded) { - cfg_unload_dsvols(); - } - - if (self_open) { - if (change_made) - (void) cfg_commit(cfg); - cfg_close(cfg); - } - - return (retval); -} - -/* - * Enable a volume under SV control (or add this char *user to the list - * of users of that volume). - * - * Parameters: - * cfg - The config file to use. - * path - The pathname of the volume - * ctag - The cluster tag for this volume (if any) - * user - The user (sv, ii, sndr) of the volume. - */ -int -cfg_vol_enable(CFGFILE *cfg, char *path, char *ctag, char *user) -{ - int rc; - int retval; - - if (!ctag || *ctag == '\0') { - ctag = "-"; - } - - retval = -1; - rc = cfg_add_user(cfg, path, ctag, user); - switch (rc) { - case CFG_USER_ERR: - spcs_log("dsvol", NULL, - gettext("unable to set up dsvol section of config for %s"), - path); - break; - case CFG_USER_OK: - retval = 0; - break; - case CFG_USER_FIRST: - /* enable sv! */ - retval = sv_action(path, cfg, ctag, DO_ENABLE); - if (retval < 0) { - (void) cfg_rem_user(cfg, path, ctag, user); - } - break; - default: - spcs_log("dsvol", NULL, - gettext("unexpected return from cfg_add_user(%d)"), rc); - break; - } - - return (retval); -} - -/* - * Disable a volume from SV control (or remove this char *user from the list - * of users of that volume). - * - * Parameters: - * cfg - The config file to use. - * path - The pathname of the volume - * ctag - The cluster tag for this volume (if any) - * user - The user (sv, ii, sndr) of the volume. - */ -int -cfg_vol_disable(CFGFILE *cfg, char *path, char *ctag, char *user) -{ - int rc; - int retval; - - if (!ctag || *ctag == '\0') { - ctag = "-"; - } - - retval = -1; - rc = cfg_rem_user(cfg, path, ctag, user); - switch (rc) { - case CFG_USER_ERR: - spcs_log("dsvol", NULL, - gettext("unable to set up dsvol section of config for %s"), - path); - break; - case CFG_USER_OK: - retval = 0; - break; - case CFG_USER_GONE: - spcs_log("dsvol", NULL, - gettext("%s tried to remove non-existent tag for %s"), - user, path); - break; - case CFG_USER_LAST: - /* diable sv! */ - retval = sv_action(path, cfg, ctag, DO_DISABLE); - break; - default: - spcs_log("dsvol", NULL, - gettext("unexpected return from cfg_rem_user(%d)"), rc); - break; - } - - return (retval); -} - -/* - * cfg_load_dsvols - * - * Description: - * Loads the dsvol section of the config file into a giant hash, to - * make searching faster. The important bit to remember is to not - * release the write lock between calling cfg_load_dsvols() and the - * cfg_*_user() functions. - * - * Assumptions: - * 1/ cfg file is open - * 2/ cfg file has been write-locked - * 3/ user of this routine may already be using hcreate/hsearch - * - * Return value: - * -1 if error, or total number of sets found - */ -int -cfg_load_dsvols(CFGFILE *cfg) -{ - int set, rc, entries; - char search_key[ CFG_MAX_KEY ]; - char *buf; - char **entry, *path, *cnode, *users; - hash_data_t *data; - int devs_added = 0; - int offset = 0; - char *ctag = cfg_get_resource(cfg); - if (!ctag || *ctag == '\0') { - ctag = "-"; - } - - dsvol = nsc_create_hash(); - if (!dsvol) { - return (-1); - } - - rc = 0; - cfg_rewind(cfg, CFG_SEC_CONF); - entries = cfg_get_section(cfg, &entry, "dsvol"); - for (set = 1; set <= entries; set++) { - buf = entry[set - 1]; - - /* split up the line */ - if (!(path = strtok(buf, " "))) { - /* oops, now what? */ - free(buf); - break; - } - if (!(cnode = strtok(0, " "))) { - free(buf); - break; - } - if (ctag && (strcmp(cnode, ctag) != 0)) { - ++offset; - free(buf); - continue; - } - - if (!(users = strtok(0, " "))) { - free(buf); - break; - } - - data = make_dsvol_data(path, cnode, users, set - offset); - if (!data) { - free(buf); - break; - } - (void) snprintf(search_key, CFG_MAX_KEY, "%s:%s", path, cnode); - rc = nsc_insert_node(dsvol, data, search_key); - if (rc < 0) { - free(buf); - break; - } - - /* we also need to keep track of node information */ - rc = add_dev_entry(path); - if (rc < 0) { - free(buf); - break; - } else if (rc) - ++devs_added; - - free(buf); - rc = 0; - } - - while (set < entries) - free(entry[set++]); - if (entries) - free(entry); - - if (devs_added) { - qsort(devlist, devcount, sizeof (device_t), compare); - rebuild_devhash(); - } - - dsvol_loaded = 1; - return (rc < 0? rc : entries); -} - -/* - * cfg_unload_dsvols - * - * Description: - * Free all memory allocated with cfg_load_dsvols. - */ -void -cfg_unload_dsvols() -{ - if (dsvol) { - nsc_remove_all(dsvol, delete_dsvol_data); - dsvol = 0; - dsvol_loaded = 0; - } -} - -/* - * cfg_load_svols - * - * Description: - * Loads the sv section of the config file into a giant hash, to make - * searching faster. The important bit to remember is to not release - * the write lock between calling cfg_load_svols() and the cfg_*_user() - * functions. - * - * Assumptions: - * 1/ cfg file is open - * 2/ cfg file has been write-locked - * 3/ user of this routine may already be using builtin hcreate/hsearch - */ -int -cfg_load_svols(CFGFILE *cfg) -{ - int set, entries, offset = 0; - char *buf, **entry; - char *path, *mode, *cnode; - hash_data_t *data; - char *ctag = cfg_get_resource(cfg); - if (!ctag || *ctag == '\0') { - ctag = "-"; - } - - svol = nsc_create_hash(); - if (!svol) { - return (-1); - } - - cfg_rewind(cfg, CFG_SEC_CONF); - entries = cfg_get_section(cfg, &entry, "sv"); - for (set = 1; set <= entries; set++) { - buf = entry[set - 1]; - - /* split up the line */ - if (!(path = strtok(buf, " "))) { - free(buf); - break; - } - if (!(mode = strtok(0, " "))) { - free(buf); - break; - } - if (!(cnode = strtok(0, " "))) { - cnode = ""; - } - - if (ctag && (strcmp(cnode, ctag) != 0)) { - ++offset; - free(buf); - continue; - } - - data = make_svol_data(path, mode, cnode, set - offset); - if (!data) { - free(buf); - break; - } - if (nsc_insert_node(svol, data, path) < 0) { - free(buf); - break; - } - free(buf); - } - while (set < entries) - free(entry[set++]); - if (entries) - free(entry); - - svol_loaded = 1; - return (0); -} - -/* - * cfg_unload_svols - * - * Description: - * Frees all memory allocated with cfg_load_dsvols - */ -void -cfg_unload_svols() -{ - if (svol) { - nsc_remove_all(svol, delete_svol_data); - svol = 0; - svol_loaded = 0; - } -} - -/* - * cfg_get_canonical_name - * - * Description: - * Find out whether a device is already known by another name in - * the config file. - * - * Parameters: - * cfg - The config file to use - * path - The pathname of the device - * result - (output) The name it is otherwise known as. This parameter - * must be freed by the caller. - * - * Return values: - * -1: error - * 0: name is as expected, or is not known - * 1: Name is known by different name (stored in 'result') - */ -int -cfg_get_canonical_name(CFGFILE *cfg, const char *path, char **result) -{ - int self_loaded; - char *alt_path; - int retval; - - if (devlist) { - self_loaded = 0; - } else { - if (cfg_load_shadows(cfg) < 0) { - return (-1); - } - self_loaded = 1; - } - - /* see if it exists under a different name */ - alt_path = find_devid(path); - if (!alt_path || strcmp(path, alt_path) == 0) { - *result = NULL; - retval = 0; - } else { - /* a-ha */ - *result = strdup(alt_path); - retval = 1; - } - - if (self_loaded) { - free_dev_entries(); - } - - return (retval); -} - -/* - * cfg_load_shadows - * - * Description: - * Load in shadow and bitmap volumes from the II section of the - * config file. SNDR's volumes are handled already by cfg_load_dsvols. - * Not all shadow volumes are listed under dsvol: they can be exported. - * - * Parameters: - * cfg - The config file to use - * - * Return values: - * -1: error - * 0: success - */ -int -cfg_load_shadows(CFGFILE *cfg) -{ - int set, self_loaded, rc, entries; - char *buf, **entry, *ptr; - int devs_added = 0; - - if (dsvol_loaded) { - self_loaded = 0; - } else { - if (cfg_load_dsvols(cfg) < 0) { - return (-1); - } - self_loaded = 1; - } - - shadowvol = nsc_create_hash(); - if (!shadowvol) { - return (-1); - } - - rc = 0; - cfg_rewind(cfg, CFG_SEC_CONF); - entries = cfg_get_section(cfg, &entry, "ii"); - for (set = 1; set <= entries; set++) { - buf = entry[set - 1]; - - /* skip the master vol */ - ptr = strtok(buf, " "); - - /* shadow is next */ - ptr = strtok(NULL, " "); - - rc = add_dev_entry(ptr); - if (rc < 0) { - free(buf); - break; - } else if (rc) - ++devs_added; - - /* and next is bitmap */ - ptr = strtok(NULL, " "); - - rc = add_dev_entry(ptr); - if (rc < 0) { - free(buf); - break; - } else if (rc) - ++devs_added; - rc = 0; - free(buf); - } - while (set < entries) - free(entry[set++]); - if (entries) - free(entry); - - if (self_loaded) { - cfg_unload_dsvols(); - } - - if (devs_added) { - /* sort it, in preparation for lookups */ - qsort(devlist, devcount, sizeof (device_t), compare); - rebuild_devhash(); - } - - return (rc); -} - -void -cfg_unload_shadows() -{ - /* do nothing */ -} - -/* ---------------------------------------------------------------------- */ - -static hash_data_t * -make_dsvol_data(char *path, char *cnode, char *users, int set) -{ - hash_data_t *data; - - data = (hash_data_t *)malloc(sizeof (hash_data_t)); - if (!data) { - return (0); - } - - data->u.users = strdup(users); - data->path = strdup(path); - data->node = strdup(cnode); - data->setno = set; - - return (data); -} - -static void -delete_dsvol_data(void *data) -{ - hash_data_t *p = (hash_data_t *)data; - - free(p->u.users); - free(p->path); - free(p->node); - free(p); -} - -static hash_data_t * -make_svol_data(char *path, char *mode, char *cnode, int set) -{ - hash_data_t *data; - - data = (hash_data_t *)malloc(sizeof (hash_data_t)); - if (!data) { - return (0); - } - - data->u.mode = strdup(mode); - data->path = strdup(path); - data->node = strdup(cnode); - data->setno = set; - - return (data); -} - - -static void -delete_svol_data(void *data) -{ - hash_data_t *p = (hash_data_t *)data; - - free(p->u.mode); - free(p->path); - free(p->node); - free(p); -} - -static int -sv_action(char *path, CFGFILE *caller_cfg, char *ctag, int enable) -{ - struct stat stb; - sv_conf_t svc; - int fd = -1; - int cfg_changed = 0; - CFGFILE *cfg; - int print_log = 0; - int err = 0, rc; - int sv_ioctl, spcs_err, self_loaded; - char *log_str1, *log_str2; - char key[ CFG_MAX_KEY ]; - char buf[ CFG_MAX_BUF ]; - hash_data_t *node; - device_t *statinfo = 0; - - if (caller_cfg == NULL) { - cfg = cfg_open(NULL); - if (cfg == NULL) - return (-1); - - if (ctag) - cfg_resource(cfg, ctag); - } else - cfg = caller_cfg; - - - self_loaded = 0; - sv_ioctl = (enable? SVIOC_ENABLE : SVIOC_DISABLE); - log_str1 = (enable? gettext("enabled %s") : gettext("disabled %s")); - log_str2 = (enable? gettext("unable to enable %s") : - gettext("unable to disable %s")); - spcs_err = (enable? SV_EENABLED : SV_EDISABLED); - bzero(&svc, sizeof (svc)); - - if (devhash) - statinfo = nsc_lookup(devhash, path); - - if (statinfo) { - if (!S_ISCHR(statinfo->mode)) - goto error; - svc.svc_major = major(statinfo->rdev); - svc.svc_minor = minor(statinfo->rdev); - } else { - if (stat(path, &stb) != 0) - goto error; - - if (!S_ISCHR(stb.st_mode)) - goto error; - svc.svc_major = major(stb.st_rdev); - svc.svc_minor = minor(stb.st_rdev); - } - - strncpy(svc.svc_path, path, sizeof (svc.svc_path)); - - fd = open(SV_DEVICE, O_RDONLY); - if (fd < 0) - goto error; - - svc.svc_flag = (NSC_DEVICE | NSC_CACHE); - svc.svc_error = spcs_s_ucreate(); - - do { - rc = ioctl(fd, sv_ioctl, &svc); - } while (rc < 0 && errno == EINTR); - - if (rc < 0) { - if (errno != spcs_err) { - spcs_log("sv", &svc.svc_error, log_str2, svc.svc_path); - if (enable) - goto error; - else - err = errno; - } else - err = spcs_err; - } - - spcs_log("sv", NULL, log_str1, svc.svc_path); - - /* SV enable succeeded */ - if (caller_cfg == NULL) /* was not previously locked */ - if (!cfg_lock(cfg, CFG_WRLOCK)) - goto error; - - if (err != spcs_err) { /* already enabled, already in config */ - if (enable) { - cfg_rewind(cfg, CFG_SEC_CONF); - (void) snprintf(buf, CFG_MAX_BUF, "%s - %s", path, - ctag? ctag : "-"); - if (cfg_put_cstring(cfg, "sv", buf, CFG_MAX_BUF) < 0) { - /* SV config not updated, so SV disable again */ - (void) ioctl(fd, SVIOC_DISABLE, &svc); - print_log++; - } else - cfg_changed = 1; - } else { - /* pull it out of the config */ - if (!svol_loaded) { - if (cfg_load_svols(cfg) < 0) { - if (NULL == caller_cfg) { - cfg_close(cfg); - } - return (-1); - } - self_loaded = 1; - } - node = nsc_lookup(svol, svc.svc_path); - if (node) { - cfg_rewind(cfg, CFG_SEC_CONF); - (void) snprintf(key, CFG_MAX_KEY, "sv.set%d", - node->setno); - if (cfg_put_cstring(cfg, key, NULL, NULL) < 0) { - spcs_log("sv", NULL, - gettext("failed to remove %s from " - "sv config"), svc.svc_path); - } - /* - * Since we deleted an entry from the config - * file, we don't know what all the new - * set numbers are. We need to reload - * everything - */ - if (!self_loaded) { - cfg_unload_svols(); - if (cfg_load_svols(cfg) < 0) { - if (NULL == caller_cfg) { - cfg_close(cfg); - } - return (-1); - } - } - cfg_changed = 1; - } - if (self_loaded) { - cfg_unload_svols(); - self_loaded = 0; - } - } - } - -#ifdef lint - (void) printf("extra line to shut lint up %s\n", module_names[0]); -#endif - -error: - if (fd >= 0) - (void) close(fd); - - if (cfg == NULL) - return (-1); - - if (cfg_changed) - if (caller_cfg == NULL) /* we opened config */ - (void) cfg_commit(cfg); - - if (caller_cfg == NULL) - cfg_close(cfg); - if ((cfg_changed) || (err == spcs_err)) - return (1); - if (print_log) - spcs_log("sv", NULL, - gettext("unable to add to configuration, disabled %s"), - svc.svc_path); - spcs_s_ufree(&svc.svc_error); - - return (-1); -} - -/* - * add_dev_entry - * - * Add an entry into the devlist and the devhash for future lookups. - * - * Return values: - * -1 An error occurred. - * 0 Entry added - * 1 Entry already exists. - */ -static int -add_dev_entry(const char *path) -{ - struct stat buf; - device_t *newmem; - hash_data_t *data; - - if (!devhash) { - devhash = nsc_create_hash(); - if (!devhash) { - return (-1); - } - } else { - data = nsc_lookup(devhash, path); - if (data) { - return (1); - } - } - - if (stat(path, &buf) < 0) { - /* ignore error, we are most likely deleting entry anyway */ - buf.st_rdev = 0; - } - - if (devcount >= devalloc) { - /* make some room */ - devalloc += DEV_EXPAND; - newmem = (device_t *)realloc(devlist, devalloc * - sizeof (device_t)); - if (!newmem) { - free_dev_entries(); - return (-1); - } else { - devlist = newmem; - } - } - - devlist[ devcount ].path = strdup(path); - devlist[ devcount ].rdev = buf.st_rdev; - devlist[ devcount ].mode = buf.st_mode; - - if (nsc_insert_node(devhash, &devlist[devcount], path) < 0) { - return (-1); - } - - ++devcount; - return (0); -} - -static void -rebuild_devhash() -{ - int i; - - if (!devhash) - nsc_remove_all(devhash, 0); - - devhash = nsc_create_hash(); - if (!devhash) - return; - - for (i = 0; i < devcount; i++) { - nsc_insert_node(devhash, &devlist[i], devlist[i].path); - } -} - -static int -compare(const void *va, const void *vb) -{ - device_t *a = (device_t *)va; - device_t *b = (device_t *)vb; - - return (b->rdev - a->rdev); -} - -static char * -find_devid(const char *path) -{ - device_t key; - device_t *result; - struct stat buf; - - if (!devlist || !devhash) - return (NULL); - - /* See if we already know the device id by this name */ - result = (device_t *)nsc_lookup(devhash, path); - if (result) { - return (NULL); - } - - /* try to find it by another name */ - if (stat(path, &buf) < 0) - return (NULL); - - key.rdev = buf.st_rdev; - - /* it's storted, so we use the binary-chop method to find it */ - result = bsearch(&key, devlist, devcount, sizeof (device_t), compare); - - if (result) { - return (result->path); - } - - return (NULL); -} - -static void -free_dev_entries() -{ - int i; - device_t *p; - - if (!devlist) { - return; - } - for (i = 0, p = devlist; i < devcount; i++, p++) { - free(p->path); - } - free(devlist); - devlist = NULL; - devcount = 0; - devalloc = 0; - - if (devhash) { - nsc_remove_all(devhash, 0); - devhash = NULL; - } -} diff --git a/usr/src/lib/libdscfg/common/mapfile-vers b/usr/src/lib/libdscfg/common/mapfile-vers deleted file mode 100644 index 0e1f4f4cae..0000000000 --- a/usr/src/lib/libdscfg/common/mapfile-vers +++ /dev/null @@ -1,100 +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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. -# -# - -# -# MAPFILE HEADER START -# -# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. -# Object versioning must comply with the rules detailed in -# -# usr/src/lib/README.mapfiles -# -# You should not be making modifications here until you've read the most current -# copy of that file. If you need help, contact a gatekeeper for guidance. -# -# MAPFILE HEADER END -# - -# -# Generic interface definition for usr/src/lib/libcfg. -# - - -$mapfile_version 2 - -SYMBOL_VERSION SUNWprivate_1.1 { - global: - cfg_get_cstring; - cfg_put_cstring; - cfg_find_cstring; - cfg_get_options; - cfg_put_options; - cfg_open; - cfg_close; - cfg_rewind; - cfg_update_parser_config; - cfg_lock; - cfg_unlock; - cfg_get_lock; - cfg_resource; - cfg_commit; - cfg_location; - cfg_error; - cfg_iscluster; - cfg_issuncluster; - cfg_dgname; - cfg_dgname_islocal; - cfg_lfinit; - cfg_filelock; - cfg_fileunlock; - cfg_readpid; - cfg_writepid; - cfg_lockd_stat; - cfg_invalidate_hsizes; - cfg_cfg_isempty; - cfg_get_section; - cfg_get_num_entries; - cfg_add_user; - cfg_rem_user; - cfg_vol_enable; - cfg_vol_disable; - cfg_load_dsvols; - cfg_unload_dsvols; - cfg_load_svols; - cfg_unload_svols; - cfg_load_shadows; - cfg_unload_shadows; - cfg_get_canonical_name; - cfg_get_tags; - cfg_is_cfg; - cfg_get_srtdsec; - cfg_free_section; - cfg_shldskip_vtoc; - cfg_get_single_option; - cfg_del_option; - cfg_get_resource; - cfg_l_dgname; - local: - *; -}; |