summaryrefslogtreecommitdiffstats
path: root/contrib/amd/fsinfo
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>1998-08-23 22:07:21 +0000
committerobrien <obrien@FreeBSD.org>1998-08-23 22:07:21 +0000
commit663d5a0f32ed8dfc091ffb6153161591ac6ba563 (patch)
tree60b090a6cbdb64326bb128ea49a231d08eb2680e /contrib/amd/fsinfo
downloadFreeBSD-src-663d5a0f32ed8dfc091ffb6153161591ac6ba563.zip
FreeBSD-src-663d5a0f32ed8dfc091ffb6153161591ac6ba563.tar.gz
Virgin import of AMD (am-utils) v6.0a16
Diffstat (limited to 'contrib/amd/fsinfo')
-rw-r--r--contrib/amd/fsinfo/fsi_analyze.c670
-rw-r--r--contrib/amd/fsinfo/fsi_data.h236
-rw-r--r--contrib/amd/fsinfo/fsi_dict.c138
-rw-r--r--contrib/amd/fsinfo/fsi_gram.y419
-rw-r--r--contrib/amd/fsinfo/fsi_lex.l270
-rw-r--r--contrib/amd/fsinfo/fsi_util.c693
-rw-r--r--contrib/amd/fsinfo/fsinfo.8101
-rw-r--r--contrib/amd/fsinfo/fsinfo.c293
-rw-r--r--contrib/amd/fsinfo/fsinfo.h131
-rw-r--r--contrib/amd/fsinfo/wr_atab.c334
-rw-r--r--contrib/amd/fsinfo/wr_bparam.c109
-rw-r--r--contrib/amd/fsinfo/wr_dumpset.c96
-rw-r--r--contrib/amd/fsinfo/wr_exportfs.c108
-rw-r--r--contrib/amd/fsinfo/wr_fstab.c342
14 files changed, 3940 insertions, 0 deletions
diff --git a/contrib/amd/fsinfo/fsi_analyze.c b/contrib/amd/fsinfo/fsi_analyze.c
new file mode 100644
index 0000000..de29913
--- /dev/null
+++ b/contrib/amd/fsinfo/fsi_analyze.c
@@ -0,0 +1,670 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: fsi_analyze.c,v 5.2.2.1 1992/02/09 15:09:41 jsp beta $
+ *
+ */
+
+/*
+ * Analyze filesystem declarations
+ *
+ * Note: most of this is magic!
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <fsi_data.h>
+#include <fsinfo.h>
+
+char *disk_fs_strings[] =
+{
+ "fstype", "opts", "dumpset", "passno", "freq", "mount", "log", 0,
+};
+
+char *mount_strings[] =
+{
+ "volname", "exportfs", 0,
+};
+
+char *fsmount_strings[] =
+{
+ "as", "volname", "fstype", "opts", "from", 0,
+};
+
+char *host_strings[] =
+{
+ "host", "netif", "config", "arch", "cluster", "os", 0,
+};
+
+char *ether_if_strings[] =
+{
+ "inaddr", "netmask", "hwaddr", 0,
+};
+
+
+/*
+ * Strip off the trailing part of a domain
+ * to produce a short-form domain relative
+ * to the local host domain.
+ * Note that this has no effect if the domain
+ * names do not have the same number of
+ * components. If that restriction proves
+ * to be a problem then the loop needs recoding
+ * to skip from right to left and do partial
+ * matches along the way -- ie more expensive.
+ */
+void
+domain_strip(char *otherdom, char *localdom)
+{
+ char *p1, *p2;
+
+ if ((p1 = strchr(otherdom, '.')) &&
+ (p2 = strchr(localdom, '.')) &&
+ STREQ(p1 + 1, p2 + 1))
+ *p1 = '\0';
+}
+
+
+/*
+ * Take a little-endian domain name and
+ * transform into a big-endian Un*x pathname.
+ * For example: kiska.doc.ic -> ic/doc/kiska
+ */
+static char *
+compute_hostpath(char *hn)
+{
+ char *p = strdup(hn);
+ char *d;
+ char path[MAXPATHLEN];
+
+ domain_strip(p, hostname);
+ path[0] = '\0';
+
+ do {
+ d = strrchr(p, '.');
+ if (d) {
+ *d = 0;
+ strcat(path, d + 1);
+ strcat(path, "/");
+ } else {
+ strcat(path, p);
+ }
+ } while (d);
+
+ log("hostpath of '%s' is '%s'", hn, path);
+
+ strcpy(p, path);
+ return p;
+}
+
+
+static dict_ent *
+find_volname(char *nn)
+{
+ dict_ent *de;
+ char *p = strdup(nn);
+ char *q;
+
+ do {
+ log("Searching for volname %s", p);
+ de = dict_locate(dict_of_volnames, p);
+ q = strrchr(p, '/');
+ if (q)
+ *q = '\0';
+ } while (!de && q);
+
+ XFREE(p);
+ return de;
+}
+
+
+static void
+show_required(ioloc *l, int mask, char *info, char *hostname, char *strings[])
+{
+ int i;
+ log("mask left for %s:%s is %#x", hostname, info, mask);
+
+ for (i = 0; strings[i]; i++)
+ if (ISSET(mask, i))
+ lerror(l, "%s:%s needs field \"%s\"", hostname, info, strings[i]);
+}
+
+
+/*
+ * Check and fill in "exportfs" details.
+ * Make sure the m_exported field references
+ * the most local node with an "exportfs" entry.
+ */
+static int
+check_exportfs(qelem *q, fsi_mount *e)
+{
+ fsi_mount *mp;
+ int errors = 0;
+
+ ITER(mp, fsi_mount, q) {
+ if (ISSET(mp->m_mask, DM_EXPORTFS)) {
+ if (e)
+ lwarning(mp->m_ioloc, "%s has duplicate exportfs data", mp->m_name);
+ mp->m_exported = mp;
+ if (!ISSET(mp->m_mask, DM_VOLNAME))
+ set_mount(mp, DM_VOLNAME, strdup(mp->m_name));
+ } else {
+ mp->m_exported = e;
+ }
+
+ /*
+ * Recursively descend the mount tree
+ */
+ if (mp->m_mount)
+ errors += check_exportfs(mp->m_mount, mp->m_exported);
+
+ /*
+ * If a volume name has been specified, but this node and none
+ * of its parents has been exported, report an error.
+ */
+ if (ISSET(mp->m_mask, DM_VOLNAME) && !mp->m_exported) {
+ lerror(mp->m_ioloc, "%s has a volname but no exportfs data", mp->m_name);
+ errors++;
+ }
+ }
+
+ return errors;
+}
+
+
+static int
+analyze_dkmount_tree(qelem *q, fsi_mount *parent, disk_fs *dk)
+{
+ fsi_mount *mp;
+ int errors = 0;
+
+ ITER(mp, fsi_mount, q) {
+ log("Mount %s:", mp->m_name);
+ if (parent) {
+ char n[MAXPATHLEN];
+ sprintf(n, "%s/%s", parent->m_name, mp->m_name);
+ if (*mp->m_name == '/')
+ lerror(mp->m_ioloc, "sub-directory %s of %s starts with '/'", mp->m_name, parent->m_name);
+ else if (STREQ(mp->m_name, "default"))
+ lwarning(mp->m_ioloc, "sub-directory of %s is named \"default\"", parent->m_name);
+ log("Changing name %s to %s", mp->m_name, n);
+ XFREE(mp->m_name);
+ mp->m_name = strdup(n);
+ }
+
+ mp->m_name_len = strlen(mp->m_name);
+ mp->m_parent = parent;
+ mp->m_dk = dk;
+ if (mp->m_mount)
+ analyze_dkmount_tree(mp->m_mount, mp, dk);
+ }
+
+ return errors;
+}
+
+
+/*
+ * The mount tree is a singleton list
+ * containing the top-level mount
+ * point for a disk.
+ */
+static int
+analyze_dkmounts(disk_fs *dk, qelem *q)
+{
+ int errors = 0;
+ fsi_mount *mp, *mp2 = 0;
+ int i = 0;
+
+ /*
+ * First scan the list of subdirs to make
+ * sure there is only one - and remember it
+ */
+ if (q) {
+ ITER(mp, fsi_mount, q) {
+ mp2 = mp;
+ i++;
+ }
+ }
+
+ /*
+ * Check...
+ */
+ if (i < 1) {
+ lerror(dk->d_ioloc, "%s:%s has no mount point", dk->d_host->h_hostname, dk->d_dev);
+ return 1;
+ }
+
+ if (i > 1) {
+ lerror(dk->d_ioloc, "%s:%s has more than one mount point", dk->d_host->h_hostname, dk->d_dev);
+ errors++;
+ }
+
+ /*
+ * Now see if a default mount point is required
+ */
+ if (STREQ(mp2->m_name, "default")) {
+ if (ISSET(mp2->m_mask, DM_VOLNAME)) {
+ char nbuf[1024];
+ compute_automount_point(nbuf, dk->d_host, mp2->m_volname);
+ XFREE(mp2->m_name);
+ mp2->m_name = strdup(nbuf);
+ log("%s:%s has default mount on %s", dk->d_host->h_hostname, dk->d_dev, mp2->m_name);
+ } else {
+ lerror(dk->d_ioloc, "no volname given for %s:%s", dk->d_host->h_hostname, dk->d_dev);
+ errors++;
+ }
+ }
+
+ /*
+ * Fill in the disk mount point
+ */
+ if (!errors && mp2 && mp2->m_name)
+ dk->d_mountpt = strdup(mp2->m_name);
+ else
+ dk->d_mountpt = strdup("error");
+
+ /*
+ * Analyze the mount tree
+ */
+ errors += analyze_dkmount_tree(q, 0, dk);
+
+ /*
+ * Analyze the export tree
+ */
+ errors += check_exportfs(q, 0);
+
+ return errors;
+}
+
+
+static void
+fixup_required_disk_info(disk_fs *dp)
+{
+ /*
+ * "fstype"
+ */
+ if (ISSET(dp->d_mask, DF_FSTYPE)) {
+ if (STREQ(dp->d_fstype, "swap")) {
+
+ /*
+ * Fixup for a swap device
+ */
+ if (!ISSET(dp->d_mask, DF_PASSNO)) {
+ dp->d_passno = 0;
+ BITSET(dp->d_mask, DF_PASSNO);
+ } else if (dp->d_freq != 0) {
+ lwarning(dp->d_ioloc,
+ "Pass number for %s:%s is non-zero",
+ dp->d_host->h_hostname, dp->d_dev);
+ }
+
+ /*
+ * "freq"
+ */
+ if (!ISSET(dp->d_mask, DF_FREQ)) {
+ dp->d_freq = 0;
+ BITSET(dp->d_mask, DF_FREQ);
+ } else if (dp->d_freq != 0) {
+ lwarning(dp->d_ioloc,
+ "dump frequency for %s:%s is non-zero",
+ dp->d_host->h_hostname, dp->d_dev);
+ }
+
+ /*
+ * "opts"
+ */
+ if (!ISSET(dp->d_mask, DF_OPTS))
+ set_disk_fs(dp, DF_OPTS, strdup("swap"));
+
+ /*
+ * "mount"
+ */
+ if (!ISSET(dp->d_mask, DF_MOUNT)) {
+ qelem *q = new_que();
+ fsi_mount *m = new_mount();
+
+ m->m_name = strdup("swap");
+ m->m_mount = new_que();
+ ins_que(&m->m_q, q->q_back);
+ dp->d_mount = q;
+ BITSET(dp->d_mask, DF_MOUNT);
+ } else {
+ lerror(dp->d_ioloc, "%s: mount field specified for swap partition", dp->d_host->h_hostname);
+ }
+ } else if (STREQ(dp->d_fstype, "export")) {
+
+ /*
+ * "passno"
+ */
+ if (!ISSET(dp->d_mask, DF_PASSNO)) {
+ dp->d_passno = 0;
+ BITSET(dp->d_mask, DF_PASSNO);
+ } else if (dp->d_passno != 0) {
+ lwarning(dp->d_ioloc,
+ "pass number for %s:%s is non-zero",
+ dp->d_host->h_hostname, dp->d_dev);
+ }
+
+ /*
+ * "freq"
+ */
+ if (!ISSET(dp->d_mask, DF_FREQ)) {
+ dp->d_freq = 0;
+ BITSET(dp->d_mask, DF_FREQ);
+ } else if (dp->d_freq != 0) {
+ lwarning(dp->d_ioloc,
+ "dump frequency for %s:%s is non-zero",
+ dp->d_host->h_hostname, dp->d_dev);
+ }
+
+ /*
+ * "opts"
+ */
+ if (!ISSET(dp->d_mask, DF_OPTS))
+ set_disk_fs(dp, DF_OPTS, strdup("rw,defaults"));
+
+ }
+ }
+}
+
+
+static void
+fixup_required_mount_info(fsmount *fp, dict_ent *de)
+{
+ if (!ISSET(fp->f_mask, FM_FROM)) {
+ if (de->de_count != 1) {
+ lerror(fp->f_ioloc, "ambiguous mount: %s is a replicated filesystem", fp->f_volname);
+ } else {
+ dict_data *dd;
+ fsi_mount *mp = 0;
+ dd = AM_FIRST(dict_data, &de->de_q);
+ mp = (fsi_mount *) dd->dd_data;
+ if (!mp)
+ abort();
+ fp->f_ref = mp;
+ set_fsmount(fp, FM_FROM, mp->m_dk->d_host->h_hostname);
+ log("set: %s comes from %s", fp->f_volname, fp->f_from);
+ }
+ }
+
+ if (!ISSET(fp->f_mask, FM_FSTYPE)) {
+ set_fsmount(fp, FM_FSTYPE, strdup("nfs"));
+ log("set: fstype is %s", fp->f_fstype);
+ }
+
+ if (!ISSET(fp->f_mask, FM_OPTS)) {
+ set_fsmount(fp, FM_OPTS, strdup("rw,nosuid,grpid,defaults"));
+ log("set: opts are %s", fp->f_opts);
+ }
+
+ if (!ISSET(fp->f_mask, FM_LOCALNAME)) {
+ if (fp->f_ref) {
+ set_fsmount(fp, FM_LOCALNAME, strdup(fp->f_volname));
+ log("set: localname is %s", fp->f_localname);
+ } else {
+ lerror(fp->f_ioloc, "cannot determine localname since volname %s is not uniquely defined", fp->f_volname);
+ }
+ }
+}
+
+
+/*
+ * For each disk on a host
+ * analyze the mount information
+ * and fill in any derivable
+ * details.
+ */
+static void
+analyze_drives(host *hp)
+{
+ qelem *q = hp->h_disk_fs;
+ disk_fs *dp;
+
+ ITER(dp, disk_fs, q) {
+ int req;
+ log("Disk %s:", dp->d_dev);
+ dp->d_host = hp;
+ fixup_required_disk_info(dp);
+ req = ~dp->d_mask & DF_REQUIRED;
+ if (req)
+ show_required(dp->d_ioloc, req, dp->d_dev, hp->h_hostname, disk_fs_strings);
+ analyze_dkmounts(dp, dp->d_mount);
+ }
+}
+
+
+/*
+ * Check that all static mounts make sense and
+ * that the source volumes exist.
+ */
+static void
+analyze_mounts(host *hp)
+{
+ qelem *q = hp->h_mount;
+ fsmount *fp;
+ int netbootp = 0;
+
+ ITER(fp, fsmount, q) {
+ char *p;
+ char *nn = strdup(fp->f_volname);
+ int req;
+ dict_ent *de = (dict_ent *) NULL;
+ int found = 0;
+ int matched = 0;
+
+ if (ISSET(fp->f_mask, FM_DIRECT)) {
+ found = 1;
+ matched = 1;
+ } else
+ do {
+ p = 0;
+ de = find_volname(nn);
+ log("Mount: %s (trying %s)", fp->f_volname, nn);
+
+ if (de) {
+ found = 1;
+
+ /*
+ * Check that the from field is really exporting
+ * the filesystem requested.
+ * LBL: If fake mount, then don't care about
+ * consistency check.
+ */
+ if (ISSET(fp->f_mask, FM_FROM) && !ISSET(fp->f_mask, FM_DIRECT)) {
+ dict_data *dd;
+ fsi_mount *mp2 = 0;
+
+ ITER(dd, dict_data, &de->de_q) {
+ fsi_mount *mp = (fsi_mount *) dd->dd_data;
+
+ if (STREQ(mp->m_dk->d_host->h_hostname, fp->f_from)) {
+ mp2 = mp;
+ break;
+ }
+ }
+
+ if (mp2) {
+ fp->f_ref = mp2;
+ matched = 1;
+ break;
+ }
+ } else {
+ matched = 1;
+ break;
+ }
+ }
+ p = strrchr(nn, '/');
+ if (p)
+ *p = 0;
+ } while (de && p);
+ XFREE(nn);
+
+ if (!found) {
+ lerror(fp->f_ioloc, "volname %s unknown", fp->f_volname);
+ } else if (matched) {
+
+ fixup_required_mount_info(fp, de);
+ req = ~fp->f_mask & FM_REQUIRED;
+ if (req) {
+ show_required(fp->f_ioloc, req, fp->f_volname, hp->h_hostname,
+ fsmount_strings);
+ } else if (STREQ(fp->f_localname, "/")) {
+ hp->h_netroot = fp;
+ netbootp |= FM_NETROOT;
+ } else if (STREQ(fp->f_localname, "swap")) {
+ hp->h_netswap = fp;
+ netbootp |= FM_NETSWAP;
+ }
+
+ } else {
+ lerror(fp->f_ioloc, "volname %s not exported from %s", fp->f_volname,
+ fp->f_from ? fp->f_from : "anywhere");
+ }
+ }
+
+ if (netbootp && (netbootp != FM_NETBOOT))
+ lerror(hp->h_ioloc, "network booting requires both root and swap areas");
+}
+
+
+void
+analyze_hosts(qelem *q)
+{
+ host *hp;
+
+ show_area_being_processed("analyze hosts", 5);
+
+ /*
+ * Check all drives
+ */
+ ITER(hp, host, q) {
+ log("disks on host %s", hp->h_hostname);
+ show_new("ana-host");
+ hp->h_hostpath = compute_hostpath(hp->h_hostname);
+
+ if (hp->h_disk_fs)
+ analyze_drives(hp);
+
+ }
+
+ show_area_being_processed("analyze mounts", 5);
+
+ /*
+ * Check static mounts
+ */
+ ITER(hp, host, q) {
+ log("mounts on host %s", hp->h_hostname);
+ show_new("ana-mount");
+ if (hp->h_mount)
+ analyze_mounts(hp);
+
+ }
+}
+
+
+/*
+ * Check an automount request
+ */
+static void
+analyze_automount(automount *ap)
+{
+ dict_ent *de = find_volname(ap->a_volname);
+
+ if (de) {
+ ap->a_mounted = de;
+ } else {
+ if (STREQ(ap->a_volname, ap->a_name))
+ lerror(ap->a_ioloc, "unknown volname %s automounted", ap->a_volname);
+ else
+ lerror(ap->a_ioloc, "unknown volname %s automounted on %s", ap->a_volname, ap->a_name);
+ }
+}
+
+
+static void
+analyze_automount_tree(qelem *q, char *pref, int lvl)
+{
+ automount *ap;
+
+ ITER(ap, automount, q) {
+ char nname[1024];
+
+ if (lvl > 0 || ap->a_mount)
+ if (ap->a_name[1] && strchr(ap->a_name + 1, '/'))
+ lerror(ap->a_ioloc, "not allowed '/' in a directory name");
+ sprintf(nname, "%s/%s", pref, ap->a_name);
+ XFREE(ap->a_name);
+ ap->a_name = strdup(nname[1] == '/' ? nname + 1 : nname);
+ log("automount point %s:", ap->a_name);
+ show_new("ana-automount");
+
+ if (ap->a_mount) {
+ analyze_automount_tree(ap->a_mount, ap->a_name, lvl + 1);
+ } else if (ap->a_hardwiredfs) {
+ log("\thardwired from %s to %s", ap->a_volname, ap->a_hardwiredfs);
+ } else if (ap->a_volname) {
+ log("\tautomount from %s", ap->a_volname);
+ analyze_automount(ap);
+ } else if (ap->a_symlink) {
+ log("\tsymlink to %s", ap->a_symlink);
+ } else {
+ ap->a_volname = strdup(ap->a_name);
+ log("\timplicit automount from %s", ap->a_volname);
+ analyze_automount(ap);
+ }
+ }
+}
+
+
+void
+analyze_automounts(qelem *q)
+{
+ auto_tree *tp;
+
+ show_area_being_processed("analyze automount", 5);
+
+ /*
+ * q is a list of automounts
+ */
+ ITER(tp, auto_tree, q)
+ analyze_automount_tree(tp->t_mount, "", 0);
+}
diff --git a/contrib/amd/fsinfo/fsi_data.h b/contrib/amd/fsinfo/fsi_data.h
new file mode 100644
index 0000000..07b7b9e
--- /dev/null
+++ b/contrib/amd/fsinfo/fsi_data.h
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: fsi_data.h,v 5.2.2.1 1992/02/09 15:09:53 jsp beta $
+ *
+ */
+
+typedef struct auto_tree auto_tree;
+typedef struct automount automount;
+typedef struct dict dict;
+typedef struct dict_data dict_data;
+typedef struct dict_ent dict_ent;
+typedef struct disk_fs disk_fs;
+typedef struct ether_if ether_if;
+typedef struct fsmount fsmount;
+typedef struct host host;
+typedef struct ioloc ioloc;
+typedef struct fsi_mount fsi_mount;
+
+
+/*
+ * Automount tree
+ */
+struct automount {
+ qelem a_q;
+ ioloc *a_ioloc;
+ char *a_name; /* Automount key */
+ char *a_volname; /* Equivalent volume to be referenced */
+ char *a_symlink; /* Symlink representation */
+ char *a_opts; /* opts for mounting */
+ char *a_hardwiredfs; /* hack to bypass bogus fs definitions */
+ qelem *a_mount; /* Tree representation */
+ dict_ent *a_mounted;
+};
+
+/*
+ * List of automount trees
+ */
+struct auto_tree {
+ qelem t_q;
+ ioloc *t_ioloc;
+ char *t_defaults;
+ qelem *t_mount;
+};
+
+/*
+ * A host
+ */
+struct host {
+ qelem q;
+ int h_mask;
+ ioloc *h_ioloc;
+ fsmount *h_netroot, *h_netswap;
+#define HF_HOST 0
+ char *h_hostname; /* The full name of the host */
+ char *h_lochost; /* The name of the host with local domains *
+ * * * stripped */
+ char *h_hostpath; /* The filesystem path to the host (cf * * *
+ * compute_hostpath) */
+#define HF_ETHER 1
+ qelem *h_ether;
+#define HF_CONFIG 2
+ qelem *h_config;
+#define HF_ARCH 3
+ char *h_arch;
+#define HF_CLUSTER 4
+ char *h_cluster;
+#define HF_OS 5
+ char *h_os;
+ qelem *h_disk_fs;
+ qelem *h_mount;
+};
+
+/*
+ * An ethernet interface
+ */
+struct ether_if {
+ qelem e_q;
+ int e_mask;
+ ioloc *e_ioloc;
+ char *e_if;
+#define EF_INADDR 0
+ struct in_addr e_inaddr;
+#define EF_NETMASK 1
+ u_long e_netmask;
+#define EF_HWADDR 2
+ char *e_hwaddr;
+};
+
+/*
+ * Disk filesystem structure.
+ *
+ * If the DF_* numbers are changed
+ * disk_fs_strings in analyze.c will
+ * need updating.
+ */
+struct disk_fs {
+ qelem d_q;
+ int d_mask;
+ ioloc *d_ioloc;
+ host *d_host;
+ char *d_mountpt;
+ char *d_dev;
+#define DF_FSTYPE 0
+ char *d_fstype;
+#define DF_OPTS 1
+ char *d_opts;
+#define DF_DUMPSET 2
+ char *d_dumpset;
+#define DF_PASSNO 3
+ int d_passno;
+#define DF_FREQ 4
+ int d_freq;
+#define DF_MOUNT 5
+ qelem *d_mount;
+#define DF_LOG 6
+ char *d_log;
+};
+
+#define DF_REQUIRED ((1<<DF_FSTYPE)|(1<<DF_OPTS)|(1<<DF_PASSNO)|(1<<DF_MOUNT))
+
+/*
+ * A mount tree
+ */
+struct fsi_mount {
+ qelem m_q;
+ ioloc *m_ioloc;
+ int m_mask;
+#define DM_VOLNAME 0
+ char *m_volname;
+#define DM_EXPORTFS 1
+ char *m_exportfs;
+#define DM_SEL 2
+ char *m_sel;
+ char *m_name;
+ int m_name_len;
+ fsi_mount *m_parent;
+ disk_fs *m_dk;
+ fsi_mount *m_exported;
+ qelem *m_mount;
+};
+
+/*
+ * Additional filesystem mounts
+ *
+ * If the FM_* numbers are changed
+ * disk_fs_strings in analyze.c will
+ * need updating.
+ */
+struct fsmount {
+ qelem f_q;
+ fsi_mount *f_ref;
+ ioloc *f_ioloc;
+ int f_mask;
+#define FM_LOCALNAME 0
+ char *f_localname;
+#define FM_VOLNAME 1
+ char *f_volname;
+#define FM_FSTYPE 2
+ char *f_fstype;
+#define FM_OPTS 3
+ char *f_opts;
+#define FM_FROM 4
+ char *f_from;
+#define FM_DIRECT 5
+};
+
+#define FM_REQUIRED ((1<<FM_VOLNAME)|(1<<FM_FSTYPE)|(1<<FM_OPTS)|(1<<FM_FROM)|(1<<FM_LOCALNAME))
+#define FM_NETROOT 0x01
+#define FM_NETSWAP 0x02
+#define FM_NETBOOT (FM_NETROOT|FM_NETSWAP)
+
+#define DICTHASH 5
+struct dict_ent {
+ dict_ent *de_next;
+ char *de_key;
+ int de_count;
+ qelem de_q;
+};
+
+/*
+ * Dictionaries ...
+ */
+struct dict_data {
+ qelem dd_q;
+ char *dd_data;
+};
+
+struct dict {
+ dict_ent *de[DICTHASH];
+};
+
+/*
+ * Source text location for error reports
+ */
+struct ioloc {
+ int i_line;
+ char *i_file;
+};
diff --git a/contrib/amd/fsinfo/fsi_dict.c b/contrib/amd/fsinfo/fsi_dict.c
new file mode 100644
index 0000000..f9e686a
--- /dev/null
+++ b/contrib/amd/fsinfo/fsi_dict.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: fsi_dict.c,v 5.2.2.1 1992/02/09 15:09:43 jsp beta $
+ *
+ */
+
+/*
+ * Dictionary support
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <fsi_data.h>
+#include <fsinfo.h>
+
+
+static int
+dict_hash(char *k)
+{
+ u_int h;
+
+ for (h = 0; *k; h += *k++) ;
+ return h % DICTHASH;
+}
+
+
+dict *
+new_dict(void)
+{
+ dict *dp = CALLOC(struct dict);
+
+ return dp;
+}
+
+
+static void
+dict_add_data(dict_ent *de, char *v)
+{
+ dict_data *dd = CALLOC(struct dict_data);
+
+ dd->dd_data = v;
+ ins_que(&dd->dd_q, de->de_q.q_back);
+ de->de_count++;
+}
+
+
+static dict_ent *
+new_dict_ent(char *k)
+{
+ dict_ent *de = CALLOC(struct dict_ent);
+
+ de->de_key = k;
+ init_que(&de->de_q);
+ return de;
+}
+
+
+dict_ent *
+dict_locate(dict *dp, char *k)
+{
+ dict_ent *de = dp->de[dict_hash(k)];
+
+ while (de && !STREQ(de->de_key, k))
+ de = de->de_next;
+ return de;
+}
+
+
+void
+dict_add(dict *dp, char *k, char *v)
+{
+ dict_ent *de = dict_locate(dp, k);
+
+ if (!de) {
+ dict_ent **dep = &dp->de[dict_hash(k)];
+ de = new_dict_ent(k);
+ de->de_next = *dep;
+ *dep = de;
+ }
+ dict_add_data(de, v);
+}
+
+
+int
+dict_iter(dict *dp, int (*fn) (qelem *))
+{
+ int i;
+ int errors = 0;
+
+ for (i = 0; i < DICTHASH; i++) {
+ dict_ent *de = dp->de[i];
+ while (de) {
+ errors += (*fn) (&de->de_q);
+ de = de->de_next;
+ }
+ }
+ return errors;
+}
diff --git a/contrib/amd/fsinfo/fsi_gram.y b/contrib/amd/fsinfo/fsi_gram.y
new file mode 100644
index 0000000..b325c77
--- /dev/null
+++ b/contrib/amd/fsinfo/fsi_gram.y
@@ -0,0 +1,419 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: fsi_gram.y,v 5.2.2.1 1992/02/09 15:09:35 jsp beta $
+ *
+ */
+
+%{
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <fsi_data.h>
+#include <fsinfo.h>
+
+extern qelem *list_of_hosts, *list_of_automounts;
+%}
+
+%union {
+ auto_tree *a;
+ disk_fs *d;
+ ether_if *e;
+ host *h;
+ qelem *q;
+ char *s;
+ fsi_mount *m;
+ fsmount *f;
+}
+
+%token tARCH
+%token tAS
+%token tAUTOMOUNT
+%token tCLUSTER
+%token tCONFIG
+%token tDUMPSET
+%token tEQ
+%token tNFSEQ
+%token tEXPORTFS
+%token tFREQ
+%token tFROM
+%token tFS
+%token tFSTYPE
+%token tHWADDR
+%token tINADDR
+%token tHOST
+%token tLOCALHOST
+%token tLOG
+%token tMOUNT
+%token tNETMASK
+%token tNETIF
+%token tVOLNAME
+%token tOPTS
+%token tOS
+%token tPASSNO
+%token tDIRECT
+%token tSEL
+%token <s> tSTR
+
+%start list_of_hosts
+
+%type <a> automount
+%type <q> automount_tree
+%type <e> ether_attr
+%type <m> dir_tree_info
+%type <d> filesystem fs_info_list
+%type <h> host host_attr host_attr_list
+%type <q> list_of_hosts list_of_filesystems list_of_mounts dir_tree
+%type <f> localinfo_list
+%type <s> opt_auto_opts
+
+%%
+
+list_of_hosts :
+ /* empty */
+ { $$ = new_que(); }
+
+ | list_of_hosts host
+ { if ($2) ins_que((qelem *) $2, list_of_hosts->q_back);
+ $$ = $1; }
+
+ | list_of_hosts automount
+ { if ($2) ins_que((qelem *) $2, list_of_automounts->q_back);
+ $$ = $1; }
+ ;
+
+/*
+ * A new host:
+ *
+ * host foo.domain
+ */
+host :
+ tHOST host_attr list_of_filesystems list_of_mounts
+ { $$ = $2; $$->h_disk_fs = $3; $$->h_mount = $4; }
+
+ | error tHOST host_attr list_of_filesystems list_of_mounts
+ { $$ = $3; $$->h_disk_fs = $4; $$->h_mount = $5; }
+
+ ;
+
+host_attr :
+ tSTR
+ { $$ = new_host(); set_host($$, HF_HOST, $1); }
+
+ | '{' host_attr_list '}' tSTR
+ { $$ = $2; set_host($$, HF_HOST, $4); }
+
+ ;
+
+host_attr_list :
+ /* empty */
+ { $$ = new_host(); }
+
+ | host_attr_list tNETIF tSTR '{' ether_attr '}'
+ { if ($5) {
+ $5->e_if = $3;
+ $$ = $1; set_host($$, HF_ETHER, (char *) $5); }
+ }
+
+ | host_attr_list tCONFIG tSTR
+ { $$ = $1; set_host($$, HF_CONFIG, $3); }
+
+ | host_attr_list tARCH '=' tSTR
+ { $$ = $1; set_host($$, HF_ARCH, $4); }
+
+ | host_attr_list tOS '=' tSTR
+ { $$ = $1; set_host($$, HF_OS, $4); }
+
+ | host_attr_list tCLUSTER '=' tSTR
+ { $$ = $1; set_host($$, HF_CLUSTER, $4); }
+
+ | host_attr_list error '=' tSTR
+ { yyerror("unknown host attribute"); }
+ ;
+
+ether_attr :
+ /* empty */
+ { $$ = new_ether_if(); }
+
+ | ether_attr tINADDR '=' tSTR
+ { $$ = $1; set_ether_if($$, EF_INADDR, $4); }
+ | ether_attr tNETMASK '=' tSTR
+ { $$ = $1; set_ether_if($$, EF_NETMASK, $4); }
+ | ether_attr tHWADDR '=' tSTR
+ { $$ = $1; set_ether_if($$, EF_HWADDR, $4); }
+ ;
+
+/*
+ * A new automount tree:
+ *
+ * automount /mountpoint { ... }
+ */
+automount :
+ tAUTOMOUNT opt_auto_opts automount_tree
+ { if ($3) {
+ $$ = new_auto_tree($2, $3);
+ } else {
+ $$ = 0;
+ }
+ }
+
+ | tAUTOMOUNT error
+ { $$ = 0; }
+ ;
+
+opt_auto_opts :
+ /* empty */
+ { $$ = strdup(""); }
+
+ | tOPTS tSTR
+ { $$ = $2; }
+ ;
+
+list_of_filesystems :
+ /* empty */
+ { $$ = 0; }
+
+ | list_of_filesystems filesystem
+ { if ($2) {
+ if ($1)
+ $$ = $1;
+ else
+ $$ = new_que();
+ ins_que(&$2->d_q, $$->q_back);
+ } else {
+ $$ = $1;
+ }
+ }
+ ;
+
+/*
+ * A new filesystem:
+ *
+ * fs /dev/whatever { ... }
+ */
+filesystem :
+ tFS tSTR '{' fs_info_list '}'
+ { $4->d_dev = $2; $$ = $4; }
+
+ | tFS error '}'
+ { $$ = (disk_fs *) 0; }
+ ;
+
+/*
+ * Per-filesystem information:
+ *
+ * fstype - the type of the filesystem (4.2, nfs, swap, export)
+ * opts - the mount options ("rw,grpid")
+ * passno - fsck pass number
+ * freq - dump frequency
+ * dumpset - tape set for filesystem dumps
+ * mount - where to mount this filesystem
+ * log - log device
+ */
+fs_info_list :
+ /* empty */
+ { $$ = new_disk_fs(); }
+
+ | fs_info_list tFSTYPE '=' tSTR
+ { $$ = $1; set_disk_fs($$, DF_FSTYPE, $4); }
+
+ | fs_info_list tOPTS '=' tSTR
+ { $$ = $1; set_disk_fs($$, DF_OPTS, $4); }
+
+ | fs_info_list tPASSNO '=' tSTR
+ { $$ = $1; set_disk_fs($$, DF_PASSNO, $4); }
+
+ | fs_info_list tFREQ '=' tSTR
+ { $$ = $1; set_disk_fs($$, DF_FREQ, $4); }
+
+ | fs_info_list tMOUNT dir_tree
+ { $$ = $1; set_disk_fs($$, DF_MOUNT, (char *) $3); }
+
+ | fs_info_list tDUMPSET '=' tSTR
+ { $$ = $1; set_disk_fs($$, DF_DUMPSET, $4); }
+
+ | fs_info_list tLOG '=' tSTR
+ { $$ = $1; set_disk_fs($$, DF_LOG, $4); }
+
+ | fs_info_list error '=' tSTR
+ { yyerror("unknown filesystem attribute"); }
+ ;
+
+/*
+ * An automount tree:
+ *
+ * name = "volname" name is a reference to volname
+ * name -> "string" name is a link to "string"
+ * name nfsalias "string" name is a link to "string", string parsed as NFS
+ * pathname.
+ * name { ... } name is an automount tree
+ */
+automount_tree :
+ /* empty */
+ { $$ = 0; }
+
+ | automount_tree tSTR opt_auto_opts '=' tSTR
+ { automount *a = new_automount($2);
+ a->a_volname = $5;
+ a->a_opts = $3;
+ if ($1)
+ $$ = $1;
+ else
+ $$ = new_que();
+ ins_que(&a->a_q, $$->q_back);
+ }
+ | automount_tree tSTR opt_auto_opts tNFSEQ tSTR
+ { automount *a = new_automount($2);
+ a->a_hardwiredfs = $5;
+ a->a_opts = $3;
+ if ($1)
+ $$ = $1;
+ else
+ $$ = new_que();
+ ins_que(&a->a_q, $$->q_back);
+ }
+
+ | automount_tree tSTR tEQ tSTR
+ { automount *a = new_automount($2);
+ a->a_symlink = $4;
+ if ($1)
+ $$ = $1;
+ else
+ $$ = new_que();
+ ins_que(&a->a_q, $$->q_back);
+ }
+
+ | automount_tree tSTR opt_auto_opts '{' automount_tree '}'
+ { automount *a = new_automount($2);
+ a->a_mount = $5;
+ a->a_opts = $3;
+ if ($1)
+ $$ = $1;
+ else
+ $$ = new_que();
+ ins_que(&a->a_q, $$->q_back);
+ }
+ ;
+
+dir_tree :
+ /* empty */
+ { $$ = 0; }
+
+ | dir_tree tSTR '{' dir_tree_info dir_tree '}'
+ { $4->m_mount = $5;
+ $4->m_name = $2;
+ if ($2[0] != '/' && $2[1] && strchr($2+1, '/'))
+ yyerror("not allowed '/' in a directory name");
+ if ($1)
+ $$ = $1;
+ else
+ $$ = new_que();
+ ins_que(&$4->m_q, $$->q_back);
+ }
+ ;
+
+dir_tree_info :
+ /* empty */
+ { $$ = new_mount(); }
+
+ | dir_tree_info tEXPORTFS tSTR
+ { $$ = $1; set_mount($$, DM_EXPORTFS, $3); }
+
+ | dir_tree_info tVOLNAME tSTR
+ { $$ = $1; set_mount($$, DM_VOLNAME, $3); }
+
+ | dir_tree_info tSEL tSTR
+ { $$ = $1; set_mount($$, DM_SEL, $3); }
+
+ | dir_tree_info error '=' tSTR
+ { yyerror("unknown directory attribute"); }
+ ;
+
+/*
+ * Additional mounts on a host
+ *
+ * mount "volname" ...
+ */
+list_of_mounts :
+ /* empty */
+ { $$ = 0; }
+
+ | list_of_mounts tMOUNT tSTR localinfo_list
+ { set_fsmount($4, FM_VOLNAME, $3);
+ if ($1)
+ $$ = $1;
+ else
+ $$ = new_que();
+ ins_que(&$4->f_q, $$->q_back);
+ }
+ ;
+
+/*
+ * Mount info:
+ *
+ * from "hostname" - obtain the object from the named host
+ * as "string" - where to mount, if different from the volname
+ * opts "string" - mount options
+ * fstype "type" - type of filesystem mount, if not nfs
+ * direct - mount entry, no need to create ad-hoc hosts file
+ */
+localinfo_list :
+ /* empty */
+ { $$ = new_fsmount(); }
+
+ | localinfo_list tDIRECT
+ { $$ = $1; set_fsmount($$, FM_DIRECT, ""); }
+
+ | localinfo_list tAS tSTR
+ { $$ = $1; set_fsmount($$, FM_LOCALNAME, $3); }
+
+ | localinfo_list tFROM tSTR
+ { $$ = $1; set_fsmount($$, FM_FROM, $3); }
+
+ | localinfo_list tFSTYPE tSTR
+ { $$ = $1; set_fsmount($$, FM_FSTYPE, $3); }
+
+ | localinfo_list tOPTS tSTR
+ { $$ = $1; set_fsmount($$, FM_OPTS, $3); }
+
+ | localinfo_list error '=' tSTR
+ { yyerror("unknown mount attribute"); }
+ ;
diff --git a/contrib/amd/fsinfo/fsi_lex.l b/contrib/amd/fsinfo/fsi_lex.l
new file mode 100644
index 0000000..98b1976
--- /dev/null
+++ b/contrib/amd/fsinfo/fsi_lex.l
@@ -0,0 +1,270 @@
+%{
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: fsi_lex.l,v 5.2.2.1 1992/02/09 15:09:36 jsp beta $
+ *
+ */
+
+/*
+ * Lexical analyzer for fsinfo.
+ * TODO: Needs rewriting.
+ */
+
+#ifdef FLEX_SCANNER
+static int yylineno;
+# define INIT_STATE { \
+ switch ((yy_start - 1) / 2) { \
+ case 0: \
+ BEGIN F; \
+ break; \
+ } \
+}
+
+#else /* not FLEX_SCANNER */
+
+/*
+ * Using old lex...
+ */
+# define INIT_STATE { \
+ switch (yybgin - yysvec - 1) { \
+ case 0: \
+ BEGIN F; \
+ break; \
+ } \
+}
+
+#endif /* end FLEX_SCANNER */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+/*
+ * Some systems include a definition for the macro ECHO in <sys/ioctl.h>,
+ * and their (bad) version of lex defines it too at the very beginning of
+ * the generated lex.yy.c file (before it can be easily undefined),
+ * resulting in a conflict. So undefine it here before needed.
+ * Luckily, it does not appear that this macro is actually used in the rest
+ * of the generated lex.yy.c file.
+ */
+#ifdef ECHO
+# undef ECHO
+#endif /* ECHO */
+#include <am_defs.h>
+#include <fsi_data.h>
+#include <fsinfo.h>
+#include <fsi_gram.h>
+/* and once again undefine this, just in case */
+#ifdef ECHO
+# undef ECHO
+#endif /* ECHO */
+
+/*
+ * There are some things that need to be defined only if useing GNU flex.
+ * These must not be defined if using standard lex
+ */
+#ifdef FLEX_SCANNER
+# ifndef ECHO
+# define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+# endif /* not ECHO */
+#endif /* FLEX_SCANNER */
+
+/*
+ * some systems such as DU-4.x have a different GNU flex in /usr/bin
+ * which automatically generates yywrap macros and symbols. So I must
+ * distinguish between them and when yywrap is actually needed.
+ */
+#ifndef yywrap
+int yywrap(void);
+#endif /* not yywrap */
+
+YYSTYPE yylval;
+static char *fsi_filename;
+static char *optr;
+static char ostr[1024];
+static int find_resword(char *);
+static int quoted;
+
+struct r {
+ char *rw;
+ int tok;
+} rr[] = {
+ { "->", tEQ },
+ { "arch", tARCH },
+ { "as", tAS },
+ { "automount", tAUTOMOUNT },
+ { "cluster", tCLUSTER },
+ { "config", tCONFIG },
+ { "direct", tDIRECT },
+ { "dumpset", tDUMPSET },
+ { "exportfs", tEXPORTFS },
+ { "freq", tFREQ },
+ { "from", tFROM },
+ { "fs", tFS },
+ { "fstype", tFSTYPE },
+ { "host", tHOST },
+ { "hwaddr", tHWADDR },
+ { "inaddr", tINADDR },
+ { "localhost", tLOCALHOST },
+ { "log", tLOG },
+ { "mount", tMOUNT },
+ { "netif", tNETIF },
+ { "netmask", tNETMASK },
+ { "nfsalias", tNFSEQ },
+ { "opts", tOPTS },
+ { "os", tOS },
+ { "passno", tPASSNO },
+ { "sel", tSEL },
+ { "volname", tVOLNAME },
+ { 0, 0 },
+};
+#define NRES_WORDS (sizeof(rr)/sizeof(rr[0])-1)
+
+%}
+
+%start F Q
+
+%%
+ INIT_STATE; /* witchcraft */
+
+<F>[^ \t\n"={}]+ { return find_resword(yytext); } /* dummy " */
+<F>[ \t] ;
+<F>"\n" { yylineno++; }
+<F>[={}] { return *yytext; }
+
+<F>\" { BEGIN Q; optr = ostr; quoted = 1; }
+<Q>\n { yylineno++; yyerror("\" expected"); BEGIN F; }
+<Q>\\b { *optr++ = '\b'; /* escape */ }
+<Q>\\t { *optr++ = '\t'; /* escape */ }
+<Q>\\\" { *optr++ = '\"'; /* escape */ }
+<Q>\\\\ { *optr++ = '\\'; /* escape */ }
+<Q>\\\n { yylineno++; /* continue */ }
+<Q>\\r { *optr++ = '\r'; /* escape */ }
+<Q>\\n { *optr++ = '\n'; /* escape */ }
+<Q>\\f { *optr++ = '\f'; /* escape */ }
+<Q>"\\ " { *optr++ = ' '; /* force space */ }
+<Q>\\. { yyerror("Unknown \\ sequence"); }
+<Q>([ \t]|"\\\n"){2,} { char *p = (char *) yytext-1; while ((p = strchr(p+1, '\n'))) yylineno++; }
+<Q>\" { BEGIN F; quoted = 0;
+ *optr = '\0';
+ yylval.s = strdup(ostr);
+ return tSTR;
+ }
+<Q>. { *optr++ = *yytext; }
+
+%%
+
+
+static int
+find_resword(char *s)
+{
+ int tok = 0;
+ int l = 0, m = NRES_WORDS/2, h = NRES_WORDS-1;
+ int rc = 0;
+
+ m = NRES_WORDS/2;
+
+#define FSTRCMP(p, q) ((*(p) == *(q)) ? strcmp((p)+1, (q)+1) : *(p) - *(q))
+
+ while ((l <= h) && (rc = FSTRCMP(s, rr[m].rw))) {
+ if (rc < 0)
+ h = m - 1;
+ else
+ l = m + 1;
+ m = (h + l) / 2;
+ }
+
+ if (rc == 0)
+ tok = rr[m].tok;
+
+ switch (tok) {
+ case tLOCALHOST:
+ s = "${host}";
+ /* fall through... */
+ case 0:
+ yylval.s = strdup(s);
+ tok = tSTR;
+ /* fall through... */
+ default:
+ return tok;
+ }
+}
+
+
+int
+yyerror(char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ col_cleanup(0);
+ fprintf(stderr, "%s:%d: ", fsi_filename ? fsi_filename : "/dev/stdin", yylineno);
+ fprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+ parse_errors++;
+ va_end(ap);
+ return 0;
+
+ /* this call will never happen */
+ unput(0);
+}
+
+
+ioloc *
+current_location(void)
+{
+ ioloc *ip = CALLOC(struct ioloc);
+ ip->i_line = yylineno;
+ ip->i_file = fsi_filename;
+ return ip;
+}
+
+
+/*
+ * some systems such as DU-4.x have a different GNU flex in /usr/bin
+ * which automatically generates yywrap macros and symbols. So I must
+ * distinguish between them and when yywrap is actually needed.
+ */
+#ifndef yywrap
+int yywrap(void)
+{
+ return 1;
+}
+#endif /* not yywrap */
diff --git a/contrib/amd/fsinfo/fsi_util.c b/contrib/amd/fsinfo/fsi_util.c
new file mode 100644
index 0000000..d69c459
--- /dev/null
+++ b/contrib/amd/fsinfo/fsi_util.c
@@ -0,0 +1,693 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: fsi_util.c,v 5.2.2.1 1992/02/09 15:09:39 jsp beta $
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <fsi_data.h>
+#include <fsinfo.h>
+
+/* static variables */
+static int show_range = 10;
+static int col = 0;
+static int total_shown = 0;
+static int total_mmm = 8;
+
+
+static int
+col_output(int len)
+{
+ int wrapped = 0;
+
+ col += len;
+ if (col > 77) {
+ fputc('\n', stdout);
+ col = len;
+ wrapped = 1;
+ }
+ return wrapped;
+}
+
+
+static void
+show_total(void)
+{
+ if (total_mmm != -show_range + 1) {
+ char n[8];
+ int len;
+
+ if (total_mmm < 0)
+ fputc('*', stdout);
+ sprintf(n, "%d", total_shown);
+ len = strlen(n);
+ if (col_output(len))
+ fputc(' ', stdout);
+ fputs(n, stdout);
+ fflush(stdout);
+ total_mmm = -show_range;
+ }
+}
+
+
+void
+col_cleanup(int eoj)
+{
+ if (verbose < 0)
+ return;
+ if (eoj) {
+ show_total();
+ fputs(")]", stdout);
+ }
+ if (col) {
+ fputc('\n', stdout);
+ col = 0;
+ }
+}
+
+
+/*
+ * Lots of ways of reporting errors...
+ */
+void
+error(char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ col_cleanup(0);
+ fprintf(stderr, "%s: Error, ", progname);
+ fprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+ errors++;
+ va_end(ap);
+}
+
+
+void
+lerror(ioloc *l, char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ col_cleanup(0);
+ fprintf(stderr, "%s:%d: ", l->i_file, l->i_line);
+ fprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+ errors++;
+ va_end(ap);
+}
+
+
+void
+lwarning(ioloc *l, char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ col_cleanup(0);
+ fprintf(stderr, "%s:%d: ", l->i_file, l->i_line);
+ fprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+ va_end(ap);
+}
+
+
+void
+fatal(char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ col_cleanup(1);
+ fprintf(stderr, "%s: Fatal, ", progname);
+ fprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+ va_end(ap);
+ exit(1);
+}
+
+
+/*
+ * Debug log
+ */
+void
+log(char *fmt, ...)
+{
+ va_list ap;
+
+ if (verbose > 0) {
+ va_start(ap, fmt);
+ fputc('#', stdout);
+ fprintf(stdout, "%s: ", progname);
+ fprintf(stdout, fmt, ap);
+ putc('\n', stdout);
+ va_end(ap);
+ }
+}
+
+
+void
+info_hdr(FILE *ef, char *info)
+{
+ fprintf(ef, "# *** NOTE: This file contains %s info\n", info);
+}
+
+
+void
+gen_hdr(FILE *ef, char *hn)
+{
+ fprintf(ef, "# *** NOTE: Only for use on %s\n", hn);
+}
+
+
+static void
+make_banner(FILE *fp)
+{
+ time_t t = time((time_t *) 0);
+ char *cp = ctime(&t);
+
+ fprintf(fp,
+ "\
+# *** This file was automatically generated -- DO NOT EDIT HERE ***\n\
+# \"%s\" run by %s@%s on %s\
+#\n\
+",
+ progname, username, hostname, cp);
+}
+
+
+void
+show_new(char *msg)
+{
+ if (verbose < 0)
+ return;
+
+ total_shown++;
+ if (total_mmm > show_range) {
+ show_total();
+ } else if (total_mmm == 0) {
+ fputc('*', stdout);
+ fflush(stdout);
+ col += 1;
+ }
+ total_mmm++;
+}
+
+
+void
+show_area_being_processed(char *area, int n)
+{
+ static char *last_area = 0;
+
+ if (verbose < 0)
+ return;
+ if (last_area) {
+ if (total_shown)
+ show_total();
+ fputs(")", stdout);
+ col += 1;
+ }
+
+ if (!last_area || !STREQ(area, last_area)) {
+ if (last_area) {
+ col_cleanup(0);
+ total_shown = 0;
+ total_mmm = show_range + 1;
+ }
+ (void) col_output(strlen(area) + 2);
+ fprintf(stdout, "[%s", area);
+ last_area = area;
+ }
+
+ fputs(" (", stdout);
+ col += 2;
+ show_range = n;
+ total_mmm = n + 1;
+
+ fflush(stdout);
+}
+
+
+/*
+ * Open a file with the given prefix and name
+ */
+FILE *
+pref_open(char *pref, char *hn, void (*hdr) (FILE *, char *), char *arg)
+{
+ char p[MAXPATHLEN];
+ FILE *ef;
+
+ sprintf(p, "%s%s", pref, hn);
+ log("Writing %s info for %s to %s", pref, hn, p);
+ ef = fopen(p, "w");
+ if (ef) {
+ (*hdr) (ef, arg);
+ make_banner(ef);
+ } else {
+ error("can't open %s for writing", p);
+ }
+
+ return ef;
+}
+
+
+int
+pref_close(FILE *fp)
+{
+ return fclose(fp) == 0;
+}
+
+
+/*
+ * Determine where Amd would automount the host/volname pair
+ */
+void
+compute_automount_point(char *buf, host *hp, char *vn)
+{
+ sprintf(buf, "%s/%s%s", autodir, hp->h_lochost, vn);
+}
+
+
+char *
+xcalloc(int i, int s)
+{
+ char *p = (char *) calloc(i, (unsigned) s);
+
+ if (!p)
+ fatal("Out of memory");
+ return p;
+}
+
+
+/*
+ * Data constructors..
+ */
+automount *
+new_automount(char *name)
+{
+ automount *ap = CALLOC(struct automount);
+
+ ap->a_ioloc = current_location();
+ ap->a_name = name;
+ ap->a_volname = 0;
+ ap->a_mount = 0;
+ ap->a_opts = 0;
+ show_new("automount");
+ return ap;
+}
+
+
+auto_tree *
+new_auto_tree(char *def, qelem *ap)
+{
+ auto_tree *tp = CALLOC(struct auto_tree);
+
+ tp->t_ioloc = current_location();
+ tp->t_defaults = def;
+ tp->t_mount = ap;
+ show_new("auto_tree");
+ return tp;
+}
+
+
+host *
+new_host(void)
+{
+ host *hp = CALLOC(struct host);
+
+ hp->h_ioloc = current_location();
+ hp->h_mask = 0;
+ show_new("host");
+ return hp;
+}
+
+
+void
+set_host(host *hp, int k, char *v)
+{
+ int m = 1 << k;
+
+ if (hp->h_mask & m) {
+ yyerror("host field \"%s\" already set", host_strings[k]);
+ return;
+ }
+ hp->h_mask |= m;
+
+ switch (k) {
+
+ case HF_HOST:{
+ char *p = strdup(v);
+ dict_ent *de = dict_locate(dict_of_hosts, v);
+
+ if (de)
+ yyerror("duplicate host %s!", v);
+ else
+ dict_add(dict_of_hosts, v, (char *) hp);
+ hp->h_hostname = v;
+ domain_strip(p, hostname);
+ if (strchr(p, '.') != 0)
+ XFREE(p);
+ else
+ hp->h_lochost = p;
+ }
+ break;
+
+ case HF_CONFIG:{
+ qelem *q;
+ qelem *vq = (qelem *) v;
+
+ hp->h_mask &= ~m;
+ if (hp->h_config)
+ q = hp->h_config;
+ else
+ q = hp->h_config = new_que();
+ ins_que(vq, q->q_back);
+ }
+ break;
+
+ case HF_ETHER:{
+ qelem *q;
+ qelem *vq = (qelem *) v;
+
+ hp->h_mask &= ~m;
+ if (hp->h_ether)
+ q = hp->h_ether;
+ else
+ q = hp->h_ether = new_que();
+ ins_que(vq, q->q_back);
+ }
+ break;
+
+ case HF_ARCH:
+ hp->h_arch = v;
+ break;
+
+ case HF_OS:
+ hp->h_os = v;
+ break;
+
+ case HF_CLUSTER:
+ hp->h_cluster = v;
+ break;
+
+ default:
+ abort();
+ break;
+ }
+}
+
+
+ether_if *
+new_ether_if(void)
+{
+ ether_if *ep = CALLOC(struct ether_if);
+
+ ep->e_mask = 0;
+ ep->e_ioloc = current_location();
+ show_new("ether_if");
+ return ep;
+}
+
+
+void
+set_ether_if(ether_if *ep, int k, char *v)
+{
+ int m = 1 << k;
+
+ if (ep->e_mask & m) {
+ yyerror("netif field \"%s\" already set", ether_if_strings[k]);
+ return;
+ }
+ ep->e_mask |= m;
+
+ switch (k) {
+
+ case EF_INADDR:{
+ ep->e_inaddr.s_addr = inet_addr(v);
+ if (ep->e_inaddr.s_addr == (u_long) - 1)
+ yyerror("malformed IP dotted quad: %s", v);
+ XFREE(v);
+ }
+ break;
+
+ case EF_NETMASK:{
+ u_long nm = 0;
+
+ if ((sscanf(v, "0x%lx", &nm) == 1 || sscanf(v, "%lx", &nm) == 1) && nm != 0)
+ ep->e_netmask = htonl(nm);
+ else
+ yyerror("malformed netmask: %s", v);
+ XFREE(v);
+ }
+ break;
+
+ case EF_HWADDR:
+ ep->e_hwaddr = v;
+ break;
+
+ default:
+ abort();
+ break;
+ }
+}
+
+
+void
+set_disk_fs(disk_fs *dp, int k, char *v)
+{
+ int m = 1 << k;
+
+ if (dp->d_mask & m) {
+ yyerror("fs field \"%s\" already set", disk_fs_strings[k]);
+ return;
+ }
+ dp->d_mask |= m;
+
+ switch (k) {
+
+ case DF_FSTYPE:
+ dp->d_fstype = v;
+ break;
+
+ case DF_OPTS:
+ dp->d_opts = v;
+ break;
+
+ case DF_DUMPSET:
+ dp->d_dumpset = v;
+ break;
+
+ case DF_LOG:
+ dp->d_log = v;
+ break;
+
+ case DF_PASSNO:
+ dp->d_passno = atoi(v);
+ XFREE(v);
+ break;
+
+ case DF_FREQ:
+ dp->d_freq = atoi(v);
+ XFREE(v);
+ break;
+
+ case DF_MOUNT:
+ dp->d_mount = &((fsi_mount *) v)->m_q;
+ break;
+
+ default:
+ abort();
+ break;
+ }
+}
+
+
+disk_fs *
+new_disk_fs(void)
+{
+ disk_fs *dp = CALLOC(struct disk_fs);
+
+ dp->d_ioloc = current_location();
+ show_new("disk_fs");
+ return dp;
+}
+
+
+void
+set_mount(fsi_mount *mp, int k, char *v)
+{
+ int m = 1 << k;
+
+ if (mp->m_mask & m) {
+ yyerror("mount tree field \"%s\" already set", mount_strings[k]);
+ return;
+ }
+ mp->m_mask |= m;
+
+ switch (k) {
+
+ case DM_VOLNAME:
+ dict_add(dict_of_volnames, v, (char *) mp);
+ mp->m_volname = v;
+ break;
+
+ case DM_EXPORTFS:
+ mp->m_exportfs = v;
+ break;
+
+ case DM_SEL:
+ mp->m_sel = v;
+ break;
+
+ default:
+ abort();
+ break;
+ }
+}
+
+
+fsi_mount *
+new_mount(void)
+{
+ fsi_mount *fp = CALLOC(struct fsi_mount);
+
+ fp->m_ioloc = current_location();
+ show_new("mount");
+ return fp;
+}
+
+
+void
+set_fsmount(fsmount *fp, int k, char *v)
+{
+ int m = 1 << k;
+
+ if (fp->f_mask & m) {
+ yyerror("mount field \"%s\" already set", fsmount_strings[k]);
+ return;
+ }
+ fp->f_mask |= m;
+
+ switch (k) {
+
+ case FM_LOCALNAME:
+ fp->f_localname = v;
+ break;
+
+ case FM_VOLNAME:
+ fp->f_volname = v;
+ break;
+
+ case FM_FSTYPE:
+ fp->f_fstype = v;
+ break;
+
+ case FM_OPTS:
+ fp->f_opts = v;
+ break;
+
+ case FM_FROM:
+ fp->f_from = v;
+ break;
+
+ case FM_DIRECT:
+ break;
+
+ default:
+ abort();
+ break;
+ }
+}
+
+
+fsmount *
+new_fsmount(void)
+{
+ fsmount *fp = CALLOC(struct fsmount);
+
+ fp->f_ioloc = current_location();
+ show_new("fsmount");
+ return fp;
+}
+
+
+void
+init_que(qelem *q)
+{
+ q->q_forw = q->q_back = q;
+}
+
+
+qelem *
+new_que(void)
+{
+ qelem *q = CALLOC(qelem);
+
+ init_que(q);
+ return q;
+}
+
+
+void
+ins_que(qelem *elem, qelem *pred)
+{
+ qelem *p;
+
+ p = pred->q_forw;
+ elem->q_back = pred;
+ elem->q_forw = p;
+ pred->q_forw = elem;
+ p->q_back = elem;
+}
+
+
+void
+rem_que(qelem *elem)
+{
+ qelem *p, *p2;
+
+ p = elem->q_forw;
+ p2 = elem->q_back;
+
+ p2->q_forw = p;
+ p->q_back = p2;
+}
diff --git a/contrib/amd/fsinfo/fsinfo.8 b/contrib/amd/fsinfo/fsinfo.8
new file mode 100644
index 0000000..5a4eec5
--- /dev/null
+++ b/contrib/amd/fsinfo/fsinfo.8
@@ -0,0 +1,101 @@
+.\"
+.\" Copyright (c) 1997-1998 Erez Zadok
+.\" Copyright (c) 1993 Jan-Simon Pendry.
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgment:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" from: @(#)fsinfo.8 8.1 (Berkeley) 6/28/93
+.\" $Id: fsinfo.8,v 1.2 1994/06/13 20:50:18 mycroft Exp $
+.\"
+.TH FSINFO 8 "June 28, 1993"
+.SH NAME
+fsinfo \- co-ordinate site-wide filesystem information
+.SH SYNOPSIS
+.B fsinfo
+[
+.B \-v
+] [
+.B \-a
+.I autodir
+] [
+.B \-b
+.I bootparams
+] [
+.B \-d
+.I dumpsets
+] [
+.B \-e
+.I exports
+] [
+.B \-f
+.I fstabs
+] [
+.B \-h
+.I hostname
+] [
+.B \-m
+.I automounts
+] [
+.B \-I
+.I dir
+] [
+.B \-D
+.I string[=string]]
+] [
+.B \-U
+.I string[=string]]
+]
+.I config
+.I ...
+.SH DESCRIPTION
+The
+.B fsinfo
+utility takes a set of system configuration information, and generates
+a co-ordinated set of
+.I amd
+,
+.I mount
+and
+.I mountd
+configuration files.
+.PP
+The
+.B fsinfo
+command is fully described in the document
+.I "Amd - The 4.4BSD Automounter"
+.SH "SEE ALSO"
+.BR amd (8),
+.BR mount (8),
+.BR mountd (8).
+.SH HISTORY
+The
+.B fsinfo
+command first appeared in 4.4BSD.
diff --git a/contrib/amd/fsinfo/fsinfo.c b/contrib/amd/fsinfo/fsinfo.c
new file mode 100644
index 0000000..e2632bf
--- /dev/null
+++ b/contrib/amd/fsinfo/fsinfo.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: fsinfo.c,v 5.2.2.1 1992/02/09 15:09:33 jsp beta $
+ *
+ */
+
+/*
+ * fsinfo
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <fsi_data.h>
+#include <fsinfo.h>
+#include <fsi_gram.h>
+
+/* globals */
+char **g_argv;
+char *autodir = "/a";
+char *progname;
+char *username;
+char hostname[MAXHOSTNAMELEN + 1];
+char idvbuf[1024];
+dict *dict_of_hosts;
+dict *dict_of_volnames;
+int errors;
+int file_io_errors;
+int parse_errors;
+int verbose;
+qelem *list_of_automounts;
+qelem *list_of_hosts;
+
+/*
+ * Output file prefixes
+ */
+char *bootparams_pref;
+char *dumpset_pref;
+char *exportfs_pref;
+char *fstab_pref;
+char *mount_pref;
+
+/* dummy variables */
+int orig_umask, foreground, debug_flags;
+pid_t mypid;
+serv_state amd_state;
+
+
+/*
+ * Argument cracking...
+ */
+static void
+fsi_get_args(int c, char *v[])
+{
+ int ch;
+ int usage = 0;
+ char *iptr = idvbuf;
+
+ /*
+ * Determine program name
+ */
+ if (v[0]) {
+ progname = strrchr(v[0], '/');
+ if (progname && progname[1])
+ progname++;
+ else
+ progname = v[0];
+ }
+
+ if (!progname)
+ progname = "fsinfo";
+
+ while ((ch = getopt(c, v, "a:b:d:e:f:h:m:D:U:I:qv")) != EOF)
+
+ switch (ch) {
+
+ case 'a':
+ autodir = optarg;
+ break;
+
+ case 'b':
+ if (bootparams_pref)
+ fatal("-b option specified twice");
+ bootparams_pref = optarg;
+ break;
+
+ case 'd':
+ if (dumpset_pref)
+ fatal("-d option specified twice");
+ dumpset_pref = optarg;
+ break;
+
+ case 'h':
+ strncpy(hostname, optarg, sizeof(hostname) - 1);
+ break;
+
+ case 'e':
+ if (exportfs_pref)
+ fatal("-e option specified twice");
+ exportfs_pref = optarg;
+ break;
+
+ case 'f':
+ if (fstab_pref)
+ fatal("-f option specified twice");
+ fstab_pref = optarg;
+ break;
+
+ case 'm':
+ if (mount_pref)
+ fatal("-m option specified twice");
+ mount_pref = optarg;
+ break;
+
+ case 'q':
+ verbose = -1;
+ break;
+
+ case 'v':
+ verbose = 1;
+ break;
+
+ case 'I':
+ case 'D':
+ case 'U':
+ sprintf(iptr, "-%c%s ", ch, optarg);
+ iptr += strlen(iptr);
+ break;
+
+ default:
+ usage++;
+ break;
+ }
+
+ if (c != optind) {
+ g_argv = v + optind - 1;
+ if (yywrap())
+ fatal("Cannot read any input files");
+ } else {
+ usage++;
+ }
+
+ if (usage) {
+ fprintf(stderr,
+ "\
+Usage: %s [-v] [-a autodir] [-h hostname] [-b bootparams] [-d dumpsets]\n\
+\t[-e exports] [-f fstabs] [-m automounts]\n\
+\t[-I dir] [-D|-U string[=string]] config ...\n", progname);
+ exit(1);
+ }
+
+ if (g_argv[0])
+ log("g_argv[0] = %s", g_argv[0]);
+ else
+ log("g_argv[0] = (nil)");
+}
+
+
+/*
+ * Determine username of caller
+ */
+static char *
+find_username(void)
+{
+ char *u = getlogin();
+
+ if (!u) {
+ struct passwd *pw = getpwuid(getuid());
+ if (pw)
+ u = pw->pw_name;
+ }
+
+ if (!u)
+ u = getenv("USER");
+ if (!u)
+ u = getenv("LOGNAME");
+ if (!u)
+ u = "root";
+
+ return strdup(u);
+}
+
+
+/*
+ * MAIN
+ */
+int
+main(int argc, char *argv[])
+{
+ /*
+ * Process arguments
+ */
+ fsi_get_args(argc, argv);
+
+ /*
+ * If no hostname given then use the local name
+ */
+ if (!*hostname && gethostname(hostname, sizeof(hostname)) < 0) {
+ perror("gethostname");
+ exit(1);
+ }
+
+ /*
+ * Get the username
+ */
+ username = find_username();
+
+ /*
+ * New hosts and automounts
+ */
+ list_of_hosts = new_que();
+ list_of_automounts = new_que();
+
+ /*
+ * New dictionaries
+ */
+ dict_of_volnames = new_dict();
+ dict_of_hosts = new_dict();
+
+ /*
+ * Parse input
+ */
+ show_area_being_processed("read config", 11);
+ if (yyparse())
+ errors = 1;
+ errors += file_io_errors + parse_errors;
+
+ if (errors == 0) {
+ /*
+ * Do semantic analysis of input
+ */
+ analyze_hosts(list_of_hosts);
+ analyze_automounts(list_of_automounts);
+ }
+
+ /*
+ * Give up if errors
+ */
+ if (errors == 0) {
+ /*
+ * Output data files
+ */
+
+ write_atab(list_of_automounts);
+ write_bootparams(list_of_hosts);
+ write_dumpset(list_of_hosts);
+ write_exportfs(list_of_hosts);
+ write_fstab(list_of_hosts);
+ }
+ col_cleanup(1);
+
+ exit(errors);
+ return errors; /* should never reach here */
+}
diff --git a/contrib/amd/fsinfo/fsinfo.h b/contrib/amd/fsinfo/fsinfo.h
new file mode 100644
index 0000000..c02b673
--- /dev/null
+++ b/contrib/amd/fsinfo/fsinfo.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: fsinfo.h,v 5.2.2.1 1992/02/09 15:09:51 jsp beta $
+ *
+ */
+
+extern FILE *pref_open(char *pref, char *hn, void (*hdr) (FILE *, char *), char *arg);
+extern auto_tree *new_auto_tree(char *, qelem *);
+extern automount *new_automount(char *);
+extern char **g_argv;
+extern char *autodir;
+extern char *bootparams_pref;
+extern char *disk_fs_strings[];
+extern char *dumpset_pref;
+extern char *ether_if_strings[];
+extern char *exportfs_pref;
+extern char *fsmount_strings[];
+extern char *fstab_pref;
+extern char *host_strings[];
+extern char *mount_pref;
+extern char *mount_strings[];
+extern char *progname;
+extern char *username;
+extern char *xcalloc(int, int);
+extern char hostname[];
+extern char idvbuf[];
+extern dict *dict_of_hosts;
+extern dict *dict_of_volnames;
+extern dict *new_dict(void);
+extern dict_ent *dict_locate(dict *, char *);
+extern disk_fs *new_disk_fs(void);
+extern ether_if *new_ether_if(void);
+extern fsmount *new_fsmount(void);
+extern host *new_host(void);
+extern int dict_iter(dict *, int (*)(qelem *));
+extern int errors;
+extern int file_io_errors;
+extern int parse_errors;
+extern int pref_close(FILE *fp);
+extern int verbose;
+extern ioloc *current_location(void);
+extern fsi_mount *new_mount(void);
+extern qelem *new_que(void);
+extern void analyze_automounts(qelem *);
+extern void analyze_hosts(qelem *);
+extern void compute_automount_point(char *, host *, char *);
+extern void dict_add(dict *, char *, char *);
+extern void error(char *fmt, ...);
+extern void fatal(char *fmt, ...);
+extern void gen_hdr(FILE *ef, char *hn);
+extern void info_hdr(FILE *ef, char *info);
+extern void init_que(qelem *);
+extern void ins_que(qelem *, qelem *);
+extern void lerror(ioloc *l, char *fmt, ...);
+extern void log(char *fmt, ...);
+extern void lwarning(ioloc *l, char *fmt, ...);
+extern void rem_que(qelem *);
+extern void set_disk_fs(disk_fs *, int, char *);
+extern void set_fsmount(fsmount *, int, char *);
+extern void set_mount(fsi_mount *, int, char *);
+extern void show_area_being_processed(char *area, int n);
+extern void show_new(char *msg);
+extern void warning(void);
+
+extern int yyerror(char *fmt, ...);
+extern void domain_strip(char *otherdom, char *localdom);
+/*
+ * some systems such as DU-4.x have a different GNU flex in /usr/bin
+ * which automatically generates yywrap macros and symbols. So I must
+ * distinguish between them and when yywrap is actually needed.
+ */
+#ifndef yywrap
+extern int yywrap(void);
+#endif /* not yywrap */
+extern int yyparse(void);
+extern int write_atab(qelem *q);
+extern int write_bootparams(qelem *q);
+extern int write_dumpset(qelem *q);
+extern int write_exportfs(qelem *q);
+extern int write_fstab(qelem *q);
+extern void col_cleanup(int eoj);
+extern void set_host(host *hp, int k, char *v);
+extern void set_ether_if(ether_if *ep, int k, char *v);
+extern int yylex(void);
+
+
+#define BITSET(m,b) ((m) |= (1<<(b)))
+#define AM_FIRST(ty, q) ((ty *) ((q)->q_forw))
+#define HEAD(ty, q) ((ty *) q)
+#define ISSET(m,b) ((m) & (1<<(b)))
+#define ITER(v, ty, q) for ((v) = AM_FIRST(ty,(q)); (v) != HEAD(ty,(q)); (v) = NEXT(ty,(v)))
+#define AM_LAST(ty, q) ((ty *) ((q)->q_back))
+#define NEXT(ty, q) ((ty *) (((qelem *) q)->q_forw))
diff --git a/contrib/amd/fsinfo/wr_atab.c b/contrib/amd/fsinfo/wr_atab.c
new file mode 100644
index 0000000..be870c0
--- /dev/null
+++ b/contrib/amd/fsinfo/wr_atab.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: wr_atab.c,v 5.2.2.1 1992/02/09 15:09:44 jsp beta $
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <fsi_data.h>
+#include <fsinfo.h>
+
+
+/*
+ * Write a sequence of automount mount map entries
+ */
+static int
+write_amount_info(FILE *af, automount *ap, int sk)
+{
+ int errors = 0;
+
+ if (ap->a_mount) {
+ /*
+ * A pseudo-directory.
+ * This can also be a top-level directory, in which
+ * case the type:=auto is not wanted...
+ *
+ * type:=auto;fs:=${map};pref:=whatever/
+ */
+ automount *ap2;
+ if (strlen(ap->a_name) > sk) {
+ fprintf(af, "%s type:=auto;fs:=${map};pref:=%s/\n",
+ ap->a_name + sk, ap->a_name + sk);
+ }
+ ITER(ap2, automount, ap->a_mount)
+ errors += write_amount_info(af, ap2, sk);
+ } else if (ap->a_hardwiredfs) {
+
+ /*
+ * A hardwired filesystem "hostname:path"
+ * rhost:=hostname;rfs:=path
+ */
+ char *key = ap->a_name + sk;
+ char *hostname = ap->a_hardwiredfs;
+ char *path = strrchr(hostname, (int) ':');
+
+ if (path == NULL) {
+ fprintf(stderr, "%s: %s not an NFS filesystem\n", ap->a_name, ap->a_hardwiredfs);
+ errors++;
+ } else {
+ *path = '\0';
+ path++;
+
+ /*
+ * Output the map key
+ */
+ fputs(key, af);
+ fprintf(af, " rhost:=%s", hostname);
+ fprintf(af, ";rfs:=%s", path);
+ if (ap->a_opts && !STREQ(ap->a_opts, "")) {
+ fprintf(af, ";%s", ap->a_opts);
+ }
+ fputc('\n', af);
+ path--;
+ *path = ':';
+ }
+ } else if (ap->a_mounted) {
+
+ /*
+ * A mounted partition
+ * type:=link [ link entries ] type:=nfs [ nfs entries ]
+ */
+ dict_data *dd;
+ dict_ent *de = ap->a_mounted;
+ int done_type_link = 0;
+ char *key = ap->a_name + sk;
+
+ /*
+ * Output the map key
+ */
+ fputs(key, af);
+
+ /*
+ * First output any Link locations that would not
+ * otherwise be correctly mounted. These refer
+ * to filesystem which are not mounted in the same
+ * place which the automounter would use.
+ */
+ ITER(dd, dict_data, &de->de_q) {
+ fsi_mount *mp = (fsi_mount *) dd->dd_data;
+ /*
+ * If the mount point and the exported volname are the
+ * same then this filesystem will be recognised by
+ * the restart code - so we don't need to put out a
+ * special rule for it.
+ */
+ if (mp->m_dk->d_host->h_lochost) {
+ char amountpt[1024];
+ compute_automount_point(amountpt, mp->m_dk->d_host, mp->m_exported->m_volname);
+ if (!STREQ(mp->m_dk->d_mountpt, amountpt)) {
+ /*
+ * ap->a_volname is the name of the aliased volume
+ * mp->m_name is the mount point of the filesystem
+ * mp->m_volname is the volume name of the filesystems
+ */
+
+ /*
+ * Find length of key and volume names
+ */
+ int avlen = strlen(ap->a_volname);
+ int mnlen = strlen(mp->m_volname);
+
+ /*
+ * Make sure a -type:=link is output once
+ */
+ if (!done_type_link) {
+ done_type_link = 1;
+ fputs(" -type:=link", af);
+ }
+
+ /*
+ * Output a selector for the hostname,
+ * the device from which to mount and
+ * where to mount. This will correspond
+ * to the values output for the fstab.
+ */
+ if (mp->m_dk->d_host->h_lochost)
+ fprintf(af, " host==%s", mp->m_dk->d_host->h_lochost);
+ else
+ fprintf(af, " hostd==%s", mp->m_dk->d_host->h_hostname);
+ fprintf(af, ";fs:=%s", mp->m_name);
+
+ /*
+ * ... and a sublink if needed
+ */
+ if (mnlen < avlen) {
+ char *sublink = ap->a_volname + mnlen + 1;
+ fprintf(af, "/%s", sublink);
+ }
+ fputs(" ||", af);
+ }
+ }
+ }
+
+ /*
+ * Next do the NFS locations
+ */
+ if (done_type_link)
+ fputs(" -", af);
+
+ ITER(dd, dict_data, &de->de_q) {
+ fsi_mount *mp = (fsi_mount *) dd->dd_data;
+ int namelen = mp->m_name_len;
+ int exp_namelen = mp->m_exported->m_name_len;
+ int volnlen = strlen(ap->a_volname);
+ int mvolnlen = strlen(mp->m_volname);
+
+ fputc(' ', af);
+
+ /*
+ * Output any selectors
+ */
+ if (mp->m_sel)
+ fprintf(af, "%s;", mp->m_sel);
+
+ /*
+ * Print host and volname of exported filesystem
+ */
+ fprintf(af, "rhost:=%s",
+ mp->m_dk->d_host->h_lochost ?
+ mp->m_dk->d_host->h_lochost :
+ mp->m_dk->d_host->h_hostname);
+ fprintf(af, ";rfs:=%s", mp->m_exported->m_volname);
+ if (ap->a_opts && !STREQ(ap->a_opts, "")) {
+ fprintf(af, ";%s", ap->a_opts);
+ }
+
+ /*
+ * Now determine whether a sublink is required.
+ */
+ if (exp_namelen < namelen || mvolnlen < volnlen) {
+ char sublink[1024];
+ sublink[0] = '\0';
+ if (exp_namelen < namelen) {
+ strcat(sublink, mp->m_name + exp_namelen + 1);
+ if (mvolnlen < volnlen)
+ strcat(sublink, "/");
+ }
+ if (mvolnlen < volnlen)
+ strcat(sublink, ap->a_volname + mvolnlen + 1);
+
+ fprintf(af, ";sublink:=%s", sublink);
+ }
+ }
+ fputc('\n', af);
+ } else if (ap->a_symlink) {
+
+ /*
+ * A specific link.
+ *
+ * type:=link;fs:=whatever
+ */
+ fprintf(af, "%s type:=link;fs:=%s\n", ap->a_name + sk, ap->a_symlink);
+ }
+
+ return errors;
+}
+
+
+/*
+ * Write a single automount configuration file
+ */
+static int
+write_amount( qelem *q, char *def)
+{
+ automount *ap;
+ int errors = 0;
+ int direct = 0;
+
+ /*
+ * Output all indirect maps
+ */
+ ITER(ap, automount, q) {
+ FILE *af;
+ char *p;
+
+ /*
+ * If there is no a_mount node then this is really
+ * a direct mount, so just keep a count and continue.
+ * Direct mounts are output into a special file during
+ * the second pass below.
+ */
+ if (!ap->a_mount) {
+ direct++;
+ continue;
+ }
+
+ p = strrchr(ap->a_name, '/');
+ if (!p)
+ p = ap->a_name;
+ else
+ p++;
+
+ af = pref_open(mount_pref, p, gen_hdr, ap->a_name);
+ if (af) {
+ show_new(ap->a_name);
+ fputs("/defaults ", af);
+ if (*def)
+ fprintf(af, "%s;", def);
+ fputs("type:=nfs\n", af);
+ errors += write_amount_info(af, ap, strlen(ap->a_name) + 1);
+ errors += pref_close(af);
+ }
+ }
+
+ /*
+ * Output any direct map entries which were found during the
+ * previous pass over the data.
+ */
+ if (direct) {
+ FILE *af = pref_open(mount_pref, "direct.map", info_hdr, "direct mount");
+
+ if (af) {
+ show_new("direct mounts");
+ fputs("/defaults ", af);
+ if (*def)
+ fprintf(af, "%s;", def);
+ fputs("type:=nfs\n", af);
+ ITER(ap, automount, q)
+ if (!ap->a_mount)
+ errors += write_amount_info(af, ap, 1);
+ errors += pref_close(af);
+ }
+ }
+ return errors;
+}
+
+
+/*
+ * Write all the needed automount configuration files
+ */
+int
+write_atab(qelem *q)
+{
+ int errors = 0;
+
+ if (mount_pref) {
+ auto_tree *tp;
+ show_area_being_processed("write automount", 5);
+ ITER(tp, auto_tree, q)
+ errors += write_amount(tp->t_mount, tp->t_defaults);
+ }
+
+ return errors;
+}
diff --git a/contrib/amd/fsinfo/wr_bparam.c b/contrib/amd/fsinfo/wr_bparam.c
new file mode 100644
index 0000000..fb4479c
--- /dev/null
+++ b/contrib/amd/fsinfo/wr_bparam.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: wr_bparam.c,v 5.2.2.1 1992/02/09 15:09:46 jsp beta $
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <fsi_data.h>
+#include <fsinfo.h>
+
+
+/*
+ * Write a host/path in NFS format
+ */
+static int
+write_nfsname(FILE *ef, fsmount *fp, char *hn)
+{
+ int errors = 0;
+ char *h = strdup(fp->f_ref->m_dk->d_host->h_hostname);
+
+ domain_strip(h, hn);
+ fprintf(ef, "%s:%s", h, fp->f_volname);
+ XFREE(h);
+ return errors;
+}
+
+
+/*
+ * Write a bootparams entry for a host
+ */
+static int
+write_boot_info(FILE *ef, host *hp)
+{
+ int errors = 0;
+
+ fprintf(ef, "%s\troot=", hp->h_hostname);
+ errors += write_nfsname(ef, hp->h_netroot, hp->h_hostname);
+ fputs(" swap=", ef);
+ errors += write_nfsname(ef, hp->h_netswap, hp->h_hostname);
+ fputs("\n", ef);
+
+ return 0;
+}
+
+
+/*
+ * Output a bootparams file
+ */
+int
+write_bootparams(qelem *q)
+{
+ int errors = 0;
+
+ if (bootparams_pref) {
+ FILE *ef = pref_open(bootparams_pref, "bootparams", info_hdr, "bootparams");
+ if (ef) {
+ host *hp;
+ ITER(hp, host, q)
+ if (hp->h_netroot && hp->h_netswap)
+ errors += write_boot_info(ef, hp);
+ errors += pref_close(ef);
+ } else {
+ errors++;
+ }
+ }
+
+ return errors;
+}
diff --git a/contrib/amd/fsinfo/wr_dumpset.c b/contrib/amd/fsinfo/wr_dumpset.c
new file mode 100644
index 0000000..b33858d
--- /dev/null
+++ b/contrib/amd/fsinfo/wr_dumpset.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: wr_dumpset.c,v 5.2.2.1 1992/02/09 15:09:47 jsp beta $
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <fsi_data.h>
+#include <fsinfo.h>
+
+
+static int
+write_dumpset_info(FILE *ef, qelem *q)
+{
+ int errors = 0;
+ disk_fs *dp;
+
+ ITER(dp, disk_fs, q) {
+ if (dp->d_dumpset) {
+ fprintf(ef, "%s\t%s:%-30s\t# %s\n",
+ dp->d_dumpset,
+ dp->d_host->h_lochost ?
+ dp->d_host->h_lochost :
+ dp->d_host->h_hostname,
+ dp->d_mountpt,
+ dp->d_dev);
+ }
+ }
+ return errors;
+}
+
+
+int
+write_dumpset(qelem *q)
+{
+ int errors = 0;
+
+ if (dumpset_pref) {
+ FILE *ef = pref_open(dumpset_pref, "dumpsets", info_hdr, "exabyte dumpset");
+ if (ef) {
+ host *hp;
+
+ ITER(hp, host, q) {
+ if (hp->h_disk_fs) {
+ errors += write_dumpset_info(ef, hp->h_disk_fs);
+ }
+ }
+ errors += pref_close(ef);
+ } else {
+ errors++;
+ }
+ }
+
+ return errors;
+}
diff --git a/contrib/amd/fsinfo/wr_exportfs.c b/contrib/amd/fsinfo/wr_exportfs.c
new file mode 100644
index 0000000..56d9bd5
--- /dev/null
+++ b/contrib/amd/fsinfo/wr_exportfs.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: wr_exportfs.c,v 5.2.2.1 1992/02/09 15:09:48 jsp beta $
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <fsi_data.h>
+#include <fsinfo.h>
+
+
+static int
+write_export_info(FILE *ef, qelem *q, int errors)
+{
+ fsi_mount *mp;
+
+ ITER(mp, fsi_mount, q) {
+ if (mp->m_mask & (1 << DM_EXPORTFS))
+ fprintf(ef, "%s\t%s\n", mp->m_volname, mp->m_exportfs);
+ if (mp->m_mount)
+ errors += write_export_info(ef, mp->m_mount, 0);
+ }
+
+ return errors;
+}
+
+
+static int
+write_dkexports(FILE *ef, qelem *q)
+{
+ int errors = 0;
+ disk_fs *dp;
+
+ ITER(dp, disk_fs, q) {
+ if (dp->d_mount)
+ errors += write_export_info(ef, dp->d_mount, 0);
+ }
+
+ return errors;
+}
+
+
+int
+write_exportfs(qelem *q)
+{
+ int errors = 0;
+
+ if (exportfs_pref) {
+ host *hp;
+
+ show_area_being_processed("write exportfs", 5);
+ ITER(hp, host, q) {
+ if (hp->h_disk_fs) {
+ FILE *ef = pref_open(exportfs_pref, hp->h_hostname, gen_hdr, hp->h_hostname);
+ if (ef) {
+ show_new(hp->h_hostname);
+ errors += write_dkexports(ef, hp->h_disk_fs);
+ errors += pref_close(ef);
+ } else {
+ errors++;
+ }
+ }
+ }
+ }
+
+ return errors;
+}
diff --git a/contrib/amd/fsinfo/wr_fstab.c b/contrib/amd/fsinfo/wr_fstab.c
new file mode 100644
index 0000000..49cbfc4
--- /dev/null
+++ b/contrib/amd/fsinfo/wr_fstab.c
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: wr_fstab.c,v 5.2.2.1 1992/02/09 15:09:49 jsp beta $
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <fsi_data.h>
+#include <fsinfo.h>
+
+#define GENERIC_OS_NAME "generic"
+
+/* forward definitions */
+static void write_aix1_dkfstab(FILE *ef, disk_fs *dp);
+static void write_aix1_dkrmount(FILE *ef, char *hn, fsmount *fp);
+static void write_aix3_dkfstab(FILE *ef, disk_fs *dp);
+static void write_aix3_dkrmount(FILE *ef, char *hn, fsmount *fp);
+static int write_dkfstab(FILE *ef, qelem *q, void (*output) (FILE *, disk_fs *));
+static int write_dkrmount(FILE *ef, qelem *q, char *hn, void (*output) (FILE *, char *, fsmount *));
+static void write_generic_dkfstab(FILE *ef, disk_fs *dp);
+static void write_generic_dkrmount(FILE *ef, char *hn, fsmount *fp);
+static void write_ultrix_dkfstab(FILE *ef, disk_fs *dp);
+static void write_ultrix_dkrmount(FILE *ef, char *hn, fsmount *fp);
+
+/* ----------------------------------------------- */
+
+static struct os_fstab_type {
+ char *os_name;
+ void (*op_fstab) (FILE *ef, disk_fs *dp);
+ void (*op_mount) (FILE *ef, char *hn, fsmount *fp);
+} os_tabs[] = {
+
+ {
+ "aix1", write_aix1_dkfstab, write_aix1_dkrmount
+ }, /* AIX 1 */
+ {
+ "aix3", write_aix3_dkfstab, write_aix3_dkrmount
+ }, /* AIX 3 */
+ {
+ "generic", write_generic_dkfstab, write_generic_dkrmount
+ }, /* Generic */
+ {
+ "u2_0", write_ultrix_dkfstab, write_ultrix_dkrmount
+ }, /* Ultrix */
+ {
+ "u3_0", write_ultrix_dkfstab, write_ultrix_dkrmount
+ }, /* Ultrix */
+ {
+ "u4_0", write_ultrix_dkfstab, write_ultrix_dkrmount
+ }, /* Ultrix */
+ {
+ 0, 0, 0
+ }
+};
+
+
+/* ---------- AIX 1 ------------------------------ */
+
+/*
+ * AIX 1 format
+ */
+static void
+write_aix1_dkfstab(FILE *ef, disk_fs *dp)
+{
+ char *hp = strdup(dp->d_host->h_hostname);
+ char *p = strchr(hp, '.');
+
+ if (p)
+ *p = '\0';
+
+ fprintf(ef, "\n%s:\n\tdev = %s\n\tvfs = %s\n\ttype = %s\n\tlog = %s\n\tvol = %s\n\topts = %s\n\tmount = true\n\tcheck = true\n\tfree = false\n",
+ dp->d_mountpt,
+ dp->d_dev,
+ dp->d_fstype,
+ dp->d_fstype,
+ dp->d_log,
+ dp->d_mountpt,
+ dp->d_opts);
+ XFREE(hp);
+}
+
+
+static void
+write_aix1_dkrmount(FILE *ef, char *hn, fsmount *fp)
+{
+ char *h = strdup(fp->f_ref->m_dk->d_host->h_hostname);
+ char *hp = strdup(h);
+ char *p = strchr(hp, '.');
+
+ if (p)
+ *p = '\0';
+ domain_strip(h, hn);
+ fprintf(ef, "\n%s:\n\tsite = %s\n\tdev = %s:%s\n\tvfs = %s\n\ttype = %s\n\tvol = %s\n\topts = %s\n\tmount = true\n\tcheck = true\n\tfree = false\n",
+ fp->f_localname,
+ hp,
+ h,
+ fp->f_volname,
+ fp->f_fstype,
+ fp->f_fstype,
+ fp->f_localname,
+ fp->f_opts);
+
+ XFREE(hp);
+ XFREE(h);
+}
+
+
+/* ---------- AIX 3 ------------------------------ */
+
+/*
+ * AIX 3 format
+ */
+static void
+write_aix3_dkfstab(FILE *ef, disk_fs *dp)
+{
+ if (STREQ(dp->d_fstype, "jfs") &&
+ NSTREQ(dp->d_dev, "/dev/", 5) &&
+ !dp->d_log)
+ error("aix 3 needs a log device for journalled filesystem (jfs) mounts");
+
+ fprintf(ef, "\n%s:\n\tdev = %s\n\tvfs = %s\n\ttype = %s\n\tlog = %s\n\tvol = %s\n\topts = %s\n\tmount = true\n\tcheck = true\n\tfree = false\n",
+ dp->d_mountpt,
+ dp->d_dev,
+ dp->d_fstype,
+ dp->d_fstype,
+ dp->d_log,
+ dp->d_mountpt,
+ dp->d_opts);
+}
+
+
+static void
+write_aix3_dkrmount(FILE *ef, char *hn, fsmount *fp)
+{
+ char *h = strdup(fp->f_ref->m_dk->d_host->h_hostname);
+
+ domain_strip(h, hn);
+ fprintf(ef, "\n%s:\n\tdev = %s:%s\n\tvfs = %s\n\ttype = %s\n\tvol = %s\n\topts = %s\n\tmount = true\n\tcheck = true\n\tfree = false\n",
+ fp->f_localname,
+ h,
+ fp->f_volname,
+ fp->f_fstype,
+ fp->f_fstype,
+ fp->f_localname,
+ fp->f_opts);
+
+ XFREE(h);
+}
+
+
+/* ---------- Ultrix ----------------------------- */
+
+static void
+write_ultrix_dkfstab(FILE *ef, disk_fs *dp)
+{
+ fprintf(ef, "%s:%s:%s:%s:%d:%d\n",
+ dp->d_dev,
+ dp->d_mountpt,
+ dp->d_fstype,
+ dp->d_opts,
+ dp->d_freq,
+ dp->d_passno);
+}
+
+
+static void
+write_ultrix_dkrmount(FILE *ef, char *hn, fsmount *fp)
+{
+ char *h = strdup(fp->f_ref->m_dk->d_host->h_hostname);
+
+ domain_strip(h, hn);
+ fprintf(ef, "%s@%s:%s:%s:%s:0:0\n",
+ fp->f_volname,
+ h,
+ fp->f_localname,
+ fp->f_fstype,
+ fp->f_opts);
+ XFREE(h);
+}
+
+
+/* ---------- Generic ---------------------------- */
+
+/*
+ * Generic (BSD, SunOS, HPUX) format
+ */
+static void
+write_generic_dkfstab(FILE *ef, disk_fs *dp)
+{
+ fprintf(ef, "%s %s %s %s %d %d\n",
+ dp->d_dev,
+ dp->d_mountpt,
+ dp->d_fstype,
+ dp->d_opts,
+ dp->d_freq,
+ dp->d_passno);
+}
+
+
+static void
+write_generic_dkrmount(FILE *ef, char *hn, fsmount *fp)
+{
+ char *h;
+
+ if (fp->f_ref) {
+ h = strdup(fp->f_ref->m_dk->d_host->h_hostname);
+ } else {
+ h = strdup(fp->f_from);
+ }
+ domain_strip(h, hn);
+ fprintf(ef, "%s:%s %s %s %s 0 0\n",
+ h,
+ fp->f_volname,
+ fp->f_localname,
+ fp->f_fstype,
+ fp->f_opts);
+ XFREE(h);
+}
+
+
+static struct os_fstab_type *
+find_fstab_type(host *hp)
+{
+ struct os_fstab_type *op = 0;
+ char *os_name = 0;
+
+again:;
+ if (os_name == 0) {
+ if (ISSET(hp->h_mask, HF_OS))
+ os_name = hp->h_os;
+ else
+ os_name = GENERIC_OS_NAME;
+ }
+ for (op = os_tabs; op->os_name; op++)
+ if (STREQ(os_name, op->os_name))
+ return op;
+
+ os_name = GENERIC_OS_NAME;
+ goto again;
+}
+
+
+static int
+write_dkfstab(FILE *ef, qelem *q, void (*output) (FILE *, disk_fs *))
+{
+ int errors = 0;
+ disk_fs *dp;
+
+ ITER(dp, disk_fs, q)
+ if (!STREQ(dp->d_fstype, "export"))
+ (*output) (ef, dp);
+
+ return errors;
+}
+
+
+static int
+write_dkrmount(FILE *ef, qelem *q, char *hn, void (*output) (FILE *, char *, fsmount *))
+{
+ int errors = 0;
+ fsmount *fp;
+
+ ITER(fp, fsmount, q)
+ (*output) (ef, hn, fp);
+
+ return errors;
+}
+
+
+int
+write_fstab(qelem *q)
+{
+ int errors = 0;
+
+ if (fstab_pref) {
+ host *hp;
+
+ show_area_being_processed("write fstab", 4);
+ ITER(hp, host, q) {
+ if (hp->h_disk_fs || hp->h_mount) {
+ FILE *ef = pref_open(fstab_pref, hp->h_hostname, gen_hdr, hp->h_hostname);
+ if (ef) {
+ struct os_fstab_type *op = find_fstab_type(hp);
+ show_new(hp->h_hostname);
+ if (hp->h_disk_fs)
+ errors += write_dkfstab(ef, hp->h_disk_fs, op->op_fstab);
+ else
+ log("No local disk mounts on %s", hp->h_hostname);
+
+ if (hp->h_mount)
+ errors += write_dkrmount(ef, hp->h_mount, hp->h_hostname, op->op_mount);
+
+ pref_close(ef);
+ }
+ } else {
+ error("no disk mounts on %s", hp->h_hostname);
+ }
+ }
+ }
+ return errors;
+}
OpenPOWER on IntegriCloud