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,
59                       u_int* n_device,
60                       ndmp9_device_info** pp);
61 static int cfg_add_env(struct cfg_cb* cb,
62                        u_int* n_env,
63                        ndmp9_pval** pp,
64                        char* name,
65                        char* value);
66 
67 
ndmcfg_load(char * filename,ndmp9_config_info * config_info)68 int ndmcfg_load(char* filename, ndmp9_config_info* config_info)
69 {
70   FILE* fp;
71   int rc;
72 
73   fp = fopen(filename, "r");
74   if (!fp) return -1;
75 
76   rc = ndmcfg_loadfp(fp, config_info);
77 
78   fclose(fp);
79 
80   return rc;
81 }
82 
ndmcfg_loadfp(FILE * fp,ndmp9_config_info * config_info)83 int ndmcfg_loadfp(FILE* fp, ndmp9_config_info* config_info)
84 {
85   struct cfg_cb _cb, *cb = &_cb;
86   int rc;
87 
88   NDMOS_MACRO_ZEROFILL(cb);
89 
90   cb->fp = fp;
91   cb->config_info = config_info;
92 
93   for (;;) {
94     rc = ndmstz_getstanza(cb->fp, cb->buf, sizeof cb->buf);
95     if (rc == EOF) { break; }
96 
97     cb->sc = ndmstz_parse(cb->buf, cb->sv, CFG_MAX_SV);
98     if (cb->sc < 1) { continue; }
99 
100     if (strcmp(cb->sv[0], "butype") == 0 && cb->sc == 2) {
101       cfg_butype(cb);
102       continue;
103     }
104 
105     if (strcmp(cb->sv[0], "fs") == 0 && cb->sc == 2) {
106       cfg_fs(cb);
107       continue;
108     }
109 
110     if (strcmp(cb->sv[0], "tape") == 0 && cb->sc == 2) {
111       cfg_tape(cb);
112       continue;
113     }
114 
115     if (strcmp(cb->sv[0], "scsi") == 0 && cb->sc == 2) {
116       cfg_scsi(cb);
117       continue;
118     }
119 
120     /*
121      * Unrecognized stanzas are deemed for other purposes
122      * and tolerated.
123      */
124   }
125 
126   return cb->n_error;
127 }
128 
129 /*
130  * [butype BUTYPE]
131  *      v2attr  0xATTR
132  *      v3attr  0xATTR
133  *      v4attr  0xATTR
134  *      default_env NAME VALUE
135  */
136 
cfg_butype(struct cfg_cb * cb)137 static int cfg_butype(struct cfg_cb* cb)
138 {
139   ndmp9_config_info* cfg = cb->config_info;
140   ndmp9_butype_info* ent = cfg->butype_info.butype_info_val;
141   int n_ent = cfg->butype_info.butype_info_len;
142   int i, rc;
143 
144   if (!ent) n_ent = 0;
145 
146   ent = NDMOS_MACRO_NEWN(ndmp9_butype_info, n_ent + 1);
147   if (!ent) {
148     cb->n_error++;
149     return -1;
150   }
151 
152   for (i = 0; i < n_ent; i++) { ent[i] = cfg->butype_info.butype_info_val[i]; }
153 
154   if (cfg->butype_info.butype_info_val) {
155     NDMOS_API_FREE(cfg->butype_info.butype_info_val);
156   }
157   cfg->butype_info.butype_info_val = ent;
158   cfg->butype_info.butype_info_len = n_ent + 1;
159   ent += n_ent;
160 
161   NDMOS_MACRO_ZEROFILL(ent);
162 
163   ent->butype_name = NDMOS_API_STRDUP(cb->sv[1]);
164 
165   for (;;) {
166     rc = ndmstz_getline(cb->fp, cb->buf, CFG_BUF_SIZE);
167     if (rc < 0) break;
168 
169     cb->sc = ndmstz_parse(cb->buf, cb->sv, CFG_MAX_SV);
170     if (cb->sc < 1) { continue; }
171 
172     if (strcmp(cb->sv[0], "v2attr") == 0 && cb->sc == 2) {
173       ent->v2attr.valid = NDMP9_VALIDITY_VALID;
174       ent->v2attr.value = strtol(cb->sv[1], 0, 0);
175       continue;
176     }
177 
178     if (strcmp(cb->sv[0], "v3attr") == 0 && cb->sc == 2) {
179       ent->v3attr.valid = NDMP9_VALIDITY_VALID;
180       ent->v3attr.value = strtol(cb->sv[1], 0, 0);
181       continue;
182     }
183 
184     if (strcmp(cb->sv[0], "v4attr") == 0 && cb->sc == 2) {
185       ent->v4attr.valid = NDMP9_VALIDITY_VALID;
186       ent->v4attr.value = strtol(cb->sv[1], 0, 0);
187       continue;
188     }
189 
190     if (strcmp(cb->sv[0], "default_env") == 0 && cb->sc == 3) {
191       cfg_add_env(cb, &ent->default_env.default_env_len,
192                   &ent->default_env.default_env_val, cb->sv[1], cb->sv[2]);
193       continue;
194     }
195 
196     /*
197      * Unrecognized lines are deemed version differences
198      * and tolerated.
199      */
200   }
201 
202   return 0;
203 }
204 
205 /*
206  * [fs MOUNTPOINT]
207  *      fs_type TYPE
208  *      fs_physical_device DEVICEPATH
209  *      fs_status "COMMENT"
210  *      fs_env NAME VALUE
211  */
212 
cfg_fs(struct cfg_cb * cb)213 static int cfg_fs(struct cfg_cb* cb)
214 {
215   ndmp9_config_info* cfg = cb->config_info;
216   ndmp9_fs_info* ent = cfg->fs_info.fs_info_val;
217   int n_ent = cfg->fs_info.fs_info_len;
218   int i, rc;
219 
220   if (!ent) n_ent = 0;
221 
222   ent = NDMOS_MACRO_NEWN(ndmp9_fs_info, n_ent + 1);
223   if (!ent) {
224     cb->n_error++;
225     return -1;
226   }
227 
228   for (i = 0; i < n_ent; i++) { ent[i] = cfg->fs_info.fs_info_val[i]; }
229 
230   if (cfg->fs_info.fs_info_val) { NDMOS_API_FREE(cfg->fs_info.fs_info_val); }
231   cfg->fs_info.fs_info_val = ent;
232   cfg->fs_info.fs_info_len = n_ent + 1;
233   ent += n_ent;
234 
235   NDMOS_MACRO_ZEROFILL(ent);
236 
237   ent->fs_logical_device = NDMOS_API_STRDUP(cb->sv[1]);
238 
239   for (;;) {
240     rc = ndmstz_getline(cb->fp, cb->buf, CFG_BUF_SIZE);
241     if (rc < 0) break;
242 
243     cb->sc = ndmstz_parse(cb->buf, cb->sv, CFG_MAX_SV);
244     if (cb->sc < 1) { continue; }
245 
246     if (strcmp(cb->sv[0], "fs_type") == 0 && cb->sc == 2) {
247       ent->fs_type = NDMOS_API_STRDUP(cb->sv[1]);
248       continue;
249     }
250 
251     if (strcmp(cb->sv[0], "fs_physical_device") == 0 && cb->sc == 2) {
252       ent->fs_physical_device = NDMOS_API_STRDUP(cb->sv[1]);
253       continue;
254     }
255 
256     if (strcmp(cb->sv[0], "fs_status") == 0 && cb->sc == 2) {
257       ent->fs_status = NDMOS_API_STRDUP(cb->sv[1]);
258       continue;
259     }
260 
261     if (strcmp(cb->sv[0], "fs_env") == 0 && cb->sc == 3) {
262       cfg_add_env(cb, &ent->fs_env.fs_env_len, &ent->fs_env.fs_env_val,
263                   cb->sv[1], cb->sv[2]);
264       continue;
265     }
266 
267     /*
268      * Unrecognized lines are deemed version differences
269      * and tolerated.
270      */
271   }
272 
273   return 0;
274 }
275 
cfg_tape(struct cfg_cb * cb)276 static int cfg_tape(struct cfg_cb* cb)
277 {
278   ndmp9_config_info* cfg = cb->config_info;
279 
280   return cfg_device(cb, &cfg->tape_info.tape_info_len,
281                     &cfg->tape_info.tape_info_val);
282 }
283 
cfg_scsi(struct cfg_cb * cb)284 static int cfg_scsi(struct cfg_cb* cb)
285 {
286   ndmp9_config_info* cfg = cb->config_info;
287 
288   return cfg_device(cb, &cfg->scsi_info.scsi_info_len,
289                     &cfg->scsi_info.scsi_info_val);
290 }
291 
292 /*
293  * [tape IDENT]  or  [scsi IDENT]
294  *      device DEVICEPATH
295  *      v3attr 0xATTR
296  *      v4attr 0xATTR
297  *      capability NAME VALUE
298  */
299 
cfg_device(struct cfg_cb * cb,u_int * n_device,ndmp9_device_info ** pp)300 static int cfg_device(struct cfg_cb* cb,
301                       u_int* n_device,
302                       ndmp9_device_info** pp)
303 {
304   ndmp9_device_info* ent = *pp;
305   ndmp9_device_capability* dcap;
306   int rc;
307   unsigned int i, n_ent = *n_device;
308 
309   if (!ent) n_ent = 0;
310 
311   for (i = 0; i < n_ent; i++) {
312     if (strcmp(ent[i].model, (*pp)[i].model) == 0) {
313       ent += i;
314       goto got_model;
315     }
316   }
317 
318   ent = NDMOS_MACRO_NEWN(ndmp9_device_info, n_ent + 1);
319   if (!ent) {
320     cb->n_error++;
321     return -1;
322   }
323 
324   for (i = 0; i < n_ent; i++) { ent[i] = (*pp)[i]; }
325 
326   if (*pp) { NDMOS_API_FREE(*pp); }
327   *pp = ent;
328   *n_device = n_ent + 1;
329   ent += n_ent;
330 
331   NDMOS_MACRO_ZEROFILL(ent);
332   ent->model = NDMOS_API_STRDUP(cb->sv[1]);
333 
334 got_model:
335   dcap =
336       NDMOS_MACRO_NEWN(ndmp9_device_capability, ent->caplist.caplist_len + 1);
337   if (!dcap) {
338     cb->n_error++;
339     return -1;
340   }
341 
342   for (i = 0; i < ent->caplist.caplist_len; i++) {
343     dcap[i] = ent->caplist.caplist_val[i];
344   }
345   if (ent->caplist.caplist_val) { NDMOS_API_FREE(ent->caplist.caplist_val); }
346 
347   ent->caplist.caplist_val = dcap;
348   dcap += ent->caplist.caplist_len++;
349   NDMOS_MACRO_ZEROFILL(dcap);
350 
351   for (;;) {
352     rc = ndmstz_getline(cb->fp, cb->buf, CFG_BUF_SIZE);
353     if (rc < 0) break;
354 
355     cb->sc = ndmstz_parse(cb->buf, cb->sv, CFG_MAX_SV);
356     if (cb->sc < 1) { continue; }
357 
358     if (strcmp(cb->sv[0], "device") == 0 && cb->sc == 2) {
359       dcap->device = NDMOS_API_STRDUP(cb->sv[1]);
360       continue;
361     }
362 
363     if (strcmp(cb->sv[0], "v3attr") == 0 && cb->sc == 2) {
364       dcap->v3attr.valid = NDMP9_VALIDITY_VALID;
365       dcap->v3attr.value = strtol(cb->sv[1], 0, 0);
366       continue;
367     }
368 
369     if (strcmp(cb->sv[0], "v4attr") == 0 && cb->sc == 2) {
370       dcap->v4attr.valid = NDMP9_VALIDITY_VALID;
371       dcap->v4attr.value = strtol(cb->sv[1], 0, 0);
372       continue;
373     }
374 
375     if (strcmp(cb->sv[0], "capability") == 0 && cb->sc == 3) {
376       cfg_add_env(cb, &dcap->capability.capability_len,
377                   &dcap->capability.capability_val, cb->sv[1], cb->sv[2]);
378       continue;
379     }
380 
381     /*
382      * Unrecognized lines are deemed version differences
383      * and tolerated.
384      */
385   }
386 
387   return 0;
388 }
389 
cfg_add_env(struct cfg_cb * cb,u_int * n_env,ndmp9_pval ** pp,char * name,char * value)390 static int cfg_add_env(struct cfg_cb* cb,
391                        u_int* n_env,
392                        ndmp9_pval** pp,
393                        char* name,
394                        char* value)
395 {
396   ndmp9_pval* ent = *pp;
397   int n_ent = *n_env;
398   int i;
399 
400   if (!ent) n_ent = 0;
401 
402   ent = NDMOS_MACRO_NEWN(ndmp9_pval, n_ent + 1);
403   if (!ent) {
404     cb->n_error++;
405     return -1;
406   }
407 
408   for (i = 0; i < n_ent; i++) { ent[i] = (*pp)[i]; }
409 
410   if (*pp) { NDMOS_API_FREE(*pp); }
411 
412   *pp = ent;
413   *n_env = n_ent + 1;
414   ent += n_ent;
415 
416   NDMOS_MACRO_ZEROFILL(ent);
417   ent->name = NDMOS_API_STRDUP(name);
418   ent->value = NDMOS_API_STRDUP(value);
419 
420   return 0;
421 }
422 
423 #ifdef SELF_TEST
424 
main(int argc,char * argv[])425 int main(int argc, char* argv[])
426 {
427   ndmp9_config_info config_info;
428   int rc, i, j, k;
429 
430   if (argc != 2) {
431     printf("usage: %s FILE\n", argv[0]);
432     return 1;
433   }
434 
435   NDMOS_MACRO_ZEROFILL(&config_info);
436 
437   rc = ndmcfg_load(argv[1], &config_info);
438   printf("%d errors\n", rc);
439 
440   for (i = 0; i < config_info.butype_info.butype_info_len; i++) {
441     ndmp9_butype_info* bu;
442 
443     bu = &config_info.butype_info.butype_info_val[i];
444     printf("butype[%d] name='%s'\n", i, bu->butype_name);
445     if (bu->v2attr.valid) {
446       printf("  v2attr 0x%x\n", bu->v2attr.value);
447     } else {
448       printf("  v2attr -invalid-\n");
449     }
450     if (bu->v3attr.valid) {
451       printf("  v3attr 0x%x\n", bu->v3attr.value);
452     } else {
453       printf("  v3attr -invalid-\n");
454     }
455     if (bu->v4attr.valid) {
456       printf("  v4attr 0x%x\n", bu->v4attr.value);
457     } else {
458       printf("  v4attr -invalid-\n");
459     }
460     for (j = 0; j < bu->default_env.default_env_len; j++) {
461       ndmp9_pval* env;
462 
463       env = &bu->default_env.default_env_val[j];
464       printf("  default_env[%d] '%s'='%s'\n", j, env->name, env->value);
465     }
466   }
467 
468   for (i = 0; i < config_info.fs_info.fs_info_len; i++) {
469     ndmp9_fs_info* fs;
470 
471     fs = &config_info.fs_info.fs_info_val[i];
472     printf("fs[%d] fs_logical_device='%s'\n", i, fs->fs_logical_device);
473     if (fs->fs_physical_device) {
474       printf("  fs_physical_device '%s'\n", fs->fs_physical_device);
475     } else {
476       printf("  fs_physical_device -null-\n");
477     }
478     if (fs->fs_type) {
479       printf("  fs_type '%s'\n", fs->fs_type);
480     } else {
481       printf("  fs_type -null-\n");
482     }
483     if (fs->fs_status) {
484       printf("  fs_status '%s'\n", fs->fs_status);
485     } else {
486       printf("  fs_status -null-\n");
487     }
488     if (fs->total_size.valid) {
489       printf("  total_size %llu\n", fs->total_size.value);
490     } else {
491       printf("  total_size -invalid-\n");
492     }
493     if (fs->used_size.valid) {
494       printf("  used_size %llu\n", fs->used_size.value);
495     } else {
496       printf("  used_size -invalid-\n");
497     }
498     if (fs->avail_size.valid) {
499       printf("  avail_size %llu\n", fs->avail_size.value);
500     } else {
501       printf("  avail_size -invalid-\n");
502     }
503     if (fs->total_inodes.valid) {
504       printf("  total_inodes %llu\n", fs->total_inodes.value);
505     } else {
506       printf("  total_inodes -invalid-\n");
507     }
508     if (fs->used_inodes.valid) {
509       printf("  used_inodes %llu\n", fs->used_inodes.value);
510     } else {
511       printf("  used_inodes -invalid-\n");
512     }
513 
514     for (j = 0; j < fs->fs_env.fs_env_len; j++) {
515       ndmp9_pval* env;
516 
517       env = &fs->fs_env.fs_env_val[j];
518       printf("  fs_env[%d] '%s'='%s'\n", j, env->name, env->value);
519     }
520   }
521 
522   for (i = 0; i < config_info.tape_info.tape_info_len; i++) {
523     ndmp9_device_info* dev;
524 
525     dev = &config_info.tape_info.tape_info_val[i];
526     printf("tape[%d] model='%s'\n", i, dev->model);
527 
528     for (j = 0; j < dev->caplist.caplist_len; j++) {
529       struct ndmp9_device_capability* dcap;
530 
531       dcap = &dev->caplist.caplist_val[j];
532       printf(" capability %d\n", j);
533 
534       if (dcap->device) {
535         printf("  device '%s'\n", dcap->device);
536       } else {
537         printf("  device -null-\n");
538       }
539       if (dcap->v3attr.valid) {
540         printf("  v3attr 0x%x\n", dcap->v3attr.value);
541       } else {
542         printf("  v3attr -invalid-\n");
543       }
544       if (dcap->v4attr.valid) {
545         printf("  v4attr 0x%x\n", dcap->v4attr.value);
546       } else {
547         printf("  v4attr -invalid-\n");
548       }
549       k = 0;
550       for (; k < dcap->capability.capability_len; k++) {
551         ndmp9_pval* env;
552         env = &dcap->capability.capability_val[k];
553         printf("  capability[%d] '%s'='%s'\n", k, env->name, env->value);
554       }
555     }
556   }
557 
558   for (i = 0; i < config_info.scsi_info.scsi_info_len; i++) {
559     ndmp9_device_info* dev;
560 
561     dev = &config_info.scsi_info.scsi_info_val[i];
562     printf("scsi[%d] model='%s'\n", i, dev->model);
563 
564     for (j = 0; j < dev->caplist.caplist_len; j++) {
565       struct ndmp9_device_capability* dcap;
566 
567       dcap = &dev->caplist.caplist_val[j];
568       printf(" capability %d\n", j);
569 
570       if (dcap->device) {
571         printf("  device '%s'\n", dcap->device);
572       } else {
573         printf("  device -null-\n");
574       }
575       if (dcap->v3attr.valid) {
576         printf("  v3attr 0x%x\n", dcap->v3attr.value);
577       } else {
578         printf("  v3attr -invalid-\n");
579       }
580       if (dcap->v4attr.valid) {
581         printf("  v4attr 0x%x\n", dcap->v4attr.value);
582       } else {
583         printf("  v4attr -invalid-\n");
584       }
585       k = 0;
586       for (; k < dcap->capability.capability_len; k++) {
587         ndmp9_pval* env;
588         env = &dcap->capability.capability_val[k];
589         printf("  capability[%d] '%s'='%s'\n", k, env->name, env->value);
590       }
591     }
592   }
593 
594 
595   return 0;
596 }
597 
598 #endif /* SELF_TEST */
599