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 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 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 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 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 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 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 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 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 186 info_hdr(FILE *ef, char *info) 187 { 188 fprintf(ef, "# *** NOTE: This file contains %s info\n", info); 189 } 190 191 192 void 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 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 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 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 * 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 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 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 * 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 * 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 * 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 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 * 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 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 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 * 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 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 * 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 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 * 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 640 init_que(qelem *q) 641 { 642 q->q_forw = q->q_back = q; 643 } 644 645 646 qelem * 647 new_que(void) 648 { 649 qelem *q = CALLOC(qelem); 650 651 init_que(q); 652 return q; 653 } 654 655 656 void 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 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