1 /*
2  * Copyright (c) 1998,1999,2000
3  *	Traakan, Inc., Los Altos, CA
4  *	All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice unmodified, this list of conditions, and the following
11  *    disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 /*
30  * Project:  NDMJOB
31  * Ident:    $Id: $
32  *
33  * Description:
34  *
35  */
36 
37 
38 #include "ndmlib.h"
39 
40 #define CFG_BUF_SIZE	512
41 #define CFG_MAX_SV	32
42 
43 /* control block */
44 struct cfg_cb {
45 	FILE *			fp;
46 	ndmp9_config_info *	config_info;
47 	char			buf[CFG_BUF_SIZE];
48 	char *			sv[CFG_MAX_SV];
49 	int			sc;
50 	int			n_error;
51 };
52 
53 
54 static int	cfg_butype (struct cfg_cb *cb);
55 static int	cfg_fs (struct cfg_cb *cb);
56 static int	cfg_tape (struct cfg_cb *cb);
57 static int	cfg_scsi (struct cfg_cb *cb);
58 static int	cfg_device (struct cfg_cb *cb, u_int *n_device,
59 			ndmp9_device_info **pp);
60 static int	cfg_add_env (struct cfg_cb *cb, u_int *n_env,
61 			ndmp9_pval **pp, char *name, char *value);
62 
63 
64 
65 
66 int
ndmcfg_load(char * filename,ndmp9_config_info * config_info)67 ndmcfg_load (char *filename, ndmp9_config_info *config_info)
68 {
69 	FILE *		fp;
70 	int		rc;
71 
72 	fp = fopen (filename, "r");
73 	if (!fp)
74 		return -1;
75 
76 	rc = ndmcfg_loadfp (fp, config_info);
77 
78 	fclose (fp);
79 
80 	return rc;
81 }
82 
83 int
ndmcfg_loadfp(FILE * fp,ndmp9_config_info * config_info)84 ndmcfg_loadfp (FILE *fp, ndmp9_config_info *config_info)
85 {
86 	struct cfg_cb	_cb, *cb = &_cb;
87 	int		rc;
88 
89 	NDMOS_MACRO_ZEROFILL (cb);
90 
91 	cb->fp = fp;
92 	cb->config_info = config_info;
93 
94 	for (;;) {
95 		rc = ndmstz_getstanza (cb->fp, cb->buf, sizeof cb->buf);
96 		if (rc == EOF) {
97 			break;
98 		}
99 
100 		cb->sc = ndmstz_parse (cb->buf, cb->sv, CFG_MAX_SV);
101 		if (cb->sc < 1) {
102 			continue;
103 		}
104 
105 		if (strcmp (cb->sv[0], "butype") == 0 && cb->sc == 2) {
106 			cfg_butype (cb);
107 			continue;
108 		}
109 
110 		if (strcmp (cb->sv[0], "fs") == 0 && cb->sc == 2) {
111 			cfg_fs (cb);
112 			continue;
113 		}
114 
115 		if (strcmp (cb->sv[0], "tape") == 0 && cb->sc == 2) {
116 			cfg_tape (cb);
117 			continue;
118 		}
119 
120 		if (strcmp (cb->sv[0], "scsi") == 0 && cb->sc == 2) {
121 			cfg_scsi (cb);
122 			continue;
123 		}
124 
125 		/*
126 		 * Unrecognized stanzas are deemed for other purposes
127 		 * and tolerated.
128 		 */
129 	}
130 
131 	return cb->n_error;
132 }
133 
134 /*
135  * [butype BUTYPE]
136  *	v2attr	0xATTR
137  *	v3attr	0xATTR
138  *	v4attr	0xATTR
139  *	default_env NAME VALUE
140  */
141 
142 static int
cfg_butype(struct cfg_cb * cb)143 cfg_butype (struct cfg_cb *cb)
144 {
145 	ndmp9_config_info *	cfg = cb->config_info;
146 	ndmp9_butype_info *	ent = cfg->butype_info.butype_info_val;
147 	int			n_ent = cfg->butype_info.butype_info_len;
148 	int			i, rc;
149 
150 	if (!ent)
151 		n_ent = 0;
152 
153 	ent = NDMOS_MACRO_NEWN(ndmp9_butype_info, n_ent+1);
154 	if (!ent) {
155 		cb->n_error++;
156 		return -1;
157 	}
158 
159 	for (i = 0; i < n_ent; i++) {
160 		ent[i] = cfg->butype_info.butype_info_val[i];
161 	}
162 
163 	if (cfg->butype_info.butype_info_val) {
164 		NDMOS_API_FREE (cfg->butype_info.butype_info_val);
165 	}
166 	cfg->butype_info.butype_info_val = ent;
167 	cfg->butype_info.butype_info_len = n_ent+1;
168 	ent += n_ent;
169 
170 	NDMOS_MACRO_ZEROFILL (ent);
171 
172 	ent->butype_name = NDMOS_API_STRDUP (cb->sv[1]);
173 
174 	for (;;) {
175 		rc = ndmstz_getline (cb->fp, cb->buf, CFG_BUF_SIZE);
176 		if (rc < 0)
177 			break;
178 
179 		cb->sc = ndmstz_parse (cb->buf, cb->sv, CFG_MAX_SV);
180 		if (cb->sc < 1) {
181 			continue;
182 		}
183 
184 		if (strcmp (cb->sv[0], "v2attr") == 0 && cb->sc == 2) {
185 			ent->v2attr.valid = NDMP9_VALIDITY_VALID;
186 			ent->v2attr.value = strtol (cb->sv[1], 0, 0);
187 			continue;
188 		}
189 
190 		if (strcmp (cb->sv[0], "v3attr") == 0 && cb->sc == 2) {
191 			ent->v3attr.valid = NDMP9_VALIDITY_VALID;
192 			ent->v3attr.value = strtol (cb->sv[1], 0, 0);
193 			continue;
194 		}
195 
196 		if (strcmp (cb->sv[0], "v4attr") == 0 && cb->sc == 2) {
197 			ent->v4attr.valid = NDMP9_VALIDITY_VALID;
198 			ent->v4attr.value = strtol (cb->sv[1], 0, 0);
199 			continue;
200 		}
201 
202 		if (strcmp (cb->sv[0], "default_env") == 0 && cb->sc == 3) {
203 			cfg_add_env (cb, &ent->default_env.default_env_len,
204 				&ent->default_env.default_env_val,
205 				cb->sv[1], cb->sv[2]);
206 			continue;
207 		}
208 
209 		/*
210 		 * Unrecognized lines are deemed version differences
211 		 * and tolerated.
212 		 */
213 	}
214 
215 	return 0;
216 }
217 
218 /*
219  * [fs MOUNTPOINT]
220  *	fs_type TYPE
221  *	fs_physical_device DEVICEPATH
222  *	fs_status "COMMENT"
223  *	fs_env NAME VALUE
224  */
225 
226 static int
cfg_fs(struct cfg_cb * cb)227 cfg_fs (struct cfg_cb *cb)
228 {
229 	ndmp9_config_info *	cfg = cb->config_info;
230 	ndmp9_fs_info *		ent = cfg->fs_info.fs_info_val;
231 	int			n_ent = cfg->fs_info.fs_info_len;
232 	int			i, rc;
233 
234 	if (!ent)
235 		n_ent = 0;
236 
237 	ent = NDMOS_MACRO_NEWN(ndmp9_fs_info, n_ent+1);
238 	if (!ent) {
239 		cb->n_error++;
240 		return -1;
241 	}
242 
243 	for (i = 0; i < n_ent; i++) {
244 		ent[i] = cfg->fs_info.fs_info_val[i];
245 	}
246 
247 	if (cfg->fs_info.fs_info_val) {
248 		NDMOS_API_FREE (cfg->fs_info.fs_info_val);
249 	}
250 	cfg->fs_info.fs_info_val = ent;
251 	cfg->fs_info.fs_info_len = n_ent+1;
252 	ent += n_ent;
253 
254 	NDMOS_MACRO_ZEROFILL (ent);
255 
256 	ent->fs_logical_device = NDMOS_API_STRDUP (cb->sv[1]);
257 
258 	for (;;) {
259 		rc = ndmstz_getline (cb->fp, cb->buf, CFG_BUF_SIZE);
260 		if (rc < 0)
261 			break;
262 
263 		cb->sc = ndmstz_parse (cb->buf, cb->sv, CFG_MAX_SV);
264 		if (cb->sc < 1) {
265 			continue;
266 		}
267 
268 		if (strcmp (cb->sv[0], "fs_type") == 0 && cb->sc == 2) {
269 			ent->fs_type = NDMOS_API_STRDUP (cb->sv[1]);
270 			continue;
271 		}
272 
273 		if (strcmp (cb->sv[0], "fs_physical_device") == 0
274 		 && cb->sc == 2) {
275 			ent->fs_physical_device = NDMOS_API_STRDUP (cb->sv[1]);
276 			continue;
277 		}
278 
279 		if (strcmp (cb->sv[0], "fs_status") == 0 && cb->sc == 2) {
280 			ent->fs_status = NDMOS_API_STRDUP (cb->sv[1]);
281 			continue;
282 		}
283 
284 		if (strcmp (cb->sv[0], "fs_env") == 0 && cb->sc == 3) {
285 			cfg_add_env (cb, &ent->fs_env.fs_env_len,
286 				&ent->fs_env.fs_env_val,
287 				cb->sv[1], cb->sv[2]);
288 			continue;
289 		}
290 
291 		/*
292 		 * Unrecognized lines are deemed version differences
293 		 * and tolerated.
294 		 */
295 	}
296 
297 	return 0;
298 }
299 
300 static int
cfg_tape(struct cfg_cb * cb)301 cfg_tape (struct cfg_cb *cb)
302 {
303 	ndmp9_config_info *	cfg = cb->config_info;
304 
305 	return cfg_device (cb, &cfg->tape_info.tape_info_len,
306 				&cfg->tape_info.tape_info_val);
307 }
308 
309 static int
cfg_scsi(struct cfg_cb * cb)310 cfg_scsi (struct cfg_cb *cb)
311 {
312 	ndmp9_config_info *	cfg = cb->config_info;
313 
314 	return cfg_device (cb, &cfg->scsi_info.scsi_info_len,
315 				&cfg->scsi_info.scsi_info_val);
316 }
317 
318 /*
319  * [tape IDENT]  or  [scsi IDENT]
320  *	device DEVICEPATH
321  *	v3attr 0xATTR
322  *	v4attr 0xATTR
323  *	capability NAME VALUE
324  */
325 
326 static int
cfg_device(struct cfg_cb * cb,u_int * n_device,ndmp9_device_info ** pp)327 cfg_device (struct cfg_cb *cb, u_int *n_device, ndmp9_device_info **pp)
328 {
329 	ndmp9_device_info *	ent = *pp;
330 	ndmp9_device_capability *dcap;
331 	int			rc;
332 	unsigned int		i, n_ent = *n_device;
333 
334 	if (!ent)
335 		n_ent = 0;
336 
337 	for (i = 0; i < n_ent; i++) {
338 		if (strcmp(ent[i].model, (*pp)[i].model) == 0) {
339 			ent += i;
340 			goto got_model;
341 		}
342 	}
343 
344 	ent = NDMOS_MACRO_NEWN(ndmp9_device_info, n_ent+1);
345 	if (!ent) {
346 		cb->n_error++;
347 		return -1;
348 	}
349 
350 	for (i = 0; i < n_ent; i++) {
351 		ent[i] = (*pp)[i];
352 	}
353 
354 	if (*pp) {
355 		NDMOS_API_FREE (*pp);
356 	}
357 	*pp = ent;
358 	*n_device = n_ent+1;
359 	ent += n_ent;
360 
361 	NDMOS_MACRO_ZEROFILL (ent);
362 	ent->model = NDMOS_API_STRDUP (cb->sv[1]);
363 
364   got_model:
365 	dcap = NDMOS_MACRO_NEWN (ndmp9_device_capability,
366 			ent->caplist.caplist_len+1);
367 	if (!dcap) {
368 		cb->n_error++;
369 		return -1;
370 	}
371 
372 	for (i = 0; i < ent->caplist.caplist_len; i++) {
373 		dcap[i] = ent->caplist.caplist_val[i];
374 	}
375 	if (ent->caplist.caplist_val) {
376 		NDMOS_API_FREE (ent->caplist.caplist_val);
377 	}
378 
379 	ent->caplist.caplist_val = dcap;
380 	dcap += ent->caplist.caplist_len++;
381 	NDMOS_MACRO_ZEROFILL (dcap);
382 
383 	for (;;) {
384 		rc = ndmstz_getline (cb->fp, cb->buf, CFG_BUF_SIZE);
385 		if (rc < 0)
386 			break;
387 
388 		cb->sc = ndmstz_parse (cb->buf, cb->sv, CFG_MAX_SV);
389 		if (cb->sc < 1) {
390 			continue;
391 		}
392 
393 		if (strcmp (cb->sv[0], "device") == 0 && cb->sc == 2) {
394 			dcap->device = NDMOS_API_STRDUP (cb->sv[1]);
395 			continue;
396 		}
397 
398 		if (strcmp (cb->sv[0], "v3attr") == 0 && cb->sc == 2) {
399 			dcap->v3attr.valid = NDMP9_VALIDITY_VALID;
400 			dcap->v3attr.value = strtol (cb->sv[1], 0, 0);
401 			continue;
402 		}
403 
404 		if (strcmp (cb->sv[0], "v4attr") == 0 && cb->sc == 2) {
405 			dcap->v4attr.valid = NDMP9_VALIDITY_VALID;
406 			dcap->v4attr.value = strtol (cb->sv[1], 0, 0);
407 			continue;
408 		}
409 
410 		if (strcmp (cb->sv[0], "capability") == 0 && cb->sc == 3) {
411 			cfg_add_env (cb, &dcap->capability.capability_len,
412 				&dcap->capability.capability_val,
413 				cb->sv[1], cb->sv[2]);
414 			continue;
415 		}
416 
417 		/*
418 		 * Unrecognized lines are deemed version differences
419 		 * and tolerated.
420 		 */
421 	}
422 
423 	return 0;
424 }
425 
426 static int
cfg_add_env(struct cfg_cb * cb,u_int * n_env,ndmp9_pval ** pp,char * name,char * value)427 cfg_add_env (struct cfg_cb *cb, u_int *n_env,
428   ndmp9_pval **pp, char *name, char *value)
429 {
430 	ndmp9_pval *		ent = *pp;
431 	int			n_ent = *n_env;
432 	int			i;
433 
434 	if (!ent)
435 		n_ent = 0;
436 
437 	ent = NDMOS_MACRO_NEWN(ndmp9_pval, n_ent+1);
438 	if (!ent) {
439 		cb->n_error++;
440 		return -1;
441 	}
442 
443 	for (i = 0; i < n_ent; i++) {
444 		ent[i] = (*pp)[i];
445 	}
446 
447 	if (*pp) {
448 		NDMOS_API_FREE (*pp);
449 	}
450 
451 	*pp = ent;
452 	*n_env = n_ent+1;
453 	ent += n_ent;
454 
455 	NDMOS_MACRO_ZEROFILL (ent);
456 	ent->name = NDMOS_API_STRDUP (name);
457 	ent->value = NDMOS_API_STRDUP (value);
458 
459 	return 0;
460 }
461 
462 #ifdef SELF_TEST
463 
464 int
main(int argc,char * argv[])465 main (int argc, char *argv[])
466 {
467 	ndmp9_config_info	config_info;
468 	int			rc, i, j, k;
469 
470 	if (argc != 2) {
471 		printf ("usage: %s FILE\n", argv[0]);
472 		return 1;
473 	}
474 
475 	NDMOS_MACRO_ZEROFILL (&config_info);
476 
477 	rc = ndmcfg_load (argv[1], &config_info);
478 	printf ("%d errors\n", rc);
479 
480 	for (i = 0; i < config_info.butype_info.butype_info_len; i++) {
481 		ndmp9_butype_info *	bu;
482 
483 		bu = &config_info.butype_info.butype_info_val[i];
484 		printf ("butype[%d] name='%s'\n", i, bu->butype_name);
485 		if (bu->v2attr.valid) {
486 			printf ("  v2attr 0x%x\n", bu->v2attr.value);
487 		} else {
488 			printf ("  v2attr -invalid-\n");
489 		}
490 		if (bu->v3attr.valid) {
491 			printf ("  v3attr 0x%x\n", bu->v3attr.value);
492 		} else {
493 			printf ("  v3attr -invalid-\n");
494 		}
495 		if (bu->v4attr.valid) {
496 			printf ("  v4attr 0x%x\n", bu->v4attr.value);
497 		} else {
498 			printf ("  v4attr -invalid-\n");
499 		}
500 		for (j = 0; j < bu->default_env.default_env_len; j++) {
501 			ndmp9_pval *	env;
502 
503 			env = &bu->default_env.default_env_val[j];
504 			printf ("  default_env[%d] '%s'='%s'\n",
505 				j, env->name, env->value);
506 		}
507 	}
508 
509 	for (i = 0; i < config_info.fs_info.fs_info_len; i++) {
510 		ndmp9_fs_info *	fs;
511 
512 		fs = &config_info.fs_info.fs_info_val[i];
513 		printf ("fs[%d] fs_logical_device='%s'\n",
514 			 i, fs->fs_logical_device);
515 		if (fs->fs_physical_device) {
516 			printf ("  fs_physical_device '%s'\n",
517 				fs->fs_physical_device);
518 		} else {
519 			printf ("  fs_physical_device -null-\n");
520 		}
521 		if (fs->fs_type) {
522 			printf ("  fs_type '%s'\n", fs->fs_type);
523 		} else {
524 			printf ("  fs_type -null-\n");
525 		}
526 		if (fs->fs_status) {
527 			printf ("  fs_status '%s'\n", fs->fs_status);
528 		} else {
529 			printf ("  fs_status -null-\n");
530 		}
531 		if (fs->total_size.valid) {
532 			printf ("  total_size %llu\n", fs->total_size.value);
533 		} else {
534 			printf ("  total_size -invalid-\n");
535 		}
536 		if (fs->used_size.valid) {
537 			printf ("  used_size %llu\n", fs->used_size.value);
538 		} else {
539 			printf ("  used_size -invalid-\n");
540 		}
541 		if (fs->avail_size.valid) {
542 			printf ("  avail_size %llu\n", fs->avail_size.value);
543 		} else {
544 			printf ("  avail_size -invalid-\n");
545 		}
546 		if (fs->total_inodes.valid) {
547 			printf ("  total_inodes %llu\n",
548 				fs->total_inodes.value);
549 		} else {
550 			printf ("  total_inodes -invalid-\n");
551 		}
552 		if (fs->used_inodes.valid) {
553 			printf ("  used_inodes %llu\n", fs->used_inodes.value);
554 		} else {
555 			printf ("  used_inodes -invalid-\n");
556 		}
557 
558 		for (j = 0; j < fs->fs_env.fs_env_len; j++) {
559 			ndmp9_pval *	env;
560 
561 			env = &fs->fs_env.fs_env_val[j];
562 			printf ("  fs_env[%d] '%s'='%s'\n",
563 				j, env->name, env->value);
564 		}
565 	}
566 
567 	for (i = 0; i < config_info.tape_info.tape_info_len; i++) {
568 		ndmp9_device_info *	dev;
569 
570 		dev = &config_info.tape_info.tape_info_val[i];
571 		printf ("tape[%d] model='%s'\n", i, dev->model);
572 
573 		for (j = 0; j < dev->caplist.caplist_len; j++) {
574 			struct ndmp9_device_capability *dcap;
575 
576 			dcap = &dev->caplist.caplist_val[j];
577 			printf (" capability %d\n", j);
578 
579 			if (dcap->device) {
580 				printf ("  device '%s'\n", dcap->device);
581 			} else {
582 				printf ("  device -null-\n");
583 			}
584 			if (dcap->v3attr.valid) {
585 				printf ("  v3attr 0x%x\n", dcap->v3attr.value);
586 			} else {
587 				printf ("  v3attr -invalid-\n");
588 			}
589 			if (dcap->v4attr.valid) {
590 				printf ("  v4attr 0x%x\n", dcap->v4attr.value);
591 			} else {
592 				printf ("  v4attr -invalid-\n");
593 			}
594 			k = 0;
595 			for (; k < dcap->capability.capability_len; k++) {
596 				ndmp9_pval *env;
597 				env = &dcap->capability.capability_val[k];
598 				printf ("  capability[%d] '%s'='%s'\n",
599 					k, env->name, env->value);
600 			}
601 		}
602 	}
603 
604 	for (i = 0; i < config_info.scsi_info.scsi_info_len; i++) {
605 		ndmp9_device_info *	dev;
606 
607 		dev = &config_info.scsi_info.scsi_info_val[i];
608 		printf ("scsi[%d] model='%s'\n", i, dev->model);
609 
610 		for (j = 0; j < dev->caplist.caplist_len; j++) {
611 			struct ndmp9_device_capability *dcap;
612 
613 			dcap = &dev->caplist.caplist_val[j];
614 			printf (" capability %d\n", j);
615 
616 			if (dcap->device) {
617 				printf ("  device '%s'\n", dcap->device);
618 			} else {
619 				printf ("  device -null-\n");
620 			}
621 			if (dcap->v3attr.valid) {
622 				printf ("  v3attr 0x%x\n", dcap->v3attr.value);
623 			} else {
624 				printf ("  v3attr -invalid-\n");
625 			}
626 			if (dcap->v4attr.valid) {
627 				printf ("  v4attr 0x%x\n", dcap->v4attr.value);
628 			} else {
629 				printf ("  v4attr -invalid-\n");
630 			}
631 			k = 0;
632 			for (; k < dcap->capability.capability_len; k++) {
633 				ndmp9_pval *env;
634 				env = &dcap->capability.capability_val[k];
635 				printf ("  capability[%d] '%s'='%s'\n",
636 					k, env->name, env->value);
637 			}
638 		}
639 	}
640 
641 
642 	return 0;
643 }
644 
645 #endif /* SELF_TEST */
646