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>
32 #include <sys/mnttab.h>
49 #include <sys/utsname.h>
53 #include "cfg_local.h"
57 #define DEBUG_CFGLISTRM
60 extern int cfg_severity
;
61 extern char *cfg_perror_str
;
64 get_bsize(cfp_t
*cfp
, char *name
)
66 char char_name
[PATH_MAX
];
72 if (strlen(name
) >= PATH_MAX
- 1)
75 rest
= strstr(name
, "/dsk/");
77 if ((rest
= strstr(name
, "/rdsk/")) == NULL
)
79 strcpy(char_name
, name
);
83 strcpy(char_name
, name
);
84 char_name
[strlen(name
) - strlen(rest
)] = 0;
85 strcat(char_name
, "/rdsk/");
86 strcat(char_name
, rest
+ 5);
89 fd
= open(char_name
, O_RDONLY
);
93 slice
= read_vtoc(fd
, &vtoc
);
100 if (vtoc
.v_part
[slice
].p_start
< CFG_VTOC_SIZE
)
101 cfp
->cf_flag
|= CFG_NOWRVTOC
;
103 return (vtoc
.v_part
[slice
].p_size
);
107 * round up to the next block size
110 get_block_size(int size
)
114 if (size
% CFG_BLOCK_SIZE
!= 0)
115 ret
= size
+ CFG_BLOCK_SIZE
- (size
% CFG_BLOCK_SIZE
);
122 * get a chunk of mem rounded up to next block size
125 get_block_buf(int size
)
130 blk_size
= get_block_size(size
);
132 if ((blk_buf
= (char *)calloc(blk_size
, sizeof (char))) == NULL
) {
133 cfg_severity
= CFG_EFATAL
;
134 cfg_perror_str
= dgettext("cfg", strerror(errno
));
141 free_block_buf(char *buf
)
148 localcf_close(cfp_t
*cfp
)
158 * Open the current configuration file
159 * Sets file descriptor in cfp->cf_fd for use by other routines
162 localcf_open(cfp_t
*cfp
, char *name
)
169 cfg_perror_str
= dgettext("cfg",
170 "cfg_open: unable to open configuration location");
171 cfg_severity
= CFG_EFATAL
;
175 cfp
->cf_fd
= open(name
, O_RDWR
|O_CREAT
|O_DSYNC
|O_RSYNC
, 0640);
176 if (cfp
->cf_fd
== -1) {
177 if ((cfp
->cf_fd
= open(name
, O_RDONLY
, 0640)) == -1) {
178 cfg_perror_str
= dgettext("cfg",
179 "cfg_open: unable to open configuration location");
180 cfg_severity
= CFG_EFATAL
;
183 cfp
->cf_flag
|= CFG_RDONLY
;
186 if (fstat(cfp
->cf_fd
, &sb
) == -1) {
188 cfg_perror_str
= dgettext("cfg",
189 "cfg_open: unable to stat configuration location");
190 cfg_severity
= CFG_EFATAL
;
195 if (S_ISBLK(sb
.st_mode
) || S_ISCHR(sb
.st_mode
)) {
196 cfp
->cf_size
= get_bsize(cfp
, name
);
198 /* skip the vtoc if necessary */
199 if (cfp
->cf_flag
& CFG_NOWRVTOC
) {
201 rc
= lseek(cfp
->cf_fd
, CFG_VTOC_SKIP
, SEEK_SET
);
202 } while (rc
== -1 && errno
== EINTR
);
205 cfg_perror_str
= dgettext("cfg",
207 cfg_severity
= CFG_EFATAL
;
213 } else if (S_ISREG(sb
.st_mode
)) {
214 cfp
->cf_flag
|= CFG_FILE
;
215 cfp
->cf_size
= FBA_NUM(FBA_SIZE(1) - 1 + sb
.st_size
);
217 cfg_perror_str
= dgettext("cfg", "cfg_open: unknown file type");
218 cfg_severity
= CFG_EFATAL
;
227 localcf_seekblk(cfp_t
*cfp
, int off
, int mode
)
232 rc
= lseek(cfp
->cf_fd
, off
, mode
);
233 } while (rc
== -1 && errno
== EINTR
);
239 localcf_readblk(cfp_t
*cfp
, void *buf
, int size
)
244 rc
= read(cfp
->cf_fd
, buf
, size
);
245 } while (rc
== -1 && errno
== EINTR
);
251 localcf_writeblk(cfp_t
*cfp
, void *buf
, int size
)
256 rc
= write(cfp
->cf_fd
, buf
, size
);
257 } while (rc
== -1 && errno
== EINTR
);
263 localcf_seek(cfp_t
*cfp
, int off
, int mode
)
268 offset
= get_block_size(off
);
270 if ((mode
== SEEK_SET
) && (cfp
->cf_flag
& CFG_NOWRVTOC
)) {
271 offset
+= CFG_VTOC_SKIP
;
275 rc
= lseek(cfp
->cf_fd
, offset
, mode
);
276 } while (rc
== -1 && errno
== EINTR
);
282 localcf_read(cfp_t
*cfp
, void *buf
, int size
)
288 blk_size
= get_block_size(size
);
289 if ((blk_buf
= get_block_buf(size
)) == NULL
)
293 rc
= read(cfp
->cf_fd
, blk_buf
, blk_size
);
294 } while (rc
== -1 && errno
== EINTR
);
296 bcopy(blk_buf
, buf
, size
);
297 free_block_buf(blk_buf
);
303 localcf_write(cfp_t
*cfp
, void *buf
, int size
)
309 blk_size
= get_block_size(size
);
310 if ((blk_buf
= get_block_buf(size
)) == NULL
)
313 bcopy(buf
, blk_buf
, size
);
316 rc
= write(cfp
->cf_fd
, blk_buf
, blk_size
);
317 } while (rc
== -1 && errno
== EINTR
);
319 free_block_buf(blk_buf
);
324 * Routines which operate on internal version of configuration
328 * Add entry to end of configuration section
332 addcfline(cfp_t
*cfp
, char *line
, int table_index
)
334 int len
= strlen(line
)+1;
335 int newsize
= DEFAULT_ENTRY_SIZE
/ 2;
341 fprintf(stderr
, "addcfline: pre l_size %d h_cfgsizes[%d]"
342 " %d l_free %u adding len %d\n",
343 cfp
->cf_head
->h_cfgs
[table_index
].l_size
, table_index
,
344 cfp
->cf_head
->h_cfgsizes
[table_index
],
345 cfp
->cf_head
->h_cfgs
[table_index
].l_free
, len
);
349 cfl
= &cfp
->cf_head
->h_cfgs
[table_index
];
350 if (cfl
->l_free
< len
) {
353 fprintf(stderr
, "resizing l_entry from %d to %d\n",
354 cfl
->l_size
+ cfl
->l_free
, cfl
->l_size
+
355 cfl
->l_free
+ newsize
);
357 cfl
->l_entry
= (char *)realloc(cfl
->l_entry
, (cfl
->l_size
+
358 cfl
->l_free
+ newsize
) * sizeof (char));
359 if (cfl
->l_entry
== NULL
) {
363 cfl
->l_free
+= newsize
;
368 /* out of list slots, get some more */
369 if (cfl
->l_nentry
% DEFAULT_NENTRIES
== 0) {
371 * first, figure out how much bigger, than realloc
376 "list %d getting more nentries, I have %d\n",
377 table_index
, cfl
->l_nentry
);
379 cfl
->l_esiz
= (int *)
380 realloc(cfl
->l_esiz
, (cfl
->l_nentry
+ DEFAULT_NENTRIES
) *
382 if (cfl
->l_esiz
== NULL
) {
389 cfl
->l_esiz
[cfl
->l_nentry
] = len
;
392 /* add line to end of list */
393 q
= cfl
->l_entry
+ cfl
->l_size
;
399 hd
->h_cfgs
[table_index
].l_size
+= len
;
400 hd
->h_cfgsizes
[table_index
] = cfl
->l_size
;
401 cfp
->cf_head
->h_csize
+= len
;
404 fprintf(stderr
, "addcfline: post l_size %d h_cfgsizes[%d]"
405 " %d l_free %u\n h_csize %d\n",
406 cfp
->cf_head
->h_cfgs
[table_index
].l_size
,
407 table_index
, cfp
->cf_head
->h_cfgsizes
[table_index
],
408 cfp
->cf_head
->h_cfgs
[table_index
].l_free
, cfp
->cf_head
->h_csize
);
415 * remove entry from configuration section
418 remcfline(cfp_t
*cfp
, int table_offset
, int setnum
)
428 cfl
= &cfp
->cf_head
->h_cfgs
[table_offset
];
432 if (cfl
->l_size
== 0) {
437 if (!q
) { /* somethings wrong here */
442 for (i
= 1; i
< setnum
; i
++) {
443 q
+= cfl
->l_esiz
[i
- 1];
444 if (i
>= cfl
->l_nentry
) { /* end of list */
449 if (q
>= cfl
->l_entry
+ cfl
->l_size
)
452 len
= cfl
->l_esiz
[i
- 1];
455 #ifdef DEBUG_CFGLISTRM
456 fprintf(stderr
, "remcfline: pre: l_size %d h_cfgsizes[%d] %d free %d"
457 " removing len %d\n",
458 ch
->h_cfgs
[table_offset
].l_size
, table_offset
,
459 ch
->h_cfgsizes
[table_offset
],
460 ch
->h_cfgs
[table_offset
].l_free
, len
);
463 p
= q
+ len
; /* next string */
465 if (!(p
>= cfl
->l_entry
+ cfl
->l_size
)) {
466 /* if we didn't delete the last string in list */
467 /* LINTED possible overflow */
468 copylen
= cfl
->l_entry
+ cfl
->l_size
- p
;
469 bcopy(p
, q
, copylen
);
470 copylen
= (cfl
->l_nentry
- i
) * sizeof (int);
471 bcopy(&cfl
->l_esiz
[i
], &cfl
->l_esiz
[i
- 1], copylen
);
474 /* decrement the number of sets in this list */
476 /* not really necessary, but.. */
477 cfl
->l_esiz
[cfl
->l_nentry
] = 0;
482 p
= cfl
->l_entry
+ cfl
->l_size
;
483 bzero(p
, cfl
->l_free
);
485 ch
->h_cfgsizes
[table_offset
] = cfl
->l_size
;
491 "remcfline: post: l_size %d h_cfgsizes[%d] %d free %d\n ",
492 ch
->h_cfgs
[table_offset
].l_size
, table_offset
,
493 ch
->h_cfgsizes
[table_offset
], ch
->h_cfgs
[table_offset
].l_free
);
500 * Read entry from configuration section
503 readcfline(cfp_t
*cfp
, char *buf
, int table_offset
, int num
)
511 /* this means they couldn't even find it in the parser tree */
512 if (table_offset
< 0)
516 cfl
= &ch
->h_cfgs
[table_offset
];
520 for (i
= 1; i
< num
; i
++) {
521 q
+= cfl
->l_esiz
[i
- 1];
522 if (i
>= cfl
->l_nentry
) /* end of list */
526 if (q
>= cfl
->l_entry
+ cfl
->l_size
)
534 * overwrite from current position with new value
537 replacecfline(cfp_t
*cfp
, char *line
, int table_offset
, int num
)
540 * take a table offset and a num to replace
541 * index in, bump the list up, leaving a hole big
542 * enough for the new string, or bcopying the rest of the list
543 * down only leaving a hole big enough.
544 * make sure not to overflow the
545 * allocated list size.
550 int len
= strlen(line
) + 1;
553 int newsize
= DEFAULT_ENTRY_SIZE
/ 2;
557 cfl
= &ch
->h_cfgs
[table_offset
];
560 for (i
= 1; i
< num
; i
++) {
561 q
+= cfl
->l_esiz
[i
- 1];
562 if (i
>= cfl
->l_nentry
) /* end of list */
565 diff
= len
- cfl
->l_esiz
[i
- 1];
566 /* check for > 0, comparing uint to int */
567 if ((diff
> 0) && (diff
> cfl
->l_free
)) {
569 * we are going to overflow, get more mem, but only
570 * 1/2 as much as initial calloc, we don't need to be greedy
574 "resizing at replacecfline from %d to %d \n",
575 cfl
->l_size
+ cfl
->l_free
, cfl
->l_size
+
576 cfl
->l_free
+ newsize
);
578 cfl
->l_entry
= (char *)realloc(cfl
->l_entry
,
579 (cfl
->l_size
+ cfl
->l_free
+ newsize
) * sizeof (char));
580 if (cfl
->l_entry
== NULL
) {
584 cfl
->l_free
+= (DEFAULT_ENTRY_SIZE
/ 2);
586 /* re-find q, we could have a whole new chunk of memory here */
588 for (i
= 1; i
< num
; i
++) {
589 q
+= cfl
->l_esiz
[i
- 1];
590 if (i
>= cfl
->l_nentry
) /* end of list */
595 p
= q
+ cfl
->l_esiz
[i
- 1]; /* next string */
596 cfl
->l_esiz
[i
- 1] += diff
; /* the new entry size */
597 if (diff
!= 0) { /* move stuff over/back for correct fit */
598 /* LINTED possible overflow */
599 bcopy(p
, p
+ diff
, (cfl
->l_entry
+ cfl
->l_size
- p
));
600 cfl
->l_free
-= diff
; /* 0 - (-1) = 1 */
603 /* total of all h_cfgs[n].l_entry */
604 cfp
->cf_head
->h_csize
+= diff
;
605 cfp
->cf_head
->h_cfgsizes
[table_offset
] = cfl
->l_size
; /* disk */
606 bzero((cfl
->l_entry
+ cfl
->l_size
), cfl
->l_free
);
614 static cfg_io_t _cfg_raw_io_def
= {
629 static cfg_io_t _cfg_block_io_def
= {
644 cfg_raw_io_provider(void)
646 return (&_cfg_raw_io_def
);
650 cfg_block_io_provider(void)
652 return (&_cfg_block_io_def
);