xref: /netbsd-src/external/bsd/am-utils/dist/fsinfo/fsi_util.c (revision 8bae5d409deb915cf7c8f0539fae22ff2cb8a313)
1 /*	$NetBSD: fsi_util.c,v 1.1.1.3 2015/01/17 16:34:17 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 1997-2014 Erez Zadok
5  * Copyright (c) 1989 Jan-Simon Pendry
6  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
7  * Copyright (c) 1989 The Regents of the University of California.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  *
35  * File: am-utils/fsinfo/fsi_util.c
36  *
37  */
38 
39 #ifdef HAVE_CONFIG_H
40 # include <config.h>
41 #endif /* HAVE_CONFIG_H */
42 #include <am_defs.h>
43 #include <fsi_data.h>
44 #include <fsinfo.h>
45 
46 /* static variables */
47 static int show_range = 10;
48 static int col = 0;
49 static int total_shown = 0;
50 static int total_mmm = 8;
51 
52 
53 static int
col_output(int len)54 col_output(int len)
55 {
56   int wrapped = 0;
57 
58   col += len;
59   if (col > 77) {
60     fputc('\n', stdout);
61     col = len;
62     wrapped = 1;
63   }
64   return wrapped;
65 }
66 
67 
68 static void
show_total(void)69 show_total(void)
70 {
71   if (total_mmm != -show_range + 1) {
72     char n[8];
73     int len;
74 
75     if (total_mmm < 0)
76       fputc('*', stdout);
77     xsnprintf(n, sizeof(n), "%d", total_shown);
78     len = strlen(n);
79     if (col_output(len))
80       fputc(' ', stdout);
81     fputs(n, stdout);
82     fflush(stdout);
83     total_mmm = -show_range;
84   }
85 }
86 
87 
88 void
col_cleanup(int eoj)89 col_cleanup(int eoj)
90 {
91   if (verbose < 0)
92     return;
93   if (eoj) {
94     show_total();
95     fputs(")]", stdout);
96   }
97   if (col) {
98     fputc('\n', stdout);
99     col = 0;
100   }
101 }
102 
103 
104 /*
105  * Lots of ways of reporting errors...
106  */
107 void
error(char * fmt,...)108 error(char *fmt, ...)
109 {
110   va_list ap;
111 
112   va_start(ap, fmt);
113   col_cleanup(0);
114   fprintf(stderr, "%s: Error, ", progname);
115   vfprintf(stderr, fmt, ap);
116   fputc('\n', stderr);
117   errors++;
118   va_end(ap);
119 }
120 
121 
122 void
lerror(ioloc * l,char * fmt,...)123 lerror(ioloc *l, char *fmt, ...)
124 {
125   va_list ap;
126 
127   va_start(ap, fmt);
128   col_cleanup(0);
129   fprintf(stderr, "%s:%d: ", l->i_file, l->i_line);
130   vfprintf(stderr, fmt, ap);
131   fputc('\n', stderr);
132   errors++;
133   va_end(ap);
134 }
135 
136 
137 void
lwarning(ioloc * l,char * fmt,...)138 lwarning(ioloc *l, char *fmt, ...)
139 {
140   va_list ap;
141 
142   va_start(ap, fmt);
143   col_cleanup(0);
144   fprintf(stderr, "%s:%d: ", l->i_file, l->i_line);
145   vfprintf(stderr, fmt, ap);
146   fputc('\n', stderr);
147   va_end(ap);
148 }
149 
150 
151 void
fatal(char * fmt,...)152 fatal(char *fmt, ...)
153 {
154   va_list ap;
155 
156   va_start(ap, fmt);
157   col_cleanup(1);
158   fprintf(stderr, "%s: Fatal, ", progname);
159   vfprintf(stderr, fmt, ap);
160   fputc('\n', stderr);
161   va_end(ap);
162   exit(1);
163 }
164 
165 
166 /*
167  * Debug log
168  */
169 void
fsi_log(char * fmt,...)170 fsi_log(char *fmt, ...)
171 {
172   va_list ap;
173 
174   if (verbose > 0) {
175     va_start(ap, fmt);
176     fputc('#', stdout);
177     fprintf(stdout, "%s: ", progname);
178     vfprintf(stdout, fmt, ap);
179     putc('\n', stdout);
180     va_end(ap);
181   }
182 }
183 
184 
185 void
info_hdr(FILE * ef,char * info)186 info_hdr(FILE *ef, char *info)
187 {
188   fprintf(ef, "# *** NOTE: This file contains %s info\n", info);
189 }
190 
191 
192 void
gen_hdr(FILE * ef,char * hn)193 gen_hdr(FILE *ef, char *hn)
194 {
195   fprintf(ef, "# *** NOTE: Only for use on %s\n", hn);
196 }
197 
198 
199 static void
make_banner(FILE * fp)200 make_banner(FILE *fp)
201 {
202   time_t t = time((time_t *) NULL);
203   char *cp = ctime(&t);
204 
205   fprintf(fp,
206 	  "\
207 # *** This file was automatically generated -- DO NOT EDIT HERE ***\n\
208 # \"%s\" run by %s@%s on %s\
209 #\n\
210 ",
211 	  progname, username, hostname, cp);
212 }
213 
214 
215 void
show_new(char * msg)216 show_new(char *msg)
217 {
218   if (verbose < 0)
219     return;
220 
221   total_shown++;
222   if (total_mmm > show_range) {
223     show_total();
224   } else if (total_mmm == 0) {
225     fputc('*', stdout);
226     fflush(stdout);
227     col += 1;
228   }
229   total_mmm++;
230 }
231 
232 
233 void
show_area_being_processed(char * area,int n)234 show_area_being_processed(char *area, int n)
235 {
236   static char *last_area = NULL;
237 
238   if (verbose < 0)
239     return;
240   if (last_area) {
241     if (total_shown)
242       show_total();
243     fputs(")", stdout);
244     col += 1;
245   }
246 
247   if (!last_area || !STREQ(area, last_area)) {
248     if (last_area) {
249       col_cleanup(0);
250       total_shown = 0;
251       total_mmm = show_range + 1;
252     }
253     (void) col_output(strlen(area) + 2);
254     fprintf(stdout, "[%s", area);
255     last_area = area;
256   }
257 
258   fputs(" (", stdout);
259   col += 2;
260   show_range = n;
261   total_mmm = n + 1;
262 
263   fflush(stdout);
264 }
265 
266 
267 /*
268  * Open a file with the given prefix and name
269  */
270 FILE *
pref_open(char * pref,char * hn,void (* hdr)(FILE *,char *),char * arg)271 pref_open(char *pref, char *hn, void (*hdr) (FILE *, char *), char *arg)
272 {
273   char p[MAXPATHLEN];
274   FILE *ef;
275 
276   xsnprintf(p, sizeof(p), "%s%s", pref, hn);
277   fsi_log("Writing %s info for %s to %s", pref, hn, p);
278   ef = fopen(p, "w");
279   if (ef) {
280     (*hdr) (ef, arg);
281     make_banner(ef);
282   } else {
283     error("can't open %s for writing", p);
284   }
285 
286   return ef;
287 }
288 
289 
290 int
pref_close(FILE * fp)291 pref_close(FILE *fp)
292 {
293   return fclose(fp) == 0;
294 }
295 
296 
297 /*
298  * Determine where Amd would automount the host/volname pair
299  */
300 void
compute_automount_point(char * buf,size_t l,host * hp,char * vn)301 compute_automount_point(char *buf, size_t l, host *hp, char *vn)
302 {
303   xsnprintf(buf, l, "%s/%s%s", autodir, hp->h_lochost, vn);
304 }
305 
306 
307 /*
308  * Data constructors..
309  */
310 automount *
new_automount(char * name)311 new_automount(char *name)
312 {
313   automount *ap = CALLOC(struct automount);
314 
315   ap->a_ioloc = current_location();
316   ap->a_name = name;
317   ap->a_volname = NULL;
318   ap->a_mount = NULL;
319   ap->a_opts = NULL;
320   show_new("automount");
321   return ap;
322 }
323 
324 
325 auto_tree *
new_auto_tree(char * def,qelem * ap)326 new_auto_tree(char *def, qelem *ap)
327 {
328   auto_tree *tp = CALLOC(struct auto_tree);
329 
330   tp->t_ioloc = current_location();
331   tp->t_defaults = def;
332   tp->t_mount = ap;
333   show_new("auto_tree");
334   return tp;
335 }
336 
337 
338 host *
new_host(void)339 new_host(void)
340 {
341   host *hp = CALLOC(struct host);
342 
343   hp->h_ioloc = current_location();
344   hp->h_mask = 0;
345   show_new("host");
346   return hp;
347 }
348 
349 
350 void
set_host(host * hp,int k,char * v)351 set_host(host *hp, int k, char *v)
352 {
353   int m = 1 << k;
354 
355   if (hp->h_mask & m) {
356     fsi_error("host field \"%s\" already set", host_strings[k]);
357     return;
358   }
359   hp->h_mask |= m;
360 
361   switch (k) {
362 
363   case HF_HOST:{
364       char *p = xstrdup(v);
365       dict_ent *de = dict_locate(dict_of_hosts, v);
366 
367       if (de)
368 	fsi_error("duplicate host %s!", v);
369       else
370 	dict_add(dict_of_hosts, v, (char *) hp);
371       hp->h_hostname = v;
372       domain_strip(p, hostname);
373       if (strchr(p, '.') != 0)
374 	XFREE(p);
375       else
376 	hp->h_lochost = p;
377     }
378     break;
379 
380   case HF_CONFIG:{
381       qelem *q;
382       qelem *vq = (qelem *) v;
383 
384       hp->h_mask &= ~m;
385       if (hp->h_config)
386 	q = hp->h_config;
387       else
388 	q = hp->h_config = new_que();
389       ins_que(vq, q->q_back);
390     }
391     break;
392 
393   case HF_ETHER:{
394       qelem *q;
395       qelem *vq = (qelem *) v;
396 
397       hp->h_mask &= ~m;
398       if (hp->h_ether)
399 	q = hp->h_ether;
400       else
401 	q = hp->h_ether = new_que();
402       ins_que(vq, q->q_back);
403     }
404     break;
405 
406   case HF_ARCH:
407     hp->h_arch = v;
408     break;
409 
410   case HF_OS:
411     hp->h_os = v;
412     break;
413 
414   case HF_CLUSTER:
415     hp->h_cluster = v;
416     break;
417 
418   default:
419     abort();
420     break;
421   }
422 }
423 
424 
425 ether_if *
new_ether_if(void)426 new_ether_if(void)
427 {
428   ether_if *ep = CALLOC(struct ether_if);
429 
430   ep->e_mask = 0;
431   ep->e_ioloc = current_location();
432   show_new("ether_if");
433   return ep;
434 }
435 
436 
437 void
set_ether_if(ether_if * ep,int k,char * v)438 set_ether_if(ether_if *ep, int k, char *v)
439 {
440   int m = 1 << k;
441 
442   if (ep->e_mask & m) {
443     fsi_error("netif field \"%s\" already set", ether_if_strings[k]);
444     return;
445   }
446   ep->e_mask |= m;
447 
448   switch (k) {
449 
450   case EF_INADDR:{
451       ep->e_inaddr.s_addr = inet_addr(v);
452       if ((int) ep->e_inaddr.s_addr == (int) INADDR_NONE)
453 	fsi_error("malformed IP dotted quad: %s", v);
454       XFREE(v);
455     }
456     break;
457 
458   case EF_NETMASK:{
459       u_long nm = 0;
460 
461       if ((sscanf(v, "0x%lx", &nm) == 1 || sscanf(v, "%lx", &nm) == 1) && nm != 0)
462 	ep->e_netmask = htonl(nm);
463       else
464 	fsi_error("malformed netmask: %s", v);
465       XFREE(v);
466     }
467     break;
468 
469   case EF_HWADDR:
470     ep->e_hwaddr = v;
471     break;
472 
473   default:
474     abort();
475     break;
476   }
477 }
478 
479 
480 void
set_disk_fs(disk_fs * dp,int k,char * v)481 set_disk_fs(disk_fs *dp, int k, char *v)
482 {
483   int m = 1 << k;
484 
485   if (dp->d_mask & m) {
486     fsi_error("fs field \"%s\" already set", disk_fs_strings[k]);
487     return;
488   }
489   dp->d_mask |= m;
490 
491   switch (k) {
492 
493   case DF_FSTYPE:
494     dp->d_fstype = v;
495     break;
496 
497   case DF_OPTS:
498     dp->d_opts = v;
499     break;
500 
501   case DF_DUMPSET:
502     dp->d_dumpset = v;
503     break;
504 
505   case DF_LOG:
506     dp->d_log = v;
507     break;
508 
509   case DF_PASSNO:
510     dp->d_passno = atoi(v);
511     XFREE(v);
512     break;
513 
514   case DF_FREQ:
515     dp->d_freq = atoi(v);
516     XFREE(v);
517     break;
518 
519   case DF_MOUNT:
520     dp->d_mount = &((fsi_mount *) v)->m_q;
521     break;
522 
523   default:
524     abort();
525     break;
526   }
527 }
528 
529 
530 disk_fs *
new_disk_fs(void)531 new_disk_fs(void)
532 {
533   disk_fs *dp = CALLOC(struct disk_fs);
534 
535   dp->d_ioloc = current_location();
536   show_new("disk_fs");
537   return dp;
538 }
539 
540 
541 void
set_mount(fsi_mount * mp,int k,char * v)542 set_mount(fsi_mount *mp, int k, char *v)
543 {
544   int m = 1 << k;
545 
546   if (mp->m_mask & m) {
547     fsi_error("mount tree field \"%s\" already set", mount_strings[k]);
548     return;
549   }
550   mp->m_mask |= m;
551 
552   switch (k) {
553 
554   case DM_VOLNAME:
555     dict_add(dict_of_volnames, v, (char *) mp);
556     mp->m_volname = v;
557     break;
558 
559   case DM_EXPORTFS:
560     mp->m_exportfs = v;
561     break;
562 
563   case DM_SEL:
564     mp->m_sel = v;
565     break;
566 
567   default:
568     abort();
569     break;
570   }
571 }
572 
573 
574 fsi_mount *
new_mount(void)575 new_mount(void)
576 {
577   fsi_mount *fp = CALLOC(struct fsi_mount);
578 
579   fp->m_ioloc = current_location();
580   show_new("mount");
581   return fp;
582 }
583 
584 
585 void
set_fsmount(fsmount * fp,int k,char * v)586 set_fsmount(fsmount *fp, int k, char *v)
587 {
588   int m = 1 << k;
589 
590   if (fp->f_mask & m) {
591     fsi_error("mount field \"%s\" already set", fsmount_strings[k]);
592     return;
593   }
594   fp->f_mask |= m;
595 
596   switch (k) {
597 
598   case FM_LOCALNAME:
599     fp->f_localname = v;
600     break;
601 
602   case FM_VOLNAME:
603     fp->f_volname = v;
604     break;
605 
606   case FM_FSTYPE:
607     fp->f_fstype = v;
608     break;
609 
610   case FM_OPTS:
611     fp->f_opts = v;
612     break;
613 
614   case FM_FROM:
615     fp->f_from = v;
616     break;
617 
618   case FM_DIRECT:
619     break;
620 
621   default:
622     abort();
623     break;
624   }
625 }
626 
627 
628 fsmount *
new_fsmount(void)629 new_fsmount(void)
630 {
631   fsmount *fp = CALLOC(struct fsmount);
632 
633   fp->f_ioloc = current_location();
634   show_new("fsmount");
635   return fp;
636 }
637 
638 
639 void
init_que(qelem * q)640 init_que(qelem *q)
641 {
642   q->q_forw = q->q_back = q;
643 }
644 
645 
646 qelem *
new_que(void)647 new_que(void)
648 {
649   qelem *q = CALLOC(qelem);
650 
651   init_que(q);
652   return q;
653 }
654 
655 
656 void
ins_que(qelem * elem,qelem * pred)657 ins_que(qelem *elem, qelem *pred)
658 {
659   qelem *p;
660 
661   p = pred->q_forw;
662   elem->q_back = pred;
663   elem->q_forw = p;
664   pred->q_forw = elem;
665   p->q_back = elem;
666 }
667 
668 
669 void
rem_que(qelem * elem)670 rem_que(qelem *elem)
671 {
672   qelem *p, *p2;
673 
674   p = elem->q_forw;
675   p2 = elem->q_back;
676 
677   p2->q_forw = p;
678   p->q_back = p2;
679 }
680