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