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