4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
28 #include <sys/types.h>
31 #include <sys/mnttab.h>
51 #include <sys/utsname.h>
55 #include "cfg_lockd.h"
65 #define MAX_CFG 16 /* Max. number of lines in /etc/dscfg_format */
66 #define MAX_SET 12 /* number of chars in a set name */
69 /* parser tree for config section */
70 static struct parser chead
[MAX_CFG
] = { NULL
};
71 static int chead_loaded
= 0;
72 static char config_file
[CFG_MAX_BUF
];
73 static char dectohex
[] = { '0', '1', '2', '3', '4', '5', '6', '7',
74 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
75 #define CHARS_TO_ENCODE "=;\t "
76 #define min(a, b) ((a) > (b) ? (b) : (a))
78 /* field to be sorted on in sorting routines */
79 static struct sortby_s
{
80 char section
[CFG_MAX_KEY
];
81 char field
[CFG_MAX_KEY
];
88 static int cfg_read(cfp_t
*);
89 static void cfg_read_parser_config(cfp_t
*);
90 static int cfg_rdlock(CFGFILE
*);
91 static int cfg_wrlock(CFGFILE
*);
93 void cfg_replace_lists(cfp_t
*);
94 void cfg_free_parser_tree();
95 void cfg_invalidate_hsizes(int, const char *);
96 int cfg_map_cfglists(cfp_t
*);
97 int cfg_hdrcmp(cfp_t
*);
98 void cfg_free_cfglist(cfp_t
*);
100 extern cfg_io_t
*cfg_block_io_provider(void);
101 extern cfg_io_t
*cfg_raw_io_provider(void);
102 extern int cl_initialized
;
106 dump_status(cfp_t
*cfp
, char *str
)
108 printf("called from %s\n", str
);
109 printf(gettext("Header info:\n"
110 "\tmagic: %x\tstate: %x\n"),
111 cfp
->cf_head
->h_magic
, cfp
->cf_head
->h_state
);
112 printf(gettext("Parser section:\n"
113 "Start: %x\tsize: %d\toffset: %d\n"),
114 cfp
->cf_mapped
, cfp
->cf_head
->h_parsesize
,
115 cfp
->cf_head
->h_parseoff
);
116 printf(gettext("Config section:\n"
117 "Start: %x\tsize:%d\tacsize: %d\n"),
118 cfp
->cf_head
->h_cparse
, cfp
->cf_head
->h_csize
,
119 cfp
->cf_head
->h_acsize
);
120 printf("\n\tccopy1: %x\tccopy2: %x\n",
121 cfp
->cf_head
->h_ccopy1
, cfp
->cf_head
->h_ccopy2
);
122 printf(gettext("Sequence:\n"
123 "\tseq1: %d\t\tseq2: %d\n"),
124 cfp
->cf_head
->h_seq1
, cfp
->cf_head
->h_seq2
);
130 * return position from parser config given tag and field
133 cfg_get_item(struct parser
*tbl
, const char *tag
, const char *field
)
138 for (i
= 0; i
< MAX_CFG
; i
++) {
139 /* only as many lists as defined */
140 if (tbl
[i
].tag
.l_word
[0] == '\0') {
144 if (strcmp(tbl
[i
].tag
.l_word
, tag
) == 0)
148 /* Handle table size */
152 if (strcmp(p
->l_word
, field
) == 0)
164 * return number of fields for given parser tag
167 cfg_get_num_flds(struct parser
*tbl
, const char *tag
, int *table_index
)
173 for (i
= 0; i
< MAX_CFG
; i
++) {
174 /* only as many lists as defined */
175 if (tbl
[i
].tag
.l_word
[0] == '\0') {
179 if (strcmp(tbl
[i
].tag
.l_word
, tag
) == 0) {
185 /* Handle table size */
199 * count white space fields
202 cfg_cnt_flds(char *value
)
205 char buf
[CFG_MAX_BUF
];
208 if ((value
== NULL
) || (strlen(value
) >= CFG_MAX_BUF
))
211 bzero(buf
, CFG_MAX_BUF
);
213 ptr
= strtok(buf
, " ");
216 ptr
= strtok(NULL
, " ");
222 * cfg_get_parser_offset
223 * returns the index for each
224 * section of the parser..
225 * ie. parser info for sndr is chead[3].tag.l_word
226 * this will help us find sndr quicker, as the
227 * the memory picture of the sets mimic this ordering
230 cfg_get_parser_offset(const char *section
)
234 for (i
= 0; i
< MAX_CFG
; i
++) {
235 /* only as many lists as defined */
236 if (chead
[i
].tag
.l_word
[0] == '\0') {
240 if (strcmp(chead
[i
].tag
.l_word
, section
) == 0)
244 /* Handle table size */
249 cfg_perror_str
= dgettext("cfg",
250 "cfg_get_parser_offset: section not found");
251 cfg_severity
= CFG_EFATAL
;
258 * move fields from old buffer to new
259 * moving only specified fields
261 * returns fields moved
264 cfg_fld_mov(char *newbuf
, char *oldbuf
, int start
, int end
)
266 char buf
[CFG_MAX_BUF
];
270 bzero(buf
, CFG_MAX_BUF
);
274 if ((start
> end
) || (strlen(oldbuf
) >= CFG_MAX_BUF
)) {
280 ptr
= strtok(buf
, " ");
283 if (flds
>= start
&& flds
<= end
) {
287 ptr
= strtok(NULL
, " ");
295 * return indication if this raw buf should be returned
296 * checks cfg->cf_node for filtering
297 * We already know that this buf meets most of our criteria
298 * find the cnode field in the buf and see if it matches
304 cfg_filter_node(CFGFILE
*cfg
, struct parser
*tbl
, char *buf
, char *tag
)
306 char tmpbuf
[CFG_MAX_BUF
];
311 if (!cfg
->cf_node
) /* no filter always good */
313 bzero(tmpbuf
, CFG_MAX_BUF
);
314 fld
= cfg_get_item(tbl
, tag
, "cnode");
315 if (fld
< 0) /* no cnode field always good */
317 strncpy(tmpbuf
, buf
, CFG_MAX_BUF
);
318 if (tmpbuf
[CFG_MAX_BUF
- 1] != '\0')
320 ptr
= strtok(tmpbuf
, " ");
321 while (ptr
&& (i
< fld
)) {
322 ptr
= strtok(NULL
, " ");
328 (void) fprintf(stderr
, "cfg_filter_node: node=%s:%d cnode=%s:%d\n",
329 cfg
->cf_node
, strlen(cfg
->cf_node
), ptr
, strlen(ptr
));
331 if (strcmp(ptr
, cfg
->cf_node
) == 0)
337 * insert resource in bufs which contain cnode parser field
340 cfg_insert_node(CFGFILE
*cfg
, struct parser
*tbl
, char *buf
, char *tag
)
342 char tmpbuf
[CFG_MAX_BUF
];
347 bzero(tmpbuf
, CFG_MAX_BUF
);
349 fld
= cfg_get_item(tbl
, tag
, "cnode");
350 nflds
= cfg_get_num_flds(tbl
, tag
, &table_index
);
351 if ((fld
< 0) && !(cfg
->cf_node
)) /* no cnode field always good */
354 cfg_fld_mov(tmpbuf
, buf
, 1, (fld
- 1));
356 strcat(tmpbuf
, cfg
->cf_node
);
360 cfg_fld_mov(tmpbuf
, buf
, (fld
+ 1), nflds
);
361 bcopy(tmpbuf
, buf
, strlen(tmpbuf
) + 1);
366 * Parser current buffer to see if a non-empty " - " cnode exists
370 cfg_is_cnode(CFGFILE
*cfg
, struct parser
*tbl
, char *buf
, char *tag
)
372 char tmpbuf
[CFG_MAX_BUF
];
373 int fld
= cfg_get_item(tbl
, tag
, "cnode");
377 cfg_fld_mov(tmpbuf
, buf
, fld
, fld
);
378 return (strcmp(tmpbuf
, "- ") ? TRUE
: FALSE
);
384 * key determines section and value
385 * special considerations:
387 * AA = data service tag
388 * BB = set number relative to first set (1..n)
389 * CC = field of set or if absent, all
392 cfg_get_cstring(CFGFILE
*cfg
, const char *key
, void *value
, int value_len
)
395 char buf
[CFG_MAX_BUF
];
396 char tmpkey
[CFG_MAX_KEY
];
411 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
412 cfg_severity
= CFG_EFATAL
;
416 if (!cfg_rdlock(cfg
)) {
417 cfg_perror_str
= dgettext("cfg", CFG_NOTLOCKED
);
418 cfg_severity
= CFG_EFATAL
;
422 bzero(buf
, sizeof (buf
));
423 bzero(set
, sizeof (set
));
424 bzero(tmpkey
, sizeof (tmpkey
));
426 section
= strtok(tmpkey
, ".");
427 setp
= strtok(NULL
, ".");
428 itemp
= strtok(NULL
, ".");
432 (void) fprintf(stderr
, "cfg_get_cstring:section:%s setp=%s\n",
435 (void) fprintf(stderr
,
436 "cfg_get_cstring:section:%s setp=%s fld=%s\n",
437 section
, setp
, itemp
);
440 table_offset
= cfg_get_parser_offset(section
);
441 setnum
= atoi(setp
+ 3);
442 if ((setnum
< 1) || (setnum
> 0x7ffd)) {
444 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
445 cfg_severity
= CFG_ENONFATAL
;
450 * we have to figure out where this set is
451 * in relation to other sets
456 for (cfp
= &cfg
->cf
[0]; cfp
<= &cfg
->cf
[1]; cfp
++) {
457 if (!cfp
->cf_fd
) continue;
458 if (cfp
->cf_head
->h_state
& CFG_HDR_INVALID
) {
459 if (!cfg_read(cfp
)) {
460 cfg_perror_str
= dgettext("cfg", CFG_RDFAILED
);
461 cfg_severity
= CFG_EFATAL
;
465 while (numfound
< setnum
) {
466 if ((*cfp
->cf_pp
->readcf
)
467 (cfp
, buf
, table_offset
, relnum
- secnum
) == NULL
) {
471 if (cfg_filter_node(cfg
, &chead
[0], buf
, section
))
474 if (numfound
== setnum
)
479 if (numfound
== setnum
)
483 /* Fail to find anything? */
484 if (cfp
>= &cfg
->cf
[2]) {
486 cfg_perror_str
= dgettext("cfg", strerror(errno
));
487 cfg_severity
= CFG_ENONFATAL
;
493 strncpy(value
, buf
, value_len
);
498 needed
= cfg_get_item(&chead
[0], section
, itemp
);
499 p
= strtok(buf
, " ");
507 if (strlen(p
) > value_len
) {
517 strncpy(value
, p
, value_len
);
521 p
= strtok(NULL
, " ");
529 cfg_perror_str
= dgettext("cfg", strerror(errno
));
530 cfg_severity
= CFG_ENONFATAL
;
536 * search for a string in the specified section
537 * in the specified field(s)
538 * if nfld is 0, then the string is searched for in
539 * every field of the entry
540 * the set number of the first occurence of target is returned
541 * ie. if /dev/vx/rdsk/vol10 is found in sndr.set9, 9 will be returned
542 * that is, of course, if the correct field was searched on.
547 cfg_find_cstring(CFGFILE
*cfg
, const char *target
,
548 const char *section
, int numflds
, ...)
553 char buf
[CFG_MAX_BUF
];
555 char **fldbuf
= NULL
;
563 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
564 cfg_severity
= CFG_EFATAL
;
569 nflds
= cfg_get_num_flds(&chead
[0], section
, &tbl_off
);
574 if ((fldbuf
= calloc(nflds
, CFG_MAX_KEY
)) == NULL
) {
575 cfg_perror_str
= dgettext("cfg", strerror(errno
));
576 cfg_severity
= CFG_EFATAL
;
580 if (numflds
== 0) { /* search the whole string */
581 if ((rc
= cfg_get_section(cfg
, &list
, section
)) <= 0) {
582 for (i
= 0; i
< nflds
; i
++)
587 for (i
= 0; i
< rc
; i
++) {
588 bzero(buf
, sizeof (buf
));
589 strcpy(buf
, list
[i
]);
590 p
= strtok(buf
, " ");
592 if (strcmp(p
, target
) == 0) { /* we found it! */
593 for (j
= 0; j
< rc
; j
++)
596 for (j
= 0; j
< nflds
; j
++)
601 p
= strtok(NULL
, " ");
604 for (i
= 0; i
< nflds
; i
++)
606 for (i
= 0; i
< rc
; i
++)
613 if ((rc
= cfg_get_section(cfg
, &list
, section
)) <= 0) {
614 for (i
= 0; i
< nflds
; i
++)
620 va_start(ap
, numflds
);
621 for (i
= 0; i
< numflds
; i
++) {
622 fldbuf
[i
] = strdup(va_arg(ap
, char *));
627 for (j
= 0; j
< numflds
; j
++) {
628 fieldnum
= cfg_get_item(&chead
[0], section
, fldbuf
[j
]);
629 for (i
= 0; i
< rc
; i
++) {
630 bzero(buf
, sizeof (buf
));
631 strcpy(buf
, list
[i
]);
633 field
= strtok(buf
, " ");
635 while (pos
< fieldnum
) {
636 field
= strtok(NULL
, " ");
640 for (j
= 0; j
< numflds
; j
++)
642 for (j
= 0; j
< rc
; j
++)
649 if (strcmp(field
, target
) == 0) {
650 for (j
= 0; j
< numflds
; j
++)
652 for (j
= 0; j
< rc
; j
++)
663 for (i
= 0; i
< nflds
; i
++)
665 for (i
= 0; i
< rc
; i
++)
674 * modify entry or add an entry to configuration section
675 * Key syntax supported
676 * tag Add entry (in entirely) to config
677 * tag.setn Add entry to setn If it exists overwrite old entry
678 * tag.setn.field Change field in setn
681 * NULL delete specified key
686 cfg_put_cstring(CFGFILE
*cfg
, const char *key
, void *value
, int val_len
)
689 char buf
[CFG_MAX_BUF
];
690 char newbuf
[CFG_MAX_BUF
];
692 char tmpkey
[CFG_MAX_KEY
];
708 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
709 cfg_severity
= CFG_EFATAL
;
713 bzero(buf
, sizeof (buf
));
715 section
= strtok(tmpkey
, ".");
716 setp
= strtok(NULL
, ".");
717 itemp
= strtok(NULL
, ".");
719 if (!cfg_wrlock(cfg
)) {
720 cfg_perror_str
= dgettext("cfg", CFG_RDFAILED
);
721 cfg_severity
= CFG_EFATAL
;
726 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
727 cfg_severity
= CFG_ENONFATAL
;
730 if (value
&& val_len
== 0) {
731 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
732 cfg_severity
= CFG_ENONFATAL
;
740 setnum
= atoi(setp
+ 3);
741 if (setnum
< 1 || setnum
> 0x7ffd) {
743 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
744 cfg_severity
= CFG_ENONFATAL
;
749 table_offset
= cfg_get_parser_offset(section
);
752 * we have to figure out where this set is
753 * in relation to other sets
759 if (setp
&& nofield
) {
760 char tmpbuf
[CFG_MAX_BUF
];
766 * Set specified but no field
768 for (cfp
= &cfg
->cf
[0]; cfp
<= &cfg
->cf
[1]; cfp
++) {
769 if (!cfp
->cf_fd
) continue;
770 if (cfp
->cf_head
->h_state
& CFG_HDR_INVALID
) {
771 if (!cfg_read(cfp
)) {
773 dgettext("cfg", CFG_RDFAILED
);
774 cfg_severity
= CFG_EFATAL
;
778 while (numfound
< setnum
) {
779 if ((*cfp
->cf_pp
->readcf
)
780 (cfp
, tmpbuf
, table_offset
, relnum
- secnum
)
785 if (cfg_filter_node(cfg
, &chead
[0], tmpbuf
,
789 if (numfound
== setnum
)
794 if (numfound
== setnum
)
798 /* Fail to find anything? */
799 if (cfp
>= &cfg
->cf
[2]) {
801 cfg_perror_str
= dgettext("cfg", strerror(errno
));
802 cfg_severity
= CFG_ENONFATAL
;
806 nflds
= cfg_get_num_flds(&chead
[0], section
, &table_index
);
809 /* Remove entry completely */
811 rc
= (*cfp
->cf_pp
->remcf
)(cfp
, table_index
,
818 got
= cfg_cnt_flds(value
);
819 bzero(buf
, sizeof (buf
));
821 strncpy(buf
, " ", 1);
822 if (strlen(value
) > sizeof (buf
) - 2) {
824 cfg_perror_str
= dgettext("cfg", strerror(errno
));
825 cfg_severity
= CFG_ENONFATAL
;
828 strncat(buf
, value
, val_len
);
830 for (/* CSTYLED */; got
< nflds
; got
++)
831 strncat(buf
, " - ", 3);
832 } else if (got
> nflds
) {
835 /* got == nflds, so cnode was included */
841 cfg_insert_node(cfg
, &chead
[0], buf
, section
);
844 (*cfp
->cf_pp
->replacecf
)(cfp
, bufp
, table_index
,
851 * Both Set and field are specified
852 * needs to get current whole entry and old requested field
853 * copy good fields to buf, replace new field in buf
854 * move everything depending of new size
855 * replace entry so set# does not change
862 for (cfp
= &cfg
->cf
[0]; cfp
<= &cfg
->cf
[1]; cfp
++) {
863 if (!cfp
->cf_fd
) continue;
864 if (cfp
->cf_head
->h_state
& CFG_HDR_INVALID
) {
865 if (!cfg_read(cfp
)) {
867 dgettext("cfg", CFG_RDFAILED
);
868 cfg_severity
= CFG_EFATAL
;
872 while (numfound
< setnum
) {
873 if ((*cfp
->cf_pp
->readcf
)
874 (cfp
, buf
, table_offset
, relnum
- secnum
)
879 if (cfg_filter_node(cfg
, &chead
[0], buf
,
883 if (numfound
== setnum
)
888 if (numfound
== setnum
)
892 /* Fail to find anything? */
893 if (cfp
>= &cfg
->cf
[2]) {
895 cfg_perror_str
= dgettext("cfg", strerror(errno
));
896 cfg_severity
= CFG_ENONFATAL
;
900 nflds
= cfg_get_num_flds(&chead
[0], section
, &table_index
);
901 fldnum
= cfg_get_item(&chead
[0], section
, itemp
);
902 bzero(newbuf
, sizeof (newbuf
));
903 strncpy(newbuf
, " ", 1);
905 /* move good flds in */
906 rc
= cfg_fld_mov(newbuf
, buf
, 1, fldnum
- 1);
910 /* move new fld in */
911 strncat(newbuf
, value
, strlen(value
));
914 /* move remaining flds in */
915 rc
= cfg_fld_mov(newbuf
, buf
, fldnum
+ 1, nflds
);
919 cnodepos
= cfg_get_item(&chead
[0], section
, "cnode");
920 if ((cnodepos
>= 0) && strcmp(itemp
, "cnode") != 0) {
921 /* add cnode if user didn't specify it */
922 cfg_insert_node(cfg
, &chead
[0],
926 (*cfp
->cf_pp
->replacecf
)(cfp
, newbuf
, table_index
,
932 if (noset
) { /* blast entire thing in */
938 if (!value
) { /* we shouldn't be here */
942 strncat(buf
, " ", 1);
943 if (strlen(value
) > sizeof (buf
) - 2) {
948 strncat(buf
, value
, val_len
);
949 nflds
= cfg_get_num_flds(&chead
[0], section
, &table_index
);
950 got
= cfg_cnt_flds(value
);
952 cnodepos
= cfg_get_item(&chead
[0], section
, "cnode");
953 if (cnodepos
< 0 || got
>= cnodepos
) {
954 /* no cnode, or cnode was specified by caller */
959 for (/* CSTYLED */; got
< nflds
; got
++)
960 strncat(buf
, " - ", 3);
961 } else if (got
> nflds
) {
962 errno
= EINVAL
; /* specified too many fields */
965 /* got == nflds, so cnode was included */
970 cfg_insert_node(cfg
, &chead
[0], buf
, section
);
973 /* Make sure we put this entry in the right database */
974 if (cfg_is_cnode(cfg
, &chead
[0], buf
, section
) &&
980 if (cfp
->cf_head
->h_state
& CFG_HDR_INVALID
) {
981 if (!cfg_read(cfp
)) {
982 cfg_perror_str
= dgettext("cfg", CFG_RDFAILED
);
983 cfg_severity
= CFG_EFATAL
;
987 if (cfp
->cf_head
->h_csize
+ strlen(buf
) > CFG_DEFAULT_SSIZE
) {
992 (*cfp
->cf_pp
->addcf
)(cfp
, bufp
, table_index
);
998 cfg_perror_str
= strerror(errno
);
999 cfg_severity
= CFG_ENONFATAL
;
1006 * Encode a single character into % + hex ascii value
1009 cfg_encode_char(char *result
, char ch
)
1012 *result
++ = dectohex
[ (ch
>> 4) & 0xf ];
1013 *result
++ = dectohex
[ ch
& 0xf ];
1019 * Reverses cfg_encode_char
1022 cfg_decode_char(char *code
)
1029 if (!isxdigit(*code
))
1031 retval
= (isdigit(*code
)? *code
- '0' : *code
- 'a' + 10);
1034 if (!isxdigit(*code
))
1036 retval
|= (isdigit(*code
)? *code
- '0' : *code
- 'a' + 10);
1044 * Transforms the key and value strings so that special characters
1045 * can be used within the options field.
1048 * Length of encoded string; -1 on failure
1051 cfg_encode_string(char *str
, char *output
, int outlen
)
1057 /* first, scan through the tag string converting %-signs */
1061 while (*p
&& curlen
< outlen
) {
1063 if (curlen
+ 3 >= outlen
) {
1066 cfg_encode_char(q
, *p
);
1075 if (curlen
< outlen
)
1078 /* now encode special characters */
1079 p
= mem
= strdup(output
);
1082 while (*p
&& curlen
< outlen
) {
1083 if (strchr(CHARS_TO_ENCODE
, *p
) != 0) {
1084 if (curlen
+ 3 >= outlen
) {
1088 cfg_encode_char(q
, *p
);
1099 if (curlen
< outlen
)
1101 /* LINTED possible ptrdiff_t overflow */
1102 return (q
- output
);
1108 * Given a string, decodes any %-encodes on it.
1111 cfg_decode_string(char *str
, char *output
, int outlen
)
1119 while (*p
&& curlen
< outlen
) {
1121 char ch
= cfg_decode_char(p
);
1135 if (curlen
< outlen
)
1141 * return first options set from basekey
1142 * Subsequent calls with basekey = NULL return next option if any
1145 * true success and more options data
1146 * -1 no options data
1150 cfg_get_options(CFGFILE
*cfg
, int section
, const char *basekey
, char *tag
,
1151 int tag_len
, char *val
, int val_len
)
1153 static char buf
[CFG_MAX_BUF
];
1154 char decode_buf
[CFG_MAX_BUF
];
1159 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
1160 cfg_severity
= CFG_EFATAL
;
1166 ttag
= strtok(NULL
, "=");
1168 bzero(buf
, CFG_MAX_BUF
);
1169 if (section
== CFG_SEC_CONF
) {
1170 rc
= cfg_get_cstring(cfg
, basekey
, buf
, CFG_MAX_BUF
);
1175 /* buf now contains raw options data */
1176 ttag
= strtok(buf
, "=");
1178 tval
= strtok(NULL
, ";");
1179 if (!(tval
) || !(ttag
))
1181 if ((strlen(tval
) > val_len
) || (strlen(ttag
) > tag_len
)) {
1185 cfg_decode_string(tval
, decode_buf
, CFG_MAX_BUF
);
1186 strncpy(val
, decode_buf
, val_len
);
1187 cfg_decode_string(ttag
, decode_buf
, CFG_MAX_BUF
);
1188 strncpy(tag
, decode_buf
, tag_len
);
1196 * Replaces existing tag with new val. If tag doesn't exist,
1197 * then it adds a new tag with the specified val.
1201 * -1 incorrect section, or read error from cfg DB
1204 cfg_put_options(CFGFILE
*cfg
, int section
, const char *basekey
, char *tag
,
1207 char buf
[CFG_MAX_BUF
];
1208 char encode_buf
[CFG_MAX_BUF
];
1213 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
1214 cfg_severity
= CFG_EFATAL
;
1219 bzero(buf
, CFG_MAX_BUF
);
1220 if (section
!= CFG_SEC_CONF
) {
1221 cfg_severity
= CFG_ENONFATAL
;
1222 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
1225 if (!tag
|| !*tag
|| !val
|| !*val
)
1227 if (cfg_get_cstring(cfg
, basekey
, buf
, CFG_MAX_BUF
) < 0) {
1228 /* cfg severity & perror_str set up cfg_get_cstring() */
1232 enclen
= cfg_encode_string(tag
, &encode_buf
[1], CFG_MAX_BUF
- 1) + 1;
1233 if (enclen
< 1 || (enclen
+ 1) >= CFG_MAX_BUF
) {
1234 cfg_severity
= CFG_ENONFATAL
;
1235 cfg_perror_str
= dgettext("cfg", "Buffer too small");
1238 encode_buf
[enclen
] = '=';
1239 encode_buf
[enclen
+ 1] = '\0';
1241 /* check the start of the string */
1242 if (strncmp(buf
, &encode_buf
[1], enclen
) == 0) {
1243 /* locate the end of this option */
1244 p
= strchr(buf
, ';');
1245 if (p
&& *(p
+ 1) != '\0') {
1246 /* add the new tag to the end */
1248 strcat(p
, &encode_buf
[1]);
1250 /* completely overwrite the existing tag */
1252 strcpy(p
, &encode_buf
[1]);
1254 if (cfg_encode_string(val
, encode_buf
, CFG_MAX_BUF
) < 0) {
1255 cfg_severity
= CFG_ENONFATAL
;
1256 cfg_perror_str
= dgettext("cfg", "Buffer too small");
1259 strcat(p
, encode_buf
);
1261 if (cfg_put_cstring(cfg
, basekey
, p
, strlen(p
)) < 0) {
1262 /* severity & perror_str set by cfg_put_cstring */
1269 /* it's hiding somewhere inside... */
1270 p
= strstr(buf
, encode_buf
);
1272 /* delete the old value */
1273 char *q
= strchr(p
+ 1, ';');
1275 strcpy(p
+ 1, q
+ 1);
1279 strcat(buf
, &encode_buf
[1]);
1281 strcat(buf
, &encode_buf
[1]);
1283 strcpy(buf
, &encode_buf
[1]);
1285 enclen
= cfg_encode_string(val
, encode_buf
, CFG_MAX_BUF
);
1286 if (enclen
< 0 || (strlen(buf
) + enclen
) >= CFG_MAX_BUF
) {
1287 cfg_severity
= CFG_ENONFATAL
;
1288 cfg_perror_str
= dgettext("cfg", "Buffer too small");
1291 strcat(buf
, encode_buf
);
1293 if (cfg_put_cstring(cfg
, basekey
, buf
, CFG_MAX_BUF
) < 0) {
1294 /* severity & perror_str set by cfg_put_cstring */
1302 * cfg_get_single_option
1304 * Scans the options string for the specified option and returns
1309 * -1 incorrect section, or read error from cfg DB
1312 cfg_get_single_option(CFGFILE
*cfg
, int section
, const char *basekey
, char *tag
,
1313 char *val
, int val_len
)
1315 char buf
[CFG_MAX_BUF
];
1316 char encode_buf
[CFG_MAX_BUF
];
1321 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
1322 cfg_severity
= CFG_EFATAL
;
1327 bzero(buf
, CFG_MAX_BUF
);
1328 if (section
!= CFG_SEC_CONF
) {
1329 cfg_severity
= CFG_ENONFATAL
;
1330 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
1333 if (cfg_get_cstring(cfg
, basekey
, buf
, CFG_MAX_BUF
) < 0) {
1334 /* severity & perror_str set by cfg_get_cstring */
1339 enclen
= cfg_encode_string(tag
, &encode_buf
[1], CFG_MAX_BUF
- 1) + 1;
1340 if (enclen
< 1 || (enclen
+ 1) >= CFG_MAX_BUF
) {
1341 cfg_severity
= CFG_ENONFATAL
;
1342 cfg_perror_str
= dgettext("cfg", "Buffer too small");
1345 encode_buf
[enclen
] = '=';
1346 encode_buf
[enclen
+ 1] = '\0';
1348 /* check the start of the string */
1349 if (strncmp(buf
, &encode_buf
[1], enclen
) == 0) {
1350 p
= strchr(buf
, '=');
1352 cfg_severity
= CFG_ENONFATAL
;
1353 cfg_perror_str
= dgettext("cfg", "Option not found");
1361 cfg_decode_string(p
, val
, val_len
);
1366 /* it's hiding somewhere inside... */
1367 p
= strstr(buf
, encode_buf
);
1374 cfg_decode_string(p
, val
, val_len
);
1387 * Removes a single key=val pair from the specified option field
1391 * -1 unable to update config
1394 cfg_del_option(CFGFILE
*cfg
, int section
, const char *basekey
, char *tag
)
1396 char buf
[CFG_MAX_BUF
];
1397 char encode_buf
[CFG_MAX_BUF
];
1402 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
1403 cfg_severity
= CFG_EFATAL
;
1407 bzero(buf
, CFG_MAX_BUF
);
1408 if (section
!= CFG_SEC_CONF
) {
1409 cfg_severity
= CFG_ENONFATAL
;
1410 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
1413 if (cfg_get_cstring(cfg
, basekey
, buf
, CFG_MAX_BUF
) < 0) {
1414 /* severity & perror_str are set by cfg_get_cstring */
1419 enclen
= cfg_encode_string(tag
, &encode_buf
[1], CFG_MAX_BUF
- 1) + 1;
1420 if (enclen
< 1 || (enclen
+ 1) >= CFG_MAX_BUF
) {
1421 cfg_severity
= CFG_ENONFATAL
;
1422 cfg_perror_str
= dgettext("cfg", "Buffer too small");
1425 encode_buf
[enclen
] = '=';
1426 encode_buf
[enclen
+ 1] = '\0';
1428 /* check the start of the string */
1429 if (strncmp(buf
, &encode_buf
[1], enclen
) == 0) {
1430 p
= strchr(buf
, ';');
1431 if (p
&& (*(p
+ 1) != '\0')) {
1432 rc
= cfg_put_cstring(cfg
, basekey
, p
+ 1,
1435 rc
= cfg_put_cstring(cfg
, basekey
, "-", 1);
1437 /* severity & perror_str are set by cfg_put_cstring */
1442 p
= strstr(buf
, encode_buf
);
1444 /* already removed */
1447 q
= strchr(p
+ 1, ';');
1450 * Now the string looks like:
1451 * | first few options | *p | option to remove | *q | rest | '\0'
1461 return (cfg_put_cstring(cfg
, basekey
, buf
, strlen(buf
)));
1465 cfg_set_memorymap(cfp_t
*cfp
)
1467 cfgheader_t
*hd
= cfp
->cf_head
;
1469 #ifdef DEBUG_CFGLIST
1470 (void) fprintf(stderr
, "callocing %d for initial reads\n", hd
->h_csize
);
1473 hd
->h_ccopy1
= (char *)calloc(hd
->h_csize
, sizeof (char));
1474 hd
->h_ccopy2
= (char *)calloc(hd
->h_csize
, sizeof (char));
1475 hd
->h_sizes1
= (int *)calloc(CFG_DEFAULT_PSIZE
, sizeof (int));
1476 hd
->h_sizes2
= (int *)calloc(CFG_DEFAULT_PSIZE
, sizeof (int));
1481 * fill in default header info
1484 cfg_init_header(cfp_t
*cfp
)
1487 cfgheader_t
*hd
= cfp
->cf_head
;
1489 hd
->h_magic
= (int32_t)CFG_NEW_MAGIC
;
1490 hd
->h_stamp
= time(&tloc
);
1493 hd
->h_parsesize
= 0;
1499 hd
->h_seq1
= hd
->h_seq2
= 1;
1500 bzero(hd
->h_cfgsizes
, MAX_CFG
* sizeof (int));
1504 * read header and all sections of configuration file
1505 * gets new data for incore copy
1506 * removes invalid header state
1507 * works even if config and persistent sections are empty
1511 cfg_read(cfp_t
*cfp
)
1516 #ifdef DEBUG_CFGLIST
1517 (void) fprintf(stderr
, "cfg_read\n");
1520 if (!cfp
->cf_head
) {
1521 if ((hd
= calloc(1, sizeof (*hd
))) == NULL
)
1524 (void) fprintf(stderr
, "initial cfg header read\n");
1529 if ((*cfp
->cf_pp
->seek
)(cfp
, 0, SEEK_SET
) < 0) {
1531 (void) fprintf(stderr
, "cfg: seek header failed\n");
1536 rc
= (*cfp
->cf_pp
->read
)(cfp
, (char *)cfp
->cf_head
, 4);
1539 (void) fprintf(stderr
, "cfg: read magic number failed\n");
1544 if ((*cfp
->cf_pp
->seek
)(cfp
, 0, SEEK_SET
) < 0) {
1546 (void) fprintf(stderr
, "cfg: seek header failed\n");
1551 rc
= (*cfp
->cf_pp
->read
)(cfp
, (char *)cfp
->cf_head
, sizeof (*hd
));
1552 if (rc
< sizeof (*hd
)) {
1554 (void) fprintf(stderr
, "cfg: read header failed\n");
1559 cfp
->cf_head
->h_cfgs
= NULL
;
1560 cfg_set_memorymap(cfp
);
1561 if (cfp
->cf_head
->h_magic
!= CFG_NEW_MAGIC
) {
1563 (void) fprintf(stderr
, "cfg_read: wrong MAGIC number %x\n",
1564 cfp
->cf_head
->h_magic
);
1569 cfp
->cf_head
->h_state
&= ~(CFG_HDR_INVALID
);
1571 #ifdef DEBUG_CFGLIST
1572 (void) fprintf(stderr
, "reading parser\n");
1574 rc
= (*cfp
->cf_pp
->read
)(cfp
, (char *)cfp
->cf_mapped
,
1575 CFG_DEFAULT_PARSE_SIZE
);
1576 if (rc
< sizeof (*hd
)) {
1578 (void) fprintf(stderr
, "cfg: read parse config failed\n");
1583 readsize
= cfp
->cf_head
->h_csize
;
1585 #ifdef DEBUG_CFGLIST
1586 (void) fprintf(stderr
, "reading copy1 readsize = %d\n", readsize
);
1588 rc
= (*cfp
->cf_pp
->read
)(cfp
, (char *)cfp
->cf_head
->h_ccopy1
,
1591 /* don't fail just return */
1593 (void) fprintf(stderr
, "cfg: read ccopy1 section failed\n");
1598 if ((*cfp
->cf_pp
->seek
)
1599 (cfp
, CFG_DEFAULT_SSIZE
- rc
, SEEK_CUR
) < 0) {
1601 (void) fprintf(stderr
, "cfg: seek (SEEK_CUR) failed\n");
1606 #ifdef DEBUG_CFGLIST
1607 (void) fprintf(stderr
, "reading copy2 readsize = %d\n", readsize
);
1610 rc
= (*cfp
->cf_pp
->read
)(cfp
, (char *)cfp
->cf_head
->h_ccopy2
,
1613 /* don't fail just return */
1615 (void) fprintf(stderr
, "cfg: read ccopy2 section failed\n");
1620 /* read the sizes of the lists from disk */
1621 if ((*cfp
->cf_pp
->seek
)
1622 (cfp
, CFG_DEFAULT_SSIZE
- rc
, SEEK_CUR
) < 0) {
1624 (void) fprintf(stderr
, "cfg: seek (SEEK_CUR) failed\n");
1629 #ifdef DEBUG_CFGLIST
1630 (void) fprintf(stderr
, "reading sizes\n");
1632 rc
= (*cfp
->cf_pp
->read
)(cfp
, (int *)cfp
->cf_head
->h_sizes1
,
1636 (void) fprintf(stderr
, "cfg: read h_sizes1 failed\n");
1641 rc
= (*cfp
->cf_pp
->read
)(cfp
, (int *)cfp
->cf_head
->h_sizes2
,
1645 (void) fprintf(stderr
, "cfg: read h_sizes2 failed\n");
1651 * If initial or invalid sequence, use first section
1653 if ((cfp
->cf_head
->h_seq1
<= 0) && (cfp
->cf_head
->h_seq2
<= 0)) {
1654 cfp
->cf_head
->h_cparse
= cfp
->cf_head
->h_ccopy1
;
1655 cfp
->cf_head
->h_sizes
= cfp
->cf_head
->h_sizes1
;
1658 if (cfp
->cf_head
->h_seq1
>= cfp
->cf_head
->h_seq2
) {
1659 cfp
->cf_head
->h_cparse
= cfp
->cf_head
->h_ccopy1
;
1660 cfp
->cf_head
->h_sizes
= cfp
->cf_head
->h_sizes1
;
1662 cfp
->cf_head
->h_cparse
= cfp
->cf_head
->h_ccopy2
;
1663 cfp
->cf_head
->h_sizes
= cfp
->cf_head
->h_sizes2
;
1667 dump_status(cfp
, "cfg_read");
1675 * Read-write locking of the configuration
1676 * reads into core all sections
1677 * builds parser trees for each section
1678 * Returns: TRUE if the lock was acquired, FALSE otherwise.
1681 cfg_lock(CFGFILE
*cfg
, CFGLOCK mode
)
1688 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
1689 cfg_severity
= CFG_EFATAL
;
1693 if (mode
== CFG_UPGRADE
) {
1697 if (mode
== CFG_WRLOCK
&& (cfg
->cf
[0].cf_flag
& CFG_RDONLY
)) {
1702 * if you don't even give me the right lock request,
1703 * why should I give you one?
1705 if (mode
!= CFG_RDLOCK
&& mode
!= CFG_WRLOCK
)
1709 if (mode
== CFG_WRLOCK
)
1716 #ifdef DEBUG_CFGLIST
1717 (void) fprintf(stderr
, "cfg_lock\n");
1719 /* Lock is always based on local file pointer */
1720 cfg
->cf
[1].cf_lock
= cfg
->cf
[0].cf_lock
= cfg
->cf
[0].cf_fd
;
1722 if (!((cfg
->cf
[0].cf_flag
& CFG_RDONLY
) &&
1723 (mode
== CFG_RDLOCK
))) {
1725 struct flock lk
= {0};
1726 lk
.l_type
= (mode
== CFG_RDLOCK
? F_RDLCK
: F_WRLCK
);
1727 lk
.l_whence
= SEEK_SET
;
1728 lk
.l_start
= (off_t
)0;
1729 lk
.l_len
= (off_t
)0;
1731 if (fcntl(cfg
->cf
[0].cf_lock
, F_SETLKW
, &lk
) < 0)
1736 /* Determine number of files open */
1737 for (cfp
= &cfg
->cf
[0]; cfp
<= &cfg
->cf
[1]; cfp
++) {
1738 if (!cfp
->cf_fd
) continue;
1739 if ((cfp
->cf_head
) &&
1740 (cfp
->cf_head
->h_state
& CFG_HDR_INVALID
)) {
1741 if ((rc
= cfg_hdrcmp(cfp
)) == 0) {
1743 (void) fprintf(stderr
,
1744 "cfg header match, skipping re-read\n");
1746 cfp
->cf_head
->h_state
|= CFG_HDR_RDLOCK
;
1747 if (mode
== CFG_WRLOCK
)
1748 cfp
->cf_head
->h_state
|= CFG_HDR_WRLOCK
;
1750 cfp
->cf_head
->h_state
&= ~(CFG_HDR_INVALID
);
1754 (void) fprintf(stderr
, "re-reading cfg, header mismatch\n");
1757 * dump what we have, info is stale
1759 cfg_free_cfglist(cfp
);
1760 cfg_free_parser_tree();
1762 if (cfp
->cf_head
->h_ccopy1
) {
1763 free(cfp
->cf_head
->h_ccopy1
);
1764 cfp
->cf_head
->h_ccopy1
= NULL
;
1766 if (cfp
->cf_head
->h_ccopy2
) {
1767 free(cfp
->cf_head
->h_ccopy2
);
1768 cfp
->cf_head
->h_ccopy2
= NULL
;
1770 if (cfp
->cf_head
->h_sizes1
) {
1771 free(cfp
->cf_head
->h_sizes1
);
1772 cfp
->cf_head
->h_sizes1
= NULL
;
1774 if (cfp
->cf_head
->h_sizes2
) {
1775 free(cfp
->cf_head
->h_sizes2
);
1776 cfp
->cf_head
->h_sizes2
= NULL
;
1781 cfp
->cf_head
= NULL
;
1784 if (cfp
->cf_head
== NULL
) {
1785 if (!cfg_read(cfp
)) {
1786 if (cfp
->cf_head
!= NULL
)
1787 cfg_init_header(cfp
);
1791 #ifdef DEBUG_CFGLIST
1792 (void) fprintf(stderr
,
1793 "reading parser config\n");
1795 /* build parser trees */
1796 cfg_read_parser_config(cfp
);
1800 cfp
->cf_head
->h_state
|= CFG_HDR_RDLOCK
;
1801 if (mode
== CFG_WRLOCK
) {
1802 if (cfp
->cf_head
->h_seq1
>= cfp
->cf_head
->h_seq2
) {
1804 (void) fprintf(stderr
,
1805 "cfg_lock: WRLOCK copying 1 to 2\n");
1807 memcpy(cfp
->cf_head
->h_ccopy2
,
1808 cfp
->cf_head
->h_ccopy1
,
1809 cfp
->cf_head
->h_csize
);
1810 memcpy(cfp
->cf_head
->h_sizes2
,
1811 cfp
->cf_head
->h_sizes1
,
1814 cfp
->cf_head
->h_cparse
= cfp
->cf_head
->h_ccopy2
;
1815 cfp
->cf_head
->h_sizes
= cfp
->cf_head
->h_sizes2
;
1818 (void) fprintf(stderr
,
1819 "cfg_lock: WRLOCK copying 2 to 1\n");
1821 memcpy(cfp
->cf_head
->h_ccopy1
,
1822 cfp
->cf_head
->h_ccopy2
,
1823 cfp
->cf_head
->h_csize
);
1824 memcpy(cfp
->cf_head
->h_sizes1
,
1825 cfp
->cf_head
->h_sizes2
,
1828 cfp
->cf_head
->h_cparse
= cfp
->cf_head
->h_ccopy1
;
1829 cfp
->cf_head
->h_sizes
= cfp
->cf_head
->h_sizes1
;
1832 cfp
->cf_head
->h_state
|= CFG_HDR_WRLOCK
;
1835 if (cfg_map_cfglists(cfp
) < 0) {
1837 (void) fprintf(stderr
, "cfg: map_cfglists failed\n");
1843 dump_status(cfp
, "cfg_lock");
1853 cfg_perror_str
= dgettext("cfg", CFG_EGENERIC
);
1854 cfg_severity
= CFG_ENONFATAL
;
1859 * Unlock the database
1862 cfp_unlock(cfp_t
*cfp
)
1865 #ifdef DEBUG_CFGLIST
1866 (void) fprintf(stderr
, "cfg_unlock\n");
1871 struct flock lk
= {0};
1872 lk
.l_type
= F_UNLCK
;
1873 lk
.l_whence
= SEEK_SET
;
1874 lk
.l_start
= (off_t
)0;
1875 lk
.l_len
= (off_t
)0;
1876 (void) fcntl(cfp
->cf_lock
, F_SETLKW
, &lk
);
1879 if (cfp
->cf_head
!= NULL
) {
1880 cfp
->cf_head
->h_state
&= ~(CFG_HDR_RDLOCK
|CFG_HDR_WRLOCK
);
1881 cfp
->cf_head
->h_state
|= CFG_HDR_INVALID
;
1885 cfg_unlock(CFGFILE
*cfg
)
1888 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
1889 cfg_severity
= CFG_EFATAL
;
1893 cfp_unlock(&cfg
->cf
[0]);
1894 cfp_unlock(&cfg
->cf
[1]);
1898 * Test for a read lock, set errno if failed.
1901 cfg_rdlock(CFGFILE
*cfg
)
1907 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
1908 cfg_severity
= CFG_EFATAL
;
1912 /* Determine number of files open */
1913 for (cfp
= &cfg
->cf
[0]; cfp
<= &cfg
->cf
[1]; cfp
++) {
1916 if (cfp
->cf_head
== NULL
) {
1918 (void) fprintf(stderr
, "cfg_rdlock: cf_head == NULL\n");
1921 * 6335583, if header == NULL,
1922 * we can't call cfg_read to fill the header again
1923 * since it will change the lock state to
1924 * CFG_HDR_WRLOCK and dscfg will be the processer
1925 * that hold the lock,
1926 * just returning a FALSE if the case,
1927 * then retrieve the lock state from flock structure.
1933 (void) fprintf(stderr
, "cfg_rdlock: cf_head != NULL\n");
1935 if ((cfp
->cf_head
->h_state
& CFG_HDR_RDLOCK
)
1936 == CFG_HDR_RDLOCK
) {
1952 * Test for a write lock, set errno if failed.
1955 cfg_wrlock(CFGFILE
*cfg
)
1961 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
1962 cfg_severity
= CFG_EFATAL
;
1966 /* Determine number of files open */
1967 for (cfp
= &cfg
->cf
[0]; cfp
<= &cfg
->cf
[1]; cfp
++) {
1970 if (cfp
->cf_head
== NULL
) {
1972 (void) fprintf(stderr
, "cfg wrlock: cf_head == NULL\n");
1975 * 6335583, see comments on cfg_rdlock
1981 (void) fprintf(stderr
, "cfg wrlock: cf_head != NULL\n");
1983 if ((cfp
->cf_head
->h_state
& CFG_HDR_WRLOCK
)
1984 == CFG_HDR_WRLOCK
) {
2001 * Find lock status of CFG database.
2002 * Returns: TRUE and sets lock and pid if the lock is held, FALSE otherwise.
2005 cfg_get_lock(CFGFILE
*cfg
, CFGLOCK
*lock
, pid_t
*pid
)
2011 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
2012 cfg_severity
= CFG_EFATAL
;
2017 switch (cfg_lockedby(pid
)) {
2024 case LOCK_NOTLOCKED
:
2029 if (cfg_wrlock(cfg
)) {
2035 if (cfg_rdlock(cfg
)) {
2041 /* Lock is always based on local file pointer */
2042 cfg
->cf
[1].cf_lock
= cfg
->cf
[0].cf_lock
= cfg
->cf
[0].cf_fd
;
2044 bzero(&lk
, sizeof (lk
));
2045 lk
.l_type
= F_WRLCK
;
2046 lk
.l_whence
= SEEK_SET
;
2047 lk
.l_start
= (off_t
)0;
2048 lk
.l_len
= (off_t
)0;
2050 if (fcntl(cfg
->cf
[0].cf_lock
, F_GETLK
, &lk
) < 0)
2053 if (lk
.l_type
== F_UNLCK
)
2058 *lock
= lk
.l_type
== F_WRLCK
? CFG_WRLOCK
: CFG_RDLOCK
;
2067 * Write modified version of header, configuration and persistent
2068 * data using 2 stage commit.
2069 * If no valid data is found in header, it is assumed to be an initial
2070 * write and we will create the default header (could be dangerous)
2071 * another tricky part, if we are doing an upgrade we may be dealing
2072 * with an old database. we need to take care seeking and writing
2073 * until such time that it is upgraded.
2075 * Mutual exclusion is checked using cfg_lock
2079 cfg_commit(CFGFILE
*cfg
)
2088 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
2089 cfg_severity
= CFG_EFATAL
;
2093 if (!cfg_wrlock(cfg
))
2096 /* Determine number of files open */
2097 for (cfp
= &cfg
->cf
[0]; cfp
<= &cfg
->cf
[1]; cfp
++) {
2102 * lets put everything back into one char *
2104 cfg_replace_lists(cfp
);
2106 if ((*cfp
->cf_pp
->seek
)(cfp
, 0, SEEK_SET
) < 0) {
2108 (void) fprintf(stderr
, "cfg: seek header failed\n");
2113 cfp
->cf_head
->h_size
= cfp
->cf_head
->h_parsesize
2114 + cfp
->cf_head
->h_csize
+ cfp
->cf_head
->h_psize
;
2115 cfp
->cf_head
->h_stamp
= time(&tloc
);
2117 /* seeking into database */
2118 if ((*cfp
->cf_pp
->seek
)(cfp
, sizeof (cfgheader_t
),
2122 if (cfp
->cf_head
->h_ccopy1
== cfp
->cf_head
->h_cparse
) {
2123 if (cfp
->cf_head
->h_seq1
< 0)
2124 cfp
->cf_head
->h_seq1
= 1;
2126 cfp
->cf_head
->h_seq1
= cfp
->cf_head
->h_seq2
+ 1;
2129 if (cfp
->cf_head
->h_seq2
< 0)
2130 cfp
->cf_head
->h_seq2
= 1;
2132 cfp
->cf_head
->h_seq2
= cfp
->cf_head
->h_seq1
+ 1;
2136 dump_status(cfp
, "cfg_commit");
2138 rc
= (*cfp
->cf_pp
->write
)(cfp
, cfp
->cf_mapped
,
2139 CFG_DEFAULT_PARSE_SIZE
);
2142 (void) fprintf(stderr
,
2143 "parse commit: rc %d h_parsesize %d\n",
2144 rc
, cfp
->cf_head
->h_parsesize
);
2148 rc
= (*cfp
->cf_pp
->write
) (cfp
, cfp
->cf_head
->h_ccopy1
,
2149 cfp
->cf_head
->h_csize
);
2152 (void) fprintf(stderr
,
2153 "csection commit 1: rc %d h_csize %d\n",
2154 rc
, cfp
->cf_head
->h_csize
);
2157 if ((*cfp
->cf_pp
->seek
)
2158 (cfp
, (2 * CFG_DEFAULT_SSIZE
) - rc
, SEEK_CUR
) < 0)
2162 * limit the write to only what we need
2164 ip
= cfp
->cf_head
->h_sizes1
;
2165 for (wrsize
= 0; *ip
; ip
+= *ip
+ 1)
2168 rc
= (*cfp
->cf_pp
->write
)(cfp
, cfp
->cf_head
->h_sizes1
,
2169 wrsize
* sizeof (int));
2172 (void) fprintf(stderr
,
2173 "cfg: write list sizes1 failed rc\n");
2177 if ((*cfp
->cf_pp
->seek
)(cfp
, CFG_DEFAULT_SSIZE
,
2181 rc
= (*cfp
->cf_pp
->write
)(cfp
, cfp
->cf_head
->h_ccopy2
,
2182 cfp
->cf_head
->h_csize
);
2185 (void) fprintf(stderr
,
2186 "csection commit 2: rc %d h_csize %d\n",
2187 rc
, cfp
->cf_head
->h_csize
);
2190 if ((*cfp
->cf_pp
->seek
)
2191 (cfp
, (CFG_DEFAULT_SSIZE
+ CFG_DEFAULT_PSIZE
) - rc
,
2196 * limit the write to only what we need
2198 ip
= cfp
->cf_head
->h_sizes2
;
2199 for (wrsize
= 0; *ip
; ip
+= *ip
+ 1)
2202 rc
= (*cfp
->cf_pp
->write
)(cfp
, cfp
->cf_head
->h_sizes2
,
2203 wrsize
* sizeof (int));
2206 (void) fprintf(stderr
,
2207 "cfg: write list sizes2 failed\n");
2214 #ifdef DEBUG_CFGLIST
2215 (void) fprintf(stderr
,
2216 "writing h_csize %d\n", cfp
->cf_head
->h_csize
);
2218 if ((*cfp
->cf_pp
->seek
)(cfp
, 0, SEEK_SET
) < 0)
2221 cfp
->cf_head
->h_size
= cfp
->cf_head
->h_parsesize
+
2222 cfp
->cf_head
->h_csize
+ cfp
->cf_head
->h_psize
;
2224 rc
= (*cfp
->cf_pp
->write
)(cfp
, cfp
->cf_head
,
2225 sizeof (cfgheader_t
));
2227 cfg_perror_str
= dgettext("cfg",
2228 "cfg_commit: header write failed");
2229 cfg_severity
= CFG_EFATAL
;
2239 * rewind internal file pointer for specified section
2240 * empty now, rewind not necessary. But don't break
2245 cfg_rewind(CFGFILE
*cfg
, int section
)
2257 * set or return the default location file to
2258 * determine the partition name of the configuration partition
2259 * location is stored in well known file location
2262 cfg_location(char *location
, int mode
, char *altroot
)
2267 char wellknown
[NSC_MAXPATH
];
2268 char loc
[NSC_MAXPATH
];
2270 if (mode
== CFG_LOC_GET_LOCAL
) {
2271 return (CFG_LOCAL_LOCATION
);
2272 } else if (mode
== CFG_LOC_GET_CLUSTER
) {
2275 fmode
= O_RDWR
| O_CREAT
;
2279 strcpy(wellknown
, altroot
);
2280 strcat(wellknown
, CFG_CLUSTER_LOCATION
);
2282 strcpy(wellknown
, CFG_CLUSTER_LOCATION
);
2284 fd
= open(wellknown
, fmode
, 0644);
2286 cfg_perror_str
= dgettext("cfg", strerror(errno
));
2287 cfg_severity
= CFG_ENONFATAL
;
2291 if (mode
== CFG_LOC_SET_CLUSTER
) {
2292 if (location
== NULL
|| (strlen(location
) > NSC_MAXPATH
)) {
2293 cfg_perror_str
= dgettext("cfg",
2294 "cfg_location: filename too big or missing");
2295 cfg_severity
= CFG_EFATAL
;
2301 * If we're in a cluster, make sure that the config location
2302 * is a raw device. Using non-raw did devices in a cluster
2303 * can result in data corruption, since inconsistent data
2304 * may reside in the block cache on one node, but has not
2305 * been flushed to disk.
2307 if (cfg_iscluster() > 0) {
2308 struct stat dscfg_stat
;
2309 if (stat(location
, &dscfg_stat
) != 0) {
2310 cfg_perror_str
= dgettext("cfg",
2311 "Unable to access dscfg location");
2312 cfg_severity
= CFG_EFATAL
;
2315 if (!S_ISCHR(dscfg_stat
.st_mode
)) {
2316 cfg_perror_str
= dgettext("cfg",
2317 "dscfg location must be a raw device");
2318 cfg_severity
= CFG_EFATAL
;
2323 if (ftruncate(fd
, 0) < 0)
2326 rc
= write(fd
, location
, strlen(location
));
2328 cfg_perror_str
= dgettext("cfg",
2329 "cfg_location: write to well known failed");
2330 cfg_severity
= CFG_EFATAL
;
2333 bzero(config_file
, sizeof (config_file
));
2335 if (lseek(fd
, 0, SEEK_SET
) < 0)
2338 bzero(config_file
, sizeof (config_file
));
2339 rc
= read(fd
, config_file
, sizeof (config_file
));
2341 cfg_perror_str
= dgettext("cfg",
2342 "cfg_location: read from well known failed");
2343 cfg_severity
= CFG_EFATAL
;
2348 strcpy(loc
, altroot
);
2349 strcat(loc
, config_file
);
2350 bzero(config_file
, sizeof (config_file
));
2351 strcpy(config_file
, loc
);
2355 * scan string out of config_file, to strip whitespace
2357 sscanf(config_file
, "%s", loc
);
2358 strcpy(config_file
, loc
);
2360 return (config_file
);
2364 * cfg_update_parser_config
2365 * If tag and key exist return -1
2367 * XXX Currently does not append new field to existing parser rule
2371 cfg_update_parser_config(CFGFILE
*cfg
, const char *key
, int section
)
2375 char buf
[CFG_MAX_BUF
];
2377 char tmpkey
[CFG_MAX_KEY
];
2382 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
2383 cfg_severity
= CFG_EFATAL
;
2387 cfp
= FP_SUN_CLUSTER(cfg
);
2388 if (!cfg_wrlock(cfg
))
2391 bzero(buf
, CFG_MAX_BUF
);
2392 bzero(tmpkey
, sizeof (tmpkey
));
2393 strcpy(tmpkey
, key
);
2394 if (section
== CFG_PARSE_CONF
) {
2401 ky
= strtok(tmpkey
, ".");
2402 fld
= strtok(NULL
, ".");
2404 size
= cfg_get_item(tbl
, ky
, fld
);
2407 * Assure we are loading a clean table, with do duplicates
2408 * based on our File Descriptor
2410 if (chead_loaded
&& (chead_loaded
!= cfp
->cf_fd
)) {
2417 fld
= strtok(NULL
, ".");
2419 size
= strlen(key
) + 2;
2420 strncat(buf
, key
, size
);
2422 (void) fprintf(stderr
, "update parser config %s size %d\n", buf
, size
);
2424 if ((size
+ cfp
->cf_head
->h_parseoff
) > CFG_DEFAULT_PARSE_SIZE
) {
2425 cfg_perror_str
= dgettext("cfg",
2426 "cfg_update_parser_config: header overrun");
2427 cfg_severity
= CFG_EFATAL
;
2429 (void) fprintf(stderr
, "update parser config: "
2430 "overrun siz %d poff %d parsesize %d\n",
2431 size
, cfp
->cf_head
->h_parseoff
, cfp
->cf_head
->h_parsesize
);
2436 bcopy(buf
, (cfp
->cf_mapped
+ cfp
->cf_head
->h_parseoff
), size
);
2437 cfp
->cf_head
->h_parseoff
+= size
;
2438 cfp
->cf_head
->h_state
|= CFG_HDR_INVALID
;
2439 if (cfp
->cf_mapped
[cfp
->cf_head
->h_parseoff
- 1] != '\n') {
2440 cfp
->cf_mapped
[cfp
->cf_head
->h_parseoff
] = '\n';
2441 cfp
->cf_head
->h_parseoff
++;
2443 cfp
->cf_head
->h_parsesize
= cfp
->cf_head
->h_parseoff
;
2444 cfg_read_parser_config(cfp
);
2448 * cfg_read_parser_config
2449 * reads parser config from file
2450 * converts it to internal tree for parsing
2451 * chead for configuration parser entries
2456 cfg_read_parser_config(cfp_t
*cfp
)
2458 struct lookup
*p
, *q
;
2459 struct parser
*thead
;
2466 char buf
[CFG_MAX_BUF
];
2474 bzero(buf
, CFG_MAX_BUF
);
2475 /* LINTED it assigns value to c */
2476 while (c
= cfp
->cf_mapped
[foff
++]) {
2481 part
= strtok(buf
, ":");
2488 key
= strtok(NULL
, ".");
2491 strcpy(thead
[n
].tag
.l_word
, key
);
2492 thead
[n
].tag
.l_value
= 0;
2493 thead
[n
].fld
= NULL
;
2495 while ((fld
= strtok(NULL
, ".")) != NULL
) {
2498 q
= thead
[n
].fld
= calloc(1,
2499 sizeof (struct lookup
));
2501 for (q
= thead
[n
].fld
; q
; q
= q
->l_next
)
2503 q
= calloc(1, sizeof (struct lookup
));
2506 strcpy(q
->l_word
, fld
);
2507 q
->l_value
= fldnum
;
2510 (void) fprintf(stderr
,
2511 "read parser: q: word %s value %d\n",
2512 q
->l_word
, q
->l_value
);
2520 /* All done, indicate parser table is loaded */
2521 if (i
&& (chead_loaded
== 0))
2522 chead_loaded
= cfp
->cf_fd
;
2525 * before I go and alloc, why am I here?
2526 * do I need a bunch of cfglists, or do I just
2527 * need to accommodate a just added parser entry
2528 * if the latter, we already have a base, just set
2529 * i to the index of the cfg which members need allocing
2531 if ((cfp
->cf_head
->h_cfgs
== NULL
) ||
2532 (cfp
->cf_head
->h_cfgs
[n
-1].l_entry
== NULL
)) {
2533 cfp
->cf_head
->h_cfgs
= (cfglist_t
*)calloc(MAX_CFG
,
2534 sizeof (cfglist_t
));
2540 if (cfp
->cf_head
->h_cfgs
) {
2542 #ifdef DEBUG_CFGLIST
2543 (void) fprintf(stderr
, "alloced %d cfg lists \n", n
+ 1);
2545 for (cfp
->cf_head
->h_ncfgs
= n
+ 1;
2546 i
< min(cfp
->cf_head
->h_ncfgs
, MAX_CFG
); i
++) {
2547 cfp
->cf_head
->h_cfgs
[i
].l_name
= '\0';
2548 cfp
->cf_head
->h_cfgs
[i
].l_name
=
2549 strdup(chead
[i
].tag
.l_word
);
2550 cfp
->cf_head
->h_cfgs
[i
].l_index
= i
;
2551 cfp
->cf_head
->h_cfgs
[i
].l_entry
=
2552 calloc(DEFAULT_ENTRY_SIZE
, sizeof (char));
2553 cfp
->cf_head
->h_cfgs
[i
].l_nentry
= 0;
2554 cfp
->cf_head
->h_cfgs
[i
].l_esiz
=
2555 calloc(DEFAULT_NENTRIES
, sizeof (int));
2556 cfp
->cf_head
->h_cfgs
[i
].l_size
= 0;
2557 cfp
->cf_head
->h_cfgs
[i
].l_free
= DEFAULT_ENTRY_SIZE
;
2558 if ((cfp
->cf_head
->h_cfgs
[i
].l_entry
== NULL
) ||
2559 (cfp
->cf_head
->h_cfgs
[i
].l_esiz
== NULL
)) {
2560 cfg_perror_str
= dgettext("cfg", "unable to"
2561 " allocate cfglist members");
2562 cfg_severity
= CFG_EFATAL
;
2566 cfg_perror_str
= dgettext("cfg", "unable to alloc cfglist");
2567 cfg_severity
= CFG_EFATAL
;
2572 * cfg_map_cfglists()
2573 * go through list of list sizes in header
2574 * and create separate lists
2577 cfg_map_cfglists(cfp_t
*cfp
)
2590 /* get the first list size */
2593 for (i
= 0; i
< min(ch
->h_ncfgs
, MAX_CFG
); i
++) {
2594 if (ch
->h_cfgsizes
[i
] > 0) {
2595 if (ch
->h_cfgsizes
[i
] > DEFAULT_ENTRY_SIZE
) {
2597 ch
->h_cfgs
[i
].l_entry
= (char *)
2598 realloc(ch
->h_cfgs
[i
].l_entry
,
2599 ch
->h_cfgsizes
[i
] * sizeof (char));
2600 /* set free to 0, we'll get more when we add */
2601 ch
->h_cfgs
[i
].l_free
= 0;
2604 ch
->h_cfgs
[i
].l_free
-= ch
->h_cfgsizes
[i
];
2606 /* get lists and marry up to each cfgs structure */
2612 if (list_size
> DEFAULT_NENTRIES
) {
2614 * we're gonna need more slots
2615 * we want to alloc on DEFAULT_NENTRIES
2616 * boundry. ie. always a multiple of it
2617 * later on, when we add to the list
2618 * we can see if we need to add by mod'ding
2619 * l_nentry and DEFAULT_NENTRIES and check for 0
2621 slot_inc
= DEFAULT_NENTRIES
-
2622 (list_size
% DEFAULT_NENTRIES
);
2623 if (slot_inc
== DEFAULT_NENTRIES
)
2624 slot_inc
= 0; /* addcfline reallocs */
2626 ch
->h_cfgs
[i
].l_esiz
= (int *)realloc(
2627 ch
->h_cfgs
[i
].l_esiz
,
2628 (list_size
+ slot_inc
) * sizeof (int));
2630 memcpy(ch
->h_cfgs
[i
].l_esiz
, ip
,
2631 list_size
* sizeof (int));
2633 ch
->h_cfgs
[i
].l_nentry
= list_size
;
2641 if (ch
->h_cfgs
[i
].l_entry
!= NULL
) {
2642 p
= ch
->h_cparse
+ offset
;
2643 #ifdef DEBUG_CFGLIST
2644 (void) fprintf(stderr
, "mapping list %d size %d offset %d, addr 0x%x\n",
2645 i
, ch
->h_cfgsizes
[i
], offset
, p
);
2647 memcpy(ch
->h_cfgs
[i
].l_entry
,
2648 p
, ch
->h_cfgsizes
[i
]);
2649 ch
->h_cfgs
[i
].l_size
= ch
->h_cfgsizes
[i
];
2650 offset
+= ch
->h_cfgsizes
[i
];
2652 #ifdef DEBUG_CFGLIST
2653 (void) fprintf(stderr
, "NULL l_entry\n");
2665 cfg_replace_lists(cfp_t
*cfp
)
2669 int size_offset
= 0;
2677 if ((cfl
= cfp
->cf_head
->h_cfgs
) == NULL
)
2680 #ifdef DEBUG_CFGLIST
2681 (void) fprintf(stderr
, "cfg_replace_lists\n");
2684 if (cf
->h_cparse
== cf
->h_ccopy1
)
2688 * check to see if we are using copy1 or 2,
2689 * grow or shrink the size, fix h_cparse reference
2690 * in case realloc gave us a funky new address.
2693 cf
->h_ccopy1
= (char *)
2694 realloc(cf
->h_ccopy1
, cf
->h_csize
* sizeof (char));
2695 cf
->h_ccopy2
= (char *)
2696 realloc(cf
->h_ccopy2
, cf
->h_csize
* sizeof (char));
2699 cf
->h_cparse
= cf
->h_ccopy1
;
2701 cf
->h_cparse
= cf
->h_ccopy2
;
2704 * just because, we'll zero out h_csize and recalc
2705 * after all, this is the number the next guy gets
2707 cf
->h_csize
= cf
->h_sizes
[0] = 0;
2708 for (i
= 0; i
< MAX_CFG
; i
++) {
2709 /* only as many lists as chead has */
2710 if (chead
[i
].tag
.l_word
[0] == '\0') {
2713 if (cfl
[i
].l_entry
&& cfl
[i
].l_entry
[0] != '\0') {
2714 #ifdef DEBUG_CFGLIST
2715 (void) fprintf(stderr
,
2716 "copying list %d at %x size %d\n",
2717 i
, cf
->h_cparse
+ offset
,
2720 memcpy((cf
->h_cparse
+ offset
),
2721 cfl
[i
].l_entry
, cfl
[i
].l_size
);
2722 offset
+= cfl
[i
].l_size
;
2723 #ifdef DEBUG_CFGLIST
2724 (void) fprintf(stderr
,
2725 "cfl[%d].l_nentry %d cfl[%d].l_esiz[%d] %d"
2726 " size offset %d\n",
2727 i
, cfl
[i
].l_nentry
, i
, cfl
[i
].l_nentry
- 1,
2728 cfl
[i
].l_esiz
[cfl
[i
].l_nentry
- 1], size_offset
);
2731 * first write the number of entries
2732 * then copy over the array ie.
2733 * a list with 5 elements would be copied
2734 * as a 6 element array slot 0 being the
2735 * number of elements
2737 cf
->h_sizes
[size_offset
++] = cfl
[i
].l_nentry
;
2738 memcpy((cf
->h_sizes
+ size_offset
), cfl
[i
].l_esiz
,
2739 cfl
[i
].l_nentry
* sizeof (int));
2740 size_offset
+= cfl
[i
].l_nentry
;
2741 cf
->h_sizes
[size_offset
] = 0;
2743 cf
->h_csize
+= cfl
[i
].l_size
;
2748 cfg_free_cfglist(cfp_t
*cfp
)
2752 if (!cfp
->cf_head
|| !cfp
->cf_head
->h_cfgs
)
2755 for (i
= 0; cfp
->cf_head
&& i
< MAX_CFG
; i
++) {
2756 if (cfp
->cf_head
->h_cfgs
[i
].l_entry
) {
2757 free(cfp
->cf_head
->h_cfgs
[i
].l_entry
);
2758 cfp
->cf_head
->h_cfgs
[i
].l_entry
= NULL
;
2761 if (cfp
->cf_head
->h_cfgs
[i
].l_name
) {
2762 free(cfp
->cf_head
->h_cfgs
[i
].l_name
);
2763 cfp
->cf_head
->h_cfgs
[i
].l_entry
= NULL
;
2766 if (cfp
->cf_head
->h_cfgs
[i
].l_esiz
) {
2767 free(cfp
->cf_head
->h_cfgs
[i
].l_esiz
);
2768 cfp
->cf_head
->h_cfgs
[i
].l_esiz
= NULL
;
2773 free(cfp
->cf_head
->h_cfgs
);
2774 cfp
->cf_head
->h_cfgs
= NULL
;
2779 cfg_free_parser_tree()
2781 struct lookup
*p
= NULL
;
2782 struct lookup
*q
= NULL
;
2785 for (i
= 0; i
< MAX_CFG
; i
++) {
2797 bzero(chead
, MAX_CFG
* sizeof (struct parser
));
2801 cfg_close(CFGFILE
*cfg
)
2806 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
2807 cfg_severity
= CFG_EFATAL
;
2811 /* Determine number of files open */
2812 for (cfp
= &cfg
->cf
[0]; cfp
<= &cfg
->cf
[1]; cfp
++) {
2813 if (!cfp
->cf_fd
) continue;
2815 (*cfp
->cf_pp
->close
)(cfp
);
2816 #ifdef DEBUG_CFGLIST
2817 (void) fprintf(stderr
, "freeing cfglists\n");
2819 cfg_free_cfglist(cfp
);
2821 #ifdef DEBUG_CFGLIST
2822 (void) fprintf(stderr
, "freeing cfp->cf_mapped\n");
2824 free(cfp
->cf_mapped
);
2825 cfp
->cf_mapped
= NULL
;
2827 #ifdef DEBUG_CFGLIST
2828 (void) fprintf(stderr
,
2829 "freeing copy1, copy2, h_sizes and cf\n");
2832 if (cfp
->cf_head
->h_ccopy1
) {
2833 free(cfp
->cf_head
->h_ccopy1
);
2834 cfp
->cf_head
->h_ccopy1
= NULL
;
2836 if (cfp
->cf_head
->h_ccopy2
) {
2837 free(cfp
->cf_head
->h_ccopy2
);
2838 cfp
->cf_head
->h_ccopy2
= NULL
;
2840 if (cfp
->cf_head
->h_sizes1
) {
2841 free(cfp
->cf_head
->h_sizes1
);
2842 cfp
->cf_head
->h_sizes1
= NULL
;
2844 if (cfp
->cf_head
->h_sizes2
) {
2845 free(cfp
->cf_head
->h_sizes2
);
2846 cfp
->cf_head
->h_sizes2
= NULL
;
2856 cfg_free_parser_tree();
2858 #ifdef DEBUG_CFGLIST
2859 (void) fprintf(stderr
, "cfg_close\n");
2865 cfg_get_resource(CFGFILE
*cfg
)
2868 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
2869 cfg_severity
= CFG_EFATAL
;
2873 return (cfg
->cf_node
);
2878 * set or clear the cluster node filter for get/put
2882 cfg_resource(CFGFILE
*cfg
, const char *node
)
2885 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
2886 cfg_severity
= CFG_EFATAL
;
2891 #ifdef DEBUG_CFGLIST
2892 (void) fprintf(stderr
,
2893 "cfg_resource: changing node from %s to %s\n",
2894 cfg
->cf_node
, (node
?node
:"NULL"));
2897 cfg
->cf_node
= NULL
;
2901 * just in case someone passes in a non-NULL
2902 * node, but has no valid value
2904 if ((node
) && (node
[0] != '\0')) {
2905 cfg
->cf_node
= strdup(node
);
2911 * Open the current configuration file
2914 cfg_open(char *name
)
2922 #ifdef DEBUG_CFGLIST
2923 (void) fprintf(stderr
, "cfg_open\n");
2927 if ((cfg
= (CFGFILE
*)calloc(1, sizeof (*cfg
))) == NULL
) {
2928 cfg_perror_str
= dgettext("cfg",
2929 "cfg_open: malloc failed");
2930 cfg_severity
= CFG_EFATAL
;
2935 if ((name
) && strlen(name
)) {
2937 (void) fprintf(stderr
, "cfg_open: Using non-standard name\n");
2939 cfp
->cf_name
= name
;
2940 cfp
->cf_pp
= (strstr(cfp
->cf_name
, "/rdsk/") == NULL
) ?
2941 cfg_block_io_provider() : cfg_raw_io_provider();
2943 cfp
->cf_name
= cfg_location(NULL
, CFG_LOC_GET_LOCAL
, NULL
);
2944 cfp
->cf_pp
= cfg_block_io_provider();
2946 /* Handle cfg_open(""), which is an open from boot tools */
2949 if (cfg_iscluster() > 0) {
2952 cfg_location(NULL
, CFG_LOC_GET_CLUSTER
, NULL
);
2954 cfp
->cf_pp
= cfg_raw_io_provider();
2960 * Open one or two configuration files
2962 for (cfp
= &cfg
->cf
[0]; cfp
->cf_name
&& (cfp
<= &cfg
->cf
[1]); cfp
++) {
2963 if ((*cfp
->cf_pp
->open
)(cfp
, cfp
->cf_name
) == NULL
) {
2964 cfg_perror_str
= dgettext("cfg",
2965 "cfg_open: unable to open configuration location");
2966 cfg_severity
= CFG_EFATAL
;
2970 /* block device smaller than repository? */
2971 rc
= (*cfp
->cf_pp
->read
)(cfp
, &magic
, sizeof (magic
));
2972 if (rc
< sizeof (magic
)) {
2973 cfg_perror_str
= dgettext("cfg",
2974 "cfg_open: unable to read configuration header");
2975 cfg_severity
= CFG_EFATAL
;
2979 if ((*cfp
->cf_pp
->seek
)(cfp
, 0, SEEK_SET
) < 0) {
2980 cfg_perror_str
= dgettext("cfg",
2981 "cfg_open: unable to seek configuration header");
2982 cfg_severity
= CFG_EFATAL
;
2987 * we can't enforce size rules on an old database
2988 * so check the magic number before we test for size
2990 if (magic
== CFG_NEW_MAGIC
) {
2991 needed
= FBA_NUM(FBA_SIZE(1) - 1 +
2992 (sizeof (struct cfgheader
) + CFG_CONFIG_SIZE
));
2997 if (cfp
->cf_size
< needed
) {
2998 cfg_perror_str
= dgettext("cfg",
2999 "cfg_open: configuration file too small");
3000 cfg_severity
= CFG_EFATAL
;
3005 cfp
->cf_mapped
= (char *)malloc(CFG_DEFAULT_PARSE_SIZE
);
3006 if (cfp
->cf_mapped
== NULL
) {
3007 cfg_perror_str
= dgettext("cfg",
3008 "cfg_open: malloc failed");
3009 cfg_severity
= CFG_EFATAL
;
3013 bzero(cfp
->cf_mapped
, CFG_DEFAULT_PARSE_SIZE
);
3017 /* Processing errors, take care of one or more cfp pointers */
3018 if (cfg_severity
&& (cfp
<= &cfg
->cf
[1])) {
3021 (*cfp
->cf_pp
->close
)(cfp
);
3024 (*cfp
->cf_pp
->close
)(cfp
);
3029 cfg_lockd
= cfg_lockd_init();
3032 #ifdef DEBUG_CFGLIST
3033 (void) fprintf(stderr
, "cfg_open ok\n");
3039 cfg_invalidate_hsizes(int fd
, const char *loc
)
3045 char buf
[2 * CFG_DEFAULT_PSIZE
];
3047 hdrsz
= sizeof (cfgheader_t
) + 512 -
3048 (sizeof (cfgheader_t
) % 512);
3050 offset
= hdrsz
+ CFG_DEFAULT_PARSE_SIZE
+
3051 (CFG_DEFAULT_SSIZE
* 2);
3053 if (cfg_shldskip_vtoc(fd
, loc
) > 0)
3054 offset
+= CFG_VTOC_SKIP
;
3056 bzero(buf
, sizeof (buf
));
3058 if (lseek(fd
, offset
, SEEK_SET
) > 0)
3059 rc
= write(fd
, buf
, sizeof (buf
));
3061 (void) fprintf(stderr
, "cfg: invalidate hsizes failed\n");
3066 cfg_error(int *severity
)
3068 if (severity
!= NULL
)
3069 *severity
= cfg_severity
;
3070 return (cfg_perror_str
? cfg_perror_str
: CFG_EGENERIC
);
3076 cfg_cfg_isempty(CFGFILE
*cfg
)
3081 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
3082 cfg_severity
= CFG_EFATAL
;
3086 cfp
= FP_SUN_CLUSTER(cfg
);
3087 if (cfp
->cf_head
->h_csize
== 0)
3094 * cfg_get_num_entries
3095 * return the number of entries in a given section of database
3096 * sndr, ii, ndr_ii...
3099 cfg_get_num_entries(CFGFILE
*cfg
, char *section
)
3106 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
3107 cfg_severity
= CFG_EFATAL
;
3111 if ((table_offset
= cfg_get_parser_offset(section
)) < 0) {
3116 /* Determine number of files open */
3117 for (cfp
= &cfg
->cf
[0]; cfp
->cf_fd
&& (cfp
<= &cfg
->cf
[1]); cfp
++)
3118 count
+= cfp
->cf_head
->h_cfgs
[table_offset
].l_nentry
;
3125 * all etries in a config file section is placed in
3126 * buf, allocation is done inside
3127 * freeing buf is responisbility of the caller
3128 * number of entries in section is returned
3129 * -1 on failure, errno is set
3132 cfg_get_section(CFGFILE
*cfg
, char ***list
, const char *section
)
3142 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
3143 cfg_severity
= CFG_EFATAL
;
3147 if ((table_offset
= cfg_get_parser_offset(section
)) < 0) {
3152 /* Determine number of files open */
3154 for (cfp
= &cfg
->cf
[0]; cfp
<= &cfg
->cf
[1]; cfp
++) {
3155 if (!cfp
->cf_fd
) continue;
3156 if (cfp
->cf_head
->h_state
& CFG_HDR_INVALID
) {
3157 if (!cfg_read(cfp
)) {
3158 cfg_perror_str
= dgettext("cfg", CFG_RDFAILED
);
3159 cfg_severity
= CFG_EFATAL
;
3164 cfl
= &cfp
->cf_head
->h_cfgs
[table_offset
];
3165 if (cfl
->l_nentry
== 0) /* empty list */
3169 buf
= (char **)malloc(cfl
->l_nentry
* sizeof (char *));
3171 buf
= (char **)realloc(buf
, (cfl
->l_nentry
+ count
) *
3177 bzero(&buf
[count
], cfl
->l_nentry
* sizeof (char *));
3181 for (i
= 0; i
< cfl
->l_nentry
; i
++) {
3182 if ((buf
[i
+ count
] = strdup(p
)) == NULL
) {
3186 p
+= cfl
->l_esiz
[i
];
3188 count
+= cfl
->l_nentry
;
3196 * cluster upgrade helper functions. These support old database operations
3197 * while upgrading nodes on a cluster.
3201 * returns the list of configured tags
3202 * return -1 on error, else the number
3203 * of tags returned in taglist
3207 cfg_get_tags(CFGFILE
*cfg
, char ***taglist
)
3213 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
3214 cfg_severity
= CFG_EFATAL
;
3218 if (!cfg_rdlock(cfg
)) {
3221 list
= calloc(1, MAX_CFG
* sizeof (char *));
3227 while ((i
< MAX_CFG
) && (chead
[i
].tag
.l_word
[0] != '\0')) {
3228 list
[i
] = strdup(chead
[i
].tag
.l_word
);
3229 if (list
[i
] == NULL
) {
3230 for (/* CSTYLE */; i
>= 0; i
--) {
3246 * is this a database?
3247 * check the header for the magic number
3248 * 0 no match 1 match, -1 on error
3251 cfg_is_cfg(CFGFILE
*cfg
)
3255 cfp_t
*cfp
= FP_SUN_CLUSTER(cfg
);
3257 rc
= (cfp
->cf_pp
->read
)(cfp
, &magic
, sizeof (magic
));
3258 if (rc
< sizeof (magic
)) {
3259 cfg_perror_str
= dgettext("cfg", "Fail to read configuration");
3260 cfg_severity
= CFG_EFATAL
;
3264 if (magic
== CFG_NEW_MAGIC
)
3267 cfg_perror_str
= dgettext("cfg",
3268 "configuration not initialized, bad magic");
3269 cfg_severity
= CFG_EFATAL
;
3275 compare(const void* a
, const void *b
)
3292 needed
= sortby
.offset
;
3294 p
= strtok(pbuf
, " ");
3296 if (needed
== pos
) {
3299 p
= strtok(NULL
, " ");
3306 q
= strtok(qbuf
, " ");
3308 if (needed
== pos
) {
3311 q
= strtok(NULL
, " ");
3331 * returns the section, sorted by supplied field
3335 cfg_get_srtdsec(CFGFILE
*cfg
, char ***list
, const char *section
,
3347 cfg_perror_str
= dgettext("cfg", CFG_EINVAL
);
3348 cfg_severity
= CFG_EFATAL
;
3352 if ((table_offset
= cfg_get_parser_offset(section
)) < 0) {
3353 cfg_perror_str
= dgettext("cfg", CFG_RDFAILED
);
3359 * do essentially what get_section does,
3360 * except stick entries in a static size
3361 * buf to make things easier to qsort
3364 for (cfp
= &cfg
->cf
[0]; cfp
<= &cfg
->cf
[1]; cfp
++) {
3365 if (!cfp
->cf_fd
) continue;
3366 if (cfp
->cf_head
->h_state
& CFG_HDR_INVALID
) {
3367 if (!cfg_read(cfp
)) {
3368 cfg_perror_str
= dgettext("cfg", CFG_RDFAILED
);
3369 cfg_severity
= CFG_EFATAL
;
3374 cfl
= &cfp
->cf_head
->h_cfgs
[table_offset
];
3375 if (cfl
->l_nentry
== 0) /* empty list */
3379 buf
= (char **)malloc(cfl
->l_nentry
* sizeof (char *));
3381 buf
= (char **)realloc(buf
, (cfl
->l_nentry
+ count
) *
3385 cfg_perror_str
= dgettext("cfg", "cfg_get_srtdsec: "
3387 cfg_severity
= CFG_EFATAL
;
3390 bzero(&buf
[count
], cfl
->l_nentry
* sizeof (char *));
3394 * allocate each line
3396 for (i
= count
; i
< cfl
->l_nentry
+ count
; i
++) {
3397 buf
[i
] = calloc(1, CFG_MAX_BUF
);
3398 if (buf
[i
] == NULL
) {
3406 tmplst
= (char *)malloc(cfl
->l_nentry
* CFG_MAX_BUF
);
3408 tmplst
= (char *)realloc(tmplst
,
3409 (cfl
->l_nentry
+ count
) * CFG_MAX_BUF
);
3410 if (tmplst
== NULL
) {
3411 cfg_perror_str
= dgettext("cfg", "cfg_get_srtdsec: "
3413 cfg_severity
= CFG_EFATAL
;
3417 bzero(&tmplst
[count
], cfl
->l_nentry
* CFG_MAX_BUF
);
3421 * put the section in tmplst and sort
3425 for (i
= 0; i
< cfl
->l_nentry
; i
++) {
3426 bcopy(q
, p
, cfl
->l_esiz
[i
]);
3428 q
+= cfl
->l_esiz
[i
];
3430 count
+= cfl
->l_nentry
;
3433 bzero(sortby
.section
, CFG_MAX_KEY
);
3434 bzero(sortby
.field
, CFG_MAX_KEY
);
3436 strcpy(sortby
.section
, section
);
3437 strcpy(sortby
.field
, field
);
3438 sortby
.comperror
= 0;
3439 sortby
.offset
= cfg_get_item(&chead
[0], section
, field
);
3441 qsort(tmplst
, count
, CFG_MAX_BUF
, compare
);
3443 if (sortby
.comperror
) {
3444 sortby
.comperror
= 0;
3445 cfg_perror_str
= dgettext("cfg", "cfg_get_srtdsec: "
3446 "comparison error");
3447 cfg_severity
= CFG_ENONFATAL
;
3448 cfg_free_section(&buf
, cfl
->l_nentry
);
3455 for (i
= 0; i
< count
; i
++) {
3456 bcopy(p
, buf
[i
], CFG_MAX_BUF
);
3466 * free an array alloc'd by get_*section
3467 * or some other array of size size
3471 cfg_free_section(char ***section
, int size
)
3474 char **secpp
= *section
;
3476 for (i
= 0; i
< size
; i
++) {
3491 cfg_shldskip_vtoc(int fd
, const char *loc
)
3497 char char_name
[PATH_MAX
];
3500 if (fstat(fd
, &sb
) == -1) {
3501 cfg_perror_str
= dgettext("cfg", "unable to stat config");
3502 cfg_severity
= CFG_EFATAL
;
3505 if (S_ISREG(sb
.st_mode
))
3508 if (S_ISCHR(sb
.st_mode
)) {
3509 if ((slice
= read_vtoc(fd
, &vtoc
)) < 0)
3512 if (vtoc
.v_part
[slice
].p_start
< CFG_VTOC_SIZE
)
3518 if (S_ISBLK(sb
.st_mode
)) {
3519 p
= strstr(loc
, "/dsk/");
3522 strcpy(char_name
, loc
);
3523 char_name
[strlen(loc
) - strlen(p
)] = 0;
3524 strcat(char_name
, "/rdsk/");
3525 strcat(char_name
, p
+ 5);
3527 if ((rfd
= open(char_name
, O_RDONLY
)) < 0) {
3530 if ((slice
= read_vtoc(rfd
, &vtoc
)) < 0) {
3535 if (vtoc
.v_part
[slice
].p_start
< CFG_VTOC_SIZE
)
3545 * comapares incore header with one on disk
3546 * returns 0 if equal, 1 if not, -1 error
3549 cfg_hdrcmp(cfp_t
*cfp
)
3551 cfgheader_t
*dskhdr
, *memhdr
;
3554 if ((dskhdr
= calloc(1, sizeof (*dskhdr
))) == NULL
) {
3555 cfg_perror_str
= dgettext("cfg", "cfg_hdrcmp: No memory");
3556 cfg_severity
= CFG_ENONFATAL
;
3559 if ((*cfp
->cf_pp
->seek
)(cfp
, 0, SEEK_SET
) < 0) {
3560 cfg_perror_str
= dgettext("cfg", "cfg_hdrcmp: seek failed");
3561 cfg_severity
= CFG_ENONFATAL
;
3566 rc
= (*cfp
->cf_pp
->read
)(cfp
, (char *)dskhdr
, sizeof (*dskhdr
));
3568 cfg_perror_str
= dgettext("cfg", "cfg_hdrcmp: read failed");
3569 cfg_severity
= CFG_ENONFATAL
;
3574 memhdr
= cfp
->cf_head
;
3576 if ((memhdr
->h_seq1
== dskhdr
->h_seq1
) &&
3577 (memhdr
->h_seq2
== dskhdr
->h_seq2
))