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