]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/amd/fsinfo/fsi_util.c
MFC r308493, r308619: Update amd from am-utils 6.1.5 to 6.2.
[FreeBSD/stable/10.git] / contrib / amd / fsinfo / fsi_util.c
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
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
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
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
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
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
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
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
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
184 info_hdr(FILE *ef, char *info)
185 {
186   fprintf(ef, "# *** NOTE: This file contains %s info\n", info);
187 }
188
189
190 void
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
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
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
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 *
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
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
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 *
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 *
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 *
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
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 *
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
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
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 *
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
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 *
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
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 *
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
638 init_que(qelem *q)
639 {
640   q->q_forw = q->q_back = q;
641 }
642
643
644 qelem *
645 new_que(void)
646 {
647   qelem *q = CALLOC(qelem);
648
649   init_que(q);
650   return q;
651 }
652
653
654 void
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
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 }