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