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 */ 45static int show_range = 10; 46static int col = 0; 47static int total_shown = 0; 48static int total_mmm = 8; 49 50 51static int 52col_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 66static void 67show_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 86void 87col_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 */ 105void 106error(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 120void 121lerror(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 135void 136lwarning(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 149void 150fatal(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 */ 167void 168fsi_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 183void 184info_hdr(FILE *ef, char *info) 185{ 186 fprintf(ef, "# *** NOTE: This file contains %s info\n", info); 187} 188 189 190void 191gen_hdr(FILE *ef, char *hn) 192{ 193 fprintf(ef, "# *** NOTE: Only for use on %s\n", hn); 194} 195 196 197static void 198make_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 213void 214show_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 231void 232show_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 */ 268FILE * 269pref_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 288int 289pref_close(FILE *fp) 290{ 291 return fclose(fp) == 0; 292} 293 294 295/* 296 * Determine where Amd would automount the host/volname pair 297 */ 298void 299compute_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 */ 308automount * 309new_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 323auto_tree * 324new_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 336host * 337new_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 348void 349set_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 423ether_if * 424new_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 435void 436set_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 478void 479set_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 528disk_fs * 529new_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 539void 540set_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 572fsi_mount * 573new_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 583void 584set_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 626fsmount * 627new_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 637void 638init_que(qelem *q) 639{ 640 q->q_forw = q->q_back = q; 641} 642 643 644qelem * 645new_que(void) 646{ 647 qelem *q = CALLOC(qelem); 648 649 init_que(q); 650 return q; 651} 652 653 654void 655ins_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 667void 668rem_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