Home | History | Annotate | Line # | Download | only in fsinfo
      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