xref: /titanic_52/usr/src/lib/libdscfg/common/cfg_local.c (revision fcf3ce441efd61da9bb2884968af01cb7c1452cc)
1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte  * CDDL HEADER START
3*fcf3ce44SJohn Forte  *
4*fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte  *
8*fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte  * and limitations under the License.
12*fcf3ce44SJohn Forte  *
13*fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte  *
19*fcf3ce44SJohn Forte  * CDDL HEADER END
20*fcf3ce44SJohn Forte  */
21*fcf3ce44SJohn Forte /*
22*fcf3ce44SJohn Forte  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*fcf3ce44SJohn Forte  * Use is subject to license terms.
24*fcf3ce44SJohn Forte  */
25*fcf3ce44SJohn Forte 
26*fcf3ce44SJohn Forte #include <stdio.h>
27*fcf3ce44SJohn Forte 
28*fcf3ce44SJohn Forte #include <sys/types.h>
29*fcf3ce44SJohn Forte #include <sys/vtoc.h>
30*fcf3ce44SJohn Forte #include <sys/wait.h>
31*fcf3ce44SJohn Forte #include <stdio.h>
32*fcf3ce44SJohn Forte #include <sys/mnttab.h>
33*fcf3ce44SJohn Forte #include <errno.h>
34*fcf3ce44SJohn Forte #include <limits.h>
35*fcf3ce44SJohn Forte #include <fcntl.h>
36*fcf3ce44SJohn Forte #include <string.h>
37*fcf3ce44SJohn Forte #include <strings.h>
38*fcf3ce44SJohn Forte #include <stdlib.h>
39*fcf3ce44SJohn Forte #include <unistd.h>
40*fcf3ce44SJohn Forte #include <sys/mman.h>
41*fcf3ce44SJohn Forte 
42*fcf3ce44SJohn Forte #include <locale.h>
43*fcf3ce44SJohn Forte #include <langinfo.h>
44*fcf3ce44SJohn Forte #include <libintl.h>
45*fcf3ce44SJohn Forte #include <stdarg.h>
46*fcf3ce44SJohn Forte #include <netdb.h>
47*fcf3ce44SJohn Forte #include <ctype.h>
48*fcf3ce44SJohn Forte #include <sys/stat.h>
49*fcf3ce44SJohn Forte #include <sys/utsname.h>
50*fcf3ce44SJohn Forte 
51*fcf3ce44SJohn Forte #include "cfg_impl.h"
52*fcf3ce44SJohn Forte #include "cfg.h"
53*fcf3ce44SJohn Forte #include "cfg_local.h"
54*fcf3ce44SJohn Forte 
55*fcf3ce44SJohn Forte #if 0
56*fcf3ce44SJohn Forte #define	DEBUG_CFGLIST
57*fcf3ce44SJohn Forte #define	DEBUG_CFGLISTRM
58*fcf3ce44SJohn Forte #endif
59*fcf3ce44SJohn Forte 
60*fcf3ce44SJohn Forte extern	int	cfg_severity;
61*fcf3ce44SJohn Forte extern	char	*cfg_perror_str;
62*fcf3ce44SJohn Forte 
63*fcf3ce44SJohn Forte long
64*fcf3ce44SJohn Forte get_bsize(cfp_t *cfp, char *name)
65*fcf3ce44SJohn Forte {
66*fcf3ce44SJohn Forte 	char char_name[PATH_MAX];
67*fcf3ce44SJohn Forte 	char *rest;
68*fcf3ce44SJohn Forte 	struct vtoc vtoc;
69*fcf3ce44SJohn Forte 	int slice;
70*fcf3ce44SJohn Forte 	int fd;
71*fcf3ce44SJohn Forte 
72*fcf3ce44SJohn Forte 	if (strlen(name) >= PATH_MAX - 1)
73*fcf3ce44SJohn Forte 		return (0);
74*fcf3ce44SJohn Forte 
75*fcf3ce44SJohn Forte 	rest = strstr(name, "/dsk/");
76*fcf3ce44SJohn Forte 	if (rest == NULL) {
77*fcf3ce44SJohn Forte 		if ((rest = strstr(name, "/rdsk/")) == NULL)
78*fcf3ce44SJohn Forte 			return (0);
79*fcf3ce44SJohn Forte 		strcpy(char_name, name);
80*fcf3ce44SJohn Forte 		goto do_open;
81*fcf3ce44SJohn Forte 
82*fcf3ce44SJohn Forte 	}
83*fcf3ce44SJohn Forte 	strcpy(char_name, name);
84*fcf3ce44SJohn Forte 	char_name[strlen(name) - strlen(rest)] = 0;
85*fcf3ce44SJohn Forte 	strcat(char_name, "/rdsk/");
86*fcf3ce44SJohn Forte 	strcat(char_name, rest + 5);
87*fcf3ce44SJohn Forte 
88*fcf3ce44SJohn Forte do_open:
89*fcf3ce44SJohn Forte 	fd = open(char_name, O_RDONLY);
90*fcf3ce44SJohn Forte 	if (fd < 0)
91*fcf3ce44SJohn Forte 		return (0);
92*fcf3ce44SJohn Forte 
93*fcf3ce44SJohn Forte 	slice = read_vtoc(fd, &vtoc);
94*fcf3ce44SJohn Forte 	if (slice < 0) {
95*fcf3ce44SJohn Forte 		(void) close(fd);
96*fcf3ce44SJohn Forte 		return (0);
97*fcf3ce44SJohn Forte 	}
98*fcf3ce44SJohn Forte 
99*fcf3ce44SJohn Forte 	(void) close(fd);
100*fcf3ce44SJohn Forte 	if (vtoc.v_part[slice].p_start < CFG_VTOC_SIZE)
101*fcf3ce44SJohn Forte 		cfp->cf_flag |= CFG_NOWRVTOC;
102*fcf3ce44SJohn Forte 
103*fcf3ce44SJohn Forte 	return (vtoc.v_part[slice].p_size);
104*fcf3ce44SJohn Forte }
105*fcf3ce44SJohn Forte 
106*fcf3ce44SJohn Forte /*
107*fcf3ce44SJohn Forte  * round up to the next block size
108*fcf3ce44SJohn Forte  */
109*fcf3ce44SJohn Forte int
110*fcf3ce44SJohn Forte get_block_size(int size)
111*fcf3ce44SJohn Forte {
112*fcf3ce44SJohn Forte 	int ret;
113*fcf3ce44SJohn Forte 
114*fcf3ce44SJohn Forte 	if (size % CFG_BLOCK_SIZE != 0)
115*fcf3ce44SJohn Forte 		ret = size + CFG_BLOCK_SIZE - (size % CFG_BLOCK_SIZE);
116*fcf3ce44SJohn Forte 	else
117*fcf3ce44SJohn Forte 		ret = size;
118*fcf3ce44SJohn Forte 	return (ret);
119*fcf3ce44SJohn Forte }
120*fcf3ce44SJohn Forte 
121*fcf3ce44SJohn Forte /*
122*fcf3ce44SJohn Forte  * get a chunk of mem rounded up to next block size
123*fcf3ce44SJohn Forte  */
124*fcf3ce44SJohn Forte char *
125*fcf3ce44SJohn Forte get_block_buf(int size)
126*fcf3ce44SJohn Forte {
127*fcf3ce44SJohn Forte 	int blk_size;
128*fcf3ce44SJohn Forte 	char *blk_buf;
129*fcf3ce44SJohn Forte 
130*fcf3ce44SJohn Forte 	blk_size = get_block_size(size);
131*fcf3ce44SJohn Forte 
132*fcf3ce44SJohn Forte 	if ((blk_buf = (char *)calloc(blk_size, sizeof (char))) == NULL) {
133*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
134*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", strerror(errno));
135*fcf3ce44SJohn Forte 		return (NULL);
136*fcf3ce44SJohn Forte 	}
137*fcf3ce44SJohn Forte 	return (blk_buf);
138*fcf3ce44SJohn Forte }
139*fcf3ce44SJohn Forte 
140*fcf3ce44SJohn Forte void
141*fcf3ce44SJohn Forte free_block_buf(char *buf)
142*fcf3ce44SJohn Forte {
143*fcf3ce44SJohn Forte 	if (buf)
144*fcf3ce44SJohn Forte 		free(buf);
145*fcf3ce44SJohn Forte }
146*fcf3ce44SJohn Forte 
147*fcf3ce44SJohn Forte void
148*fcf3ce44SJohn Forte localcf_close(cfp_t *cfp)
149*fcf3ce44SJohn Forte {
150*fcf3ce44SJohn Forte 	fsync(cfp->cf_fd);
151*fcf3ce44SJohn Forte 	cfp_unlock(cfp);
152*fcf3ce44SJohn Forte 	close(cfp->cf_fd);
153*fcf3ce44SJohn Forte }
154*fcf3ce44SJohn Forte 
155*fcf3ce44SJohn Forte 
156*fcf3ce44SJohn Forte /*
157*fcf3ce44SJohn Forte  * cfg_open
158*fcf3ce44SJohn Forte  * Open the current configuration file
159*fcf3ce44SJohn Forte  * Sets file descriptor in cfp->cf_fd for use by other routines
160*fcf3ce44SJohn Forte  */
161*fcf3ce44SJohn Forte cfp_t *
162*fcf3ce44SJohn Forte localcf_open(cfp_t *cfp, char *name)
163*fcf3ce44SJohn Forte {
164*fcf3ce44SJohn Forte 	struct stat sb;
165*fcf3ce44SJohn Forte 	int rc;
166*fcf3ce44SJohn Forte 
167*fcf3ce44SJohn Forte 
168*fcf3ce44SJohn Forte 	if (name == NULL) {
169*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg",
170*fcf3ce44SJohn Forte 		    "cfg_open: unable to open configuration location");
171*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
172*fcf3ce44SJohn Forte 		return (NULL);
173*fcf3ce44SJohn Forte 	}
174*fcf3ce44SJohn Forte 
175*fcf3ce44SJohn Forte 	cfp->cf_fd = open(name, O_RDWR|O_CREAT|O_DSYNC|O_RSYNC, 0640);
176*fcf3ce44SJohn Forte 	if (cfp->cf_fd == -1) {
177*fcf3ce44SJohn Forte 		if ((cfp->cf_fd = open(name, O_RDONLY, 0640)) == -1) {
178*fcf3ce44SJohn Forte 			cfg_perror_str = dgettext("cfg",
179*fcf3ce44SJohn Forte 			    "cfg_open: unable to open configuration location");
180*fcf3ce44SJohn Forte 			cfg_severity = CFG_EFATAL;
181*fcf3ce44SJohn Forte 			return (NULL);
182*fcf3ce44SJohn Forte 		}
183*fcf3ce44SJohn Forte 		cfp->cf_flag |= CFG_RDONLY;
184*fcf3ce44SJohn Forte 	}
185*fcf3ce44SJohn Forte 
186*fcf3ce44SJohn Forte 	if (fstat(cfp->cf_fd, &sb) == -1) {
187*fcf3ce44SJohn Forte 		close(cfp->cf_fd);
188*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg",
189*fcf3ce44SJohn Forte 		    "cfg_open: unable to stat configuration location");
190*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
191*fcf3ce44SJohn Forte 		return (NULL);
192*fcf3ce44SJohn Forte 	}
193*fcf3ce44SJohn Forte 
194*fcf3ce44SJohn Forte 
195*fcf3ce44SJohn Forte 	if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode)) {
196*fcf3ce44SJohn Forte 		cfp->cf_size = get_bsize(cfp, name);
197*fcf3ce44SJohn Forte 
198*fcf3ce44SJohn Forte 		/* skip the vtoc if necessary */
199*fcf3ce44SJohn Forte 		if (cfp->cf_flag & CFG_NOWRVTOC) {
200*fcf3ce44SJohn Forte 			do {
201*fcf3ce44SJohn Forte 				rc = lseek(cfp->cf_fd, CFG_VTOC_SKIP, SEEK_SET);
202*fcf3ce44SJohn Forte 			} while (rc == -1 && errno == EINTR);
203*fcf3ce44SJohn Forte 
204*fcf3ce44SJohn Forte 			if (rc == -1) {
205*fcf3ce44SJohn Forte 				cfg_perror_str = dgettext("cfg",
206*fcf3ce44SJohn Forte 				    strerror(errno));
207*fcf3ce44SJohn Forte 				cfg_severity = CFG_EFATAL;
208*fcf3ce44SJohn Forte 				close(cfp->cf_fd);
209*fcf3ce44SJohn Forte 				return (NULL);
210*fcf3ce44SJohn Forte 			}
211*fcf3ce44SJohn Forte 		}
212*fcf3ce44SJohn Forte 
213*fcf3ce44SJohn Forte 	} else if (S_ISREG(sb.st_mode)) {
214*fcf3ce44SJohn Forte 		cfp->cf_flag |= CFG_FILE;
215*fcf3ce44SJohn Forte 		cfp->cf_size = FBA_NUM(FBA_SIZE(1) - 1 + sb.st_size);
216*fcf3ce44SJohn Forte 	} else {
217*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", "cfg_open: unknown file type");
218*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
219*fcf3ce44SJohn Forte 		close(cfp->cf_fd);
220*fcf3ce44SJohn Forte 		cfp->cf_fd = NULL;
221*fcf3ce44SJohn Forte 		return (NULL);
222*fcf3ce44SJohn Forte 	}
223*fcf3ce44SJohn Forte 	return (cfp);
224*fcf3ce44SJohn Forte }
225*fcf3ce44SJohn Forte 
226*fcf3ce44SJohn Forte int
227*fcf3ce44SJohn Forte localcf_seekblk(cfp_t *cfp, int off, int mode)
228*fcf3ce44SJohn Forte {
229*fcf3ce44SJohn Forte 	int rc;
230*fcf3ce44SJohn Forte 
231*fcf3ce44SJohn Forte 	do {
232*fcf3ce44SJohn Forte 		rc = lseek(cfp->cf_fd, off, mode);
233*fcf3ce44SJohn Forte 	} while (rc == -1 && errno == EINTR);
234*fcf3ce44SJohn Forte 
235*fcf3ce44SJohn Forte 	return (rc);
236*fcf3ce44SJohn Forte }
237*fcf3ce44SJohn Forte 
238*fcf3ce44SJohn Forte int
239*fcf3ce44SJohn Forte localcf_readblk(cfp_t *cfp, void *buf, int size)
240*fcf3ce44SJohn Forte {
241*fcf3ce44SJohn Forte 	int rc;
242*fcf3ce44SJohn Forte 
243*fcf3ce44SJohn Forte 	do {
244*fcf3ce44SJohn Forte 		rc = read(cfp->cf_fd, buf, size);
245*fcf3ce44SJohn Forte 	} while (rc == -1 && errno == EINTR);
246*fcf3ce44SJohn Forte 
247*fcf3ce44SJohn Forte 	return (rc);
248*fcf3ce44SJohn Forte }
249*fcf3ce44SJohn Forte 
250*fcf3ce44SJohn Forte int
251*fcf3ce44SJohn Forte localcf_writeblk(cfp_t *cfp, void *buf, int size)
252*fcf3ce44SJohn Forte {
253*fcf3ce44SJohn Forte 	int rc;
254*fcf3ce44SJohn Forte 
255*fcf3ce44SJohn Forte 	do {
256*fcf3ce44SJohn Forte 		rc = write(cfp->cf_fd, buf, size);
257*fcf3ce44SJohn Forte 	} while (rc == -1 && errno == EINTR);
258*fcf3ce44SJohn Forte 
259*fcf3ce44SJohn Forte 	return (rc);
260*fcf3ce44SJohn Forte }
261*fcf3ce44SJohn Forte 
262*fcf3ce44SJohn Forte int
263*fcf3ce44SJohn Forte localcf_seek(cfp_t *cfp, int off, int mode)
264*fcf3ce44SJohn Forte {
265*fcf3ce44SJohn Forte 	int rc;
266*fcf3ce44SJohn Forte 	int offset;
267*fcf3ce44SJohn Forte 
268*fcf3ce44SJohn Forte 	offset = get_block_size(off);
269*fcf3ce44SJohn Forte 
270*fcf3ce44SJohn Forte 	if ((mode == SEEK_SET) && (cfp->cf_flag & CFG_NOWRVTOC)) {
271*fcf3ce44SJohn Forte 		offset += CFG_VTOC_SKIP;
272*fcf3ce44SJohn Forte 	}
273*fcf3ce44SJohn Forte 
274*fcf3ce44SJohn Forte 	do {
275*fcf3ce44SJohn Forte 		rc = lseek(cfp->cf_fd, offset, mode);
276*fcf3ce44SJohn Forte 	} while (rc == -1 && errno == EINTR);
277*fcf3ce44SJohn Forte 
278*fcf3ce44SJohn Forte 	return (rc);
279*fcf3ce44SJohn Forte }
280*fcf3ce44SJohn Forte 
281*fcf3ce44SJohn Forte int
282*fcf3ce44SJohn Forte localcf_read(cfp_t *cfp, void *buf, int size)
283*fcf3ce44SJohn Forte {
284*fcf3ce44SJohn Forte 	int rc;
285*fcf3ce44SJohn Forte 	int blk_size;
286*fcf3ce44SJohn Forte 	char *blk_buf;
287*fcf3ce44SJohn Forte 
288*fcf3ce44SJohn Forte 	blk_size = get_block_size(size);
289*fcf3ce44SJohn Forte 	if ((blk_buf = get_block_buf(size)) == NULL)
290*fcf3ce44SJohn Forte 		return (-1);
291*fcf3ce44SJohn Forte 
292*fcf3ce44SJohn Forte 	do {
293*fcf3ce44SJohn Forte 		rc = read(cfp->cf_fd, blk_buf, blk_size);
294*fcf3ce44SJohn Forte 	} while (rc == -1 && errno == EINTR);
295*fcf3ce44SJohn Forte 
296*fcf3ce44SJohn Forte 	bcopy(blk_buf, buf, size);
297*fcf3ce44SJohn Forte 	free_block_buf(blk_buf);
298*fcf3ce44SJohn Forte 
299*fcf3ce44SJohn Forte 	return (rc);
300*fcf3ce44SJohn Forte }
301*fcf3ce44SJohn Forte 
302*fcf3ce44SJohn Forte int
303*fcf3ce44SJohn Forte localcf_write(cfp_t *cfp, void *buf, int size)
304*fcf3ce44SJohn Forte {
305*fcf3ce44SJohn Forte 	int rc;
306*fcf3ce44SJohn Forte 	int blk_size;
307*fcf3ce44SJohn Forte 	char *blk_buf;
308*fcf3ce44SJohn Forte 
309*fcf3ce44SJohn Forte 	blk_size = get_block_size(size);
310*fcf3ce44SJohn Forte 	if ((blk_buf = get_block_buf(size)) == NULL)
311*fcf3ce44SJohn Forte 		return (-1);
312*fcf3ce44SJohn Forte 
313*fcf3ce44SJohn Forte 	bcopy(buf, blk_buf, size);
314*fcf3ce44SJohn Forte 
315*fcf3ce44SJohn Forte 	do {
316*fcf3ce44SJohn Forte 		rc = write(cfp->cf_fd, blk_buf, blk_size);
317*fcf3ce44SJohn Forte 	} while (rc == -1 && errno == EINTR);
318*fcf3ce44SJohn Forte 
319*fcf3ce44SJohn Forte 	free_block_buf(blk_buf);
320*fcf3ce44SJohn Forte 
321*fcf3ce44SJohn Forte 	return (rc);
322*fcf3ce44SJohn Forte }
323*fcf3ce44SJohn Forte /*
324*fcf3ce44SJohn Forte  * Routines which operate on internal version of configuration
325*fcf3ce44SJohn Forte  */
326*fcf3ce44SJohn Forte 
327*fcf3ce44SJohn Forte /*
328*fcf3ce44SJohn Forte  * Add entry to end  of configuration section
329*fcf3ce44SJohn Forte  */
330*fcf3ce44SJohn Forte 
331*fcf3ce44SJohn Forte int
332*fcf3ce44SJohn Forte addcfline(cfp_t *cfp, char *line, int table_index)
333*fcf3ce44SJohn Forte {
334*fcf3ce44SJohn Forte 	int len = strlen(line)+1;
335*fcf3ce44SJohn Forte 	int newsize = DEFAULT_ENTRY_SIZE / 2;
336*fcf3ce44SJohn Forte 	cfgheader_t *hd;
337*fcf3ce44SJohn Forte 	cfglist_t *cfl;
338*fcf3ce44SJohn Forte 	char *q;
339*fcf3ce44SJohn Forte 
340*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
341*fcf3ce44SJohn Forte 	fprintf(stderr, "addcfline: pre l_size %d h_cfgsizes[%d]"
342*fcf3ce44SJohn Forte 	    " %d l_free %u adding len %d\n",
343*fcf3ce44SJohn Forte 	    cfp->cf_head->h_cfgs[table_index].l_size, table_index,
344*fcf3ce44SJohn Forte 	    cfp->cf_head->h_cfgsizes[table_index],
345*fcf3ce44SJohn Forte 	    cfp->cf_head->h_cfgs[table_index].l_free, len);
346*fcf3ce44SJohn Forte #endif
347*fcf3ce44SJohn Forte 
348*fcf3ce44SJohn Forte 	hd = cfp->cf_head;
349*fcf3ce44SJohn Forte 	cfl = &cfp->cf_head->h_cfgs[table_index];
350*fcf3ce44SJohn Forte 	if (cfl->l_free < len) {
351*fcf3ce44SJohn Forte 
352*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
353*fcf3ce44SJohn Forte 		fprintf(stderr, "resizing l_entry from %d to %d\n",
354*fcf3ce44SJohn Forte 		    cfl->l_size + cfl->l_free, cfl->l_size +
355*fcf3ce44SJohn Forte 		    cfl->l_free + newsize);
356*fcf3ce44SJohn Forte #endif
357*fcf3ce44SJohn Forte 		cfl->l_entry = (char *)realloc(cfl->l_entry, (cfl->l_size +
358*fcf3ce44SJohn Forte 		    cfl->l_free + newsize) * sizeof (char));
359*fcf3ce44SJohn Forte 		if (cfl->l_entry == NULL) {
360*fcf3ce44SJohn Forte 			errno = ENOMEM;
361*fcf3ce44SJohn Forte 			return (-1);
362*fcf3ce44SJohn Forte 		}
363*fcf3ce44SJohn Forte 		cfl->l_free += newsize;
364*fcf3ce44SJohn Forte 
365*fcf3ce44SJohn Forte 	}
366*fcf3ce44SJohn Forte 	cfl->l_free -= len;
367*fcf3ce44SJohn Forte 
368*fcf3ce44SJohn Forte 	/* out of list slots, get some more */
369*fcf3ce44SJohn Forte 	if (cfl->l_nentry % DEFAULT_NENTRIES == 0) {
370*fcf3ce44SJohn Forte 		/*
371*fcf3ce44SJohn Forte 		 * first, figure out how much bigger, than realloc
372*fcf3ce44SJohn Forte 		 */
373*fcf3ce44SJohn Forte 
374*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
375*fcf3ce44SJohn Forte 		fprintf(stderr,
376*fcf3ce44SJohn Forte 		    "list %d getting more nentries, I have %d\n",
377*fcf3ce44SJohn Forte 		    table_index, cfl->l_nentry);
378*fcf3ce44SJohn Forte #endif
379*fcf3ce44SJohn Forte 		cfl->l_esiz = (int *)
380*fcf3ce44SJohn Forte 		    realloc(cfl->l_esiz, (cfl->l_nentry + DEFAULT_NENTRIES) *
381*fcf3ce44SJohn Forte 		    sizeof (int));
382*fcf3ce44SJohn Forte 		if (cfl->l_esiz == NULL) {
383*fcf3ce44SJohn Forte 			errno = ENOMEM;
384*fcf3ce44SJohn Forte 			return (-1);
385*fcf3ce44SJohn Forte 		}
386*fcf3ce44SJohn Forte 	}
387*fcf3ce44SJohn Forte 
388*fcf3ce44SJohn Forte 
389*fcf3ce44SJohn Forte 	cfl->l_esiz[cfl->l_nentry] = len;
390*fcf3ce44SJohn Forte 	cfl->l_nentry++;
391*fcf3ce44SJohn Forte 
392*fcf3ce44SJohn Forte 	/* add line to end of list */
393*fcf3ce44SJohn Forte 	q = cfl->l_entry + cfl->l_size;
394*fcf3ce44SJohn Forte 
395*fcf3ce44SJohn Forte 	strcpy(q, line);
396*fcf3ce44SJohn Forte 	q += len;
397*fcf3ce44SJohn Forte 
398*fcf3ce44SJohn Forte 	/* set sizes */
399*fcf3ce44SJohn Forte 	hd->h_cfgs[table_index].l_size += len;
400*fcf3ce44SJohn Forte 	hd->h_cfgsizes[table_index] = cfl->l_size;
401*fcf3ce44SJohn Forte 	cfp->cf_head->h_csize += len;
402*fcf3ce44SJohn Forte 
403*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
404*fcf3ce44SJohn Forte 	fprintf(stderr, "addcfline: post l_size %d h_cfgsizes[%d]"
405*fcf3ce44SJohn Forte 	    " %d l_free %u\n h_csize %d\n",
406*fcf3ce44SJohn Forte 	    cfp->cf_head->h_cfgs[table_index].l_size,
407*fcf3ce44SJohn Forte 	    table_index, cfp->cf_head->h_cfgsizes[table_index],
408*fcf3ce44SJohn Forte 	    cfp->cf_head->h_cfgs[table_index].l_free, cfp->cf_head->h_csize);
409*fcf3ce44SJohn Forte #endif
410*fcf3ce44SJohn Forte 
411*fcf3ce44SJohn Forte 	return (1);
412*fcf3ce44SJohn Forte }
413*fcf3ce44SJohn Forte 
414*fcf3ce44SJohn Forte /*
415*fcf3ce44SJohn Forte  * remove entry from configuration section
416*fcf3ce44SJohn Forte  */
417*fcf3ce44SJohn Forte int
418*fcf3ce44SJohn Forte remcfline(cfp_t *cfp, int table_offset, int setnum)
419*fcf3ce44SJohn Forte {
420*fcf3ce44SJohn Forte 	cfgheader_t *ch;
421*fcf3ce44SJohn Forte 	char *p, *q;
422*fcf3ce44SJohn Forte 	int len;
423*fcf3ce44SJohn Forte 	int copylen;
424*fcf3ce44SJohn Forte 	int i;
425*fcf3ce44SJohn Forte 	cfglist_t *cfl;
426*fcf3ce44SJohn Forte 	ch = cfp->cf_head;
427*fcf3ce44SJohn Forte 
428*fcf3ce44SJohn Forte 	cfl = &cfp->cf_head->h_cfgs[table_offset];
429*fcf3ce44SJohn Forte 
430*fcf3ce44SJohn Forte 	q = cfl->l_entry;
431*fcf3ce44SJohn Forte 
432*fcf3ce44SJohn Forte 	if (cfl->l_size == 0) {
433*fcf3ce44SJohn Forte 		/* list is empty */
434*fcf3ce44SJohn Forte 		return (-1);
435*fcf3ce44SJohn Forte 	}
436*fcf3ce44SJohn Forte 
437*fcf3ce44SJohn Forte 	if (!q) { /* somethings wrong here */
438*fcf3ce44SJohn Forte 		return (-1);
439*fcf3ce44SJohn Forte 	}
440*fcf3ce44SJohn Forte 
441*fcf3ce44SJohn Forte 
442*fcf3ce44SJohn Forte 	for (i = 1; i < setnum; i++) {
443*fcf3ce44SJohn Forte 		q += cfl->l_esiz[i - 1];
444*fcf3ce44SJohn Forte 		if (i >= cfl->l_nentry) { /* end of list */
445*fcf3ce44SJohn Forte 			return (-1);
446*fcf3ce44SJohn Forte 		}
447*fcf3ce44SJohn Forte 	}
448*fcf3ce44SJohn Forte 
449*fcf3ce44SJohn Forte 	if (q >= cfl->l_entry + cfl->l_size)
450*fcf3ce44SJohn Forte 		return (-1);
451*fcf3ce44SJohn Forte 
452*fcf3ce44SJohn Forte 	len = cfl->l_esiz[i - 1];
453*fcf3ce44SJohn Forte 
454*fcf3ce44SJohn Forte 
455*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLISTRM
456*fcf3ce44SJohn Forte 	fprintf(stderr, "remcfline: pre: l_size %d h_cfgsizes[%d] %d free %d"
457*fcf3ce44SJohn Forte 	    " removing len %d\n",
458*fcf3ce44SJohn Forte 	    ch->h_cfgs[table_offset].l_size, table_offset,
459*fcf3ce44SJohn Forte 	    ch->h_cfgsizes[table_offset],
460*fcf3ce44SJohn Forte 	    ch->h_cfgs[table_offset].l_free, len);
461*fcf3ce44SJohn Forte #endif
462*fcf3ce44SJohn Forte 
463*fcf3ce44SJohn Forte 	p = q + len; /* next string */
464*fcf3ce44SJohn Forte 
465*fcf3ce44SJohn Forte 	if (!(p >= cfl->l_entry + cfl->l_size)) {
466*fcf3ce44SJohn Forte 		/* if we didn't delete the last string in list */
467*fcf3ce44SJohn Forte 		/* LINTED possible overflow */
468*fcf3ce44SJohn Forte 		copylen = cfl->l_entry + cfl->l_size - p;
469*fcf3ce44SJohn Forte 		bcopy(p, q, copylen);
470*fcf3ce44SJohn Forte 		copylen = (cfl->l_nentry - i) * sizeof (int);
471*fcf3ce44SJohn Forte 		bcopy(&cfl->l_esiz[i], &cfl->l_esiz[i - 1], copylen);
472*fcf3ce44SJohn Forte 	}
473*fcf3ce44SJohn Forte 
474*fcf3ce44SJohn Forte 	/* decrement the number of sets in this list */
475*fcf3ce44SJohn Forte 	cfl->l_nentry--;
476*fcf3ce44SJohn Forte 	/* not really necessary, but.. */
477*fcf3ce44SJohn Forte 	cfl->l_esiz[cfl->l_nentry] = 0;
478*fcf3ce44SJohn Forte 
479*fcf3ce44SJohn Forte 	cfl->l_size -= len;
480*fcf3ce44SJohn Forte 	cfl->l_free += len;
481*fcf3ce44SJohn Forte 
482*fcf3ce44SJohn Forte 	p = cfl->l_entry + cfl->l_size;
483*fcf3ce44SJohn Forte 	bzero(p, cfl->l_free);
484*fcf3ce44SJohn Forte 
485*fcf3ce44SJohn Forte 	ch->h_cfgsizes[table_offset] = cfl->l_size;
486*fcf3ce44SJohn Forte 	ch->h_csize -= len;
487*fcf3ce44SJohn Forte 
488*fcf3ce44SJohn Forte 
489*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
490*fcf3ce44SJohn Forte 	fprintf(stderr,
491*fcf3ce44SJohn Forte 	    "remcfline: post: l_size %d h_cfgsizes[%d] %d free %d\n ",
492*fcf3ce44SJohn Forte 	    ch->h_cfgs[table_offset].l_size, table_offset,
493*fcf3ce44SJohn Forte 	    ch->h_cfgsizes[table_offset], ch->h_cfgs[table_offset].l_free);
494*fcf3ce44SJohn Forte #endif
495*fcf3ce44SJohn Forte 
496*fcf3ce44SJohn Forte 	return (0);
497*fcf3ce44SJohn Forte 
498*fcf3ce44SJohn Forte }
499*fcf3ce44SJohn Forte /*
500*fcf3ce44SJohn Forte  * Read entry from configuration section
501*fcf3ce44SJohn Forte  */
502*fcf3ce44SJohn Forte char *
503*fcf3ce44SJohn Forte readcfline(cfp_t *cfp, char *buf, int table_offset, int num)
504*fcf3ce44SJohn Forte {
505*fcf3ce44SJohn Forte 
506*fcf3ce44SJohn Forte 	char *q;
507*fcf3ce44SJohn Forte 	int i;
508*fcf3ce44SJohn Forte 	cfgheader_t *ch;
509*fcf3ce44SJohn Forte 	cfglist_t  *cfl;
510*fcf3ce44SJohn Forte 
511*fcf3ce44SJohn Forte 	/* this means they couldn't even find it in the parser tree */
512*fcf3ce44SJohn Forte 	if (table_offset < 0)
513*fcf3ce44SJohn Forte 		return (NULL);
514*fcf3ce44SJohn Forte 
515*fcf3ce44SJohn Forte 	ch = cfp->cf_head;
516*fcf3ce44SJohn Forte 	cfl = &ch->h_cfgs[table_offset];
517*fcf3ce44SJohn Forte 
518*fcf3ce44SJohn Forte 	q = cfl->l_entry;
519*fcf3ce44SJohn Forte 
520*fcf3ce44SJohn Forte 	for (i = 1; i < num; i++) {
521*fcf3ce44SJohn Forte 		q += cfl->l_esiz[i - 1];
522*fcf3ce44SJohn Forte 		if (i >= cfl->l_nentry) /* end of list */
523*fcf3ce44SJohn Forte 			return (NULL);
524*fcf3ce44SJohn Forte 	}
525*fcf3ce44SJohn Forte 
526*fcf3ce44SJohn Forte 	if (q >= cfl->l_entry + cfl->l_size)
527*fcf3ce44SJohn Forte 		return (NULL);
528*fcf3ce44SJohn Forte 	strcpy(buf, q);
529*fcf3ce44SJohn Forte 	return (q);
530*fcf3ce44SJohn Forte }
531*fcf3ce44SJohn Forte 
532*fcf3ce44SJohn Forte 
533*fcf3ce44SJohn Forte /*
534*fcf3ce44SJohn Forte  * overwrite from current position with new value
535*fcf3ce44SJohn Forte  */
536*fcf3ce44SJohn Forte int
537*fcf3ce44SJohn Forte replacecfline(cfp_t *cfp, char *line, int table_offset, int num)
538*fcf3ce44SJohn Forte {
539*fcf3ce44SJohn Forte /*
540*fcf3ce44SJohn Forte  * take a table offset and a num to replace
541*fcf3ce44SJohn Forte  * index in, bump the list up, leaving a hole big
542*fcf3ce44SJohn Forte  * enough for the new string, or bcopying the rest of the list
543*fcf3ce44SJohn Forte  * down only leaving a hole big enough.
544*fcf3ce44SJohn Forte  * make sure not to overflow the
545*fcf3ce44SJohn Forte  * allocated list size.
546*fcf3ce44SJohn Forte  */
547*fcf3ce44SJohn Forte 	cfgheader_t *ch;
548*fcf3ce44SJohn Forte 	cfglist_t  *cfl;
549*fcf3ce44SJohn Forte 	char *p, *q;
550*fcf3ce44SJohn Forte 	int len = strlen(line) + 1;
551*fcf3ce44SJohn Forte 	int diff = 0;
552*fcf3ce44SJohn Forte 	int i;
553*fcf3ce44SJohn Forte 	int newsize = DEFAULT_ENTRY_SIZE / 2;
554*fcf3ce44SJohn Forte 
555*fcf3ce44SJohn Forte 
556*fcf3ce44SJohn Forte 	ch = cfp->cf_head;
557*fcf3ce44SJohn Forte 	cfl = &ch->h_cfgs[table_offset];
558*fcf3ce44SJohn Forte 
559*fcf3ce44SJohn Forte 	q = cfl->l_entry;
560*fcf3ce44SJohn Forte 	for (i = 1; i < num; i++) {
561*fcf3ce44SJohn Forte 		q += cfl->l_esiz[i - 1];
562*fcf3ce44SJohn Forte 		if (i >= cfl->l_nentry) /* end of list */
563*fcf3ce44SJohn Forte 			return (-1);
564*fcf3ce44SJohn Forte 	}
565*fcf3ce44SJohn Forte 	diff = len - cfl->l_esiz[i - 1];
566*fcf3ce44SJohn Forte 	/* check for > 0, comparing uint to int */
567*fcf3ce44SJohn Forte 	if ((diff > 0) && (diff > cfl->l_free)) {
568*fcf3ce44SJohn Forte 		/*
569*fcf3ce44SJohn Forte 		 * we are going to overflow, get more mem, but only
570*fcf3ce44SJohn Forte 		 * 1/2 as much as initial calloc, we don't need to be greedy
571*fcf3ce44SJohn Forte 		 */
572*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
573*fcf3ce44SJohn Forte 		fprintf(stderr,
574*fcf3ce44SJohn Forte 		    "resizing at replacecfline from %d to %d \n",
575*fcf3ce44SJohn Forte 		    cfl->l_size + cfl->l_free, cfl->l_size +
576*fcf3ce44SJohn Forte 		    cfl->l_free + newsize);
577*fcf3ce44SJohn Forte #endif
578*fcf3ce44SJohn Forte 		cfl->l_entry = (char *)realloc(cfl->l_entry,
579*fcf3ce44SJohn Forte 		    (cfl->l_size + cfl->l_free + newsize) * sizeof (char));
580*fcf3ce44SJohn Forte 		if (cfl->l_entry == NULL) {
581*fcf3ce44SJohn Forte 			errno = ENOMEM;
582*fcf3ce44SJohn Forte 			return (-1);
583*fcf3ce44SJohn Forte 		}
584*fcf3ce44SJohn Forte 		cfl->l_free += (DEFAULT_ENTRY_SIZE / 2);
585*fcf3ce44SJohn Forte 
586*fcf3ce44SJohn Forte 		/* re-find q, we could have a whole new chunk of memory here */
587*fcf3ce44SJohn Forte 		q = cfl->l_entry;
588*fcf3ce44SJohn Forte 		for (i = 1; i < num; i++) {
589*fcf3ce44SJohn Forte 			q += cfl->l_esiz[i - 1];
590*fcf3ce44SJohn Forte 			if (i >= cfl->l_nentry) /* end of list */
591*fcf3ce44SJohn Forte 				return (-1);
592*fcf3ce44SJohn Forte 		}
593*fcf3ce44SJohn Forte 	}
594*fcf3ce44SJohn Forte 
595*fcf3ce44SJohn Forte 	p = q + cfl->l_esiz[i - 1]; /* next string */
596*fcf3ce44SJohn Forte 	cfl->l_esiz[i - 1] += diff; /* the new entry size */
597*fcf3ce44SJohn Forte 	if (diff != 0) { /* move stuff over/back for correct fit */
598*fcf3ce44SJohn Forte 		/* LINTED possible overflow */
599*fcf3ce44SJohn Forte 		bcopy(p, p + diff, (cfl->l_entry + cfl->l_size - p));
600*fcf3ce44SJohn Forte 		cfl->l_free -= diff; /* 0 - (-1) = 1 */
601*fcf3ce44SJohn Forte 		cfl->l_size += diff;
602*fcf3ce44SJohn Forte 
603*fcf3ce44SJohn Forte 		/* total of all h_cfgs[n].l_entry */
604*fcf3ce44SJohn Forte 		cfp->cf_head->h_csize += diff;
605*fcf3ce44SJohn Forte 		cfp->cf_head->h_cfgsizes[table_offset] = cfl->l_size; /* disk */
606*fcf3ce44SJohn Forte 		bzero((cfl->l_entry + cfl->l_size), cfl->l_free);
607*fcf3ce44SJohn Forte 	}
608*fcf3ce44SJohn Forte 
609*fcf3ce44SJohn Forte 	strcpy(q, line);
610*fcf3ce44SJohn Forte 	return (1);
611*fcf3ce44SJohn Forte 
612*fcf3ce44SJohn Forte }
613*fcf3ce44SJohn Forte 
614*fcf3ce44SJohn Forte static cfg_io_t _cfg_raw_io_def = {
615*fcf3ce44SJohn Forte 	NULL,
616*fcf3ce44SJohn Forte 	"Local",
617*fcf3ce44SJohn Forte 	localcf_open,
618*fcf3ce44SJohn Forte 	localcf_close,
619*fcf3ce44SJohn Forte 	localcf_seek,
620*fcf3ce44SJohn Forte 	localcf_read,
621*fcf3ce44SJohn Forte 	localcf_write,
622*fcf3ce44SJohn Forte 	readcfline,
623*fcf3ce44SJohn Forte 	addcfline,
624*fcf3ce44SJohn Forte 	remcfline,
625*fcf3ce44SJohn Forte 	replacecfline,
626*fcf3ce44SJohn Forte 
627*fcf3ce44SJohn Forte };
628*fcf3ce44SJohn Forte 
629*fcf3ce44SJohn Forte static cfg_io_t _cfg_block_io_def = {
630*fcf3ce44SJohn Forte 	NULL,
631*fcf3ce44SJohn Forte 	"Local",
632*fcf3ce44SJohn Forte 	localcf_open,
633*fcf3ce44SJohn Forte 	localcf_close,
634*fcf3ce44SJohn Forte 	localcf_seekblk,
635*fcf3ce44SJohn Forte 	localcf_readblk,
636*fcf3ce44SJohn Forte 	localcf_writeblk,
637*fcf3ce44SJohn Forte 	readcfline,
638*fcf3ce44SJohn Forte 	addcfline,
639*fcf3ce44SJohn Forte 	remcfline,
640*fcf3ce44SJohn Forte 	replacecfline,
641*fcf3ce44SJohn Forte };
642*fcf3ce44SJohn Forte 
643*fcf3ce44SJohn Forte cfg_io_t *
644*fcf3ce44SJohn Forte cfg_raw_io_provider(void)
645*fcf3ce44SJohn Forte {
646*fcf3ce44SJohn Forte 	return (&_cfg_raw_io_def);
647*fcf3ce44SJohn Forte }
648*fcf3ce44SJohn Forte 
649*fcf3ce44SJohn Forte cfg_io_t *
650*fcf3ce44SJohn Forte cfg_block_io_provider(void)
651*fcf3ce44SJohn Forte {
652*fcf3ce44SJohn Forte 	return (&_cfg_block_io_def);
653*fcf3ce44SJohn Forte }
654