diff options
author | Pedro F. Giffuni <pfg@FreeBSD.org> | 2015-01-28 22:55:06 +0000 |
---|---|---|
committer | Pedro F. Giffuni <pfg@FreeBSD.org> | 2015-01-28 22:55:06 +0000 |
commit | e925d4a747df4a349c2baac436a71f606945baa5 (patch) | |
tree | e3a2ccc21623f0453c6f43f9016535205ba10d21 /contrib/amd/amd | |
parent | 509fcedcfec077a6070002f4059db0ae675be869 (diff) | |
download | src-e925d4a747df4a349c2baac436a71f606945baa5.tar.gz src-e925d4a747df4a349c2baac436a71f606945baa5.zip |
amd: flatten the tree
Notes
Notes:
svn path=/vendor/amd/dist/; revision=277863
Diffstat (limited to 'contrib/amd/amd')
64 files changed, 0 insertions, 25993 deletions
diff --git a/contrib/amd/amd/am_ops.c b/contrib/amd/amd/am_ops.c deleted file mode 100644 index 5a5c33650eca..000000000000 --- a/contrib/amd/amd/am_ops.c +++ /dev/null @@ -1,475 +0,0 @@ -/* - * Copyright (c) 1997-2006 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 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. - * - * - * File: am-utils/amd/am_ops.c - * - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - - -/* - * The order of these entries matters, since lookups in this table are done - * on a first-match basis. The entries below are a mixture of native - * filesystems supported by the OS (HAVE_FS_FOO), and some meta-filesystems - * supported by amd (HAVE_AMU_FS_FOO). The order is set here in expected - * match-hit such that more popular filesystems are listed first (nfs is the - * most popular, followed by a symlink F/S) - */ -static am_ops *vops[] = -{ -#ifdef HAVE_FS_NFS - &nfs_ops, /* network F/S (version 2) */ -#endif /* HAVE_FS_NFS */ -#ifdef HAVE_AMU_FS_LINK - &amfs_link_ops, /* symlink F/S */ -#endif /* HAVE_AMU_FS_LINK */ - - /* - * Other amd-supported meta-filesystems. - */ -#ifdef HAVE_AMU_FS_NFSX - &amfs_nfsx_ops, /* multiple-nfs F/S */ -#endif /* HAVE_AMU_FS_NFSX */ -#ifdef HAVE_AMU_FS_NFSL - &amfs_nfsl_ops, /* NFS with local link existence check */ -#endif /* HAVE_AMU_FS_NFSL */ -#ifdef HAVE_AMU_FS_HOST - &amfs_host_ops, /* multiple exported nfs F/S */ -#endif /* HAVE_AMU_FS_HOST */ -#ifdef HAVE_AMU_FS_LINKX - &amfs_linkx_ops, /* symlink F/S with link target verify */ -#endif /* HAVE_AMU_FS_LINKX */ -#ifdef HAVE_AMU_FS_PROGRAM - &amfs_program_ops, /* program F/S */ -#endif /* HAVE_AMU_FS_PROGRAM */ -#ifdef HAVE_AMU_FS_UNION - &amfs_union_ops, /* union F/S */ -#endif /* HAVE_AMU_FS_UNION */ - - /* - * A few more native filesystems. - */ -#ifdef HAVE_FS_UFS - &ufs_ops, /* Unix F/S */ -#endif /* HAVE_FS_UFS */ -#ifdef HAVE_FS_XFS - &xfs_ops, /* Unix (irix) F/S */ -#endif /* HAVE_FS_XFS */ -#ifdef HAVE_FS_EFS - &efs_ops, /* Unix (irix) F/S */ -#endif /* HAVE_FS_EFS */ -#ifdef HAVE_FS_LOFS - &lofs_ops, /* loopback F/S */ -#endif /* HAVE_FS_LOFS */ -#ifdef HAVE_FS_CDFS - &cdfs_ops, /* CDROM/HSFS/ISO9960 F/S */ -#endif /* HAVE_FS_CDFS */ -#ifdef HAVE_FS_PCFS - &pcfs_ops, /* Floppy/MSDOS F/S */ -#endif /* HAVE_FS_PCFS */ -#ifdef HAVE_FS_CACHEFS - &cachefs_ops, /* caching F/S */ -#endif /* HAVE_FS_CACHEFS */ -#ifdef HAVE_FS_NULLFS -/* FILL IN */ /* null (loopback) F/S */ -#endif /* HAVE_FS_NULLFS */ -#ifdef HAVE_FS_UNIONFS -/* FILL IN */ /* union (bsd44) F/S */ -#endif /* HAVE_FS_UNIONFS */ -#ifdef HAVE_FS_UMAPFS -/* FILL IN */ /* uid/gid mapping F/S */ -#endif /* HAVE_FS_UMAPFS */ - - /* - * These 4 should be last, in the order: - * (1) amfs_auto - * (2) amfs_direct - * (3) amfs_toplvl - * (4) amfs_error - */ -#ifdef HAVE_AMU_FS_AUTO - &amfs_auto_ops, /* Automounter F/S */ -#endif /* HAVE_AMU_FS_AUTO */ -#ifdef HAVE_AMU_FS_DIRECT - &amfs_direct_ops, /* direct-mount F/S */ -#endif /* HAVE_AMU_FS_DIRECT */ -#ifdef HAVE_AMU_FS_TOPLVL - &amfs_toplvl_ops, /* top-level mount F/S */ -#endif /* HAVE_AMU_FS_TOPLVL */ -#ifdef HAVE_AMU_FS_ERROR - &amfs_error_ops, /* error F/S */ -#endif /* HAVE_AMU_FS_ERROR */ - 0 -}; - - -void -ops_showamfstypes(char *buf, size_t l) -{ - struct am_ops **ap; - int linesize = 0; - - buf[0] = '\0'; - for (ap = vops; *ap; ap++) { - xstrlcat(buf, (*ap)->fs_type, l); - if (ap[1]) - xstrlcat(buf, ", ", l); - linesize += strlen((*ap)->fs_type) + 2; - if (linesize > 62) { - linesize = 0; - xstrlcat(buf, "\n ", l); - } - } -} - - -static void -ops_show1(char *buf, size_t l, int *linesizep, const char *name) -{ - xstrlcat(buf, name, l); - xstrlcat(buf, ", ", l); - *linesizep += strlen(name) + 2; - if (*linesizep > 60) { - xstrlcat(buf, "\t\n", l); - *linesizep = 0; - } -} - - -void -ops_showfstypes(char *buf, size_t l) -{ - int linesize = 0; - - buf[0] = '\0'; - -#ifdef MNTTAB_TYPE_AUTOFS - ops_show1(buf, l, &linesize, MNTTAB_TYPE_AUTOFS); -#endif /* MNTTAB_TYPE_AUTOFS */ - -#ifdef MNTTAB_TYPE_CACHEFS - ops_show1(buf, l, &linesize, MNTTAB_TYPE_CACHEFS); -#endif /* MNTTAB_TYPE_CACHEFS */ - -#ifdef MNTTAB_TYPE_CDFS - ops_show1(buf, l, &linesize, MNTTAB_TYPE_CDFS); -#endif /* MNTTAB_TYPE_CDFS */ - -#ifdef MNTTAB_TYPE_CFS - ops_show1(buf, l, &linesize, MNTTAB_TYPE_CFS); -#endif /* MNTTAB_TYPE_CFS */ - -#ifdef MNTTAB_TYPE_LOFS - ops_show1(buf, l, &linesize, MNTTAB_TYPE_LOFS); -#endif /* MNTTAB_TYPE_LOFS */ - -#ifdef MNTTAB_TYPE_EFS - ops_show1(buf, l, &linesize, MNTTAB_TYPE_EFS); -#endif /* MNTTAB_TYPE_EFS */ - -#ifdef MNTTAB_TYPE_MFS - ops_show1(buf, l, &linesize, MNTTAB_TYPE_MFS); -#endif /* MNTTAB_TYPE_MFS */ - -#ifdef MNTTAB_TYPE_NFS - ops_show1(buf, l, &linesize, MNTTAB_TYPE_NFS); -#endif /* MNTTAB_TYPE_NFS */ - -#ifdef MNTTAB_TYPE_NFS3 - ops_show1(buf, l, &linesize, "nfs3"); /* always hard-code as nfs3 */ -#endif /* MNTTAB_TYPE_NFS3 */ - -#ifdef MNTTAB_TYPE_NULLFS - ops_show1(buf, l, &linesize, MNTTAB_TYPE_NULLFS); -#endif /* MNTTAB_TYPE_NULLFS */ - -#ifdef MNTTAB_TYPE_PCFS - ops_show1(buf, l, &linesize, MNTTAB_TYPE_PCFS); -#endif /* MNTTAB_TYPE_PCFS */ - -#ifdef MNTTAB_TYPE_TFS - ops_show1(buf, l, &linesize, MNTTAB_TYPE_TFS); -#endif /* MNTTAB_TYPE_TFS */ - -#ifdef MNTTAB_TYPE_TMPFS - ops_show1(buf, l, &linesize, MNTTAB_TYPE_TMPFS); -#endif /* MNTTAB_TYPE_TMPFS */ - -#ifdef MNTTAB_TYPE_UFS - ops_show1(buf, l, &linesize, MNTTAB_TYPE_UFS); -#endif /* MNTTAB_TYPE_UFS */ - -#ifdef MNTTAB_TYPE_UMAPFS - ops_show1(buf, l, &linesize, MNTTAB_TYPE_UMAPFS); -#endif /* MNTTAB_TYPE_UMAPFS */ - -#ifdef MNTTAB_TYPE_UNIONFS - ops_show1(buf, l, &linesize, MNTTAB_TYPE_UNIONFS); -#endif /* MNTTAB_TYPE_UNIONFS */ - -#ifdef MNTTAB_TYPE_XFS - ops_show1(buf, l, &linesize, MNTTAB_TYPE_XFS); -#endif /* MNTTAB_TYPE_XFS */ - - /* terminate with a period, newline, and NULL */ - if (buf[strlen(buf)-1] == '\n') - buf[strlen(buf) - 4] = '\0'; - else - buf[strlen(buf) - 2] = '\0'; - xstrlcat(buf, ".\n", l); -} - - -/* - * return string option which is the reverse of opt. - * nosuid -> suid - * quota -> noquota - * ro -> rw - * etc. - * may return pointer to static buffer or subpointer within opt. - */ -static char * -reverse_option(const char *opt) -{ - static char buf[80]; - - /* sanity check */ - if (!opt) - return NULL; - - /* check special cases */ - /* XXX: if this gets too long, rewrite the code more flexibly */ - if (STREQ(opt, "ro")) return "rw"; - if (STREQ(opt, "rw")) return "ro"; - if (STREQ(opt, "bg")) return "fg"; - if (STREQ(opt, "fg")) return "bg"; - if (STREQ(opt, "soft")) return "hard"; - if (STREQ(opt, "hard")) return "soft"; - - /* check if string starts with 'no' and chop it */ - if (NSTREQ(opt, "no", 2)) { - xstrlcpy(buf, &opt[2], sizeof(buf)); - } else { - /* finally return a string prepended with 'no' */ - xstrlcpy(buf, "no", sizeof(buf)); - xstrlcat(buf, opt, sizeof(buf)); - } - return buf; -} - - -/* - * start with an empty string. for each opts1 option that is not - * in opts2, add it to the string (make sure the reverse of it - * isn't in either). finally add opts2. return new string. - * Both opts1 and opts2 must not be null! - * Caller must eventually free the string being returned. - */ -static char * -merge_opts(const char *opts1, const char *opts2) -{ - mntent_t mnt2; /* place holder for opts2 */ - char *newstr; /* new string to return (malloc'ed) */ - char *tmpstr; /* temp */ - char *eq; /* pointer to whatever follows '=' within temp */ - char oneopt[80]; /* one option w/o value if any */ - char *revoneopt; /* reverse of oneopt */ - size_t len = strlen(opts1) + strlen(opts2) + 2; /* space for "," and NULL */ - char *s1 = strdup(opts1); /* copy of opts1 to munge */ - - /* initialization */ - mnt2.mnt_opts = (char *) opts2; - newstr = xmalloc(len); - newstr[0] = '\0'; - - for (tmpstr = strtok(s1, ","); - tmpstr; - tmpstr = strtok(NULL, ",")) { - /* copy option to temp buffer */ - xstrlcpy(oneopt, tmpstr, 80); - /* if option has a value such as rsize=1024, chop the value part */ - if ((eq = haseq(oneopt))) - *eq = '\0'; - /* find reverse option of oneopt */ - revoneopt = reverse_option(oneopt); - /* if option orits reverse exist in opts2, ignore it */ - if (amu_hasmntopt(&mnt2, oneopt) || amu_hasmntopt(&mnt2, revoneopt)) - continue; - /* add option to returned string */ - if (newstr[0]) { - xstrlcat(newstr, ",", len); - xstrlcat(newstr, tmpstr, len); - } else { - xstrlcpy(newstr, tmpstr, len); - } - } - - /* finally, append opts2 itself */ - if (newstr[0]) { - xstrlcat(newstr, ",", len); - xstrlcat(newstr, opts2, len); - } else { - xstrlcpy(newstr, opts2, len); - } - - XFREE(s1); - return newstr; -} - - -am_ops * -ops_search(char *type) -{ - am_ops **vp; - am_ops *rop = 0; - for (vp = vops; (rop = *vp); vp++) - if (STREQ(rop->fs_type, type)) - break; - return rop; -} - - -am_ops * -ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map) -{ - am_ops *rop = 0; - char *link_dir; - - /* - * First crack the global opts and the local opts - */ - if (!eval_fs_opts(fo, key, g_key, path, keym, map)) { - rop = &amfs_error_ops; - } else if (fo->opt_type == 0) { - plog(XLOG_USER, "No fs type specified (key = \"%s\", map = \"%s\")", keym, map); - rop = &amfs_error_ops; - } else { - /* - * Next find the correct filesystem type - */ - rop = ops_search(fo->opt_type); - if (!rop) { - plog(XLOG_USER, "fs type \"%s\" not recognized", fo->opt_type); - rop = &amfs_error_ops; - } - } - - /* - * Make sure we have a default mount option. - * Otherwise skip past any leading '-'. - */ - if (fo->opt_opts == 0) - fo->opt_opts = strdup("rw,defaults"); - else if (*fo->opt_opts == '-') { - /* - * We cannot simply do fo->opt_opts++ here since the opts - * module will try to free the pointer fo->opt_opts later. - * So just reallocate the thing -- stolcke 11/11/94 - */ - char *old = fo->opt_opts; - fo->opt_opts = strdup(old + 1); - XFREE(old); - } - - /* - * If addopts option was used, then append it to the - * current options and remote mount options. - */ - if (fo->opt_addopts) { - if (STREQ(fo->opt_opts, fo->opt_remopts)) { - /* optimize things for the common case where opts==remopts */ - char *mergedstr; - mergedstr = merge_opts(fo->opt_opts, fo->opt_addopts); - plog(XLOG_INFO, "merge rem/opts \"%s\" add \"%s\" => \"%s\"", - fo->opt_opts, fo->opt_addopts, mergedstr); - XFREE(fo->opt_opts); - XFREE(fo->opt_remopts); - fo->opt_opts = mergedstr; - fo->opt_remopts = strdup(mergedstr); - } else { - char *mergedstr, *remmergedstr; - mergedstr = merge_opts(fo->opt_opts, fo->opt_addopts); - plog(XLOG_INFO, "merge opts \"%s\" add \"%s\" => \"%s\"", - fo->opt_opts, fo->opt_addopts, mergedstr); - XFREE(fo->opt_opts); - fo->opt_opts = mergedstr; - remmergedstr = merge_opts(fo->opt_remopts, fo->opt_addopts); - plog(XLOG_INFO, "merge remopts \"%s\" add \"%s\" => \"%s\"", - fo->opt_remopts, fo->opt_addopts, remmergedstr); - XFREE(fo->opt_remopts); - fo->opt_remopts = remmergedstr; - } - } - - /* - * Initialize opt_mount_type to "nfs", if it's not initialized already - */ - if (!fo->opt_mount_type) - fo->opt_mount_type = "nfs"; - - /* Normalize the sublink and make it absolute */ - link_dir = fo->opt_sublink; - if (link_dir && link_dir[0] && link_dir[0] != '/') { - link_dir = str3cat((char *) 0, fo->opt_fs, "/", link_dir); - normalize_slash(link_dir); - XFREE(fo->opt_sublink); - fo->opt_sublink = link_dir; - } - - /* - * Check the filesystem is happy - */ - if (fo->fs_mtab) - XFREE(fo->fs_mtab); - - fo->fs_mtab = rop->fs_match(fo); - if (fo->fs_mtab) - return rop; - - /* - * Return error file system - */ - fo->fs_mtab = amfs_error_ops.fs_match(fo); - return &amfs_error_ops; -} diff --git a/contrib/amd/amd/amd.8 b/contrib/amd/amd/amd.8 deleted file mode 100644 index 565a5505b8c2..000000000000 --- a/contrib/amd/amd/amd.8 +++ /dev/null @@ -1,371 +0,0 @@ -.\" -.\" Copyright (c) 1997-2006 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 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. -.\" -.\" %W% (Berkeley) %G% -.\" -.\" $Id: amd.8,v 1.14.2.1 2006/01/02 18:48:23 ezk Exp $ -.\" -.TH AMD 8 "3 November 1989" -.SH NAME -amd \- automatically mount file systems -.SH SYNOPSIS -.B amd -.B \-H -.br -.B amd -[ -.BI \-F " conf_file" -] -.br -.B amd -[ -.B \-nprvHS -] [ -.BI \-a " mount_point" -] [ -.BI \-c " duration" -] [ -.BI \-d " domain" -] [ -.BI \-k " kernel-arch" -] [ -.BI \-l " logfile" -] [ -.BI \-o " op_sys_ver" -] [ -.BI \-t " interval.interval" -] [ -.BI \-w " interval" -] [ -.BI \-x " log-option" -] [ -.BI \-y " YP-domain" -] [ -.BI \-A " arch" -] [ -.BI \-C " cluster-name" -] [ -.BI \-D " option" -] [ -.BI \-F " conf_file" -] [ -.BI \-O " op_sys_name" -] [ -.BI \-T " tag" -] -[ -.I directory -.I mapname -.RI [ " \-map-options " ] -] .\|.\|. -.SH DESCRIPTION -.B Amd -is a daemon that automatically mounts filesystems -whenever a file or directory -within that filesystem is accessed. -Filesystems are automatically unmounted when they -appear to have become quiescent. -.LP -.B Amd -operates by attaching itself as an -.SM NFS -server to each of the specified -.IB directories . -Lookups within the specified directories -are handled by -.BR amd , -which uses the map defined by -.I mapname -to determine how to resolve the lookup. -Generally, this will be a host name, some filesystem information -and some mount options for the given filesystem. -.LP -In the first form depicted above, -.B amd -will print a short help string. In the second form, if no options are -specified, or the -.B -F -is used, -.B amd -will read configuration parameters from the file -.I conf_file -which defaults to -.BR /etc/amd.conf . -The last form is described below. -.SH OPTIONS - -.\"*******************************************************" - -.TP -.BI \-a " temporary-directory" -Specify an alternative location for the real mount points. -The default is -.BR /a . - -.TP -.BI \-c " duration" -Specify a -.IR duration , -in seconds, that a looked up name remains -cached when not in use. The default is 5 minutes. - -.TP -.BI \-d " domain" -Specify the local domain name. If this option is not -given the domain name is determined from the hostname. - -.TP -.BI \-k " kernel-arch" -Specifies the kernel architecture. This is used solely -to set the ${karch} selector. - -.TP -.BI \-l " logfile" -Specify a logfile in which to record mount and unmount events. -If -.I logfile -is the string -.B syslog -then the log messages will be sent to the system log daemon by -.IR syslog (3). -The default syslog facility used is LOG_DAEMON. If you -wish to change it, append its name to the log file name, delimited by a -single colon. For example, if -.I logfile -is the string -.B syslog:local7 -then -.B Amd -will log messages via -.IR syslog (3) -using the LOG_LOCAL7 facility (if it exists on the system). - -.TP -.B \-n -Normalize hostnames. -The name refereed to by ${rhost} is normalized relative to the -host database before being used. The effect is to translate -aliases into ``official'' names. - -.TP -.BI \-o " op_sys_ver" -Override the compiled-in version number of the operating system. Useful -when the built in version is not desired for backward compatibility reasons. -For example, if the build in version is ``2.5.1'', you can override it to -``5.5.1'', and use older maps that were written with the latter in mind. - -.TP -.B \-p -Print PID. -Outputs the process-id of -.B amd -to standard output where it can be saved into a file. - -.TP -.B \-r -Restart existing mounts. -.B Amd -will scan the mount file table to determine which filesystems -are currently mounted. Whenever one of these would have -been auto-mounted, -.B amd -.I inherits -it. - -.TP -.BI \-t " timeout.retransmit" -Specify the NFS timeout -.IR interval , -in tenths of a second, between NFS/RPC retries (for UDP only). The default -is 0.8 seconds. The second value alters the retransmit counter, which -defaults to 11 retransmissions. Both of these values are used by the kernel -to communicate with amd. Useful defaults are supplied if either or both -values are missing. - -Amd relies on the kernel RPC retransmit mechanism to trigger mount retries. -The values of these parameters change the overall retry interval. Too long -an interval gives poor interactive response; too short an interval causes -excessive retries. - -.TP -.B \-v -Version. Displays version and configuration information on standard error. - -.TP -.BI \-w " interval" -Specify an -.IR interval , -in seconds, between attempts to dismount -filesystems that have exceeded their cached times. -The default is 2 minutes. - -.TP -.BI \-x " options" -Specify run-time logging options. The options are a comma separated -list chosen from: fatal, error, user, warn, info, map, stats, all. - -.TP -.BI \-y " domain" -Specify an alternative NIS domain from which to fetch the NIS maps. -The default is the system domain name. This option is ignored if NIS -support is not available. - -.TP -.BI \-A " arch" -Specifies the OS architecture. This is used solely to set the ${arch} -selector. - -.TP -.BI \-C " cluster-name" -Specify an alternative HP-UX cluster name to use. - -.TP -.BI \-D " option" -Select from a variety of debug options. Prefixing an -option with the strings -.B no -reverses the effect of that option. Options are cumulative. -The most useful option is -.BR all . -Since -.I \-D -is only used for debugging other options are not documented here: -the current supported set of options is listed by the \-v option -and a fuller description is available in the program source. - -.TP -.BI \-F " conf_file" -Specify an amd configuration file to use. See -.BR amd.conf (5) -for description of this file's format. This configuration file is used to -specify any options in lieu of typing many of them on the command line. The -.I amd.conf -file includes directives for every command line option amd has, and many -more that are only available via the configuration file facility. The -configuration file specified by this option is processed after all other -options had been processed, regardless of the actual location of this option -on the command line. - -.TP -.B \-H -Print help and usage string. - -.TP -.BI \-O " op_sys_name" -Override the compiled-in name of the operating system. Useful when the -built in name is not desired for backward compatibility reasons. For -example, if the build in name is ``sunos5'', you can override it to -``sos5'', and use older maps which were written with the latter in mind. - -.TP -.B \-S -Do not lock the running executable pages of amd into memory. To improve -amd's performance, systems that support the -.BR plock (3) -call, could lock the amd process into memory. This way there is less chance -the operating system will schedule, page out, and swap the amd process as -needed. This tends improves amd's performance, at the cost of reserving the -memory used by the amd process (making it unavailable for other processes). -If this behavior is not desired, use the -.B \-S -option. - -.TP -.BI \-T " tag" -Specify a tag to use with -.BR amd.conf (5). -All map entries tagged with -.I tag -will be processed. Map entries that are not tagged are always processed. -Map entries that are tagged with a tag other than -.I tag -will not be processed. - -.SH FILES -.TP 5 -.B /a -directory under which filesystems are dynamically mounted -.TP 5 -.B /etc/amd.conf -default configuration file -.SH CAVEATS -Some care may be required when creating a mount map. -.LP -Symbolic links on an NFS filesystem can be incredibly inefficient. -In most implementations of NFS, their interpolations are not cached -by the kernel and each time a symlink is encountered during a -.I lookuppn -translation it costs an RPC call to the NFS server. -It would appear that a large improvement in real-time -performance could be gained by adding a cache somewhere. -Replacing symlinks with a suitable incarnation of the auto-mounter -results in a large real-time speedup, but also causes a large -number of process context switches. -.LP -A weird imagination is most useful to gain full advantage of all -the features. -.SH "SEE ALSO" -.BR amd.conf (5), -.BR amq (8), -.BR domainname (1), -.BR hostname (1), -.BR automount (8), -.BR mount (8), -.BR umount (8), -.BR mtab (5), -.BR syslog (3). -.LP -``am-utils'' -.BR info (1) -entry. -.LP -.I "Linux NFS and Automounter Administration" -by Erez Zadok, ISBN 0-7821-2739-8, (Sybex, 2001). -.LP -.I http://www.am-utils.org -.LP -.I "Amd \- The 4.4 BSD Automounter" -.SH AUTHORS -Jan-Simon Pendry <jsp@doc.ic.ac.uk>, Department of Computing, Imperial College, London, UK. -.P -Erez Zadok <ezk@cs.sunysb.edu>, Computer Science Department, Stony Brook -University, Stony Brook, New York, USA. -.P -Other authors and contributors to am-utils are listed in the -.B AUTHORS -file distributed with am-utils. diff --git a/contrib/amd/amd/amd.c b/contrib/amd/amd/amd.c deleted file mode 100644 index 37eab5d8442c..000000000000 --- a/contrib/amd/amd/amd.c +++ /dev/null @@ -1,577 +0,0 @@ -/* - * Copyright (c) 1997-2006 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 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. - * - * - * File: am-utils/amd/amd.c - * - */ - -/* - * Automounter - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -struct amu_global_options gopt; /* where global options are stored */ - -char pid_fsname[SIZEOF_PID_FSNAME]; /* "kiska.southseas.nz:(pid%d)" */ -char *hostdomain = "unknown.domain"; -#define SIZEOF_HOSTD (2 * MAXHOSTNAMELEN + 1) /* Host+domain */ -char hostd[SIZEOF_HOSTD]; /* Host+domain */ -char *endian = ARCH_ENDIAN; /* Big or Little endian */ -char *cpu = HOST_CPU; /* CPU type */ -char *PrimNetName; /* name of primary network */ -char *PrimNetNum; /* number of primary network */ - -int immediate_abort; /* Should close-down unmounts be retried */ -int orig_umask = 022; -int select_intr_valid; - -jmp_buf select_intr; -struct amd_stats amd_stats; /* Server statistics */ -struct in_addr myipaddr; /* (An) IP address of this host */ -time_t do_mapc_reload = 0; /* mapc_reload() call required? */ - -#ifdef HAVE_FS_AUTOFS -int amd_use_autofs = 0; -#endif /* HAVE_FS_AUTOFS */ - -#ifdef HAVE_SIGACTION -sigset_t masked_sigs; -#endif /* HAVE_SIGACTION */ - - -/* - * Signal handler: - * SIGINT - tells amd to do a full shutdown, including unmounting all - * filesystem. - * SIGTERM - tells amd to shutdown now. Just unmounts the automount nodes. - */ -static RETSIGTYPE -sigterm(int sig) -{ -#ifdef REINSTALL_SIGNAL_HANDLER - signal(sig, sigterm); -#endif /* REINSTALL_SIGNAL_HANDLER */ - - switch (sig) { - case SIGINT: - immediate_abort = 15; - break; - - case SIGTERM: - immediate_abort = -1; - /* fall through... */ - - default: - plog(XLOG_WARNING, "WARNING: automounter going down on signal %d", sig); - break; - } - if (select_intr_valid) - longjmp(select_intr, sig); -} - - -/* - * Hook for cache reload. - * When a SIGHUP arrives it schedules a call to mapc_reload - */ -static RETSIGTYPE -sighup(int sig) -{ -#ifdef REINSTALL_SIGNAL_HANDLER - signal(sig, sighup); -#endif /* REINSTALL_SIGNAL_HANDLER */ - - if (sig != SIGHUP) - dlog("spurious call to sighup"); - /* - * Force a reload by zero'ing the timer - */ - if (amd_state == Run) - do_mapc_reload = 0; -} - - -static RETSIGTYPE -parent_exit(int sig) -{ - /* - * This signal handler is called during Amd initialization. The parent - * forks a child to do all the hard automounting work, and waits for a - * SIGQUIT signal from the child. When the parent gets the signal it's - * supposed to call this handler and exit(3), thus completing the - * daemonizing process. Alas, on some systems, especially Linux 2.4/2.6 - * with Glibc, exit(3) doesn't always terminate the parent process. - * Worse, the parent process now refuses to accept any more SIGQUIT - * signals -- they are blocked. What's really annoying is that this - * doesn't happen all the time, suggesting a race condition somewhere. - * (This happens even if I change the logic to use another signal.) I - * traced this to something which exit(3) does in addition to exiting the - * process, probably some atexit() stuff or other side-effects related to - * signal handling. Either way, since at this stage the parent process - * just needs to terminate, I'm simply calling _exit(2). Note also that - * the OpenGroup doesn't list exit(3) as a recommended "Base Interface" - * but they do list _exit(2) as one. This fix seems to work reliably all - * the time. -Erez (2/27/2005) - */ - _exit(0); -} - - -static int -daemon_mode(void) -{ - int bgpid; - -#ifdef HAVE_SIGACTION - struct sigaction sa, osa; - - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = parent_exit; - sa.sa_flags = 0; - sigemptyset(&(sa.sa_mask)); - sigaddset(&(sa.sa_mask), SIGQUIT); - sigaction(SIGQUIT, &sa, &osa); -#else /* not HAVE_SIGACTION */ - signal(SIGQUIT, parent_exit); -#endif /* not HAVE_SIGACTION */ - - bgpid = background(); - - if (bgpid != 0) { - /* - * Now wait for the automount points to - * complete. - */ - for (;;) - pause(); - /* should never reach here */ - } -#ifdef HAVE_SIGACTION - sigaction(SIGQUIT, &osa, NULL); -#else /* not HAVE_SIGACTION */ - signal(SIGQUIT, SIG_DFL); -#endif /* not HAVE_SIGACTION */ - - /* - * Record our pid to make it easier to kill the correct amd. - */ - if (gopt.flags & CFM_PRINT_PID) { - if (STREQ(gopt.pid_file, "/dev/stdout")) { - printf("%ld\n", (long) am_mypid); - /* flush stdout, just in case */ - fflush(stdout); - } else { - FILE *f; - mode_t prev_umask = umask(0022); /* set secure temporary umask */ - - f = fopen(gopt.pid_file, "w"); - if (f) { - fprintf(f, "%ld\n", (long) am_mypid); - (void) fclose(f); - } else { - fprintf(stderr, "cannot open %s (errno=%d)\n", gopt.pid_file, errno); - } - umask(prev_umask); /* restore umask */ - } - } - - /* - * Pretend we are in the foreground again - */ - foreground = 1; - - /* - * Dissociate from the controlling terminal - */ - amu_release_controlling_tty(); - - return getppid(); -} - - -/* - * Initialize global options structure. - */ -static void -init_global_options(void) -{ -#if defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME) - static struct utsname un; -#endif /* defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME) */ - int i; - - memset(&gopt, 0, sizeof(struct amu_global_options)); - - /* name of current architecture */ - gopt.arch = HOST_ARCH; - - /* automounter temp dir */ - gopt.auto_dir = "/a"; - - /* toplevel attribute cache timeout */ - gopt.auto_attrcache = 0; - - /* cluster name */ - gopt.cluster = NULL; - - /* executable map timeout */ - gopt.exec_map_timeout = AMFS_EXEC_MAP_TIMEOUT; - - /* - * kernel architecture: this you must get from uname() if possible. - */ -#if defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME) - if (uname(&un) >= 0) - gopt.karch = un.machine; - else -#endif /* defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME) */ - gopt.karch = HOST_ARCH; - - /* amd log file */ - gopt.logfile = NULL; - - /* operating system name */ - gopt.op_sys = HOST_OS_NAME; - - /* OS version */ - gopt.op_sys_ver = HOST_OS_VERSION; - - /* full OS name and version */ - gopt.op_sys_full = HOST_OS; - - /* OS version */ - gopt.op_sys_vendor = HOST_VENDOR; - - /* pid file */ - gopt.pid_file = "/dev/stdout"; - - /* local domain */ - gopt.sub_domain = NULL; - - /* reset NFS (and toplvl) retransmit counter and retry interval */ - for (i=0; i<AMU_TYPE_MAX; ++i) { - gopt.amfs_auto_retrans[i] = -1; /* -1 means "never set before" */ - gopt.amfs_auto_timeo[i] = -1; /* -1 means "never set before" */ - } - - /* cache duration */ - gopt.am_timeo = AM_TTL; - - /* dismount interval */ - gopt.am_timeo_w = AM_TTL_W; - - /* map reload intervl */ - gopt.map_reload_interval = ONE_HOUR; - - /* - * various CFM_* flags that are on by default. - */ - gopt.flags = CFM_DEFAULT_FLAGS; - -#ifdef HAVE_MAP_HESIOD - /* Hesiod rhs zone */ - gopt.hesiod_base = "automount"; -#endif /* HAVE_MAP_HESIOD */ - -#ifdef HAVE_MAP_LDAP - /* LDAP base */ - gopt.ldap_base = NULL; - - /* LDAP host ports */ - gopt.ldap_hostports = NULL; - - /* LDAP cache */ - gopt.ldap_cache_seconds = 0; - gopt.ldap_cache_maxmem = 131072; - - /* LDAP protocol version */ - gopt.ldap_proto_version = 2; -#endif /* HAVE_MAP_LDAP */ - -#ifdef HAVE_MAP_NIS - /* YP domain name */ - gopt.nis_domain = NULL; -#endif /* HAVE_MAP_NIS */ -} - - -/* - * Lock process text and data segment in memory (after forking the daemon) - */ -static void -do_memory_locking(void) -{ -#if defined(HAVE_PLOCK) || defined(HAVE_MLOCKALL) - int locked_ok = 0; -#else /* not HAVE_PLOCK and not HAVE_MLOCKALL */ - plog(XLOG_WARNING, "Process memory locking not supported by the OS"); -#endif /* not HAVE_PLOCK and not HAVE_MLOCKALL */ -#ifdef HAVE_PLOCK -# ifdef _AIX - /* - * On AIX you must lower the stack size using ulimit() before calling - * plock. Otherwise plock will reserve a lot of memory space based on - * your maximum stack size limit. Since it is not easily possible to - * tell what should the limit be, I print a warning before calling - * plock(). See the manual pages for ulimit(1,3,4) on your AIX system. - */ - plog(XLOG_WARNING, "AIX: may need to lower stack size using ulimit(3) before calling plock"); -# endif /* _AIX */ - if (!locked_ok && plock(PROCLOCK) != 0) - plog(XLOG_WARNING, "Couldn't lock process pages in memory using plock(): %m"); - else - locked_ok = 1; -#endif /* HAVE_PLOCK */ -#ifdef HAVE_MLOCKALL - if (!locked_ok && mlockall(MCL_CURRENT|MCL_FUTURE) != 0) - plog(XLOG_WARNING, "Couldn't lock process pages in memory using mlockall(): %m"); - else - locked_ok = 1; -#endif /* HAVE_MLOCKALL */ -#if defined(HAVE_PLOCK) || defined(HAVE_MLOCKALL) - if (locked_ok) - plog(XLOG_INFO, "Locked process pages in memory"); -#endif /* HAVE_PLOCK || HAVE_MLOCKALL */ - -#if defined(HAVE_MADVISE) && defined(MADV_PROTECT) - madvise(0, 0, MADV_PROTECT); /* may be redundant of the above worked out */ -#endif /* defined(HAVE_MADVISE) && defined(MADV_PROTECT) */ -} - - -int -main(int argc, char *argv[]) -{ - char *domdot, *verstr, *vertmp; - int ppid = 0; - int error; - char *progname = NULL; /* "amd" */ - char hostname[MAXHOSTNAMELEN + 1] = "localhost"; /* Hostname */ - - /* - * Make sure some built-in assumptions are true before we start - */ - assert(sizeof(nfscookie) >= sizeof(u_int)); - assert(sizeof(int) >= 4); - - /* - * Set processing status. - */ - amd_state = Start; - - /* - * Determine program name - */ - if (argv[0]) { - progname = strrchr(argv[0], '/'); - if (progname && progname[1]) - progname++; - else - progname = argv[0]; - } - if (!progname) - progname = "amd"; - am_set_progname(progname); - - /* - * Initialize process id. This is kept - * cached since it is used for generating - * and using file handles. - */ - am_set_mypid(); - - /* - * Get local machine name - */ - if (gethostname(hostname, sizeof(hostname)) < 0) { - plog(XLOG_FATAL, "gethostname: %m"); - going_down(1); - } - hostname[sizeof(hostname) - 1] = '\0'; - - /* - * Check it makes sense - */ - if (!*hostname) { - plog(XLOG_FATAL, "host name is not set"); - going_down(1); - } - - /* - * Initialize global options structure. - */ - init_global_options(); - - /* - * Partially initialize hostd[]. This - * is completed in get_args(). - */ - if ((domdot = strchr(hostname, '.'))) { - /* - * Hostname already contains domainname. - * Split out hostname and domainname - * components - */ - *domdot++ = '\0'; - hostdomain = domdot; - } - xstrlcpy(hostd, hostname, sizeof(hostd)); - am_set_hostname(hostname); - - /* - * Setup signal handlers - */ - /* SIGINT: trap interrupts for shutdowns */ - setup_sighandler(SIGINT, sigterm); - /* SIGTERM: trap terminate so we can shutdown cleanly (some chance) */ - setup_sighandler(SIGTERM, sigterm); - /* SIGHUP: hangups tell us to reload the cache */ - setup_sighandler(SIGHUP, sighup); - /* - * SIGCHLD: trap Death-of-a-child. These allow us to pick up the exit - * status of backgrounded mounts. See "sched.c". - */ - setup_sighandler(SIGCHLD, sigchld); -#ifdef HAVE_SIGACTION - /* construct global "masked_sigs" used in nfs_start.c */ - sigemptyset(&masked_sigs); - sigaddset(&masked_sigs, SIGINT); - sigaddset(&masked_sigs, SIGTERM); - sigaddset(&masked_sigs, SIGHUP); - sigaddset(&masked_sigs, SIGCHLD); -#endif /* HAVE_SIGACTION */ - - /* - * Fix-up any umask problems. Most systems default - * to 002 which is not too convenient for our purposes - */ - orig_umask = umask(0); - - /* - * Figure out primary network name - */ - getwire(&PrimNetName, &PrimNetNum); - - /* - * Determine command-line arguments - */ - get_args(argc, argv); - - /* - * Log version information. - */ - vertmp = get_version_string(); - verstr = strtok(vertmp, "\n"); - plog(XLOG_INFO, "AM-UTILS VERSION INFORMATION:"); - while (verstr) { - plog(XLOG_INFO, "%s", verstr); - verstr = strtok(NULL, "\n"); - } - XFREE(vertmp); - - /* - * Get our own IP address so that we can mount the automounter. We pass - * localhost_address which could be used as the default localhost - * name/address in amu_get_myaddress(). - */ - amu_get_myaddress(&myipaddr, gopt.localhost_address); - plog(XLOG_INFO, "My ip addr is %s", inet_ntoa(myipaddr)); - - /* avoid hanging on other NFS servers if started elsewhere */ - if (chdir("/") < 0) - plog(XLOG_INFO, "cannot chdir to /: %m"); - - /* - * Now check we are root. - */ - if (geteuid() != 0) { - plog(XLOG_FATAL, "Must be root to mount filesystems (euid = %ld)", (long) geteuid()); - going_down(1); - } - -#ifdef HAVE_MAP_NIS - /* - * If the domain was specified then bind it here - * to circumvent any default bindings that may - * be done in the C library. - */ - if (gopt.nis_domain && yp_bind(gopt.nis_domain)) { - plog(XLOG_FATAL, "Can't bind to NIS domain \"%s\"", gopt.nis_domain); - going_down(1); - } -#endif /* HAVE_MAP_NIS */ - - if (!amuDebug(D_DAEMON)) - ppid = daemon_mode(); - - /* - * Lock process text and data segment in memory. - */ - if (gopt.flags & CFM_PROCESS_LOCK) { - do_memory_locking(); - } - - do_mapc_reload = clocktime(NULL) + gopt.map_reload_interval; - - /* - * Register automounter with system. - */ - error = mount_automounter(ppid); - if (error && ppid) - kill(ppid, SIGALRM); - -#ifdef HAVE_FS_AUTOFS - /* - * XXX this should be part of going_down(), but I can't move it there - * because it would be calling non-library code from the library... ugh - */ - if (amd_use_autofs) - destroy_autofs_service(); -#endif /* HAVE_FS_AUTOFS */ - - going_down(error); - - abort(); - return 1; /* should never get here */ -} diff --git a/contrib/amd/amd/amd.h b/contrib/amd/amd/amd.h deleted file mode 100644 index 0e371b72a5b0..000000000000 --- a/contrib/amd/amd/amd.h +++ /dev/null @@ -1,867 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/amd.h - * - */ - -#ifndef _AMD_H -#define _AMD_H - - -/* - * MACROS: - */ - -/* - * Define a default debug mtab path for systems - * that support mtab on file. - */ -#ifdef MOUNT_TABLE_ON_FILE -# define DEBUG_MNTTAB_FILE "/tmp/mnttab" -#endif /* MOUNT_TABLE_ON_FILE */ - -/* options for amd.conf */ -#define CFM_BROWSABLE_DIRS 0x00000001 -#define CFM_MOUNT_TYPE_AUTOFS 0x00000002 /* use kernel autofs support */ -#define CFM_SELECTORS_IN_DEFAULTS 0x00000004 -#define CFM_NORMALIZE_HOSTNAMES 0x00000008 -#define CFM_PROCESS_LOCK 0x00000010 -#define CFM_PRINT_PID 0x00000020 -#define CFM_RESTART_EXISTING_MOUNTS 0x00000040 -#define CFM_SHOW_STATFS_ENTRIES 0x00000080 -#define CFM_FULLY_QUALIFIED_HOSTS 0x00000100 -#define CFM_BROWSABLE_DIRS_FULL 0x00000200 /* allow '/' in readdir() */ -#define CFM_UNMOUNT_ON_EXIT 0x00000400 /* when amd finishing */ -#define CFM_USE_TCPWRAPPERS 0x00000800 -#define CFM_AUTOFS_USE_LOFS 0x00001000 -#define CFM_NFS_INSECURE_PORT 0x00002000 -#define CFM_DOMAIN_STRIP 0x00004000 -#define CFM_NORMALIZE_SLASHES 0x00008000 /* normalize slashes? */ -#define CFM_FORCED_UNMOUNTS 0x00010000 /* forced unmounts? */ -#define CFM_TRUNCATE_LOG 0x00020000 /* truncate log file? */ -#if 0 -/* XXX: reserved to sync up with am-utils-6.2 */ -#define CFM_SUN_MAP_SYNTAX 0x00040000 /* Sun map syntax? */ -#endif -#define CFM_NFS_ANY_INTERFACE 0x00080000 /* all interfaces are acceptable */ - -/* defaults global flags: plock, tcpwrappers, and autofs/lofs */ -#define CFM_DEFAULT_FLAGS (CFM_PROCESS_LOCK|CFM_USE_TCPWRAPPERS|CFM_AUTOFS_USE_LOFS|CFM_DOMAIN_STRIP|CFM_NORMALIZE_SLASHES) - -/* - * macro definitions for automounter vfs/vnode operations. - */ -#define VLOOK_CREATE 0x1 -#define VLOOK_DELETE 0x2 -#define VLOOK_LOOKUP 0x3 - -/* - * macro definitions for automounter vfs capabilities - */ -#define FS_DIRECTORY 0x0001 /* This looks like a dir, not a link */ -#define FS_MBACKGROUND 0x0002 /* Should background this mount */ -#define FS_NOTIMEOUT 0x0004 /* Don't bother with timeouts */ -#define FS_MKMNT 0x0008 /* Need to make the mount point */ -#define FS_UBACKGROUND 0x0010 /* Unmount in background */ -#define FS_BACKGROUND (FS_MBACKGROUND|FS_UBACKGROUND) -#define FS_DISCARD 0x0020 /* Discard immediately on last reference */ -#define FS_AMQINFO 0x0040 /* Amq is interested in this fs type */ -#define FS_AUTOFS 0x0080 /* This filesystem can be an autofs f/s */ -#define FS_DIRECT 0x0100 /* Direct mount */ -#define FS_ON_AUTOFS 0x0200 /* This filesystem can be mounted directly - onto an autofs mountpoint */ - -/* - * macros for struct am_node (map of auto-mount points). - */ -#define AMF_NOTIMEOUT 0x0001 /* This node never times out */ -#define AMF_ROOT 0x0002 /* This is a root node */ -#define AMF_AUTOFS 0x0004 /* This node is part of an autofs filesystem */ -#define AMF_REMOUNT 0x0008 /* This node needs to be remounted */ -#define AMF_SOFTLOOKUP 0x0010 /* This node returns EIO if server is down */ - -/* - * macros for struct mntfs (list of mounted filesystems) - */ -#define MFF_MOUNTED 0x0001 /* Node is mounted */ -#define MFF_MOUNTING 0x0002 /* Mount is in progress */ -#define MFF_UNMOUNTING 0x0004 /* Unmount is in progress */ -#define MFF_RESTART 0x0008 /* Restarted node */ -#define MFF_MKMNT 0x0010 /* Delete this node's am_mount */ -#define MFF_ERROR 0x0020 /* This node failed to mount */ -#define MFF_LOGDOWN 0x0040 /* Logged that this mount is down */ -#define MFF_RSTKEEP 0x0080 /* Don't timeout this filesystem - restarted */ -#define MFF_WANTTIMO 0x0100 /* Need a timeout call when not busy */ -#define MFF_NFSLINK 0x0200 /* nfsl type, and deemed a link */ -#define MFF_IS_AUTOFS 0x0400 /* this filesystem is of type autofs */ -#define MFF_NFS_SCALEDOWN 0x0800 /* the mount failed, retry with v2/UDP */ -#define MFF_ON_AUTOFS 0x1000 /* autofs has a lofs/link to this f/s */ -#define MFF_WEBNFS 0x2000 /* use public filehandle */ - -/* - * macros for struct fserver. - */ -#define FSF_VALID 0x0001 /* Valid information available */ -#define FSF_DOWN 0x0002 /* This fileserver is thought to be down */ -#define FSF_ERROR 0x0004 /* Permanent error has occurred */ -#define FSF_WANT 0x0008 /* Want a wakeup call */ -#define FSF_PINGING 0x0010 /* Already doing pings */ -#define FSF_WEBNFS 0x0020 /* Don't try to contact portmapper */ -#define FSF_PING_UNINIT 0x0040 /* ping values have not been initilized */ -#define FSF_FORCE_UNMOUNT 0x0080 /* force umount of this fserver */ -#define FSRV_ERROR(fs) ((fs) && (((fs)->fs_flags & FSF_ERROR) == FSF_ERROR)) -#define FSRV_ISDOWN(fs) ((fs) && (((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_DOWN|FSF_VALID))) -#define FSRV_ISUP(fs) (!(fs) || (((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_VALID))) - -/* some systems (SunOS 4.x) neglect to define the mount null message */ -#ifndef MOUNTPROC_NULL -# define MOUNTPROC_NULL ((u_long)(0)) -#endif /* not MOUNTPROC_NULL */ - -/* - * Error to return if remote host is not available. - * Try, in order, "host down", "host unreachable", "invalid argument". - */ -#ifdef EHOSTDOWN -# define AM_ERRNO_HOST_DOWN EHOSTDOWN -#else /* not EHOSTDOWN */ -# ifdef EHOSTUNREACH -# define AM_ERRNO_HOST_DOWN EHOSTUNREACH -# else /* not EHOSTUNREACH */ -# define AM_ERRNO_HOST_DOWN EINVAL -# endif /* not EHOSTUNREACH */ -#endif /* not EHOSTDOWN */ - -/* Hash table size */ -#define NKVHASH (1 << 2) /* Power of two */ - -/* Max entries to return in one call */ -#define MAX_READDIR_ENTRIES 16 - -/* - * default amfs_auto retrans - 1/10th seconds - */ -#define AMFS_AUTO_RETRANS(x) ((ALLOWED_MOUNT_TIME*10+5*gopt.amfs_auto_timeo[(x)])/gopt.amfs_auto_timeo[(x)] * 2) - -/* - * The following values can be tuned... - */ -#define AM_TTL (300) /* Default cache period (5 min) */ -#define AM_TTL_W (120) /* Default unmount interval (2 min) */ -#define AM_PINGER 30 /* NFS ping interval for live systems */ -#define AMFS_AUTO_TIMEO 8 /* Default amfs_auto timeout - .8s */ -#define AMFS_EXEC_MAP_TIMEOUT 10 /* default 10sec exec map timeout */ - -/* interval between forced retries of a mount */ -#define RETRY_INTERVAL 2 - -#ifndef ROOT_MAP -# define ROOT_MAP "\"root\"" -#endif /* not ROOT_MAP */ - -#define ereturn(x) do { *error_return = x; return 0; } while (0) - -#define NEVER (time_t) 0 - -#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) -# define AMD_SERVICE_NAME "amd" /* for tcpwrappers */ -#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */ - -/* - * TYPEDEFS: - */ - -typedef struct cf_map cf_map_t; -typedef struct kv kv; -typedef struct am_node am_node; -typedef struct mntfs mntfs; -typedef struct am_opts am_opts; -typedef struct am_ops am_ops; -typedef struct am_stats am_stats; -typedef struct fserver fserver; - -typedef voidp wchan_t; -typedef voidp opaque_t; - -/* - * Cache map operations - */ -typedef void add_fn(mnt_map *, char *, char *); -typedef int init_fn(mnt_map *, char *, time_t *); -typedef int mtime_fn(mnt_map *, char *, time_t *); -typedef int isup_fn(mnt_map *, char *); -typedef int reload_fn(mnt_map *, char *, add_fn *); -typedef int search_fn(mnt_map *, char *, char *, char **, time_t *); -typedef int task_fun(opaque_t); -typedef void cb_fun(int, int, opaque_t); -typedef void fwd_fun(voidp, int, struct sockaddr_in *, - struct sockaddr_in *, opaque_t, int); -typedef int key_fun(char *, opaque_t); -typedef void callout_fun(opaque_t); - -/* - * automounter vfs/vnode operations. - */ -typedef char *(*vfs_match) (am_opts *); -typedef int (*vfs_init) (mntfs *); -typedef int (*vmount_fs) (am_node *, mntfs *); -typedef int (*vumount_fs) (am_node *, mntfs *); -typedef am_node *(*vlookup_child) (am_node *, char *, int *, int); -typedef am_node *(*vmount_child) (am_node *, int *); -typedef int (*vreaddir) (am_node *, nfscookie, nfsdirlist *, nfsentry *, u_int); -typedef am_node *(*vreadlink) (am_node *, int *); -typedef void (*vmounted) (mntfs *); -typedef void (*vumounted) (mntfs *); -typedef fserver *(*vffserver) (mntfs *); -typedef wchan_t (*vget_wchan) (mntfs *); - - - -/* - * STRUCTURES: - */ - -/* global amd options that are manipulated by conf.c */ -struct amu_global_options { - char *arch; /* name of current architecture */ - char *auto_dir; /* automounter temp dir */ - int auto_attrcache; /* attribute cache timeout for auto dirs */ - char *cluster; /* cluster name */ - char *karch; /* kernel architecture */ - char *logfile; /* amd log file */ - char *op_sys; /* operating system name ${os} */ - char *op_sys_ver; /* OS version ${osver} */ - char *op_sys_full; /* full OS name ${full_os} */ - char *op_sys_vendor; /* name of OS vendor ${vendor} */ - char *pid_file; /* PID file */ - char *sub_domain; /* local domain */ - char *localhost_address; /* localhost address (NULL means use 127.0.0.1) */ - char *map_defaults; /* global map /default options */ - char *map_options; /* global map options */ - int map_reload_interval; /* map reload interval */ - char *map_type; /* global map type */ - char *search_path; /* search path for maps */ - char *mount_type; /* mount type for map */ - char *debug_mtab_file; /* path for the mtab file during debug mode */ - u_int flags; /* various CFM_* flags */ - -#define AMU_TYPE_NONE -1 /* for amfs_auto_{timeo,retrans,toplvl} */ -#define AMU_TYPE_UDP 0 /* for amfs_auto_{timeo,retrans,toplvl} */ -#define AMU_TYPE_TCP 1 /* for amfs_auto_{timeo,retrans,toplvl} */ - /* - * Note: toplvl is only UDP, but we want to separate it from regular - * NFS mounts which Amd makes, because the toplvl mount is a localhost - * mount for which different timeo/retrans parameters may be desired. - */ -#define AMU_TYPE_TOPLVL 2 /* for amfs_auto_{timeo,retrans,toplvl} */ -#define AMU_TYPE_MAX 3 /* for amfs_auto_{timeo,retrans,toplvl} */ - int amfs_auto_retrans[AMU_TYPE_MAX]; /* NFS retransmit counter */ - int amfs_auto_timeo[AMU_TYPE_MAX]; /* NFS retry interval */ - - int am_timeo; /* cache duration */ - int am_timeo_w; /* dismount interval */ - u_long portmap_program; /* amd RPC program number */ - u_short preferred_amq_port; /* preferred amq service RPC port number (0 means "any") */ -#ifdef HAVE_MAP_HESIOD - char *hesiod_base; /* Hesiod rhs */ -#endif /* HAVE_MAP_HESIOD */ -#ifdef HAVE_MAP_LDAP - char *ldap_base; /* LDAP base */ - char *ldap_hostports; /* LDAP host ports */ - long ldap_cache_seconds; /* LDAP internal cache - keep seconds */ - long ldap_cache_maxmem; /* LDAP internal cache - max memory (bytes) */ - long ldap_proto_version; /* LDAP protocol version */ -#endif /* HAVE_MAP_LDAP */ -#ifdef HAVE_MAP_NIS - char *nis_domain; /* YP domain name */ -#endif /* HAVE_MAP_NIS */ - char *nfs_proto; /* NFS protocol (NULL, udp, tcp) */ - int nfs_vers; /* NFS version (0, 2, 3, 4) */ - u_int exec_map_timeout; /* timeout (seconds) for executable maps */ -}; - -/* if you add anything here, update conf.c:reset_cf_map() */ -struct cf_map { - char *cfm_dir; /* /home, /u, /src */ - char *cfm_name; /* amd.home, /etc/amd.home ... */ - char *cfm_type; /* file, hesiod, ndbm, nis ... */ - char *cfm_defaults; /* map /defaults options in amd.conf */ - char *cfm_opts; /* -cache:=all, etc. */ - char *cfm_search_path; /* /etc/local:/etc/amdmaps:/misc/yp */ - char *cfm_tag; /* optional map tag for amd -T */ - u_int cfm_flags; /* browsable_dirs? mount_type? */ - struct cf_map *cfm_next; /* pointer to next in list (if any) */ -}; - -/* - * Key-value pair - */ -struct kv { - kv *next; - char *key; -#ifdef HAVE_REGEXEC - regex_t re; /* store the regexp from regcomp() */ -#endif /* HAVE_REGEXEC */ - char *val; -}; - -struct mnt_map { - qelem hdr; - int refc; /* Reference count */ - short flags; /* Allocation flags */ - short alloc; /* Allocation mode */ - time_t modify; /* Modify time of map */ - u_int reloads; /* Number of times map was reloaded */ - char *map_name; /* Name of this map */ - char *wildcard; /* Wildcard value */ - reload_fn *reload; /* Function to be used for reloads */ - isup_fn *isup; /* Is service up or not? (1=up, 0=down) */ - search_fn *search; /* Function to be used for searching */ - mtime_fn *mtime; /* Modify time function */ - kv *kvhash[NKVHASH]; /* Cached data */ - cf_map_t *cfm; /* pointer to per-map amd.conf opts, if any */ - void *map_data; /* Map data black box */ -}; - -/* - * Options - */ -struct am_opts { - char *fs_glob; /* Smashed copy of global options */ - char *fs_local; /* Expanded copy of local options */ - char *fs_mtab; /* Mount table entry */ - /* Other options ... */ - char *opt_dev; - char *opt_delay; - char *opt_dir; - char *opt_fs; - char *opt_group; - char *opt_mount; - char *opt_opts; - char *opt_remopts; - char *opt_pref; - char *opt_cache; - char *opt_rfs; - char *opt_rhost; - char *opt_sublink; - char *opt_type; - char *opt_mount_type; /* "nfs" or "autofs" */ - char *opt_unmount; - char *opt_umount; /* an "alias" for opt_unmount (type:=program) */ - char *opt_user; - char *opt_maptype; /* map type: file, nis, hesiod, etc. */ - char *opt_cachedir; /* cache directory */ - char *opt_addopts; /* options to add to opt_opts */ -}; - -struct am_ops { - char *fs_type; /* type of filesystems e.g. "nfsx" */ - vfs_match fs_match; /* fxn: match */ - vfs_init fs_init; /* fxn: initialization */ - vmount_fs mount_fs; /* fxn: mount my own vnode */ - vumount_fs umount_fs; /* fxn: unmount my own vnode */ - vlookup_child lookup_child; /* fxn: lookup path-name */ - vmount_child mount_child; /* fxn: mount path-name */ - vreaddir readdir; /* fxn: read directory */ - vreadlink readlink; /* fxn: read link */ - vmounted mounted; /* fxn: after-mount extra actions */ - vumounted umounted; /* fxn: after-umount extra actions */ - vffserver ffserver; /* fxn: find a file server */ - vget_wchan get_wchan; /* fxn: get the waiting channel */ - int nfs_fs_flags; /* filesystem flags FS_* for nfs mounts */ -#ifdef HAVE_FS_AUTOFS - int autofs_fs_flags;/* filesystem flags FS_* for autofs mounts */ -#endif /* HAVE_FS_AUTOFS */ -}; - -/* - * List of mounted filesystems - */ -struct mntfs { - qelem mf_q; /* List of mounted filesystems */ - am_ops *mf_ops; /* Operations on this mountpoint */ - am_opts *mf_fo; /* File opts */ - char *mf_mount; /* "/a/kiska/home/kiska" */ - char *mf_info; /* Mount info */ - char *mf_auto; /* Automount opts */ - char *mf_mopts; /* FS mount opts */ - char *mf_remopts; /* Remote FS mount opts */ - char *mf_loopdev; /* loop device name for /dev/loop mounts */ - fserver *mf_server; /* File server */ - int mf_fsflags; /* Flags FS_* copied from mf_ops->*_fs_flags */ - int mf_flags; /* Flags MFF_* */ - int mf_error; /* Error code from background mount */ - int mf_refc; /* Number of references to this node */ - int mf_cid; /* Callout id */ - void (*mf_prfree) (opaque_t); /* Free private space */ - opaque_t mf_private; /* Private - per-fs data */ -}; - -/* - * List of fileservers - */ -struct fserver { - qelem fs_q; /* List of fileservers */ - int fs_refc; /* Number of references to this server */ - char *fs_host; /* Normalized hostname of server */ - struct sockaddr_in *fs_ip; /* Network address of server */ - int fs_cid; /* Callout id */ - int fs_pinger; /* Ping (keepalive) interval */ - int fs_flags; /* Flags */ - char *fs_type; /* File server type */ - u_long fs_version; /* NFS version of server (2, 3, etc.)*/ - char *fs_proto; /* NFS protocol of server (tcp, udp, etc.) */ - opaque_t fs_private; /* Private data */ - void (*fs_prfree) (opaque_t); /* Free private data */ -}; - -/* - * Per-mountpoint statistics - */ -struct am_stats { - time_t s_mtime; /* Mount time */ - u_short s_uid; /* Uid of mounter */ - int s_getattr; /* Count of getattrs */ - int s_lookup; /* Count of lookups */ - int s_readdir; /* Count of readdirs */ - int s_readlink; /* Count of readlinks */ - int s_statfs; /* Count of statfs */ -}; - -/* - * System statistics - */ -struct amd_stats { - int d_drops; /* Dropped requests */ - int d_stale; /* Stale NFS handles */ - int d_mok; /* Successful mounts */ - int d_merr; /* Failed mounts */ - int d_uerr; /* Failed unmounts */ -}; -extern struct amd_stats amd_stats; - -/* - * Map of auto-mount points. - */ -struct am_node { - int am_mapno; /* Map number */ - mntfs *am_mnt; /* Mounted filesystem */ - mntfs **am_mfarray; /* Filesystem sources to try to mount */ - char *am_name; /* "kiska": name of this node */ - char *am_path; /* "/home/kiska": path of this node's mount point */ - char *am_link; /* "/a/kiska/home/kiska/this/that": link to sub-dir */ - am_node *am_parent; /* Parent of this node */ - am_node *am_ysib; /* Younger sibling of this node */ - am_node *am_osib; /* Older sibling of this node */ - am_node *am_child; /* First child of this node */ - nfsattrstat am_attr; /* File attributes */ -#define am_fattr am_attr.ns_u.ns_attr_u - int am_flags; /* Boolean flags AMF_* */ - int am_error; /* Specific mount error */ - time_t am_ttl; /* Time to live */ - int am_timeo_w; /* Dismount wait interval */ - int am_timeo; /* Cache timeout interval */ - u_int am_gen; /* Generation number */ - char *am_pref; /* Mount info prefix */ - am_stats am_stats; /* Statistics gathering */ - SVCXPRT *am_transp; /* Info for quick reply */ - dev_t am_dev; /* Device number */ - dev_t am_rdev; /* Remote/real device number */ -#ifdef HAVE_FS_AUTOFS - autofs_fh_t *am_autofs_fh; - time_t am_autofs_ttl; /* Time to expire autofs nodes */ -#endif /* HAVE_FS_AUTOFS */ -}; - -/* - * EXTERNALS: - */ - -/* - * Amq server global functions - */ -extern amq_mount_info_list *amqproc_getmntfs_1_svc(voidp argp, struct svc_req *rqstp); -extern amq_mount_stats *amqproc_stats_1_svc(voidp argp, struct svc_req *rqstp); -extern amq_mount_tree_list *amqproc_export_1_svc(voidp argp, struct svc_req *rqstp); -extern amq_mount_tree_p *amqproc_mnttree_1_svc(voidp argp, struct svc_req *rqstp); -extern amq_string *amqproc_getvers_1_svc(voidp argp, struct svc_req *rqstp); -extern amq_string *amqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp); -extern int *amqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp); -extern int *amqproc_mount_1_svc(voidp argp, struct svc_req *rqstp); -extern int *amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp); -extern voidp amqproc_null_1_svc(voidp argp, struct svc_req *rqstp); -extern voidp amqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp); - -/* other external definitions */ -extern am_nfs_fh *get_root_nfs_fh(char *dir); -extern am_node *find_ap(char *); -extern am_node *get_ap_child(am_node *, char *); -extern bool_t xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead); -extern fserver *find_nfs_srvr(mntfs *mf); -extern int mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf); -extern int process_all_regular_maps(void); -extern cf_map_t *find_cf_map(const char *name); -extern int set_conf_kv(const char *section, const char *k, const char *v); -extern int mount_node(opaque_t arg); -extern int unmount_mp(am_node *mp); -extern int yyparse (void); - -extern void amfs_mkcacheref(mntfs *mf); -extern int amfs_mount(am_node *mp, mntfs *mf, char *opts); -extern void assign_error_mntfs(am_node *mp); -extern am_node *next_nonerror_node(am_node *xp); -extern void flush_srvr_nfs_cache(fserver *fs); -extern void am_mounted(am_node *); -extern void mf_mounted(mntfs *mf, bool_t call_free_opts); -extern void am_unmounted(am_node *); -extern am_node *get_exported_ap(int index); -extern am_node *get_first_exported_ap(int *index); -extern am_node *get_next_exported_ap(int *index); -extern am_node *path_to_exported_ap(char *path); -extern am_node *exported_ap_alloc(void); -extern am_node *find_mf(mntfs *); -extern am_node *next_map(int *); -extern am_ops *ops_match(am_opts *, char *, char *, char *, char *, char *); -extern am_ops *ops_search(char *); -extern fserver *dup_srvr(fserver *); -extern void srvrlog(fserver *, char *); -extern int get_mountd_port(fserver *, u_short *, wchan_t); -extern void flush_nfs_fhandle_cache(fserver *); - -extern mntfs *dup_mntfs(mntfs *); -extern mntfs *find_mntfs(am_ops *, am_opts *, char *, char *, char *, char *, char *); -extern mntfs *locate_mntfs(am_ops *, am_opts *, char *, char *, char *, char *, char *); -extern mntfs *new_mntfs(void); -extern mntfs *realloc_mntfs(mntfs *, am_ops *, am_opts *, char *, char *, char *, char *, char *); -extern void flush_mntfs(void); -extern void free_mntfs(voidp); - - -extern void amq_program_1(struct svc_req *rqstp, SVCXPRT *transp); -extern int background(void); -extern void deslashify(char *); -extern void do_task_notify(void); -extern int eval_fs_opts(am_opts *, char *, char *, char *, char *, char *); -extern void forcibly_timeout_mp(am_node *); -extern void free_map(am_node *); -extern void free_opts(am_opts *); -extern void free_srvr(fserver *); -extern int fwd_init(void); -extern int fwd_packet(int, char *, int, struct sockaddr_in *, struct sockaddr_in *, opaque_t, fwd_fun *); -extern void fwd_reply(void); -extern void get_args(int argc, char *argv[]); -extern wchan_t get_mntfs_wchan(mntfs *mf); -extern void host_normalize(char **); -extern void init_map(am_node *, char *); -extern void ins_que(qelem *, qelem *); -extern void insert_am(am_node *, am_node *); -extern int make_nfs_auth(void); -extern void make_root_node(void); -extern void map_flush_srvr(fserver *); -extern void mapc_add_kv(mnt_map *, char *, char *); -extern mnt_map *mapc_find(char *, char *, const char *); -extern void mapc_free(opaque_t); -extern int mapc_keyiter(mnt_map *, key_fun, opaque_t); -extern void mapc_reload(void); -extern int mapc_search(mnt_map *, char *, char **); -extern void mapc_showtypes(char *buf, size_t l); -extern int mapc_type_exists(const char *type); -extern void mk_fattr(nfsfattr *, nfsftype); -extern int mount_auto_node(char *, opaque_t); -extern int mount_automounter(int); -extern int mount_exported(void); -extern void mp_to_fh(am_node *, am_nfs_fh *); -extern void new_ttl(am_node *); -extern void nfs_quick_reply(am_node *mp, int error); -extern void normalize_slash(char *); -extern void ops_showamfstypes(char *buf, size_t l); -extern void ops_showfstypes(char *outbuf, size_t l); -extern void rem_que(qelem *); -extern void reschedule_timeout_mp(void); -extern void restart(void); -extern void restart_automounter_nodes(void); -extern int root_keyiter(key_fun *, opaque_t); -extern void root_newmap(const char *, const char *, const char *, const cf_map_t *); -extern void run_task(task_fun *, opaque_t, cb_fun *, opaque_t); -extern void sched_task(cb_fun *, opaque_t, wchan_t); -extern int softclock(void); -extern int timeout(u_int, void (*fn)(opaque_t), opaque_t); -extern void timeout_mp(opaque_t); -extern void untimeout(int); -extern void umount_exported(void); -extern int valid_key(char *); -extern void wakeup(wchan_t); -extern void wakeup_srvr(fserver *); -extern void wakeup_task(int, int, wchan_t); -#define SIZEOF_PID_FSNAME (16 + MAXHOSTNAMELEN) -extern char pid_fsname[SIZEOF_PID_FSNAME]; /* "kiska.southseas.nz:(pid%d)" */ -#define SIZEOF_HOSTD (2 * MAXHOSTNAMELEN + 1) -extern char hostd[SIZEOF_HOSTD]; /* Host+domain */ -#define SIZEOF_OPTS 256 /* used for char opts[] and preopts[] */ - -/* - * Global variables. - */ -extern FILE *yyin; -extern SVCXPRT *current_transp; /* For nfs_quick_reply() */ -extern char *conf_tag; -#define SIZEOF_UID_STR 12 -#define SIZEOF_GID_STR 12 -extern char *opt_gid, gid_str[SIZEOF_GID_STR]; -extern char *opt_uid, uid_str[SIZEOF_UID_STR]; -extern int NumChildren; -extern int fwd_sock; -extern int select_intr_valid; -extern int immediate_abort; /* Should close-down unmounts be retried */ -extern int usage; -extern int use_conf_file; /* use amd configuration file */ -extern int task_notify_todo; /* Task notifier needs running */ -extern jmp_buf select_intr; -extern qelem mfhead; -extern struct amu_global_options gopt; /* where global options are stored */ -extern time_t do_mapc_reload; /* Flush & reload mount map cache */ -extern time_t next_softclock; /* Time to call softclock() */ - -#ifdef HAVE_SIGACTION -extern sigset_t masked_sigs; -#endif /* HAVE_SIGACTION */ - -#if defined(HAVE_AMU_FS_LINK) || defined(HAVE_AMU_FS_LINKX) -extern char *amfs_link_match(am_opts *fo); -#endif /* defined(HAVE_AMU_FS_LINK) || defined(HAVE_AMU_FS_LINKX) */ - -#ifdef HAVE_FS_AUTOFS -extern int amd_use_autofs; - -extern int autofs_get_fh(am_node *mp); -extern void autofs_release_fh(am_node *mp); -extern void autofs_get_mp(am_node *mp); -extern void autofs_release_mp(am_node *mp); -extern void autofs_add_fdset(fd_set *readfds); -extern int autofs_handle_fdset(fd_set *readfds, int nsel); -extern void autofs_mounted(am_node *mp); -extern void autofs_mount_succeeded(am_node *mp); -extern void autofs_mount_failed(am_node *mp); -extern int autofs_umount_succeeded(am_node *mp); -extern int autofs_umount_failed(am_node *mp); -extern int autofs_mount_fs(am_node *mp, mntfs *mf); -extern int autofs_umount_fs(am_node *mp, mntfs *mf); -extern void autofs_get_opts(char *opts, size_t l, autofs_fh_t *fh); -extern int autofs_compute_mount_flags(mntent_t *); -extern void autofs_timeout_mp(am_node *); -extern int create_autofs_service(void); -extern int destroy_autofs_service(void); -#endif /* HAVE_FS_AUTOFS */ - -/**************************************************************************/ -/*** Generic file-system types, implemented as part of the native O/S. ***/ -/**************************************************************************/ - -/* - * Loopback File System - * Many systems can't support this, and in any case most of the - * functionality is available with Symlink FS. - */ -#ifdef HAVE_FS_LOFS -extern am_ops lofs_ops; -extern int mount_lofs(char *mntdir, char *fs_name, char *opts, int on_autofs); -#endif /* HAVE_FS_LOFS */ - -/* - * CD-ROM File System (CD-ROM) - * (HSFS: High Sierra F/S on some machines) - * Many systems can't support this, and in any case most of the - * functionality is available with program FS. - */ -#ifdef HAVE_FS_CDFS -extern am_ops cdfs_ops; -#endif /* HAVE_FS_CDFS */ - -/* - * PC File System (MS-DOS) - * Many systems can't support this, and in any case most of the - * functionality is available with program FS. - */ -#ifdef HAVE_FS_PCFS -extern am_ops pcfs_ops; -#endif /* HAVE_FS_PCFS */ - -/* - * Caching File System (Solaris) - */ -#ifdef HAVE_FS_CACHEFS -extern am_ops cachefs_ops; -#endif /* HAVE_FS_CACHEFS */ - -/* - * Network File System - * Good, slow, NFS V.2. - */ -#ifdef HAVE_FS_NFS -extern am_ops nfs_ops; /* NFS */ -extern fserver *find_nfs_srvr (mntfs *); -extern qelem nfs_srvr_list; -#endif /* HAVE_FS_NFS */ - -/* - * Un*x File System - * Normal local disk file system. - */ -#ifdef HAVE_FS_UFS -extern am_ops ufs_ops; /* Un*x file system */ -#endif /* HAVE_FS_UFS */ - -/* Unix file system (irix) */ -#ifdef HAVE_FS_XFS -extern am_ops xfs_ops; /* Un*x file system */ -#endif /* HAVE_FS_XFS */ - -/* Unix file system (irix) */ -#ifdef HAVE_FS_EFS -extern am_ops efs_ops; /* Un*x file system */ -#endif /* HAVE_FS_EFS */ - -/**************************************************************************/ -/*** Automounter file-system types, implemented by amd. ***/ -/**************************************************************************/ - -/* - * Root AMD File System - */ -extern am_ops amfs_root_ops; /* Root file system */ - -/* - * Generic amfs helper methods - */ -extern am_node *amfs_generic_lookup_child(am_node *mp, char *fname, int *error_return, int op); -extern am_node *amfs_generic_mount_child(am_node *ap, int *error_return); -extern int amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count); -extern int amfs_generic_umount(am_node *mp, mntfs *mf); -extern void amfs_generic_mounted(mntfs *mf); -extern char *amfs_generic_match(am_opts *fo); -extern fserver *amfs_generic_find_srvr(mntfs *); - -/* - * Automount File System - */ -#ifdef HAVE_AMU_FS_AUTO -extern am_ops amfs_auto_ops; /* Automount file system (this!) */ -#endif /* HAVE_AMU_FS_AUTO */ - -/* - * Toplvl Automount File System - */ -#ifdef HAVE_AMU_FS_TOPLVL -extern am_ops amfs_toplvl_ops; /* Toplvl Automount file system */ -extern int amfs_toplvl_mount(am_node *mp, mntfs *mf); -extern int amfs_toplvl_umount(am_node *mp, mntfs *mf); -#endif /* HAVE_AMU_FS_TOPLVL */ - -/* - * Direct Automount File System - */ -#ifdef HAVE_AMU_FS_DIRECT -extern am_ops amfs_direct_ops; /* Direct Automount file system (this too) */ -#endif /* HAVE_AMU_FS_DIRECT */ - -/* - * Error File System - */ -#ifdef HAVE_AMU_FS_ERROR -extern am_ops amfs_error_ops; /* Error file system */ -extern am_node *amfs_error_lookup_child(am_node *mp, char *fname, int *error_return, int op); -extern am_node *amfs_error_mount_child(am_node *ap, int *error_return); -extern int amfs_error_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count); -#endif /* HAVE_AMU_FS_ERROR */ - -/* - * NFS mounts with local existence check. - */ -#ifdef HAVE_AMU_FS_NFSL -extern am_ops amfs_nfsl_ops; /* NFSL */ -#endif /* HAVE_AMU_FS_NFSL */ - -/* - * Multi-nfs mounts. - */ -#ifdef HAVE_AMU_FS_NFSX -extern am_ops amfs_nfsx_ops; /* NFSX */ -#endif /* HAVE_AMU_FS_NFSX */ - -/* - * NFS host - a whole tree. - */ -#ifdef HAVE_AMU_FS_HOST -extern am_ops amfs_host_ops; /* NFS host */ -#endif /* HAVE_AMU_FS_HOST */ - -/* - * Program File System - * This is useful for things like RVD. - */ -#ifdef HAVE_AMU_FS_PROGRAM -extern am_ops amfs_program_ops; /* Program File System */ -#endif /* HAVE_AMU_FS_PROGRAM */ - -/* - * Symbolic-link file system. - * A "filesystem" which is just a symbol link. - */ -#ifdef HAVE_AMU_FS_LINK -extern am_ops amfs_link_ops; /* Symlink FS */ -#endif /* HAVE_AMU_FS_LINK */ - -/* - * Symbolic-link file system, which also checks that the target of - * the symlink exists. - * A "filesystem" which is just a symbol link. - */ -#ifdef HAVE_AMU_FS_LINKX -extern am_ops amfs_linkx_ops; /* Symlink FS with existence check */ -#endif /* HAVE_AMU_FS_LINKX */ - -/* - * Union file system - */ -#ifdef HAVE_AMU_FS_UNION -extern am_ops amfs_union_ops; /* Union FS */ -#endif /* HAVE_AMU_FS_UNION */ - -#endif /* not _AMD_H */ diff --git a/contrib/amd/amd/amfs_auto.c b/contrib/amd/amd/amfs_auto.c deleted file mode 100644 index 75a451fd111d..000000000000 --- a/contrib/amd/amd/amfs_auto.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/amfs_auto.c - * - */ - -/* - * Automount file system - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/**************************************************************************** - *** MACROS *** - ****************************************************************************/ - - -/**************************************************************************** - *** STRUCTURES *** - ****************************************************************************/ - - -/**************************************************************************** - *** FORWARD DEFINITIONS *** - ****************************************************************************/ -static int amfs_auto_mount(am_node *mp, mntfs *mf); - - -/**************************************************************************** - *** OPS STRUCTURES *** - ****************************************************************************/ -am_ops amfs_auto_ops = -{ - "auto", - amfs_generic_match, - 0, /* amfs_auto_init */ - amfs_auto_mount, - amfs_generic_umount, - amfs_generic_lookup_child, - amfs_generic_mount_child, - amfs_generic_readdir, - 0, /* amfs_auto_readlink */ - amfs_generic_mounted, - 0, /* amfs_auto_umounted */ - amfs_generic_find_srvr, - 0, /* amfs_auto_get_wchan */ - FS_AMQINFO | FS_DIRECTORY, -#ifdef HAVE_FS_AUTOFS - AUTOFS_AUTO_FS_FLAGS, -#endif /* HAVE_FS_AUTOFS */ -}; - - -/**************************************************************************** - *** FUNCTIONS *** - ****************************************************************************/ -/* - * Mount a sub-mount - */ -static int -amfs_auto_mount(am_node *mp, mntfs *mf) -{ - /* - * Pseudo-directories are used to provide some structure - * to the automounted directories instead - * of putting them all in the top-level automount directory. - * - * Here, just increment the parent's link count. - */ - mp->am_parent->am_fattr.na_nlink++; - - /* - * Info field of . means use parent's info field. - * Historical - not documented. - */ - if (mf->mf_info[0] == '.' && mf->mf_info[1] == '\0') - mf->mf_info = strealloc(mf->mf_info, mp->am_parent->am_mnt->mf_info); - - /* - * Compute prefix: - * - * If there is an option prefix then use that else - * If the parent had a prefix then use that with name - * of this node appended else - * Use the name of this node. - * - * That means if you want no prefix you must say so - * in the map. - */ - if (mf->mf_fo->opt_pref) { - /* allow pref:=null to set a real null prefix */ - if (STREQ(mf->mf_fo->opt_pref, "null")) { - mp->am_pref = strdup(""); - } else { - /* - * the prefix specified as an option - */ - mp->am_pref = strdup(mf->mf_fo->opt_pref); - } - } else { - /* - * else the parent's prefix - * followed by the name - * followed by / - */ - char *ppref = mp->am_parent->am_pref; - if (ppref == 0) - ppref = ""; - mp->am_pref = str3cat((char *) 0, ppref, mp->am_name, "/"); - } - -#ifdef HAVE_FS_AUTOFS - if (mf->mf_flags & MFF_IS_AUTOFS) { - char opts[SIZEOF_OPTS]; - int error; - - autofs_get_opts(opts, sizeof(opts), mp->am_autofs_fh); - - /* now do the mount */ - error = amfs_mount(mp, mf, opts); - if (error) { - errno = error; - plog(XLOG_FATAL, "amfs_auto_mount: amfs_mount failed: %m"); - return error; - } - } -#endif /* HAVE_FS_AUTOFS */ - - /* - * Attach a map cache - */ - amfs_mkcacheref(mf); - - return 0; -} diff --git a/contrib/amd/amd/amfs_direct.c b/contrib/amd/amd/amfs_direct.c deleted file mode 100644 index dbef743d0d7e..000000000000 --- a/contrib/amd/amd/amfs_direct.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/amfs_direct.c - * - */ - -/* - * Direct file system - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/**************************************************************************** - *** FORWARD DEFINITIONS *** - ****************************************************************************/ -static am_node *amfs_direct_readlink(am_node *mp, int *error_return); - -/**************************************************************************** - *** OPS STRUCTURES *** - ****************************************************************************/ -am_ops amfs_direct_ops = -{ - "direct", - amfs_generic_match, - 0, /* amfs_direct_init */ - amfs_toplvl_mount, - amfs_toplvl_umount, - amfs_generic_lookup_child, - amfs_generic_mount_child, - amfs_error_readdir, - amfs_direct_readlink, - amfs_generic_mounted, - 0, /* amfs_direct_umounted */ - amfs_generic_find_srvr, - 0, /* amfs_direct_get_wchan */ - FS_DIRECT | FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO, -#ifdef HAVE_FS_AUTOFS - AUTOFS_DIRECT_FS_FLAGS, -#endif /* HAVE_FS_AUTOFS */ -}; - - -/**************************************************************************** - *** FUNCTIONS *** - ****************************************************************************/ - -static am_node * -amfs_direct_readlink(am_node *mp, int *error_return) -{ - am_node *xp; - int rc = 0; - - xp = next_nonerror_node(mp->am_child); - if (!xp) { - if (!mp->am_mnt->mf_private) - amfs_mkcacheref(mp->am_mnt); /* XXX */ - xp = amfs_generic_lookup_child(mp, mp->am_path + 1, &rc, VLOOK_CREATE); - if (xp && rc < 0) - xp = amfs_generic_mount_child(xp, &rc); - } - if (xp) { - new_ttl(xp); /* (7/12/89) from Rein Tollevik */ - return xp; - } - if (amd_state == Finishing) - rc = ENOENT; - *error_return = rc; - return 0; -} diff --git a/contrib/amd/amd/amfs_error.c b/contrib/amd/amd/amfs_error.c deleted file mode 100644 index 51bdaa6db14d..000000000000 --- a/contrib/amd/amd/amfs_error.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 1997-2006 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 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. - * - * - * File: am-utils/amd/amfs_error.c - * - */ - -/* - * Error file system. - * This is used as a last resort catchall if - * nothing else worked. EFS just returns lots - * of error codes, except for unmount which - * always works of course. - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -static char *amfs_error_match(am_opts *fo); -static int amfs_error_mount(am_node *am, mntfs *mf); -static int amfs_error_umount(am_node *am, mntfs *mf); - - -/* - * Ops structure - */ -am_ops amfs_error_ops = -{ - "error", - amfs_error_match, - 0, /* amfs_error_init */ - amfs_error_mount, - amfs_error_umount, - amfs_error_lookup_child, - amfs_error_mount_child, - amfs_error_readdir, - 0, /* amfs_error_readlink */ - 0, /* amfs_error_mounted */ - 0, /* amfs_error_umounted */ - amfs_generic_find_srvr, - 0, /* amfs_error_get_wchan */ - FS_DISCARD, /* nfs_fs_flags */ -#ifdef HAVE_FS_AUTOFS - AUTOFS_ERROR_FS_FLAGS, -#endif /* HAVE_FS_AUTOFS */ -}; - - - -/* - * EFS file system always matches - */ -static char * -amfs_error_match(am_opts *fo) -{ - return strdup("(error-hook)"); -} - - -static int -amfs_error_mount(am_node *am, mntfs *mf) -{ - return ENOENT; -} - - -static int -amfs_error_umount(am_node *am, mntfs *mf) -{ - /* - * Always succeed - */ - return 0; -} - - -/* - * EFS interface to RPC lookup() routine. - * Should never get here in the automounter. - * If we do then just give an error. - */ -am_node * -amfs_error_lookup_child(am_node *mp, char *fname, int *error_return, int op) -{ - *error_return = ESTALE; - return 0; -} - - -/* - * EFS interface to RPC lookup() routine. - * Should never get here in the automounter. - * If we do then just give an error. - */ -am_node * -amfs_error_mount_child(am_node *ap, int *error_return) -{ - *error_return = ESTALE; - return 0; -} - - -/* - * EFS interface to RPC readdir() routine. - * Should never get here in the automounter. - * If we do then just give an error. - */ -int -amfs_error_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count) -{ - return ESTALE; -} diff --git a/contrib/amd/amd/amfs_generic.c b/contrib/amd/amd/amfs_generic.c deleted file mode 100644 index 3e7c365a7593..000000000000 --- a/contrib/amd/amd/amfs_generic.c +++ /dev/null @@ -1,1262 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/amfs_generic.c - * - */ - -/* - * generic functions used by amfs filesystems, ripped out of amfs_auto.c. - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - - -/**************************************************************************** - *** MACROS *** - ****************************************************************************/ -#define IN_PROGRESS(cp) ((cp)->mp->am_mnt->mf_flags & MFF_MOUNTING) - - -/**************************************************************************** - *** STRUCTURES *** - ****************************************************************************/ -/* - * Mounting a file system may take a significant period of time. The - * problem is that if this is done in the main process thread then the - * entire automounter could be blocked, possibly hanging lots of processes - * on the system. Instead we use a continuation scheme to allow mounts to - * be attempted in a sub-process. When the sub-process exits we pick up the - * exit status (by convention a UN*X error number) and continue in a - * notifier. The notifier gets handed a data structure and can then - * determine whether the mount was successful or not. If not, it updates - * the data structure and tries again until there are no more ways to try - * the mount, or some other permanent error occurs. In the mean time no RPC - * reply is sent, even after the mount is successful. We rely on the RPC - * retry mechanism to resend the lookup request which can then be handled. - */ -struct continuation { - am_node *mp; /* Node we are trying to mount */ - int retry; /* Try again? */ - time_t start; /* Time we started this mount */ - int callout; /* Callout identifier */ - mntfs **mf; /* Current mntfs */ -}; - - -/**************************************************************************** - *** FORWARD DEFINITIONS *** - ****************************************************************************/ -static am_node *amfs_lookup_node(am_node *mp, char *fname, int *error_return); -static mntfs *amfs_lookup_one_mntfs(am_node *new_mp, mntfs *mf, char *ivec, - char *def_opts, char *pfname); -static mntfs **amfs_lookup_mntfs(am_node *new_mp, int *error_return); -static void amfs_cont(int rc, int term, opaque_t arg); -static void amfs_retry(int rc, int term, opaque_t arg); -static void free_continuation(struct continuation *cp); -static int amfs_bgmount(struct continuation *cp); -static char *amfs_parse_defaults(am_node *mp, mntfs *mf, char *def_opts); - - -/**************************************************************************** - *** FUNCTIONS *** - ****************************************************************************/ -static am_node * -amfs_lookup_node(am_node *mp, char *fname, int *error_return) -{ - am_node *new_mp; - int error = 0; /* Error so far */ - int in_progress = 0; /* # of (un)mount in progress */ - mntfs *mf; - char *expanded_fname = 0; - - dlog("in amfs_lookup_node"); - - /* - * If the server is shutting down - * then don't return information - * about the mount point. - */ - if (amd_state == Finishing) { - if (mp->am_mnt == 0 || mp->am_mnt->mf_fsflags & FS_DIRECT) { - dlog("%s mount ignored - going down", fname); - } else { - dlog("%s/%s mount ignored - going down", mp->am_path, fname); - } - ereturn(ENOENT); - } - - /* - * Handle special case of "." and ".." - */ - if (fname[0] == '.') { - if (fname[1] == '\0') - return mp; /* "." is the current node */ - if (fname[1] == '.' && fname[2] == '\0') { - if (mp->am_parent) { - dlog(".. in %s gives %s", mp->am_path, mp->am_parent->am_path); - return mp->am_parent; /* ".." is the parent node */ - } - ereturn(ESTALE); - } - } - - /* - * Check for valid key name. - * If it is invalid then pretend it doesn't exist. - */ - if (!valid_key(fname)) { - plog(XLOG_WARNING, "Key \"%s\" contains a disallowed character", fname); - ereturn(ENOENT); - } - - /* - * Expand key name. - * expanded_fname is now a private copy. - */ - expanded_fname = expand_selectors(fname); - - /* - * Search children of this node - */ - for (new_mp = mp->am_child; new_mp; new_mp = new_mp->am_osib) { - if (FSTREQ(new_mp->am_name, expanded_fname)) { - if (new_mp->am_error) { - error = new_mp->am_error; - continue; - } - - /* - * If the error code is undefined then it must be - * in progress. - */ - mf = new_mp->am_mnt; - if (mf->mf_error < 0) - goto in_progrss; - - /* - * If there was a previous error with this node - * then return that error code. - */ - if (mf->mf_flags & MFF_ERROR) { - error = mf->mf_error; - continue; - } - if (!(mf->mf_flags & MFF_MOUNTED) || (mf->mf_flags & MFF_UNMOUNTING)) { - in_progrss: - /* - * If the fs is not mounted or it is unmounting then there - * is a background (un)mount in progress. In this case - * we just drop the RPC request (return nil) and - * wait for a retry, by which time the (un)mount may - * have completed. - */ - dlog("ignoring mount of %s in %s -- %smounting in progress, flags %x", - expanded_fname, mf->mf_mount, - (mf->mf_flags & MFF_UNMOUNTING) ? "un" : "", mf->mf_flags); - in_progress++; - if (mf->mf_flags & MFF_UNMOUNTING) { - dlog("will remount later"); - new_mp->am_flags |= AMF_REMOUNT; - } - continue; - } - - /* - * Otherwise we have a hit: return the current mount point. - */ - dlog("matched %s in %s", expanded_fname, new_mp->am_path); - XFREE(expanded_fname); - return new_mp; - } - } - - if (in_progress) { - dlog("Waiting while %d mount(s) in progress", in_progress); - XFREE(expanded_fname); - ereturn(-1); - } - - /* - * If an error occurred then return it. - */ - if (error) { - dlog("Returning error: %s", strerror(error)); - XFREE(expanded_fname); - ereturn(error); - } - - /* - * If the server is going down then just return, - * don't try to mount any more file systems - */ - if ((int) amd_state >= (int) Finishing) { - dlog("not found - server going down anyway"); - ereturn(ENOENT); - } - - /* - * Allocate a new map - */ - new_mp = get_ap_child(mp, expanded_fname); - XFREE(expanded_fname); - if (new_mp == 0) - ereturn(ENOSPC); - - *error_return = -1; - return new_mp; -} - - - -static mntfs * -amfs_lookup_one_mntfs(am_node *new_mp, mntfs *mf, char *ivec, - char *def_opts, char *pfname) -{ - am_ops *p; - am_opts *fs_opts; - mntfs *new_mf; - char *mp_dir = 0; -#ifdef HAVE_FS_AUTOFS - int on_autofs = 1; -#endif /* HAVE_FS_AUTOFS */ - - /* match the operators */ - fs_opts = CALLOC(am_opts); - p = ops_match(fs_opts, ivec, def_opts, new_mp->am_path, - pfname, mf->mf_info); -#ifdef HAVE_FS_AUTOFS - /* XXX: this should be factored out into an autofs-specific function */ - if (new_mp->am_flags & AMF_AUTOFS) { - /* ignore user-provided fs if we're using autofs */ - if (fs_opts->opt_sublink) { - /* - * For sublinks we need to use a hack with autofs: - * mount the filesystem on the original opt_fs (which is NOT an - * autofs mountpoint) and symlink (or lofs-mount) to it from - * the autofs mountpoint. - */ - on_autofs = 0; - mp_dir = fs_opts->opt_fs; - } else { - if (p->autofs_fs_flags & FS_ON_AUTOFS) { - mp_dir = new_mp->am_path; - } else { - mp_dir = fs_opts->opt_fs; - on_autofs = 0; - } - } - } else -#endif /* HAVE_FS_AUTOFS */ - mp_dir = fs_opts->opt_fs; - - /* - * Find or allocate a filesystem for this node. - */ - new_mf = find_mntfs(p, fs_opts, - mp_dir, - fs_opts->fs_mtab, - def_opts, - fs_opts->opt_opts, - fs_opts->opt_remopts); - - /* - * See whether this is a real filesystem - */ - p = new_mf->mf_ops; - if (p == &amfs_error_ops) { - plog(XLOG_MAP, "Map entry %s for %s did not match", ivec, new_mp->am_path); - free_mntfs(new_mf); - return NULL; - } - - dlog("Got a hit with %s", p->fs_type); - -#ifdef HAVE_FS_AUTOFS - if (new_mp->am_flags & AMF_AUTOFS && on_autofs) { - new_mf->mf_flags |= MFF_ON_AUTOFS; - new_mf->mf_fsflags = new_mf->mf_ops->autofs_fs_flags; - } - /* - * A new filesystem is an autofs filesystems if: - * 1. it claims it can be one (has the FS_AUTOFS flag) - * 2. autofs is enabled system-wide - * 3. either has an autofs parent, - * or it is explicitly requested to be autofs. - */ - if (new_mf->mf_ops->autofs_fs_flags & FS_AUTOFS && - amd_use_autofs && - ((mf->mf_flags & MFF_IS_AUTOFS) || - (new_mf->mf_fo && new_mf->mf_fo->opt_mount_type && - STREQ(new_mf->mf_fo->opt_mount_type, "autofs")))) - new_mf->mf_flags |= MFF_IS_AUTOFS; -#endif /* HAVE_FS_AUTOFS */ - - return new_mf; -} - - -static mntfs ** -amfs_lookup_mntfs(am_node *new_mp, int *error_return) -{ - am_node *mp; - char *info; /* Mount info - where to get the file system */ - char **ivecs, **cur_ivec; /* Split version of info */ - int num_ivecs; - char *orig_def_opts; /* Original Automount options */ - char *def_opts; /* Automount options */ - int error = 0; /* Error so far */ - char path_name[MAXPATHLEN]; /* General path name buffer */ - char *pfname; /* Path for database lookup */ - mntfs *mf, **mf_array; - int count; - - dlog("in amfs_lookup_mntfs"); - - mp = new_mp->am_parent; - - /* - * If we get here then this is a reference to an, - * as yet, unknown name so we need to search the mount - * map for it. - */ - if (mp->am_pref) { - if (strlen(mp->am_pref) + strlen(new_mp->am_name) >= sizeof(path_name)) - ereturn(ENAMETOOLONG); - xsnprintf(path_name, sizeof(path_name), "%s%s", mp->am_pref, new_mp->am_name); - pfname = path_name; - } else { - pfname = new_mp->am_name; - } - - mf = mp->am_mnt; - - dlog("will search map info in %s to find %s", mf->mf_info, pfname); - /* - * Consult the oracle for some mount information. - * info is malloc'ed and belongs to this routine. - * It ends up being free'd in free_continuation(). - * - * Note that this may return -1 indicating that information - * is not yet available. - */ - error = mapc_search((mnt_map *) mf->mf_private, pfname, &info); - if (error) { - if (error > 0) - plog(XLOG_MAP, "No map entry for %s", pfname); - else - plog(XLOG_MAP, "Waiting on map entry for %s", pfname); - ereturn(error); - } - dlog("mount info is %s", info); - - /* - * Split info into an argument vector. - * The vector is malloc'ed and belongs to - * this routine. It is free'd further down. - * - * Note: the vector pointers point into info, so don't free it! - */ - ivecs = strsplit(info, ' ', '\"'); - - if (mf->mf_auto) - def_opts = mf->mf_auto; - else - def_opts = ""; - - orig_def_opts = amfs_parse_defaults(mp, mf, strdup(def_opts)); - def_opts = strdup(orig_def_opts); - - /* first build our defaults */ - num_ivecs = 0; - for (cur_ivec = ivecs; *cur_ivec; cur_ivec++) { - if (**cur_ivec == '-') { - /* - * Pick up new defaults - */ - char *new_def_opts = str3cat(NULL, def_opts, ";", *cur_ivec + 1); - XFREE(def_opts); - def_opts = new_def_opts; - dlog("Setting def_opts to \"%s\"", def_opts); - continue; - } else - num_ivecs++; - } - - mf_array = calloc(num_ivecs + 1, sizeof(mntfs *)); - - /* construct the array of struct mntfs for this mount point */ - for (count = 0, cur_ivec = ivecs; *cur_ivec; cur_ivec++) { - mntfs *new_mf; - - if (**cur_ivec == '-') { - XFREE(def_opts); - if ((*cur_ivec)[1] == '\0') { - /* - * If we have a single dash '-' than we need to reset the - * default options. - */ - def_opts = strdup(orig_def_opts); - dlog("Resetting the default options, a single dash '-' was found."); - } else { - /* append options to /default options */ - def_opts = str3cat((char *) 0, orig_def_opts, ";", *cur_ivec + 1); - dlog("Resetting def_opts to \"%s\"", def_opts); - } - continue; - } - - /* - * If a mntfs has already been found, and we find - * a cut then don't try any more locations. - * - * XXX: we do not know when the "/" was added as an equivalent for "||". - * It's undocumented, it might go away at any time. Caveat emptor. - */ - if (STREQ(*cur_ivec, "/") || STREQ(*cur_ivec, "||")) { - if (count > 0) { - dlog("Cut: not trying any more locations for %s", mp->am_path); - break; - } - continue; - } - - new_mf = amfs_lookup_one_mntfs(new_mp, mf, *cur_ivec, def_opts, pfname); - if (new_mf == NULL) - continue; - mf_array[count++] = new_mf; - } - - /* We're done with ivecs */ - XFREE(ivecs); - XFREE(info); - XFREE(orig_def_opts); - XFREE(def_opts); - if (count == 0) { /* no match */ - XFREE(mf_array); - ereturn(ENOENT); - } - - return mf_array; -} - - -/* - * The continuation function. This is called by - * the task notifier when a background mount attempt - * completes. - */ -static void -amfs_cont(int rc, int term, opaque_t arg) -{ - struct continuation *cp = (struct continuation *) arg; - am_node *mp = cp->mp; - mntfs *mf = mp->am_mnt; - - dlog("amfs_cont: '%s'", mp->am_path); - - /* - * Definitely not trying to mount at the moment - */ - mf->mf_flags &= ~MFF_MOUNTING; - - /* - * While we are mounting - try to avoid race conditions - */ - new_ttl(mp); - - /* - * Wakeup anything waiting for this mount - */ - wakeup(get_mntfs_wchan(mf)); - - /* - * Check for termination signal or exit status... - */ - if (rc || term) { -#ifdef HAVE_FS_AUTOFS - if (mf->mf_flags & MFF_IS_AUTOFS && - !(mf->mf_flags & MFF_MOUNTED)) - autofs_release_fh(mp); -#endif /* HAVE_FS_AUTOFS */ - - if (term) { - /* - * Not sure what to do for an error code. - */ - mf->mf_error = EIO; /* XXX ? */ - mf->mf_flags |= MFF_ERROR; - plog(XLOG_ERROR, "mount for %s got signal %d", mp->am_path, term); - } else { - /* - * Check for exit status... - */ -#ifdef __linux__ - /* - * HACK ALERT! - * - * On Linux (and maybe not only) it's possible to run - * an amd which "knows" how to mount certain combinations - * of nfs_proto/nfs_version which the kernel doesn't grok. - * So if we got an EINVAL and we have a server that's not - * using NFSv2/UDP, try again with NFSv2/UDP. - * - * Too bad that there is no way to dynamically determine - * what combinations the _client_ supports, as opposed to - * what the _server_ supports... - */ - if (rc == EINVAL && - mf->mf_server && - (mf->mf_server->fs_version != 2 || - !STREQ(mf->mf_server->fs_proto, "udp"))) - mf->mf_flags |= MFF_NFS_SCALEDOWN; - else -#endif /* __linux__ */ - { - mf->mf_error = rc; - mf->mf_flags |= MFF_ERROR; - errno = rc; /* XXX */ - if (!STREQ(mp->am_mnt->mf_ops->fs_type, "linkx")) - plog(XLOG_ERROR, "%s: mount (amfs_cont): %m", mp->am_path); - } - } - - if (!(mf->mf_flags & MFF_NFS_SCALEDOWN)) { - /* - * If we get here then that attempt didn't work, so - * move the info vector pointer along by one and - * call the background mount routine again - */ - amd_stats.d_merr++; - cp->mf++; - } - amfs_bgmount(cp); - if (mp->am_error > 0) - assign_error_mntfs(mp); - } else { - /* - * The mount worked. - */ - dlog("Mounting %s returned success", cp->mp->am_path); - am_mounted(cp->mp); - free_continuation(cp); - } - - reschedule_timeout_mp(); -} - - -/* - * Retry a mount - */ -static void -amfs_retry(int rc, int term, opaque_t arg) -{ - struct continuation *cp = (struct continuation *) arg; - am_node *mp = cp->mp; - int error = 0; - - dlog("Commencing retry for mount of %s", mp->am_path); - - new_ttl(mp); - - if ((cp->start + ALLOWED_MOUNT_TIME) < clocktime(NULL)) { - /* - * The entire mount has timed out. Set the error code and skip past all - * the mntfs's so that amfs_bgmount will not have any more - * ways to try the mount, thus causing an error. - */ - plog(XLOG_INFO, "mount of \"%s\" has timed out", mp->am_path); - error = ETIMEDOUT; - while (*cp->mf) - cp->mf++; - /* explicitly forbid further retries after timeout */ - cp->retry = FALSE; - } - if (error || !IN_PROGRESS(cp)) - error = amfs_bgmount(cp); - - reschedule_timeout_mp(); -} - - -/* - * Discard an old continuation - */ -static void -free_continuation(struct continuation *cp) -{ - mntfs **mfp; - - dlog("free_continuation"); - if (cp->callout) - untimeout(cp->callout); - /* - * we must free the mntfs's in the list. - * so free all of them if there was an error, - * or free all but the used one, if the mount succeeded. - */ - for (mfp = cp->mp->am_mfarray; *mfp; mfp++) { - free_mntfs(*mfp); - } - XFREE(cp->mp->am_mfarray); - cp->mp->am_mfarray = 0; - XFREE(cp); -} - - -/* - * Pick a file system to try mounting and - * do that in the background if necessary - * -For each location: - discard previous mount location if required - fetch next mount location - if the filesystem failed to be mounted then - this_error = error from filesystem - goto failed - if the filesystem is mounting or unmounting then - goto retry; - if the fileserver is down then - this_error = EIO - continue; - if the filesystem is already mounted - break - fi - - this_error = initialize mount point - - if no error on this mount and mount is delayed then - this_error = -1 - fi - if this_error < 0 then - retry = true - fi - if no error on this mount then - if mount in background then - run mount in background - return -1 - else - this_error = mount in foreground - fi - fi - if an error occurred on this mount then - update stats - save error in mount point - fi -endfor - */ -static int -amfs_bgmount(struct continuation *cp) -{ - am_node *mp = cp->mp; - mntfs *mf; /* Current mntfs */ - int this_error = -1; /* Per-mount error */ - int hard_error = -1; /* Cumulative per-node error */ - - if (mp->am_mnt) - free_mntfs(mp->am_mnt); - - /* - * Try to mount each location. - * At the end: - * hard_error == 0 indicates something was mounted. - * hard_error > 0 indicates everything failed with a hard error - * hard_error < 0 indicates nothing could be mounted now - */ - for (mp->am_mnt = *cp->mf; *cp->mf; cp->mf++, mp->am_mnt = *cp->mf) { - am_ops *p; - - mf = dup_mntfs(mp->am_mnt); - p = mf->mf_ops; - - if (hard_error < 0) - hard_error = this_error; - this_error = 0; - - if (mf->mf_error > 0) { - this_error = mf->mf_error; - goto failed; - } - - if (mf->mf_flags & (MFF_MOUNTING | MFF_UNMOUNTING)) { - /* - * Still mounting - retry later - */ - dlog("mount of \"%s\" already pending", mf->mf_info); - goto retry; - } - - if (FSRV_ISDOWN(mf->mf_server)) { - /* - * Would just mount from the same place - * as a hung mount - so give up - */ - dlog("%s is already hung - giving up", mf->mf_server->fs_host); - this_error = EIO; - goto failed; - } - - if (mp->am_link) { - XFREE(mp->am_link); - mp->am_link = NULL; - } - if (mf->mf_fo && mf->mf_fo->opt_sublink) - mp->am_link = strdup(mf->mf_fo->opt_sublink); - - /* - * Will usually need to play around with the mount nodes - * file attribute structure. This must be done here. - * Try and get things initialized, even if the fileserver - * is not known to be up. In the common case this will - * progress things faster. - */ - - /* - * Fill in attribute fields. - */ - if (mf->mf_fsflags & FS_DIRECTORY) - mk_fattr(&mp->am_fattr, NFDIR); - else - mk_fattr(&mp->am_fattr, NFLNK); - - if (mf->mf_flags & MFF_MOUNTED) { - dlog("duplicate mount of \"%s\" ...", mf->mf_info); - /* - * Skip initial processing of the mountpoint if already mounted. - * This could happen if we have multiple sublinks into the same f/s, - * or if we are restarting an already-mounted filesystem. - */ - goto already_mounted; - } - - if (mf->mf_fo && mf->mf_fo->fs_mtab) { - plog(XLOG_MAP, "Trying mount of %s on %s fstype %s mount_type %s", - mf->mf_fo->fs_mtab, mf->mf_mount, p->fs_type, - mp->am_flags & AMF_AUTOFS ? "autofs" : "non-autofs"); - } - - if (p->fs_init && !(mf->mf_flags & MFF_RESTART)) - this_error = p->fs_init(mf); - - if (this_error > 0) - goto failed; - if (this_error < 0) - goto retry; - - if (mf->mf_fo && mf->mf_fo->opt_delay) { - /* - * If there is a delay timer on the mount - * then don't try to mount if the timer - * has not expired. - */ - int i = atoi(mf->mf_fo->opt_delay); - time_t now = clocktime(NULL); - if (i > 0 && now < (cp->start + i)) { - dlog("Mount of %s delayed by %lds", mf->mf_mount, (long) (i - now + cp->start)); - goto retry; - } - } - - /* - * If the directory is not yet made and it needs to be made, then make it! - */ - if (!(mf->mf_flags & MFF_MKMNT) && mf->mf_fsflags & FS_MKMNT) { - plog(XLOG_INFO, "creating mountpoint directory '%s'", mf->mf_mount); - this_error = mkdirs(mf->mf_mount, 0555); - if (this_error) { - plog(XLOG_ERROR, "mkdirs failed: %s", strerror(this_error)); - goto failed; - } - mf->mf_flags |= MFF_MKMNT; - } - -#ifdef HAVE_FS_AUTOFS - if (mf->mf_flags & MFF_IS_AUTOFS) - if ((this_error = autofs_get_fh(mp))) - goto failed; -#endif /* HAVE_FS_AUTOFS */ - - already_mounted: - mf->mf_flags |= MFF_MOUNTING; - if (mf->mf_fsflags & FS_MBACKGROUND) { - dlog("backgrounding mount of \"%s\"", mf->mf_mount); - if (cp->callout) { - untimeout(cp->callout); - cp->callout = 0; - } - - /* actually run the task, backgrounding as necessary */ - run_task(mount_node, (opaque_t) mp, amfs_cont, (opaque_t) cp); - return -1; - } else { - dlog("foreground mount of \"%s\" ...", mf->mf_mount); - this_error = mount_node((opaque_t) mp); - } - - mf->mf_flags &= ~MFF_MOUNTING; - if (this_error > 0) - goto failed; - if (this_error == 0) { - am_mounted(mp); - break; /* Success */ - } - - retry: - if (!cp->retry) - continue; - dlog("will retry ...\n"); - - /* - * Arrange that amfs_bgmount is called - * after anything else happens. - */ - dlog("Arranging to retry mount of %s", mp->am_path); - sched_task(amfs_retry, (opaque_t) cp, get_mntfs_wchan(mf)); - if (cp->callout) - untimeout(cp->callout); - cp->callout = timeout(RETRY_INTERVAL, wakeup, - (opaque_t) get_mntfs_wchan(mf)); - - mp->am_ttl = clocktime(NULL) + RETRY_INTERVAL; - - /* - * Not done yet - so don't return anything - */ - return -1; - - failed: - amd_stats.d_merr++; - mf->mf_error = this_error; - mf->mf_flags |= MFF_ERROR; -#ifdef HAVE_FS_AUTOFS - if (mp->am_autofs_fh) - autofs_release_fh(mp); -#endif /* HAVE_FS_AUTOFS */ - if (mf->mf_flags & MFF_MKMNT) { - rmdirs(mf->mf_mount); - mf->mf_flags &= ~MFF_MKMNT; - } - /* - * Wakeup anything waiting for this mount - */ - wakeup(get_mntfs_wchan(mf)); - free_mntfs(mf); - /* continue */ - } - - /* - * If we get here, then either the mount succeeded or - * there is no more mount information available. - */ - if (this_error) { - mp->am_mnt = mf = new_mntfs(); - -#ifdef HAVE_FS_AUTOFS - if (mp->am_flags & AMF_AUTOFS) - autofs_mount_failed(mp); - else -#endif /* HAVE_FS_AUTOFS */ - nfs_quick_reply(mp, this_error); - - if (hard_error <= 0) - hard_error = this_error; - if (hard_error < 0) - hard_error = ETIMEDOUT; - - /* - * Set a small(ish) timeout on an error node if - * the error was not a time out. - */ - switch (hard_error) { - case ETIMEDOUT: - case EWOULDBLOCK: - case EIO: - mp->am_timeo = 17; - break; - default: - mp->am_timeo = 5; - break; - } - new_ttl(mp); - } else { - mf = mp->am_mnt; - /* - * Wakeup anything waiting for this mount - */ - wakeup(get_mntfs_wchan(mf)); - hard_error = 0; - } - - /* - * Make sure that the error value in the mntfs has a - * reasonable value. - */ - if (mf->mf_error < 0) { - mf->mf_error = hard_error; - if (hard_error) - mf->mf_flags |= MFF_ERROR; - } - - /* - * In any case we don't need the continuation any more - */ - free_continuation(cp); - - return hard_error; -} - - -static char * -amfs_parse_defaults(am_node *mp, mntfs *mf, char *def_opts) -{ - char *dflts; - char *dfl; - char **rvec = NULL; - struct mnt_map *mm = (mnt_map *) mf->mf_private; - - dlog("determining /defaults entry value"); - - /* - * Find out if amd.conf overrode any map-specific /defaults. - * - * HACK ALERT: there's no easy way to find out what the map mount point is - * at this point, so I am forced to initialize the mnt_map->cfm field here - * for the first time, upon the very first search for a /defaults entry in - * this map. This initialization is much better done in mapc_create(), - * but it's impossible to do that there with the current code structure. - */ - if (mm->cfm == NULL) { /* then initialize it for first time */ - mm->cfm = find_cf_map(mf->mf_mount); - } - if (mm->cfm && mm->cfm->cfm_defaults) { - dlog("map %s map_defaults override: %s", mf->mf_mount, mm->cfm->cfm_defaults); - dflts = strdup(mm->cfm->cfm_defaults); - } else if (mapc_search(mm, "/defaults", &dflts) == 0) { - dlog("/defaults gave %s", dflts); - } else { - return def_opts; /* if nothing found */ - } - - /* trim leading '-' in case thee's one */ - if (*dflts == '-') - dfl = dflts + 1; - else - dfl = dflts; - - /* - * Chop the defaults up - */ - rvec = strsplit(dfl, ' ', '\"'); - - if (gopt.flags & CFM_SELECTORS_IN_DEFAULTS) { - /* - * Pick whichever first entry matched the list of selectors. - * Strip the selectors from the string, and assign to dfl the - * rest of the string. - */ - if (rvec) { - am_opts ap; - am_ops *pt; - char **sp = rvec; - while (*sp) { /* loop until you find something, if any */ - memset((char *) &ap, 0, sizeof(am_opts)); - /* - * This next routine cause many spurious "expansion of ... is" - * messages, which are ignored, b/c all we need out of this - * routine is to match selectors. These spurious messages may - * be wrong, esp. if they try to expand ${key} b/c it will - * get expanded to "/defaults" - */ - pt = ops_match(&ap, *sp, "", mp->am_path, "/defaults", - mp->am_parent->am_mnt->mf_info); - free_opts(&ap); /* don't leak */ - if (pt == &amfs_error_ops) { - plog(XLOG_MAP, "did not match defaults for \"%s\"", *sp); - } else { - dfl = strip_selectors(*sp, "/defaults"); - plog(XLOG_MAP, "matched default selectors \"%s\"", dfl); - break; - } - ++sp; - } - } - } else { /* not selectors_in_defaults */ - /* - * Extract first value - */ - dfl = rvec[0]; - } - - /* - * If there were any values at all... - */ - if (dfl) { - /* - * Log error if there were other values - */ - if (!(gopt.flags & CFM_SELECTORS_IN_DEFAULTS) && rvec[1]) { - dlog("/defaults chopped into %s", dfl); - plog(XLOG_USER, "More than a single value for /defaults in %s", mf->mf_info); - } - - /* - * Prepend to existing defaults if they exist, - * otherwise just use these defaults. - */ - if (*def_opts && *dfl) { - size_t l = strlen(def_opts) + strlen(dfl) + 2; - char *nopts = (char *) xmalloc(l); - xsnprintf(nopts, l, "%s;%s", dfl, def_opts); - XFREE(def_opts); - def_opts = nopts; - } else if (*dfl) { - def_opts = strealloc(def_opts, dfl); - } - } - - XFREE(dflts); - - /* don't need info vector any more */ - if (rvec) - XFREE(rvec); - - return def_opts; -} - - -am_node * -amfs_generic_mount_child(am_node *new_mp, int *error_return) -{ - int error; - struct continuation *cp; /* Continuation structure if need to mount */ - - dlog("in amfs_generic_mount_child"); - - *error_return = error = 0; /* Error so far */ - - /* we have an errorfs attached to the am_node, free it */ - free_mntfs(new_mp->am_mnt); - new_mp->am_mnt = 0; - - /* - * Construct a continuation - */ - cp = ALLOC(struct continuation); - cp->callout = 0; - cp->mp = new_mp; - cp->retry = TRUE; - cp->start = clocktime(NULL); - cp->mf = new_mp->am_mfarray; - - /* - * Try and mount the file system. If this succeeds immediately (possible - * for a ufs file system) then return the attributes, otherwise just - * return an error. - */ - error = amfs_bgmount(cp); - reschedule_timeout_mp(); - if (!error) - return new_mp; - - /* - * Code for quick reply. If current_transp is set, then it's the - * transp that's been passed down from nfs_program_2() or from - * autofs_program_[123](). - * If new_mp->am_transp is not already set, set it by copying in - * current_transp. Once am_transp is set, nfs_quick_reply() and - * autofs_mount_succeeded() can use it to send a reply to the - * client that requested this mount. - */ - if (current_transp && !new_mp->am_transp) { - dlog("Saving RPC transport for %s", new_mp->am_path); - new_mp->am_transp = (SVCXPRT *) xmalloc(sizeof(SVCXPRT)); - *(new_mp->am_transp) = *current_transp; - } - if (error && (new_mp->am_mnt->mf_ops == &amfs_error_ops)) - new_mp->am_error = error; - - if (new_mp->am_error > 0) - assign_error_mntfs(new_mp); - - ereturn(error); -} - - -/* - * Automount interface to RPC lookup routine - * Find the corresponding entry and return - * the file handle for it. - */ -am_node * -amfs_generic_lookup_child(am_node *mp, char *fname, int *error_return, int op) -{ - am_node *new_mp; - mntfs **mf_array; - int mp_error; - - dlog("in amfs_generic_lookup_child"); - - *error_return = 0; - new_mp = amfs_lookup_node(mp, fname, error_return); - - /* return if we got an error */ - if (!new_mp || *error_return > 0) - return new_mp; - - /* also return if it's already mounted and known to be up */ - if (*error_return == 0 && FSRV_ISUP(new_mp->am_mnt->mf_server)) - return new_mp; - - switch (op) { - case VLOOK_DELETE: - /* - * If doing a delete then don't create again! - */ - ereturn(ENOENT); - case VLOOK_LOOKUP: - return new_mp; - } - - /* save error_return */ - mp_error = *error_return; - - mf_array = amfs_lookup_mntfs(new_mp, error_return); - if (!mf_array) { - new_mp->am_error = new_mp->am_mnt->mf_error = *error_return; - free_map(new_mp); - return NULL; - } - - /* - * Already mounted but known to be down: - * check if we have any alternatives to mount - */ - if (mp_error == 0) { - mntfs **mfp; - for (mfp = mf_array; *mfp; mfp++) - if (*mfp != new_mp->am_mnt) - break; - if (*mfp != NULL) { - /* - * we found an alternative, so try mounting again. - */ - *error_return = -1; - } else { - for (mfp = mf_array; *mfp; mfp++) - free_mntfs(*mfp); - XFREE(mf_array); - if (new_mp->am_flags & AMF_SOFTLOOKUP) { - ereturn(EIO); - } else { - *error_return = 0; - return new_mp; - } - } - } - - /* store the array inside the am_node */ - new_mp->am_mfarray = mf_array; - - /* - * Note: while it might seem like a good idea to prioritize - * the list of mntfs's we got here, it probably isn't. - * It would ignore the ordering of entries specified by the user, - * which is counterintuitive and confusing. - */ - return new_mp; -} - - -void -amfs_generic_mounted(mntfs *mf) -{ - amfs_mkcacheref(mf); -} - - -/* - * Unmount an automount sub-node - */ -int -amfs_generic_umount(am_node *mp, mntfs *mf) -{ - int error = 0; - -#ifdef HAVE_FS_AUTOFS - int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0; - if (mf->mf_flags & MFF_IS_AUTOFS) - error = UMOUNT_FS(mp->am_path, mnttab_file_name, unmount_flags); -#endif /* HAVE_FS_AUTOFS */ - - return error; -} - - -char * -amfs_generic_match(am_opts *fo) -{ - char *p; - - if (!fo->opt_rfs) { - plog(XLOG_USER, "amfs_generic_match: no mount point named (rfs:=)"); - return 0; - } - if (!fo->opt_fs) { - plog(XLOG_USER, "amfs_generic_match: no map named (fs:=)"); - return 0; - } - - /* - * Swap round fs:= and rfs:= options - * ... historical (jsp) - */ - p = fo->opt_rfs; - fo->opt_rfs = fo->opt_fs; - fo->opt_fs = p; - - /* - * mtab entry turns out to be the name of the mount map - */ - return strdup(fo->opt_rfs ? fo->opt_rfs : "."); -} diff --git a/contrib/amd/amd/amfs_host.c b/contrib/amd/amd/amfs_host.c deleted file mode 100644 index 55423c46ea33..000000000000 --- a/contrib/amd/amd/amfs_host.c +++ /dev/null @@ -1,709 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/amfs_host.c - * - */ - -/* - * NFS host file system. - * Mounts all exported filesystems from a given host. - * This has now degenerated into a mess but will not - * be rewritten. Amd 6 will support the abstractions - * needed to make this work correctly. - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -static char *amfs_host_match(am_opts *fo); -static int amfs_host_init(mntfs *mf); -static int amfs_host_mount(am_node *am, mntfs *mf); -static int amfs_host_umount(am_node *am, mntfs *mf); -static void amfs_host_umounted(mntfs *mf); - -/* - * Ops structure - */ -am_ops amfs_host_ops = -{ - "host", - amfs_host_match, - amfs_host_init, - amfs_host_mount, - amfs_host_umount, - amfs_error_lookup_child, - amfs_error_mount_child, - amfs_error_readdir, - 0, /* amfs_host_readlink */ - 0, /* amfs_host_mounted */ - amfs_host_umounted, - find_nfs_srvr, - 0, /* amfs_host_get_wchan */ - FS_MKMNT | FS_BACKGROUND | FS_AMQINFO, -#ifdef HAVE_FS_AUTOFS - AUTOFS_HOST_FS_FLAGS, -#endif /* HAVE_FS_AUTOFS */ -}; - - -/* - * Determine the mount point: - * - * The next change we put in to better handle PCs. This is a bit - * disgusting, so you'd better sit down. We change the make_mntpt function - * to look for exported file systems without a leading '/'. If they don't - * have a leading '/', we add one. If the export is 'a:' through 'z:' - * (without a leading slash), we change it to 'a%' (or b% or z%). This - * allows the entire PC disk to be mounted. - */ -static void -make_mntpt(char *mntpt, size_t l, const exports ex, const char *mf_mount) -{ - if (ex->ex_dir[0] == '/') { - if (ex->ex_dir[1] == 0) - xstrlcpy(mntpt, mf_mount, l); - else - xsnprintf(mntpt, l, "%s%s", mf_mount, ex->ex_dir); - } else if (ex->ex_dir[0] >= 'a' && - ex->ex_dir[0] <= 'z' && - ex->ex_dir[1] == ':' && - ex->ex_dir[2] == '/' && - ex->ex_dir[3] == 0) - xsnprintf(mntpt, l, "%s/%c%%", mf_mount, ex->ex_dir[0]); - else - xsnprintf(mntpt, l, "%s/%s", mf_mount, ex->ex_dir); -} - - -/* - * Execute needs the same as NFS plus a helper command - */ -static char * -amfs_host_match(am_opts *fo) -{ - extern am_ops nfs_ops; - - /* - * Make sure rfs is specified to keep nfs_match happy... - */ - if (!fo->opt_rfs) - fo->opt_rfs = "/"; - - return (*nfs_ops.fs_match) (fo); -} - - -static int -amfs_host_init(mntfs *mf) -{ - u_short mountd_port; - - if (strchr(mf->mf_info, ':') == 0) - return ENOENT; - - /* - * This is primarily to schedule a wakeup so that as soon - * as our fileserver is ready, we can continue setting up - * the host filesystem. If we don't do this, the standard - * amfs_auto code will set up a fileserver structure, but it will - * have to wait for another nfs request from the client to come - * in before finishing. Our way is faster since we don't have - * to wait for the client to resend its request (which could - * take a second or two). - */ - /* - * First, we find the fileserver for this mntfs and then call - * get_mountd_port with our mntfs passed as the wait channel. - * get_mountd_port will check some things and then schedule - * it so that when the fileserver is ready, a wakeup is done - * on this mntfs. amfs_cont() is already sleeping on this mntfs - * so as soon as that wakeup happens amfs_cont() is called and - * this mount is retried. - */ - if (mf->mf_server) - /* - * We don't really care if there's an error returned. - * Since this is just to help speed things along, the - * error will get handled properly elsewhere. - */ - get_mountd_port(mf->mf_server, &mountd_port, get_mntfs_wchan(mf)); - - return 0; -} - - -static int -do_mount(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf) -{ - struct stat stb; - - dlog("amfs_host: mounting fs %s on %s\n", fs_name, mntdir); - - (void) mkdirs(mntdir, 0555); - if (stat(mntdir, &stb) < 0 || (stb.st_mode & S_IFMT) != S_IFDIR) { - plog(XLOG_ERROR, "No mount point for %s - skipping", mntdir); - return ENOENT; - } - - return mount_nfs_fh(fhp, mntdir, fs_name, mf); -} - - -static int -sortfun(const voidp x, const voidp y) -{ - exports *a = (exports *) x; - exports *b = (exports *) y; - - return strcmp((*a)->ex_dir, (*b)->ex_dir); -} - - -/* - * Get filehandle - */ -static int -fetch_fhandle(CLIENT *client, char *dir, am_nfs_handle_t *fhp, u_long nfs_version) -{ - struct timeval tv; - enum clnt_stat clnt_stat; - struct fhstatus res; -#ifdef HAVE_FS_NFS3 - struct am_mountres3 res3; -#endif /* HAVE_FS_NFS3 */ - - /* - * Pick a number, any number... - */ - tv.tv_sec = 20; - tv.tv_usec = 0; - - dlog("Fetching fhandle for %s", dir); - - /* - * Call the mount daemon on the remote host to - * get the filehandle. Use NFS version specific call. - */ - - plog(XLOG_INFO, "fetch_fhandle: NFS version %d", (int) nfs_version); -#ifdef HAVE_FS_NFS3 - if (nfs_version == NFS_VERSION3) { - memset((char *) &res3, 0, sizeof(res3)); - clnt_stat = clnt_call(client, - MOUNTPROC_MNT, - (XDRPROC_T_TYPE) xdr_dirpath, - (SVC_IN_ARG_TYPE) &dir, - (XDRPROC_T_TYPE) xdr_am_mountres3, - (SVC_IN_ARG_TYPE) &res3, - tv); - if (clnt_stat != RPC_SUCCESS) { - plog(XLOG_ERROR, "mountd rpc failed: %s", clnt_sperrno(clnt_stat)); - return EIO; - } - /* Check the status of the filehandle */ - if ((errno = res3.fhs_status)) { - dlog("fhandle fetch for mount version 3 failed: %m"); - return errno; - } - memset((voidp) &fhp->v3, 0, sizeof(am_nfs_fh3)); - fhp->v3.am_fh3_length = res3.mountres3_u.mountinfo.fhandle.fhandle3_len; - memmove(fhp->v3.am_fh3_data, - res3.mountres3_u.mountinfo.fhandle.fhandle3_val, - fhp->v3.am_fh3_length); - } else { /* not NFS_VERSION3 mount */ -#endif /* HAVE_FS_NFS3 */ - clnt_stat = clnt_call(client, - MOUNTPROC_MNT, - (XDRPROC_T_TYPE) xdr_dirpath, - (SVC_IN_ARG_TYPE) &dir, - (XDRPROC_T_TYPE) xdr_fhstatus, - (SVC_IN_ARG_TYPE) &res, - tv); - if (clnt_stat != RPC_SUCCESS) { - plog(XLOG_ERROR, "mountd rpc failed: %s", clnt_sperrno(clnt_stat)); - return EIO; - } - /* Check status of filehandle */ - if (res.fhs_status) { - errno = res.fhs_status; - dlog("fhandle fetch for mount version 1 failed: %m"); - return errno; - } - memmove(&fhp->v2, &res.fhs_fh, NFS_FHSIZE); -#ifdef HAVE_FS_NFS3 - } /* end of "if (nfs_version == NFS_VERSION3)" statement */ -#endif /* HAVE_FS_NFS3 */ - - /* all is well */ - return 0; -} - - -/* - * Scan mount table to see if something already mounted - */ -static int -already_mounted(mntlist *mlist, char *dir) -{ - mntlist *ml; - - for (ml = mlist; ml; ml = ml->mnext) - if (STREQ(ml->mnt->mnt_dir, dir)) - return 1; - return 0; -} - - -static int -amfs_host_mount(am_node *am, mntfs *mf) -{ - struct timeval tv2; - CLIENT *client; - enum clnt_stat clnt_stat; - int n_export; - int j, k; - exports exlist = 0, ex; - exports *ep = 0; - am_nfs_handle_t *fp = 0; - char *host; - int error = 0; - struct sockaddr_in sin; - int sock = RPC_ANYSOCK; - int ok = FALSE; - mntlist *mlist; - char fs_name[MAXPATHLEN], *rfs_dir; - char mntpt[MAXPATHLEN]; - struct timeval tv; - u_long mnt_version; - - /* - * WebNFS servers don't necessarily run mountd. - */ - if (mf->mf_flags & MFF_WEBNFS) { - plog(XLOG_ERROR, "amfs_host_mount: cannot support WebNFS"); - return EIO; - } - - /* - * Read the mount list - */ - mlist = read_mtab(mf->mf_mount, mnttab_file_name); - -#ifdef MOUNT_TABLE_ON_FILE - /* - * Unlock the mount list - */ - unlock_mntlist(); -#endif /* MOUNT_TABLE_ON_FILE */ - - /* - * Take a copy of the server hostname, address, and nfs version - * to mount version conversion. - */ - host = mf->mf_server->fs_host; - sin = *mf->mf_server->fs_ip; - plog(XLOG_INFO, "amfs_host_mount: NFS version %d", (int) mf->mf_server->fs_version); -#ifdef HAVE_FS_NFS3 - if (mf->mf_server->fs_version == NFS_VERSION3) - mnt_version = AM_MOUNTVERS3; - else -#endif /* HAVE_FS_NFS3 */ - mnt_version = MOUNTVERS; - - /* - * The original 10 second per try timeout is WAY too large, especially - * if we're only waiting 10 or 20 seconds max for the response. - * That would mean we'd try only once in 10 seconds, and we could - * lose the transmit or receive packet, and never try again. - * A 2-second per try timeout here is much more reasonable. - * 09/28/92 Mike Mitchell, mcm@unx.sas.com - */ - tv.tv_sec = 2; - tv.tv_usec = 0; - - /* - * Create a client attached to mountd - */ - client = get_mount_client(host, &sin, &tv, &sock, mnt_version); - if (client == NULL) { -#ifdef HAVE_CLNT_SPCREATEERROR - plog(XLOG_ERROR, "get_mount_client failed for %s: %s", - host, clnt_spcreateerror("")); -#else /* not HAVE_CLNT_SPCREATEERROR */ - plog(XLOG_ERROR, "get_mount_client failed for %s", host); -#endif /* not HAVE_CLNT_SPCREATEERROR */ - error = EIO; - goto out; - } - if (!nfs_auth) { - error = make_nfs_auth(); - if (error) - goto out; - } - client->cl_auth = nfs_auth; - - dlog("Fetching export list from %s", host); - - /* - * Fetch the export list - */ - tv2.tv_sec = 10; - tv2.tv_usec = 0; - clnt_stat = clnt_call(client, - MOUNTPROC_EXPORT, - (XDRPROC_T_TYPE) xdr_void, - 0, - (XDRPROC_T_TYPE) xdr_exports, - (SVC_IN_ARG_TYPE) & exlist, - tv2); - if (clnt_stat != RPC_SUCCESS) { - const char *msg = clnt_sperrno(clnt_stat); - plog(XLOG_ERROR, "host_mount rpc failed: %s", msg); - /* clnt_perror(client, "rpc"); */ - error = EIO; - goto out; - } - - /* - * Figure out how many exports were returned - */ - for (n_export = 0, ex = exlist; ex; ex = ex->ex_next) { - n_export++; - } - - /* - * Allocate an array of pointers into the list - * so that they can be sorted. If the filesystem - * is already mounted then ignore it. - */ - ep = (exports *) xmalloc(n_export * sizeof(exports)); - for (j = 0, ex = exlist; ex; ex = ex->ex_next) { - make_mntpt(mntpt, sizeof(mntpt), ex, mf->mf_mount); - if (already_mounted(mlist, mntpt)) - /* we have at least one mounted f/s, so don't fail the mount */ - ok = TRUE; - else - ep[j++] = ex; - } - n_export = j; - - /* - * Sort into order. - * This way the mounts are done in order down the tree, - * instead of any random order returned by the mount - * daemon (the protocol doesn't specify...). - */ - qsort(ep, n_export, sizeof(exports), sortfun); - - /* - * Allocate an array of filehandles - */ - fp = (am_nfs_handle_t *) xmalloc(n_export * sizeof(am_nfs_handle_t)); - - /* - * Try to obtain filehandles for each directory. - * If a fetch fails then just zero out the array - * reference but discard the error. - */ - for (j = k = 0; j < n_export; j++) { - /* Check and avoid a duplicated export entry */ - if (j > k && ep[k] && STREQ(ep[j]->ex_dir, ep[k]->ex_dir)) { - dlog("avoiding dup fhandle requested for %s", ep[j]->ex_dir); - ep[j] = 0; - } else { - k = j; - error = fetch_fhandle(client, ep[j]->ex_dir, &fp[j], - mf->mf_server->fs_version); - if (error) - ep[j] = 0; - } - } - - /* - * Mount each filesystem for which we have a filehandle. - * If any of the mounts succeed then mark "ok" and return - * error code 0 at the end. If they all fail then return - * the last error code. - */ - xstrlcpy(fs_name, mf->mf_info, MAXPATHLEN); - if ((rfs_dir = strchr(fs_name, ':')) == (char *) 0) { - plog(XLOG_FATAL, "amfs_host_mount: mf_info has no colon"); - error = EINVAL; - goto out; - } - ++rfs_dir; - for (j = 0; j < n_export; j++) { - ex = ep[j]; - if (ex) { - /* - * Note: the sizeof space left in rfs_dir is what's left in fs_name - * after strchr() above returned a pointer _inside_ fs_name. The - * calculation below also takes into account that rfs_dir was - * incremented by the ++ above. - */ - xstrlcpy(rfs_dir, ex->ex_dir, sizeof(fs_name) - (rfs_dir - fs_name)); - make_mntpt(mntpt, sizeof(mntpt), ex, mf->mf_mount); - if (do_mount(&fp[j], mntpt, fs_name, mf) == 0) - ok = TRUE; - } - } - - /* - * Clean up and exit - */ -out: - discard_mntlist(mlist); - if (ep) - XFREE(ep); - if (fp) - XFREE(fp); - if (sock != RPC_ANYSOCK) - (void) amu_close(sock); - if (client) - clnt_destroy(client); - if (exlist) - xdr_pri_free((XDRPROC_T_TYPE) xdr_exports, (caddr_t) &exlist); - if (ok) - return 0; - return error; -} - - -/* - * Return true if pref is a directory prefix of dir. - * - * XXX TODO: - * Does not work if pref is "/". - */ -static int -directory_prefix(char *pref, char *dir) -{ - int len = strlen(pref); - - if (!NSTREQ(pref, dir, len)) - return FALSE; - if (dir[len] == '/' || dir[len] == '\0') - return TRUE; - return FALSE; -} - - -/* - * Unmount a mount tree - */ -static int -amfs_host_umount(am_node *am, mntfs *mf) -{ - mntlist *ml, *mprev; - int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0; - int xerror = 0; - - /* - * Read the mount list - */ - mntlist *mlist = read_mtab(mf->mf_mount, mnttab_file_name); - -#ifdef MOUNT_TABLE_ON_FILE - /* - * Unlock the mount list - */ - unlock_mntlist(); -#endif /* MOUNT_TABLE_ON_FILE */ - - /* - * Reverse list... - */ - ml = mlist; - mprev = 0; - while (ml) { - mntlist *ml2 = ml->mnext; - ml->mnext = mprev; - mprev = ml; - ml = ml2; - } - mlist = mprev; - - /* - * Unmount all filesystems... - */ - for (ml = mlist; ml && !xerror; ml = ml->mnext) { - char *dir = ml->mnt->mnt_dir; - if (directory_prefix(mf->mf_mount, dir)) { - int error; - dlog("amfs_host: unmounts %s", dir); - /* - * Unmount "dir" - */ - error = UMOUNT_FS(dir, mnttab_file_name, unmount_flags); - /* - * Keep track of errors - */ - if (error) { - /* - * If we have not already set xerror and error is not ENOENT, - * then set xerror equal to error and log it. - * 'xerror' is the return value for this function. - * - * We do not want to pass ENOENT as an error because if the - * directory does not exists our work is done anyway. - */ - if (!xerror && error != ENOENT) - xerror = error; - if (error != EBUSY) { - errno = error; - plog(XLOG_ERROR, "Tree unmount of %s failed: %m", ml->mnt->mnt_dir); - } - } else { - (void) rmdirs(dir); - } - } - } - - /* - * Throw away mount list - */ - discard_mntlist(mlist); - - /* - * Try to remount, except when we are shutting down. - */ - if (xerror && amd_state != Finishing) { - xerror = amfs_host_mount(am, mf); - if (!xerror) { - /* - * Don't log this - it's usually too verbose - plog(XLOG_INFO, "Remounted host %s", mf->mf_info); - */ - xerror = EBUSY; - } - } - return xerror; -} - - -/* - * Tell mountd we're done. - * This is not quite right, because we may still - * have other filesystems mounted, but the existing - * mountd protocol is badly broken anyway. - */ -static void -amfs_host_umounted(mntfs *mf) -{ - char *host; - CLIENT *client; - enum clnt_stat clnt_stat; - struct sockaddr_in sin; - int sock = RPC_ANYSOCK; - struct timeval tv; - u_long mnt_version; - - if (mf->mf_error || mf->mf_refc > 1 || !mf->mf_server) - return; - - /* - * WebNFS servers shouldn't ever get here. - */ - if (mf->mf_flags & MFF_WEBNFS) { - plog(XLOG_ERROR, "amfs_host_umounted: cannot support WebNFS"); - return; - } - - /* - * Take a copy of the server hostname, address, and NFS version - * to mount version conversion. - */ - host = mf->mf_server->fs_host; - sin = *mf->mf_server->fs_ip; - plog(XLOG_INFO, "amfs_host_umounted: NFS version %d", (int) mf->mf_server->fs_version); -#ifdef HAVE_FS_NFS3 - if (mf->mf_server->fs_version == NFS_VERSION3) - mnt_version = AM_MOUNTVERS3; - else -#endif /* HAVE_FS_NFS3 */ - mnt_version = MOUNTVERS; - - /* - * Create a client attached to mountd - */ - tv.tv_sec = 10; - tv.tv_usec = 0; - client = get_mount_client(host, &sin, &tv, &sock, mnt_version); - if (client == NULL) { -#ifdef HAVE_CLNT_SPCREATEERROR - plog(XLOG_ERROR, "get_mount_client failed for %s: %s", - host, clnt_spcreateerror("")); -#else /* not HAVE_CLNT_SPCREATEERROR */ - plog(XLOG_ERROR, "get_mount_client failed for %s", host); -#endif /* not HAVE_CLNT_SPCREATEERROR */ - goto out; - } - - if (!nfs_auth) { - if (make_nfs_auth()) - goto out; - } - client->cl_auth = nfs_auth; - - dlog("Unmounting all from %s", host); - - clnt_stat = clnt_call(client, - MOUNTPROC_UMNTALL, - (XDRPROC_T_TYPE) xdr_void, - 0, - (XDRPROC_T_TYPE) xdr_void, - 0, - tv); - if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_SYSTEMERROR) { - /* RPC_SYSTEMERROR seems to be returned for no good reason ... */ - const char *msg = clnt_sperrno(clnt_stat); - plog(XLOG_ERROR, "unmount all from %s rpc failed: %s", host, msg); - goto out; - } - -out: - if (sock != RPC_ANYSOCK) - (void) amu_close(sock); - if (client) - clnt_destroy(client); -} diff --git a/contrib/amd/amd/amfs_link.c b/contrib/amd/amd/amfs_link.c deleted file mode 100644 index e75ab862f8bc..000000000000 --- a/contrib/amd/amd/amfs_link.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/amfs_link.c - * - */ - -/* - * Symbol-link file system - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* forward declarations */ -static int amfs_link_mount(am_node *mp, mntfs *mf); -static int amfs_link_umount(am_node *mp, mntfs *mf); - -/* - * Ops structures - */ -am_ops amfs_link_ops = -{ - "link", - amfs_link_match, - 0, /* amfs_link_init */ - amfs_link_mount, - amfs_link_umount, - amfs_error_lookup_child, - amfs_error_mount_child, - amfs_error_readdir, - 0, /* amfs_link_readlink */ - 0, /* amfs_link_mounted */ - 0, /* amfs_link_umounted */ - amfs_generic_find_srvr, - 0, /* nfs_fs_flags */ - 0, /* amfs_link_get_wchan */ -#ifdef HAVE_FS_AUTOFS - AUTOFS_LINK_FS_FLAGS, -#endif /* HAVE_FS_AUTOFS */ -}; - - -/* - * SFS needs a link. - */ -char * -amfs_link_match(am_opts *fo) -{ - - if (!fo->opt_fs) { - plog(XLOG_USER, "link: no fs specified"); - return 0; - } - - /* - * If the link target points to another mount point, then we could - * end up with an unpleasant situation, where the link f/s simply - * "assumes" the mntfs of that mount point. - * - * For example, if the link points to /usr, and /usr is a real ufs - * filesystem, then the link f/s will use the inherited ufs mntfs, - * and the end result will be that it will become unmountable. - * - * To prevent this, we use a hack: we prepend a dot ('.') to opt_fs if - * its original value was an absolute path, so that it will never match - * any other mntfs. - * - * XXX: a less hacky solution should be used... - */ - if (fo->opt_fs[0] == '/') { - char *link_hack = str3cat(NULL, ".", fo->opt_fs, ""); - if (!fo->opt_sublink) - fo->opt_sublink = strdup(fo->opt_fs); - XFREE(fo->opt_fs); - fo->opt_fs = link_hack; - } - - return strdup(fo->opt_fs); -} - - -static int -amfs_link_mount(am_node *mp, mntfs *mf) -{ - return 0; -} - - -static int -amfs_link_umount(am_node *mp, mntfs *mf) -{ - return 0; -} diff --git a/contrib/amd/amd/amfs_linkx.c b/contrib/amd/amd/amfs_linkx.c deleted file mode 100644 index e306eda91d3b..000000000000 --- a/contrib/amd/amd/amfs_linkx.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/amfs_linkx.c - * - */ - -/* - * Symbol-link file system, with test that the target of the link exists. - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* forward declarations */ -static int amfs_linkx_mount(am_node *mp, mntfs *mf); -static int amfs_linkx_umount(am_node *mp, mntfs *mf); - -/* - * linkx operations - */ -struct am_ops amfs_linkx_ops = -{ - "linkx", - amfs_link_match, - 0, /* amfs_linkx_init */ - amfs_linkx_mount, - amfs_linkx_umount, - amfs_error_lookup_child, - amfs_error_mount_child, - amfs_error_readdir, - 0, /* amfs_linkx_readlink */ - 0, /* amfs_linkx_mounted */ - 0, /* amfs_linkx_umounted */ - amfs_generic_find_srvr, - 0, /* amfs_linkx_get_wchan */ - FS_MBACKGROUND, -#ifdef HAVE_FS_AUTOFS - AUTOFS_LINKX_FS_FLAGS, -#endif /* HAVE_FS_AUTOFS */ -}; - - -static int -amfs_linkx_mount(am_node *mp, mntfs *mf) -{ - /* - * Check for existence of target. - */ - struct stat stb; - char *ln; - - if (mp->am_link) - ln = mp->am_link; - else /* should never occur */ - ln = mf->mf_mount; - - /* - * Use lstat, not stat, since we don't - * want to know if the ultimate target of - * a symlink chain exists, just the first. - */ - if (lstat(ln, &stb) < 0) - return errno; - - return 0; -} - - -static int -amfs_linkx_umount(am_node *mp, mntfs *mf) -{ - return 0; -} diff --git a/contrib/amd/amd/amfs_nfsl.c b/contrib/amd/amd/amfs_nfsl.c deleted file mode 100644 index bb48f0efd255..000000000000 --- a/contrib/amd/amd/amfs_nfsl.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/amfs_nfsl.c - * - */ - -/* - * NFSL: Network file system with local existence check. If the local - * path denoted by $rfs exists, it behaves as type:=link. - * - * Example: - * pkg type:=nfsl;rhost:=jonny;rfs:=/n/johnny/src/pkg;fs:=${rfs} - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - - -/* forward declarations */ -static char *amfs_nfsl_match(am_opts *fo); -static int amfs_nfsl_init(mntfs *mf); -static int amfs_nfsl_mount(am_node *mp, mntfs *mf); -static int amfs_nfsl_umount(am_node *mp, mntfs *mf); -static void amfs_nfsl_umounted(mntfs *mf); -static fserver *amfs_nfsl_ffserver(mntfs *mf); - -/* - * NFS-Link operations - */ -am_ops amfs_nfsl_ops = -{ - "nfsl", - amfs_nfsl_match, - amfs_nfsl_init, - amfs_nfsl_mount, - amfs_nfsl_umount, - amfs_error_lookup_child, - amfs_error_mount_child, - amfs_error_readdir, - 0, /* amfs_nfsl_readlink */ - 0, /* amfs_nfsl_mounted */ - amfs_nfsl_umounted, - amfs_nfsl_ffserver, - 0, /* amfs_nfsl_get_wchan */ - FS_MKMNT | FS_BACKGROUND | FS_AMQINFO, /* nfs_fs_flags */ -#ifdef HAVE_FS_AUTOFS - AUTOFS_NFSL_FS_FLAGS, -#endif /* HAVE_FS_AUTOFS */ -}; - - -/* - * Check that f/s has all needed fields. - * Returns: matched string if found, NULL otherwise. - */ -static char * -amfs_nfsl_match(am_opts *fo) -{ - char *cp; - char *ho = fo->opt_rhost; - char *retval; - struct stat stb; - - if (fo->opt_sublink) - cp = fo->opt_sublink; - else - cp = fo->opt_fs; - - if (!cp || !ho) { - plog(XLOG_USER, "amfs_nfsl: host $fs and $rhost must be specified"); - return NULL; - } - - /* - * If this host is not the same as $rhost, or if link does not exist, - * call nfs_ops.fs_match(). - * If link value exists (or same host), call amfs_link_ops.fs_match(). - */ - if (!STRCEQ(ho, am_get_hostname())) { - plog(XLOG_INFO, "amfs_nfsl: \"%s\" is not local host, using type:=nfs", ho); - retval = nfs_ops.fs_match(fo); - } else if (lstat(cp, &stb) < 0) { - plog(XLOG_INFO, "amfs_nfsl: \"%s\" does not exist, using type:=nfs", cp); - retval = nfs_ops.fs_match(fo); - } else { - plog(XLOG_INFO, "amfs_nfsl: \"%s\" exists, using type:=link", cp); - retval = amfs_link_ops.fs_match(fo); - } - return retval; -} - - -/* - * Initialize. - * Returns: 0 if OK, non-zero (errno) if failed. - */ -static int -amfs_nfsl_init(mntfs *mf) -{ - int ret = 0; - if (mf->mf_flags & MFF_NFSLINK) { - if (amfs_link_ops.fs_init) - ret = amfs_link_ops.fs_init(mf); - } else { - if (nfs_ops.fs_init) - ret = nfs_ops.fs_init(mf); - } - return ret; -} - - -/* - * Mount vfs. - * Returns: 0 if OK, non-zero (errno) if failed. - */ -static int -amfs_nfsl_mount(am_node *mp, mntfs *mf) -{ - int ret = 0; - if (mf->mf_flags & MFF_NFSLINK) { - if (amfs_link_ops.mount_fs) - ret = amfs_link_ops.mount_fs(mp, mf); - } else { - if (nfs_ops.mount_fs) - ret = nfs_ops.mount_fs(mp, mf); - } - return ret; -} - - -/* - * Unmount VFS. - * Returns: 0 if OK, non-zero (errno) if failed. - */ -static int -amfs_nfsl_umount(am_node *mp, mntfs *mf) -{ - int ret = 0; - if (mf->mf_flags & MFF_NFSLINK) { - if (amfs_link_ops.umount_fs) - ret = amfs_link_ops.umount_fs(mp, mf); - } else { - if (nfs_ops.umount_fs) - ret = nfs_ops.umount_fs(mp, mf); - } - return ret; -} - - -/* - * Async unmount callback function. - * After the base umount() succeeds, we may want to take extra actions, - * such as informing remote mount daemons that we've unmounted them. - * See amfs_auto_umounted(), host_umounted(), nfs_umounted(). - */ -static void -amfs_nfsl_umounted(mntfs *mf) -{ - if (mf->mf_flags & MFF_NFSLINK) { - if (amfs_link_ops.umounted) - amfs_link_ops.umounted(mf); - } else { - if (nfs_ops.umounted) - nfs_ops.umounted(mf); - } -} - - -/* - * Find a file server. - * Returns: fserver of found server, or NULL if not found. - */ -static fserver * -amfs_nfsl_ffserver(mntfs *mf) -{ - char *cp; - char *ho = mf->mf_fo->opt_rhost; - struct stat stb; - - if (mf->mf_fo->opt_sublink) - cp = mf->mf_fo->opt_sublink; - else - cp = mf->mf_fo->opt_fs; - - /* - * If this host is not the same as $rhost, or if link does not exist, - * call amfs_link_ops.ffserver(). - * If link value exists (or same host), then call ops_nfs.ffserver(). - */ - if (!STRCEQ(ho, am_get_hostname()) || lstat(cp, &stb) < 0) { - return nfs_ops.ffserver(mf); - } else { - mf->mf_flags |= MFF_NFSLINK; - /* remove the FS_MKMNT flag, we don't want amd touching the mountpoint */ - mf->mf_fsflags &= ~FS_MKMNT; - return amfs_link_ops.ffserver(mf); - } -} diff --git a/contrib/amd/amd/amfs_nfsx.c b/contrib/amd/amd/amfs_nfsx.c deleted file mode 100644 index 91be8af47e11..000000000000 --- a/contrib/amd/amd/amfs_nfsx.c +++ /dev/null @@ -1,512 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/amfs_nfsx.c - * - */ - -/* - * NFS hierarchical mounts - * - * TODO: Re-implement. - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* - * The rfs field contains a list of mounts to be done from - * the remote host. - */ -typedef struct amfs_nfsx_mnt { - mntfs *n_mnt; - int n_error; -} amfs_nfsx_mnt; - -struct amfs_nfsx { - int nx_c; /* Number of elements in nx_v */ - amfs_nfsx_mnt *nx_v; /* Underlying mounts */ - amfs_nfsx_mnt *nx_try; - am_node *nx_mp; -}; - -/* forward definitions */ -static char *amfs_nfsx_match(am_opts *fo); -static int amfs_nfsx_mount(am_node *am, mntfs *mf); -static int amfs_nfsx_umount(am_node *am, mntfs *mf); -static int amfs_nfsx_init(mntfs *mf); - -/* - * Ops structure - */ -am_ops amfs_nfsx_ops = -{ - "nfsx", - amfs_nfsx_match, - amfs_nfsx_init, - amfs_nfsx_mount, - amfs_nfsx_umount, - amfs_error_lookup_child, - amfs_error_mount_child, - amfs_error_readdir, - 0, /* amfs_nfsx_readlink */ - 0, /* amfs_nfsx_mounted */ - 0, /* amfs_nfsx_umounted */ - find_nfs_srvr, /* XXX */ - 0, /* amfs_nfsx_get_wchan */ - /* FS_UBACKGROUND| */ FS_AMQINFO, /* nfs_fs_flags */ -#ifdef HAVE_FS_AUTOFS - AUTOFS_NFSX_FS_FLAGS, -#endif /* HAVE_FS_AUTOFS */ -}; - - -static char * -amfs_nfsx_match(am_opts *fo) -{ - char *xmtab; - char *ptr; - int len; - - if (!fo->opt_rfs) { - plog(XLOG_USER, "amfs_nfsx: no remote filesystem specified"); - return FALSE; - } - - if (!fo->opt_rhost) { - plog(XLOG_USER, "amfs_nfsx: no remote host specified"); - return FALSE; - } - - /* set default sublink */ - if (fo->opt_sublink == 0) { - ptr = strchr(fo->opt_rfs, ','); - if (ptr && ptr > (fo->opt_rfs + 1)) - fo->opt_sublink = strnsave(fo->opt_rfs + 1, ptr - fo->opt_rfs - 1); - } - - /* - * Remove trailing ",..." from ${fs} - * After deslashifying, overwrite the end of ${fs} with "/" - * to make sure it is unique. - */ - if ((ptr = strchr(fo->opt_fs, ','))) - *ptr = '\0'; - deslashify(fo->opt_fs); - - /* - * Bump string length to allow trailing / - */ - len = strlen(fo->opt_fs); - fo->opt_fs = xrealloc(fo->opt_fs, len + 1 + 1); - ptr = fo->opt_fs + len; - - /* - * Make unique... - */ - *ptr++ = '/'; - *ptr = '\0'; - - /* - * Determine magic cookie to put in mtab - */ - xmtab = str3cat((char *) 0, fo->opt_rhost, ":", fo->opt_rfs); - dlog("NFSX: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"", - fo->opt_rhost, fo->opt_rfs, fo->opt_fs); - - return xmtab; -} - - -static void -amfs_nfsx_prfree(opaque_t vp) -{ - struct amfs_nfsx *nx = (struct amfs_nfsx *) vp; - int i; - - for (i = 0; i < nx->nx_c; i++) { - mntfs *m = nx->nx_v[i].n_mnt; - if (m) - free_mntfs(m); - } - - XFREE(nx->nx_v); - XFREE(nx); -} - - -static int -amfs_nfsx_init(mntfs *mf) -{ - /* - * mf_info has the form: - * host:/prefix/path,sub,sub,sub - */ - int i; - int glob_error; - struct amfs_nfsx *nx; - int asked_for_wakeup = 0; - - nx = (struct amfs_nfsx *) mf->mf_private; - - if (nx == 0) { - char **ivec; - char *info = 0; - char *host; - char *pref; - int error = 0; - - info = strdup(mf->mf_info); - host = strchr(info, ':'); - if (!host) { - error = EINVAL; - goto errexit; - } - pref = host + 1; - host = info; - - /* - * Split the prefix off from the suffices - */ - ivec = strsplit(pref, ',', '\''); - - /* - * Count array size - */ - for (i = 0; ivec[i]; i++) - /* nothing */; - - nx = ALLOC(struct amfs_nfsx); - mf->mf_private = (opaque_t) nx; - mf->mf_prfree = amfs_nfsx_prfree; - - nx->nx_c = i - 1; /* i-1 because we don't want the prefix */ - nx->nx_v = (amfs_nfsx_mnt *) xmalloc(nx->nx_c * sizeof(amfs_nfsx_mnt)); - nx->nx_mp = 0; - { - char *mp = 0; - char *xinfo = 0; - char *fs = mf->mf_fo->opt_fs; - char *rfs = 0; - for (i = 0; i < nx->nx_c; i++) { - char *path = ivec[i + 1]; - rfs = str3cat(rfs, pref, "/", path); - /* - * Determine the mount point. - * If this is the root, then don't remove - * the trailing slash to avoid mntfs name clashes. - */ - mp = str3cat(mp, fs, "/", rfs); - normalize_slash(mp); - deslashify(mp); - /* - * Determine the mount info - */ - xinfo = str3cat(xinfo, host, *path == '/' ? "" : "/", path); - normalize_slash(xinfo); - if (pref[1] != '\0') - deslashify(xinfo); - dlog("amfs_nfsx: init mount for %s on %s", xinfo, mp); - nx->nx_v[i].n_error = -1; - nx->nx_v[i].n_mnt = find_mntfs(&nfs_ops, mf->mf_fo, mp, xinfo, "", mf->mf_mopts, mf->mf_remopts); - /* propagate the on_autofs flag */ - nx->nx_v[i].n_mnt->mf_flags |= mf->mf_flags & MFF_ON_AUTOFS; - } - if (rfs) - XFREE(rfs); - if (mp) - XFREE(mp); - if (xinfo) - XFREE(xinfo); - } - - XFREE(ivec); - errexit: - if (info) - XFREE(info); - if (error) - return error; - } - - /* - * Iterate through the mntfs's and call - * the underlying init routine on each - */ - glob_error = 0; - - for (i = 0; i < nx->nx_c; i++) { - amfs_nfsx_mnt *n = &nx->nx_v[i]; - mntfs *m = n->n_mnt; - int error = 0; - if (m->mf_ops->fs_init && !(mf->mf_flags & MFF_RESTART)) - error = m->mf_ops->fs_init(m); - /* - * if you just "return error" here, you will have made a failure - * in any submounts to fail the whole group. There was old unused code - * here before. - */ - if (error > 0) - n->n_error = error; - - else if (error < 0) { - glob_error = -1; - if (!asked_for_wakeup) { - asked_for_wakeup = 1; - sched_task(wakeup_task, (opaque_t) mf, get_mntfs_wchan(m)); - } - } - } - - return glob_error; -} - - -static void -amfs_nfsx_cont(int rc, int term, opaque_t arg) -{ - mntfs *mf = (mntfs *) arg; - struct amfs_nfsx *nx = (struct amfs_nfsx *) mf->mf_private; - am_node *mp = nx->nx_mp; - amfs_nfsx_mnt *n = nx->nx_try; - - n->n_mnt->mf_flags &= ~(MFF_ERROR | MFF_MOUNTING); - mf->mf_flags &= ~MFF_ERROR; - - /* - * Wakeup anything waiting for this mount - */ - wakeup(get_mntfs_wchan(n->n_mnt)); - - if (rc || term) { - if (term) { - /* - * Not sure what to do for an error code. - */ - plog(XLOG_ERROR, "mount for %s got signal %d", n->n_mnt->mf_mount, term); - n->n_error = EIO; - } else { - /* - * Check for exit status - */ - errno = rc; /* XXX */ - plog(XLOG_ERROR, "%s: mount (amfs_nfsx_cont): %m", n->n_mnt->mf_mount); - n->n_error = rc; - } - free_mntfs(n->n_mnt); - n->n_mnt = new_mntfs(); - n->n_mnt->mf_error = n->n_error; - n->n_mnt->mf_flags |= MFF_ERROR; - } else { - /* - * The mount worked. - */ - mf_mounted(n->n_mnt, FALSE); /* FALSE => don't free the n_mnt->am_opts */ - n->n_error = 0; - } - - /* - * Do the remaining bits - */ - if (amfs_nfsx_mount(mp, mf) >= 0) - wakeup(get_mntfs_wchan(mf)); -} - - -static int -try_amfs_nfsx_mount(opaque_t mv) -{ - mntfs *mf = (mntfs *) mv; - struct amfs_nfsx *nx = (struct amfs_nfsx *) mf->mf_private; - am_node *mp = nx->nx_mp; - int error; - - error = mf->mf_ops->mount_fs(mp, mf); - - return error; -} - - -static int -amfs_nfsx_remount(am_node *am, mntfs *mf, int fg) -{ - struct amfs_nfsx *nx = (struct amfs_nfsx *) mf->mf_private; - amfs_nfsx_mnt *n; - int glob_error = -1; - - /* Save the am_node pointer for later use */ - nx->nx_mp = am; - - /* - * Iterate through the mntfs's and mount each filesystem - * which is not yet mounted. - */ - for (n = nx->nx_v; n < nx->nx_v + nx->nx_c; n++) { - mntfs *m = n->n_mnt; - - if (m->mf_flags & MFF_MOUNTING) - break; - - if (m->mf_flags & MFF_MOUNTED) { - mf_mounted(m, FALSE); /* FALSE => don't free the m->am_opts */ - n->n_error = glob_error = 0; - continue; - } - - if (n->n_error < 0) { - /* Create the mountpoint, if and as required */ - if (!(m->mf_flags & MFF_MKMNT) && m->mf_fsflags & FS_MKMNT) { - if (!mkdirs(m->mf_mount, 0555)) - m->mf_flags |= MFF_MKMNT; - } - - dlog("calling underlying mount on %s", m->mf_mount); - if (!fg && foreground && (m->mf_fsflags & FS_MBACKGROUND)) { - m->mf_flags |= MFF_MOUNTING; - dlog("backgrounding mount of \"%s\"", m->mf_info); - nx->nx_try = n; - run_task(try_amfs_nfsx_mount, (opaque_t) m, amfs_nfsx_cont, (opaque_t) mf); - n->n_error = -1; - return -1; - } else { - dlog("foreground mount of \"%s\" ...", mf->mf_info); - n->n_error = m->mf_ops->mount_fs(am, m); - } - - if (n->n_error > 0) - dlog("underlying fmount of %s failed: %s", m->mf_mount, strerror(n->n_error)); - - if (n->n_error == 0) { - glob_error = 0; - } else if (glob_error < 0) { - glob_error = n->n_error; - } - } - } - - return glob_error < 0 ? 0 : glob_error; -} - - -static int -amfs_nfsx_mount(am_node *am, mntfs *mf) -{ - return amfs_nfsx_remount(am, mf, FALSE); -} - - -/* - * Unmount an NFS hierarchy. - * Note that this is called in the foreground - * and so may hang under extremely rare conditions. - */ -static int -amfs_nfsx_umount(am_node *am, mntfs *mf) -{ - struct amfs_nfsx *nx = (struct amfs_nfsx *) mf->mf_private; - amfs_nfsx_mnt *n; - int glob_error = 0; - - /* - * Iterate in reverse through the mntfs's and unmount each filesystem - * which is mounted. - */ - for (n = nx->nx_v + nx->nx_c - 1; n >= nx->nx_v; --n) { - mntfs *m = n->n_mnt; - /* - * If this node has not been messed with - * and there has been no error so far - * then try and unmount. - * If an error had occurred then zero - * the error code so that the remount - * only tries to unmount those nodes - * which had been successfully unmounted. - */ - if (n->n_error == 0) { - dlog("calling underlying fumount on %s", m->mf_mount); - n->n_error = m->mf_ops->umount_fs(am, m); - if (n->n_error) { - glob_error = n->n_error; - n->n_error = 0; - } else { - /* - * Make sure remount gets this node - */ - n->n_error = -1; - } - } - } - - /* - * If any unmounts failed then remount the - * whole lot... - */ - if (glob_error) { - glob_error = amfs_nfsx_remount(am, mf, TRUE); - if (glob_error) { - errno = glob_error; /* XXX */ - plog(XLOG_USER, "amfs_nfsx: remount of %s failed: %m", mf->mf_mount); - } - glob_error = EBUSY; - } else { - /* - * Remove all the mount points - */ - for (n = nx->nx_v; n < nx->nx_v + nx->nx_c; n++) { - mntfs *m = n->n_mnt; - dlog("calling underlying umounted on %s", m->mf_mount); - if (m->mf_ops->umounted) - m->mf_ops->umounted(m); - - if (n->n_error < 0) { - if (m->mf_fsflags & FS_MKMNT) { - (void) rmdirs(m->mf_mount); - m->mf_flags &= ~MFF_MKMNT; - } - } - free_mntfs(m); - n->n_mnt = 0; - n->n_error = -1; - } - } - - return glob_error; -} diff --git a/contrib/amd/amd/amfs_program.c b/contrib/amd/amd/amfs_program.c deleted file mode 100644 index 843e8050c11b..000000000000 --- a/contrib/amd/amd/amfs_program.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (c) 1997-2006 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 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. - * - * - * File: am-utils/amd/amfs_program.c - * - */ - -/* - * Program file system - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* forward definitions */ -static char *amfs_program_match(am_opts *fo); -static int amfs_program_mount(am_node *am, mntfs *mf); -static int amfs_program_umount(am_node *am, mntfs *mf); -static int amfs_program_init(mntfs *mf); - -/* - * Ops structure - */ -am_ops amfs_program_ops = -{ - "program", - amfs_program_match, - amfs_program_init, - amfs_program_mount, - amfs_program_umount, - amfs_error_lookup_child, - amfs_error_mount_child, - amfs_error_readdir, - 0, /* amfs_program_readlink */ - 0, /* amfs_program_mounted */ - 0, /* amfs_program_umounted */ - amfs_generic_find_srvr, - 0, /* amfs_program_get_wchan */ - FS_MKMNT | FS_BACKGROUND | FS_AMQINFO, /* nfs_fs_flags */ -#ifdef HAVE_FS_AUTOFS - AUTOFS_PROGRAM_FS_FLAGS, -#endif /* HAVE_FS_AUTOFS */ -}; - - -/* - * Execute needs a mount and unmount command. - */ -static char * -amfs_program_match(am_opts *fo) -{ - char *prog; - - if (fo->opt_unmount && fo->opt_umount) { - plog(XLOG_ERROR, "program: cannot specify both unmount and umount options"); - return 0; - } - if (!fo->opt_mount) { - plog(XLOG_ERROR, "program: must specify mount command"); - return 0; - } - if (!fo->opt_unmount && !fo->opt_umount) { - fo->opt_unmount = str3cat(NULL, UNMOUNT_PROGRAM, " umount ", fo->opt_fs); - plog(XLOG_INFO, "program: un/umount not specified; using default \"%s\"", - fo->opt_unmount); - } - prog = strchr(fo->opt_mount, ' '); - - return strdup(prog ? prog + 1 : fo->opt_mount); -} - - -static int -amfs_program_init(mntfs *mf) -{ - /* check if already saved value */ - if (mf->mf_private != NULL) - return 0; - - /* save unmount (or umount) command */ - if (mf->mf_fo->opt_unmount != NULL) - mf->mf_private = (opaque_t) strdup(mf->mf_fo->opt_unmount); - else - mf->mf_private = (opaque_t) strdup(mf->mf_fo->opt_umount); - mf->mf_prfree = (void (*)(opaque_t)) free; - - return 0; -} - - -static int -amfs_program_exec(char *info) -{ - char **xivec; - int error; - - /* - * Split copy of command info string - */ - info = strdup(info); - if (info == 0) - return ENOBUFS; - xivec = strsplit(info, ' ', '\''); - - /* - * Put stdout to stderr - */ - (void) fclose(stdout); - if (!logfp) - logfp = stderr; /* initialize before possible first use */ - (void) dup(fileno(logfp)); - if (fileno(logfp) != fileno(stderr)) { - (void) fclose(stderr); - (void) dup(fileno(logfp)); - } - - /* - * Try the exec - */ - if (amuDebug(D_FULL)) { - char **cp = xivec; - plog(XLOG_DEBUG, "executing (un)mount command..."); - while (*cp) { - plog(XLOG_DEBUG, "arg[%ld] = '%s'", (long) (cp - xivec), *cp); - cp++; - } - } - - if (xivec[0] == 0 || xivec[1] == 0) { - errno = EINVAL; - plog(XLOG_USER, "1st/2nd args missing to (un)mount program"); - } else { - (void) execv(xivec[0], xivec + 1); - } - - /* - * Save error number - */ - error = errno; - plog(XLOG_ERROR, "exec failed: %m"); - - /* - * Free allocate memory - */ - XFREE(info); - XFREE(xivec); - - /* - * Return error - */ - return error; -} - - -static int -amfs_program_mount(am_node *am, mntfs *mf) -{ - return amfs_program_exec(mf->mf_fo->opt_mount); -} - - -static int -amfs_program_umount(am_node *am, mntfs *mf) -{ - return amfs_program_exec((char *) mf->mf_private); -} diff --git a/contrib/amd/amd/amfs_root.c b/contrib/amd/amd/amfs_root.c deleted file mode 100644 index 243267e71e86..000000000000 --- a/contrib/amd/amd/amfs_root.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/amfs_root.c - * - */ - -/* - * Root file system - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/**************************************************************************** - *** FORWARD DEFINITIONS *** - ****************************************************************************/ -static int amfs_root_mount(am_node *mp, mntfs *mf); - -/**************************************************************************** - *** OPS STRUCTURES *** - ****************************************************************************/ -am_ops amfs_root_ops = -{ - "root", - 0, /* amfs_root_match */ - 0, /* amfs_root_init */ - amfs_root_mount, - amfs_generic_umount, - amfs_generic_lookup_child, - amfs_generic_mount_child, - amfs_generic_readdir, - 0, /* amfs_root_readlink */ - 0, /* amfs_root_mounted */ - 0, /* amfs_root_umounted */ - amfs_generic_find_srvr, - 0, /* amfs_root_get_wchan */ - FS_NOTIMEOUT | FS_AMQINFO | FS_DIRECTORY, /* nfs_fs_flags */ -#ifdef HAVE_FS_AUTOFS - AUTOFS_ROOT_FS_FLAGS, -#endif /* HAVE_FS_AUTOFS */ -}; - - -/**************************************************************************** - *** FUNCTIONS *** - ****************************************************************************/ - -/* - * Mount the root... - */ -static int -amfs_root_mount(am_node *mp, mntfs *mf) -{ - mf->mf_mount = strealloc(mf->mf_mount, pid_fsname); - mf->mf_private = (opaque_t) mapc_find(mf->mf_info, "", NULL); - mf->mf_prfree = mapc_free; - - return 0; -} diff --git a/contrib/amd/amd/amfs_toplvl.c b/contrib/amd/amd/amfs_toplvl.c deleted file mode 100644 index 1b968f197f55..000000000000 --- a/contrib/amd/amd/amfs_toplvl.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/amfs_toplvl.c - * - */ - -/* - * Top-level file system - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/**************************************************************************** - *** FORWARD DEFINITIONS *** - ****************************************************************************/ -static int amfs_toplvl_init(mntfs *mf); - -/**************************************************************************** - *** OPS STRUCTURES *** - ****************************************************************************/ -am_ops amfs_toplvl_ops = -{ - "toplvl", - amfs_generic_match, - amfs_toplvl_init, /* amfs_toplvl_init */ - amfs_toplvl_mount, - amfs_toplvl_umount, - amfs_generic_lookup_child, - amfs_generic_mount_child, - amfs_generic_readdir, - 0, /* amfs_toplvl_readlink */ - amfs_generic_mounted, - 0, /* amfs_toplvl_umounted */ - amfs_generic_find_srvr, - 0, /* amfs_toplvl_get_wchan */ - FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | - FS_AMQINFO | FS_DIRECTORY, /* nfs_fs_flags */ -#ifdef HAVE_FS_AUTOFS - AUTOFS_TOPLVL_FS_FLAGS, -#endif /* HAVE_FS_AUTOFS */ -}; - - -/**************************************************************************** - *** FUNCTIONS *** - ****************************************************************************/ - -static void -set_auto_attrcache_timeout(char *preopts, char *opts, size_t l) -{ - -#ifdef MNTTAB_OPT_NOAC - /* - * Don't cache attributes - they are changing under the kernel's feet. - * For example, IRIX5.2 will dispense with nfs lookup calls and hand stale - * filehandles to getattr unless we disable attribute caching on the - * automount points. - */ - if (gopt.auto_attrcache == 0) { - xsnprintf(preopts, l, ",%s", MNTTAB_OPT_NOAC); - xstrlcat(opts, preopts, l); - } -#endif /* MNTTAB_OPT_NOAC */ - - /* - * XXX: note that setting these to 0 in the past resulted in an error on - * some systems, which is why it's better to use "noac" if possible. For - * now, we're setting everything possible, but if this will cause trouble, - * then we'll have to condition the remainder of this on OPT_NOAC. - */ -#ifdef MNTTAB_OPT_ACTIMEO - xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTIMEO, gopt.auto_attrcache); - xstrlcat(opts, preopts, l); -#else /* MNTTAB_OPT_ACTIMEO */ -# ifdef MNTTAB_OPT_ACDIRMIN - xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTDIRMIN, gopt.auto_attrcache); - xstrlcat(opts, preopts, l); -# endif /* MNTTAB_OPT_ACDIRMIN */ -# ifdef MNTTAB_OPT_ACDIRMAX - xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTDIRMAX, gopt.auto_attrcache); - xstrlcat(opts, preopts, l); -# endif /* MNTTAB_OPT_ACDIRMAX */ -# ifdef MNTTAB_OPT_ACREGMIN - xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTREGMIN, gopt.auto_attrcache); - xstrlcat(opts, preopts, l); -# endif /* MNTTAB_OPT_ACREGMIN */ -# ifdef MNTTAB_OPT_ACREGMAX - xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTREGMAX, gopt.auto_attrcache); - xstrlcat(opts, preopts, l); -# endif /* MNTTAB_OPT_ACREGMAX */ -#endif /* MNTTAB_OPT_ACTIMEO */ -} - - -/* - * Initialize a top-level mount. In our case, if the user asked for - * forced_unmounts, and the OS supports it, then we try forced/lazy unmounts - * on any previous toplvl mounts. This is useful if a previous Amd died and - * left behind toplvl mount points (this Amd will clean them up). - * - * WARNING: Don't use forced/lazy unmounts if you have another valid Amd - * running, because this code WILL force those valid toplvl mount points to - * be detached as well! - */ -static int -amfs_toplvl_init(mntfs *mf) -{ - int error = 0; - -#if defined(MNT2_GEN_OPT_FORCE) || defined(MNT2_GEN_OPT_DETACH) - if (gopt.flags & CFM_FORCED_UNMOUNTS) { - plog(XLOG_INFO, "amfs_toplvl_init: trying forced/lazy unmount of %s", - mf->mf_mount); - error = umount2_fs(mf->mf_mount, AMU_UMOUNT_FORCE | AMU_UMOUNT_DETACH); - if (error) - plog(XLOG_INFO, "amfs_toplvl_init: forced/lazy unmount failed: %m"); - else - dlog("amfs_toplvl_init: forced/lazy unmount succeeded"); - } -#endif /* MNT2_GEN_OPT_FORCE || MNT2_GEN_OPT_DETACH */ - return error; -} - - -/* - * Mount the top-level - */ -int -amfs_toplvl_mount(am_node *mp, mntfs *mf) -{ - struct stat stb; - char opts[SIZEOF_OPTS], preopts[SIZEOF_OPTS], toplvl_opts[40]; - int error; - - /* - * Mounting the automounter. - * Make sure the mount directory exists, construct - * the mount options and call the mount_amfs_toplvl routine. - */ - - if (stat(mp->am_path, &stb) < 0) { - return errno; - } else if ((stb.st_mode & S_IFMT) != S_IFDIR) { - plog(XLOG_WARNING, "%s is not a directory", mp->am_path); - return ENOTDIR; - } - - /* - * Construct some mount options: - * - * Tack on magic map=<mapname> option in mtab to emulate - * SunOS automounter behavior. - */ - -#ifdef HAVE_FS_AUTOFS - if (mf->mf_flags & MFF_IS_AUTOFS) { - autofs_get_opts(opts, sizeof(opts), mp->am_autofs_fh); - } else -#endif /* HAVE_FS_AUTOFS */ - { - preopts[0] = '\0'; -#ifdef MNTTAB_OPT_INTR - xstrlcat(preopts, MNTTAB_OPT_INTR, sizeof(preopts)); - xstrlcat(preopts, ",", sizeof(preopts)); -#endif /* MNTTAB_OPT_INTR */ -#ifdef MNTTAB_OPT_IGNORE - xstrlcat(preopts, MNTTAB_OPT_IGNORE, sizeof(preopts)); - xstrlcat(preopts, ",", sizeof(preopts)); -#endif /* MNTTAB_OPT_IGNORE */ - /* write most of the initial options + preopts */ - xsnprintf(opts, sizeof(opts), "%s%s,%s=%d,%s,map=%s", - preopts, - MNTTAB_OPT_RW, - MNTTAB_OPT_PORT, nfs_port, - mf->mf_ops->fs_type, mf->mf_info); - - /* process toplvl timeo/retrans options, if any */ - if (gopt.amfs_auto_timeo[AMU_TYPE_TOPLVL] > 0) { - xsnprintf(toplvl_opts, sizeof(toplvl_opts), ",%s=%d", - MNTTAB_OPT_TIMEO, gopt.amfs_auto_timeo[AMU_TYPE_TOPLVL]); - xstrlcat(opts, toplvl_opts, sizeof(opts)); - } - if (gopt.amfs_auto_retrans[AMU_TYPE_TOPLVL] > 0) { - xsnprintf(toplvl_opts, sizeof(toplvl_opts), ",%s=%d", - MNTTAB_OPT_RETRANS, gopt.amfs_auto_retrans[AMU_TYPE_TOPLVL]); - xstrlcat(opts, toplvl_opts, sizeof(opts)); - } - -#ifdef MNTTAB_OPT_NOAC - if (gopt.auto_attrcache == 0) { - xstrlcat(opts, ",", sizeof(opts)); - xstrlcat(opts, MNTTAB_OPT_NOAC, sizeof(opts)); - } else -#endif /* MNTTAB_OPT_NOAC */ - set_auto_attrcache_timeout(preopts, opts, sizeof(preopts)); - } - - /* now do the mount */ - error = amfs_mount(mp, mf, opts); - if (error) { - errno = error; - plog(XLOG_FATAL, "amfs_toplvl_mount: amfs_mount failed: %m"); - return error; - } - return 0; -} - - -/* - * Unmount a top-level automount node - */ -int -amfs_toplvl_umount(am_node *mp, mntfs *mf) -{ - struct stat stb; - int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0; - int error; - int count = 0; /* how many times did we try to unmount? */ - -again: - /* - * The lstat is needed if this mount is type=direct. - * When that happens, the kernel cache gets confused - * between the underlying type (dir) and the mounted - * type (link) and so needs to be re-synced before - * the unmount. This is all because the unmount system - * call follows links and so can't actually unmount - * a link (stupid!). It was noted that doing an ls -ld - * of the mount point to see why things were not working - * actually fixed the problem - so simulate an ls -ld here. - */ - if (lstat(mp->am_path, &stb) < 0) { - error = errno; - dlog("lstat(%s): %m", mp->am_path); - goto out; - } - if ((stb.st_mode & S_IFMT) != S_IFDIR) { - plog(XLOG_ERROR, "amfs_toplvl_umount: %s is not a directory, aborting.", mp->am_path); - error = ENOTDIR; - goto out; - } - - error = UMOUNT_FS(mp->am_path, mnttab_file_name, unmount_flags); - if (error == EBUSY) { -#ifdef HAVE_FS_AUTOFS - /* - * autofs mounts are "in place", so it is possible - * that we can't just unmount our mount points and go away. - * If that's the case, just give up. - */ - if (mf->mf_flags & MFF_IS_AUTOFS) - return error; -#endif /* HAVE_FS_AUTOFS */ - plog(XLOG_WARNING, "amfs_toplvl_unmount retrying %s in 1s", mp->am_path); - count++; - sleep(1); - /* - * If user wants forced/lazy unmount semantics, then set those flags, - * but only after we've tried normal lstat/umount a few times -- - * otherwise forced unmounts may hang this very same Amd (by preventing - * it from achieving a clean unmount). - */ - if (gopt.flags & CFM_FORCED_UNMOUNTS) { - if (count == 5) { /* after 5 seconds, try MNT_FORCE */ - dlog("enabling forced unmounts for toplvl node %s", mp->am_path); - unmount_flags |= AMU_UMOUNT_FORCE; - } - if (count == 10) { /* after 10 seconds, try MNT_DETACH */ - dlog("enabling detached unmounts for toplvl node %s", mp->am_path); - unmount_flags |= AMU_UMOUNT_DETACH; - } - } - goto again; - } -out: - return error; -} diff --git a/contrib/amd/amd/amfs_union.c b/contrib/amd/amd/amfs_union.c deleted file mode 100644 index 6adb5b0bd9cb..000000000000 --- a/contrib/amd/amd/amfs_union.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/amfs_union.c - * - */ - -/* - * Union automounter file system - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/**************************************************************************** - *** FORWARD DEFINITIONS *** - ****************************************************************************/ -static int create_amfs_union_node(char *dir, opaque_t arg); -static void amfs_union_mounted(mntfs *mf); - - -/**************************************************************************** - *** OPS STRUCTURES *** - ****************************************************************************/ -am_ops amfs_union_ops = -{ - "union", - amfs_generic_match, - 0, /* amfs_union_init */ - amfs_toplvl_mount, - amfs_toplvl_umount, - amfs_generic_lookup_child, - amfs_generic_mount_child, - amfs_generic_readdir, - 0, /* amfs_union_readlink */ - amfs_union_mounted, - 0, /* amfs_union_umounted */ - amfs_generic_find_srvr, - 0, /* amfs_union_get_wchan */ - FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO | FS_DIRECTORY, -#ifdef HAVE_FS_AUTOFS - AUTOFS_UNION_FS_FLAGS, -#endif /* HAVE_FS_AUTOFS */ -}; - - -/* - * Create a reference to a union'ed entry - * XXX: this function may not be used anywhere... - */ -static int -create_amfs_union_node(char *dir, opaque_t arg) -{ - if (!STREQ(dir, "/defaults")) { - int error = 0; - am_node *am; - am = amfs_generic_lookup_child(arg, dir, &error, VLOOK_CREATE); - if (am && error < 0) - am = amfs_generic_mount_child(am, &error); - if (error > 0) { - errno = error; /* XXX */ - plog(XLOG_ERROR, "unionfs: could not mount %s: %m", dir); - } - return error; - } - return 0; -} - - -static void -amfs_union_mounted(mntfs *mf) -{ - int index; - am_node *mp; - - amfs_mkcacheref(mf); - - /* - * Having made the union mount point, - * populate all the entries... - */ - for (mp = get_first_exported_ap(&index); - mp; - mp = get_next_exported_ap(&index)) { - if (mp->am_mnt == mf) { - /* return value from create_amfs_union_node is ignored by mapc_keyiter */ - (void) mapc_keyiter((mnt_map *) mp->am_mnt->mf_private, - create_amfs_union_node, - mp); - break; - } - } -} diff --git a/contrib/amd/amd/amq_subr.c b/contrib/amd/amd/amq_subr.c deleted file mode 100644 index 79ecafc3d9b3..000000000000 --- a/contrib/amd/amd/amq_subr.c +++ /dev/null @@ -1,479 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/amq_subr.c - * - */ -/* - * Auxiliary routines for amq tool - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* forward definitions */ -bool_t xdr_amq_mount_tree_node(XDR *xdrs, amq_mount_tree *objp); -bool_t xdr_amq_mount_subtree(XDR *xdrs, amq_mount_tree *objp); - - -voidp -amqproc_null_1_svc(voidp argp, struct svc_req *rqstp) -{ - static char res; - - return (voidp) &res; -} - - -/* - * Return a sub-tree of mounts - */ -amq_mount_tree_p * -amqproc_mnttree_1_svc(voidp argp, struct svc_req *rqstp) -{ - static am_node *mp; - - mp = find_ap(*(char **) argp); - return (amq_mount_tree_p *) ((void *)&mp); -} - - -/* - * Unmount a single node - */ -voidp -amqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp) -{ - static char res; - am_node *mp = find_ap(*(char **) argp); - - if (mp) - forcibly_timeout_mp(mp); - - return (voidp) &res; -} - - -/* - * Return global statistics - */ -amq_mount_stats * -amqproc_stats_1_svc(voidp argp, struct svc_req *rqstp) -{ - return (amq_mount_stats *) ((void *)&amd_stats); -} - - -/* - * Return the entire tree of mount nodes - */ -amq_mount_tree_list * -amqproc_export_1_svc(voidp argp, struct svc_req *rqstp) -{ - static amq_mount_tree_list aml; - static am_node *mp; - - mp = get_exported_ap(0); - aml.amq_mount_tree_list_val = (amq_mount_tree_p *) ((void *) &mp); - aml.amq_mount_tree_list_len = 1; /* XXX */ - - return &aml; -} - - -int * -amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp) -{ - static int rc; - amq_setopt *opt = (amq_setopt *) argp; - - rc = 0; - - switch (opt->as_opt) { - - case AMOPT_DEBUG: - if (debug_option(opt->as_str)) - rc = EINVAL; - break; - - case AMOPT_LOGFILE: - if (gopt.logfile && opt->as_str - && STREQ(gopt.logfile, opt->as_str)) { - if (switch_to_logfile(opt->as_str, orig_umask, 0)) - rc = EINVAL; - } else { - rc = EACCES; - } - break; - - case AMOPT_XLOG: - if (switch_option(opt->as_str)) - rc = EINVAL; - break; - - case AMOPT_FLUSHMAPC: - if (amd_state == Run) { - plog(XLOG_INFO, "amq says flush cache"); - do_mapc_reload = 0; - flush_nfs_fhandle_cache((fserver *) NULL); - flush_srvr_nfs_cache((fserver *) NULL); - } - break; - } - - return &rc; -} - - -amq_mount_info_list * -amqproc_getmntfs_1_svc(voidp argp, struct svc_req *rqstp) -{ - return (amq_mount_info_list *) ((void *)&mfhead); /* XXX */ -} - - -amq_string * -amqproc_getvers_1_svc(voidp argp, struct svc_req *rqstp) -{ - static amq_string res; - - res = get_version_string(); - return &res; -} - - -/* get PID of remote amd */ -int * -amqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp) -{ - static int res; - - res = getpid(); - return &res; -} - - -/* - * Process PAWD string of remote pawd tool. - * - * We repeat the resolution of the string until the resolved string resolves - * to itself. This ensures that we follow path resolutions through all - * possible Amd mount points until we reach some sort of convergence. To - * prevent possible infinite loops, we break out of this loop if the strings - * do not converge after MAX_PAWD_TRIES times. - */ -amq_string * -amqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp) -{ - static amq_string res; -#define MAX_PAWD_TRIES 10 - int index, len, maxagain = MAX_PAWD_TRIES; - am_node *mp; - char *mountpoint; - char *dir = *(char **) argp; - static char tmp_buf[MAXPATHLEN]; - char prev_buf[MAXPATHLEN]; - - tmp_buf[0] = prev_buf[0] = '\0'; /* default is empty string: no match */ - do { - for (mp = get_first_exported_ap(&index); - mp; - mp = get_next_exported_ap(&index)) { - if (STREQ(mp->am_mnt->mf_ops->fs_type, "toplvl")) - continue; - if (STREQ(mp->am_mnt->mf_ops->fs_type, "auto")) - continue; - mountpoint = (mp->am_link ? mp->am_link : mp->am_mnt->mf_mount); - len = strlen(mountpoint); - if (len == 0) - continue; - if (!NSTREQ(mountpoint, dir, len)) - continue; - if (dir[len] != '\0' && dir[len] != '/') - continue; - xstrlcpy(tmp_buf, mp->am_path, sizeof(tmp_buf)); - xstrlcat(tmp_buf, &dir[len], sizeof(tmp_buf)); - break; - } /* end of "for" loop */ - /* once tmp_buf and prev_buf are equal, break out of "do" loop */ - if (STREQ(tmp_buf, prev_buf)) - break; - else - xstrlcpy(prev_buf, tmp_buf, sizeof(prev_buf)); - } while (--maxagain); - /* check if we couldn't resolve the string after MAX_PAWD_TRIES times */ - if (maxagain <= 0) - plog(XLOG_WARNING, "path \"%s\" did not resolve after %d tries", - tmp_buf, MAX_PAWD_TRIES); - - res = tmp_buf; - return &res; -} - - -/* - * XDR routines. - */ - - -bool_t -xdr_amq_setopt(XDR *xdrs, amq_setopt *objp) -{ - if (!xdr_enum(xdrs, (enum_t *) ((voidp) &objp->as_opt))) { - return (FALSE); - } - if (!xdr_string(xdrs, &objp->as_str, AMQ_STRLEN)) { - return (FALSE); - } - return (TRUE); -} - - -/* - * More XDR routines - Should be used for OUTPUT ONLY. - */ -bool_t -xdr_amq_mount_tree_node(XDR *xdrs, amq_mount_tree *objp) -{ - am_node *mp = (am_node *) objp; - long mtime; - - if (!xdr_amq_string(xdrs, &mp->am_mnt->mf_info)) { - return (FALSE); - } - if (!xdr_amq_string(xdrs, &mp->am_path)) { - return (FALSE); - } - if (!xdr_amq_string(xdrs, mp->am_link ? &mp->am_link : &mp->am_mnt->mf_mount)) { - return (FALSE); - } - if (!xdr_amq_string(xdrs, &mp->am_mnt->mf_ops->fs_type)) { - return (FALSE); - } - mtime = mp->am_stats.s_mtime; - if (!xdr_long(xdrs, &mtime)) { - return (FALSE); - } - if (!xdr_u_short(xdrs, &mp->am_stats.s_uid)) { - return (FALSE); - } - if (!xdr_int(xdrs, &mp->am_stats.s_getattr)) { - return (FALSE); - } - if (!xdr_int(xdrs, &mp->am_stats.s_lookup)) { - return (FALSE); - } - if (!xdr_int(xdrs, &mp->am_stats.s_readdir)) { - return (FALSE); - } - if (!xdr_int(xdrs, &mp->am_stats.s_readlink)) { - return (FALSE); - } - if (!xdr_int(xdrs, &mp->am_stats.s_statfs)) { - return (FALSE); - } - return (TRUE); -} - - -bool_t -xdr_amq_mount_subtree(XDR *xdrs, amq_mount_tree *objp) -{ - am_node *mp = (am_node *) objp; - - if (!xdr_amq_mount_tree_node(xdrs, objp)) { - return (FALSE); - } - if (!xdr_pointer(xdrs, - (char **) ((voidp) &mp->am_osib), - sizeof(amq_mount_tree), - (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) { - return (FALSE); - } - if (!xdr_pointer(xdrs, - (char **) ((voidp) &mp->am_child), - sizeof(amq_mount_tree), - (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) { - return (FALSE); - } - return (TRUE); -} - - -bool_t -xdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp) -{ - am_node *mp = (am_node *) objp; - am_node *mnil = NULL; - - if (!xdr_amq_mount_tree_node(xdrs, objp)) { - return (FALSE); - } - if (!xdr_pointer(xdrs, - (char **) ((voidp) &mnil), - sizeof(amq_mount_tree), - (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) { - return (FALSE); - } - if (!xdr_pointer(xdrs, - (char **) ((voidp) &mp->am_child), - sizeof(amq_mount_tree), - (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) { - return (FALSE); - } - return (TRUE); -} - - -bool_t -xdr_amq_mount_tree_p(XDR *xdrs, amq_mount_tree_p *objp) -{ - if (!xdr_pointer(xdrs, (char **) objp, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_tree)) { - return (FALSE); - } - return (TRUE); -} - - -bool_t -xdr_amq_mount_stats(XDR *xdrs, amq_mount_stats *objp) -{ - if (!xdr_int(xdrs, &objp->as_drops)) { - return (FALSE); - } - if (!xdr_int(xdrs, &objp->as_stale)) { - return (FALSE); - } - if (!xdr_int(xdrs, &objp->as_mok)) { - return (FALSE); - } - if (!xdr_int(xdrs, &objp->as_merr)) { - return (FALSE); - } - if (!xdr_int(xdrs, &objp->as_uerr)) { - return (FALSE); - } - return (TRUE); -} - - - -bool_t -xdr_amq_mount_tree_list(XDR *xdrs, amq_mount_tree_list *objp) -{ - if (!xdr_array(xdrs, - (char **) ((voidp) &objp->amq_mount_tree_list_val), - (u_int *) &objp->amq_mount_tree_list_len, - ~0, - sizeof(amq_mount_tree_p), - (XDRPROC_T_TYPE) xdr_amq_mount_tree_p)) { - return (FALSE); - } - return (TRUE); -} - - - -/* - * Compute length of list - */ -bool_t -xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead) -{ - mntfs *mf; - u_int len = 0; - - for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) { - if (!(mf->mf_fsflags & FS_AMQINFO)) - continue; - len++; - } - xdr_u_int(xdrs, &len); - - /* - * Send individual data items - */ - for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) { - int up; - if (!(mf->mf_fsflags & FS_AMQINFO)) - continue; - - if (!xdr_amq_string(xdrs, &mf->mf_ops->fs_type)) { - return (FALSE); - } - if (!xdr_amq_string(xdrs, &mf->mf_mount)) { - return (FALSE); - } - if (!xdr_amq_string(xdrs, &mf->mf_info)) { - return (FALSE); - } - if (!xdr_amq_string(xdrs, &mf->mf_server->fs_host)) { - return (FALSE); - } - if (!xdr_int(xdrs, &mf->mf_error)) { - return (FALSE); - } - if (!xdr_int(xdrs, &mf->mf_refc)) { - return (FALSE); - } - if (FSRV_ERROR(mf->mf_server) || FSRV_ISDOWN(mf->mf_server)) - up = 0; - else if (FSRV_ISUP(mf->mf_server)) - up = 1; - else - up = -1; - if (!xdr_int(xdrs, &up)) { - return (FALSE); - } - } - return (TRUE); -} - - -bool_t -xdr_pri_free(XDRPROC_T_TYPE xdr_args, caddr_t args_ptr) -{ - XDR xdr; - - xdr.x_op = XDR_FREE; - return ((*xdr_args) (&xdr, (caddr_t *) args_ptr)); -} diff --git a/contrib/amd/amd/amq_svc.c b/contrib/amd/amd/amq_svc.c deleted file mode 100644 index 6fadb160c121..000000000000 --- a/contrib/amd/amd/amq_svc.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/amq_svc.c - * - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* typedefs */ -typedef char *(*amqsvcproc_t)(voidp, struct svc_req *); - -#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) -# ifdef NEED_LIBWRAP_SEVERITY_VARIABLES -/* - * Some systems that define libwrap already define these two variables - * in libwrap, while others don't: so I need to know precisely iff - * to define these two severity variables. - */ -int allow_severity=0, deny_severity=0; -# endif /* NEED_LIBWRAP_SEVERITY_VARIABLES */ - -/* - * check if remote amq is authorized to access this amd. - * Returns: 1=allowed, 0=denied. - */ -static int -amqsvc_is_client_allowed(const struct sockaddr_in *addr, char *remote) -{ - struct hostent *h; - char *name = NULL, **ad; - int ret = 0; /* default is 0==denied */ - - /* Check IP address */ - if (hosts_ctl(AMD_SERVICE_NAME, "", remote, "")) { - ret = 1; - goto out; - } - /* Get address */ - if (!(h = gethostbyaddr((const char *)&(addr->sin_addr), - sizeof(addr->sin_addr), - AF_INET))) - goto out; - if (!(name = strdup(h->h_name))) - goto out; - /* Paranoia check */ - if (!(h = gethostbyname(name))) - goto out; - for (ad = h->h_addr_list; *ad; ad++) - if (!memcmp(*ad, &(addr->sin_addr), h->h_length)) - break; - if (!*ad) - goto out; - if (hosts_ctl(AMD_SERVICE_NAME, "", h->h_name, "")) { - return 1; - goto out; - } - /* Check aliases */ - for (ad = h->h_aliases; *ad; ad++) - if (hosts_ctl(AMD_SERVICE_NAME, "", *ad, "")) { - return 1; - goto out; - } - - out: - if (name) - XFREE(name); - return ret; -} -#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */ - - -void -amq_program_1(struct svc_req *rqstp, SVCXPRT *transp) -{ - union { - amq_string amqproc_mnttree_1_arg; - amq_string amqproc_umnt_1_arg; - amq_setopt amqproc_setopt_1_arg; - } argument; - char *result; - xdrproc_t xdr_argument, xdr_result; - amqsvcproc_t local; - -#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) - if (gopt.flags & CFM_USE_TCPWRAPPERS) { - struct sockaddr_in *remote_addr = svc_getcaller(rqstp->rq_xprt); - char *remote_hostname = inet_ntoa(remote_addr->sin_addr); - - if (!amqsvc_is_client_allowed(remote_addr, remote_hostname)) { - plog(XLOG_WARNING, "Amd denied remote amq service to %s", remote_hostname); - svcerr_auth(transp, AUTH_FAILED); - return; - } else { - dlog("Amd allowed remote amq service to %s", remote_hostname); - } - } -#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */ - - switch (rqstp->rq_proc) { - - case AMQPROC_NULL: - xdr_argument = (xdrproc_t) xdr_void; - xdr_result = (xdrproc_t) xdr_void; - local = (amqsvcproc_t) amqproc_null_1_svc; - break; - - case AMQPROC_MNTTREE: - xdr_argument = (xdrproc_t) xdr_amq_string; - xdr_result = (xdrproc_t) xdr_amq_mount_tree_p; - local = (amqsvcproc_t) amqproc_mnttree_1_svc; - break; - - case AMQPROC_UMNT: - xdr_argument = (xdrproc_t) xdr_amq_string; - xdr_result = (xdrproc_t) xdr_void; - local = (amqsvcproc_t) amqproc_umnt_1_svc; - break; - - case AMQPROC_STATS: - xdr_argument = (xdrproc_t) xdr_void; - xdr_result = (xdrproc_t) xdr_amq_mount_stats; - local = (amqsvcproc_t) amqproc_stats_1_svc; - break; - - case AMQPROC_EXPORT: - xdr_argument = (xdrproc_t) xdr_void; - xdr_result = (xdrproc_t) xdr_amq_mount_tree_list; - local = (amqsvcproc_t) amqproc_export_1_svc; - break; - - case AMQPROC_SETOPT: - xdr_argument = (xdrproc_t) xdr_amq_setopt; - xdr_result = (xdrproc_t) xdr_int; - local = (amqsvcproc_t) amqproc_setopt_1_svc; - break; - - case AMQPROC_GETMNTFS: - xdr_argument = (xdrproc_t) xdr_void; - xdr_result = (xdrproc_t) xdr_amq_mount_info_qelem; - local = (amqsvcproc_t) amqproc_getmntfs_1_svc; - break; - - case AMQPROC_GETVERS: - xdr_argument = (xdrproc_t) xdr_void; - xdr_result = (xdrproc_t) xdr_amq_string; - local = (amqsvcproc_t) amqproc_getvers_1_svc; - break; - - case AMQPROC_GETPID: - xdr_argument = (xdrproc_t) xdr_void; - xdr_result = (xdrproc_t) xdr_int; - local = (amqsvcproc_t) amqproc_getpid_1_svc; - break; - - case AMQPROC_PAWD: - xdr_argument = (xdrproc_t) xdr_amq_string; - xdr_result = (xdrproc_t) xdr_amq_string; - local = (amqsvcproc_t) amqproc_pawd_1_svc; - break; - - default: - svcerr_noproc(transp); - return; - } - - memset((char *) &argument, 0, sizeof(argument)); - if (!svc_getargs(transp, - (XDRPROC_T_TYPE) xdr_argument, - (SVC_IN_ARG_TYPE) & argument)) { - svcerr_decode(transp); - return; - } - - result = (*local) (&argument, rqstp); - - if (result != NULL && !svc_sendreply(transp, - (XDRPROC_T_TYPE) xdr_result, - result)) { - svcerr_systemerr(transp); - } - - if (!svc_freeargs(transp, - (XDRPROC_T_TYPE) xdr_argument, - (SVC_IN_ARG_TYPE) & argument)) { - plog(XLOG_FATAL, "unable to free rpc arguments in amqprog_1"); - going_down(1); - } -} diff --git a/contrib/amd/amd/autil.c b/contrib/amd/amd/autil.c deleted file mode 100644 index a5ecd6d0d1f3..000000000000 --- a/contrib/amd/amd/autil.c +++ /dev/null @@ -1,783 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/autil.c - * - */ - -/* - * utilities specified to amd, taken out of the older amd/util.c. - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -int NumChildren = 0; /* number of children of primary amd */ -static char invalid_keys[] = "\"'!;@ \t\n"; - -/**************************************************************************** - *** MACROS *** - ****************************************************************************/ - -#ifdef HAVE_TRANSPORT_TYPE_TLI -# define PARENT_USLEEP_TIME 100000 /* 0.1 seconds */ -#endif /* HAVE_TRANSPORT_TYPE_TLI */ - - -/**************************************************************************** - *** FORWARD DEFINITIONS *** - ****************************************************************************/ -static void domain_strip(char *otherdom, char *localdom); -static int dofork(void); - - -/**************************************************************************** - *** FUNCTIONS *** - ****************************************************************************/ - -/* - * Copy s into p, reallocating p if necessary - */ -char * -strealloc(char *p, char *s) -{ - size_t len = strlen(s) + 1; - - p = (char *) xrealloc((voidp) p, len); - - xstrlcpy(p, s, len); -#ifdef DEBUG_MEM -# if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY) - malloc_verify(); -# endif /* not defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY) */ -#endif /* DEBUG_MEM */ - return p; -} - - -/* - * 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. - */ -static void -domain_strip(char *otherdom, char *localdom) -{ - char *p1, *p2; - - if ((p1 = strchr(otherdom, '.')) && - (p2 = strchr(localdom, '.')) && - STREQ(p1 + 1, p2 + 1)) - *p1 = '\0'; -} - - -/* - * Normalize a host name: replace cnames with real names, and decide if to - * strip domain name or not. - */ -void -host_normalize(char **chp) -{ - /* - * Normalize hosts is used to resolve host name aliases - * and replace them with the standard-form name. - * Invoked with "-n" command line option. - */ - if (gopt.flags & CFM_NORMALIZE_HOSTNAMES) { - struct hostent *hp; - hp = gethostbyname(*chp); - if (hp && hp->h_addrtype == AF_INET) { - dlog("Hostname %s normalized to %s", *chp, hp->h_name); - *chp = strealloc(*chp, (char *) hp->h_name); - } - } - if (gopt.flags & CFM_DOMAIN_STRIP) { - domain_strip(*chp, hostd); - } -} - - -/* - * Keys are not allowed to contain " ' ! or ; to avoid - * problems with macro expansions. - */ -int -valid_key(char *key) -{ - while (*key) - if (strchr(invalid_keys, *key++)) - return FALSE; - return TRUE; -} - - -void -forcibly_timeout_mp(am_node *mp) -{ - mntfs *mf = mp->am_mnt; - /* - * Arrange to timeout this node - */ - if (mf && ((mp->am_flags & AMF_ROOT) || - (mf->mf_flags & (MFF_MOUNTING | MFF_UNMOUNTING)))) { - if (mf->mf_flags & MFF_UNMOUNTING) - plog(XLOG_WARNING, "node %s is currently being unmounted, ignoring timeout request", mp->am_path); - else - plog(XLOG_WARNING, "ignoring timeout request for active node %s", mp->am_path); - } else { - plog(XLOG_INFO, "\"%s\" forcibly timed out", mp->am_path); - mp->am_flags &= ~AMF_NOTIMEOUT; - mp->am_ttl = clocktime(NULL); - /* - * Force mtime update of parent dir, to prevent DNLC/dcache from caching - * the old entry, which could result in ESTALE errors, bad symlinks, and - * more. - */ - clocktime(&mp->am_parent->am_fattr.na_mtime); - reschedule_timeout_mp(); - } -} - - -void -mf_mounted(mntfs *mf, bool_t call_free_opts) -{ - int quoted; - int wasmounted = mf->mf_flags & MFF_MOUNTED; - - if (!wasmounted) { - /* - * If this is a freshly mounted - * filesystem then update the - * mntfs structure... - */ - mf->mf_flags |= MFF_MOUNTED; - mf->mf_error = 0; - - /* - * Do mounted callback - */ - if (mf->mf_ops->mounted) - mf->mf_ops->mounted(mf); - - /* - * Be careful when calling free_ops and XFREE here. Some pseudo file - * systems like nfsx call this function (mf_mounted), even though it - * would be called by the lower-level amd file system functions. nfsx - * needs to call this function because of the other actions it takes. - * So we pass a boolean from the caller (yes, not so clean workaround) - * to determine if we should free or not. If we're not freeing (often - * because we're called from a callback function), then just to be sure, - * we'll zero out the am_opts structure and set the pointer to NULL. - * The parent mntfs node owns this memory and is going to free it with a - * call to mf_mounted(mntfs,TRUE) (see comment in the am_mounted code). - */ - if (call_free_opts) { - free_opts(mf->mf_fo); /* this free is needed to prevent leaks */ - XFREE(mf->mf_fo); /* (also this one) */ - } else { - memset(mf->mf_fo, 0, sizeof(am_opts)); - mf->mf_fo = NULL; - } - } - - if (mf->mf_flags & MFF_RESTART) { - mf->mf_flags &= ~MFF_RESTART; - dlog("Restarted filesystem %s, flags 0x%x", mf->mf_mount, mf->mf_flags); - } - - /* - * Log message - */ - quoted = strchr(mf->mf_info, ' ') != 0; - plog(XLOG_INFO, "%s%s%s %s fstype %s on %s", - quoted ? "\"" : "", - mf->mf_info, - quoted ? "\"" : "", - wasmounted ? "referenced" : "mounted", - mf->mf_ops->fs_type, mf->mf_mount); -} - - -void -am_mounted(am_node *mp) -{ - int notimeout = 0; /* assume normal timeouts initially */ - mntfs *mf = mp->am_mnt; - - /* - * This is the parent mntfs which does the mf->mf_fo (am_opts type), and - * we're passing TRUE here to tell mf_mounted to actually free the - * am_opts. See a related comment in mf_mounted(). - */ - mf_mounted(mf, TRUE); - -#ifdef HAVE_FS_AUTOFS - if (mf->mf_flags & MFF_IS_AUTOFS) - autofs_mounted(mp); -#endif /* HAVE_FS_AUTOFS */ - - /* - * Patch up path for direct mounts - */ - if (mp->am_parent && mp->am_parent->am_mnt->mf_fsflags & FS_DIRECT) - mp->am_path = str3cat(mp->am_path, mp->am_parent->am_path, "/", "."); - - /* - * Check whether this mount should be cached permanently or not, - * and handle user-requested timeouts. - */ - /* first check if file system was set to never timeout */ - if (mf->mf_fsflags & FS_NOTIMEOUT) - notimeout = 1; - /* next, alter that decision by map flags */ - if (mf->mf_mopts) { - mntent_t mnt; - mnt.mnt_opts = mf->mf_mopts; - - /* umount option: user wants to unmount this entry */ - if (amu_hasmntopt(&mnt, "unmount") || amu_hasmntopt(&mnt, "umount")) - notimeout = 0; - /* noumount option: user does NOT want to unmount this entry */ - if (amu_hasmntopt(&mnt, "nounmount") || amu_hasmntopt(&mnt, "noumount")) - notimeout = 1; - /* utimeout=N option: user wants to unmount this option AND set timeout */ - if ((mp->am_timeo = hasmntval(&mnt, "utimeout")) == 0) - mp->am_timeo = gopt.am_timeo; /* otherwise use default timeout */ - else - notimeout = 0; - /* special case: don't try to unmount "/" (it can never succeed) */ - if (mf->mf_mount[0] == '/' && mf->mf_mount[1] == '\0') - notimeout = 1; - } - /* finally set actual flags */ - if (notimeout) { - mp->am_flags |= AMF_NOTIMEOUT; - plog(XLOG_INFO, "%s set to never timeout", mp->am_path); - } else { - mp->am_flags &= ~AMF_NOTIMEOUT; - plog(XLOG_INFO, "%s set to timeout in %d seconds", mp->am_path, mp->am_timeo); - } - - /* - * If this node is a symlink then - * compute the length of the returned string. - */ - if (mp->am_fattr.na_type == NFLNK) - mp->am_fattr.na_size = strlen(mp->am_link ? mp->am_link : mf->mf_mount); - - /* - * Record mount time, and update am_stats at the same time. - */ - mp->am_stats.s_mtime = clocktime(&mp->am_fattr.na_mtime); - new_ttl(mp); - - /* - * Update mtime of parent node (copying "struct nfstime" in '=' below) - */ - if (mp->am_parent && mp->am_parent->am_mnt) - mp->am_parent->am_fattr.na_mtime = mp->am_fattr.na_mtime; - - /* - * This is ugly, but essentially unavoidable - * Sublinks must be treated separately as type==link - * when the base type is different. - */ - if (mp->am_link && mf->mf_ops != &amfs_link_ops) - amfs_link_ops.mount_fs(mp, mf); - - /* - * Now, if we can, do a reply to our client here - * to speed things up. - */ -#ifdef HAVE_FS_AUTOFS - if (mp->am_flags & AMF_AUTOFS) - autofs_mount_succeeded(mp); - else -#endif /* HAVE_FS_AUTOFS */ - nfs_quick_reply(mp, 0); - - /* - * Update stats - */ - amd_stats.d_mok++; -} - - -/* - * Replace mount point with a reference to an error filesystem. - * The mount point (struct mntfs) is NOT discarded, - * the caller must do it if it wants to _before_ calling this function. - */ -void -assign_error_mntfs(am_node *mp) -{ - int error; - dlog("assign_error_mntfs"); - /* - * Save the old error code - */ - error = mp->am_error; - if (error <= 0) - error = mp->am_mnt->mf_error; - /* - * Allocate a new error reference - */ - mp->am_mnt = new_mntfs(); - /* - * Put back the error code - */ - mp->am_mnt->mf_error = error; - mp->am_mnt->mf_flags |= MFF_ERROR; - /* - * Zero the error in the mount point - */ - mp->am_error = 0; -} - - -/* - * Build a new map cache for this node, or re-use - * an existing cache for the same map. - */ -void -amfs_mkcacheref(mntfs *mf) -{ - char *cache; - - if (mf->mf_fo && mf->mf_fo->opt_cache) - cache = mf->mf_fo->opt_cache; - else - cache = "none"; - mf->mf_private = (opaque_t) mapc_find(mf->mf_info, - cache, - (mf->mf_fo ? mf->mf_fo->opt_maptype : NULL)); - mf->mf_prfree = mapc_free; -} - - -/* - * Locate next node in sibling list which is mounted - * and is not an error node. - */ -am_node * -next_nonerror_node(am_node *xp) -{ - mntfs *mf; - - /* - * Bug report (7/12/89) from Rein Tollevik <rein@ifi.uio.no> - * Fixes a race condition when mounting direct automounts. - * Also fixes a problem when doing a readdir on a directory - * containing hung automounts. - */ - while (xp && - (!(mf = xp->am_mnt) || /* No mounted filesystem */ - mf->mf_error != 0 || /* There was a mntfs error */ - xp->am_error != 0 || /* There was a mount error */ - !(mf->mf_flags & MFF_MOUNTED) || /* The fs is not mounted */ - (mf->mf_server->fs_flags & FSF_DOWN)) /* The fs may be down */ - ) - xp = xp->am_osib; - - return xp; -} - - -/* - * Mount an automounter directory. - * The automounter is connected into the system - * as a user-level NFS server. amfs_mount constructs - * the necessary NFS parameters to be given to the - * kernel so that it will talk back to us. - * - * NOTE: automounter mounts in themselves are using NFS Version 2 (UDP). - * - * NEW: on certain systems, mounting can be done using the - * kernel-level automount (autofs) support. In that case, - * we don't need NFS at all here. - */ -int -amfs_mount(am_node *mp, mntfs *mf, char *opts) -{ - char fs_hostname[MAXHOSTNAMELEN + MAXPATHLEN + 1]; - int retry, error = 0, genflags; - int on_autofs = mf->mf_flags & MFF_ON_AUTOFS; - char *dir = mf->mf_mount; - mntent_t mnt; - MTYPE_TYPE type; - int forced_unmount = 0; /* are we using forced unmounts? */ - - memset((voidp) &mnt, 0, sizeof(mnt)); - mnt.mnt_dir = dir; - mnt.mnt_fsname = pid_fsname; - mnt.mnt_opts = opts; - -#ifdef HAVE_FS_AUTOFS - if (mf->mf_flags & MFF_IS_AUTOFS) { - type = MOUNT_TYPE_AUTOFS; - /* - * Make sure that amd's top-level autofs mounts are hidden by default - * from df. - * XXX: It works ok on Linux, might not work on other systems. - */ - mnt.mnt_type = "autofs"; - } else -#endif /* HAVE_FS_AUTOFS */ - { - type = MOUNT_TYPE_NFS; - /* - * Make sure that amd's top-level NFS mounts are hidden by default - * from df. - * If they don't appear to support the either the "ignore" mnttab - * option entry, or the "auto" one, set the mount type to "nfs". - */ - mnt.mnt_type = HIDE_MOUNT_TYPE; - } - - retry = hasmntval(&mnt, MNTTAB_OPT_RETRY); - if (retry <= 0) - retry = 2; /* XXX: default to 2 retries */ - - /* - * SET MOUNT ARGS - */ - - /* - * Make a ``hostname'' string for the kernel - */ - xsnprintf(fs_hostname, sizeof(fs_hostname), "pid%ld@%s:%s", - get_server_pid(), am_get_hostname(), dir); - /* - * Most kernels have a name length restriction (64 bytes)... - */ - if (strlen(fs_hostname) >= MAXHOSTNAMELEN) - xstrlcpy(fs_hostname + MAXHOSTNAMELEN - 3, "..", - sizeof(fs_hostname) - MAXHOSTNAMELEN + 3); -#ifdef HOSTNAMESZ - /* - * ... and some of these restrictions are 32 bytes (HOSTNAMESZ) - * If you need to get the definition for HOSTNAMESZ found, you may - * add the proper header file to the conf/nfs_prot/nfs_prot_*.h file. - */ - if (strlen(fs_hostname) >= HOSTNAMESZ) - xstrlcpy(fs_hostname + HOSTNAMESZ - 3, "..", - sizeof(fs_hostname) - HOSTNAMESZ + 3); -#endif /* HOSTNAMESZ */ - - /* - * Finally we can compute the mount genflags set above, - * and add any automounter specific flags. - */ - genflags = compute_mount_flags(&mnt); -#ifdef HAVE_FS_AUTOFS - if (on_autofs) - genflags |= autofs_compute_mount_flags(&mnt); -#endif /* HAVE_FS_AUTOFS */ - genflags |= compute_automounter_mount_flags(&mnt); - -again: - if (!(mf->mf_flags & MFF_IS_AUTOFS)) { - nfs_args_t nfs_args; - am_nfs_fh *fhp; - am_nfs_handle_t anh; -#ifndef HAVE_TRANSPORT_TYPE_TLI - u_short port; - struct sockaddr_in sin; -#endif /* not HAVE_TRANSPORT_TYPE_TLI */ - - /* - * get fhandle of remote path for automount point - */ - fhp = get_root_nfs_fh(dir); - if (!fhp) { - plog(XLOG_FATAL, "Can't find root file handle for %s", dir); - return EINVAL; - } - -#ifndef HAVE_TRANSPORT_TYPE_TLI - /* - * Create sockaddr to point to the local machine. - */ - memset((voidp) &sin, 0, sizeof(sin)); - /* as per POSIX, sin_len need not be set (used internally by kernel) */ - sin.sin_family = AF_INET; - sin.sin_addr = myipaddr; - port = hasmntval(&mnt, MNTTAB_OPT_PORT); - if (port) { - sin.sin_port = htons(port); - } else { - plog(XLOG_ERROR, "no port number specified for %s", dir); - return EINVAL; - } -#endif /* not HAVE_TRANSPORT_TYPE_TLI */ - - /* setup the many fields and flags within nfs_args */ - memmove(&anh.v2, fhp, sizeof(*fhp)); -#ifdef HAVE_TRANSPORT_TYPE_TLI - compute_nfs_args(&nfs_args, - &mnt, - genflags, - nfsncp, - NULL, /* remote host IP addr is set below */ - NFS_VERSION, /* version 2 */ - "udp", - &anh, - fs_hostname, - pid_fsname); - /* - * IMPORTANT: set the correct IP address AFTERWARDS. It cannot - * be done using the normal mechanism of compute_nfs_args(), because - * that one will allocate a new address and use NFS_SA_DREF() to copy - * parts to it, while assuming that the ip_addr passed is always - * a "struct sockaddr_in". That assumption is incorrect on TLI systems, - * because they define a special macro HOST_SELF which is DIFFERENT - * than localhost (127.0.0.1)! - */ - nfs_args.addr = &nfsxprt->xp_ltaddr; -#else /* not HAVE_TRANSPORT_TYPE_TLI */ - compute_nfs_args(&nfs_args, - &mnt, - genflags, - NULL, - &sin, - NFS_VERSION, /* version 2 */ - "udp", - &anh, - fs_hostname, - pid_fsname); -#endif /* not HAVE_TRANSPORT_TYPE_TLI */ - - /************************************************************************* - * NOTE: while compute_nfs_args() works ok for regular NFS mounts * - * the toplvl one is not quite regular, and so some options must be * - * corrected by hand more carefully, *after* compute_nfs_args() runs. * - *************************************************************************/ - compute_automounter_nfs_args(&nfs_args, &mnt); - - if (amuDebug(D_TRACE)) { - print_nfs_args(&nfs_args, 0); - plog(XLOG_DEBUG, "Generic mount flags 0x%x", genflags); - } - - /* This is it! Here we try to mount amd on its mount points */ - error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args, - retry, type, 0, NULL, mnttab_file_name, on_autofs); - -#ifdef HAVE_TRANSPORT_TYPE_TLI - free_knetconfig(nfs_args.knconf); - /* - * local automounter mounts do not allocate a special address, so - * no need to XFREE(nfs_args.addr) under TLI. - */ -#endif /* HAVE_TRANSPORT_TYPE_TLI */ - -#ifdef HAVE_FS_AUTOFS - } else { - /* This is it! Here we try to mount amd on its mount points */ - error = mount_fs(&mnt, genflags, (caddr_t) mp->am_autofs_fh, - retry, type, 0, NULL, mnttab_file_name, on_autofs); -#endif /* HAVE_FS_AUTOFS */ - } - if (error == 0 || forced_unmount) - return error; - - /* - * If user wants forced/lazy unmount semantics, then try it iff the - * current mount failed with EIO or ESTALE. - */ - if (gopt.flags & CFM_FORCED_UNMOUNTS) { - switch (errno) { - case ESTALE: - case EIO: - forced_unmount = errno; - plog(XLOG_WARNING, "Mount %s failed (%m); force unmount.", mp->am_path); - if ((error = UMOUNT_FS(mp->am_path, mnttab_file_name, - AMU_UMOUNT_FORCE | AMU_UMOUNT_DETACH)) < 0) { - plog(XLOG_WARNING, "Forced umount %s failed: %m.", mp->am_path); - errno = forced_unmount; - } else - goto again; - default: - break; - } - } - - return error; -} - - -void -am_unmounted(am_node *mp) -{ - mntfs *mf = mp->am_mnt; - - if (!foreground) /* firewall - should never happen */ - return; - - /* - * Do unmounted callback - */ - if (mf->mf_ops->umounted) - mf->mf_ops->umounted(mf); - - /* - * This is ugly, but essentially unavoidable. - * Sublinks must be treated separately as type==link - * when the base type is different. - */ - if (mp->am_link && mf->mf_ops != &amfs_link_ops) - amfs_link_ops.umount_fs(mp, mf); - -#ifdef HAVE_FS_AUTOFS - if (mf->mf_flags & MFF_IS_AUTOFS) - autofs_release_fh(mp); - if (mp->am_flags & AMF_AUTOFS) - autofs_umount_succeeded(mp); -#endif /* HAVE_FS_AUTOFS */ - - /* - * Clean up any directories that were made - * - * If we remove the mount point of a pending mount, any queued access - * to it will fail. So don't do it in that case. - * Also don't do it if the refcount is > 1. - */ - if (mf->mf_flags & MFF_MKMNT && - mf->mf_refc == 1 && - !(mp->am_flags & AMF_REMOUNT)) { - plog(XLOG_INFO, "removing mountpoint directory '%s'", mf->mf_mount); - rmdirs(mf->mf_mount); - mf->mf_flags &= ~MFF_MKMNT; - } - - /* - * If this is a pseudo-directory then adjust the link count - * in the parent - */ - if (mp->am_parent && mp->am_fattr.na_type == NFDIR) - --mp->am_parent->am_fattr.na_nlink; - - /* - * Update mtime of parent node - */ - if (mp->am_parent && mp->am_parent->am_mnt) - clocktime(&mp->am_parent->am_fattr.na_mtime); - - if (mp->am_parent && (mp->am_flags & AMF_REMOUNT)) { - char *fname = strdup(mp->am_name); - am_node *mp_parent = mp->am_parent; - mntfs *mf_parent = mp_parent->am_mnt; - int error = 0; - - free_map(mp); - plog(XLOG_INFO, "am_unmounted: remounting %s", fname); - mp = mf_parent->mf_ops->lookup_child(mp_parent, fname, &error, VLOOK_CREATE); - if (mp && error < 0) - mp = mf_parent->mf_ops->mount_child(mp, &error); - if (error > 0) { - errno = error; - plog(XLOG_ERROR, "am_unmounted: could not remount %s: %m", fname); - } - XFREE(fname); - } else - /* - * We have a race here. - * If this node has a pending mount and amd is going down (unmounting - * everything in the process), then we could potentially free it here - * while a struct continuation still has a reference to it. So when - * amfs_cont is called, it blows up. - * We avoid the race by refusing to free any nodes that have - * pending mounts (defined as having a non-NULL am_mfarray). - */ - if (!mp->am_mfarray) - free_map(mp); -} - - -/* - * Fork the automounter - * - * TODO: Need a better strategy for handling errors - */ -static int -dofork(void) -{ - int pid; - -top: - pid = fork(); - - if (pid < 0) { /* fork error, retry in 1 second */ - sleep(1); - goto top; - } - if (pid == 0) { /* child process (foreground==false) */ - am_set_mypid(); - foreground = 0; - } else { /* parent process, has one more child */ - NumChildren++; - } - - return pid; -} - - -int -background(void) -{ - int pid = dofork(); - - if (pid == 0) { - dlog("backgrounded"); - foreground = 0; - } else - dlog("forked process %d", pid); - return pid; -} diff --git a/contrib/amd/amd/clock.c b/contrib/amd/amd/clock.c deleted file mode 100644 index 0caa7dff2c73..000000000000 --- a/contrib/amd/amd/clock.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (c) 1997-2006 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 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. - * - * - * File: am-utils/amd/clock.c - * - */ - -/* - * Callouts. - * - * Modeled on kernel object of the same name. - * See usual references. - * - * Use of a heap-based mechanism was rejected: - * 1. more complex implementation needed. - * 2. not obvious that a list is too slow for Amd. - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -void reschedule_timeouts(time_t now, time_t then); - -typedef struct callout callout; -struct callout { - callout *c_next; /* List of callouts */ - callout_fun *c_fn; /* Function to call */ - opaque_t c_arg; /* Argument to pass to call */ - time_t c_time; /* Time of call */ - int c_id; /* Unique identifier */ -}; - -static callout callouts; /* List of pending callouts */ -static callout *free_callouts; /* Cache of free callouts */ -static int nfree_callouts; /* Number on free list */ -static int callout_id; /* Next free callout identifier */ - -time_t next_softclock; /* Time of next call to softclock() */ - - -/* - * Number of callout slots we keep on the free list - */ -#define CALLOUT_FREE_SLOP 10 - -/* - * Global assumption: valid id's are non-zero. - */ -#define CID_ALLOC() (++callout_id) -#define CID_UNDEF (0) - - -static callout * -alloc_callout(void) -{ - callout *cp = free_callouts; - - if (cp) { - --nfree_callouts; - free_callouts = free_callouts->c_next; - return cp; - } - return ALLOC(struct callout); -} - - -static void -free_callout(callout *cp) -{ - if (nfree_callouts > CALLOUT_FREE_SLOP) { - XFREE(cp); - } else { - cp->c_next = free_callouts; - free_callouts = cp; - nfree_callouts++; - } -} - - -/* - * Schedule a callout. - * - * (*fn)(fn_arg) will be called at clocktime(NULL) + secs - */ -int -timeout(u_int secs, callout_fun *fn, opaque_t fn_arg) -{ - callout *cp, *cp2; - time_t t = clocktime(NULL) + secs; - - /* - * Allocate and fill in a new callout structure - */ - callout *cpnew = alloc_callout(); - cpnew->c_arg = fn_arg; - cpnew->c_fn = fn; - cpnew->c_time = t; - cpnew->c_id = CID_ALLOC(); - - if (t < next_softclock) - next_softclock = t; - - /* - * Find the correct place in the list - */ - for (cp = &callouts; (cp2 = cp->c_next); cp = cp2) - if (cp2->c_time >= t) - break; - - /* - * And link it in - */ - cp->c_next = cpnew; - cpnew->c_next = cp2; - - /* - * Return callout identifier - */ - return cpnew->c_id; -} - - -/* - * De-schedule a callout - */ -void -untimeout(int id) -{ - callout *cp, *cp2; - for (cp = &callouts; (cp2 = cp->c_next); cp = cp2) { - if (cp2->c_id == id) { - cp->c_next = cp2->c_next; - free_callout(cp2); - break; - } - } -} - - -/* - * Reschedule after clock changed - */ -void -reschedule_timeouts(time_t now, time_t then) -{ - callout *cp; - - for (cp = callouts.c_next; cp; cp = cp->c_next) { - if (cp->c_time >= now && cp->c_time <= then) { - plog(XLOG_WARNING, "job %d rescheduled to run immediately", cp->c_id); - dlog("rescheduling job %d back %ld seconds", - cp->c_id, (long) (cp->c_time - now)); - next_softclock = cp->c_time = now; - } - } -} - - -/* - * Clock handler - */ -int -softclock(void) -{ - time_t now; - callout *cp; - - do { - if (task_notify_todo) - do_task_notify(); - - now = clocktime(NULL); - - /* - * While there are more callouts waiting... - */ - while ((cp = callouts.c_next) && cp->c_time <= now) { - /* - * Extract first from list, save fn & fn_arg and - * unlink callout from list and free. - * Finally call function. - * - * The free is done first because - * it is quite common that the - * function will call timeout() - * and try to allocate a callout - */ - callout_fun *fn = cp->c_fn; - opaque_t fn_arg = cp->c_arg; - - callouts.c_next = cp->c_next; - free_callout(cp); - (*fn) (fn_arg); - } - - } while (task_notify_todo); - - /* - * Return number of seconds to next event, - * or 0 if there is no event. - */ - if ((cp = callouts.c_next)) - return cp->c_time - now; - return 0; -} diff --git a/contrib/amd/amd/conf.c b/contrib/amd/amd/conf.c deleted file mode 100644 index 2fc587b0cadb..000000000000 --- a/contrib/amd/amd/conf.c +++ /dev/null @@ -1,1406 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/conf.c - * - */ - -/* - * Functions to handle the configuration file. - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - - -/* - * MACROS: - */ -/* Turn on to show some info about maps being configured */ -/* #define DEBUG_CONF */ - -/* - * TYPEDEFS: - */ -typedef int (*OptFuncPtr)(const char *); - -/* - * STRUCTURES: - */ -struct _func_map { - char *name; - OptFuncPtr func; -}; - -/* - * FORWARD DECLARATIONS: - */ -static int gopt_arch(const char *val); -static int gopt_auto_attrcache(const char *val); -static int gopt_auto_dir(const char *val); -static int gopt_autofs_use_lofs(const char *val); -static int gopt_browsable_dirs(const char *val); -static int gopt_cache_duration(const char *val); -static int gopt_cluster(const char *val); -static int gopt_debug_mtab_file(const char *val); -static int gopt_debug_options(const char *val); -static int gopt_dismount_interval(const char *val); -static int gopt_domain_strip(const char *val); -static int gopt_exec_map_timeout(const char *val); -static int gopt_forced_unmounts(const char *val); -static int gopt_full_os(const char *val); -static int gopt_fully_qualified_hosts(const char *val); -static int gopt_hesiod_base(const char *val); -static int gopt_karch(const char *val); -static int gopt_ldap_base(const char *val); -static int gopt_ldap_cache_maxmem(const char *val); -static int gopt_ldap_cache_seconds(const char *val); -static int gopt_ldap_hostports(const char *val); -static int gopt_ldap_proto_version(const char *val); -static int gopt_local_domain(const char *val); -static int gopt_localhost_address(const char *val); -static int gopt_log_file(const char *val); -static int gopt_log_options(const char *val); -static int gopt_map_defaults(const char *val); -static int gopt_map_options(const char *val); -static int gopt_map_reload_interval(const char *val); -static int gopt_map_type(const char *val); -static int gopt_mount_type(const char *val); -static int gopt_pid_file(const char *val); -static int gopt_portmap_program(const char *val); -static int gopt_preferred_amq_port(const char *val); -static int gopt_nfs_allow_any_interface(const char *val); -static int gopt_nfs_allow_insecure_port(const char *val); -static int gopt_nfs_proto(const char *val); -static int gopt_nfs_retransmit_counter(const char *val); -static int gopt_nfs_retransmit_counter_udp(const char *val); -static int gopt_nfs_retransmit_counter_tcp(const char *val); -static int gopt_nfs_retransmit_counter_toplvl(const char *val); -static int gopt_nfs_retry_interval(const char *val); -static int gopt_nfs_retry_interval_udp(const char *val); -static int gopt_nfs_retry_interval_tcp(const char *val); -static int gopt_nfs_retry_interval_toplvl(const char *val); -static int gopt_nfs_vers(const char *val); -static int gopt_nis_domain(const char *val); -static int gopt_normalize_hostnames(const char *val); -static int gopt_normalize_slashes(const char *val); -static int gopt_os(const char *val); -static int gopt_osver(const char *val); -static int gopt_plock(const char *val); -static int gopt_print_pid(const char *val); -static int gopt_print_version(const char *val); -static int gopt_restart_mounts(const char *val); -static int gopt_search_path(const char *val); -static int gopt_selectors_in_defaults(const char *val); -static int gopt_show_statfs_entries(const char *val); -static int gopt_truncate_log(const char *val); -static int gopt_unmount_on_exit(const char *val); -static int gopt_use_tcpwrappers(const char *val); -static int gopt_vendor(const char *val); -static int process_global_option(const char *key, const char *val); -static int process_one_regular_map(const cf_map_t *cfm); -static int process_regular_option(const char *section, const char *key, const char *val, cf_map_t *cfm); -static int ropt_browsable_dirs(const char *val, cf_map_t *cfm); -static int ropt_map_name(const char *val, cf_map_t *cfm); -static int ropt_map_defaults(const char *val, cf_map_t *cfm); -static int ropt_map_options(const char *val, cf_map_t *cfm); -static int ropt_map_type(const char *val, cf_map_t *cfm); -static int ropt_mount_type(const char *val, cf_map_t *cfm); -static int ropt_search_path(const char *val, cf_map_t *cfm); -static int ropt_tag(const char *val, cf_map_t *cfm); -static void init_cf_map(cf_map_t *cfm); - - -/* - * STATIC VARIABLES: - */ -static cf_map_t *head_map, *cur_map; - -static struct _func_map glob_functable[] = { - {"arch", gopt_arch}, - {"auto_attrcache", gopt_auto_attrcache}, - {"auto_dir", gopt_auto_dir}, - {"autofs_use_lofs", gopt_autofs_use_lofs}, - {"browsable_dirs", gopt_browsable_dirs}, - {"cache_duration", gopt_cache_duration}, - {"cluster", gopt_cluster}, - {"debug_mtab_file", gopt_debug_mtab_file}, - {"debug_options", gopt_debug_options}, - {"dismount_interval", gopt_dismount_interval}, - {"domain_strip", gopt_domain_strip}, - {"exec_map_timeout", gopt_exec_map_timeout}, - {"forced_unmounts", gopt_forced_unmounts}, - {"fully_qualified_hosts", gopt_fully_qualified_hosts}, - {"full_os", gopt_full_os}, - {"hesiod_base", gopt_hesiod_base}, - {"karch", gopt_karch}, - {"ldap_base", gopt_ldap_base}, - {"ldap_cache_maxmem", gopt_ldap_cache_maxmem}, - {"ldap_cache_seconds", gopt_ldap_cache_seconds}, - {"ldap_hostports", gopt_ldap_hostports}, - {"ldap_proto_version", gopt_ldap_proto_version}, - {"local_domain", gopt_local_domain}, - {"localhost_address", gopt_localhost_address}, - {"log_file", gopt_log_file}, - {"log_options", gopt_log_options}, - {"map_defaults", gopt_map_defaults}, - {"map_options", gopt_map_options}, - {"map_reload_interval", gopt_map_reload_interval}, - {"map_type", gopt_map_type}, - {"mount_type", gopt_mount_type}, - {"pid_file", gopt_pid_file}, - {"portmap_program", gopt_portmap_program}, - {"preferred_amq_port", gopt_preferred_amq_port}, - {"nfs_allow_any_interface", gopt_nfs_allow_any_interface}, - {"nfs_allow_insecure_port", gopt_nfs_allow_insecure_port}, - {"nfs_proto", gopt_nfs_proto}, - {"nfs_retransmit_counter", gopt_nfs_retransmit_counter}, - {"nfs_retransmit_counter_udp", gopt_nfs_retransmit_counter_udp}, - {"nfs_retransmit_counter_tcp", gopt_nfs_retransmit_counter_tcp}, - {"nfs_retransmit_counter_toplvl", gopt_nfs_retransmit_counter_toplvl}, - {"nfs_retry_interval", gopt_nfs_retry_interval}, - {"nfs_retry_interval_udp", gopt_nfs_retry_interval_udp}, - {"nfs_retry_interval_tcp", gopt_nfs_retry_interval_tcp}, - {"nfs_retry_interval_toplvl", gopt_nfs_retry_interval_toplvl}, - {"nfs_vers", gopt_nfs_vers}, - {"nis_domain", gopt_nis_domain}, - {"normalize_hostnames", gopt_normalize_hostnames}, - {"normalize_slashes", gopt_normalize_slashes}, - {"os", gopt_os}, - {"osver", gopt_osver}, - {"plock", gopt_plock}, - {"print_pid", gopt_print_pid}, - {"print_version", gopt_print_version}, - {"restart_mounts", gopt_restart_mounts}, - {"search_path", gopt_search_path}, - {"selectors_on_default", gopt_selectors_in_defaults}, - {"selectors_in_defaults", gopt_selectors_in_defaults}, - {"show_statfs_entries", gopt_show_statfs_entries}, - {"truncate_log", gopt_truncate_log}, - {"unmount_on_exit", gopt_unmount_on_exit}, - {"use_tcpwrappers", gopt_use_tcpwrappers}, - {"vendor", gopt_vendor}, - {NULL, NULL} -}; - - -/* - * Initialize a map from [global] defaults. - */ -static void -init_cf_map(cf_map_t *cfm) -{ - if (!cfm) - return; - - /* - * Initialize a regular map's flags and other variables from the - * global ones, so that they are applied to all maps. Of course, each map - * can then override the flags individually. - * - * NOTES: - * (1): Will only work for maps that appear after [global]. - * (2): I'm assigning pointers directly from the global map. - */ - - /* initialize map_type from [global] */ - cfm->cfm_type = gopt.map_type; - - /* initialize map_defaults from [global] */ - cfm->cfm_defaults = gopt.map_defaults; - - /* initialize map_opts from [global] */ - cfm->cfm_opts = gopt.map_options; - - /* initialize search_path from [global] */ - cfm->cfm_search_path = gopt.search_path; - - /* - * Initialize flags that are common both to [global] and a local map. - */ - cfm->cfm_flags = gopt.flags & (CFM_BROWSABLE_DIRS | - CFM_BROWSABLE_DIRS_FULL | - CFM_MOUNT_TYPE_AUTOFS | - CFM_SELECTORS_IN_DEFAULTS); -} - - -/* - * Process configuration file options (called from YACC parser). - * Return 0 if OK, 1 otherwise. - */ -int -set_conf_kv(const char *section, const char *key, const char *val) -{ - int ret; - -#ifdef DEBUG_CONF - fprintf(stderr, "set_conf_kv: section=%s, key=%s, val=%s\n", - section, key, val); -#endif /* DEBUG_CONF */ - - /* - * If global section, process kv pairs one at a time. - */ - if (STREQ(section, "global")) { - /* - * Check if a regular map was configured before "global", - * and warn about it. - */ - if (cur_map && cur_map->cfm_dir) { - static short printed_this_error; - if (!printed_this_error) { - fprintf(stderr, "found regular map \"%s\" before global one.\n", - cur_map->cfm_dir); - printed_this_error = 1; - } - } - - /* process the global option first */ - ret = process_global_option(key, val); - - /* return status from the processing of the global option */ - return ret; - } - - /* - * Otherwise we found a non-global option: store it after some testing. - */ - - /* initialize (static) global list head and current map pointer */ - if (!head_map && !cur_map) { - cur_map = CALLOC(cf_map_t); - if (!cur_map) { - perror("calloc"); - exit(1); - } - /* initialize first head map from global defaults */ - init_cf_map(cur_map); - head_map = cur_map; - } - - /* check if we found a new map, then allocate and initialize it */ - if (cur_map->cfm_dir && !STREQ(cur_map->cfm_dir, section)) { - /* allocate new map struct */ - cf_map_t *tmp_map = CALLOC(cf_map_t); - if (!tmp_map) { - perror("calloc"); - exit(1); - } - /* initialize it from global defaults */ - init_cf_map(tmp_map); - /* append it to end of linked list */ - cur_map->cfm_next = tmp_map; - cur_map = tmp_map; - } - - /* now process a single entry of a regular map */ - return process_regular_option(section, key, val, cur_map); -} - - -/* - * Process global section of configuration file options. - * Return 0 upon success, 1 otherwise. - */ -static int -process_global_option(const char *key, const char *val) -{ - struct _func_map *gfp; - - /* ensure that val is valid */ - if (!val || val[0] == '\0') - return 1; - - /* - * search for global function. - */ - for (gfp = glob_functable; gfp->name; gfp++) - if (FSTREQ(gfp->name, key)) - return (gfp->func)(val); - - fprintf(stderr, "conf: unknown global key: \"%s\"\n", key); - return 1; /* failed to match any command */ -} - - -static int -gopt_arch(const char *val) -{ - gopt.arch = strdup((char *)val); - return 0; -} - - -static int -gopt_auto_attrcache(const char *val) -{ - gopt.auto_attrcache = atoi(val); - if (gopt.auto_attrcache < 0) { - fprintf(stderr, "conf: bad attrcache value: \"%s\"\n", val); - return 1; - } - return 0; -} - - -static int -gopt_auto_dir(const char *val) -{ - gopt.auto_dir = strdup((char *)val); - return 0; -} - - -static int -gopt_autofs_use_lofs(const char *val) -{ - if (STREQ(val, "yes")) { - gopt.flags |= CFM_AUTOFS_USE_LOFS; - return 0; - } else if (STREQ(val, "no")) { - gopt.flags &= ~CFM_AUTOFS_USE_LOFS; - return 0; - } - - fprintf(stderr, "conf: unknown value to autofs_use_lofs \"%s\"\n", val); - return 1; /* unknown value */ -} - - -static int -gopt_browsable_dirs(const char *val) -{ - if (STREQ(val, "full")) { - gopt.flags |= CFM_BROWSABLE_DIRS_FULL; - return 0; - } else if (STREQ(val, "yes")) { - gopt.flags |= CFM_BROWSABLE_DIRS; - return 0; - } else if (STREQ(val, "no")) { - gopt.flags &= ~CFM_BROWSABLE_DIRS; - return 0; - } - - fprintf(stderr, "conf: unknown value to browsable_dirs \"%s\"\n", val); - return 1; /* unknown value */ -} - - -static int -gopt_cache_duration(const char *val) -{ - gopt.am_timeo = atoi(val); - if (gopt.am_timeo <= 0) - gopt.am_timeo = AM_TTL; - return 0; -} - - -static int -gopt_cluster(const char *val) -{ - gopt.cluster = strdup((char *)val); - return 0; -} - - -static int -gopt_debug_mtab_file(const char *val) -{ - gopt.debug_mtab_file = strdup((char*)val); - return 0; -} - - -static int -gopt_debug_options(const char *val) -{ -#ifdef DEBUG - usage += debug_option((char *)val); - return 0; -#else /* not DEBUG */ - fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n", - am_get_progname()); - return 1; -#endif /* not DEBUG */ -} - - -static int -gopt_dismount_interval(const char *val) -{ - gopt.am_timeo_w = atoi(val); - if (gopt.am_timeo_w <= 0) - gopt.am_timeo_w = AM_TTL_W; - return 0; -} - - -static int -gopt_domain_strip(const char *val) -{ - if (STREQ(val, "yes")) { - gopt.flags |= CFM_DOMAIN_STRIP; - return 0; - } else if (STREQ(val, "no")) { - gopt.flags &= ~CFM_DOMAIN_STRIP; - return 0; - } - - fprintf(stderr, "conf: unknown value to domain_strip \"%s\"\n", val); - return 1; /* unknown value */ -} - - -static int -gopt_exec_map_timeout(const char *val) -{ - gopt.exec_map_timeout = atoi(val); - if (gopt.exec_map_timeout <= 0) - gopt.exec_map_timeout = AMFS_EXEC_MAP_TIMEOUT; /* default exec map timeout */ - return 0; -} - - -static int -gopt_forced_unmounts(const char *val) -{ - if (STREQ(val, "yes")) { -#if !defined(MNT2_GEN_OPT_DETACH) && !defined(MNT2_GEN_OPT_FORCE) - fprintf(stderr, "conf: forced_unmounts unsupported on this system.\n"); - return 1; -#else /* defined(MNT2_GEN_OPT_DETACH) || defined(MNT2_GEN_OPT_FORCE) */ -# ifdef __linux__ - /* - * HACK ALERT: Linux has had MNT_FORCE since 2.2, but it hasn't gotten - * stable until 2.4. And it had MNT_DETACH since 2.4, but it hasn't - * gotten stable since 2.6. So alert users if they're trying to use a - * feature that may not work well on their older kernel. - */ - { - struct utsname un; - if (uname(&un) >= 0) { -# ifdef MNT2_GEN_OPT_FORCE - if (strcmp(un.release, "2.4.0") < 0) - fprintf(stderr, "warning: forced-unmounts (MNT_FORCE) may not work well before 2.4.0\n"); -# endif /* MNT2_GEN_OPT_FORCE */ -# ifdef MNT2_GEN_OPT_DETACH - if (strcmp(un.release, "2.6.0") < 0) - fprintf(stderr, "warning: lazy-unmounts (MNT_DETACH) may not work well before 2.6.0\n"); -# endif /* MNT2_GEN_OPT_DETACH */ - } - } -# endif /* __linux__ */ - gopt.flags |= CFM_FORCED_UNMOUNTS; - return 0; -#endif /* defined(MNT2_GEN_OPT_DETACH) || defined(MNT2_GEN_OPT_FORCE) */ - } else if (STREQ(val, "no")) { - gopt.flags &= ~CFM_FORCED_UNMOUNTS; - return 0; - } - - fprintf(stderr, "conf: unknown value to unmount_on_exit \"%s\"\n", val); - return 1; /* unknown value */ -} - - -static int -gopt_full_os(const char *val) -{ - gopt.op_sys_full = strdup((char *)val); - return 0; -} - - -static int -gopt_fully_qualified_hosts(const char *val) -{ - if (STREQ(val, "yes")) { - gopt.flags |= CFM_FULLY_QUALIFIED_HOSTS; - return 0; - } else if (STREQ(val, "no")) { - gopt.flags &= ~CFM_FULLY_QUALIFIED_HOSTS; - return 0; - } - - fprintf(stderr, "conf: unknown value to fully_qualified_hosts \"%s\"\n", val); - return 1; /* unknown value */ -} - - -static int -gopt_hesiod_base(const char *val) -{ -#ifdef HAVE_MAP_HESIOD - gopt.hesiod_base = strdup((char *)val); - return 0; -#else /* not HAVE_MAP_HESIOD */ - fprintf(stderr, "conf: hesiod_base option ignored. No Hesiod support available.\n"); - return 1; -#endif /* not HAVE_MAP_HESIOD */ -} - - -static int -gopt_karch(const char *val) -{ - gopt.karch = strdup((char *)val); - return 0; -} - - -static int -gopt_pid_file(const char *val) -{ - gopt.pid_file = strdup((char *)val); - return 0; -} - - -static int -gopt_local_domain(const char *val) -{ - gopt.sub_domain = strdup((char *)val); - return 0; -} - - -static int -gopt_localhost_address(const char *val) -{ - gopt.localhost_address = strdup((char *)val); - return 0; -} - - -static int -gopt_ldap_base(const char *val) -{ -#ifdef HAVE_MAP_LDAP - gopt.ldap_base = strdup((char *)val); - return 0; -#else /* not HAVE_MAP_LDAP */ - fprintf(stderr, "conf: ldap_base option ignored. No LDAP support available.\n"); - return 1; -#endif /* not HAVE_MAP_LDAP */ -} - - -static int -gopt_ldap_cache_seconds(const char *val) -{ -#ifdef HAVE_MAP_LDAP - char *end; - - gopt.ldap_cache_seconds = strtol((char *)val, &end, 10); - if (end == val) { - fprintf(stderr, "conf: bad LDAP cache (seconds) option: %s\n",val); - return 1; - } - return 0; -#else /* not HAVE_MAP_LDAP */ - fprintf(stderr, "conf: ldap_cache_seconds option ignored. No LDAP support available.\n"); - return 1; -#endif /* not HAVE_MAP_LDAP */ -} - - -static int -gopt_ldap_cache_maxmem(const char *val) -{ -#ifdef HAVE_MAP_LDAP - char *end; - - gopt.ldap_cache_maxmem = strtol((char *)val, &end, 10); - if (end == val) { - fprintf(stderr, "conf: bad LDAP cache (maxmem) option: %s\n",val); - return 1; - } - return 0; -#else /* not HAVE_MAP_LDAP */ - fprintf(stderr, "conf: ldap_cache_maxmem option ignored. No LDAP support available.\n"); - return 1; -#endif /* not HAVE_MAP_LDAP */ -} - - -static int -gopt_ldap_hostports(const char *val) -{ -#ifdef HAVE_MAP_LDAP - gopt.ldap_hostports = strdup((char *)val); - return 0; -#else /* not HAVE_MAP_LDAP */ - fprintf(stderr, "conf: ldap_hostports option ignored. No LDAP support available.\n"); - return 1; -#endif /* not HAVE_MAP_LDAP */ - -} - - -static int -gopt_ldap_proto_version(const char *val) -{ -#ifdef HAVE_MAP_LDAP - char *end; - - gopt.ldap_proto_version = strtol((char *)val, &end, 10); - if (end == val) { - fprintf(stderr, "conf: bad ldap_proto_version option: %s\n",val); - return 1; - } - - if (gopt.ldap_proto_version < 0 || gopt.ldap_proto_version > LDAP_VERSION_MAX) { - fprintf(stderr, "conf: bad ldap_proto_version option value: %s\n",val); - return 1; - } - switch (gopt.ldap_proto_version) { - /* XXX: what about LDAP_VERSION1? */ - case LDAP_VERSION2: -#ifdef LDAP_VERSION3 - case LDAP_VERSION3: -#endif /* LDAP_VERSION3 */ -#ifdef LDAP_VERSION4 - case LDAP_VERSION4: -#endif /* LDAP_VERSION4 */ - break; - default: - fprintf(stderr, "conf: unsupported ldap_proto_version option value: %s\n",val); - return 1; - } - return 0; -#else /* not HAVE_MAP_LDAP */ - fprintf(stderr, "conf: ldap_proto_version option ignored. No LDAP support available.\n"); - return 1; -#endif /* not HAVE_MAP_LDAP */ -} - - -static int -gopt_log_file(const char *val) -{ - gopt.logfile = strdup((char *)val); - return 0; -} - - -static int -gopt_log_options(const char *val) -{ - usage += switch_option((char *)val); - return 0; -} - - -static int -gopt_map_defaults(const char *val) -{ - gopt.map_defaults = strdup((char *)val); - return 0; -} - - -static int -gopt_map_options(const char *val) -{ - gopt.map_options = strdup((char *)val); - return 0; -} - - -static int -gopt_map_reload_interval(const char *val) -{ - gopt.map_reload_interval = atoi(val); - if (gopt.map_reload_interval <= 0) - gopt.map_reload_interval = ONE_HOUR; - return 0; -} - - -static int -gopt_map_type(const char *val) -{ - /* check if map type exist */ - if (!mapc_type_exists(val)) { - fprintf(stderr, "conf: no such map type \"%s\"\n", val); - return 1; - } - gopt.map_type = strdup((char *)val); - return 0; -} - - -static int -gopt_mount_type(const char *val) -{ - if (STREQ(val, "autofs")) { -#ifdef HAVE_FS_AUTOFS - gopt.flags |= CFM_MOUNT_TYPE_AUTOFS; - amd_use_autofs++; - return 0; -#else /* not HAVE_FS_AUTOFS */ - fprintf(stderr, "conf: no autofs support available\n"); - return 1; -#endif /* not HAVE_FS_AUTOFS */ - } else if (STREQ(val, "nfs")) { - gopt.flags &= ~CFM_MOUNT_TYPE_AUTOFS; - return 0; - } - - fprintf(stderr, "conf: unknown value to mount_type \"%s\"\n", val); - return 1; /* unknown value */ -} - - -static int -gopt_portmap_program(const char *val) -{ - gopt.portmap_program = atol(val); - /* - * allow alternate program numbers to be no more than 10 offset from - * official amd program number (300019). - */ - if (gopt.portmap_program < AMQ_PROGRAM || - gopt.portmap_program > AMQ_PROGRAM + 10) { - gopt.portmap_program = AMQ_PROGRAM; - set_amd_program_number(gopt.portmap_program); - fprintf(stderr, "conf: illegal amd program number \"%s\"\n", val); - return 1; - } - - set_amd_program_number(gopt.portmap_program); - return 0; /* all is OK */ -} - - -static int -gopt_preferred_amq_port(const char *val) -{ - gopt.preferred_amq_port = atoi(val); - - /* - * No need to check value: preferred_amq_port is an unsigned short and 0 - * is a valid number, meaning "any port". - */ - return 0; /* all is OK */ -} - - -static int -gopt_nfs_allow_any_interface(const char *val) -{ - if (STREQ(val, "yes")) { - gopt.flags |= CFM_NFS_ANY_INTERFACE; - return 0; - } else if (STREQ(val, "no")) { - gopt.flags &= ~CFM_NFS_ANY_INTERFACE; - return 0; - } - - fprintf(stderr, "conf: unknown value to nfs_allow_insecure_port \"%s\"\n", val); - return 1; /* unknown value */ -} - - -static int -gopt_nfs_allow_insecure_port(const char *val) -{ - if (STREQ(val, "yes")) { - gopt.flags |= CFM_NFS_INSECURE_PORT; - return 0; - } else if (STREQ(val, "no")) { - gopt.flags &= ~CFM_NFS_INSECURE_PORT; - return 0; - } - - fprintf(stderr, "conf: unknown value to nfs_allow_insecure_port \"%s\"\n", val); - return 1; /* unknown value */ -} - - -static int -gopt_nfs_proto(const char *val) -{ - if (STREQ(val, "udp") || STREQ(val, "tcp")) { - gopt.nfs_proto = strdup((char *)val); - return 0; - } - fprintf(stderr, "conf: illegal nfs_proto \"%s\"\n", val); - return 1; -} - - -static int -gopt_nfs_retransmit_counter(const char *val) -{ - int i; - - for (i=0; i<AMU_TYPE_MAX; ++i) - gopt.amfs_auto_retrans[i] = atoi(val); - return 0; -} - - -static int -gopt_nfs_retransmit_counter_udp(const char *val) -{ - gopt.amfs_auto_retrans[AMU_TYPE_UDP] = atoi(val); - return 0; -} - - -static int -gopt_nfs_retransmit_counter_tcp(const char *val) -{ - gopt.amfs_auto_retrans[AMU_TYPE_TCP] = atoi(val); - return 0; -} - - -static int -gopt_nfs_retransmit_counter_toplvl(const char *val) -{ - gopt.amfs_auto_retrans[AMU_TYPE_TOPLVL] = atoi(val); - return 0; -} - - -static int -gopt_nfs_retry_interval(const char *val) -{ - int i; - - for (i=0; i<AMU_TYPE_MAX; ++i) - gopt.amfs_auto_timeo[i] = atoi(val); - return 0; -} - - -static int -gopt_nfs_retry_interval_udp(const char *val) -{ - gopt.amfs_auto_timeo[AMU_TYPE_UDP] = atoi(val); - return 0; -} - - -static int -gopt_nfs_retry_interval_tcp(const char *val) -{ - gopt.amfs_auto_timeo[AMU_TYPE_TCP] = atoi(val); - return 0; -} - - -static int -gopt_nfs_retry_interval_toplvl(const char *val) -{ - gopt.amfs_auto_timeo[AMU_TYPE_TOPLVL] = atoi(val); - return 0; -} - - -static int -gopt_nfs_vers(const char *val) -{ - int i = atoi(val); - - if (i == 2 || i == 3) { - gopt.nfs_vers = i; - return 0; - } - fprintf(stderr, "conf: illegal nfs_vers \"%s\"\n", val); - return 1; -} - - -static int -gopt_nis_domain(const char *val) -{ -#ifdef HAVE_MAP_NIS - gopt.nis_domain = strdup((char *)val); - return 0; -#else /* not HAVE_MAP_NIS */ - fprintf(stderr, "conf: nis_domain option ignored. No NIS support available.\n"); - return 1; -#endif /* not HAVE_MAP_NIS */ -} - - -static int -gopt_normalize_hostnames(const char *val) -{ - if (STREQ(val, "yes")) { - gopt.flags |= CFM_NORMALIZE_HOSTNAMES; - return 0; - } else if (STREQ(val, "no")) { - gopt.flags &= ~CFM_NORMALIZE_HOSTNAMES; - return 0; - } - - fprintf(stderr, "conf: unknown value to normalize_hostnames \"%s\"\n", val); - return 1; /* unknown value */ -} - - -static int -gopt_normalize_slashes(const char *val) -{ - if (STREQ(val, "yes")) { - gopt.flags |= CFM_NORMALIZE_SLASHES; - return 0; - } else if (STREQ(val, "no")) { - gopt.flags &= ~CFM_NORMALIZE_SLASHES; - return 0; - } - - fprintf(stderr, "conf: unknown value to normalize_slashes \"%s\"\n", val); - return 1; /* unknown value */ -} - - -static int -gopt_os(const char *val) -{ - gopt.op_sys = strdup((char *)val); - return 0; -} - - -static int -gopt_osver(const char *val) -{ - gopt.op_sys_ver = strdup((char *)val); - return 0; -} - - -static int -gopt_plock(const char *val) -{ - if (STREQ(val, "yes")) { - gopt.flags |= CFM_PROCESS_LOCK; - return 0; - } else if (STREQ(val, "no")) { - gopt.flags &= ~CFM_PROCESS_LOCK; - return 0; - } - - fprintf(stderr, "conf: unknown value to plock \"%s\"\n", val); - return 1; /* unknown value */ -} - - -static int -gopt_print_pid(const char *val) -{ - if (STREQ(val, "yes")) { - gopt.flags |= CFM_PRINT_PID; - return 0; - } else if (STREQ(val, "no")) { - gopt.flags &= ~CFM_PRINT_PID; - return 0; - } - - fprintf(stderr, "conf: unknown value to print_pid \"%s\"\n", val); - return 1; /* unknown value */ -} - - -static int -gopt_print_version(const char *val) -{ - if (STREQ(val, "yes")) { - char *vers = get_version_string(); - fputs(vers, stderr); - XFREE(vers); - return 0; - } else if (STREQ(val, "no")) { - return 0; - } - - fprintf(stderr, "conf: unknown value to print_version \"%s\"\n", val); - return 1; /* unknown value */ -} - - -static int -gopt_restart_mounts(const char *val) -{ - if (STREQ(val, "yes")) { - gopt.flags |= CFM_RESTART_EXISTING_MOUNTS; - return 0; - } else if (STREQ(val, "no")) { - gopt.flags &= ~CFM_RESTART_EXISTING_MOUNTS; - return 0; - } - - fprintf(stderr, "conf: unknown value to restart_mounts \"%s\"\n", val); - return 1; /* unknown value */ -} - - -static int -gopt_search_path(const char *val) -{ - gopt.search_path = strdup((char *)val); - return 0; -} - - -static int -gopt_selectors_in_defaults(const char *val) -{ - if (STREQ(val, "yes")) { - gopt.flags |= CFM_SELECTORS_IN_DEFAULTS; - return 0; - } else if (STREQ(val, "no")) { - gopt.flags &= ~CFM_SELECTORS_IN_DEFAULTS; - return 0; - } - - fprintf(stderr, "conf: unknown value to enable_default_selectors \"%s\"\n", val); - return 1; /* unknown value */ -} - - -static int -gopt_show_statfs_entries(const char *val) -{ - if (STREQ(val, "yes")) { - gopt.flags |= CFM_SHOW_STATFS_ENTRIES; - return 0; - } else if (STREQ(val, "no")) { - gopt.flags &= ~CFM_SHOW_STATFS_ENTRIES; - return 0; - } - - fprintf(stderr, "conf: unknown value to show_statfs_entries \"%s\"\n", val); - return 1; /* unknown value */ -} - - -static int -gopt_truncate_log(const char *val) -{ - if (STREQ(val, "yes")) { - gopt.flags |= CFM_TRUNCATE_LOG; - return 0; - } else if (STREQ(val, "no")) { - gopt.flags &= ~CFM_TRUNCATE_LOG; - return 0; - } - - fprintf(stderr, "conf: unknown value to truncate_log \"%s\"\n", val); - return 1; /* unknown value */ -} - - -static int -gopt_unmount_on_exit(const char *val) -{ - if (STREQ(val, "yes")) { - gopt.flags |= CFM_UNMOUNT_ON_EXIT; - return 0; - } else if (STREQ(val, "no")) { - gopt.flags &= ~CFM_UNMOUNT_ON_EXIT; - return 0; - } - - fprintf(stderr, "conf: unknown value to unmount_on_exit \"%s\"\n", val); - return 1; /* unknown value */ -} - - -static int -gopt_use_tcpwrappers(const char *val) -{ -#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) - if (STREQ(val, "yes")) { - gopt.flags |= CFM_USE_TCPWRAPPERS; - return 0; - } else if (STREQ(val, "no")) { - gopt.flags &= ~CFM_USE_TCPWRAPPERS; - return 0; - } -#else /* not defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */ - fprintf(stderr, "conf: no tcpd/libwrap support available\n"); - return 1; -#endif /* not defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */ - - fprintf(stderr, "conf: unknown value to use_tcpwrappers \"%s\"\n", val); - return 1; /* unknown value */ -} - - -static int -gopt_vendor(const char *val) -{ - gopt.op_sys_vendor = strdup((char *)val); - return 0; -} - - -/* - * Collect one entry for a regular map - */ -static int -process_regular_option(const char *section, const char *key, const char *val, cf_map_t *cfm) -{ - /* ensure that val is valid */ - if (!section || section[0] == '\0' || - !key || key[0] == '\0' || - !val || val[0] == '\0' || - !cfm) { - fprintf(stderr, "conf: process_regular_option: null entries\n"); - return 1; - } - - /* check if initializing a new map */ - if (!cfm->cfm_dir) - cfm->cfm_dir = strdup((char *)section); - - /* check for each possible field */ - if (STREQ(key, "browsable_dirs")) - return ropt_browsable_dirs(val, cfm); - - if (STREQ(key, "map_name")) - return ropt_map_name(val, cfm); - - if (STREQ(key, "map_defaults")) - return ropt_map_defaults(val, cfm); - - if (STREQ(key, "map_options")) - return ropt_map_options(val, cfm); - - if (STREQ(key, "map_type")) - return ropt_map_type(val, cfm); - - if (STREQ(key, "mount_type")) - return ropt_mount_type(val, cfm); - - if (STREQ(key, "search_path")) - return ropt_search_path(val, cfm); - - if (STREQ(key, "tag")) - return ropt_tag(val, cfm); - - fprintf(stderr, "conf: unknown regular key \"%s\" for section \"%s\"\n", - key, section); - return 1; /* failed to match any command */ -} - - -static int -ropt_browsable_dirs(const char *val, cf_map_t *cfm) -{ - if (STREQ(val, "full")) { - cfm->cfm_flags |= CFM_BROWSABLE_DIRS_FULL; - return 0; - } else if (STREQ(val, "yes")) { - cfm->cfm_flags |= CFM_BROWSABLE_DIRS; - return 0; - } else if (STREQ(val, "no")) { - cfm->cfm_flags &= ~CFM_BROWSABLE_DIRS; - return 0; - } - - fprintf(stderr, "conf: unknown value to browsable_dirs \"%s\"\n", val); - return 1; /* unknown value */ -} - - -static int -ropt_map_name(const char *val, cf_map_t *cfm) -{ - cfm->cfm_name = strdup((char *)val); - return 0; -} - - -static int -ropt_map_defaults(const char *val, cf_map_t *cfm) -{ - cfm->cfm_defaults = strdup((char *)val); - return 0; -} - - -static int -ropt_map_options(const char *val, cf_map_t *cfm) -{ - cfm->cfm_opts = strdup((char *)val); - return 0; -} - - -static int -ropt_map_type(const char *val, cf_map_t *cfm) -{ - /* check if map type exist */ - if (!mapc_type_exists(val)) { - fprintf(stderr, "conf: no such map type \"%s\"\n", val); - return 1; - } - cfm->cfm_type = strdup((char *)val); - return 0; -} - - -static int -ropt_mount_type(const char *val, cf_map_t *cfm) -{ - if (STREQ(val, "autofs")) { -#ifdef HAVE_FS_AUTOFS - cfm->cfm_flags |= CFM_MOUNT_TYPE_AUTOFS; - amd_use_autofs++; - return 0; -#else /* not HAVE_FS_AUTOFS */ - fprintf(stderr, "conf: no autofs support available\n"); - return 1; -#endif /* not HAVE_FS_AUTOFS */ - } else if (STREQ(val, "nfs")) { - cfm->cfm_flags &= ~CFM_MOUNT_TYPE_AUTOFS; - return 0; - } - - fprintf(stderr, "conf: unknown value to mount_type \"%s\"\n", val); - return 1; /* unknown value */ -} - - -static int -ropt_search_path(const char *val, cf_map_t *cfm) -{ - cfm->cfm_search_path = strdup((char *)val); - return 0; -} - - -static int -ropt_tag(const char *val, cf_map_t *cfm) -{ - cfm->cfm_tag = strdup((char *)val); - return 0; -} - - -/* - * Process one collected map. - */ -static int -process_one_regular_map(const cf_map_t *cfm) -{ - if (!cfm->cfm_name) { - fprintf(stderr, "conf: map_name must be defined for map \"%s\"\n", cfm->cfm_dir); - return 1; - } - /* - * If map has no tag defined, process the map. - * If no conf_tag was set in amd -T, process all untagged entries. - * If a tag is defined, then process it only if it matches the map tag. - */ - if (!cfm->cfm_tag || - (conf_tag && STREQ(cfm->cfm_tag, conf_tag))) { -#ifdef DEBUG_CONF - fprintf(stderr, "processing map %s (flags=0x%x)...\n", - cfm->cfm_dir, cfm->cfm_flags); -#endif /* DEBUG_CONF */ - root_newmap(cfm->cfm_dir, - cfm->cfm_opts ? cfm->cfm_opts : "", - cfm->cfm_name, - cfm); - } else { - fprintf(stderr, "skipping map %s...\n", cfm->cfm_dir); - } - - return 0; -} - - -/* - * Process all regular maps in conf file (if any) - */ -int -process_all_regular_maps(void) -{ - cf_map_t *tmp_map = head_map; - - /* - * If the amd.conf file only has a [global] section (pretty useless - * IMHO), there's nothing to process - */ - if (!tmp_map) - return 0; - - while (tmp_map) { - if (process_one_regular_map(tmp_map) != 0) - return 1; - tmp_map = tmp_map->cfm_next; - } - return 0; -} - - -/* - * Find a cf_map_t for a given map name. - * Return NULL if not found. - */ -cf_map_t * -find_cf_map(const char *name) -{ - - cf_map_t *tmp_map = head_map; - - if (!tmp_map || !name) - return NULL; - - while (tmp_map) { - if (STREQ(tmp_map->cfm_dir,name)) { - return tmp_map; - } - tmp_map = tmp_map->cfm_next; - } - return NULL; -} diff --git a/contrib/amd/amd/conf_parse.y b/contrib/amd/amd/conf_parse.y deleted file mode 100644 index b397b0573242..000000000000 --- a/contrib/amd/amd/conf_parse.y +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 1997-2006 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 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. - * - * - * File: am-utils/amd/conf_parse.y - * - */ - -%{ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -extern char *yytext; -extern int ayylineno; -extern int yylex(void); - -static int yyerror(const char *s); -static int retval; -static char *header_section = NULL; /* start with no header section */ - -#define YYDEBUG 1 - -#define PARSE_DEBUG 0 - -#if PARSE_DEBUG -# define dprintf(f,s) fprintf(stderr, (f), ayylineno, (s)) -# define amu_return(v) -#else /* not PARSE_DEBUG */ -# define dprintf(f,s) -# define amu_return(v) return((v)) -#endif /* not PARSE_DEBUG */ - -%} - -%union { -char *strtype; -} - -%token LEFT_BRACKET RIGHT_BRACKET EQUAL -%token NEWLINE -%token <strtype> NONWS_STRING -%token <strtype> NONWSEQ_STRING -%token <strtype> QUOTED_NONWSEQ_STRING - -%start file -%% - -/****************************************************************************/ -file : { yydebug = PARSE_DEBUG; } newlines map_sections - | { yydebug = PARSE_DEBUG; } map_sections - ; - -newlines : NEWLINE - | NEWLINE newlines - ; - -map_sections : map_section - | map_section map_sections - ; - -map_section : sec_header kv_pairs - ; - -sec_header : LEFT_BRACKET NONWS_STRING RIGHT_BRACKET NEWLINE - { - if (yydebug) - fprintf(stderr, "sec_header1 = \"%s\"\n", $2); - header_section = $2; - } - ; - -kv_pairs : kv_pair - | kv_pair kv_pairs - ; - -kv_pair : NONWS_STRING EQUAL NONWS_STRING NEWLINE - { - if (yydebug) - fprintf(stderr,"parse1: key=\"%s\", val=\"%s\"\n", $1, $3); - retval = set_conf_kv(header_section, $1, $3); - if (retval != 0) { - yyerror("syntax error"); - YYABORT; - } - } - | NONWS_STRING EQUAL NONWSEQ_STRING NEWLINE - { - if (yydebug) - fprintf(stderr,"parse2: key=\"%s\", val=\"%s\"\n", $1, $3); - retval = set_conf_kv(header_section, $1, $3); - if (retval != 0) { - yyerror("syntax error"); - YYABORT; - } - } - | NONWS_STRING EQUAL QUOTED_NONWSEQ_STRING NEWLINE - { - if (yydebug) - fprintf(stderr,"parse3: key=\"%s\", val=\"%s\"\n", $1, $3); - retval = set_conf_kv(header_section, $1, $3); - if (retval != 0) { - yyerror("syntax error"); - YYABORT; - } - } - | NEWLINE - ; - -/****************************************************************************/ -%% - -static int -yyerror(const char *s) -{ - fprintf(stderr, "AMDCONF: %s on line %d (section %s)\n", - s, ayylineno, - (header_section ? header_section : "null")); - exit(1); - return 1; /* to full compilers that insist on a return statement */ -} diff --git a/contrib/amd/amd/conf_tok.l b/contrib/amd/amd/conf_tok.l deleted file mode 100644 index b572e4d7d5a3..000000000000 --- a/contrib/amd/amd/conf_tok.l +++ /dev/null @@ -1,192 +0,0 @@ -%{ -/* - * Copyright (c) 1997-2006 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 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. - * - * - * File: am-utils/amd/conf_tok.l - * - */ - -/* - * Lexical analyzer for AMD configuration parser. - */ - -#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 <amd.h> -#include <conf_parse.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 using 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 */ - -int ayylineno = 0; - -int yylex(void); -/* - * 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 */ - -#define TOK_DEBUG 0 - -#if TOK_DEBUG -# define dprintf(f,s) fprintf(stderr, (f), ayylineno, (s)) -# define amu_return(v) -#else /* not TOK_DEBUG */ -# define dprintf(f,s) -# define amu_return(v) return((v)) -#endif /* not TOK_DEBUG */ - -/* no need to use yywrap() */ -#define YY_SKIP_YYWRAP - -%} - -/* This option causes Solaris lex to fail. Use flex. See BUGS file */ -/* no need to use yyunput() */ -%option nounput - -/* allocate more output slots so lex scanners don't run out of mem */ -%o 1024 - -DIGIT [0-9] -ALPHA [A-Za-z] -ALPHANUM [A-Za-z0-9] -SYMBOL [A-Za-z0-9_-] -PATH [A-Za-z0-9_-/] -NONWSCHAR [^ \t\n\[\]=] -NONWSEQCHAR [^ \t\n\[\]] -NONNL [^\n] -NONQUOTE [^\"] - -%% - -\n { - ayylineno++; - amu_return(NEWLINE); - } - -\[ { - dprintf("%8d: Left bracket \"%s\"\n", yytext); - yylval.strtype = strdup((char *)yytext); - amu_return(LEFT_BRACKET); - } - -\] { - dprintf("%8d: Right bracket \"%s\"\n", yytext); - yylval.strtype = strdup((char *)yytext); - amu_return(RIGHT_BRACKET); - } - -= { - dprintf("%8d: Equal \"%s\"\n", yytext); - yylval.strtype = strdup((char *)yytext); - amu_return(EQUAL); - } - -[ \t]* { - dprintf("%8d: Whitespace \"%s\"\n", yytext); - } -"#"[^\n]*\n { - /* a comment line includes the terminating \n */ - ayylineno++; - yytext[strlen((char *)yytext)-1] = '\0'; - dprintf("%8d: Comment \"%s\"\n", yytext); - } - -{NONWSCHAR}{NONWSCHAR}* { - dprintf("%8d: Non-WS string \"%s\"\n", yytext); - yylval.strtype = strdup((char *)yytext); - amu_return(NONWS_STRING); - } - -\"{NONQUOTE}{NONQUOTE}*\" { - dprintf("%8d: QUOTED-Non-WS-EQ string \"%s\"\n", yytext); - /* must strip quotes */ - yytext[strlen((char *)yytext)-1] = '\0'; - yylval.strtype = strdup((char *)&yytext[1]); - amu_return(QUOTED_NONWSEQ_STRING); - } - -{NONWSEQCHAR}{NONWSEQCHAR}* { - dprintf("%8d: Non-WS-EQ string \"%s\"\n", yytext); - yylval.strtype = strdup((char *)yytext); - amu_return(NONWSEQ_STRING); - } - -%% - -/* - * 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/amd/get_args.c b/contrib/amd/amd/get_args.c deleted file mode 100644 index 12a7d07efd59..000000000000 --- a/contrib/amd/amd/get_args.c +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/get_args.c - * - */ - -/* - * Argument decode - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* include auto-generated version file */ -#include <build_version.h> - -char *amu_conf_file = "/etc/amd.conf"; /* default amd configuration file */ -char *conf_tag = NULL; /* default conf file tags to use */ -int usage = 0; -int use_conf_file = 0; /* default don't use amd.conf file */ -char *mnttab_file_name = NULL; /* symbol must be available always */ - - -/* - * Return the version string (dynamic buffer) - */ -char * -get_version_string(void) -{ - char *vers = NULL; - char tmpbuf[1024]; - char *wire_buf; - int wire_buf_len = 0; - size_t len; /* max allocated length (to avoid buf overflow) */ - - /* - * First get dynamic string listing all known networks. - * This could be a long list, if host has lots of interfaces. - */ - wire_buf = print_wires(); - if (wire_buf) - wire_buf_len = strlen(wire_buf); - - len = 2048 + wire_buf_len; - vers = xmalloc(len); - xsnprintf(vers, len, "%s\n%s\n%s\n%s\n", - "Copyright (c) 1997-2006 Erez Zadok", - "Copyright (c) 1990 Jan-Simon Pendry", - "Copyright (c) 1990 Imperial College of Science, Technology & Medicine", - "Copyright (c) 1990 The Regents of the University of California."); - xsnprintf(tmpbuf, sizeof(tmpbuf), "%s version %s (build %d).\n", - PACKAGE_NAME, PACKAGE_VERSION, AMU_BUILD_VERSION); - strlcat(vers, tmpbuf, len); - xsnprintf(tmpbuf, sizeof(tmpbuf), "Report bugs to %s.\n", PACKAGE_BUGREPORT); - strlcat(vers, tmpbuf, len); - xsnprintf(tmpbuf, sizeof(tmpbuf), "Configured by %s@%s on date %s.\n", - USER_NAME, HOST_NAME, CONFIG_DATE); - strlcat(vers, tmpbuf, len); - xsnprintf(tmpbuf, sizeof(tmpbuf), "Built by %s@%s on date %s.\n", - BUILD_USER, BUILD_HOST, BUILD_DATE); - strlcat(vers, tmpbuf, len); - xsnprintf(tmpbuf, sizeof(tmpbuf), "cpu=%s (%s-endian), arch=%s, karch=%s.\n", - cpu, endian, gopt.arch, gopt.karch); - strlcat(vers, tmpbuf, len); - xsnprintf(tmpbuf, sizeof(tmpbuf), "full_os=%s, os=%s, osver=%s, vendor=%s, distro=%s.\n", - gopt.op_sys_full, gopt.op_sys, gopt.op_sys_ver, gopt.op_sys_vendor, DISTRO_NAME); - strlcat(vers, tmpbuf, len); - xsnprintf(tmpbuf, sizeof(tmpbuf), "domain=%s, host=%s, hostd=%s.\n", - hostdomain, am_get_hostname(), hostd); - strlcat(vers, tmpbuf, len); - - strlcat(vers, "Map support for: ", len); - mapc_showtypes(tmpbuf, sizeof(tmpbuf)); - strlcat(vers, tmpbuf, len); - strlcat(vers, ".\nAMFS: ", len); - ops_showamfstypes(tmpbuf, sizeof(tmpbuf)); - strlcat(vers, tmpbuf, len); - strlcat(vers, ", inherit.\nFS: ", len); /* hack: "show" that we support type:=inherit */ - ops_showfstypes(tmpbuf, sizeof(tmpbuf)); - strlcat(vers, tmpbuf, len); - - /* append list of networks if available */ - if (wire_buf) { - strlcat(vers, wire_buf, len); - XFREE(wire_buf); - } - - return vers; -} - - -static void -show_usage(void) -{ - fprintf(stderr, - "Usage: %s [-nprvHS] [-a mount_point] [-c cache_time] [-d domain]\n\ -\t[-k kernel_arch] [-l logfile%s\n\ -\t[-t timeout.retrans] [-w wait_timeout] [-A arch] [-C cluster_name]\n\ -\t[-o op_sys_ver] [-O op_sys_name]\n\ -\t[-F conf_file] [-T conf_tag]", am_get_progname(), -#ifdef HAVE_SYSLOG -# ifdef LOG_DAEMON - "|\"syslog[:facility]\"]" -# else /* not LOG_DAEMON */ - "|\"syslog\"]" -# endif /* not LOG_DAEMON */ -#else /* not HAVE_SYSLOG */ - "]" -#endif /* not HAVE_SYSLOG */ - ); - -#ifdef HAVE_MAP_NIS - fputs(" [-y nis-domain]\n", stderr); -#else /* not HAVE_MAP_NIS */ - fputc('\n', stderr); -#endif /* HAVE_MAP_NIS */ - - show_opts('x', xlog_opt); -#ifdef DEBUG - show_opts('D', dbg_opt); -#endif /* DEBUG */ - fprintf(stderr, "\t[directory mapname [-map_options]] ...\n"); -} - - -void -get_args(int argc, char *argv[]) -{ - int opt_ch, i; - FILE *fp = stdin; - char getopt_arguments[] = "+nprvSa:c:d:k:l:o:t:w:x:y:C:D:F:T:O:HA:"; - char *getopt_args; - int print_version = 0; /* 1 means we should print version info */ - -#ifdef HAVE_GNU_GETOPT - getopt_args = getopt_arguments; -#else /* ! HAVE_GNU_GETOPT */ - getopt_args = &getopt_arguments[1]; -#endif /* HAVE_GNU_GETOPT */ - - /* if no arguments were passed, try to use /etc/amd.conf file */ - if (argc <= 1) - use_conf_file = 1; - - while ((opt_ch = getopt(argc, argv, getopt_args)) != -1) - switch (opt_ch) { - - case 'a': - if (*optarg != '/') { - fprintf(stderr, "%s: -a option must begin with a '/'\n", - am_get_progname()); - exit(1); - } - gopt.auto_dir = optarg; - break; - - case 'c': - gopt.am_timeo = atoi(optarg); - if (gopt.am_timeo <= 0) - gopt.am_timeo = AM_TTL; - break; - - case 'd': - gopt.sub_domain = optarg; - break; - - case 'k': - gopt.karch = optarg; - break; - - case 'l': - gopt.logfile = optarg; - break; - - case 'n': - gopt.flags |= CFM_NORMALIZE_HOSTNAMES; - break; - - case 'o': - gopt.op_sys_ver = optarg; - break; - - case 'p': - gopt.flags |= CFM_PRINT_PID; - break; - - case 'r': - gopt.flags |= CFM_RESTART_EXISTING_MOUNTS; - break; - - case 't': - /* timeo.retrans (also affects toplvl mounts) */ - { - char *dot = strchr(optarg, '.'); - int i; - if (dot) - *dot = '\0'; - if (*optarg) { - for (i=0; i<AMU_TYPE_MAX; ++i) - gopt.amfs_auto_timeo[i] = atoi(optarg); - } - if (dot) { - for (i=0; i<AMU_TYPE_MAX; ++i) - gopt.amfs_auto_retrans[i] = atoi(dot + 1); - *dot = '.'; - } - } - break; - - case 'v': - /* - * defer to print version info after every variable had been - * initialized. - */ - print_version++; - break; - - case 'w': - gopt.am_timeo_w = atoi(optarg); - if (gopt.am_timeo_w <= 0) - gopt.am_timeo_w = AM_TTL_W; - break; - - case 'x': - usage += switch_option(optarg); - break; - - case 'y': -#ifdef HAVE_MAP_NIS - gopt.nis_domain = optarg; -#else /* not HAVE_MAP_NIS */ - plog(XLOG_USER, "-y: option ignored. No NIS support available."); -#endif /* not HAVE_MAP_NIS */ - break; - - case 'A': - gopt.arch = optarg; - break; - - case 'C': - gopt.cluster = optarg; - break; - - case 'D': -#ifdef DEBUG - usage += debug_option(optarg); -#else /* not DEBUG */ - fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n", - am_get_progname()); -#endif /* not DEBUG */ - break; - - case 'F': - amu_conf_file = optarg; - use_conf_file = 1; - break; - - case 'H': - show_usage(); - exit(1); - break; - - case 'O': - gopt.op_sys = optarg; - break; - - case 'S': - gopt.flags &= ~CFM_PROCESS_LOCK; /* turn process locking off */ - break; - - case 'T': - conf_tag = optarg; - break; - - default: - usage = 1; - break; - } - - /* - * amd.conf file: if not command-line arguments were used, or if -F was - * specified, then use that amd.conf file. If the file cannot be opened, - * abort amd. If it can be found, open it, parse it, and then close it. - */ - if (use_conf_file && amu_conf_file) { - fp = fopen(amu_conf_file, "r"); - if (!fp) { - char buf[128]; - xsnprintf(buf, sizeof(buf), "Amd configuration file (%s)", - amu_conf_file); - perror(buf); - exit(1); - } - yyin = fp; - yyparse(); - fclose(fp); - if (process_all_regular_maps() != 0) - exit(1); - } - - /* make sure there are some default options defined */ - if (xlog_level_init == ~0) { - switch_option(""); - } -#ifdef DEBUG - usage += switch_option("debug"); -#endif /* DEBUG */ - - /* log information regarding amd.conf file */ - if (use_conf_file && amu_conf_file) - plog(XLOG_INFO, "using configuration file %s", amu_conf_file); - -#ifdef HAVE_MAP_LDAP - /* ensure that if ldap_base is specified, that also ldap_hostports is */ - if (gopt.ldap_hostports && !gopt.ldap_base) { - fprintf(stderr, "must specify both ldap_hostports and ldap_base\n"); - exit(1); - } -#endif /* HAVE_MAP_LDAP */ - - if (usage) { - show_usage(); - exit(1); - } - - while (optind <= argc - 2) { - char *dir = argv[optind++]; - char *map = argv[optind++]; - char *opts = ""; - if (argv[optind] && *argv[optind] == '-') - opts = &argv[optind++][1]; - - root_newmap(dir, opts, map, NULL); - } - - if (optind == argc) { - /* - * Append domain name to hostname. - * sub_domain overrides hostdomain - * if given. - */ - if (gopt.sub_domain) - hostdomain = gopt.sub_domain; - if (*hostdomain == '.') - hostdomain++; - xstrlcat(hostd, ".", sizeof(hostd)); - xstrlcat(hostd, hostdomain, sizeof(hostd)); - -#ifdef MOUNT_TABLE_ON_FILE - if (amuDebug(D_MTAB)) - if (gopt.debug_mtab_file) - mnttab_file_name = gopt.debug_mtab_file; /* user supplied debug mtab path */ - else - mnttab_file_name = DEBUG_MNTTAB_FILE; /* default debug mtab path */ - else - mnttab_file_name = MNTTAB_FILE_NAME; -#else /* not MOUNT_TABLE_ON_FILE */ - if (amuDebug(D_MTAB)) - dlog("-D mtab option ignored"); -# ifdef MNTTAB_FILE_NAME - mnttab_file_name = MNTTAB_FILE_NAME; -# endif /* MNTTAB_FILE_NAME */ -#endif /* not MOUNT_TABLE_ON_FILE */ - - /* - * If the kernel architecture was not specified - * then use the machine architecture. - */ - if (gopt.karch == NULL) - gopt.karch = gopt.arch; - - if (gopt.cluster == NULL) - gopt.cluster = hostdomain; - - /* sanity checking, normalize values just in case (toplvl too) */ - for (i=0; i<AMU_TYPE_MAX; ++i) { - if (gopt.amfs_auto_timeo[i] == 0) - gopt.amfs_auto_timeo[i] = AMFS_AUTO_TIMEO; - if (gopt.amfs_auto_retrans[i] == 0) - gopt.amfs_auto_retrans[i] = AMFS_AUTO_RETRANS(i); - if (gopt.amfs_auto_retrans[i] == 0) - gopt.amfs_auto_retrans[i] = 3; /* under very unusual circumstances, could be zero */ - } - } - - /* finally print version string and exit, if asked for */ - if (print_version) { - fputs(get_version_string(), stderr); - exit(0); - } - - if (switch_to_logfile(gopt.logfile, orig_umask, - (gopt.flags & CFM_TRUNCATE_LOG)) != 0) - plog(XLOG_USER, "Cannot switch logfile"); - - return; -} diff --git a/contrib/amd/amd/info_exec.c b/contrib/amd/amd/info_exec.c deleted file mode 100644 index 8ccab9aee579..000000000000 --- a/contrib/amd/amd/info_exec.c +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/info_exec.c - * - */ - -/* - * Get info from executable map - * - * Original from Erik Kline, 2004. - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -#define MAX_LINE_LEN 1500 - -/* forward declarations */ -int exec_init(mnt_map *m, char *map, time_t *tp); -int exec_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp); - - -/* - * a timed fgets() - */ -static char * -fgets_timed(char *s, int size, int rdfd, int secs) -{ - fd_set fds; - struct timeval timeo; - time_t start, now; - int rval=0, i=0; - - if (!s || size < 0 || rdfd < 0) - return 0; - - s[0] = 0; - if (size == 0) - return s; - - start = clocktime(NULL); - while (s[i] != '\n' && i < size-1) { - s[i+1] = 0; /* places the requisite trailing '\0' */ - - /* ready for reading */ - rval = read(rdfd, (void *)(s+i), 1); - if (rval == 1) { - if (s[i] == 0) { - rval = 0; - break; - } - i++; - continue; - } else if (rval == 0) { - break; - } else if (rval < 0 && errno != EAGAIN && errno != EINTR) { - plog(XLOG_WARNING, "fgets_timed read error: %m"); - break; - } - - timeo.tv_usec = 0; - now = clocktime(NULL) - start; - if (secs <= 0) - timeo.tv_sec = 0; - else if (now < secs) - timeo.tv_sec = secs - now; - else { - /* timed out (now>=secs) */ - plog(XLOG_WARNING, "executable map read timed out (> %d secs)", secs); - rval = -1; - break; - } - - FD_ZERO(&fds); - FD_SET(rdfd, &fds); - - rval = select(rdfd+1, &fds, 0, 0, &timeo); - if (rval < 0) { - /* error selecting */ - plog(XLOG_WARNING, "fgets_timed select error: %m"); - if (errno == EINTR) - continue; - rval = -1; - break; - } else if (rval == 0) { - /* timed out */ - plog(XLOG_WARNING, "executable map read timed out (> %d secs)", secs); - rval = -1; - break; - } - } - - if (rval > 0) - return s; - - close(rdfd); - return (rval == 0 ? s : 0); -} - - -static int -read_line(char *buf, int size, int fd) -{ - int done = 0; - - while (fgets_timed(buf, size, fd, gopt.exec_map_timeout)) { - int len = strlen(buf); - done += len; - if (len > 1 && buf[len - 2] == '\\' && - buf[len - 1] == '\n') { - buf += len - 2; - size -= len - 2; - *buf = '\n'; - buf[1] = '\0'; - } else { - return done; - } - } - - return done; -} - - -/* - * Try to locate a value in a query answer - */ -static int -exec_parse_qanswer(int fd, char *map, char *key, char **pval, time_t *tp) -{ - char qanswer[MAX_LINE_LEN], *dc = 0; - int chuck = 0; - int line_no = 0; - - while (read_line(qanswer, sizeof(qanswer), fd)) { - char *cp; - char *hash; - int len = strlen(qanswer); - line_no++; - - /* - * Make sure we got the whole line - */ - if (qanswer[len - 1] != '\n') { - plog(XLOG_WARNING, "line %d in \"%s\" is too long", line_no, map); - chuck = 1; - } else { - qanswer[len - 1] = '\0'; - } - - /* - * Strip comments - */ - hash = strchr(qanswer, '#'); - if (hash) - *hash = '\0'; - - /* - * Find beginning of value (query answer) - */ - for (cp = qanswer; *cp && !isascii((int)*cp) && !isspace((int)*cp); cp++) - ;; - - /* Ignore blank lines */ - if (!*cp) - goto again; - - /* - * Return a copy of the data - */ - dc = strdup(cp); - *pval = dc; - dlog("%s returns %s", key, dc); - - close(fd); - return 0; - - again: - /* - * If the last read didn't get a whole line then - * throw away the remainder before continuing... - */ - if (chuck) { - while (fgets_timed(qanswer, sizeof(qanswer), fd, gopt.exec_map_timeout) && - !strchr(qanswer, '\n')) ; - chuck = 0; - } - } - - return ENOENT; -} - - -static int -set_nonblock(int fd) -{ - int val; - - if (fd < 0) - return 0; - - if ((val = fcntl(fd, F_GETFL, 0)) < 0) { - plog(XLOG_WARNING, "set_nonblock fcntl F_GETFL error: %m"); - return 0; - } - - val |= O_NONBLOCK; - if (fcntl(fd, F_SETFL, val) < 0) { - plog(XLOG_WARNING, "set_nonblock fcntl F_SETFL error: %m"); - return 0; - } - - return 1; -} - - -static int -exec_map_open(char *emap, char *key) -{ - pid_t p1, p2; - int pdes[2], nullfd, i; - char *argv[3]; - - if (!emap) - return 0; - - argv[0] = emap; - argv[1] = key; - argv[2] = NULL; - - if ((nullfd = open("/dev/null", O_WRONLY|O_NOCTTY)) < 0) - return -1; - - if (pipe(pdes) < 0) { - close(nullfd); - return -1; - } - - switch ((p1 = vfork())) { - case -1: - /* parent: fork error */ - close(nullfd); - close(pdes[0]); - close(pdes[1]); - return -1; - case 0: - /* child #1 */ - p2 = vfork(); - switch (p2) { - case -1: - /* child #1: fork error */ - exit(errno); - case 0: - /* child #2: init will reap our status */ - if (pdes[1] != STDOUT_FILENO) { - dup2(pdes[1], STDOUT_FILENO); - close(pdes[1]); - } - - if (nullfd != STDERR_FILENO) { - dup2(nullfd, STDERR_FILENO); - close(nullfd); - } - - for (i=0; i<FD_SETSIZE; i++) - if (i != STDOUT_FILENO && i != STDERR_FILENO) - close(i); - - /* make the write descriptor non-blocking */ - if (!set_nonblock(STDOUT_FILENO)) { - close(STDOUT_FILENO); - exit(-1); - } - - execve(emap, argv, NULL); - exit(errno); /* in case execve failed */ - } - - /* child #1 */ - exit(0); - } - - /* parent */ - close(nullfd); - close(pdes[1]); - - /* anti-zombie insurance */ - while (waitpid(p1,0,0) < 0) - if (errno != EINTR) - exit(errno); - - /* make the read descriptor non-blocking */ - if (!set_nonblock(pdes[0])) { - close(pdes[0]); - return -1; - } - - return pdes[0]; -} - - -/* - * Check for various permissions on executable map without trying to - * fork a new executable-map process. - * - * return: >0 (errno) if failed - * 0 if ok - */ -static int -exec_check_perm(char *map) -{ - struct stat sb; - - /* sanity and permission checks */ - if (!map) { - dlog("exec_check_permission got a NULL map"); - return EINVAL; - } - if (stat(map, &sb)) { - plog(XLOG_ERROR, "map \"%s\" stat failure: %m", map); - return errno; - } - if (!S_ISREG(sb.st_mode)) { - plog(XLOG_ERROR, "map \"%s\" should be regular file", map); - return EINVAL; - } - if (sb.st_uid != 0) { - plog(XLOG_ERROR, "map \"%s\" owned by uid %u (must be 0)", map, (u_int) sb.st_uid); - return EACCES; - } - if (!(sb.st_mode & S_IXUSR)) { - plog(XLOG_ERROR, "map \"%s\" should be executable", map); - return EACCES; - } - if (sb.st_mode & (S_ISUID|S_ISGID)) { - plog(XLOG_ERROR, "map \"%s\" should not be setuid/setgid", map); - return EACCES; - } - if (sb.st_mode & S_IWOTH) { - plog(XLOG_ERROR, "map \"%s\" should not be world writeable", map); - return EACCES; - } - - return 0; /* all is well */ -} - - -int -exec_init(mnt_map *m, char *map, time_t *tp) -{ - /* - * Basically just test that the executable map can be found - * and has proper permissions. - */ - return exec_check_perm(map); -} - - -int -exec_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) -{ - int mapfd, ret; - - if ((ret = exec_check_perm(map)) != 0) { - return ret; - } - - if (!key) - return 0; - - if (logfp) - fflush(logfp); - dlog("exec_search \"%s\", key: \"%s\"", map, key); - mapfd = exec_map_open(map, key); - - if (mapfd >= 0) { - if (tp) - *tp = clocktime(NULL); - - return exec_parse_qanswer(mapfd, map, key, pval, tp); - } - - return errno; -} diff --git a/contrib/amd/amd/info_file.c b/contrib/amd/amd/info_file.c deleted file mode 100644 index 3777a2aebe94..000000000000 --- a/contrib/amd/amd/info_file.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/info_file.c - * - */ - -/* - * Get info from file - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -#define MAX_LINE_LEN 1500 - -/* forward declarations */ -int file_init_or_mtime(mnt_map *m, char *map, time_t *tp); -int file_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *)); -int file_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp); - - -static int -read_line(char *buf, int size, FILE *fp) -{ - int done = 0; - - do { - while (fgets(buf, size, fp)) { - int len = strlen(buf); - done += len; - if (len > 1 && buf[len - 2] == '\\' && - buf[len - 1] == '\n') { - int ch; - buf += len - 2; - size -= len - 2; - *buf = '\n'; - buf[1] = '\0'; - /* - * Skip leading white space on next line - */ - while ((ch = getc(fp)) != EOF && - isascii(ch) && isspace(ch)) ; - (void) ungetc(ch, fp); - } else { - return done; - } - } - } while (size > 0 && !feof(fp) && !ferror(fp)); - - return done; -} - - -/* - * Try to locate a key in a file - */ -static int -file_search_or_reload(FILE *fp, - char *map, - char *key, - char **val, - mnt_map *m, - void (*fn) (mnt_map *m, char *, char *)) -{ - char key_val[MAX_LINE_LEN]; - int chuck = 0; - int line_no = 0; - - while (read_line(key_val, sizeof(key_val), fp)) { - char *kp; - char *cp; - char *hash; - int len = strlen(key_val); - line_no++; - - /* - * Make sure we got the whole line - */ - if (key_val[len - 1] != '\n') { - plog(XLOG_WARNING, "line %d in \"%s\" is too long", line_no, map); - chuck = 1; - } else { - key_val[len - 1] = '\0'; - } - - /* - * Strip comments - */ - hash = strchr(key_val, '#'); - if (hash) - *hash = '\0'; - - /* - * Find start of key - */ - for (kp = key_val; *kp && isascii(*kp) && isspace((int)*kp); kp++) ; - - /* - * Ignore blank lines - */ - if (!*kp) - goto again; - - /* - * Find end of key - */ - for (cp = kp; *cp && (!isascii(*cp) || !isspace((int)*cp)); cp++) ; - - /* - * Check whether key matches - */ - if (*cp) - *cp++ = '\0'; - - if (fn || (*key == *kp && STREQ(key, kp))) { - while (*cp && isascii(*cp) && isspace((int)*cp)) - cp++; - if (*cp) { - /* - * Return a copy of the data - */ - char *dc = strdup(cp); - if (fn) { - (*fn) (m, strdup(kp), dc); - } else { - *val = dc; - dlog("%s returns %s", key, dc); - } - if (!fn) - return 0; - } else { - plog(XLOG_USER, "%s: line %d has no value field", map, line_no); - } - } - - again: - /* - * If the last read didn't get a whole line then - * throw away the remainder before continuing... - */ - if (chuck) { - while (fgets(key_val, sizeof(key_val), fp) && - !strchr(key_val, '\n')) ; - chuck = 0; - } - } - - return fn ? 0 : ENOENT; -} - - -static FILE * -file_open(char *map, time_t *tp) -{ - FILE *mapf = fopen(map, "r"); - - if (mapf && tp) { - struct stat stb; - if (fstat(fileno(mapf), &stb) < 0) - *tp = clocktime(NULL); - else - *tp = stb.st_mtime; - } - return mapf; -} - - -int -file_init_or_mtime(mnt_map *m, char *map, time_t *tp) -{ - FILE *mapf = file_open(map, tp); - - if (mapf) { - fclose(mapf); - return 0; - } - return errno; -} - - -int -file_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *)) -{ - FILE *mapf = file_open(map, (time_t *) 0); - - if (mapf) { - int error = file_search_or_reload(mapf, map, 0, 0, m, fn); - (void) fclose(mapf); - return error; - } - return errno; -} - - -int -file_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) -{ - time_t t; - FILE *mapf = file_open(map, &t); - - if (mapf) { - int error; - if (*tp < t) { - *tp = t; - error = -1; - } else { - error = file_search_or_reload(mapf, map, key, pval, 0, 0); - } - (void) fclose(mapf); - return error; - } - return errno; -} diff --git a/contrib/amd/amd/info_hesiod.c b/contrib/amd/amd/info_hesiod.c deleted file mode 100644 index e345c9961508..000000000000 --- a/contrib/amd/amd/info_hesiod.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 1997-2006 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 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. - * - * - * File: am-utils/amd/info_hesiod.c - * - */ - -/* - * Get info from Hesiod - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -#define HES_PREFIX "hesiod." -#define HES_PREFLEN 7 - -#ifdef HAVE_HESIOD_INIT -/* bsdi3 does not define this extern in any header file */ -extern char **hesiod_resolve(void *context, const char *name, const char *type); -extern int hesiod_init(void **context); -static voidp hesiod_context; -#endif /* HAVE_HESIOD_INIT */ - -/* forward declarations */ -int amu_hesiod_init(mnt_map *m, char *map, time_t *tp); -int hesiod_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp); -int hesiod_isup(mnt_map *m, char *map); - -/* - * No easy way to probe the server - check the map name begins with "hesiod." - * Note: this name includes 'amu_' so as to not conflict with libhesiod's - * hesiod_init() function. - */ -int -amu_hesiod_init(mnt_map *m, char *map, time_t *tp) -{ - dlog("amu_hesiod_init(%s)", map); - *tp = 0; - -#ifdef HAVE_HESIOD_INIT - if (!hesiod_context && hesiod_init(&hesiod_context) != 0) - return ENOENT; -#endif /* HAVE_HESIOD_INIT */ - - return NSTREQ(map, HES_PREFIX, HES_PREFLEN) ? 0 : ENOENT; -} - - -/* - * Do a Hesiod nameserver call. - * Modify time is ignored by Hesiod - XXX - */ -int -hesiod_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) -{ - char hes_key[MAXPATHLEN]; - char **rvec; -#ifndef HAVE_HESIOD_INIT - int error; -#endif /* not HAVE_HESIOD_INIT */ - - dlog("hesiod_search(m=%lx, map=%s, key=%s, pval=%lx tp=%lx)", - (unsigned long) m, map, key, (unsigned long) pval, (unsigned long) tp); - - if (key[0] == '.') - return ENOENT; - - xsnprintf(hes_key, sizeof(hes_key), "%s.%s", key, map + HES_PREFLEN); - - /* - * Call the resolver - */ - dlog("Hesiod base is: %s\n", gopt.hesiod_base); - dlog("hesiod_search: hes_resolve(%s, %s)", hes_key, gopt.hesiod_base); - if (amuDebug(D_INFO)) - _res.options |= RES_DEBUG; - -#ifdef HAVE_HESIOD_INIT - /* new style hesiod */ - rvec = hesiod_resolve(hesiod_context, hes_key, gopt.hesiod_base); -#else /* not HAVE_HESIOD_INIT */ - rvec = hes_resolve(hes_key, gopt.hesiod_base); -#endif /* not HAVE_HESIOD_INIT */ - - /* - * If a reply was forthcoming then return - * it (and free subsequent replies) - */ - if (rvec && *rvec) { - *pval = *rvec; - while (*++rvec) - XFREE(*rvec); - return 0; - } - -#ifdef HAVE_HESIOD_INIT - /* new style hesiod */ - return errno; -#else /* not HAVE_HESIOD_INIT */ - /* - * Otherwise reflect the hesiod error into a Un*x error - */ - dlog("hesiod_search: Error: %d", hes_error()); - switch (hes_error()) { - case HES_ER_NOTFOUND: - error = ENOENT; - break; - case HES_ER_CONFIG: - error = EIO; - break; - case HES_ER_NET: - error = ETIMEDOUT; - break; - default: - error = EINVAL; - break; - } - dlog("hesiod_search: Returning: %d", error); - return error; -#endif /* not HAVE_HESIOD_INIT */ -} - - -/* - * Check if Hesiod is up, so we can determine if to clear the map or not. - * Test it by querying for /defaults. - * Returns: 0 if Hesiod is down, 1 if it is up. - */ -int -hesiod_isup(mnt_map *m, char *map) -{ - int error; - char *val; - time_t mtime; - static int last_status = 1; /* assume up by default */ - - error = hesiod_search(m, map, "/defaults", &val, &mtime); - dlog("hesiod_isup(%s): %s", map, strerror(error)); - if (error != 0 && error != ENOENT) { - plog(XLOG_ERROR, - "hesiod_isup: error getting `/defaults' entry in map %s: %m", map); - last_status = 0; - return 0; /* Hesiod is down */ - } - if (last_status == 0) { /* if was down before */ - plog(XLOG_INFO, "hesiod_isup: Hesiod came back up for map %s", map); - last_status = 1; - } - return 1; /* Hesiod is up */ -} diff --git a/contrib/amd/amd/info_ldap.c b/contrib/amd/amd/info_ldap.c deleted file mode 100644 index 36ce1c8693d3..000000000000 --- a/contrib/amd/amd/info_ldap.c +++ /dev/null @@ -1,573 +0,0 @@ -/* - * Copyright (c) 1997-2006 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 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. - * - * - * File: am-utils/amd/info_ldap.c - * - */ - - -/* - * Get info from LDAP (Lightweight Directory Access Protocol) - * LDAP Home Page: http://www.umich.edu/~rsug/ldap/ - */ - -/* - * WARNING: as of Linux Fedora Core 5 (which comes with openldap-2.3.9), the - * ldap.h headers deprecate several functions used in this file, such as - * ldap_unbind. You get compile errors about missing extern definitions. - * Those externs are still in <ldap.h>, but surrounded by an ifdef - * LDAP_DEPRECATED. I am turning on that ifdef here, under the assumption - * that the functions may be deprecated, but they still work for this - * (older?) version of the LDAP API. It gets am-utils to compile, but it is - * not clear if it will work perfectly. - */ -#ifndef LDAP_DEPRECATED -# define LDAP_DEPRECATED 1 -#endif /* not LDAP_DEPRECATED */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - - -/* - * MACROS: - */ -#define AMD_LDAP_TYPE "ldap" -/* Time to live for an LDAP cached in an mnt_map */ -#define AMD_LDAP_TTL 3600 -#define AMD_LDAP_RETRIES 5 -#define AMD_LDAP_HOST "ldap" -#ifndef LDAP_PORT -# define LDAP_PORT 389 -#endif /* LDAP_PORT */ - -/* How timestamps are searched */ -#define AMD_LDAP_TSFILTER "(&(objectClass=amdmapTimestamp)(amdmapName=%s))" -/* How maps are searched */ -#define AMD_LDAP_FILTER "(&(objectClass=amdmap)(amdmapName=%s)(amdmapKey=%s))" -/* How timestamps are stored */ -#define AMD_LDAP_TSATTR "amdmaptimestamp" -/* How maps are stored */ -#define AMD_LDAP_ATTR "amdmapvalue" - -/* - * TYPEDEFS: - */ -typedef struct ald_ent ALD; -typedef struct cr_ent CR; -typedef struct he_ent HE_ENT; - -/* - * STRUCTURES: - */ -struct ald_ent { - LDAP *ldap; - HE_ENT *hostent; - CR *credentials; - time_t timestamp; -}; - -struct cr_ent { - char *who; - char *pw; - int method; -}; - -struct he_ent { - char *host; - int port; - struct he_ent *next; -}; - -/* - * FORWARD DECLARATIONS: - */ -static int amu_ldap_rebind(ALD *a); -static int get_ldap_timestamp(ALD *a, char *map, time_t *ts); - - -/* - * FUNCTIONS: - */ - -static void -he_free(HE_ENT *h) -{ - XFREE(h->host); - if (h->next != NULL) - he_free(h->next); - XFREE(h); -} - - -static HE_ENT * -string2he(char *s_orig) -{ - char *c, *p; - char *s; - HE_ENT *new, *old = NULL; - - if (NULL == s_orig || NULL == (s = strdup(s_orig))) - return NULL; - for (p = s; p; p = strchr(p, ',')) { - if (old != NULL) { - new = ALLOC(HE_ENT); - old->next = new; - old = new; - } else { - old = ALLOC(HE_ENT); - old->next = NULL; - } - c = strchr(p, ':'); - if (c) { /* Host and port */ - *c++ = '\0'; - old->host = strdup(p); - old->port = atoi(c); - } else - old->host = strdup(p); - - } - XFREE(s); - return (old); -} - - -static void -cr_free(CR *c) -{ - XFREE(c->who); - XFREE(c->pw); - XFREE(c); -} - - -/* - * Special ldap_unbind function to handle SIGPIPE. - * We first ignore SIGPIPE, in case a remote LDAP server was - * restarted, then we reinstall the handler. - */ -static int -amu_ldap_unbind(LDAP *ld) -{ - int e; -#ifdef HAVE_SIGACTION - struct sigaction sa; -#else /* not HAVE_SIGACTION */ - void (*handler)(int); -#endif /* not HAVE_SIGACTION */ - - dlog("amu_ldap_unbind()\n"); - -#ifdef HAVE_SIGACTION - sa.sa_handler = SIG_IGN; - sa.sa_flags = 0; - sigemptyset(&(sa.sa_mask)); - sigaddset(&(sa.sa_mask), SIGPIPE); - sigaction(SIGPIPE, &sa, &sa); /* set IGNORE, and get old action */ -#else /* not HAVE_SIGACTION */ - handler = signal(SIGPIPE, SIG_IGN); -#endif /* not HAVE_SIGACTION */ - - e = ldap_unbind(ld); - -#ifdef HAVE_SIGACTION - sigemptyset(&(sa.sa_mask)); - sigaddset(&(sa.sa_mask), SIGPIPE); - sigaction(SIGPIPE, &sa, NULL); -#else /* not HAVE_SIGACTION */ - (void) signal(SIGPIPE, handler); -#endif /* not HAVE_SIGACTION */ - - return e; -} - - -static void -ald_free(ALD *a) -{ - he_free(a->hostent); - cr_free(a->credentials); - if (a->ldap != NULL) - amu_ldap_unbind(a->ldap); - XFREE(a); -} - - -int -amu_ldap_init(mnt_map *m, char *map, time_t *ts) -{ - ALD *aldh; - CR *creds; - - dlog("-> amu_ldap_init: map <%s>\n", map); - - /* - * XXX: by checking that map_type must be defined, aren't we - * excluding the possibility of automatic searches through all - * map types? - */ - if (!gopt.map_type || !STREQ(gopt.map_type, AMD_LDAP_TYPE)) { - dlog("amu_ldap_init called with map_type <%s>\n", - (gopt.map_type ? gopt.map_type : "null")); - } else { - dlog("Map %s is ldap\n", map); - } - - aldh = ALLOC(ALD); - creds = ALLOC(CR); - aldh->ldap = NULL; - aldh->hostent = string2he(gopt.ldap_hostports); - if (aldh->hostent == NULL) { - plog(XLOG_USER, "Unable to parse hostport %s for ldap map %s", - gopt.ldap_hostports ? gopt.ldap_hostports : "(null)", map); - XFREE(creds); - XFREE(aldh); - return (ENOENT); - } - creds->who = ""; - creds->pw = ""; - creds->method = LDAP_AUTH_SIMPLE; - aldh->credentials = creds; - aldh->timestamp = 0; - aldh->ldap = NULL; - dlog("Trying for %s:%d\n", aldh->hostent->host, aldh->hostent->port); - if (amu_ldap_rebind(aldh)) { - ald_free(aldh); - return (ENOENT); - } - m->map_data = (void *) aldh; - dlog("Bound to %s:%d\n", aldh->hostent->host, aldh->hostent->port); - if (get_ldap_timestamp(aldh, map, ts)) - return (ENOENT); - dlog("Got timestamp for map %s: %ld\n", map, (u_long) *ts); - - return (0); -} - - -static int -amu_ldap_rebind(ALD *a) -{ - LDAP *ld; - HE_ENT *h; - CR *c = a->credentials; - time_t now = clocktime(NULL); - int try; - - dlog("-> amu_ldap_rebind\n"); - - if (a->ldap != NULL) { - if ((a->timestamp - now) > AMD_LDAP_TTL) { - dlog("Re-establishing ldap connection\n"); - amu_ldap_unbind(a->ldap); - a->timestamp = now; - a->ldap = NULL; - } else { - /* Assume all is OK. If it wasn't we'll be back! */ - dlog("amu_ldap_rebind: timestamp OK\n"); - return (0); - } - } - - for (try=0; try<10; try++) { /* XXX: try up to 10 times (makes sense?) */ - for (h = a->hostent; h != NULL; h = h->next) { - if ((ld = ldap_open(h->host, h->port)) == NULL) { - plog(XLOG_WARNING, "Unable to ldap_open to %s:%d\n", h->host, h->port); - break; - } -#if LDAP_VERSION_MAX > LDAP_VERSION2 - /* handle LDAPv3 and heigher, if available and amd.conf-igured */ - if (gopt.ldap_proto_version > LDAP_VERSION2) { - if (!ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &gopt.ldap_proto_version)) { - dlog("amu_ldap_rebind: LDAP protocol version set to %ld\n", - gopt.ldap_proto_version); - } else { - plog(XLOG_WARNING, "Unable to set ldap protocol version to %ld\n", - gopt.ldap_proto_version); - break; - } - } -#endif /* LDAP_VERSION_MAX > LDAP_VERSION2 */ - if (ldap_bind_s(ld, c->who, c->pw, c->method) != LDAP_SUCCESS) { - plog(XLOG_WARNING, "Unable to ldap_bind to %s:%d as %s\n", - h->host, h->port, c->who); - break; - } - if (gopt.ldap_cache_seconds > 0) { -#if defined(HAVE_LDAP_ENABLE_CACHE) && defined(HAVE_EXTERN_LDAP_ENABLE_CACHE) - ldap_enable_cache(ld, gopt.ldap_cache_seconds, gopt.ldap_cache_maxmem); -#else /* not defined(HAVE_LDAP_ENABLE_CACHE) && defined(HAVE_EXTERN_LDAP_ENABLE_CACHE) */ - plog(XLOG_WARNING, "ldap_enable_cache(%ld) is not available on this system!\n", gopt.ldap_cache_seconds); -#endif /* not defined(HAVE_LDAP_ENABLE_CACHE) && defined(HAVE_EXTERN_LDAP_ENABLE_CACHE) */ - } - a->ldap = ld; - a->timestamp = now; - return (0); - } - plog(XLOG_WARNING, "Exhausted list of ldap servers, looping.\n"); - } - - plog(XLOG_USER, "Unable to (re)bind to any ldap hosts\n"); - return (ENOENT); -} - - -static int -get_ldap_timestamp(ALD *a, char *map, time_t *ts) -{ - struct timeval tv; - char **vals, *end; - char filter[MAXPATHLEN]; - int i, err = 0, nentries = 0; - LDAPMessage *res = NULL, *entry; - - dlog("-> get_ldap_timestamp: map <%s>\n", map); - - tv.tv_sec = 3; - tv.tv_usec = 0; - xsnprintf(filter, sizeof(filter), AMD_LDAP_TSFILTER, map); - dlog("Getting timestamp for map %s\n", map); - dlog("Filter is: %s\n", filter); - dlog("Base is: %s\n", gopt.ldap_base); - for (i = 0; i < AMD_LDAP_RETRIES; i++) { - err = ldap_search_st(a->ldap, - gopt.ldap_base, - LDAP_SCOPE_SUBTREE, - filter, - 0, - 0, - &tv, - &res); - if (err == LDAP_SUCCESS) - break; - if (res) { - ldap_msgfree(res); - res = NULL; - } - plog(XLOG_USER, "Timestamp LDAP search attempt %d failed: %s\n", - i + 1, ldap_err2string(err)); - if (err != LDAP_TIMEOUT) { - dlog("get_ldap_timestamp: unbinding...\n"); - amu_ldap_unbind(a->ldap); - a->ldap = NULL; - if (amu_ldap_rebind(a)) - return (ENOENT); - } - dlog("Timestamp search failed, trying again...\n"); - } - - if (err != LDAP_SUCCESS) { - *ts = 0; - plog(XLOG_USER, "LDAP timestamp search failed: %s\n", - ldap_err2string(err)); - if (res) - ldap_msgfree(res); - return (ENOENT); - } - - nentries = ldap_count_entries(a->ldap, res); - if (nentries == 0) { - plog(XLOG_USER, "No timestamp entry for map %s\n", map); - *ts = 0; - ldap_msgfree(res); - return (ENOENT); - } - - entry = ldap_first_entry(a->ldap, res); - vals = ldap_get_values(a->ldap, entry, AMD_LDAP_TSATTR); - if (ldap_count_values(vals) == 0) { - plog(XLOG_USER, "Missing timestamp value for map %s\n", map); - *ts = 0; - ldap_value_free(vals); - ldap_msgfree(res); - return (ENOENT); - } - dlog("TS value is:%s:\n", vals[0]); - - if (vals[0]) { - *ts = (time_t) strtol(vals[0], &end, 10); - if (end == vals[0]) { - plog(XLOG_USER, "Unable to decode ldap timestamp %s for map %s\n", - vals[0], map); - err = ENOENT; - } - if (!*ts > 0) { - plog(XLOG_USER, "Nonpositive timestamp %ld for map %s\n", - (u_long) *ts, map); - err = ENOENT; - } - } else { - plog(XLOG_USER, "Empty timestamp value for map %s\n", map); - *ts = 0; - err = ENOENT; - } - - ldap_value_free(vals); - ldap_msgfree(res); - dlog("The timestamp for %s is %ld (err=%d)\n", map, (u_long) *ts, err); - return (err); -} - - -int -amu_ldap_search(mnt_map *m, char *map, char *key, char **pval, time_t *ts) -{ - char **vals, filter[MAXPATHLEN], filter2[2 * MAXPATHLEN]; - char *f1, *f2; - struct timeval tv; - int i, err = 0, nvals = 0, nentries = 0; - LDAPMessage *entry, *res = NULL; - ALD *a = (ALD *) (m->map_data); - - dlog("-> amu_ldap_search: map <%s>, key <%s>\n", map, key); - - tv.tv_sec = 2; - tv.tv_usec = 0; - if (a == NULL) { - plog(XLOG_USER, "LDAP panic: no map data\n"); - return (EIO); - } - if (amu_ldap_rebind(a)) /* Check that's the handle is still valid */ - return (ENOENT); - - xsnprintf(filter, sizeof(filter), AMD_LDAP_FILTER, map, key); - /* "*" is special to ldap_search(); run through the filter escaping it. */ - f1 = filter; f2 = filter2; - while (*f1) { - if (*f1 == '*') { - *f2++ = '\\'; *f2++ = '2'; *f2++ = 'a'; - f1++; - } else { - *f2++ = *f1++; - } - } - *f2 = '\0'; - dlog("Search with filter: <%s>\n", filter2); - for (i = 0; i < AMD_LDAP_RETRIES; i++) { - err = ldap_search_st(a->ldap, - gopt.ldap_base, - LDAP_SCOPE_SUBTREE, - filter2, - 0, - 0, - &tv, - &res); - if (err == LDAP_SUCCESS) - break; - if (res) { - ldap_msgfree(res); - res = NULL; - } - plog(XLOG_USER, "LDAP search attempt %d failed: %s\n", - i + 1, ldap_err2string(err)); - if (err != LDAP_TIMEOUT) { - dlog("amu_ldap_search: unbinding...\n"); - amu_ldap_unbind(a->ldap); - a->ldap = NULL; - if (amu_ldap_rebind(a)) - return (ENOENT); - } - } - - switch (err) { - case LDAP_SUCCESS: - break; - case LDAP_NO_SUCH_OBJECT: - dlog("No object\n"); - if (res) - ldap_msgfree(res); - return (ENOENT); - default: - plog(XLOG_USER, "LDAP search failed: %s\n", - ldap_err2string(err)); - if (res) - ldap_msgfree(res); - return (EIO); - } - - nentries = ldap_count_entries(a->ldap, res); - dlog("Search found %d entries\n", nentries); - if (nentries == 0) { - ldap_msgfree(res); - return (ENOENT); - } - entry = ldap_first_entry(a->ldap, res); - vals = ldap_get_values(a->ldap, entry, AMD_LDAP_ATTR); - nvals = ldap_count_values(vals); - if (nvals == 0) { - plog(XLOG_USER, "Missing value for %s in map %s\n", key, map); - ldap_value_free(vals); - ldap_msgfree(res); - return (EIO); - } - dlog("Map %s, %s => %s\n", map, key, vals[0]); - if (vals[0]) { - *pval = strdup(vals[0]); - err = 0; - } else { - plog(XLOG_USER, "Empty value for %s in map %s\n", key, map); - err = ENOENT; - } - ldap_msgfree(res); - ldap_value_free(vals); - - return (err); -} - - -int -amu_ldap_mtime(mnt_map *m, char *map, time_t *ts) -{ - ALD *aldh = (ALD *) (m->map_data); - - if (aldh == NULL) { - dlog("LDAP panic: unable to find map data\n"); - return (ENOENT); - } - if (amu_ldap_rebind(aldh)) { - return (ENOENT); - } - if (get_ldap_timestamp(aldh, map, ts)) { - return (ENOENT); - } - return (0); -} diff --git a/contrib/amd/amd/info_ndbm.c b/contrib/amd/amd/info_ndbm.c deleted file mode 100644 index 8a52ba9e201d..000000000000 --- a/contrib/amd/amd/info_ndbm.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 1997-2006 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 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. - * - * - * File: am-utils/amd/info_ndbm.c - * - */ - -/* - * Get info from NDBM map - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* forward declarations */ -int ndbm_init(mnt_map *m, char *map, time_t *tp); -int ndbm_mtime(mnt_map *m, char *map, time_t *tp); -int ndbm_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp); - - -static int -search_ndbm(DBM *db, char *key, char **val) -{ - datum k, v; - - k.dptr = key; - k.dsize = strlen(key) + 1; - v = dbm_fetch(db, k); - if (v.dptr) { - *val = strdup(v.dptr); - return 0; - } - return ENOENT; -} - - -int -ndbm_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) -{ - DBM *db; - - db = dbm_open(map, O_RDONLY, 0); - if (db) { - struct stat stb; - int error; -#ifdef DBM_SUFFIX - char dbfilename[256]; - - xstrlcpy(dbfilename, map, sizeof(dbfilename)); - xstrlcat(dbfilename, DBM_SUFFIX, sizeof(dbfilename)); - error = stat(dbfilename, &stb); -#else /* not DBM_SUFFIX */ - error = fstat(dbm_pagfno(db), &stb); -#endif /* not DBM_SUFFIX */ - if (!error && *tp < stb.st_mtime) { - *tp = stb.st_mtime; - error = -1; - } else { - error = search_ndbm(db, key, pval); - } - (void) dbm_close(db); - return error; - } - return errno; -} - - -int -ndbm_init(mnt_map *m, char *map, time_t *tp) -{ - DBM *db; - - db = dbm_open(map, O_RDONLY, 0); - if (db) { - struct stat stb; - int error; -#ifdef DBM_SUFFIX - char dbfilename[256]; - - xstrlcpy(dbfilename, map, sizeof(dbfilename)); - xstrlcat(dbfilename, DBM_SUFFIX, sizeof(dbfilename)); - error = stat(dbfilename, &stb); -#else /* not DBM_SUFFIX */ - error = fstat(dbm_pagfno(db), &stb); -#endif /* not DBM_SUFFIX */ - if (error < 0) - *tp = clocktime(NULL); - else - *tp = stb.st_mtime; - dbm_close(db); - return 0; - } - return errno; -} - - -int -ndbm_mtime(mnt_map *m, char *map, time_t *tp) -{ - return ndbm_init(m,map, tp); -} diff --git a/contrib/amd/amd/info_nis.c b/contrib/amd/amd/info_nis.c deleted file mode 100644 index bcb87d5d02aa..000000000000 --- a/contrib/amd/amd/info_nis.c +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Copyright (c) 1997-2006 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 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. - * - * - * File: am-utils/amd/info_nis.c - * - */ - -/* - * Get info from NIS map - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - - -/* - * NIS+ servers in NIS compat mode don't have yp_order() - * - * has_yp_order = 1 NIS server - * = 0 NIS+ server - * = -1 server is down - */ -static int has_yp_order = -1; - -/* forward declarations */ -int nis_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *)); -int nis_search(mnt_map *m, char *map, char *key, char **val, time_t *tp); -int nis_init(mnt_map *m, char *map, time_t *tp); -int nis_isup(mnt_map *m, char *map); -int nis_mtime(mnt_map *m, char *map, time_t *tp); - -/* typedefs */ -typedef void (*nis_callback_fxn_t)(mnt_map *, char *, char *); -#ifndef DEFINED_YPALL_CALLBACK_FXN_T -typedef int (*ypall_callback_fxn_t)(); -#endif /* DEFINED_YPALL_CALLBACK_FXN_T */ - -struct nis_callback_data { - mnt_map *ncd_m; - char *ncd_map; - nis_callback_fxn_t ncd_fn; -}; - -/* Map to the right version of yp_all */ -#ifdef HAVE_BAD_YP_ALL -# define yp_all am_yp_all -static int am_yp_all(char *indomain, char *inmap, struct ypall_callback *incallback); -#endif /* HAVE_BAD_YP_ALL */ - - -/* - * Figure out the nis domain name - */ -static int -determine_nis_domain(void) -{ - static int nis_not_running = 0; - char default_domain[YPMAXDOMAIN]; - - if (nis_not_running) - return ENOENT; - - if (getdomainname(default_domain, sizeof(default_domain)) < 0) { - nis_not_running = 1; - plog(XLOG_ERROR, "getdomainname: %m"); - return EIO; - } - if (!*default_domain) { - nis_not_running = 1; - plog(XLOG_WARNING, "NIS domain name is not set. NIS ignored."); - return ENOENT; - } - gopt.nis_domain = strdup(default_domain); - - return 0; -} - - -/* - * Callback from yp_all - */ -static int -callback(int status, char *key, int kl, char *val, int vl, char *data) -{ - struct nis_callback_data *ncdp = (struct nis_callback_data *) data; - - if (status == YP_TRUE) { - - /* add to list of maps */ - char *kp = strnsave(key, kl); - char *vp = strnsave(val, vl); - - (*ncdp->ncd_fn) (ncdp->ncd_m, kp, vp); - - /* we want more ... */ - return FALSE; - - } else { - - /* NOMORE means end of map - otherwise log error */ - if (status != YP_NOMORE) { - /* check what went wrong */ - int e = ypprot_err(status); - - plog(XLOG_ERROR, "yp enumeration of %s: %s, status=%d, e=%d", - ncdp->ncd_map, yperr_string(e), status, e); - } - return TRUE; - } -} - - -int -nis_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *)) -{ - int error; - struct nis_callback_data data; - struct ypall_callback cbinfo; - - if (!gopt.nis_domain) { - error = determine_nis_domain(); - if (error) - return error; - } - data.ncd_m = m; - data.ncd_map = map; - data.ncd_fn = fn; - cbinfo.data = (voidp) &data; - cbinfo.foreach = (ypall_callback_fxn_t) callback; - - /* - * If you are using NIS and your yp_all function is "broken", you have to - * get it fixed. The bug in yp_all() is that it does not close a TCP - * connection to ypserv, and this ypserv runs out of open file descriptors, - * getting into an infinite loop, thus all YP clients eventually unbind - * and hang too. - */ - error = yp_all(gopt.nis_domain, map, &cbinfo); - - if (error) - plog(XLOG_ERROR, "error grabbing nis map of %s: %s", map, yperr_string(ypprot_err(error))); - return error; -} - - -/* - * Check if NIS is up, so we can determine if to clear the map or not. - * Test it by checking the yp order. - * Returns: 0 if NIS is down, 1 if it is up. - */ -int -nis_isup(mnt_map *m, char *map) -{ - YP_ORDER_OUTORDER_TYPE order; - int error; - char *master; - static int last_status = 1; /* assume up by default */ - - switch (has_yp_order) { - case 1: - /* - * NIS server with yp_order - */ - error = yp_order(gopt.nis_domain, map, &order); - if (error != 0) { - plog(XLOG_ERROR, - "nis_isup: error getting the order of map %s: %s", - map, yperr_string(ypprot_err(error))); - last_status = 0; - return 0; /* NIS is down */ - } - break; - - case 0: - /* - * NIS+ server without yp_order - */ - error = yp_master(gopt.nis_domain, map, &master); - if (error != 0) { - plog(XLOG_ERROR, - "nis_isup: error getting the master of map %s: %s", - map, yperr_string(ypprot_err(error))); - last_status = 0; - return 0; /* NIS+ is down */ - } - break; - - default: - /* - * server was down - */ - last_status = 0; - } - - if (last_status == 0) { /* reinitialize if was down before */ - time_t dummy; - error = nis_init(m, map, &dummy); - if (error) - return 0; /* still down */ - plog(XLOG_INFO, "nis_isup: NIS came back up for map %s", map); - last_status = 1; - } - return 1; /* NIS is up */ -} - - -/* - * Try to locate a key using NIS. - */ -int -nis_search(mnt_map *m, char *map, char *key, char **val, time_t *tp) -{ - int outlen; - int res; - YP_ORDER_OUTORDER_TYPE order; - - /* - * Make sure domain initialized - */ - if (!gopt.nis_domain) { - int error = determine_nis_domain(); - if (error) - return error; - } - - - switch (has_yp_order) { - case 1: - /* - * NIS server with yp_order - * Check if map has changed - */ - if (yp_order(gopt.nis_domain, map, &order)) - return EIO; - if ((time_t) order > *tp) { - *tp = (time_t) order; - return -1; - } - break; - - case 0: - /* - * NIS+ server without yp_order - * Check if timeout has expired to invalidate the cache - */ - order = time(NULL); - if ((time_t)order - *tp > gopt.am_timeo) { - *tp = (time_t)order; - return(-1); - } - break; - - default: - /* - * server was down - */ - if (nis_isup(m, map)) - return -1; - return EIO; - } - - /* - * Lookup key - */ - res = yp_match(gopt.nis_domain, map, key, strlen(key), val, &outlen); - - /* - * Do something interesting with the return code - */ - switch (res) { - case 0: - return 0; - - case YPERR_KEY: - return ENOENT; - - default: - plog(XLOG_ERROR, "nis_search: %s: %s", map, yperr_string(res)); - return EIO; - } -} - - -int -nis_init(mnt_map *m, char *map, time_t *tp) -{ - YP_ORDER_OUTORDER_TYPE order; - int yp_order_result; - char *master; - - if (!gopt.nis_domain) { - int error = determine_nis_domain(); - if (error) - return error; - } - - /* - * To see if the map exists, try to find - * a master for it. - */ - yp_order_result = yp_order(gopt.nis_domain, map, &order); - switch (yp_order_result) { - case 0: - /* NIS server found */ - has_yp_order = 1; - *tp = (time_t) order; - dlog("NIS master for %s@%s has order %lu", map, gopt.nis_domain, (unsigned long) order); - break; - case YPERR_YPERR: - /* NIS+ server found ! */ - has_yp_order = 0; - /* try yp_master() instead */ - if (yp_master(gopt.nis_domain, map, &master)) { - return ENOENT; - } else { - dlog("NIS master for %s@%s is a NIS+ server", map, gopt.nis_domain); - /* Use fake timestamps */ - *tp = time(NULL); - } - break; - default: - /* server is down */ - has_yp_order = -1; - return ENOENT; - } - return 0; -} - - -int -nis_mtime(mnt_map *m, char *map, time_t *tp) -{ - return nis_init(m, map, tp); -} - - -#ifdef HAVE_BAD_YP_ALL -/* - * If you are using NIS and your yp_all function is "broken", use an - * alternate code which avoids a bug in yp_all(). The bug in yp_all() is - * that it does not close a TCP connection to ypserv, and this ypserv runs - * out of open filedescriptors, getting into an infinite loop, thus all YP - * clients eventually unbind and hang too. - * - * Systems known to be plagued with this bug: - * earlier SunOS 4.x - * all irix systems (at this time, up to 6.4 was checked) - * - * -Erez Zadok <ezk@cs.columbia.edu> - * -James Tanis <jtt@cs.columbia.edu> */ -static int -am_yp_all(char *indomain, char *inmap, struct ypall_callback *incallback) -{ - int i, j; - char *outkey, *outval; - int outkeylen, outvallen; - char *outkey_old; - int outkeylen_old; - - plog(XLOG_INFO, "NIS map %s reloading using am_yp_all", inmap); - - i = yp_first(indomain, inmap, &outkey, &outkeylen, &outval, &outvallen); - if (i) { - plog(XLOG_ERROR, "yp_first() returned error: %s\n", yperr_string(i)); - } - do { - j = (incallback->foreach)(YP_TRUE, - outkey, - outkeylen, - outval, - outvallen, - incallback->data); - if (j != FALSE) /* terminate loop */ - break; - - /* - * We have to manually free all char ** arguments to yp_first/yp_next - * outval must be freed *before* calling yp_next again, outkey can be - * freed as outkey_old *after* the call (this saves one call to - * strnsave). - */ - XFREE(outval); - outkey_old = outkey; - outkeylen_old = outkeylen; - i = yp_next(indomain, - inmap, - outkey_old, - outkeylen_old, - &outkey, - &outkeylen, - &outval, - &outvallen); - XFREE(outkey_old); - } while (!i); - if (i) { - dlog("yp_next() returned error: %s\n", yperr_string(i)); - } - if (i == YPERR_NOMORE) - return 0; - return i; -} -#endif /* HAVE_BAD_YP_ALL */ diff --git a/contrib/amd/amd/info_nisplus.c b/contrib/amd/amd/info_nisplus.c deleted file mode 100644 index d392b48fed6a..000000000000 --- a/contrib/amd/amd/info_nisplus.c +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright (c) 1997-2006 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 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. - * - * - * File: am-utils/amd/info_nisplus.c - * - */ - -/* - * Get info from NIS+ (version 3) map - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -#define NISPLUS_KEY "key=" -#define NISPLUS_ORGDIR ".org_dir" - -struct nis_callback_data { - mnt_map *ncd_m; - char *ncd_map; - void (*ncd_fn)(); -}; - -struct nisplus_search_callback_data { - nis_name key; - char *value; -}; - - -static int -nisplus_callback(const nis_name key, const nis_object *value, voidp opaquedata) -{ - char *kp = strnsave(ENTRY_VAL(value, 0), ENTRY_LEN(value, 0)); - char *vp = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1)); - struct nis_callback_data *data = (struct nis_callback_data *) opaquedata; - - dlog("NISplus callback for <%s,%s>", kp, vp); - - (*data->ncd_fn) (data->ncd_m, kp, vp); - - /* - * We want more ... - */ - return FALSE; -} - - -int -nisplus_reload(mnt_map *m, char *map, void (*fn) ()) -{ - int error = 0; - struct nis_callback_data data; - nis_result *result; - char *org; /* if map does not have ".org_dir" then append it */ - nis_name map_name; - size_t l; - - org = strstr(map, NISPLUS_ORGDIR); - if (org == NULL) - org = NISPLUS_ORGDIR; - else - org = ""; - - /* make some room for the NIS map_name */ - l = strlen(map) + sizeof(NISPLUS_ORGDIR); - map_name = xmalloc(l); - if (map_name == NULL) { - plog(XLOG_ERROR, "Unable to create map_name %s: %s", - map, strerror(ENOMEM)); - return ENOMEM; - } - xsnprintf(map_name, l, "%s%s", map, org); - - data.ncd_m = m; - data.ncd_map = map_name; - data.ncd_fn = fn; - - dlog("NISplus reload for %s", map); - - result = nis_list(map_name, - EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH, - (int (*)()) nisplus_callback, - &data); - - /* free off the NIS map_name */ - XFREE(map_name); - - if (result->status != NIS_SUCCESS && result->status != NIS_CBRESULTS) - error = 1; - - if (error) - plog(XLOG_ERROR, "error grabbing nisplus map of %s: %s", - map, - nis_sperrno(result->status)); - - nis_freeresult(result); - return error; -} - - -static int -nisplus_search_callback(const nis_name key, const nis_object *value, voidp opaquedata) -{ - struct nisplus_search_callback_data *data = (struct nisplus_search_callback_data *) opaquedata; - - dlog("NISplus search callback for <%s>", ENTRY_VAL(value, 0)); - dlog("NISplus search callback value <%s>", ENTRY_VAL(value, 1)); - - data->value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1)); - return TRUE; -} - - -/* - * Try to locate a key using NIS+. - */ -int -nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp) -{ - nis_result *result; - int error = 0; - struct nisplus_search_callback_data data; - nis_name index; - char *org; /* if map does not have ".org_dir" then append it */ - size_t l; - - org = strstr(map, NISPLUS_ORGDIR); - if (org == NULL) - org = NISPLUS_ORGDIR; - else - org = ""; - - /* make some room for the NIS index */ - l = sizeof('[') /* for opening selection criteria */ - + sizeof(NISPLUS_KEY) - + strlen(key) - + sizeof(']') /* for closing selection criteria */ - + sizeof(',') /* + 1 for , separator */ - + strlen(map) - + sizeof(NISPLUS_ORGDIR); - index = xmalloc(l); - if (index == NULL) { - plog(XLOG_ERROR, - "Unable to create index %s: %s", - map, - strerror(ENOMEM)); - return ENOMEM; - } - xsnprintf(index, l, "[%s%s],%s%s", NISPLUS_KEY, key, map, org); - - data.key = key; - data.value = NULL; - - dlog("NISplus search for %s", index); - - result = nis_list(index, - EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH, - (int (*)()) nisplus_search_callback, - &data); - - /* free off the NIS index */ - XFREE(index); - - if (result == NULL) { - plog(XLOG_ERROR, "nisplus_search: %s: %s", map, strerror(ENOMEM)); - return ENOMEM; - } - - /* - * Do something interesting with the return code - */ - switch (result->status) { - case NIS_SUCCESS: - case NIS_CBRESULTS: - - if (data.value == NULL) { - nis_object *value = result->objects.objects_val; - dlog("NISplus search found <nothing>"); - dlog("NISplus search for %s: %s(%d)", - map, nis_sperrno(result->status), result->status); - - if (value != NULL) - data.value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1)); - } - *val = data.value; - - if (*val) { - error = 0; - dlog("NISplus search found %s", *val); - } else { - error = ENOENT; - dlog("NISplus search found nothing"); - } - - *tp = 0; - break; - - case NIS_NOSUCHNAME: - dlog("NISplus search returned %d", result->status); - error = ENOENT; - break; - - default: - plog(XLOG_ERROR, "nisplus_search: %s: %s", map, nis_sperrno(result->status)); - error = EIO; - break; - } - nis_freeresult(result); - - return error; -} - - -int -nisplus_init(mnt_map *m, char *map, time_t *tp) -{ - nis_result *result; - char *org; /* if map does not have ".org_dir" then append it */ - nis_name map_name; - int error = 0; - size_t l; - - org = strstr(map, NISPLUS_ORGDIR); - if (org == NULL) - org = NISPLUS_ORGDIR; - else - org = ""; - - /* make some room for the NIS map_name */ - l = strlen(map) + sizeof(NISPLUS_ORGDIR); - map_name = xmalloc(l); - if (map_name == NULL) { - plog(XLOG_ERROR, - "Unable to create map_name %s: %s", - map, - strerror(ENOMEM)); - return ENOMEM; - } - xsnprintf(map_name, l, "%s%s", map, org); - - result = nis_lookup(map_name, (EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH)); - - /* free off the NIS map_name */ - XFREE(map_name); - - if (result == NULL) { - plog(XLOG_ERROR, "NISplus init <%s>: %s", map, strerror(ENOMEM)); - return ENOMEM; - } - - if (result->status != NIS_SUCCESS) { - dlog("NISplus init <%s>: %s (%d)", - map, nis_sperrno(result->status), result->status); - - error = ENOENT; - } - - *tp = 0; /* no time */ - nis_freeresult(result); - return error; -} - - -int -nisplus_mtime(mnt_map *m, char *map, time_t *tp) -{ - return nisplus_init(m,map, tp); -} diff --git a/contrib/amd/amd/info_passwd.c b/contrib/amd/amd/info_passwd.c deleted file mode 100644 index c8bf388b1d65..000000000000 --- a/contrib/amd/amd/info_passwd.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/info_passwd.c - * - */ - -/* - * Get info from password "file" - * - * This is experimental and probably doesn't do what you expect. - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -#define PASSWD_MAP "/etc/passwd" - -/* forward declarations */ -int passwd_init(mnt_map *m, char *map, time_t *tp); -int passwd_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp); - - -/* - * Nothing to probe - check the map name is PASSWD_MAP. - */ -int -passwd_init(mnt_map *m, char *map, time_t *tp) -{ - *tp = 0; - - /* - * Recognize the old format "PASSWD_MAP" - * Uses default return string - * "type:=nfs;rfs:=/${var0}/${var1};rhost:=${var1};sublink:=${var2};fs:=${autodir}${var3}" - */ - if (STREQ(map, PASSWD_MAP)) - return 0; - /* - * Recognize the new format "PASSWD_MAP:pval-format" - */ - if (!NSTREQ(map, PASSWD_MAP, sizeof(PASSWD_MAP) - 1)) - return ENOENT; - if (map[sizeof(PASSWD_MAP)-1] != ':') - return ENOENT; - - return 0; -} - - -/* - * Grab the entry via the getpwname routine - * Modify time is ignored by passwd - XXX - */ -int -passwd_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) -{ - char *dir = 0; - struct passwd *pw; - - if (STREQ(key, "/defaults")) { - *pval = strdup("type:=nfs"); - return 0; - } - pw = getpwnam(key); - - if (pw) { - /* - * We chop the home directory up as follows: - * /anydir/dom1/dom2/dom3/user - * - * and return - * rfs:=/anydir/dom3;rhost:=dom3.dom2.dom1;sublink:=user - * and now have - * var0:=pw-prefix:=anydir - * var1:=pw-rhost:=dom3.dom2.dom1 - * var2:=pw-user:=user - * var3:=pw-home:=/anydir/dom1/dom2/dom3/user - * - * This allows cross-domain entries in your passwd file. - * ... but forget about security! - */ - char *user; - char *p, *q; - char val[MAXPATHLEN]; - char rhost[MAXHOSTNAMELEN]; - dir = strdup(pw->pw_dir); - - /* - * Find user name. If no / then Invalid... - */ - user = strrchr(dir, '/'); - if (!user) - goto enoent; - *user++ = '\0'; - - /* - * Find start of host "path". If no / then Invalid... - */ - p = strchr(dir + 1, '/'); - if (!p) - goto enoent; - *p++ = '\0'; - - /* - * At this point, p is dom1/dom2/dom3 - * Copy, backwards, into rhost replacing - * / with . - */ - rhost[0] = '\0'; - do { - q = strrchr(p, '/'); - if (q) { - xstrlcat(rhost, q + 1, sizeof(rhost)); - xstrlcat(rhost, ".", sizeof(rhost)); - *q = '\0'; - } else { - xstrlcat(rhost, p, sizeof(rhost)); - } - } while (q); - - /* - * Sanity check - */ - if (*rhost == '\0' || *user == '\0' || *dir == '\0') - goto enoent; - - /* - * Make up return string - */ - q = strchr(rhost, '.'); - if (q) - *q = '\0'; - p = strchr(map, ':'); - if (p) - p++; - else - p = "type:=nfs;rfs:=/${var0}/${var1};rhost:=${var1};sublink:=${var2};fs:=${autodir}${var3}"; - xsnprintf(val, sizeof(val), "var0:=%s;var1:=%s;var2:=%s;var3:=%s;%s", - dir+1, rhost, user, pw->pw_dir, p); - dlog("passwd_search: map=%s key=%s -> %s", map, key, val); - if (q) - *q = '.'; - *pval = strdup(val); - return 0; - } - -enoent: - if (dir) - XFREE(dir); - - return ENOENT; -} diff --git a/contrib/amd/amd/info_union.c b/contrib/amd/amd/info_union.c deleted file mode 100644 index 8f0631c64ac9..000000000000 --- a/contrib/amd/amd/info_union.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/info_union.c - * - */ - -/* - * Get info from the system namespace - * - * NOTE: Cannot handle reads back through the automounter. - * THIS WILL CAUSE A DEADLOCK! - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -#define UNION_PREFIX "union:" -#define UNION_PREFLEN 6 - -/* forward declarations */ -int union_init(mnt_map *m, char *map, time_t *tp); -int union_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp); -int union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *)); - - -/* - * No way to probe - check the map name begins with "union:" - */ -int -union_init(mnt_map *m, char *map, time_t *tp) -{ - *tp = 0; - return NSTREQ(map, UNION_PREFIX, UNION_PREFLEN) ? 0 : ENOENT; -} - - -int -union_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) -{ - char *mapd = strdup(map + UNION_PREFLEN); - char **v = strsplit(mapd, ':', '\"'); - char **p; - size_t l; - - for (p = v; p[1]; p++) ; - l = strlen(*p) + 5; - *pval = xmalloc(l); - xsnprintf(*pval, l, "fs:=%s", *p); - XFREE(mapd); - XFREE(v); - return 0; -} - - -int -union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *)) -{ - char *mapd = strdup(map + UNION_PREFLEN); - char **v = strsplit(mapd, ':', '\"'); - char **dir; - - /* - * Add fake /defaults entry - */ - (*fn) (m, strdup("/defaults"), strdup("type:=link;opts:=nounmount;sublink:=${key}")); - - for (dir = v; *dir; dir++) { - size_t l; - struct dirent *dp; - - DIR *dirp = opendir(*dir); - if (!dirp) { - plog(XLOG_USER, "Cannot read directory %s: %m", *dir); - continue; - } - l = strlen(*dir) + 5; - - dlog("Reading directory %s...", *dir); - while ((dp = readdir(dirp))) { - char *val, *dpname = &dp->d_name[0]; - if (dpname[0] == '.' && - (dpname[1] == '\0' || - (dpname[1] == '.' && dpname[2] == '\0'))) - continue; - - dlog("... gives %s", dp->d_name); - val = xmalloc(l); - xsnprintf(val, l + 5, "fs:=%s", *dir); - (*fn) (m, strdup(dp->d_name), val); - } - closedir(dirp); - } - - /* - * Add wildcard entry - */ - { - size_t l = strlen(*(dir-1)) + 5; - char *val = xmalloc(l); - - xsnprintf(val, l, "fs:=%s", *(dir-1)); - (*fn) (m, strdup("*"), val); - } - XFREE(mapd); - XFREE(v); - return 0; -} diff --git a/contrib/amd/amd/map.c b/contrib/amd/amd/map.c deleted file mode 100644 index 8696dfd6984d..000000000000 --- a/contrib/amd/amd/map.c +++ /dev/null @@ -1,1072 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/map.c - * - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -#define smallest_t(t1, t2) (t1 != NEVER ? (t2 != NEVER ? (t1 < t2 ? t1 : t2) : t1) : t2) -#define IGNORE_FLAGS (MFF_MOUNTING|MFF_UNMOUNTING|MFF_RESTART) -#define new_gen() (am_gen++) - -/* - * Generation Numbers. - * - * Generation numbers are allocated to every node created - * by amd. When a filehandle is computed and sent to the - * kernel, the generation number makes sure that it is safe - * to reallocate a node slot even when the kernel has a cached - * reference to its old incarnation. - * No garbage collection is done, since it is assumed that - * there is no way that 2^32 generation numbers could ever - * be allocated by a single run of amd - there is simply - * not enough cpu time available. - * Famous last words... -Ion - */ -static u_int am_gen = 2; /* Initial generation number */ -static int timeout_mp_id; /* Id from last call to timeout */ - -static am_node *root_node; /* The root of the mount tree */ -static am_node **exported_ap = (am_node **) 0; -static int exported_ap_size = 0; -static int first_free_map = 0; /* First available free slot */ -static int last_used_map = -1; /* Last unavailable used slot */ - - -/* - * This is the default attributes field which - * is copied into every new node to be created. - * The individual filesystem fs_init() routines - * patch the copy to represent the particular - * details for the relevant filesystem type - */ -static nfsfattr gen_fattr = -{ - NFLNK, /* type */ - NFSMODE_LNK | 0777, /* mode */ - 1, /* nlink */ - 0, /* uid */ - 0, /* gid */ - 0, /* size */ - 4096, /* blocksize */ - 0, /* rdev */ - 1, /* blocks */ - 0, /* fsid */ - 0, /* fileid */ - {0, 0}, /* atime */ - {0, 0}, /* mtime */ - {0, 0}, /* ctime */ -}; - -/* forward declarations */ -static int unmount_node(opaque_t arg); -static void exported_ap_free(am_node *mp); -static void remove_am(am_node *mp); -static am_node *get_root_ap(char *dir); - - -/* - * Iterator functions for exported_ap[] - */ -am_node * -get_first_exported_ap(int *index) -{ - *index = -1; - return get_next_exported_ap(index); -} - - -am_node * -get_next_exported_ap(int *index) -{ - (*index)++; - while (*index < exported_ap_size) { - if (exported_ap[*index] != NULL) - return exported_ap[*index]; - (*index)++; - } - return NULL; -} - - -/* - * Get exported_ap by index - */ -am_node * -get_exported_ap(int index) -{ - if (index < 0 || index >= exported_ap_size) - return 0; - return exported_ap[index]; -} - - -/* - * Get exported_ap by path - */ -am_node * -path_to_exported_ap(char *path) -{ - int index; - am_node *mp; - - mp = get_first_exported_ap(&index); - while (mp != NULL) { - if (STREQ(mp->am_path, path)) - break; - mp = get_next_exported_ap(&index); - } - return mp; -} - - -/* - * Resize exported_ap map - */ -static int -exported_ap_realloc_map(int nsize) -{ - /* - * this shouldn't happen, but... - */ - if (nsize < 0 || nsize == exported_ap_size) - return 0; - - exported_ap = (am_node **) xrealloc((voidp) exported_ap, nsize * sizeof(am_node *)); - - if (nsize > exported_ap_size) - memset((char *) (exported_ap + exported_ap_size), 0, - (nsize - exported_ap_size) * sizeof(am_node *)); - exported_ap_size = nsize; - - return 1; -} - - - -am_node * -get_ap_child(am_node *mp, char *fname) -{ - am_node *new_mp; - mntfs *mf = mp->am_mnt; - - /* - * Allocate a new map - */ - new_mp = exported_ap_alloc(); - if (new_mp) { - /* - * Fill it in - */ - init_map(new_mp, fname); - - /* - * Put it in the table - */ - insert_am(new_mp, mp); - - /* - * Fill in some other fields, - * path and mount point. - * - * bugfix: do not prepend old am_path if direct map - * <wls@astro.umd.edu> William Sebok - */ - new_mp->am_path = str3cat(new_mp->am_path, - (mf->mf_fsflags & FS_DIRECT) - ? "" - : mp->am_path, - *fname == '/' ? "" : "/", fname); - dlog("setting path to %s", new_mp->am_path); - } - - return new_mp; -} - -/* - * Allocate a new mount slot and create - * a new node. - * Fills in the map number of the node, - * but leaves everything else uninitialized. - */ -am_node * -exported_ap_alloc(void) -{ - am_node *mp, **mpp; - - /* - * First check if there are any slots left, realloc if needed - */ - if (first_free_map >= exported_ap_size) - if (!exported_ap_realloc_map(exported_ap_size + NEXP_AP)) - return 0; - - /* - * Grab the next free slot - */ - mpp = exported_ap + first_free_map; - mp = *mpp = ALLOC(struct am_node); - memset((char *) mp, 0, sizeof(struct am_node)); - - mp->am_mapno = first_free_map++; - - /* - * Update free pointer - */ - while (first_free_map < exported_ap_size && exported_ap[first_free_map]) - first_free_map++; - - if (first_free_map > last_used_map) - last_used_map = first_free_map - 1; - - return mp; -} - - -/* - * Free a mount slot - */ -static void -exported_ap_free(am_node *mp) -{ - /* - * Sanity check - */ - if (!mp) - return; - - /* - * Zero the slot pointer to avoid double free's - */ - exported_ap[mp->am_mapno] = 0; - - /* - * Update the free and last_used indices - */ - if (mp->am_mapno == last_used_map) - while (last_used_map >= 0 && exported_ap[last_used_map] == 0) - --last_used_map; - - if (first_free_map > mp->am_mapno) - first_free_map = mp->am_mapno; - - /* - * Free the mount node, and zero out it's internal struct data. - */ - memset((char *) mp, 0, sizeof(am_node)); - XFREE(mp); -} - - -/* - * Insert mp into the correct place, - * where p_mp is its parent node. - * A new node gets placed as the youngest sibling - * of any other children, and the parent's child - * pointer is adjusted to point to the new child node. - */ -void -insert_am(am_node *mp, am_node *p_mp) -{ - /* - * If this is going in at the root then flag it - * so that it cannot be unmounted by amq. - */ - if (p_mp == root_node) - mp->am_flags |= AMF_ROOT; - /* - * Fill in n-way links - */ - mp->am_parent = p_mp; - mp->am_osib = p_mp->am_child; - if (mp->am_osib) - mp->am_osib->am_ysib = mp; - p_mp->am_child = mp; -#ifdef HAVE_FS_AUTOFS - if (p_mp->am_mnt->mf_flags & MFF_IS_AUTOFS) - mp->am_flags |= AMF_AUTOFS; -#endif /* HAVE_FS_AUTOFS */ -} - - -/* - * Remove am from its place in the mount tree - */ -static void -remove_am(am_node *mp) -{ - /* - * 1. Consistency check - */ - if (mp->am_child && mp->am_parent) { - plog(XLOG_WARNING, "children of \"%s\" still exist - deleting anyway", mp->am_path); - } - - /* - * 2. Update parent's child pointer - */ - if (mp->am_parent && mp->am_parent->am_child == mp) - mp->am_parent->am_child = mp->am_osib; - - /* - * 3. Unlink from sibling chain - */ - if (mp->am_ysib) - mp->am_ysib->am_osib = mp->am_osib; - if (mp->am_osib) - mp->am_osib->am_ysib = mp->am_ysib; -} - - -/* - * Compute a new time to live value for a node. - */ -void -new_ttl(am_node *mp) -{ - mp->am_timeo_w = 0; - mp->am_ttl = clocktime(&mp->am_fattr.na_atime); - mp->am_ttl += mp->am_timeo; /* sun's -tl option */ -} - - -void -mk_fattr(nfsfattr *fattr, nfsftype vntype) -{ - switch (vntype) { - case NFDIR: - fattr->na_type = NFDIR; - fattr->na_mode = NFSMODE_DIR | 0555; - fattr->na_nlink = 2; - fattr->na_size = 512; - break; - case NFLNK: - fattr->na_type = NFLNK; - fattr->na_mode = NFSMODE_LNK | 0777; - fattr->na_nlink = 1; - fattr->na_size = 0; - break; - default: - plog(XLOG_FATAL, "Unknown fattr type %d - ignored", vntype); - break; - } -} - - -/* - * Initialize an allocated mount node. - * It is assumed that the mount node was b-zero'd - * before getting here so anything that would - * be set to zero isn't done here. - */ -void -init_map(am_node *mp, char *dir) -{ - /* - * mp->am_mapno is initialized by exported_ap_alloc - * other fields don't need to be set to zero. - */ - mp->am_mnt = new_mntfs(); - mp->am_mfarray = 0; - mp->am_name = strdup(dir); - mp->am_path = strdup(dir); - mp->am_gen = new_gen(); -#ifdef HAVE_FS_AUTOFS - mp->am_autofs_fh = 0; -#endif /* HAVE_FS_AUTOFS */ - - mp->am_timeo = gopt.am_timeo; - mp->am_attr.ns_status = NFS_OK; - mp->am_fattr = gen_fattr; - mp->am_fattr.na_fsid = 42; - mp->am_fattr.na_fileid = mp->am_gen; - clocktime(&mp->am_fattr.na_atime); - /* next line copies a "struct nfstime" among several fields */ - mp->am_fattr.na_mtime = mp->am_fattr.na_ctime = mp->am_fattr.na_atime; - - new_ttl(mp); - mp->am_stats.s_mtime = mp->am_fattr.na_atime.nt_seconds; - mp->am_dev = -1; - mp->am_rdev = -1; -} - - -/* - * Free a mount node. - * The node must be already unmounted. - */ -void -free_map(am_node *mp) -{ - remove_am(mp); - - if (mp->am_link) - XFREE(mp->am_link); - if (mp->am_name) - XFREE(mp->am_name); - if (mp->am_path) - XFREE(mp->am_path); - if (mp->am_pref) - XFREE(mp->am_pref); - if (mp->am_transp) - XFREE(mp->am_transp); - - if (mp->am_mnt) - free_mntfs(mp->am_mnt); - - if (mp->am_mfarray) { - mntfs **temp_mf; - for (temp_mf = mp->am_mfarray; *temp_mf; temp_mf++) - free_mntfs(*temp_mf); - XFREE(mp->am_mfarray); - } - -#ifdef HAVE_FS_AUTOFS - if (mp->am_autofs_fh) - autofs_release_fh(mp); -#endif /* HAVE_FS_AUTOFS */ - - exported_ap_free(mp); -} - - -static am_node * -find_ap_recursive(char *dir, am_node *mp) -{ - if (mp) { - am_node *mp2; - if (STREQ(mp->am_path, dir)) - return mp; - - if ((mp->am_mnt->mf_flags & MFF_MOUNTED) && - STREQ(mp->am_mnt->mf_mount, dir)) - return mp; - - mp2 = find_ap_recursive(dir, mp->am_osib); - if (mp2) - return mp2; - return find_ap_recursive(dir, mp->am_child); - } - - return 0; -} - - -/* - * Find the mount node corresponding to dir. dir can match either the - * automount path or, if the node is mounted, the mount location. - */ -am_node * -find_ap(char *dir) -{ - int i; - - for (i = last_used_map; i >= 0; --i) { - am_node *mp = exported_ap[i]; - if (mp && (mp->am_flags & AMF_ROOT)) { - mp = find_ap_recursive(dir, exported_ap[i]); - if (mp) { - return mp; - } - } - } - - return 0; -} - - -/* - * Find the mount node corresponding - * to the mntfs structure. - */ -am_node * -find_mf(mntfs *mf) -{ - int i; - - for (i = last_used_map; i >= 0; --i) { - am_node *mp = exported_ap[i]; - if (mp && mp->am_mnt == mf) - return mp; - } - - return 0; -} - - -/* - * Get the filehandle for a particular named directory. - * This is used during the bootstrap to tell the kernel - * the filehandles of the initial automount points. - */ -am_nfs_fh * -get_root_nfs_fh(char *dir) -{ - static am_nfs_fh nfh; - am_node *mp = get_root_ap(dir); - if (mp) { - mp_to_fh(mp, &nfh); - return &nfh; - } - - /* - * Should never get here... - */ - plog(XLOG_ERROR, "Can't find root filehandle for %s", dir); - - return 0; -} - - -static am_node * -get_root_ap(char *dir) -{ - am_node *mp = find_ap(dir); - - if (mp && mp->am_parent == root_node) - return mp; - - return 0; -} - - -/* - * Timeout all nodes waiting on - * a given Fserver. - */ -void -map_flush_srvr(fserver *fs) -{ - int i; - int done = 0; - - for (i = last_used_map; i >= 0; --i) { - am_node *mp = exported_ap[i]; - if (mp && mp->am_mnt && mp->am_mnt->mf_server == fs) { - plog(XLOG_INFO, "Flushed %s; dependent on %s", mp->am_path, fs->fs_host); - mp->am_ttl = clocktime(NULL); - done = 1; - } - } - if (done) - reschedule_timeout_mp(); -} - - -/* - * Mount a top level automount node - * by calling lookup in the parent - * (root) node which will cause the - * automount node to be automounted. - */ -int -mount_auto_node(char *dir, opaque_t arg) -{ - int error = 0; - am_node *mp = (am_node *) arg; - am_node *new_mp; - - new_mp = mp->am_mnt->mf_ops->lookup_child(mp, dir, &error, VLOOK_CREATE); - if (new_mp && error < 0) { - /* - * We can't allow the fileid of the root node to change. - * Should be ok to force it to 1, always. - */ - new_mp->am_gen = new_mp->am_fattr.na_fileid = 1; - - new_mp = mp->am_mnt->mf_ops->mount_child(new_mp, &error); - } - - if (error > 0) { - errno = error; /* XXX */ - plog(XLOG_ERROR, "Could not mount %s: %m", dir); - } - return error; -} - - -/* - * Cause all the top-level mount nodes - * to be automounted - */ -int -mount_exported(void) -{ - /* - * Iterate over all the nodes to be started - */ - return root_keyiter(mount_auto_node, root_node); -} - - -/* - * Construct top-level node - */ -void -make_root_node(void) -{ - mntfs *root_mnt; - char *rootmap = ROOT_MAP; - root_node = exported_ap_alloc(); - - /* - * Allocate a new map - */ - init_map(root_node, ""); - - /* - * Allocate a new mounted filesystem - */ - root_mnt = find_mntfs(&amfs_root_ops, (am_opts *) 0, "", rootmap, "", "", ""); - - /* - * Replace the initial null reference - */ - free_mntfs(root_node->am_mnt); - root_node->am_mnt = root_mnt; - - /* - * Initialize the root - */ - if (root_mnt->mf_ops->fs_init) - (*root_mnt->mf_ops->fs_init) (root_mnt); - - /* - * Mount the root - */ - root_mnt->mf_error = root_mnt->mf_ops->mount_fs(root_node, root_mnt); -} - - -/* - * Cause all the nodes to be unmounted by timing - * them out. - */ -void -umount_exported(void) -{ - int i; - - for (i = last_used_map; i >= 0; --i) { - am_node *mp = exported_ap[i]; - mntfs *mf; - - if (!mp) - continue; - - mf = mp->am_mnt; - if (mf->mf_flags & MFF_UNMOUNTING) { - /* - * If this node is being unmounted then just ignore it. However, - * this could prevent amd from finishing if the unmount gets blocked - * since the am_node will never be free'd. am_unmounted needs - * telling about this possibility. - XXX - */ - continue; - } - - if (!(mf->mf_fsflags & FS_DIRECTORY)) - /* - * When shutting down this had better - * look like a directory, otherwise it - * can't be unmounted! - */ - mk_fattr(&mp->am_fattr, NFDIR); - - if ((--immediate_abort < 0 && - !(mp->am_flags & AMF_ROOT) && mp->am_parent) || - (mf->mf_flags & MFF_RESTART)) { - - /* - * Just throw this node away without bothering to unmount it. If - * the server is not known to be up then don't discard the mounted - * on directory or Amd might hang... - */ - if (mf->mf_server && - (mf->mf_server->fs_flags & (FSF_DOWN | FSF_VALID)) != FSF_VALID) - mf->mf_flags &= ~MFF_MKMNT; - if (gopt.flags & CFM_UNMOUNT_ON_EXIT || mp->am_flags & AMF_AUTOFS) { - plog(XLOG_INFO, "on-exit attempt to unmount %s", mf->mf_mount); - /* - * use unmount_mp, not unmount_node, so that unmounts be - * backgrounded as needed. - */ - unmount_mp((opaque_t) mp); - } else { - am_unmounted(mp); - } - exported_ap[i] = 0; - } else { - /* - * Any other node gets forcibly timed out. - */ - mp->am_flags &= ~AMF_NOTIMEOUT; - mp->am_mnt->mf_flags &= ~MFF_RSTKEEP; - mp->am_ttl = 0; - mp->am_timeo = 1; - mp->am_timeo_w = 0; - } - } -} - - -/* - * Try to mount a file system. Can be called directly or in a sub-process by run_task. - * - * Warning: this function might be running in a child process context. - * Don't expect any changes made here to survive in the parent amd process. - */ -int -mount_node(opaque_t arg) -{ - am_node *mp = (am_node *) arg; - mntfs *mf = mp->am_mnt; - int error = 0; - -#ifdef HAVE_FS_AUTOFS - if (mp->am_flags & AMF_AUTOFS) - error = autofs_mount_fs(mp, mf); - else -#endif /* HAVE_FS_AUTOFS */ - if (!(mf->mf_flags & MFF_MOUNTED)) - error = mf->mf_ops->mount_fs(mp, mf); - - if (error > 0) - dlog("mount_node: call to mf_ops->mount_fs(%s) failed: %s", - mp->am_path, strerror(error)); - return error; -} - - -static int -unmount_node(opaque_t arg) -{ - am_node *mp = (am_node *) arg; - mntfs *mf = mp->am_mnt; - int error = 0; - - if (mf->mf_flags & MFF_ERROR) { - /* - * Just unlink - */ - dlog("No-op unmount of error node %s", mf->mf_info); - } else { - dlog("Unmounting <%s> <%s> (%s) flags %x", - mp->am_path, mf->mf_mount, mf->mf_info, mf->mf_flags); -#ifdef HAVE_FS_AUTOFS - if (mp->am_flags & AMF_AUTOFS) - error = autofs_umount_fs(mp, mf); - else -#endif /* HAVE_FS_AUTOFS */ - if (mf->mf_refc == 1) - error = mf->mf_ops->umount_fs(mp, mf); - } - - /* do this again, it might have changed */ - mf = mp->am_mnt; - if (error) { - errno = error; /* XXX */ - dlog("%s: unmount: %m", mf->mf_mount); - } - - return error; -} - - -static void -free_map_if_success(int rc, int term, opaque_t arg) -{ - am_node *mp = (am_node *) arg; - mntfs *mf = mp->am_mnt; - wchan_t wchan = get_mntfs_wchan(mf); - - /* - * Not unmounting any more - */ - mf->mf_flags &= ~MFF_UNMOUNTING; - - /* - * If a timeout was deferred because the underlying filesystem - * was busy then arrange for a timeout as soon as possible. - */ - if (mf->mf_flags & MFF_WANTTIMO) { - mf->mf_flags &= ~MFF_WANTTIMO; - reschedule_timeout_mp(); - } - if (term) { - plog(XLOG_ERROR, "unmount for %s got signal %d", mp->am_path, term); -#if defined(DEBUG) && defined(SIGTRAP) - /* - * dbx likes to put a trap on exit(). - * Pretend it succeeded for now... - */ - if (term == SIGTRAP) { - am_unmounted(mp); - } -#endif /* DEBUG */ -#ifdef HAVE_FS_AUTOFS - if (mp->am_flags & AMF_AUTOFS) - autofs_umount_failed(mp); -#endif /* HAVE_FS_AUTOFS */ - amd_stats.d_uerr++; - } else if (rc) { - if (mf->mf_ops == &amfs_program_ops || rc == EBUSY) - plog(XLOG_STATS, "\"%s\" on %s still active", mp->am_path, mf->mf_mount); - else - plog(XLOG_ERROR, "%s: unmount: %s", mp->am_path, strerror(rc)); -#ifdef HAVE_FS_AUTOFS - if (mf->mf_flags & MFF_IS_AUTOFS) - autofs_get_mp(mp); - if (mp->am_flags & AMF_AUTOFS) - autofs_umount_failed(mp); -#endif /* HAVE_FS_AUTOFS */ - amd_stats.d_uerr++; - } else { - am_unmounted(mp); - } - - /* - * Wakeup anything waiting for this unmount - */ - wakeup(wchan); -} - - -int -unmount_mp(am_node *mp) -{ - int was_backgrounded = 0; - mntfs *mf = mp->am_mnt; - -#ifdef notdef - plog(XLOG_INFO, "\"%s\" on %s timed out (flags 0x%x)", - mp->am_path, mp->am_mnt->mf_mount, (int) mf->mf_flags); -#endif /* notdef */ - -#ifndef MNT2_NFS_OPT_SYMTTL - /* - * This code is needed to defeat Solaris 2.4's (and newer) symlink - * values cache. It forces the last-modified time of the symlink to be - * current. It is not needed if the O/S has an nfs flag to turn off the - * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez. - * - * Additionally, Linux currently ignores the nt_useconds field, - * so we must update the nt_seconds field every time if clocktime(NULL) - * didn't return a new number of seconds. - */ - if (mp->am_parent) { - time_t last = mp->am_parent->am_attr.ns_u.ns_attr_u.na_mtime.nt_seconds; - clocktime(&mp->am_parent->am_attr.ns_u.ns_attr_u.na_mtime); - /* defensive programming... can't we assert the above condition? */ - if (last == (time_t) mp->am_parent->am_attr.ns_u.ns_attr_u.na_mtime.nt_seconds) - mp->am_parent->am_attr.ns_u.ns_attr_u.na_mtime.nt_seconds++; - } -#endif /* not MNT2_NFS_OPT_SYMTTL */ - - if (mf->mf_refc == 1 && !FSRV_ISUP(mf->mf_server)) { - /* - * Don't try to unmount from a server that is known to be down - */ - if (!(mf->mf_flags & MFF_LOGDOWN)) { - /* Only log this once, otherwise gets a bit boring */ - plog(XLOG_STATS, "file server %s is down - timeout of \"%s\" ignored", mf->mf_server->fs_host, mp->am_path); - mf->mf_flags |= MFF_LOGDOWN; - } - return 0; - } - - dlog("\"%s\" on %s timed out", mp->am_path, mp->am_mnt->mf_mount); - mf->mf_flags |= MFF_UNMOUNTING; - -#ifdef HAVE_FS_AUTOFS - if (mf->mf_flags & MFF_IS_AUTOFS) - autofs_release_mp(mp); -#endif /* HAVE_FS_AUTOFS */ - - if ((mf->mf_fsflags & FS_UBACKGROUND) && - (mf->mf_flags & MFF_MOUNTED)) { - dlog("Trying unmount in background"); - run_task(unmount_node, (opaque_t) mp, - free_map_if_success, (opaque_t) mp); - was_backgrounded = 1; - } else { - dlog("Trying unmount in foreground"); - free_map_if_success(unmount_node((opaque_t) mp), 0, (opaque_t) mp); - dlog("unmount attempt done"); - } - - return was_backgrounded; -} - - -void -timeout_mp(opaque_t v) /* argument not used?! */ -{ - int i; - time_t t = NEVER; - time_t now = clocktime(NULL); - int backoff = NumChildren / 4; - - dlog("Timing out automount points..."); - - for (i = last_used_map; i >= 0; --i) { - am_node *mp = exported_ap[i]; - mntfs *mf; - - /* - * Just continue if nothing mounted - */ - if (!mp) - continue; - - /* - * Pick up mounted filesystem - */ - mf = mp->am_mnt; - if (!mf) - continue; - -#ifdef HAVE_FS_AUTOFS - if (mf->mf_flags & MFF_IS_AUTOFS && mp->am_autofs_ttl != NEVER) { - if (now >= mp->am_autofs_ttl) - autofs_timeout_mp(mp); - t = smallest_t(t, mp->am_autofs_ttl); - } -#endif /* HAVE_FS_AUTOFS */ - - if (mp->am_flags & AMF_NOTIMEOUT) - continue; - - /* - * Don't delete last reference to a restarted filesystem. - */ - if ((mf->mf_flags & MFF_RSTKEEP) && mf->mf_refc == 1) - continue; - - /* - * If there is action on this filesystem then ignore it - */ - if (!(mf->mf_flags & IGNORE_FLAGS)) { - int expired = 0; - mf->mf_flags &= ~MFF_WANTTIMO; - if (now >= mp->am_ttl) { - if (!backoff) { - expired = 1; - - /* - * Move the ttl forward to avoid thrashing effects - * on the next call to timeout! - */ - /* sun's -tw option */ - if (mp->am_timeo_w < 4 * gopt.am_timeo_w) - mp->am_timeo_w += gopt.am_timeo_w; - mp->am_ttl = now + mp->am_timeo_w; - - } else { - /* - * Just backoff this unmount for - * a couple of seconds to avoid - * many multiple unmounts being - * started in parallel. - */ - mp->am_ttl = now + backoff + 1; - } - } - - /* - * If the next ttl is smallest, use that - */ - t = smallest_t(t, mp->am_ttl); - - if (!mp->am_child && mf->mf_error >= 0 && expired) { - /* - * If the unmount was backgrounded then - * bump the backoff counter. - */ - if (unmount_mp(mp)) { - backoff = 2; - } - } - } else if (mf->mf_flags & MFF_UNMOUNTING) { - mf->mf_flags |= MFF_WANTTIMO; - } - } - - if (t == NEVER) { - dlog("No further timeouts"); - t = now + ONE_HOUR; - } - - /* - * Sanity check to avoid runaways. - * Absolutely should never get this but - * if you do without this trap amd will thrash. - */ - if (t <= now) { - t = now + 6; /* XXX */ - plog(XLOG_ERROR, "Got a zero interval in timeout_mp()!"); - } - - /* - * XXX - when shutting down, make things happen faster - */ - if ((int) amd_state >= (int) Finishing) - t = now + 1; - dlog("Next mount timeout in %lds", (long) (t - now)); - - timeout_mp_id = timeout(t - now, timeout_mp, 0); -} - - -/* - * Cause timeout_mp to be called soonest - */ -void -reschedule_timeout_mp(void) -{ - if (timeout_mp_id) - untimeout(timeout_mp_id); - timeout_mp_id = timeout(0, timeout_mp, 0); -} diff --git a/contrib/amd/amd/mapc.c b/contrib/amd/amd/mapc.c deleted file mode 100644 index d7efdbcfd217..000000000000 --- a/contrib/amd/amd/mapc.c +++ /dev/null @@ -1,1192 +0,0 @@ -/* - * Copyright (c) 1997-2006 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 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. - * - * - * File: am-utils/amd/mapc.c - * - */ - -/* - * Mount map cache - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* - * Make a duplicate reference to an existing map - */ -#define mapc_dup(m) ((m)->refc++, (m)) - -/* - * Map cache types - * default, none, incremental, all, regexp - * MAPC_RE implies MAPC_ALL and must be numerically - * greater. - */ -#define MAPC_DFLT 0x000 -#define MAPC_NONE 0x001 -#define MAPC_INC 0x002 -#define MAPC_ROOT 0x004 -#define MAPC_ALL 0x010 -#define MAPC_CACHE_MASK 0x0ff -#define MAPC_SYNC 0x100 - -#ifdef HAVE_REGEXEC -# define MAPC_RE 0x020 -# define MAPC_ISRE(m) ((m)->alloc == MAPC_RE) -#else /* not HAVE_REGEXEC */ -# define MAPC_ISRE(m) FALSE -#endif /* not HAVE_REGEXEC */ - -/* - * Lookup recursion - */ -#define MREC_FULL 2 -#define MREC_PART 1 -#define MREC_NONE 0 - -static struct opt_tab mapc_opt[] = -{ - {"all", MAPC_ALL}, - {"default", MAPC_DFLT}, - {"inc", MAPC_INC}, - {"mapdefault", MAPC_DFLT}, - {"none", MAPC_NONE}, -#ifdef HAVE_REGEXEC - {"re", MAPC_RE}, - {"regexp", MAPC_RE}, -#endif /* HAVE_REGEXEC */ - {"sync", MAPC_SYNC}, - {0, 0} -}; - -/* - * Wildcard key - */ -static char wildcard[] = "*"; - -/* - * Map type - */ -typedef struct map_type map_type; -struct map_type { - char *name; /* Name of this map type */ - init_fn *init; /* Initialization */ - reload_fn *reload; /* Reload or fill */ - isup_fn *isup; /* Is service up or not? (1=up, 0=down) */ - search_fn *search; /* Search for new entry */ - mtime_fn *mtime; /* Find modify time */ - int def_alloc; /* Default allocation mode */ -}; - -/* - * Map for root node - */ -static mnt_map *root_map; - -/* - * List of known maps - */ -qelem map_list_head = {&map_list_head, &map_list_head}; - -/* - * Configuration - */ - -/* forward definitions */ -static const char *get_full_path(const char *map, const char *path, const char *type); -static int mapc_meta_search(mnt_map *, char *, char **, int); -static void mapc_sync(mnt_map *); -static void mapc_clear(mnt_map *); - -/* ROOT MAP */ -static int root_init(mnt_map *, char *, time_t *); - -/* ERROR MAP */ -static int error_init(mnt_map *, char *, time_t *); -static int error_reload(mnt_map *, char *, add_fn *); -static int error_search(mnt_map *, char *, char *, char **, time_t *); -static int error_mtime(mnt_map *, char *, time_t *); - -/* PASSWD MAPS */ -#ifdef HAVE_MAP_PASSWD -extern int passwd_init(mnt_map *, char *, time_t *); -extern int passwd_search(mnt_map *, char *, char *, char **, time_t *); -#endif /* HAVE_MAP_PASSWD */ - -/* HESIOD MAPS */ -#ifdef HAVE_MAP_HESIOD -extern int amu_hesiod_init(mnt_map *, char *map, time_t *tp); -extern int hesiod_isup(mnt_map *, char *); -extern int hesiod_search(mnt_map *, char *, char *, char **, time_t *); -#endif /* HAVE_MAP_HESIOD */ - -/* LDAP MAPS */ -#ifdef HAVE_MAP_LDAP -extern int amu_ldap_init(mnt_map *, char *map, time_t *tp); -extern int amu_ldap_search(mnt_map *, char *, char *, char **, time_t *); -extern int amu_ldap_mtime(mnt_map *, char *, time_t *); -#endif /* HAVE_MAP_LDAP */ - -/* UNION MAPS */ -#ifdef HAVE_MAP_UNION -extern int union_init(mnt_map *, char *, time_t *); -extern int union_search(mnt_map *, char *, char *, char **, time_t *); -extern int union_reload(mnt_map *, char *, add_fn *); -#endif /* HAVE_MAP_UNION */ - -/* Network Information Service PLUS (NIS+) */ -#ifdef HAVE_MAP_NISPLUS -extern int nisplus_init(mnt_map *, char *, time_t *); -extern int nisplus_reload(mnt_map *, char *, add_fn *); -extern int nisplus_search(mnt_map *, char *, char *, char **, time_t *); -extern int nisplus_mtime(mnt_map *, char *, time_t *); -#endif /* HAVE_MAP_NISPLUS */ - -/* Network Information Service (YP, Yellow Pages) */ -#ifdef HAVE_MAP_NIS -extern int nis_init(mnt_map *, char *, time_t *); -extern int nis_reload(mnt_map *, char *, add_fn *); -extern int nis_isup(mnt_map *, char *); -extern int nis_search(mnt_map *, char *, char *, char **, time_t *); -extern int nis_mtime(mnt_map *, char *, time_t *); -#endif /* HAVE_MAP_NIS */ - -/* NDBM MAPS */ -#ifdef HAVE_MAP_NDBM -extern int ndbm_init(mnt_map *, char *, time_t *); -extern int ndbm_search(mnt_map *, char *, char *, char **, time_t *); -extern int ndbm_mtime(mnt_map *, char *, time_t *); -#endif /* HAVE_MAP_NDBM */ - -/* EXECUTABLE MAPS */ -#ifdef HAVE_MAP_EXEC -extern int exec_init(mnt_map *, char *, time_t *); -extern int exec_search(mnt_map *, char *, char *, char **, time_t *); -#endif /* HAVE_MAP_EXEC */ - -/* FILE MAPS */ -#ifdef HAVE_MAP_FILE -extern int file_init_or_mtime(mnt_map *, char *, time_t *); -extern int file_reload(mnt_map *, char *, add_fn *); -extern int file_search(mnt_map *, char *, char *, char **, time_t *); -#endif /* HAVE_MAP_FILE */ - - -/* note that the choice of MAPC_{INC,ALL} will affect browsable_dirs */ -static map_type maptypes[] = -{ - { - "root", - root_init, - error_reload, - NULL, /* isup function */ - error_search, - error_mtime, - MAPC_ROOT - }, -#ifdef HAVE_MAP_PASSWD - { - "passwd", - passwd_init, - error_reload, - NULL, /* isup function */ - passwd_search, - error_mtime, - MAPC_INC - }, -#endif /* HAVE_MAP_PASSWD */ -#ifdef HAVE_MAP_HESIOD - { - "hesiod", - amu_hesiod_init, - error_reload, - hesiod_isup, /* is Hesiod up or not? */ - hesiod_search, - error_mtime, - MAPC_INC - }, -#endif /* HAVE_MAP_HESIOD */ -#ifdef HAVE_MAP_LDAP - { - "ldap", - amu_ldap_init, - error_reload, - NULL, /* isup function */ - amu_ldap_search, - amu_ldap_mtime, - MAPC_INC - }, -#endif /* HAVE_MAP_LDAP */ -#ifdef HAVE_MAP_UNION - { - "union", - union_init, - union_reload, - NULL, /* isup function */ - union_search, - error_mtime, - MAPC_ALL - }, -#endif /* HAVE_MAP_UNION */ -#ifdef HAVE_MAP_NISPLUS - { - "nisplus", - nisplus_init, - nisplus_reload, - NULL, /* isup function */ - nisplus_search, - nisplus_mtime, - MAPC_INC - }, -#endif /* HAVE_MAP_NISPLUS */ -#ifdef HAVE_MAP_NIS - { - "nis", - nis_init, - nis_reload, - nis_isup, /* is NIS up or not? */ - nis_search, - nis_mtime, - MAPC_ALL - }, -#endif /* HAVE_MAP_NIS */ -#ifdef HAVE_MAP_NDBM - { - "ndbm", - ndbm_init, - error_reload, - NULL, /* isup function */ - ndbm_search, - ndbm_mtime, - MAPC_INC - }, -#endif /* HAVE_MAP_NDBM */ -#ifdef HAVE_MAP_FILE - { - "file", - file_init_or_mtime, - file_reload, - NULL, /* isup function */ - file_search, - file_init_or_mtime, - MAPC_ALL - }, -#endif /* HAVE_MAP_FILE */ -#ifdef HAVE_MAP_EXEC - { - "exec", - exec_init, - error_reload, - NULL, /* isup function */ - exec_search, - error_mtime, - MAPC_INC - }, -#endif /* HAVE_MAP_EXEC */ - { - "error", - error_init, - error_reload, - NULL, /* isup function */ - error_search, - error_mtime, - MAPC_NONE - }, -}; - - -/* - * Hash function - */ -static u_int -kvhash_of(char *key) -{ - u_int i, j; - - for (i = 0; (j = *key++); i += j) ; - - return i % NKVHASH; -} - - -void -mapc_showtypes(char *buf, size_t l) -{ - map_type *mt=NULL, *lastmt; - int linesize = 0, i; - - i = sizeof(maptypes) / sizeof(maptypes[0]); - lastmt = maptypes + i; - buf[0] = '\0'; - for (mt = maptypes; mt < lastmt; mt++) { - xstrlcat(buf, mt->name, l); - if (mt == (lastmt-1)) - break; /* if last one, don't do xstrlcat's that follows */ - linesize += strlen(mt->name); - if (--i > 0) { - xstrlcat(buf, ", ", l); - linesize += 2; - } - if (linesize > 54) { - linesize = 0; - xstrlcat(buf, "\n\t\t ", l); - } - } -} - - -/* - * Check if a map of a certain type exists. - * Return 1 (true) if exists, 0 (false) if not. - */ -int -mapc_type_exists(const char *type) -{ - map_type *mt; - - if (!type) - return 0; - for (mt = maptypes; - mt < maptypes + sizeof(maptypes) / sizeof(maptypes[0]); - mt++) { - if (STREQ(type, mt->name)) - return 1; - } - return 0; /* not found anywhere */ -} - - -/* - * Add key and val to the map m. - * key and val are assumed to be safe copies - */ -void -mapc_add_kv(mnt_map *m, char *key, char *val) -{ - kv **h; - kv *n; - int hash = kvhash_of(key); -#ifdef HAVE_REGEXEC - regex_t re; -#endif /* HAVE_REGEXEC */ - - dlog("add_kv: %s -> %s", key, val); - -#ifdef HAVE_REGEXEC - if (MAPC_ISRE(m)) { - char pattern[MAXPATHLEN]; - int retval; - - /* - * Make sure the string is bound to the start and end - */ - xsnprintf(pattern, sizeof(pattern), "^%s$", key); - retval = regcomp(&re, pattern, REG_ICASE); - if (retval != 0) { - char errstr[256]; - - /* XXX: this code was recently ported, and must be tested -Erez */ - errstr[0] = '\0'; - regerror(retval, &re, errstr, 256); - plog(XLOG_USER, "error compiling RE \"%s\": %s", pattern, errstr); - return; - } - } -#endif /* HAVE_REGEXEC */ - - h = &m->kvhash[hash]; - n = ALLOC(struct kv); - n->key = key; -#ifdef HAVE_REGEXEC - memcpy(&n->re, &re, sizeof(regex_t)); -#endif /* HAVE_REGEXEC */ - n->val = val; - n->next = *h; - *h = n; -} - - -static void -mapc_repl_kv(mnt_map *m, char *key, char *val) -{ - kv *k; - - /* - * Compute the hash table offset - */ - k = m->kvhash[kvhash_of(key)]; - - /* - * Scan the linked list for the key - */ - while (k && !FSTREQ(k->key, key)) - k = k->next; - - if (k) { - XFREE(k->val); - k->val = val; - } else { - mapc_add_kv(m, key, val); - } -} - - -/* - * Search a map for a key. - * Calls map specific search routine. - * While map is out of date, keep re-syncing. - */ -static int -search_map(mnt_map *m, char *key, char **valp) -{ - int rc; - - do { - rc = (*m->search) (m, m->map_name, key, valp, &m->modify); - if (rc < 0) { - plog(XLOG_MAP, "Re-synchronizing cache for map %s", m->map_name); - mapc_sync(m); - } - } while (rc < 0); - - return rc; -} - - -/* - * Do a wildcard lookup in the map and - * save the result. - */ -static void -mapc_find_wildcard(mnt_map *m) -{ - /* - * Attempt to find the wildcard entry - */ - int rc = search_map(m, wildcard, &m->wildcard); - - if (rc != 0) - m->wildcard = 0; -} - - -/* - * Do a map reload. - * Attempt to reload without losing current data by switching the hashes - * round. - * If reloading was needed and succeeded, return 1; else return 0. - */ -static int -mapc_reload_map(mnt_map *m) -{ - int error, ret = 0; - kv *maphash[NKVHASH], *tmphash[NKVHASH]; - time_t t; - - error = (*m->mtime) (m, m->map_name, &t); - if (error) { - t = m->modify; - } - - /* - * skip reloading maps that have not been modified, unless - * amq -f was used (do_mapc_reload is 0) - */ - if (m->reloads != 0 && do_mapc_reload != 0) { - if (t <= m->modify) { - plog(XLOG_INFO, "reload of map %s is not needed (in sync)", m->map_name); - dlog("map %s last load time is %d, last modify time is %d", - m->map_name, (int) m->modify, (int) t); - return ret; - } - } - - /* copy the old hash and zero the map */ - memcpy((voidp) maphash, (voidp) m->kvhash, sizeof(m->kvhash)); - memset((voidp) m->kvhash, 0, sizeof(m->kvhash)); - - dlog("calling map reload on %s", m->map_name); - error = (*m->reload) (m, m->map_name, mapc_add_kv); - if (error) { - if (m->reloads == 0) - plog(XLOG_FATAL, "first time load of map %s failed!", m->map_name); - else - plog(XLOG_ERROR, "reload of map %s failed - using old values", - m->map_name); - mapc_clear(m); - memcpy((voidp) m->kvhash, (voidp) maphash, sizeof(m->kvhash)); - } else { - if (m->reloads++ == 0) - plog(XLOG_INFO, "first time load of map %s succeeded", m->map_name); - else - plog(XLOG_INFO, "reload #%d of map %s succeeded", - m->reloads, m->map_name); - memcpy((voidp) tmphash, (voidp) m->kvhash, sizeof(m->kvhash)); - memcpy((voidp) m->kvhash, (voidp) maphash, sizeof(m->kvhash)); - mapc_clear(m); - memcpy((voidp) m->kvhash, (voidp) tmphash, sizeof(m->kvhash)); - m->modify = t; - ret = 1; - } - m->wildcard = 0; - - dlog("calling mapc_search for wildcard"); - error = mapc_search(m, wildcard, &m->wildcard); - if (error) - m->wildcard = 0; - return ret; -} - - -/* - * Create a new map - */ -static mnt_map * -mapc_create(char *map, char *opt, const char *type) -{ - mnt_map *m = ALLOC(struct mnt_map); - map_type *mt; - time_t modify = 0; - int alloc = 0; - - cmdoption(opt, mapc_opt, &alloc); - - /* - * If using a configuration file, and the map_type is defined, then look - * for it, in the maptypes array. If found, initialize the map using that - * map_type. If not found, return error. If no map_type was defined, - * default to cycling through all maptypes. - */ - if (use_conf_file && type) { - /* find what type of map this one is */ - for (mt = maptypes; - mt < maptypes + sizeof(maptypes) / sizeof(maptypes[0]); - mt++) { - if (STREQ(type, mt->name)) { - plog(XLOG_INFO, "initializing amd.conf map %s of type %s", map, type); - if ((*mt->init) (m, map, &modify) == 0) { - break; - } else { - plog(XLOG_ERROR, "failed to initialize map %s", map); - error_init(m, map, &modify); - break; - } - } - } /* end of "for (mt =" loop */ - - } else { /* cycle through all known maptypes */ - - /* - * not using amd conf file or using it by w/o specifying map type - */ - for (mt = maptypes; - mt < maptypes + sizeof(maptypes) / sizeof(maptypes[0]); - mt++) { - dlog("trying to initialize map %s of type %s ...", map, mt->name); - if ((*mt->init) (m, map, &modify) == 0) { - break; - } - } - } /* end of "if (use_conf_file && (colpos = strchr ..." statement */ - - /* assert: mt in maptypes */ - - m->flags = alloc & ~MAPC_CACHE_MASK; - alloc &= MAPC_CACHE_MASK; - - if (alloc == MAPC_DFLT) - alloc = mt->def_alloc; - - switch (alloc) { - default: - plog(XLOG_USER, "Ambiguous map cache type \"%s\"; using \"inc\"", opt); - alloc = MAPC_INC; - /* fall-through... */ - case MAPC_NONE: - case MAPC_INC: - case MAPC_ROOT: - break; - - case MAPC_ALL: - /* - * If there is no support for reload and it was requested - * then back off to incremental instead. - */ - if (mt->reload == error_reload) { - plog(XLOG_WARNING, "Map type \"%s\" does not support cache type \"all\"; using \"inc\"", mt->name); - alloc = MAPC_INC; - } - break; - -#ifdef HAVE_REGEXEC - case MAPC_RE: - if (mt->reload == error_reload) { - plog(XLOG_WARNING, "Map type \"%s\" does not support cache type \"re\"", mt->name); - mt = &maptypes[sizeof(maptypes) / sizeof(maptypes[0]) - 1]; - /* assert: mt->name == "error" */ - } - break; -#endif /* HAVE_REGEXEC */ - } - - dlog("Map for %s coming from maptype %s", map, mt->name); - - m->alloc = alloc; - m->reload = mt->reload; - m->isup = mt->isup; - m->modify = modify; - m->search = alloc >= MAPC_ALL ? error_search : mt->search; - m->mtime = mt->mtime; - memset((voidp) m->kvhash, 0, sizeof(m->kvhash)); - m->map_name = strdup(map); - m->refc = 1; - m->wildcard = 0; - m->reloads = 0; - /* Unfortunately with current code structure, this cannot be initialized here */ - m->cfm = NULL; - - /* - * synchronize cache with reality - */ - mapc_sync(m); - - return m; -} - - -/* - * Free the cached data in a map - */ -static void -mapc_clear(mnt_map *m) -{ - int i; - - /* - * For each of the hash slots, chain - * along free'ing the data. - */ - for (i = 0; i < NKVHASH; i++) { - kv *k = m->kvhash[i]; - while (k) { - kv *n = k->next; - XFREE(k->key); - if (k->val) - XFREE(k->val); - XFREE(k); - k = n; - } - } - - /* - * Zero the hash slots - */ - memset((voidp) m->kvhash, 0, sizeof(m->kvhash)); - - /* - * Free the wildcard if it exists - */ - if (m->wildcard) { - XFREE(m->wildcard); - m->wildcard = 0; - } -} - - -/* - * Find a map, or create one if it does not exist - */ -mnt_map * -mapc_find(char *map, char *opt, const char *maptype) -{ - mnt_map *m; - - /* - * Search the list of known maps to see if - * it has already been loaded. If it is found - * then return a duplicate reference to it. - * Otherwise make a new map as required and - * add it to the list of maps - */ - ITER(m, mnt_map, &map_list_head) - if (STREQ(m->map_name, map)) - return mapc_dup(m); - m = mapc_create(map, opt, maptype); - ins_que(&m->hdr, &map_list_head); - - return m; -} - - -/* - * Free a map. - */ -void -mapc_free(opaque_t arg) -{ - mnt_map *m = (mnt_map *) arg; - - /* - * Decrement the reference count. - * If the reference count hits zero - * then throw the map away. - */ - if (m && --m->refc == 0) { - mapc_clear(m); - XFREE(m->map_name); - rem_que(&m->hdr); - XFREE(m); - } -} - - -/* - * Search the map for the key. Put a safe (malloc'ed) copy in *pval or - * return an error code - */ -static int -mapc_meta_search(mnt_map *m, char *key, char **pval, int recurse) -{ - int error = 0; - kv *k = 0; - - /* - * Firewall - */ - if (!m) { - plog(XLOG_ERROR, "Null map request for %s", key); - return ENOENT; - } - - if (m->flags & MAPC_SYNC) { - /* - * Get modify time... - */ - time_t t; - error = (*m->mtime) (m, m->map_name, &t); - if (error || t > m->modify) { - plog(XLOG_INFO, "Map %s is out of date", m->map_name); - mapc_sync(m); - } - } - - if (!MAPC_ISRE(m)) { - /* - * Compute the hash table offset - */ - k = m->kvhash[kvhash_of(key)]; - - /* - * Scan the linked list for the key - */ - while (k && !FSTREQ(k->key, key)) - k = k->next; - - } - -#ifdef HAVE_REGEXEC - else if (recurse == MREC_FULL) { - /* - * Try for an RE match against the entire map. - * Note that this will be done in a "random" - * order. - */ - int i; - - for (i = 0; i < NKVHASH; i++) { - k = m->kvhash[i]; - while (k) { - int retval; - - /* XXX: this code was recently ported, and must be tested -Erez */ - retval = regexec(&k->re, key, 0, 0, 0); - if (retval == 0) { /* succeeded */ - break; - } else { /* failed to match, log error */ - char errstr[256]; - - errstr[0] = '\0'; - regerror(retval, &k->re, errstr, 256); - plog(XLOG_USER, "error matching RE \"%s\" against \"%s\": %s", - key, k->key, errstr); - } - k = k->next; - } - if (k) - break; - } - } -#endif /* HAVE_REGEXEC */ - - /* - * If found then take a copy - */ - if (k) { - if (k->val) - *pval = strdup(k->val); - else - error = ENOENT; - } else if (m->alloc >= MAPC_ALL) { - /* - * If the entire map is cached then this - * key does not exist. - */ - error = ENOENT; - } else { - /* - * Otherwise search the map. If we are - * in incremental mode then add the key - * to the cache. - */ - error = search_map(m, key, pval); - if (!error && m->alloc == MAPC_INC) - mapc_add_kv(m, strdup(key), strdup(*pval)); - } - - /* - * If an error, and a wildcard exists, - * and the key is not internal then - * return a copy of the wildcard. - */ - if (error > 0) { - if (recurse == MREC_FULL && !MAPC_ISRE(m)) { - char wildname[MAXPATHLEN]; - char *subp; - if (*key == '/') - return error; - /* - * Keep chopping sub-directories from the RHS - * and replacing with "/ *" and repeat the lookup. - * For example: - * "src/gnu/gcc" -> "src / gnu / *" -> "src / *" - */ - xstrlcpy(wildname, key, sizeof(wildname)); - while (error && (subp = strrchr(wildname, '/'))) { - /* - * sizeof space left in subp is sizeof wildname minus what's left - * after the strchr above returned a pointer inside wildname into - * subp. - */ - xstrlcpy(subp, "/*", sizeof(wildname) - (subp - wildname)); - dlog("mapc recurses on %s", wildname); - error = mapc_meta_search(m, wildname, pval, MREC_PART); - if (error) - *subp = 0; - } - - if (error > 0 && m->wildcard) { - *pval = strdup(m->wildcard); - error = 0; - } - } - } - return error; -} - - -int -mapc_search(mnt_map *m, char *key, char **pval) -{ - return mapc_meta_search(m, key, pval, MREC_FULL); -} - - -/* - * Get map cache in sync with physical representation - */ -static void -mapc_sync(mnt_map *m) -{ - int need_mtime_update = 0; - - if (m->alloc == MAPC_ROOT) - return; /* nothing to do */ - - /* do not clear map if map service is down */ - if (m->isup) { - if (!((*m->isup)(m, m->map_name))) { - plog(XLOG_ERROR, "mapc_sync: map %s is down: not clearing map", m->map_name); - return; - } - } - - if (m->alloc >= MAPC_ALL) { - /* mapc_reload_map() always works */ - need_mtime_update = mapc_reload_map(m); - } else { - mapc_clear(m); - /* - * Attempt to find the wildcard entry - */ - mapc_find_wildcard(m); - need_mtime_update = 1; /* because mapc_clear always works */ - } - - /* - * To be safe, update the mtime of the mnt_map's own node, so that the - * kernel will flush all of its cached entries. - */ - if (need_mtime_update && m->cfm) { - am_node *mp = find_ap(m->cfm->cfm_dir); - if (mp) { - clocktime(&mp->am_fattr.na_mtime); - } else { - plog(XLOG_ERROR, "cannot find map %s to update its mtime", - m->cfm->cfm_dir); - } - } -} - - -/* - * Reload all the maps - * Called when Amd gets hit by a SIGHUP. - */ -void -mapc_reload(void) -{ - mnt_map *m; - - /* - * For all the maps, - * Throw away the existing information. - * Do a reload - * Find the wildcard - */ - ITER(m, mnt_map, &map_list_head) - mapc_sync(m); -} - - -/* - * Root map. - * The root map is used to bootstrap amd. - * All the require top-level mounts are added - * into the root map and then the map is iterated - * and a lookup is done on all the mount points. - * This causes the top level mounts to be automounted. - */ -static int -root_init(mnt_map *m, char *map, time_t *tp) -{ - *tp = clocktime(NULL); - return STREQ(map, ROOT_MAP) ? 0 : ENOENT; -} - - -/* - * Add a new entry to the root map - * - * dir - directory (key) - * opts - mount options - * map - map name - * cfm - optional amd configuration file map section structure - */ -void -root_newmap(const char *dir, const char *opts, const char *map, const cf_map_t *cfm) -{ - char str[MAXPATHLEN]; - - /* - * First make sure we have a root map to talk about... - */ - if (!root_map) - root_map = mapc_find(ROOT_MAP, "mapdefault", NULL); - - /* - * Then add the entry... - */ - - /* - * Here I plug in the code to process other amd.conf options like - * map_type, search_path, and flags (browsable_dirs, mount_type). - */ - - if (cfm) { - if (map) { - xsnprintf(str, sizeof(str), - "cache:=mapdefault;type:=toplvl;mount_type:=%s;fs:=\"%s\"", - cfm->cfm_flags & CFM_MOUNT_TYPE_AUTOFS ? "autofs" : "nfs", - get_full_path(map, cfm->cfm_search_path, cfm->cfm_type)); - if (opts && opts[0] != '\0') { - xstrlcat(str, ";", sizeof(str)); - xstrlcat(str, opts, sizeof(str)); - } - if (cfm->cfm_flags & CFM_BROWSABLE_DIRS_FULL) - xstrlcat(str, ";opts:=rw,fullybrowsable", sizeof(str)); - if (cfm->cfm_flags & CFM_BROWSABLE_DIRS) - xstrlcat(str, ";opts:=rw,browsable", sizeof(str)); - if (cfm->cfm_type) { - xstrlcat(str, ";maptype:=", sizeof(str)); - xstrlcat(str, cfm->cfm_type, sizeof(str)); - } - } else { - xstrlcpy(str, opts, sizeof(str)); - } - } else { - if (map) - xsnprintf(str, sizeof(str), - "cache:=mapdefault;type:=toplvl;fs:=\"%s\";%s", - map, opts ? opts : ""); - else - xstrlcpy(str, opts, sizeof(str)); - } - mapc_repl_kv(root_map, strdup((char *)dir), strdup(str)); -} - - -int -mapc_keyiter(mnt_map *m, key_fun *fn, opaque_t arg) -{ - int i; - int c = 0; - - for (i = 0; i < NKVHASH; i++) { - kv *k = m->kvhash[i]; - while (k) { - (*fn) (k->key, arg); - k = k->next; - c++; - } - } - - return c; -} - - -/* - * Iterate on the root map and call (*fn)() on the key of all the nodes. - * Returns the number of entries in the root map. - */ -int -root_keyiter(key_fun *fn, opaque_t arg) -{ - if (root_map) { - int c = mapc_keyiter(root_map, fn, arg); - return c; - } - - return 0; -} - - -/* - * Error map - */ -static int -error_init(mnt_map *m, char *map, time_t *tp) -{ - plog(XLOG_USER, "No source data for map %s", map); - *tp = 0; - - return 0; -} - - -static int -error_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) -{ - return ENOENT; -} - - -static int -error_reload(mnt_map *m, char *map, add_fn *fn) -{ - return ENOENT; -} - - -static int -error_mtime(mnt_map *m, char *map, time_t *tp) -{ - *tp = 0; - - return 0; -} - - -/* - * Return absolute path of map, searched in a type-specific path. - * Note: uses a static buffer for returned data. - */ -static const char * -get_full_path(const char *map, const char *path, const char *type) -{ - char component[MAXPATHLEN], *str; - static char full_path[MAXPATHLEN]; - int len; - - /* for now, only file-type search paths are implemented */ - if (type && !STREQ(type, "file")) - return map; - - /* if null map, return it */ - if (!map) - return map; - - /* if map includes a '/', return it (absolute or relative path) */ - if (strchr(map, '/')) - return map; - - /* if path is empty, return map */ - if (!path) - return map; - - /* now break path into components, and search in each */ - xstrlcpy(component, path, sizeof(component)); - - str = strtok(component, ":"); - do { - xstrlcpy(full_path, str, sizeof(full_path)); - len = strlen(full_path); - if (full_path[len - 1] != '/') /* add trailing "/" if needed */ - xstrlcat(full_path, "/", sizeof(full_path)); - xstrlcat(full_path, map, sizeof(full_path)); - if (access(full_path, R_OK) == 0) - return full_path; - str = strtok(NULL, ":"); - } while (str); - - return map; /* if found nothing, return map */ -} diff --git a/contrib/amd/amd/mntfs.c b/contrib/amd/amd/mntfs.c deleted file mode 100644 index 6021838425c0..000000000000 --- a/contrib/amd/amd/mntfs.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/mntfs.c - * - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -qelem mfhead = {&mfhead, &mfhead}; - -int mntfs_allocated; - - -mntfs * -dup_mntfs(mntfs *mf) -{ - if (mf->mf_refc == 0) { - if (mf->mf_cid) - untimeout(mf->mf_cid); - mf->mf_cid = 0; - } - mf->mf_refc++; - - return mf; -} - - -static void -init_mntfs(mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts) -{ - mf->mf_ops = ops; - mf->mf_fsflags = ops->nfs_fs_flags; - mf->mf_fo = mo; - mf->mf_mount = strdup(mp); - mf->mf_info = strdup(info); - mf->mf_auto = strdup(auto_opts); - mf->mf_mopts = strdup(mopts); - mf->mf_remopts = strdup(remopts); - mf->mf_loopdev = NULL; - mf->mf_refc = 1; - mf->mf_flags = 0; - mf->mf_error = -1; - mf->mf_cid = 0; - mf->mf_private = 0; - mf->mf_prfree = 0; - - if (ops->ffserver) - mf->mf_server = (*ops->ffserver) (mf); - else - mf->mf_server = 0; -} - - -static mntfs * -alloc_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts) -{ - mntfs *mf = ALLOC(struct mntfs); - - init_mntfs(mf, ops, mo, mp, info, auto_opts, mopts, remopts); - ins_que(&mf->mf_q, &mfhead); - mntfs_allocated++; - - return mf; -} - - -/* find a matching mntfs in our list */ -mntfs * -locate_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts) -{ - mntfs *mf; - - dlog("Locating mntfs reference to (%s,%s)", mp, info); - - ITER(mf, mntfs, &mfhead) { - /* - * For backwards compatibility purposes, we treat already-mounted - * filesystems differently and only require a match of their mount point, - * not of their server info. After all, there is little we can do if - * the user asks us to mount two different things onto the same mount: one - * will always cover the other one. - */ - if (STREQ(mf->mf_mount, mp) && - ((mf->mf_flags & MFF_MOUNTED && !(mf->mf_fsflags & FS_DIRECT)) - || (STREQ(mf->mf_info, info) && mf->mf_ops == ops))) { - /* - * Handle cases where error ops are involved - */ - if (ops == &amfs_error_ops) { - /* - * If the existing ops are not amfs_error_ops - * then continue... - */ - if (mf->mf_ops != &amfs_error_ops) - continue; - return dup_mntfs(mf); - } - - dlog("mf->mf_flags = %#x", mf->mf_flags); - mf->mf_fo = mo; - if ((mf->mf_flags & MFF_RESTART) && amd_state < Finishing) { - /* - * Restart a previously mounted filesystem. - */ - dlog("Restarting filesystem %s", mf->mf_mount); - - /* - * If we are restarting an amd internal filesystem, - * we need to initialize it a bit. - * - * We know it's internal because it is marked as toplvl. - */ - if (mf->mf_ops == &amfs_toplvl_ops) { - mf->mf_ops = ops; - mf->mf_info = strealloc(mf->mf_info, info); - ops->mounted(mf); /* XXX: not right, but will do for now */ - } - - return mf; - } - - if (!(mf->mf_flags & (MFF_MOUNTED | MFF_MOUNTING | MFF_UNMOUNTING))) { - fserver *fs; - mf->mf_flags &= ~MFF_ERROR; - mf->mf_error = -1; - mf->mf_auto = strealloc(mf->mf_auto, auto_opts); - mf->mf_mopts = strealloc(mf->mf_mopts, mopts); - mf->mf_remopts = strealloc(mf->mf_remopts, remopts); - mf->mf_info = strealloc(mf->mf_info, info); - - if (mf->mf_private && mf->mf_prfree) { - mf->mf_prfree(mf->mf_private); - mf->mf_private = 0; - } - - fs = ops->ffserver ? (*ops->ffserver) (mf) : (fserver *) NULL; - if (mf->mf_server) - free_srvr(mf->mf_server); - mf->mf_server = fs; - } - return dup_mntfs(mf); - } /* end of "if (STREQ(mf-> ..." */ - } /* end of ITER */ - - return 0; -} - - -/* find a matching mntfs in our list, create a new one if none is found */ -mntfs * -find_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts) -{ - mntfs *mf = locate_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts); - if (mf) - return mf; - - return alloc_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts); -} - - -mntfs * -new_mntfs(void) -{ - return alloc_mntfs(&amfs_error_ops, (am_opts *) 0, "//nil//", ".", "", "", ""); -} - - -static void -uninit_mntfs(mntfs *mf) -{ - if (mf->mf_auto) - XFREE(mf->mf_auto); - if (mf->mf_mopts) - XFREE(mf->mf_mopts); - if (mf->mf_remopts) - XFREE(mf->mf_remopts); - if (mf->mf_info) - XFREE(mf->mf_info); - if (mf->mf_private && mf->mf_prfree) - (*mf->mf_prfree) (mf->mf_private); - - if (mf->mf_mount) - XFREE(mf->mf_mount); - - /* - * Clean up the file server - */ - if (mf->mf_server) - free_srvr(mf->mf_server); - - /* - * Don't do a callback on this mount - */ - if (mf->mf_cid) { - untimeout(mf->mf_cid); - mf->mf_cid = 0; - } -} - - -static void -discard_mntfs(voidp v) -{ - mntfs *mf = v; - - rem_que(&mf->mf_q); - - /* - * Free memory - */ - uninit_mntfs(mf); - XFREE(mf); - - --mntfs_allocated; -} - - -void -flush_mntfs(void) -{ - mntfs *mf; - - mf = AM_FIRST(mntfs, &mfhead); - while (mf != HEAD(mntfs, &mfhead)) { - mntfs *mf2 = mf; - mf = NEXT(mntfs, mf); - if (mf2->mf_refc == 0 && mf2->mf_cid) - discard_mntfs(mf2); - } -} - - -void -free_mntfs(opaque_t arg) -{ - mntfs *mf = (mntfs *) arg; - - dlog("free_mntfs <%s> type %s mf_refc %d flags %x", - mf->mf_mount, mf->mf_ops->fs_type, mf->mf_refc, mf->mf_flags); - - /* - * We shouldn't ever be called to free something that has - * a non-positive refcount. Something is badly wrong if - * we have been! Ignore the request for now... - */ - if (mf->mf_refc <= 0) { - plog(XLOG_ERROR, "IGNORING free_mntfs for <%s>: refc %d, flags %x (bug?)", - mf->mf_mount, mf->mf_refc, mf->mf_flags); - return; - } - - /* don't discard last reference of a restarted/kept mntfs */ - if (mf->mf_refc == 1 && mf->mf_flags & MFF_RSTKEEP) { - plog(XLOG_ERROR, "IGNORING free_mntfs for <%s>: refc %d, flags %x (restarted)", - mf->mf_mount, mf->mf_refc, mf->mf_flags); - return; - } - - if (--mf->mf_refc == 0) { - if (mf->mf_flags & MFF_MOUNTED) { - int quoted; - mf->mf_flags &= ~MFF_MOUNTED; - - /* - * Record for posterity - */ - quoted = strchr(mf->mf_info, ' ') != 0; /* cheap */ - plog(XLOG_INFO, "%s%s%s %sed fstype %s from %s", - quoted ? "\"" : "", - mf->mf_info, - quoted ? "\"" : "", - mf->mf_error ? "discard" : "unmount", - mf->mf_ops->fs_type, mf->mf_mount); - } - - if (mf->mf_fsflags & FS_DISCARD) { - dlog("Immediately discarding mntfs for %s", mf->mf_mount); - discard_mntfs(mf); - - } else { - - if (mf->mf_flags & MFF_RESTART) { - dlog("Discarding remount hook for %s", mf->mf_mount); - } else { - dlog("Discarding last mntfs reference to %s fstype %s", - mf->mf_mount, mf->mf_ops->fs_type); - } - if (mf->mf_flags & (MFF_MOUNTED | MFF_MOUNTING | MFF_UNMOUNTING)) - dlog("mntfs reference for %s still active", mf->mf_mount); - mf->mf_cid = timeout(ALLOWED_MOUNT_TIME, discard_mntfs, (voidp) mf); - } - } -} - - -mntfs * -realloc_mntfs(mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts) -{ - mntfs *mf2; - - if (mf->mf_refc == 1 && - mf->mf_flags & MFF_RESTART && - STREQ(mf->mf_mount, mp)) { - /* - * If we are inheriting then just return - * the same node... - */ - return mf; - } - - /* - * Re-use the existing mntfs if it is mounted. - * This traps a race in nfsx. - */ - if (mf->mf_ops != &amfs_error_ops && - (mf->mf_flags & MFF_MOUNTED) && - !FSRV_ISDOWN(mf->mf_server)) { - mf->mf_fo = mo; - return mf; - } - - mf2 = find_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts); - free_mntfs(mf); - return mf2; -} diff --git a/contrib/amd/amd/nfs_prot_svc.c b/contrib/amd/amd/nfs_prot_svc.c deleted file mode 100644 index 0dd6992cf9e7..000000000000 --- a/contrib/amd/amd/nfs_prot_svc.c +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright (c) 1997-2006 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 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. - * - * - * File: am-utils/amd/nfs_prot_svc.c - * - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* external definitions */ -extern voidp nfsproc_null_2_svc(voidp, struct svc_req *); -extern nfsattrstat *nfsproc_getattr_2_svc(am_nfs_fh *, struct svc_req *); -extern nfsattrstat *nfsproc_setattr_2_svc(nfssattrargs *, struct svc_req *); -extern voidp nfsproc_root_2_svc(voidp, struct svc_req *); -extern nfsdiropres *nfsproc_lookup_2_svc(nfsdiropargs *, struct svc_req *); -extern nfsreadlinkres *nfsproc_readlink_2_svc(am_nfs_fh *, struct svc_req *); -extern nfsreadres *nfsproc_read_2_svc(nfsreadargs *, struct svc_req *); -extern voidp nfsproc_writecache_2_svc(voidp, struct svc_req *); -extern nfsattrstat *nfsproc_write_2_svc(nfswriteargs *, struct svc_req *); -extern nfsdiropres *nfsproc_create_2_svc(nfscreateargs *, struct svc_req *); -extern nfsstat *nfsproc_remove_2_svc(nfsdiropargs *, struct svc_req *); -extern nfsstat *nfsproc_rename_2_svc(nfsrenameargs *, struct svc_req *); -extern nfsstat *nfsproc_link_2_svc(nfslinkargs *, struct svc_req *); -extern nfsstat *nfsproc_symlink_2_svc(nfssymlinkargs *, struct svc_req *); -extern nfsdiropres *nfsproc_mkdir_2_svc(nfscreateargs *, struct svc_req *); -extern nfsstat *nfsproc_rmdir_2_svc(nfsdiropargs *, struct svc_req *); -extern nfsreaddirres *nfsproc_readdir_2_svc(nfsreaddirargs *, struct svc_req *); -extern nfsstatfsres *nfsproc_statfs_2_svc(am_nfs_fh *, struct svc_req *); - -/* global variables */ -SVCXPRT *current_transp; - -/* typedefs */ -typedef char *(*nfssvcproc_t)(voidp, struct svc_req *); - - -void -nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp) -{ - union { - am_nfs_fh nfsproc_getattr_2_arg; - nfssattrargs nfsproc_setattr_2_arg; - nfsdiropargs nfsproc_lookup_2_arg; - am_nfs_fh nfsproc_readlink_2_arg; - nfsreadargs nfsproc_read_2_arg; - nfswriteargs nfsproc_write_2_arg; - nfscreateargs nfsproc_create_2_arg; - nfsdiropargs nfsproc_remove_2_arg; - nfsrenameargs nfsproc_rename_2_arg; - nfslinkargs nfsproc_link_2_arg; - nfssymlinkargs nfsproc_symlink_2_arg; - nfscreateargs nfsproc_mkdir_2_arg; - nfsdiropargs fsproc_rmdir_2_arg; - nfsreaddirargs nfsproc_readdir_2_arg; - am_nfs_fh nfsproc_statfs_2_arg; - } argument; - char *result; - xdrproc_t xdr_argument, xdr_result; - nfssvcproc_t local; - -#ifdef HAVE_TRANSPORT_TYPE_TLI - /* - * On TLI systems we don't use an INET network type, but a "ticlts" (see - * /etc/netconfig and conf/transp_tli.c:create_nfs_service). This means - * that packets could only come from the loopback interface, and we don't - * need to check them and filter possibly spoofed packets. Therefore we - * only need to check if the UID caller is correct. - */ -# ifdef HAVE___RPC_GET_LOCAL_UID - uid_t u; - /* extern definition for an internal libnsl function */ - extern int __rpc_get_local_uid(SVCXPRT *transp, uid_t *uid); - if (__rpc_get_local_uid(transp, &u) >= 0 && u != 0) { - plog(XLOG_WARNING, "ignoring request from UID %ld, must be 0", (long) u); - return; - } -# else /* not HAVE___RPC_GET_LOCAL_UID */ - dlog("cannot verify local uid for rpc request"); -# endif /* HAVE___RPC_GET_LOCAL_UID */ -#else /* not HAVE_TRANPORT_TYPE_TLI */ - struct sockaddr_in *sinp; - char dq[20], dq2[28]; - sinp = amu_svc_getcaller(rqstp->rq_xprt); -# ifdef MNT2_NFS_OPT_RESVPORT - /* Verify that the request comes from a reserved port */ - if (sinp && - ntohs(sinp->sin_port) >= IPPORT_RESERVED && - !(gopt.flags & CFM_NFS_INSECURE_PORT)) { - plog(XLOG_WARNING, "ignoring request from %s:%u, port not reserved", - inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr), - ntohs(sinp->sin_port)); - return; - } -# endif /* MNT2_NFS_OPT_RESVPORT */ - /* if the address does not match, ignore the request */ - if (sinp && (sinp->sin_addr.s_addr != myipaddr.s_addr)) { - if (gopt.flags & CFM_NFS_ANY_INTERFACE) { - if (!is_interface_local(sinp->sin_addr.s_addr)) { - plog(XLOG_WARNING, "ignoring request from %s:%u, not a local interface", - inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr), - ntohs(sinp->sin_port)); - } - } else { - plog(XLOG_WARNING, "ignoring request from %s:%u, expected %s", - inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr), - ntohs(sinp->sin_port), - inet_dquad(dq2, sizeof(dq2), myipaddr.s_addr)); - return; - } - } -#endif /* not HAVE_TRANPORT_TYPE_TLI */ - - current_transp = NULL; - - switch (rqstp->rq_proc) { - - case NFSPROC_NULL: - xdr_argument = (xdrproc_t) xdr_void; - xdr_result = (xdrproc_t) xdr_void; - local = (nfssvcproc_t) nfsproc_null_2_svc; - break; - - case NFSPROC_GETATTR: - xdr_argument = (xdrproc_t) xdr_nfs_fh; - xdr_result = (xdrproc_t) xdr_attrstat; - local = (nfssvcproc_t) nfsproc_getattr_2_svc; - break; - - case NFSPROC_SETATTR: - xdr_argument = (xdrproc_t) xdr_sattrargs; - xdr_result = (xdrproc_t) xdr_attrstat; - local = (nfssvcproc_t) nfsproc_setattr_2_svc; - break; - - case NFSPROC_ROOT: - xdr_argument = (xdrproc_t) xdr_void; - xdr_result = (xdrproc_t) xdr_void; - local = (nfssvcproc_t) nfsproc_root_2_svc; - break; - - case NFSPROC_LOOKUP: - xdr_argument = (xdrproc_t) xdr_diropargs; - xdr_result = (xdrproc_t) xdr_diropres; - local = (nfssvcproc_t) nfsproc_lookup_2_svc; - /* - * Cheap way to pass transp down to amfs_auto_lookuppn so it can - * be stored in the am_node structure and later used for - * quick_reply(). - */ - current_transp = transp; - break; - - case NFSPROC_READLINK: - xdr_argument = (xdrproc_t) xdr_nfs_fh; - xdr_result = (xdrproc_t) xdr_readlinkres; - local = (nfssvcproc_t) nfsproc_readlink_2_svc; - break; - - case NFSPROC_READ: - xdr_argument = (xdrproc_t) xdr_readargs; - xdr_result = (xdrproc_t) xdr_readres; - local = (nfssvcproc_t) nfsproc_read_2_svc; - break; - - case NFSPROC_WRITECACHE: - xdr_argument = (xdrproc_t) xdr_void; - xdr_result = (xdrproc_t) xdr_void; - local = (nfssvcproc_t) nfsproc_writecache_2_svc; - break; - - case NFSPROC_WRITE: - xdr_argument = (xdrproc_t) xdr_writeargs; - xdr_result = (xdrproc_t) xdr_attrstat; - local = (nfssvcproc_t) nfsproc_write_2_svc; - break; - - case NFSPROC_CREATE: - xdr_argument = (xdrproc_t) xdr_createargs; - xdr_result = (xdrproc_t) xdr_diropres; - local = (nfssvcproc_t) nfsproc_create_2_svc; - break; - - case NFSPROC_REMOVE: - xdr_argument = (xdrproc_t) xdr_diropargs; - xdr_result = (xdrproc_t) xdr_nfsstat; - local = (nfssvcproc_t) nfsproc_remove_2_svc; - break; - - case NFSPROC_RENAME: - xdr_argument = (xdrproc_t) xdr_renameargs; - xdr_result = (xdrproc_t) xdr_nfsstat; - local = (nfssvcproc_t) nfsproc_rename_2_svc; - break; - - case NFSPROC_LINK: - xdr_argument = (xdrproc_t) xdr_linkargs; - xdr_result = (xdrproc_t) xdr_nfsstat; - local = (nfssvcproc_t) nfsproc_link_2_svc; - break; - - case NFSPROC_SYMLINK: - xdr_argument = (xdrproc_t) xdr_symlinkargs; - xdr_result = (xdrproc_t) xdr_nfsstat; - local = (nfssvcproc_t) nfsproc_symlink_2_svc; - break; - - case NFSPROC_MKDIR: - xdr_argument = (xdrproc_t) xdr_createargs; - xdr_result = (xdrproc_t) xdr_diropres; - local = (nfssvcproc_t) nfsproc_mkdir_2_svc; - break; - - case NFSPROC_RMDIR: - xdr_argument = (xdrproc_t) xdr_diropargs; - xdr_result = (xdrproc_t) xdr_nfsstat; - local = (nfssvcproc_t) nfsproc_rmdir_2_svc; - break; - - case NFSPROC_READDIR: - xdr_argument = (xdrproc_t) xdr_readdirargs; - xdr_result = (xdrproc_t) xdr_readdirres; - local = (nfssvcproc_t) nfsproc_readdir_2_svc; - break; - - case NFSPROC_STATFS: - xdr_argument = (xdrproc_t) xdr_nfs_fh; - xdr_result = (xdrproc_t) xdr_statfsres; - local = (nfssvcproc_t) nfsproc_statfs_2_svc; - break; - - default: - svcerr_noproc(transp); - return; - } - - memset((char *) &argument, 0, sizeof(argument)); - if (!svc_getargs(transp, - (XDRPROC_T_TYPE) xdr_argument, - (SVC_IN_ARG_TYPE) &argument)) { - plog(XLOG_ERROR, - "NFS xdr decode failed for %d %d %d", - (int) rqstp->rq_prog, (int) rqstp->rq_vers, (int) rqstp->rq_proc); - svcerr_decode(transp); - return; - } - result = (*local) (&argument, rqstp); - - current_transp = NULL; - - if (result != NULL && !svc_sendreply(transp, - (XDRPROC_T_TYPE) xdr_result, - result)) { - svcerr_systemerr(transp); - } - if (!svc_freeargs(transp, - (XDRPROC_T_TYPE) xdr_argument, - (SVC_IN_ARG_TYPE) & argument)) { - plog(XLOG_FATAL, "unable to free rpc arguments in nfs_program_2"); - going_down(1); - } -} diff --git a/contrib/amd/amd/nfs_start.c b/contrib/amd/amd/nfs_start.c deleted file mode 100644 index f6aba94e2b6d..000000000000 --- a/contrib/amd/amd/nfs_start.c +++ /dev/null @@ -1,453 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/nfs_start.c - * - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -#ifndef SELECT_MAXWAIT -# define SELECT_MAXWAIT 16 -#endif /* not SELECT_MAXWAIT */ - -SVCXPRT *nfsxprt = NULL; -u_short nfs_port = 0; - -#ifndef HAVE_SIGACTION -# define MASKED_SIGS (sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGCHLD)|sigmask(SIGHUP)) -#endif /* not HAVE_SIGACTION */ - -#ifdef DEBUG -/* - * Check that we are not burning resources - */ -static void -checkup(void) -{ - - static int max_fd = 0; - static char *max_mem = 0; - - int next_fd = dup(0); - caddr_t next_mem = sbrk(0); - close(next_fd); - - if (max_fd < next_fd) { - dlog("%d new fds allocated; total is %d", - next_fd - max_fd, next_fd); - max_fd = next_fd; - } - if (max_mem < next_mem) { -#ifdef HAVE_GETPAGESIZE - dlog("%#lx bytes of memory allocated; total is %#lx (%ld pages)", - (long) (next_mem - max_mem), (unsigned long) next_mem, - ((long) next_mem + getpagesize() - 1) / (long) getpagesize()); -#else /* not HAVE_GETPAGESIZE */ - dlog("%#lx bytes of memory allocated; total is %#lx", - (long) (next_mem - max_mem), (unsigned long) next_mem); -#endif /* not HAVE_GETPAGESIZE */ - max_mem = next_mem; - - } -} -#else /* not DEBUG */ -#define checkup() -#endif /* not DEBUG */ - - -static int -#ifdef HAVE_SIGACTION -do_select(sigset_t smask, int fds, fd_set *fdp, struct timeval *tvp) -#else /* not HAVE_SIGACTION */ -do_select(int smask, int fds, fd_set *fdp, struct timeval *tvp) -#endif /* not HAVE_SIGACTION */ -{ - - int sig; - int nsel; - - if ((sig = setjmp(select_intr))) { - select_intr_valid = 0; - /* Got a signal */ - switch (sig) { - case SIGINT: - case SIGTERM: - amd_state = Finishing; - reschedule_timeout_mp(); - break; - } - nsel = -1; - errno = EINTR; - } else { - select_intr_valid = 1; - /* - * Allow interrupts. If a signal - * occurs, then it will cause a longjmp - * up above. - */ -#ifdef HAVE_SIGACTION - sigprocmask(SIG_SETMASK, &smask, NULL); -#else /* not HAVE_SIGACTION */ - (void) sigsetmask(smask); -#endif /* not HAVE_SIGACTION */ - - /* - * Wait for input - */ - nsel = select(fds, fdp, (fd_set *) 0, (fd_set *) 0, - tvp->tv_sec ? tvp : (struct timeval *) 0); - } - -#ifdef HAVE_SIGACTION - sigprocmask(SIG_BLOCK, &masked_sigs, NULL); -#else /* not HAVE_SIGACTION */ - (void) sigblock(MASKED_SIGS); -#endif /* not HAVE_SIGACTION */ - - /* - * Perhaps reload the cache? - */ - if (do_mapc_reload < clocktime(NULL)) { - mapc_reload(); - do_mapc_reload = clocktime(NULL) + gopt.map_reload_interval; - } - return nsel; -} - - -/* - * Determine whether anything is left in - * the RPC input queue. - */ -static int -rpc_pending_now(void) -{ - struct timeval tvv; - int nsel; - fd_set readfds; - - FD_ZERO(&readfds); - FD_SET(fwd_sock, &readfds); - - tvv.tv_sec = tvv.tv_usec = 0; - nsel = select(FD_SETSIZE, &readfds, (fd_set *) 0, (fd_set *) 0, &tvv); - if (nsel < 1) - return (0); - if (FD_ISSET(fwd_sock, &readfds)) - return (1); - - return (0); -} - - -static serv_state -run_rpc(void) -{ -#ifdef HAVE_SIGACTION - sigset_t smask; - sigprocmask(SIG_BLOCK, &masked_sigs, &smask); -#else /* not HAVE_SIGACTION */ - int smask = sigblock(MASKED_SIGS); -#endif /* not HAVE_SIGACTION */ - - next_softclock = clocktime(NULL); - - amd_state = Run; - - /* - * Keep on trucking while we are in Run mode. This state - * is switched to Quit after all the file systems have - * been unmounted. - */ - while ((int) amd_state <= (int) Finishing) { - struct timeval tvv; - int nsel; - time_t now; - fd_set readfds; - -#ifdef HAVE_SVC_GETREQSET - memmove(&readfds, &svc_fdset, sizeof(svc_fdset)); -#else /* not HAVE_SVC_GETREQSET */ - FD_ZERO(&readfds); -# ifdef HAVE_FD_SET_FDS_BITS - readfds.fds_bits[0] = svc_fds; -# else /* not HAVE_FD_SET_FDS_BITS */ - readfds = svc_fds; -# endif /* not HAVE_FD_SET_FDS_BITS */ -#endif /* not HAVE_SVC_GETREQSET */ - FD_SET(fwd_sock, &readfds); - - checkup(); - - /* - * If the full timeout code is not called, - * then recompute the time delta manually. - */ - now = clocktime(NULL); - - if (next_softclock <= now) { - if (amd_state == Finishing) - umount_exported(); - tvv.tv_sec = softclock(); - } else { - tvv.tv_sec = next_softclock - now; - } - tvv.tv_usec = 0; - - if (amd_state == Finishing && get_exported_ap(0) == NULL) { - flush_mntfs(); - amd_state = Quit; - break; - } - -#ifdef HAVE_FS_AUTOFS - autofs_add_fdset(&readfds); -#endif /* HAVE_FS_AUTOFS */ - - if (tvv.tv_sec <= 0) - tvv.tv_sec = SELECT_MAXWAIT; - if (tvv.tv_sec) { - dlog("Select waits for %ds", (int) tvv.tv_sec); - } else { - dlog("Select waits for Godot"); - } - - nsel = do_select(smask, FD_SETSIZE, &readfds, &tvv); - - switch (nsel) { - case -1: - if (errno == EINTR) { - dlog("select interrupted"); - continue; - } - plog(XLOG_ERROR, "select: %m"); - break; - - case 0: - break; - - default: - /* - * Read all pending NFS responses at once to avoid having responses - * queue up as a consequence of retransmissions. - */ - if (FD_ISSET(fwd_sock, &readfds)) { - FD_CLR(fwd_sock, &readfds); - --nsel; - do { - fwd_reply(); - } while (rpc_pending_now() > 0); - } - -#ifdef HAVE_FS_AUTOFS - if (nsel) - nsel = autofs_handle_fdset(&readfds, nsel); -#endif /* HAVE_FS_AUTOFS */ - - if (nsel) { - /* - * Anything left must be a normal - * RPC request. - */ -#ifdef HAVE_SVC_GETREQSET - svc_getreqset(&readfds); -#else /* not HAVE_SVC_GETREQSET */ -# ifdef HAVE_FD_SET_FDS_BITS - svc_getreq(readfds.fds_bits[0]); -# else /* not HAVE_FD_SET_FDS_BITS */ - svc_getreq(readfds); -# endif /* not HAVE_FD_SET_FDS_BITS */ -#endif /* not HAVE_SVC_GETREQSET */ - } - break; - } - } - -#ifdef HAVE_SIGACTION - sigprocmask(SIG_SETMASK, &smask, NULL); -#else /* not HAVE_SIGACTION */ - (void) sigsetmask(smask); -#endif /* not HAVE_SIGACTION */ - - if (amd_state == Quit) - amd_state = Done; - - return amd_state; -} - - -int -mount_automounter(int ppid) -{ - /* - * Old code replaced by rpc-trash patch. - * Erez Zadok <ezk@cs.columbia.edu> - int so = socket(AF_INET, SOCK_DGRAM, 0); - */ - SVCXPRT *udp_amqp = NULL, *tcp_amqp = NULL; - int nmount, ret; - int soNFS; - int udp_soAMQ, tcp_soAMQ; - struct netconfig *udp_amqncp, *tcp_amqncp; - - /* - * This must be done first, because it attempts to bind - * to various UDP ports and we don't want anything else - * potentially taking over those ports before we get a chance - * to reserve them. - */ - if (gopt.flags & CFM_RESTART_EXISTING_MOUNTS) - restart_automounter_nodes(); - - /* - * Start RPC forwarding - */ - if (fwd_init() != 0) - return 3; - - /* - * Construct the root automount node - */ - make_root_node(); - - /* - * Pick up the pieces from a previous run - * This is likely to (indirectly) need the rpc_fwd package - * so it *must* come after the call to fwd_init(). - */ - if (gopt.flags & CFM_RESTART_EXISTING_MOUNTS) - restart(); - - /* - * Create the nfs service for amd - * If nfs_port is already initialized, it means we - * already created the service during restart_automounter_nodes(). - */ - if (nfs_port == 0) { - ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2); - if (ret != 0) - return ret; - } - xsnprintf(pid_fsname, sizeof(pid_fsname), "%s:(pid%ld,port%u)", - am_get_hostname(), (long) am_mypid, nfs_port); - - /* security: if user sets -D amq, don't even create listening socket */ - if (!amuDebug(D_AMQ)) { - ret = create_amq_service(&udp_soAMQ, - &udp_amqp, - &udp_amqncp, - &tcp_soAMQ, - &tcp_amqp, - &tcp_amqncp, - gopt.preferred_amq_port); - if (ret != 0) - return ret; - } - -#ifdef HAVE_FS_AUTOFS - if (amd_use_autofs) { - /* - * Create the autofs service for amd. - */ - ret = create_autofs_service(); - /* if autofs service fails it is OK if using a test amd */ - if (ret != 0) { - plog(XLOG_WARNING, "autofs service registration failed, turning off autofs support"); - amd_use_autofs = 0; - } - } -#endif /* HAVE_FS_AUTOFS */ - - /* - * Mount the top-level auto-mountpoints - */ - nmount = mount_exported(); - - /* - * Now safe to tell parent that we are up and running - */ - if (ppid) - kill(ppid, SIGQUIT); - - if (nmount == 0) { - plog(XLOG_FATAL, "No work to do - quitting"); - amd_state = Done; - return 0; - } - - if (!amuDebug(D_AMQ)) { - /* - * Complete registration of amq (first TCP service then UDP) - */ - unregister_amq(); - - ret = amu_svc_register(tcp_amqp, get_amd_program_number(), AMQ_VERSION, - amq_program_1, IPPROTO_TCP, tcp_amqncp); - if (ret != 1) { - plog(XLOG_FATAL, "unable to register (AMQ_PROGRAM=%d, AMQ_VERSION, tcp)", get_amd_program_number()); - return 3; - } - - ret = amu_svc_register(udp_amqp, get_amd_program_number(), AMQ_VERSION, - amq_program_1, IPPROTO_UDP, udp_amqncp); - if (ret != 1) { - plog(XLOG_FATAL, "unable to register (AMQ_PROGRAM=%d, AMQ_VERSION, udp)", get_amd_program_number()); - return 4; - } - } - - /* - * Start timeout_mp rolling - */ - reschedule_timeout_mp(); - - /* - * Start the server - */ - if (run_rpc() != Done) { - plog(XLOG_FATAL, "run_rpc failed"); - amd_state = Done; - } - return 0; -} diff --git a/contrib/amd/amd/nfs_subr.c b/contrib/amd/amd/nfs_subr.c deleted file mode 100644 index 80d3ca8e311c..000000000000 --- a/contrib/amd/amd/nfs_subr.c +++ /dev/null @@ -1,828 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/nfs_subr.c - * - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* - * Convert from UN*X to NFS error code. - * Some systems like linux define their own (see - * conf/mount/mount_linux.h). - */ -#ifndef nfs_error -# define nfs_error(e) ((nfsstat)(e)) -#endif /* nfs_error */ - -/* - * File Handle structure - * - * This is interpreted by indexing the exported array - * by fhh_id (for old-style filehandles), or by retrieving - * the node name from fhh_path (for new-style filehandles). - * - * The whole structure is mapped onto a standard fhandle_t - * when transmitted. - */ -struct am_fh { - u_int fhh_gen; /* generation number */ - union { - struct { - int fhh_type; /* old or new am_fh */ - pid_t fhh_pid; /* process id */ - int fhh_id; /* map id */ - } s; - char fhh_path[NFS_FHSIZE-sizeof(u_int)]; /* path to am_node */ - } u; -}; - - -/* forward declarations */ -/* converting am-filehandles to mount-points */ -static am_node *fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop); -static am_node *fh_to_mp(am_nfs_fh *fhp); -static void count_map_entries(const am_node *mp, u_int *out_blocks, u_int *out_bfree, u_int *out_bavail); - - -static char * -do_readlink(am_node *mp, int *error_return) -{ - char *ln; - - /* - * If there is a readlink method then use it, - * otherwise if a link exists use that, - * otherwise use the mount point. - */ - if (mp->am_mnt->mf_ops->readlink) { - int retry = 0; - mp = (*mp->am_mnt->mf_ops->readlink) (mp, &retry); - if (mp == 0) { - *error_return = retry; - return 0; - } - /* reschedule_timeout_mp(); */ - } - - if (mp->am_link) { - ln = mp->am_link; - } else { - ln = mp->am_mnt->mf_mount; - } - - return ln; -} - - -voidp -nfsproc_null_2_svc(voidp argp, struct svc_req *rqstp) -{ - static char res; - - return (voidp) &res; -} - - -nfsattrstat * -nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) -{ - static nfsattrstat res; - am_node *mp; - int retry; - time_t now = clocktime(NULL); - - if (amuDebug(D_TRACE)) - plog(XLOG_DEBUG, "getattr:"); - - mp = fh_to_mp3(argp, &retry, VLOOK_CREATE); - if (mp == 0) { - if (amuDebug(D_TRACE)) - plog(XLOG_DEBUG, "\tretry=%d", retry); - - if (retry < 0) { - amd_stats.d_drops++; - return 0; - } - res.ns_status = nfs_error(retry); - return &res; - } - - res = mp->am_attr; - if (amuDebug(D_TRACE)) - plog(XLOG_DEBUG, "\tstat(%s), size = %d, mtime=%ld.%ld", - mp->am_path, - (int) res.ns_u.ns_attr_u.na_size, - (long) res.ns_u.ns_attr_u.na_mtime.nt_seconds, - (long) res.ns_u.ns_attr_u.na_mtime.nt_useconds); - - /* Delay unmount of what was looked up */ - if (mp->am_timeo_w < 4 * gopt.am_timeo_w) - mp->am_timeo_w += gopt.am_timeo_w; - mp->am_ttl = now + mp->am_timeo_w; - - mp->am_stats.s_getattr++; - return &res; -} - - -nfsattrstat * -nfsproc_setattr_2_svc(nfssattrargs *argp, struct svc_req *rqstp) -{ - static nfsattrstat res; - - if (!fh_to_mp(&argp->sag_fhandle)) - res.ns_status = nfs_error(ESTALE); - else - res.ns_status = nfs_error(EROFS); - - return &res; -} - - -voidp -nfsproc_root_2_svc(voidp argp, struct svc_req *rqstp) -{ - static char res; - - return (voidp) &res; -} - - -nfsdiropres * -nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp) -{ - static nfsdiropres res; - am_node *mp; - int retry; - uid_t uid; - gid_t gid; - - if (amuDebug(D_TRACE)) - plog(XLOG_DEBUG, "lookup:"); - - /* finally, find the effective uid/gid from RPC request */ - if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0) - plog(XLOG_ERROR, "cannot get uid/gid from RPC credentials"); - xsnprintf(opt_uid, sizeof(uid_str), "%d", (int) uid); - xsnprintf(opt_gid, sizeof(gid_str), "%d", (int) gid); - - mp = fh_to_mp3(&argp->da_fhandle, &retry, VLOOK_CREATE); - if (mp == 0) { - if (retry < 0) { - amd_stats.d_drops++; - return 0; - } - res.dr_status = nfs_error(retry); - } else { - int error; - am_node *ap; - if (amuDebug(D_TRACE)) - plog(XLOG_DEBUG, "\tlookup(%s, %s)", mp->am_path, argp->da_name); - ap = mp->am_mnt->mf_ops->lookup_child(mp, argp->da_name, &error, VLOOK_CREATE); - if (ap && error < 0) - ap = mp->am_mnt->mf_ops->mount_child(ap, &error); - if (ap == 0) { - if (error < 0) { - amd_stats.d_drops++; - return 0; - } - res.dr_status = nfs_error(error); - } else { - /* - * XXX: EXPERIMENTAL! Delay unmount of what was looked up. This - * should reduce the chance for race condition between unmounting an - * entry synchronously, and re-mounting it asynchronously. - */ - if (ap->am_ttl < mp->am_ttl) - ap->am_ttl = mp->am_ttl; - mp_to_fh(ap, &res.dr_u.dr_drok_u.drok_fhandle); - res.dr_u.dr_drok_u.drok_attributes = ap->am_fattr; - res.dr_status = NFS_OK; - } - mp->am_stats.s_lookup++; - /* reschedule_timeout_mp(); */ - } - - return &res; -} - - -void -nfs_quick_reply(am_node *mp, int error) -{ - SVCXPRT *transp = mp->am_transp; - nfsdiropres res; - xdrproc_t xdr_result = (xdrproc_t) xdr_diropres; - - /* - * If there's a transp structure then we can reply to the client's - * nfs lookup request. - */ - if (transp) { - if (error == 0) { - /* - * Construct a valid reply to a lookup request. Same - * code as in nfsproc_lookup_2_svc() above. - */ - mp_to_fh(mp, &res.dr_u.dr_drok_u.drok_fhandle); - res.dr_u.dr_drok_u.drok_attributes = mp->am_fattr; - res.dr_status = NFS_OK; - } else - /* - * Return the error that was passed to us. - */ - res.dr_status = nfs_error(error); - - /* - * Send off our reply - */ - if (!svc_sendreply(transp, (XDRPROC_T_TYPE) xdr_result, (SVC_IN_ARG_TYPE) & res)) - svcerr_systemerr(transp); - - /* - * Free up transp. It's only used for one reply. - */ - XFREE(mp->am_transp); - dlog("Quick reply sent for %s", mp->am_mnt->mf_mount); - } -} - - -nfsreadlinkres * -nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) -{ - static nfsreadlinkres res; - am_node *mp; - int retry; - - if (amuDebug(D_TRACE)) - plog(XLOG_DEBUG, "readlink:"); - - mp = fh_to_mp3(argp, &retry, VLOOK_CREATE); - if (mp == 0) { - readlink_retry: - if (retry < 0) { - amd_stats.d_drops++; - return 0; - } - res.rlr_status = nfs_error(retry); - } else { - char *ln = do_readlink(mp, &retry); - if (ln == 0) - goto readlink_retry; - res.rlr_status = NFS_OK; - if (amuDebug(D_TRACE) && ln) - plog(XLOG_DEBUG, "\treadlink(%s) = %s", mp->am_path, ln); - res.rlr_u.rlr_data_u = ln; - mp->am_stats.s_readlink++; - } - - return &res; -} - - -nfsreadres * -nfsproc_read_2_svc(nfsreadargs *argp, struct svc_req *rqstp) -{ - static nfsreadres res; - - memset((char *) &res, 0, sizeof(res)); - res.rr_status = nfs_error(EACCES); - - return &res; -} - - -voidp -nfsproc_writecache_2_svc(voidp argp, struct svc_req *rqstp) -{ - static char res; - - return (voidp) &res; -} - - -nfsattrstat * -nfsproc_write_2_svc(nfswriteargs *argp, struct svc_req *rqstp) -{ - static nfsattrstat res; - - if (!fh_to_mp(&argp->wra_fhandle)) - res.ns_status = nfs_error(ESTALE); - else - res.ns_status = nfs_error(EROFS); - - return &res; -} - - -nfsdiropres * -nfsproc_create_2_svc(nfscreateargs *argp, struct svc_req *rqstp) -{ - static nfsdiropres res; - - if (!fh_to_mp(&argp->ca_where.da_fhandle)) - res.dr_status = nfs_error(ESTALE); - else - res.dr_status = nfs_error(EROFS); - - return &res; -} - - -static nfsstat * -unlink_or_rmdir(nfsdiropargs *argp, struct svc_req *rqstp, int unlinkp) -{ - static nfsstat res; - int retry; - - am_node *mp = fh_to_mp3(&argp->da_fhandle, &retry, VLOOK_DELETE); - if (mp == 0) { - if (retry < 0) { - amd_stats.d_drops++; - return 0; - } - res = nfs_error(retry); - goto out; - } - - if (mp->am_fattr.na_type != NFDIR) { - res = nfs_error(ENOTDIR); - goto out; - } - - if (amuDebug(D_TRACE)) - plog(XLOG_DEBUG, "\tremove(%s, %s)", mp->am_path, argp->da_name); - - mp = mp->am_mnt->mf_ops->lookup_child(mp, argp->da_name, &retry, VLOOK_DELETE); - if (mp == 0) { - /* - * Ignore retries... - */ - if (retry < 0) - retry = 0; - /* - * Usual NFS workaround... - */ - else if (retry == ENOENT) - retry = 0; - res = nfs_error(retry); - } else { - forcibly_timeout_mp(mp); - res = NFS_OK; - } - -out: - return &res; -} - - -nfsstat * -nfsproc_remove_2_svc(nfsdiropargs *argp, struct svc_req *rqstp) -{ - return unlink_or_rmdir(argp, rqstp, TRUE); -} - - -nfsstat * -nfsproc_rename_2_svc(nfsrenameargs *argp, struct svc_req *rqstp) -{ - static nfsstat res; - - if (!fh_to_mp(&argp->rna_from.da_fhandle) || !fh_to_mp(&argp->rna_to.da_fhandle)) - res = nfs_error(ESTALE); - /* - * If the kernel is doing clever things with referenced files - * then let it pretend... - */ - else if (NSTREQ(argp->rna_to.da_name, ".nfs", 4)) - res = NFS_OK; - /* - * otherwise a failure - */ - else - res = nfs_error(EROFS); - - return &res; -} - - -nfsstat * -nfsproc_link_2_svc(nfslinkargs *argp, struct svc_req *rqstp) -{ - static nfsstat res; - - if (!fh_to_mp(&argp->la_fhandle) || !fh_to_mp(&argp->la_to.da_fhandle)) - res = nfs_error(ESTALE); - else - res = nfs_error(EROFS); - - return &res; -} - - -nfsstat * -nfsproc_symlink_2_svc(nfssymlinkargs *argp, struct svc_req *rqstp) -{ - static nfsstat res; - - if (!fh_to_mp(&argp->sla_from.da_fhandle)) - res = nfs_error(ESTALE); - else - res = nfs_error(EROFS); - - return &res; -} - - -nfsdiropres * -nfsproc_mkdir_2_svc(nfscreateargs *argp, struct svc_req *rqstp) -{ - static nfsdiropres res; - - if (!fh_to_mp(&argp->ca_where.da_fhandle)) - res.dr_status = nfs_error(ESTALE); - else - res.dr_status = nfs_error(EROFS); - - return &res; -} - - -nfsstat * -nfsproc_rmdir_2_svc(nfsdiropargs *argp, struct svc_req *rqstp) -{ - return unlink_or_rmdir(argp, rqstp, FALSE); -} - - -nfsreaddirres * -nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp) -{ - static nfsreaddirres res; - static nfsentry e_res[MAX_READDIR_ENTRIES]; - am_node *mp; - int retry; - - if (amuDebug(D_TRACE)) - plog(XLOG_DEBUG, "readdir:"); - - mp = fh_to_mp3(&argp->rda_fhandle, &retry, VLOOK_CREATE); - if (mp == 0) { - if (retry < 0) { - amd_stats.d_drops++; - return 0; - } - res.rdr_status = nfs_error(retry); - } else { - if (amuDebug(D_TRACE)) - plog(XLOG_DEBUG, "\treaddir(%s)", mp->am_path); - res.rdr_status = nfs_error((*mp->am_mnt->mf_ops->readdir) - (mp, argp->rda_cookie, - &res.rdr_u.rdr_reply_u, e_res, argp->rda_count)); - mp->am_stats.s_readdir++; - } - - return &res; -} - - -nfsstatfsres * -nfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) -{ - static nfsstatfsres res; - am_node *mp; - int retry; - mntent_t mnt; - - if (amuDebug(D_TRACE)) - plog(XLOG_DEBUG, "statfs:"); - - mp = fh_to_mp3(argp, &retry, VLOOK_CREATE); - if (mp == 0) { - if (retry < 0) { - amd_stats.d_drops++; - return 0; - } - res.sfr_status = nfs_error(retry); - } else { - nfsstatfsokres *fp; - if (amuDebug(D_TRACE)) - plog(XLOG_DEBUG, "\tstat_fs(%s)", mp->am_path); - - /* - * just return faked up file system information - */ - fp = &res.sfr_u.sfr_reply_u; - - fp->sfrok_tsize = 1024; - fp->sfrok_bsize = 1024; - - /* check if map is browsable and show_statfs_entries=yes */ - if ((gopt.flags & CFM_SHOW_STATFS_ENTRIES) && - mp->am_mnt && mp->am_mnt->mf_mopts) { - mnt.mnt_opts = mp->am_mnt->mf_mopts; - if (amu_hasmntopt(&mnt, "browsable")) { - count_map_entries(mp, - &fp->sfrok_blocks, - &fp->sfrok_bfree, - &fp->sfrok_bavail); - } - } else { - fp->sfrok_blocks = 0; /* set to 1 if you don't want empty automounts */ - fp->sfrok_bfree = 0; - fp->sfrok_bavail = 0; - } - - res.sfr_status = NFS_OK; - mp->am_stats.s_statfs++; - } - - return &res; -} - - -/* - * count how many total entries there are in a map, and how many - * of them are in use. - */ -static void -count_map_entries(const am_node *mp, u_int *out_blocks, u_int *out_bfree, u_int *out_bavail) -{ - u_int blocks, bfree, bavail, i; - mntfs *mf; - mnt_map *mmp; - kv *k; - - blocks = bfree = bavail = 0; - if (!mp) - goto out; - mf = mp->am_mnt; - if (!mf) - goto out; - mmp = (mnt_map *) mf->mf_private; - if (!mmp) - goto out; - - /* iterate over keys */ - for (i = 0; i < NKVHASH; i++) { - for (k = mmp->kvhash[i]; k ; k = k->next) { - if (!k->key) - continue; - blocks++; - /* - * XXX: Need to count how many are actively in use and recompute - * bfree and bavail based on it. - */ - } - } - -out: - *out_blocks = blocks; - *out_bfree = bfree; - *out_bavail = bavail; -} - - -/* - * Convert from file handle to automount node. - */ -static am_node * -fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop) -{ - struct am_fh *fp = (struct am_fh *) fhp; - am_node *ap = 0; - - if (fp->u.s.fhh_type != 0) { - /* New filehandle type */ - int len = sizeof(*fhp) - sizeof(fp->fhh_gen); - char *path = xmalloc(len+1); - /* - * Because fhp is treated as a filehandle we use memcpy - * instead of xstrlcpy. - */ - memcpy(path, (char *) fp->u.fhh_path, len); - path[len] = '\0'; - /* dlog("fh_to_mp3: new filehandle: %s", path); */ - - ap = path_to_exported_ap(path); - XFREE(path); - } else { - /* dlog("fh_to_mp3: old filehandle: %d", fp->u.s.fhh_id); */ - /* - * Check process id matches - * If it doesn't then it is probably - * from an old kernel-cached filehandle - * which is now out of date. - */ - if (fp->u.s.fhh_pid != get_server_pid()) { - dlog("fh_to_mp3: wrong pid %ld != my pid %ld", - (long) fp->u.s.fhh_pid, get_server_pid()); - goto drop; - } - - /* - * Get hold of the supposed mount node - */ - ap = get_exported_ap(fp->u.s.fhh_id); - } - - /* - * Check the generation number in the node - * matches the one from the kernel. If not - * then the old node has been timed out and - * a new one allocated. - */ - if (ap != NULL && ap->am_gen != fp->fhh_gen) - ap = 0; - - /* - * If it doesn't exists then drop the request - */ - if (!ap) - goto drop; - -#if 0 - /* - * If the node is hung then locate a new node - * for it. This implements the replicated filesystem - * retries. - */ - if (ap->am_mnt && FSRV_ISDOWN(ap->am_mnt->mf_server) && ap->am_parent) { - int error; - am_node *orig_ap = ap; - - dlog("fh_to_mp3: %s (%s) is hung: lookup alternative file server", - orig_ap->am_path, orig_ap->am_mnt->mf_info); - - /* - * Update modify time of parent node. - * With any luck the kernel will re-stat - * the child node and get new information. - */ - clocktime(&orig_ap->am_fattr.na_mtime); - - /* - * Call the parent's lookup routine for an object - * with the same name. This may return -1 in error - * if a mount is in progress. In any case, if no - * mount node is returned the error code is propagated - * to the caller. - */ - if (vop == VLOOK_CREATE) { - ap = orig_ap->am_parent->am_mnt->mf_ops->lookup_child(orig_ap->am_parent, orig_ap->am_name, &error, vop); - if (ap && error < 0) - ap = orig_ap->am_parent->am_mnt->mf_ops->mount_child(ap, &error); - } else { - ap = 0; - error = ESTALE; - } - if (ap == 0) { - if (error < 0 && amd_state == Finishing) - error = ENOENT; - *rp = error; - return 0; - } - - /* - * Update last access to original node. This - * avoids timing it out and so sending ESTALE - * back to the kernel. - * XXX - Not sure we need this anymore (jsp, 90/10/6). - */ - new_ttl(orig_ap); - - } -#endif - - /* - * Disallow references to objects being unmounted, unless - * they are automount points. - */ - if (ap->am_mnt && (ap->am_mnt->mf_flags & MFF_UNMOUNTING) && - !(ap->am_flags & AMF_ROOT)) { - if (amd_state == Finishing) - *rp = ENOENT; - else - *rp = -1; - return 0; - } - new_ttl(ap); - -drop: - if (!ap || !ap->am_mnt) { - /* - * If we are shutting down then it is likely - * that this node has disappeared because of - * a fast timeout. To avoid things thrashing - * just pretend it doesn't exist at all. If - * ESTALE is returned, some NFS clients just - * keep retrying (stupid or what - if it's - * stale now, what's it going to be in 5 minutes?) - */ - if (amd_state == Finishing) - *rp = ENOENT; - else - *rp = ESTALE; - amd_stats.d_stale++; - } - - return ap; -} - - -static am_node * -fh_to_mp(am_nfs_fh *fhp) -{ - int dummy; - - return fh_to_mp3(fhp, &dummy, VLOOK_CREATE); -} - - -/* - * Convert from automount node to file handle. - */ -void -mp_to_fh(am_node *mp, am_nfs_fh *fhp) -{ - u_int pathlen; - struct am_fh *fp = (struct am_fh *) fhp; - - memset((char *) fhp, 0, sizeof(am_nfs_fh)); - - /* Store the generation number */ - fp->fhh_gen = mp->am_gen; - - pathlen = strlen(mp->am_path); - if (pathlen <= sizeof(*fhp) - sizeof(fp->fhh_gen)) { - /* dlog("mp_to_fh: new filehandle: %s", mp->am_path); */ - - /* - * Because fhp is treated as a filehandle we use memcpy instead of - * xstrlcpy. - */ - memcpy(fp->u.fhh_path, mp->am_path, pathlen); /* making a filehandle */ - } else { - /* - * Take the process id - */ - fp->u.s.fhh_pid = get_server_pid(); - - /* - * ... the map number - */ - fp->u.s.fhh_id = mp->am_mapno; - - /* - * ... and the generation number (previously stored) - * to make a "unique" triple that will never - * be reallocated except across reboots (which doesn't matter) - * or if we are unlucky enough to be given the same - * pid as a previous amd (very unlikely). - */ - /* dlog("mp_to_fh: old filehandle: %d", fp->u.s.fhh_id); */ - } -} diff --git a/contrib/amd/amd/ops_TEMPLATE.c b/contrib/amd/amd/ops_TEMPLATE.c deleted file mode 100644 index 3f7421984412..000000000000 --- a/contrib/amd/amd/ops_TEMPLATE.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/ops_TEMPLATE.c - * - */ - -/* - * An empty template for an amd pseudo filesystem "foofs". - */ - -/* - * NOTE: if this is an Amd file system, prepend "amfs_" to all foofs symbols - * and renamed the file name to amfs_foofs.c. If it is a native file system - * (such as pcfs, isofs, or ffs), then you can keep the names as is, and - * just rename the file to ops_foofs.c. - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* forward declarations */ -static char *foofs_match(am_opts *fo); -static int foofs_init(mntfs *mf); -static int foofs_mount(am_node *mp, mntfs *mf); -static int foofs_umount(am_node *mp, mntfs *mf); -static am_node *foofs_lookuppn(am_node *mp, char *fname, int *error_return, int op); -static int foofs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count); -static am_node *foofs_readlink(am_node *mp, int *error_return); -static void foofs_mounted(am_node *am, mntfs *mf); -static void foofs_umounted(am_node *mp, mntfs *mf); -static fserver *foofs_ffserver(mntfs *mf); - - -/* - * Foofs operations. - * Define only those you need, others set to 0 (NULL) - */ -am_ops foofs_ops = -{ - "foofs", /* name of file system */ - foofs_match, /* match */ - foofs_init, /* initialize */ - foofs_mount, /* mount vnode */ - foofs_umount, /* unmount vnode */ - foofs_lookup_child, /* lookup path-name */ - foofs_mount_child, /* mount path-name */ - foofs_readdir, /* read directory */ - foofs_readlink, /* read link */ - foofs_mounted, /* after-mount extra actions */ - foofs_umounted, /* after-umount extra actions */ - foofs_ffserver, /* find a file server */ - foofs_get_wchan, /* return the waiting channel */ - FS_MKMNT | FS_BACKGROUND | FS_AMQINFO, /* nfs_fs_flags */ -#ifdef HAVE_FS_AUTOFS - AUTOFS_TEMPLATE_FS_FLAGS, -#endif /* HAVE_FS_AUTOFS */ -}; - - -/* - * Check that f/s has all needed fields. - * Returns: matched string if found, NULL otherwise. - */ -static char * -foofs_match(am_opts *fo) -{ - char *cp = "fill this with a way to find the match"; - - plog(XLOG_INFO, "entering foofs_match..."); - - if (cp) - return cp; /* OK */ - - return NULL; /* not OK */ -} - - -/* - * Initialize. - * Returns: 0 if OK, non-zero (errno) if failed. - */ -static int -foofs_init(mntfs *mf) -{ - int error = 0; - - plog(XLOG_INFO, "entering foofs_init..."); - - error = EPERM; /* XXX: fixme */ - return error; -} - - -/* - * Mount vnode. - * Returns: 0 if OK, non-zero (errno) if failed. - */ -static int -foofs_mount(am_node *mp) -{ - int error = 0; - - plog(XLOG_INFO, "entering foofs_mount..."); - - error = EPERM; /* XXX: fixme */ - return error; -} - - -/* - * Mount vfs. - * Returns: 0 if OK, non-zero (errno) if failed. - */ -static int -foofs_fmount(mntfs *mf) -{ - int error = 0; - - plog(XLOG_INFO, "entering foofs_fmount..."); - - error = EPERM; /* XXX: fixme */ - return error; -} - - -/* - * Unmount vnode. - * Returns: 0 if OK, non-zero (errno) if failed. - */ -static int -foofs_umount(am_node *mp) -{ - int error = 0; - - plog(XLOG_INFO, "entering foofs_umount..."); - - error = EPERM; /* XXX: fixme */ - return error; -} - - -/* - * Unmount VFS. - * Returns: 0 if OK, non-zero (errno) if failed. - */ -static int -foofs_fumount(mntfs *mf) -{ - int error = 0; - - plog(XLOG_INFO, "entering foofs_fumount..."); - - error = EPERM; /* XXX: fixme */ - return error; -} - - -/* - * Lookup path-name. - * Returns: the am_node that was found, or NULL if failed. - * If failed, also fills in errno in error_return. - */ -static am_node * -foofs_lookuppn(am_node *mp, char *fname, int *error_return, int op) -{ - int error = 0; - - plog(XLOG_INFO, "entering foofs_lookuppn..."); - - error = EPERM; /* XXX: fixme */ - - *error_return = error; - return NULL; -} - - -/* - * Read directory. - * Returns: 0 if OK, non-zero (errno) if failed. - * If OK, fills in ep with chain of directory entries. - */ -static int -foofs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count) -{ - int error = 0; - - plog(XLOG_INFO, "entering foofs_readdir..."); - - error = EPERM; /* XXX: fixme */ - return error; -} - - -/* - * Read link. - * Returns: am_node found, or NULL if not found. - * If failed, fills in errno in error_return. - */ -static am_node * -foofs_readlink(am_node *mp, int *error_return) -{ - int error = 0; - - plog(XLOG_INFO, "entering foofs_readlink..."); - - error = EPERM; /* XXX: fixme */ - - *error_return = error; - return NULL; -} - - -/* - * Async mount callback function. - * After the base mount went OK, sometimes - * there are additional actions that are needed. See union_mounted() and - * toplvl_mounted(). - */ -static void -foofs_mounted(mntfs *mf) -{ - plog(XLOG_INFO, "entering foofs_mounted..."); - - return; -} - - -/* - * Async unmount callback function. - * After the base umount() succeeds, we may want to take extra actions, - * such as informing remote mount daemons that we've unmounted them. - * See amfs_auto_umounted(), host_umounted(), nfs_umounted(). - */ -static void -foofs_umounted(am_node *mp) -{ - plog(XLOG_INFO, "entering foofs_umounted..."); - - return; -} - - -/* - * Find a file server. - * Returns: fserver of found server, or NULL if not found. - */ -static fserver * -foofs_ffserver(mntfs *mf) -{ - plog(XLOG_INFO, "entering foofs_ffserver..."); - - return NULL; -} - - -/* - * Normally just return mf. Only inherit needs to do special tricks. - */ -static wchan_t * -foofs_get_wchan(mntfs *mf) -{ - plog(XLOG_INFO, "entering foofs_get_wchan..."); - - return mf; -} diff --git a/contrib/amd/amd/ops_autofs.c b/contrib/amd/amd/ops_autofs.c deleted file mode 100644 index bd0bb122fe03..000000000000 --- a/contrib/amd/amd/ops_autofs.c +++ /dev/null @@ -1,1279 +0,0 @@ -/* - * Copyright (c) 1997-2001 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * %W% (Berkeley) %G% - * - * $Id: ops_autofs.c,v 1.7.2.4 2001/04/24 06:17:40 ib42 Exp $ - * - */ - -/* - * Automounter filesystem - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* - * KLUDGE: wrap whole file in HAVE_FS_AUTOFS, because - * not all systems with an automounter file system are supported - * by am-utils yet... - */ - -#ifdef HAVE_FS_AUTOFS - -/* - * MACROS: - */ -#ifndef AUTOFS_NULL -# define AUTOFS_NULL ((u_long)0) -#endif /* not AUTOFS_NULL */ - -/* - * VARIABLES: - */ - -/* forward declarations */ -static int mount_autofs(char *dir, char *opts); -static int autofs_mount_1_svc(struct mntrequest *mr, struct mntres *result, struct authunix_parms *cred); -static int autofs_unmount_1_svc(struct umntrequest *ur, struct umntres *result, struct authunix_parms *cred); - -/* external declarations */ -extern bool_t xdr_mntrequest(XDR *, mntrequest *); -extern bool_t xdr_mntres(XDR *, mntres *); -extern bool_t xdr_umntrequest(XDR *, umntrequest *); -extern bool_t xdr_umntres(XDR *, umntres *); - -/* - * STRUCTURES: - */ - -/* Sun's kernel-based automounter-supporting file system */ -am_ops autofs_ops = -{ - "autofs", - amfs_auto_match, - 0, /* amfs_auto_init */ - autofs_mount, - 0, - autofs_umount, - 0, - amfs_auto_lookuppn, - amfs_auto_readdir, /* browsable version of readdir() */ - 0, /* autofs_readlink */ - autofs_mounted, - 0, /* autofs_umounted */ - find_amfs_auto_srvr, - FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO | FS_DIRECTORY -}; - - -/**************************************************************************** - *** FUNCTIONS *** - ****************************************************************************/ - -/* - * Mount the top-level using autofs - */ -int -autofs_mount(am_node *mp) -{ - mntfs *mf = mp->am_mnt; - struct stat stb; - char opts[256], preopts[256]; - int error; - char *mnttype; - - /* - * Mounting the automounter. - * Make sure the mount directory exists, construct - * the mount options and call the mount_autofs routine. - */ - - if (stat(mp->am_path, &stb) < 0) { - return errno; - } else if ((stb.st_mode & S_IFMT) != S_IFDIR) { - plog(XLOG_WARNING, "%s is not a directory", mp->am_path); - return ENOTDIR; - } - if (mf->mf_ops == &autofs_ops) - mnttype = "indirect"; - else if (mf->mf_ops == &amfs_direct_ops) - mnttype = "direct"; -#ifdef HAVE_AMU_FS_UNION - else if (mf->mf_ops == &amfs_union_ops) - mnttype = "union"; -#endif /* HAVE_AMU_FS_UNION */ - else - mnttype = "auto"; - - /* - * Construct some mount options: - * - * Tack on magic map=<mapname> option in mtab to emulate - * SunOS automounter behavior. - */ - preopts[0] = '\0'; -#ifdef MNTTAB_OPT_INTR - strcat(preopts, MNTTAB_OPT_INTR); - strcat(preopts, ","); -#endif /* MNTTAB_OPT_INTR */ -#ifdef MNTTAB_OPT_IGNORE - strcat(preopts, MNTTAB_OPT_IGNORE); - strcat(preopts, ","); -#endif /* MNTTAB_OPT_IGNORE */ - sprintf(opts, "%s%s,%s=%d,%s=%d,%s=%d,%s,map=%s", - preopts, - MNTTAB_OPT_RW, - MNTTAB_OPT_PORT, nfs_port, - MNTTAB_OPT_TIMEO, gopt.amfs_auto_timeo, - MNTTAB_OPT_RETRANS, gopt.amfs_auto_retrans, - mnttype, mf->mf_info); - - /* now do the mount */ - error = mount_autofs(mf->mf_mount, opts); - if (error) { - errno = error; - plog(XLOG_FATAL, "mount_autofs: %m"); - return error; - } - return 0; -} - - -void -autofs_mounted(mntfs *mf) -{ - amfs_auto_mkcacheref(mf); -} - - -/* - * Unmount a top-level automount node - */ -int -autofs_umount(am_node *mp) -{ - int error; - struct stat stb; - - /* - * The lstat is needed if this mount is type=direct. When that happens, - * the kernel cache gets confused between the underlying type (dir) and - * the mounted type (link) and so needs to be re-synced before the - * unmount. This is all because the unmount system call follows links and - * so can't actually unmount a link (stupid!). It was noted that doing an - * ls -ld of the mount point to see why things were not working actually - * fixed the problem - so simulate an ls -ld here. - */ - if (lstat(mp->am_path, &stb) < 0) { -#ifdef DEBUG - dlog("lstat(%s): %m", mp->am_path); -#endif /* DEBUG */ - } - error = UMOUNT_FS(mp->am_path, mnttab_file_name); - if (error == EBUSY && mp->am_flags & AMF_AUTOFS) { - plog(XLOG_WARNING, "autofs_unmount of %s busy (autofs). exit", mp->am_path); - error = 0; /* fake unmount was ok */ - } - return error; -} - - -/* - * Mount an automounter directory. - * The automounter is connected into the system - * as a user-level NFS server. mount_autofs constructs - * the necessary NFS parameters to be given to the - * kernel so that it will talk back to us. - */ -static int -mount_autofs(char *dir, char *opts) -{ - char fs_hostname[MAXHOSTNAMELEN + MAXPATHLEN + 1]; - char *map_opt, buf[MAXHOSTNAMELEN]; - int retry, error, flags; - struct utsname utsname; - mntent_t mnt; - autofs_args_t autofs_args; - MTYPE_TYPE type = MOUNT_TYPE_AUTOFS; - - memset((voidp) &autofs_args, 0, sizeof(autofs_args)); /* Paranoid */ - - memset((voidp) &mnt, 0, sizeof(mnt)); - mnt.mnt_dir = dir; - mnt.mnt_fsname = pid_fsname; - mnt.mnt_opts = opts; - mnt.mnt_type = type; - - retry = hasmntval(&mnt, "retry"); - if (retry <= 0) - retry = 2; /* XXX */ - - /* - * SET MOUNT ARGS - */ - if (uname(&utsname) < 0) { - strcpy(buf, "localhost.autofs"); - } else { - strcpy(buf, utsname.nodename); - strcat(buf, ".autofs"); - } -#ifdef HAVE_FIELD_AUTOFS_ARGS_T_ADDR - autofs_args.addr.buf = buf; - autofs_args.addr.len = strlen(autofs_args.addr.buf); - autofs_args.addr.maxlen = autofs_args.addr.len; -#endif /* HAVE_FIELD_AUTOFS_ARGS_T_ADDR */ - - autofs_args.path = dir; - autofs_args.opts = opts; - - map_opt = hasmntopt(&mnt, "map"); - if (map_opt) { - map_opt += sizeof("map="); /* skip the "map=" */ - if (map_opt == NULL) { - plog(XLOG_WARNING, "map= has a null map name. reset to amd.unknown"); - map_opt = "amd.unknown"; - } - } - autofs_args.map = map_opt; - - /* XXX: these I set arbitrarily... */ - autofs_args.mount_to = 300; - autofs_args.rpc_to = 60; - autofs_args.direct = 0; - - /* - * Make a ``hostname'' string for the kernel - */ - sprintf(fs_hostname, "pid%ld@%s:%s", - (long) (foreground ? am_mypid : getppid()), - am_get_hostname(), dir); - - /* - * Most kernels have a name length restriction. - */ - if (strlen(fs_hostname) >= MAXHOSTNAMELEN) - strcpy(fs_hostname + MAXHOSTNAMELEN - 3, ".."); - - /* - * Finally we can compute the mount flags set above. - */ - flags = compute_mount_flags(&mnt); - - /* - * This is it! Here we try to mount amd on its mount points. - */ - error = mount_fs(&mnt, flags, (caddr_t) &autofs_args, retry, type, 0, NULL, mnttab_file_name); - return error; -} - - -/****************************************************************************/ -/* autofs program dispatcher */ -void -autofs_program_1(struct svc_req *rqstp, SVCXPRT *transp) -{ - int ret; - union { - mntrequest autofs_mount_1_arg; - umntrequest autofs_umount_1_arg; - } argument; - union { - mntres mount_res; - umntres umount_res; - } result; - - bool_t (*xdr_argument)(), (*xdr_result)(); - int (*local)(); - - switch (rqstp->rq_proc) { - - case AUTOFS_NULL: - svc_sendreply(transp, - (XDRPROC_T_TYPE) xdr_void, - (SVC_IN_ARG_TYPE) NULL); - return; - - case AUTOFS_MOUNT: - xdr_argument = xdr_mntrequest; - xdr_result = xdr_mntres; - local = (int (*)()) autofs_mount_1_svc; - break; - - case AUTOFS_UNMOUNT: - xdr_argument = xdr_umntrequest; - xdr_result = xdr_umntres; - local = (int (*)()) autofs_unmount_1_svc; - break; - - default: - svcerr_noproc(transp); - return; - } - - memset((char *) &argument, 0, sizeof(argument)); - if (!svc_getargs(transp, - (XDRPROC_T_TYPE) xdr_argument, - (SVC_IN_ARG_TYPE) &argument)) { - plog(XLOG_ERROR, - "AUTOFS xdr decode failed for %d %d %d", - (int) rqstp->rq_prog, (int) rqstp->rq_vers, (int) rqstp->rq_proc); - svcerr_decode(transp); - return; - } - - ret = (*local) (&argument, &result, rqstp); - if (!svc_sendreply(transp, - (XDRPROC_T_TYPE) xdr_result, - (SVC_IN_ARG_TYPE) &result)) { - svcerr_systemerr(transp); - } - - if (!svc_freeargs(transp, - (XDRPROC_T_TYPE) xdr_argument, - (SVC_IN_ARG_TYPE) &argument)) { - plog(XLOG_FATAL, "unable to free rpc arguments in autofs_program_1"); - going_down(1); - } -} - - -static int -autofs_mount_1_svc(struct mntrequest *mr, struct mntres *result, struct authunix_parms *cred) -{ - int err = 0; - am_node *anp, *anp2; - - plog(XLOG_INFO, "XXX: autofs_mount_1_svc: %s:%s:%s:%s", - mr->map, mr->name, mr->opts, mr->path); - - /* look for map (eg. "/home") */ - anp = find_ap(mr->path); - if (!anp) { - plog(XLOG_ERROR, "map %s not found", mr->path); - err = ENOENT; - goto out; - } - /* turn on autofs in map flags */ - if (!(anp->am_flags & AMF_AUTOFS)) { - plog(XLOG_INFO, "turning on AMF_AUTOFS for node %s", mr->path); - anp->am_flags |= AMF_AUTOFS; - } - - /* - * Look for (and create if needed) the new node. - * - * If an error occurred, return it. If a -1 was returned, that indicates - * that a mount is in progress, so sleep a while (while the backgrounded - * mount is happening), and then signal the autofs to retry the mount. - * - * There's something I don't understand. I was thinking that this code - * here is the one which will succeed eventually and will send an RPC - * reply to the kernel, but apparently that happens somewhere else, not - * here. It works though, just that I don't know how. Arg. -Erez. - * */ - err = 0; - anp2 = autofs_lookuppn(anp, mr->name, &err, VLOOK_CREATE); - if (!anp2) { - if (err == -1) { /* then tell autofs to retry */ - sleep(1); - err = EAGAIN; - } - goto out; - } - -out: - result->status = err; - return err; -} - - -static int -autofs_unmount_1_svc(struct umntrequest *ur, struct umntres *result, struct authunix_parms *cred) -{ - int err = 0; - -#ifdef HAVE_FIELD_UMNTREQUEST_RDEVID - plog(XLOG_INFO, "XXX: autofs_unmount_1_svc: %d:%lu:%lu:0x%lx", - ur->isdirect, (unsigned long) ur->devid, (unsigned long) ur->rdevid, - (unsigned long) ur->next); -#else /* HAVE_FIELD_UMNTREQUEST_RDEVID */ - plog(XLOG_INFO, "XXX: autofs_unmount_1_svc: %d:%lu:0x%lx", - ur->isdirect, (unsigned long) ur->devid, - (unsigned long) ur->next); -#endif /* HAVE_FIELD_UMNTREQUEST_RDEVID */ - - err = EINVAL; /* XXX: not implemented yet */ - goto out; - -out: - result->status = err; - return err; -} - - -/* - * Pick a file system to try mounting and - * do that in the background if necessary - * - For each location: - if it is new -defaults then - extract and process - continue; - fi - if it is a cut then - if a location has been tried then - break; - fi - continue; - fi - parse mount location - discard previous mount location if required - find matching mounted filesystem - if not applicable then - this_error = No such file or directory - continue - fi - if the filesystem failed to be mounted then - this_error = error from filesystem - elif the filesystem is mounting or unmounting then - this_error = -1 - elif the fileserver is down then - this_error = -1 - elif the filesystem is already mounted - this_error = 0 - break - fi - if no error on this mount then - this_error = initialize mount point - fi - if no error on this mount and mount is delayed then - this_error = -1 - fi - if this_error < 0 then - retry = true - fi - if no error on this mount then - make mount point if required - fi - if no error on this mount then - if mount in background then - run mount in background - return -1 - else - this_error = mount in foreground - fi - fi - if an error occurred on this mount then - update stats - save error in mount point - fi - endfor - */ -static int -autofs_bgmount(struct continuation *cp, int mpe) -{ - mntfs *mf = cp->mp->am_mnt; /* Current mntfs */ - mntfs *mf_retry = 0; /* First mntfs which needed retrying */ - int this_error = -1; /* Per-mount error */ - int hard_error = -1; - int mp_error = mpe; - - /* - * Try to mount each location. - * At the end: - * hard_error == 0 indicates something was mounted. - * hard_error > 0 indicates everything failed with a hard error - * hard_error < 0 indicates nothing could be mounted now - */ - for (; this_error && *cp->ivec; cp->ivec++) { - am_ops *p; - am_node *mp = cp->mp; - char *link_dir; - int dont_retry; - - if (hard_error < 0) - hard_error = this_error; - - this_error = -1; - - if (**cp->ivec == '-') { - /* - * Pick up new defaults - */ - if (cp->auto_opts && *cp->auto_opts) - cp->def_opts = str3cat(cp->def_opts, cp->auto_opts, ";", *cp->ivec + 1); - else - cp->def_opts = strealloc(cp->def_opts, *cp->ivec + 1); -#ifdef DEBUG - dlog("Setting def_opts to \"%s\"", cp->def_opts); -#endif /* DEBUG */ - continue; - } - /* - * If a mount has been attempted, and we find - * a cut then don't try any more locations. - */ - if (STREQ(*cp->ivec, "/") || STREQ(*cp->ivec, "||")) { - if (cp->tried) { -#ifdef DEBUG - dlog("Cut: not trying any more locations for %s", - mp->am_path); -#endif /* DEBUG */ - break; - } - continue; - } - - /* match the operators */ - p = ops_match(&cp->fs_opts, *cp->ivec, cp->def_opts, mp->am_path, cp->key, mp->am_parent->am_mnt->mf_info); - - /* - * Find a mounted filesystem for this node. - */ - mp->am_mnt = mf = realloc_mntfs(mf, p, &cp->fs_opts, - cp->fs_opts.opt_fs, - cp->fs_opts.fs_mtab, - cp->auto_opts, - cp->fs_opts.opt_opts, - cp->fs_opts.opt_remopts); - - p = mf->mf_ops; -#ifdef DEBUG - dlog("Got a hit with %s", p->fs_type); -#endif /* DEBUG */ - - /* - * Note whether this is a real mount attempt - */ - if (p == &amfs_error_ops) { - plog(XLOG_MAP, "Map entry %s for %s did not match", *cp->ivec, mp->am_path); - if (this_error <= 0) - this_error = ENOENT; - continue; - } else { - if (cp->fs_opts.fs_mtab) { - plog(XLOG_MAP, "Trying mount of %s on \"%s\" fstype %s", - cp->fs_opts.fs_mtab, mp->am_path, p->fs_type); - } - cp->tried = TRUE; - } - - this_error = 0; - dont_retry = FALSE; - - if (mp->am_link) { - XFREE(mp->am_link); - mp->am_link = 0; - } - link_dir = mf->mf_fo->opt_sublink; - - if (link_dir && *link_dir) { - if (*link_dir == '/') { - mp->am_link = strdup(link_dir); - } else { - /* - * try getting fs option from continuation, not mountpoint! - * Don't try logging the string from mf, since it may be bad! - */ - if (cp->fs_opts.opt_fs != mf->mf_fo->opt_fs) - plog(XLOG_ERROR, "use %s instead of 0x%lx", - cp->fs_opts.opt_fs, (unsigned long) mf->mf_fo->opt_fs); - - mp->am_link = str3cat((char *) 0, - cp->fs_opts.opt_fs, "/", link_dir); - - normalize_slash(mp->am_link); - } - } - - if (mf->mf_error > 0) { - this_error = mf->mf_error; - } else if (mf->mf_flags & (MFF_MOUNTING | MFF_UNMOUNTING)) { - /* - * Still mounting - retry later - */ -#ifdef DEBUG - dlog("Duplicate pending mount fstype %s", p->fs_type); -#endif /* DEBUG */ - this_error = -1; - } else if (FSRV_ISDOWN(mf->mf_server)) { - /* - * Would just mount from the same place - * as a hung mount - so give up - */ -#ifdef DEBUG - dlog("%s is already hung - giving up", mf->mf_mount); -#endif /* DEBUG */ - mp_error = EWOULDBLOCK; - dont_retry = TRUE; - this_error = -1; - } else if (mf->mf_flags & MFF_MOUNTED) { -#ifdef DEBUG - dlog("duplicate mount of \"%s\" ...", mf->mf_info); -#endif /* DEBUG */ - - /* - * Just call mounted() - */ - am_mounted(mp); - - this_error = 0; - break; - } - - /* - * Will usually need to play around with the mount nodes - * file attribute structure. This must be done here. - * Try and get things initialized, even if the fileserver - * is not known to be up. In the common case this will - * progress things faster. - */ - if (!this_error) { - /* - * Fill in attribute fields. - */ - if (mf->mf_ops->fs_flags & FS_DIRECTORY) - mk_fattr(mp, NFDIR); - else - mk_fattr(mp, NFLNK); - - if (p->fs_init) - this_error = (*p->fs_init) (mf); - } - - /* - * Make sure the fileserver is UP before doing any more work - */ - if (!FSRV_ISUP(mf->mf_server)) { -#ifdef DEBUG - dlog("waiting for server %s to become available", mf->mf_server->fs_host); -#endif /* DEBUG */ - this_error = -1; - } - - if (!this_error && mf->mf_fo->opt_delay) { - /* - * If there is a delay timer on the mount - * then don't try to mount if the timer - * has not expired. - */ - int i = atoi(mf->mf_fo->opt_delay); - if (i > 0 && clocktime() < (cp->start + i)) { -#ifdef DEBUG - dlog("Mount of %s delayed by %lds", mf->mf_mount, i - clocktime() + cp->start); -#endif /* DEBUG */ - this_error = -1; - } - } - - if (this_error < 0 && !dont_retry) { - if (!mf_retry) - mf_retry = dup_mntfs(mf); - cp->retry = TRUE; - } - - if (!this_error) { - if (p->fs_flags & FS_MBACKGROUND) { - mf->mf_flags |= MFF_MOUNTING; /* XXX */ -#ifdef DEBUG - dlog("backgrounding mount of \"%s\"", mf->mf_mount); -#endif /* DEBUG */ - if (cp->callout) { - untimeout(cp->callout); - cp->callout = 0; - } - run_task(try_mount, (voidp) mp, amfs_auto_cont, (voidp) cp); - mf->mf_flags |= MFF_MKMNT; /* XXX */ - if (mf_retry) - free_mntfs(mf_retry); - return -1; - } else { -#ifdef DEBUG - dlog("foreground mount of \"%s\" ...", mf->mf_info); -#endif /* DEBUG */ - this_error = try_mount((voidp) mp); - if (this_error < 0) { - if (!mf_retry) - mf_retry = dup_mntfs(mf); - cp->retry = TRUE; - } - } - } - - if (this_error >= 0) { - if (this_error > 0) { - amd_stats.d_merr++; - if (mf != mf_retry) { - mf->mf_error = this_error; - mf->mf_flags |= MFF_ERROR; - } - } - - /* - * Wakeup anything waiting for this mount - */ - wakeup((voidp) mf); - } - } - - if (this_error && cp->retry) { - free_mntfs(mf); - mf = cp->mp->am_mnt = mf_retry; - /* - * Not retrying again (so far) - */ - cp->retry = FALSE; - cp->tried = FALSE; - /* - * Start at the beginning. - * Rewind the location vector and - * reset the default options. - */ - cp->ivec = cp->xivec; - cp->def_opts = strealloc(cp->def_opts, cp->auto_opts); - /* - * Arrange that autofs_bgmount is called - * after anything else happens. - */ -#ifdef DEBUG - dlog("Arranging to retry mount of %s", cp->mp->am_path); -#endif /* DEBUG */ - sched_task(amfs_auto_retry, (voidp) cp, (voidp) mf); - if (cp->callout) - untimeout(cp->callout); - cp->callout = timeout(RETRY_INTERVAL, wakeup, (voidp) mf); - - cp->mp->am_ttl = clocktime() + RETRY_INTERVAL; - - /* - * Not done yet - so don't return anything - */ - return -1; - } - - if (hard_error < 0 || this_error == 0) - hard_error = this_error; - - /* - * Discard handle on duff filesystem. - * This should never happen since it - * should be caught by the case above. - */ - if (mf_retry) { - if (hard_error) - plog(XLOG_ERROR, "discarding a retry mntfs for %s", mf_retry->mf_mount); - free_mntfs(mf_retry); - } - - /* - * If we get here, then either the mount succeeded or - * there is no more mount information available. - */ - if (hard_error < 0 && mp_error) - hard_error = cp->mp->am_error = mp_error; - if (hard_error > 0) { - /* - * Set a small(ish) timeout on an error node if - * the error was not a time out. - */ - switch (hard_error) { - case ETIMEDOUT: - case EWOULDBLOCK: - cp->mp->am_timeo = 17; - break; - default: - cp->mp->am_timeo = 5; - break; - } - new_ttl(cp->mp); - } - - /* - * Make sure that the error value in the mntfs has a - * reasonable value. - */ - if (mf->mf_error < 0) { - mf->mf_error = hard_error; - if (hard_error) - mf->mf_flags |= MFF_ERROR; - } - - /* - * In any case we don't need the continuation any more - */ - free_continuation(cp); - - return hard_error; -} - - -/* - * Automount interface to RPC lookup routine - * Find the corresponding entry and return - * the file handle for it. - */ -am_node * -autofs_lookuppn(am_node *mp, char *fname, int *error_return, int op) -{ - am_node *ap, *new_mp, *ap_hung; - char *info; /* Mount info - where to get the file system */ - char **ivec, **xivec; /* Split version of info */ - char *auto_opts; /* Automount options */ - int error = 0; /* Error so far */ - char path_name[MAXPATHLEN]; /* General path name buffer */ - char apath[MAXPATHLEN]; /* autofs path (added space) */ - char *pfname; /* Path for database lookup */ - struct continuation *cp; /* Continuation structure if need to mount */ - int in_progress = 0; /* # of (un)mount in progress */ - char *dflts; - mntfs *mf; - -#ifdef DEBUG - dlog("in autofs_lookuppn"); -#endif /* DEBUG */ - - /* - * If the server is shutting down - * then don't return information - * about the mount point. - */ - if (amd_state == Finishing) { -#ifdef DEBUG - if ((mf = mp->am_mnt) == 0 || mf->mf_ops == &amfs_direct_ops) { - dlog("%s mount ignored - going down", fname); - } else { - dlog("%s/%s mount ignored - going down", mp->am_path, fname); - } -#endif /* DEBUG */ - ereturn(ENOENT); - } - - /* - * Handle special case of "." and ".." - */ - if (fname[0] == '.') { - if (fname[1] == '\0') - return mp; /* "." is the current node */ - if (fname[1] == '.' && fname[2] == '\0') { - if (mp->am_parent) { -#ifdef DEBUG - dlog(".. in %s gives %s", mp->am_path, mp->am_parent->am_path); -#endif /* DEBUG */ - return mp->am_parent; /* ".." is the parent node */ - } - ereturn(ESTALE); - } - } - - /* - * Check for valid key name. - * If it is invalid then pretend it doesn't exist. - */ - if (!valid_key(fname)) { - plog(XLOG_WARNING, "Key \"%s\" contains a disallowed character", fname); - ereturn(ENOENT); - } - - /* - * Expand key name. - * fname is now a private copy. - */ - fname = expand_key(fname); - - for (ap_hung = 0, ap = mp->am_child; ap; ap = ap->am_osib) { - /* - * Otherwise search children of this node - */ - if (FSTREQ(ap->am_name, fname)) { - mf = ap->am_mnt; - if (ap->am_error) { - error = ap->am_error; - continue; - } - /* - * If the error code is undefined then it must be - * in progress. - */ - if (mf->mf_error < 0) - goto in_progrss; - - /* - * Check for a hung node - */ - if (FSRV_ISDOWN(mf->mf_server)) { -#ifdef DEBUG - dlog("server hung"); -#endif /* DEBUG */ - error = ap->am_error; - ap_hung = ap; - continue; - } - /* - * If there was a previous error with this node - * then return that error code. - */ - if (mf->mf_flags & MFF_ERROR) { - error = mf->mf_error; - continue; - } - if (!(mf->mf_flags & MFF_MOUNTED) || (mf->mf_flags & MFF_UNMOUNTING)) { - in_progrss: - /* - * If the fs is not mounted or it is unmounting then there - * is a background (un)mount in progress. In this case - * we just drop the RPC request (return nil) and - * wait for a retry, by which time the (un)mount may - * have completed. - */ -#ifdef DEBUG - dlog("ignoring mount of %s in %s -- flags (%x) in progress", - fname, mf->mf_mount, mf->mf_flags); -#endif /* DEBUG */ - in_progress++; - continue; - } - - /* - * Otherwise we have a hit: return the current mount point. - */ -#ifdef DEBUG - dlog("matched %s in %s", fname, ap->am_path); -#endif /* DEBUG */ - XFREE(fname); - return ap; - } - } - - if (in_progress) { -#ifdef DEBUG - dlog("Waiting while %d mount(s) in progress", in_progress); -#endif /* DEBUG */ - XFREE(fname); - ereturn(-1); - } - - /* - * If an error occurred then return it. - */ - if (error) { -#ifdef DEBUG - errno = error; /* XXX */ - dlog("Returning error: %m"); -#endif /* DEBUG */ - XFREE(fname); - ereturn(error); - } - - /* - * If doing a delete then don't create again! - */ - switch (op) { - case VLOOK_DELETE: - ereturn(ENOENT); - - case VLOOK_CREATE: - break; - - default: - plog(XLOG_FATAL, "Unknown op to autofs_lookuppn: 0x%x", op); - ereturn(EINVAL); - } - - /* - * If the server is going down then just return, - * don't try to mount any more file systems - */ - if ((int) amd_state >= (int) Finishing) { -#ifdef DEBUG - dlog("not found - server going down anyway"); -#endif /* DEBUG */ - XFREE(fname); - ereturn(ENOENT); - } - - /* - * If we get there then this is a reference to an, - * as yet, unknown name so we need to search the mount - * map for it. - */ - if (mp->am_pref) { - sprintf(path_name, "%s%s", mp->am_pref, fname); - pfname = path_name; - } else { - pfname = fname; - } - - mf = mp->am_mnt; - -#ifdef DEBUG - dlog("will search map info in %s to find %s", mf->mf_info, pfname); -#endif /* DEBUG */ - /* - * Consult the oracle for some mount information. - * info is malloc'ed and belongs to this routine. - * It ends up being free'd in free_continuation(). - * - * Note that this may return -1 indicating that information - * is not yet available. - */ - error = mapc_search((mnt_map *) mf->mf_private, pfname, &info); - if (error) { - if (error > 0) - plog(XLOG_MAP, "No map entry for %s", pfname); - else - plog(XLOG_MAP, "Waiting on map entry for %s", pfname); - XFREE(fname); - ereturn(error); - } -#ifdef DEBUG - dlog("mount info is %s", info); -#endif /* DEBUG */ - - /* - * Split info into an argument vector. - * The vector is malloc'ed and belongs to - * this routine. It is free'd in free_continuation() - */ - xivec = ivec = strsplit(info, ' ', '\"'); - - /* - * Default error code... - */ - if (ap_hung) - error = EWOULDBLOCK; - else - error = ENOENT; - - /* - * Allocate a new map - */ - new_mp = exported_ap_alloc(); - if (new_mp == 0) { - XFREE(xivec); - XFREE(info); - XFREE(fname); - ereturn(ENOSPC); - } - if (mf->mf_auto) - auto_opts = mf->mf_auto; - else - auto_opts = ""; - - auto_opts = strdup(auto_opts); - -#ifdef DEBUG - dlog("searching for /defaults entry"); -#endif /* DEBUG */ - if (mapc_search((mnt_map *) mf->mf_private, "/defaults", &dflts) == 0) { - char *dfl; - char **rvec; -#ifdef DEBUG - dlog("/defaults gave %s", dflts); -#endif /* DEBUG */ - if (*dflts == '-') - dfl = dflts + 1; - else - dfl = dflts; - - /* - * Chop the defaults up - */ - rvec = strsplit(dfl, ' ', '\"'); - - if (gopt.flags & CFM_SELECTORS_IN_DEFAULTS) { - /* - * Pick whichever first entry matched the list of selectors. - * Strip the selectors from the string, and assign to dfl the - * rest of the string. - */ - if (rvec) { - am_opts ap; - am_ops *pt; - char **sp = rvec; - while (*sp) { /* loop until you find something, if any */ - memset((char *) &ap, 0, sizeof(am_opts)); - pt = ops_match(&ap, *sp, "", mp->am_path, "/defaults", - mp->am_parent->am_mnt->mf_info); - free_opts(&ap); /* don't leak */ - if (pt == &amfs_error_ops) { - plog(XLOG_MAP, "did not match defaults for \"%s\"", *sp); - } else { - dfl = strip_selectors(*sp, "/defaults"); - plog(XLOG_MAP, "matched default selectors \"%s\"", dfl); - break; - } - ++sp; - } - } - } else { /* not selectors_in_defaults */ - /* - * Extract first value - */ - dfl = rvec[0]; - } - - /* - * If there were any values at all... - */ - if (dfl) { - /* - * Log error if there were other values - */ - if (!(gopt.flags & CFM_SELECTORS_IN_DEFAULTS) && rvec[1]) { -# ifdef DEBUG - dlog("/defaults chopped into %s", dfl); -# endif /* DEBUG */ - plog(XLOG_USER, "More than a single value for /defaults in %s", mf->mf_info); - } - - /* - * Prepend to existing defaults if they exist, - * otherwise just use these defaults. - */ - if (*auto_opts && *dfl) { - char *nopts = (char *) xmalloc(strlen(auto_opts) + strlen(dfl) + 2); - sprintf(nopts, "%s;%s", dfl, auto_opts); - XFREE(auto_opts); - auto_opts = nopts; - } else if (*dfl) { - auto_opts = strealloc(auto_opts, dfl); - } - } - XFREE(dflts); - /* - * Don't need info vector any more - */ - XFREE(rvec); - } - - /* - * Fill it in - */ - init_map(new_mp, fname); - - /* - * Turn on autofs flag if needed. - */ - if (mp->am_flags & AMF_AUTOFS) { - new_mp->am_flags |= AMF_AUTOFS; - } - - /* - * Put it in the table - */ - insert_am(new_mp, mp); - - /* - * Fill in some other fields, - * path and mount point. - * - * bugfix: do not prepend old am_path if direct map - * <wls@astro.umd.edu> William Sebok - */ - - strcpy(apath, fname); - strcat(apath, " "); - new_mp->am_path = str3cat(new_mp->am_path, - mf->mf_ops == &amfs_direct_ops ? "" : mp->am_path, - *fname == '/' ? "" : "/", - apath); - -#ifdef DEBUG - dlog("setting path to \"%s\"", new_mp->am_path); -#endif /* DEBUG */ - - /* - * Take private copy of pfname - */ - pfname = strdup(pfname); - - /* - * Construct a continuation - */ - cp = ALLOC(struct continuation); - cp->callout = 0; - cp->mp = new_mp; - cp->xivec = xivec; - cp->ivec = ivec; - cp->info = info; - cp->key = pfname; - cp->auto_opts = auto_opts; - cp->retry = FALSE; - cp->tried = FALSE; - cp->start = clocktime(); - cp->def_opts = strdup(auto_opts); - memset((voidp) &cp->fs_opts, 0, sizeof(cp->fs_opts)); - - /* - * Try and mount the file system. If this succeeds immediately (possible - * for a ufs file system) then return the attributes, otherwise just - * return an error. - */ - error = autofs_bgmount(cp, error); - reschedule_timeout_mp(); - if (!error) { - XFREE(fname); - return new_mp; - } - - /* - * Code for quick reply. If nfs_program_2_transp is set, then - * its the transp that's been passed down from nfs_program_2(). - * If new_mp->am_transp is not already set, set it by copying in - * nfs_program_2_transp. Once am_transp is set, quick_reply() can - * use it to send a reply to the client that requested this mount. - */ - if (nfs_program_2_transp && !new_mp->am_transp) { - new_mp->am_transp = (SVCXPRT *) xmalloc(sizeof(SVCXPRT)); - *(new_mp->am_transp) = *nfs_program_2_transp; - } - if (error && (new_mp->am_mnt->mf_ops == &amfs_error_ops)) - new_mp->am_error = error; - - assign_error_mntfs(new_mp); - - XFREE(fname); - - ereturn(error); -} -#endif /* HAVE_FS_AUTOFS */ diff --git a/contrib/amd/amd/ops_cachefs.c b/contrib/amd/amd/ops_cachefs.c deleted file mode 100644 index d3e303bc2bf9..000000000000 --- a/contrib/amd/amd/ops_cachefs.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/ops_cachefs.c - * - */ - -/* - * Caching filesystem (Solaris 2.x) - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* forward declarations */ -static char *cachefs_match(am_opts *fo); -static int cachefs_init(mntfs *mf); -static int cachefs_mount(am_node *am, mntfs *mf); -static int cachefs_umount(am_node *am, mntfs *mf); - - -/* - * Ops structure - */ -am_ops cachefs_ops = -{ - "cachefs", - cachefs_match, - cachefs_init, - cachefs_mount, - cachefs_umount, - amfs_error_lookup_child, - amfs_error_mount_child, - amfs_error_readdir, - 0, /* cachefs_readlink */ - 0, /* cachefs_mounted */ - 0, /* cachefs_umounted */ - amfs_generic_find_srvr, - 0, /* cachefs_get_wchan */ - FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */ -#ifdef HAVE_FS_AUTOFS - AUTOFS_CACHEFS_FS_FLAGS, -#endif /* HAVE_FS_AUTOFS */ -}; - - -/* - * Check that f/s has all needed fields. - * Returns: matched string if found, NULL otherwise. - */ -static char * -cachefs_match(am_opts *fo) -{ - /* sanity check */ - if (!fo->opt_rfs || !fo->opt_fs || !fo->opt_cachedir) { - plog(XLOG_USER, "cachefs: must specify cachedir, rfs, and fs"); - return NULL; - } - - dlog("CACHEFS: using cache directory \"%s\"", fo->opt_cachedir); - - /* determine magic cookie to put in mtab */ - return strdup(fo->opt_cachedir); -} - - -/* - * Initialize. - * Returns: 0 if OK, non-zero (errno) if failed. - */ -static int -cachefs_init(mntfs *mf) -{ - /* - * Save cache directory name - */ - if (!mf->mf_private) { - mf->mf_private = (voidp) strdup(mf->mf_fo->opt_cachedir); - mf->mf_prfree = (void (*)(voidp)) free; - } - - return 0; -} - - -/* - * mntpt is the mount point ($fs) [XXX: was 'dir'] - * backdir is the mounted pathname ($rfs) [XXX: was 'fs_name'] - * cachedir is the cache directory ($cachedir) - */ -static int -mount_cachefs(char *mntdir, char *backdir, char *cachedir, - char *opts, int on_autofs) -{ - cachefs_args_t ca; - mntent_t mnt; - int flags; - char *cp; - MTYPE_TYPE type = MOUNT_TYPE_CACHEFS; /* F/S mount type */ - - memset((voidp) &ca, 0, sizeof(ca)); /* Paranoid */ - - /* - * Fill in the mount structure - */ - memset((voidp) &mnt, 0, sizeof(mnt)); - mnt.mnt_dir = mntdir; - mnt.mnt_fsname = backdir; - mnt.mnt_type = MNTTAB_TYPE_CACHEFS; - mnt.mnt_opts = opts; - - flags = compute_mount_flags(&mnt); -#ifdef HAVE_FS_AUTOFS - if (on_autofs) - flags |= autofs_compute_mount_flags(&mnt); -#endif /* HAVE_FS_AUTOFS */ - - /* Fill in cachefs mount arguments */ - - /* - * XXX: Caveats - * (1) cache directory is NOT checked for sanity beforehand, nor is it - * purged. Maybe it should be purged first? - * (2) cache directory is NOT locked. Should we? - */ - - /* mount flags */ - ca.cfs_options.opt_flags = CFS_WRITE_AROUND | CFS_ACCESS_BACKFS; - /* cache population size */ - ca.cfs_options.opt_popsize = DEF_POP_SIZE; /* default: 64K */ - /* filegrp size */ - ca.cfs_options.opt_fgsize = DEF_FILEGRP_SIZE; /* default: 256 */ - - /* CFS ID for file system (must be unique) */ - ca.cfs_fsid = cachedir; - - /* CFS fscdir name */ - memset(ca.cfs_cacheid, 0, sizeof(ca.cfs_cacheid)); - /* - * Append cacheid and mountpoint. - * sizeof(cfs_cacheid) should be C_MAX_MOUNT_FSCDIRNAME as per - * <sys/fs/cachefs_fs.h> (checked on Solaris 8). - */ - xsnprintf(ca.cfs_cacheid, sizeof(ca.cfs_cacheid), - "%s:%s", ca.cfs_fsid, mntdir); - /* convert '/' to '_' (Solaris does that...) */ - cp = ca.cfs_cacheid; - while ((cp = strpbrk(cp, "/")) != NULL) - *cp = '_'; - - /* path for this cache dir */ - ca.cfs_cachedir = cachedir; - - /* back filesystem dir */ - ca.cfs_backfs = backdir; - - /* same as nfs values (XXX: need to handle these options) */ - ca.cfs_acregmin = 0; - ca.cfs_acregmax = 0; - ca.cfs_acdirmin = 0; - ca.cfs_acdirmax = 0; - - /* - * Call generic mount routine - */ - return mount_fs(&mnt, flags, (caddr_t) &ca, 0, type, 0, NULL, mnttab_file_name, on_autofs); -} - - -static int -cachefs_mount(am_node *am, mntfs *mf) -{ - int on_autofs = mf->mf_flags & MFF_ON_AUTOFS; - int error; - - error = mount_cachefs(mf->mf_mount, - mf->mf_fo->opt_rfs, - mf->mf_fo->opt_cachedir, - mf->mf_mopts, - on_autofs); - if (error) { - errno = error; - /* according to Solaris, if errno==ESRCH, "options to not match" */ - if (error == ESRCH) - plog(XLOG_ERROR, "mount_cachefs: options to no match: %m"); - else - plog(XLOG_ERROR, "mount_cachefs: %m"); - return error; - } - - return 0; -} - - -static int -cachefs_umount(am_node *am, mntfs *mf) -{ - int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0; - int error; - - error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags); - - /* - * In the case of cachefs, we must fsck the cache directory. Otherwise, - * it will remain inconsistent, and the next cachefs mount will fail - * with the error "no space left on device" (ENOSPC). - * - * XXX: this is hacky! use fork/exec/wait instead... - */ - if (!error) { - char *cachedir = NULL; - char cmd[128]; - - cachedir = (char *) mf->mf_private; - plog(XLOG_INFO, "running fsck on cache directory \"%s\"", cachedir); - xsnprintf(cmd, sizeof(cmd), "fsck -F cachefs %s", cachedir); - system(cmd); - } - - return error; -} diff --git a/contrib/amd/amd/ops_cdfs.c b/contrib/amd/amd/ops_cdfs.c deleted file mode 100644 index 40355ac5c078..000000000000 --- a/contrib/amd/amd/ops_cdfs.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/ops_cdfs.c - * - */ - -/* - * High Sierra (CD-ROM) file system - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* forward declarations */ -static char *cdfs_match(am_opts *fo); -static int cdfs_mount(am_node *am, mntfs *mf); -static int cdfs_umount(am_node *am, mntfs *mf); - -/* - * Ops structure - */ -am_ops cdfs_ops = -{ - "cdfs", - cdfs_match, - 0, /* cdfs_init */ - cdfs_mount, - cdfs_umount, - amfs_error_lookup_child, - amfs_error_mount_child, - amfs_error_readdir, - 0, /* cdfs_readlink */ - 0, /* cdfs_mounted */ - 0, /* cdfs_umounted */ - amfs_generic_find_srvr, - 0, /* cdfs_get_wchan */ - FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */ -#ifdef HAVE_FS_AUTOFS - AUTOFS_CDFS_FS_FLAGS, -#endif /* HAVE_FS_AUTOFS */ -}; - - -/* - * CDFS needs remote filesystem. - */ -static char * -cdfs_match(am_opts *fo) -{ - if (!fo->opt_dev) { - plog(XLOG_USER, "cdfs: no source device specified"); - return 0; - } - dlog("CDFS: mounting device \"%s\" on \"%s\"", - fo->opt_dev, fo->opt_fs); - - /* - * Determine magic cookie to put in mtab - */ - return strdup(fo->opt_dev); -} - - -static int -mount_cdfs(char *mntdir, char *fs_name, char *opts, int on_autofs) -{ - cdfs_args_t cdfs_args; - mntent_t mnt; - int genflags, cdfs_flags, retval; - - /* - * Figure out the name of the file system type. - */ - MTYPE_TYPE type = MOUNT_TYPE_CDFS; - - memset((voidp) &cdfs_args, 0, sizeof(cdfs_args)); /* Paranoid */ - cdfs_flags = 0; - - /* - * Fill in the mount structure - */ - memset((voidp) &mnt, 0, sizeof(mnt)); - mnt.mnt_dir = mntdir; - mnt.mnt_fsname = fs_name; - mnt.mnt_type = MNTTAB_TYPE_CDFS; - mnt.mnt_opts = opts; - -#if defined(MNT2_CDFS_OPT_DEFPERM) && defined(MNTTAB_OPT_DEFPERM) - if (amu_hasmntopt(&mnt, MNTTAB_OPT_DEFPERM)) -# ifdef MNT2_CDFS_OPT_DEFPERM - cdfs_flags |= MNT2_CDFS_OPT_DEFPERM; -# else /* not MNT2_CDFS_OPT_DEFPERM */ - cdfs_flags &= ~MNT2_CDFS_OPT_NODEFPERM; -# endif /* not MNT2_CDFS_OPT_DEFPERM */ -#endif /* defined(MNT2_CDFS_OPT_DEFPERM) && defined(MNTTAB_OPT_DEFPERM) */ - -#if defined(MNT2_CDFS_OPT_NODEFPERM) && defined(MNTTAB_OPT_NODEFPERM) - if (amu_hasmntopt(&mnt, MNTTAB_OPT_NODEFPERM)) - cdfs_flags |= MNT2_CDFS_OPT_NODEFPERM; -#endif /* MNTTAB_OPT_NODEFPERM */ - -#if defined(MNT2_CDFS_OPT_NOVERSION) && defined(MNTTAB_OPT_NOVERSION) - if (amu_hasmntopt(&mnt, MNTTAB_OPT_NOVERSION)) - cdfs_flags |= MNT2_CDFS_OPT_NOVERSION; -#endif /* defined(MNT2_CDFS_OPT_NOVERSION) && defined(MNTTAB_OPT_NOVERSION) */ - -#if defined(MNT2_CDFS_OPT_RRIP) && defined(MNTTAB_OPT_RRIP) - if (amu_hasmntopt(&mnt, MNTTAB_OPT_RRIP)) - cdfs_flags |= MNT2_CDFS_OPT_RRIP; -#endif /* defined(MNT2_CDFS_OPT_RRIP) && defined(MNTTAB_OPT_RRIP) */ -#if defined(MNT2_CDFS_OPT_NORRIP) && defined(MNTTAB_OPT_NORRIP) - if (amu_hasmntopt(&mnt, MNTTAB_OPT_NORRIP)) - cdfs_flags |= MNT2_CDFS_OPT_NORRIP; -#endif /* defined(MNT2_CDFS_OPT_NORRIP) && defined(MNTTAB_OPT_NORRIP) */ - -#if defined(MNT2_CDFS_OPT_GENS) && defined(MNTTAB_OPT_GENS) - if (amu_hasmntopt(&mnt, MNTTAB_OPT_GENS)) - cdfs_flags |= MNT2_CDFS_OPT_GENS; -#endif /* defined(MNT2_CDFS_OPT_GENS) && defined(MNTTAB_OPT_GENS) */ -#if defined(MNT2_CDFS_OPT_EXTATT) && defined(MNTTAB_OPT_EXTATT) - if (amu_hasmntopt(&mnt, MNTTAB_OPT_EXTATT)) - cdfs_flags |= MNT2_CDFS_OPT_EXTATT; -#endif /* defined(MNT2_CDFS_OPT_EXTATT) && defined(MNTTAB_OPT_EXTATT) */ - - genflags = compute_mount_flags(&mnt); -#ifdef HAVE_FS_AUTOFS - if (on_autofs) - genflags |= autofs_compute_mount_flags(&mnt); -#endif /* HAVE_FS_AUTOFS */ - -#ifdef HAVE_CDFS_ARGS_T_FLAGS - cdfs_args.flags = cdfs_flags; -#endif /* HAVE_CDFS_ARGS_T_FLAGS */ - -#ifdef HAVE_CDFS_ARGS_T_ISO_FLAGS - cdfs_args.iso_flags = genflags | cdfs_flags; -#endif /* HAVE_CDFS_ARGS_T_ISO_FLAGS */ - -#ifdef HAVE_CDFS_ARGS_T_ISO_PGTHRESH - cdfs_args.iso_pgthresh = hasmntval(&mnt, MNTTAB_OPT_PGTHRESH); -#endif /* HAVE_CDFS_ARGS_T_ISO_PGTHRESH */ - -#ifdef HAVE_CDFS_ARGS_T_NORRIP - /* XXX: need to provide norrip mount opt */ - cdfs_args.norrip = 0; /* use Rock-Ridge Protocol extensions */ -#endif /* HAVE_CDFS_ARGS_T_NORRIP */ - -#ifdef HAVE_CDFS_ARGS_T_SSECTOR - /* XXX: need to provide ssector mount option */ - cdfs_args.ssector = 0; /* use 1st session on disk */ -#endif /* HAVE_CDFS_ARGS_T_SSECTOR */ - -#ifdef HAVE_CDFS_ARGS_T_FSPEC - cdfs_args.fspec = fs_name; -#endif /* HAVE_CDFS_ARGS_T_FSPEC */ - - /* - * Call generic mount routine - */ - retval = mount_fs(&mnt, genflags, (caddr_t) &cdfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs); - - return retval; -} - - -static int -cdfs_mount(am_node *am, mntfs *mf) -{ - int on_autofs = mf->mf_flags & MFF_ON_AUTOFS; - int error; - - error = mount_cdfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs); - if (error) { - errno = error; - plog(XLOG_ERROR, "mount_cdfs: %m"); - return error; - } - return 0; -} - - -static int -cdfs_umount(am_node *am, mntfs *mf) -{ - int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0; - - return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags); -} diff --git a/contrib/amd/amd/ops_efs.c b/contrib/amd/amd/ops_efs.c deleted file mode 100644 index 047fe1e4690c..000000000000 --- a/contrib/amd/amd/ops_efs.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/ops_efs.c - * - */ - -/* - * Irix UN*X file system: EFS (Extent File System) - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* forward declarations */ -static char *efs_match(am_opts *fo); -static int efs_mount(am_node *am, mntfs *mf); -static int efs_umount(am_node *am, mntfs *mf); - -/* - * Ops structure - */ -am_ops efs_ops = -{ - "efs", - efs_match, - 0, /* efs_init */ - efs_mount, - efs_umount, - amfs_error_lookup_child, - amfs_error_mount_child, - amfs_error_readdir, - 0, /* efs_readlink */ - 0, /* efs_mounted */ - 0, /* efs_umounted */ - amfs_generic_find_srvr, - 0, /* efs_get_wchan */ - FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */ -#ifdef HAVE_FS_AUTOFS - AUTOFS_EFS_FS_FLAGS, -#endif /* HAVE_FS_AUTOFS */ -}; - - -/* - * EFS needs local filesystem and device. - */ -static char * -efs_match(am_opts *fo) -{ - - if (!fo->opt_dev) { - plog(XLOG_USER, "efs: no device specified"); - return 0; - } - - dlog("EFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs); - - /* - * Determine magic cookie to put in mtab - */ - return strdup(fo->opt_dev); -} - - -static int -mount_efs(char *mntdir, char *fs_name, char *opts, int on_autofs) -{ - efs_args_t efs_args; - mntent_t mnt; - int flags; - - /* - * Figure out the name of the file system type. - */ - MTYPE_TYPE type = MOUNT_TYPE_EFS; - - memset((voidp) &efs_args, 0, sizeof(efs_args)); /* Paranoid */ - - /* - * Fill in the mount structure - */ - memset((voidp) &mnt, 0, sizeof(mnt)); - mnt.mnt_dir = mntdir; - mnt.mnt_fsname = fs_name; - mnt.mnt_type = MNTTAB_TYPE_EFS; - mnt.mnt_opts = opts; - - flags = compute_mount_flags(&mnt); -#ifdef HAVE_FS_AUTOFS - if (on_autofs) - flags |= autofs_compute_mount_flags(&mnt); -#endif /* HAVE_FS_AUTOFS */ - -#ifdef HAVE_EFS_ARGS_T_FLAGS - efs_args.flags = 0; /* XXX: fix this to correct flags */ -#endif /* HAVE_EFS_ARGS_T_FLAGS */ -#ifdef HAVE_EFS_ARGS_T_FSPEC - efs_args.fspec = fs_name; -#endif /* HAVE_EFS_ARGS_T_FSPEC */ - - /* - * Call generic mount routine - */ - return mount_fs(&mnt, flags, (caddr_t) &efs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs); -} - - -static int -efs_mount(am_node *am, mntfs *mf) -{ - int on_autofs = mf->mf_flags & MFF_ON_AUTOFS; - int error; - - error = mount_efs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs); - if (error) { - errno = error; - plog(XLOG_ERROR, "mount_efs: %m"); - return error; - } - - return 0; -} - - -static int -efs_umount(am_node *am, mntfs *mf) -{ - int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0; - - return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags); -} - diff --git a/contrib/amd/amd/ops_lofs.c b/contrib/amd/amd/ops_lofs.c deleted file mode 100644 index 26fdc9f9b626..000000000000 --- a/contrib/amd/amd/ops_lofs.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/ops_lofs.c - * - */ - -/* - * Loopback file system - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* forward definitions */ -static char *lofs_match(am_opts *fo); -static int lofs_mount(am_node *am, mntfs *mf); -static int lofs_umount(am_node *am, mntfs *mf); - -/* - * Ops structure - */ -am_ops lofs_ops = -{ - "lofs", - lofs_match, - 0, /* lofs_init */ - lofs_mount, - lofs_umount, - amfs_error_lookup_child, - amfs_error_mount_child, - amfs_error_readdir, - 0, /* lofs_readlink */ - 0, /* lofs_mounted */ - 0, /* lofs_umounted */ - amfs_generic_find_srvr, - 0, /* lofs_get_wchan */ - FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */ -#ifdef HAVE_FS_AUTOFS - AUTOFS_LOFS_FS_FLAGS, -#endif /* HAVE_FS_AUTOFS */ -}; - - -/* - * LOFS needs remote filesystem. - */ -static char * -lofs_match(am_opts *fo) -{ - if (!fo->opt_rfs) { - plog(XLOG_USER, "lofs: no source filesystem specified"); - return 0; - } - dlog("LOFS: mounting fs \"%s\" on \"%s\"", - fo->opt_rfs, fo->opt_fs); - - /* - * Determine magic cookie to put in mtab - */ - return strdup(fo->opt_rfs); -} - - -int -mount_lofs(char *mntdir, char *fs_name, char *opts, int on_autofs) -{ - mntent_t mnt; - int flags; - - /* - * Figure out the name of the file system type. - */ - MTYPE_TYPE type = MOUNT_TYPE_LOFS; - - /* - * Fill in the mount structure - */ - memset((voidp) &mnt, 0, sizeof(mnt)); - mnt.mnt_dir = mntdir; - mnt.mnt_fsname = fs_name; - mnt.mnt_type = MNTTAB_TYPE_LOFS; - mnt.mnt_opts = opts; - - flags = compute_mount_flags(&mnt); -#ifdef HAVE_FS_AUTOFS - if (on_autofs) - flags |= autofs_compute_mount_flags(&mnt); -#endif /* HAVE_FS_AUTOFS */ - - /* - * Call generic mount routine - */ - return mount_fs(&mnt, flags, NULL, 0, type, 0, NULL, mnttab_file_name, on_autofs); -} - - -static int -lofs_mount(am_node *am, mntfs *mf) -{ - int on_autofs = mf->mf_flags & MFF_ON_AUTOFS; - int error; - - error = mount_lofs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs); - if (error) { - errno = error; - plog(XLOG_ERROR, "mount_lofs: %m"); - return error; - } - return 0; -} - - -static int -lofs_umount(am_node *am, mntfs *mf) -{ - int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0; - - return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags); -} diff --git a/contrib/amd/amd/ops_mfs.c b/contrib/amd/amd/ops_mfs.c deleted file mode 100644 index ccaa49c569cd..000000000000 --- a/contrib/amd/amd/ops_mfs.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/ops_mfs.c - * - */ - -/* - * Memory file system (RAM filesystem) - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* FEEL FREE TO IMPLEMENT THIS... :-) */ diff --git a/contrib/amd/amd/ops_nfs.c b/contrib/amd/amd/ops_nfs.c deleted file mode 100644 index a6a85858d484..000000000000 --- a/contrib/amd/amd/ops_nfs.c +++ /dev/null @@ -1,1042 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/ops_nfs.c - * - */ - -/* - * Network file system - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* - * Convert from nfsstat to UN*X error code - */ -#define unx_error(e) ((int)(e)) - -/* - * FH_TTL is the time a file handle will remain in the cache since - * last being used. If the file handle becomes invalid, then it - * will be flushed anyway. - */ -#define FH_TTL (5 * 60) /* five minutes */ -#define FH_TTL_ERROR (30) /* 30 seconds */ -#define FHID_ALLOC() (++fh_id) - -/* - * The NFS layer maintains a cache of file handles. - * This is *fundamental* to the implementation and - * also allows quick remounting when a filesystem - * is accessed soon after timing out. - * - * The NFS server layer knows to flush this cache - * when a server goes down so avoiding stale handles. - * - * Each cache entry keeps a hard reference to - * the corresponding server. This ensures that - * the server keepalive information is maintained. - * - * The copy of the sockaddr_in here is taken so - * that the port can be twiddled to talk to mountd - * instead of portmap or the NFS server as used - * elsewhere. - * The port# is flushed if a server goes down. - * The IP address is never flushed - we assume - * that the address of a mounted machine never - * changes. If it does, then you have other - * problems... - */ -typedef struct fh_cache fh_cache; -struct fh_cache { - qelem fh_q; /* List header */ - wchan_t fh_wchan; /* Wait channel */ - int fh_error; /* Valid data? */ - int fh_id; /* Unique id */ - int fh_cid; /* Callout id */ - u_long fh_nfs_version; /* highest NFS version on host */ - am_nfs_handle_t fh_nfs_handle; /* Handle on filesystem */ - int fh_status; /* Status of last rpc */ - struct sockaddr_in fh_sin; /* Address of mountd */ - fserver *fh_fs; /* Server holding filesystem */ - char *fh_path; /* Filesystem on host */ -}; - -/* forward definitions */ -static int nfs_init(mntfs *mf); -static char *nfs_match(am_opts *fo); -static int nfs_mount(am_node *am, mntfs *mf); -static int nfs_umount(am_node *am, mntfs *mf); -static void nfs_umounted(mntfs *mf); -static int call_mountd(fh_cache *fp, u_long proc, fwd_fun f, wchan_t wchan); -static int webnfs_lookup(fh_cache *fp, fwd_fun f, wchan_t wchan); -static int fh_id = 0; - -/* globals */ -AUTH *nfs_auth; -qelem fh_head = {&fh_head, &fh_head}; - -/* - * Network file system operations - */ -am_ops nfs_ops = -{ - "nfs", - nfs_match, - nfs_init, - nfs_mount, - nfs_umount, - amfs_error_lookup_child, - amfs_error_mount_child, - amfs_error_readdir, - 0, /* nfs_readlink */ - 0, /* nfs_mounted */ - nfs_umounted, - find_nfs_srvr, - 0, /* nfs_get_wchan */ - FS_MKMNT | FS_BACKGROUND | FS_AMQINFO, /* nfs_fs_flags */ -#ifdef HAVE_FS_AUTOFS - AUTOFS_NFS_FS_FLAGS, -#endif /* HAVE_FS_AUTOFS */ -}; - - -static fh_cache * -find_nfs_fhandle_cache(opaque_t arg, int done) -{ - fh_cache *fp, *fp2 = 0; - int id = (long) arg; /* for 64-bit archs */ - - ITER(fp, fh_cache, &fh_head) { - if (fp->fh_id == id) { - fp2 = fp; - break; - } - } - - if (fp2) { - dlog("fh cache gives fp %#lx, fs %s", (unsigned long) fp2, fp2->fh_path); - } else { - dlog("fh cache search failed"); - } - - if (fp2 && !done) { - fp2->fh_error = ETIMEDOUT; - return 0; - } - - return fp2; -} - - -/* - * Called when a filehandle appears via the mount protocol - */ -static void -got_nfs_fh_mount(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia, opaque_t arg, int done) -{ - fh_cache *fp; - struct fhstatus res; -#ifdef HAVE_FS_NFS3 - struct am_mountres3 res3; -#endif /* HAVE_FS_NFS3 */ - - fp = find_nfs_fhandle_cache(arg, done); - if (!fp) - return; - - /* - * retrieve the correct RPC reply for the file handle, based on the - * NFS protocol version. - */ -#ifdef HAVE_FS_NFS3 - if (fp->fh_nfs_version == NFS_VERSION3) { - memset(&res3, 0, sizeof(res3)); - fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &res3, - (XDRPROC_T_TYPE) xdr_am_mountres3); - fp->fh_status = unx_error(res3.fhs_status); - memset(&fp->fh_nfs_handle.v3, 0, sizeof(am_nfs_fh3)); - fp->fh_nfs_handle.v3.am_fh3_length = res3.mountres3_u.mountinfo.fhandle.fhandle3_len; - memmove(fp->fh_nfs_handle.v3.am_fh3_data, - res3.mountres3_u.mountinfo.fhandle.fhandle3_val, - fp->fh_nfs_handle.v3.am_fh3_length); - } else { -#endif /* HAVE_FS_NFS3 */ - memset(&res, 0, sizeof(res)); - fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &res, - (XDRPROC_T_TYPE) xdr_fhstatus); - fp->fh_status = unx_error(res.fhs_status); - memmove(&fp->fh_nfs_handle.v2, &res.fhs_fh, NFS_FHSIZE); -#ifdef HAVE_FS_NFS3 - } -#endif /* HAVE_FS_NFS3 */ - - if (!fp->fh_error) { - dlog("got filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path); - } else { - plog(XLOG_USER, "filehandle denied for %s:%s", fp->fh_fs->fs_host, fp->fh_path); - /* - * Force the error to be EACCES. It's debatable whether it should be - * ENOENT instead, but the server really doesn't give us any clues, and - * EACCES is more in line with the "filehandle denied" message. - */ - fp->fh_error = EACCES; - } - - /* - * Wakeup anything sleeping on this filehandle - */ - if (fp->fh_wchan) { - dlog("Calling wakeup on %#lx", (unsigned long) fp->fh_wchan); - wakeup(fp->fh_wchan); - } -} - - -/* - * Called when a filehandle appears via WebNFS - */ -static void -got_nfs_fh_webnfs(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia, opaque_t arg, int done) -{ - fh_cache *fp; - nfsdiropres res; -#ifdef HAVE_FS_NFS3 - am_LOOKUP3res res3; -#endif /* HAVE_FS_NFS3 */ - - fp = find_nfs_fhandle_cache(arg, done); - if (!fp) - return; - - /* - * retrieve the correct RPC reply for the file handle, based on the - * NFS protocol version. - */ -#ifdef HAVE_FS_NFS3 - if (fp->fh_nfs_version == NFS_VERSION3) { - memset(&res3, 0, sizeof(res3)); - fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &res3, - (XDRPROC_T_TYPE) xdr_am_LOOKUP3res); - fp->fh_status = unx_error(res3.status); - memset(&fp->fh_nfs_handle.v3, 0, sizeof(am_nfs_fh3)); - fp->fh_nfs_handle.v3.am_fh3_length = res3.res_u.ok.object.am_fh3_length; - memmove(fp->fh_nfs_handle.v3.am_fh3_data, - res3.res_u.ok.object.am_fh3_data, - fp->fh_nfs_handle.v3.am_fh3_length); - } else { -#endif /* HAVE_FS_NFS3 */ - memset(&res, 0, sizeof(res)); - fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &res, - (XDRPROC_T_TYPE) xdr_diropres); - fp->fh_status = unx_error(res.dr_status); - memmove(&fp->fh_nfs_handle.v2, &res.dr_u.dr_drok_u.drok_fhandle, NFS_FHSIZE); -#ifdef HAVE_FS_NFS3 - } -#endif /* HAVE_FS_NFS3 */ - - if (!fp->fh_error) { - dlog("got filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path); - } else { - plog(XLOG_USER, "filehandle denied for %s:%s", fp->fh_fs->fs_host, fp->fh_path); - /* - * Force the error to be EACCES. It's debatable whether it should be - * ENOENT instead, but the server really doesn't give us any clues, and - * EACCES is more in line with the "filehandle denied" message. - */ - fp->fh_error = EACCES; - } - - /* - * Wakeup anything sleeping on this filehandle - */ - if (fp->fh_wchan) { - dlog("Calling wakeup on %#lx", (unsigned long) fp->fh_wchan); - wakeup(fp->fh_wchan); - } -} - - -void -flush_nfs_fhandle_cache(fserver *fs) -{ - fh_cache *fp; - - ITER(fp, fh_cache, &fh_head) { - if (fp->fh_fs == fs || fs == NULL) { - /* - * Only invalidate port info for non-WebNFS servers - */ - if (!(fp->fh_fs->fs_flags & FSF_WEBNFS)) - fp->fh_sin.sin_port = (u_short) 0; - fp->fh_error = -1; - } - } -} - - -static void -discard_fh(opaque_t arg) -{ - fh_cache *fp = (fh_cache *) arg; - - rem_que(&fp->fh_q); - if (fp->fh_fs) { - dlog("Discarding filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path); - free_srvr(fp->fh_fs); - } - if (fp->fh_path) - XFREE(fp->fh_path); - XFREE(fp); -} - - -/* - * Determine the file handle for a node - */ -static int -prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, mntfs *mf) -{ - fh_cache *fp, *fp_save = 0; - int error; - int reuse_id = FALSE; - - dlog("Searching cache for %s:%s", fs->fs_host, path); - - /* - * First search the cache - */ - ITER(fp, fh_cache, &fh_head) { - if (fs != fp->fh_fs || !STREQ(path, fp->fh_path)) - continue; /* skip to next ITER item */ - /* else we got a match */ - switch (fp->fh_error) { - case 0: - plog(XLOG_INFO, "prime_nfs_fhandle_cache: NFS version %d", (int) fp->fh_nfs_version); - - error = fp->fh_error = fp->fh_status; - - if (error == 0) { - if (mf->mf_flags & MFF_NFS_SCALEDOWN) { - fp_save = fp; - /* XXX: why reuse the ID? */ - reuse_id = TRUE; - break; - } - - if (fhbuf) { -#ifdef HAVE_FS_NFS3 - if (fp->fh_nfs_version == NFS_VERSION3) { - memmove((voidp) &(fhbuf->v3), (voidp) &(fp->fh_nfs_handle.v3), - sizeof(fp->fh_nfs_handle.v3)); - } else -#endif /* HAVE_FS_NFS3 */ - { - memmove((voidp) &(fhbuf->v2), (voidp) &(fp->fh_nfs_handle.v2), - sizeof(fp->fh_nfs_handle.v2)); - } - } - if (fp->fh_cid) - untimeout(fp->fh_cid); - fp->fh_cid = timeout(FH_TTL, discard_fh, (opaque_t) fp); - } else if (error == EACCES) { - /* - * Now decode the file handle return code. - */ - plog(XLOG_INFO, "Filehandle denied for \"%s:%s\"", - fs->fs_host, path); - } else { - errno = error; /* XXX */ - plog(XLOG_INFO, "Filehandle error for \"%s:%s\": %m", - fs->fs_host, path); - } - - /* - * The error was returned from the remote mount daemon. - * Policy: this error will be cached for now... - */ - return error; - - case -1: - /* - * Still thinking about it, but we can re-use. - */ - fp_save = fp; - reuse_id = TRUE; - break; - - default: - /* - * Return the error. - * Policy: make sure we recompute if required again - * in case this was caused by a network failure. - * This can thrash mountd's though... If you find - * your mountd going slowly then: - * 1. Add a fork() loop to main. - * 2. Remove the call to innetgr() and don't use - * netgroups, especially if you don't use YP. - */ - error = fp->fh_error; - fp->fh_error = -1; - return error; - } /* end of switch statement */ - } /* end of ITER loop */ - - /* - * Not in cache - */ - if (fp_save) { - fp = fp_save; - /* - * Re-use existing slot - */ - untimeout(fp->fh_cid); - free_srvr(fp->fh_fs); - XFREE(fp->fh_path); - } else { - fp = ALLOC(struct fh_cache); - memset((voidp) fp, 0, sizeof(struct fh_cache)); - ins_que(&fp->fh_q, &fh_head); - } - if (!reuse_id) - fp->fh_id = FHID_ALLOC(); - fp->fh_wchan = get_mntfs_wchan(mf); - fp->fh_error = -1; - fp->fh_cid = timeout(FH_TTL, discard_fh, (opaque_t) fp); - - /* - * If fs->fs_ip is null, remote server is probably down. - */ - if (!fs->fs_ip) { - /* Mark the fileserver down and invalid again */ - fs->fs_flags &= ~FSF_VALID; - fs->fs_flags |= FSF_DOWN; - error = AM_ERRNO_HOST_DOWN; - return error; - } - - /* - * Either fp has been freshly allocated or the address has changed. - * Initialize address and nfs version. Don't try to re-use the port - * information unless using WebNFS where the port is fixed either by - * the spec or the "port" mount option. - */ - if (fp->fh_sin.sin_addr.s_addr != fs->fs_ip->sin_addr.s_addr) { - fp->fh_sin = *fs->fs_ip; - if (!(mf->mf_flags & MFF_WEBNFS)) - fp->fh_sin.sin_port = 0; - fp->fh_nfs_version = fs->fs_version; - } - - fp->fh_fs = dup_srvr(fs); - fp->fh_path = strdup(path); - - if (mf->mf_flags & MFF_WEBNFS) - error = webnfs_lookup(fp, got_nfs_fh_webnfs, get_mntfs_wchan(mf)); - else - error = call_mountd(fp, MOUNTPROC_MNT, got_nfs_fh_mount, get_mntfs_wchan(mf)); - if (error) { - /* - * Local error - cache for a short period - * just to prevent thrashing. - */ - untimeout(fp->fh_cid); - fp->fh_cid = timeout(error < 0 ? 2 * ALLOWED_MOUNT_TIME : FH_TTL_ERROR, - discard_fh, (opaque_t) fp); - fp->fh_error = error; - } else { - error = fp->fh_error; - } - - return error; -} - - -int -make_nfs_auth(void) -{ - AUTH_CREATE_GIDLIST_TYPE group_wheel = 0; - - /* Some NFS mounts (particularly cross-domain) require FQDNs to succeed */ - -#ifdef HAVE_TRANSPORT_TYPE_TLI - if (gopt.flags & CFM_FULLY_QUALIFIED_HOSTS) { - plog(XLOG_INFO, "Using NFS auth for FQHN \"%s\"", hostd); - nfs_auth = authsys_create(hostd, 0, 0, 1, &group_wheel); - } else { - nfs_auth = authsys_create_default(); - } -#else /* not HAVE_TRANSPORT_TYPE_TLI */ - if (gopt.flags & CFM_FULLY_QUALIFIED_HOSTS) { - plog(XLOG_INFO, "Using NFS auth for FQHN \"%s\"", hostd); - nfs_auth = authunix_create(hostd, 0, 0, 1, &group_wheel); - } else { - nfs_auth = authunix_create_default(); - } -#endif /* not HAVE_TRANSPORT_TYPE_TLI */ - - if (!nfs_auth) - return ENOBUFS; - - return 0; -} - - -static int -call_mountd(fh_cache *fp, u_long proc, fwd_fun fun, wchan_t wchan) -{ - struct rpc_msg mnt_msg; - int len; - char iobuf[UDPMSGSIZE]; - int error; - u_long mnt_version; - - if (!nfs_auth) { - error = make_nfs_auth(); - if (error) - return error; - } - - if (fp->fh_sin.sin_port == 0) { - u_short mountd_port; - error = get_mountd_port(fp->fh_fs, &mountd_port, wchan); - if (error) - return error; - fp->fh_sin.sin_port = mountd_port; - } - - /* find the right version of the mount protocol */ -#ifdef HAVE_FS_NFS3 - if (fp->fh_nfs_version == NFS_VERSION3) - mnt_version = AM_MOUNTVERS3; - else -#endif /* HAVE_FS_NFS3 */ - mnt_version = MOUNTVERS; - plog(XLOG_INFO, "call_mountd: NFS version %d, mount version %d", - (int) fp->fh_nfs_version, (int) mnt_version); - - rpc_msg_init(&mnt_msg, MOUNTPROG, mnt_version, MOUNTPROC_NULL); - len = make_rpc_packet(iobuf, - sizeof(iobuf), - proc, - &mnt_msg, - (voidp) &fp->fh_path, - (XDRPROC_T_TYPE) xdr_nfspath, - nfs_auth); - - if (len > 0) { - error = fwd_packet(MK_RPC_XID(RPC_XID_MOUNTD, fp->fh_id), - iobuf, - len, - &fp->fh_sin, - &fp->fh_sin, - (opaque_t) ((long) fp->fh_id), /* cast to long needed for 64-bit archs */ - fun); - } else { - error = -len; - } - - /* - * It may be the case that we're sending to the wrong MOUNTD port. This - * occurs if mountd is restarted on the server after the port has been - * looked up and stored in the filehandle cache somewhere. The correct - * solution, if we're going to cache port numbers is to catch the ICMP - * port unreachable reply from the server and cause the portmap request - * to be redone. The quick solution here is to invalidate the MOUNTD - * port. - */ - fp->fh_sin.sin_port = 0; - - return error; -} - - -static int -webnfs_lookup(fh_cache *fp, fwd_fun fun, wchan_t wchan) -{ - struct rpc_msg wnfs_msg; - int len; - char iobuf[UDPMSGSIZE]; - int error; - u_long proc; - XDRPROC_T_TYPE xdr_fn; - voidp argp; - nfsdiropargs args; -#ifdef HAVE_FS_NFS3 - am_LOOKUP3args args3; -#endif - char *wnfs_path; - size_t l; - - if (!nfs_auth) { - error = make_nfs_auth(); - if (error) - return error; - } - - if (fp->fh_sin.sin_port == 0) { - /* FIXME: wrong, don't discard sin_port in the first place for WebNFS. */ - plog(XLOG_WARNING, "webnfs_lookup: port == 0 for nfs on %s, fixed", - fp->fh_fs->fs_host); - fp->fh_sin.sin_port = htons(NFS_PORT); - } - - /* - * Use native path like the rest of amd (cf. RFC 2054, 6.1). - */ - l = strlen(fp->fh_path) + 2; - wnfs_path = (char *) xmalloc(l); - wnfs_path[0] = 0x80; - xstrlcpy(wnfs_path + 1, fp->fh_path, l - 1); - - /* find the right program and lookup procedure */ -#ifdef HAVE_FS_NFS3 - if (fp->fh_nfs_version == NFS_VERSION3) { - proc = AM_NFSPROC3_LOOKUP; - xdr_fn = (XDRPROC_T_TYPE) xdr_am_LOOKUP3args; - argp = &args3; - /* WebNFS public file handle */ - args3.what.dir.am_fh3_length = 0; - args3.what.name = wnfs_path; - } else { -#endif /* HAVE_FS_NFS3 */ - proc = NFSPROC_LOOKUP; - xdr_fn = (XDRPROC_T_TYPE) xdr_diropargs; - argp = &args; - /* WebNFS public file handle */ - memset(&args.da_fhandle, 0, NFS_FHSIZE); - args.da_name = wnfs_path; -#ifdef HAVE_FS_NFS3 - } -#endif /* HAVE_FS_NFS3 */ - - plog(XLOG_INFO, "webnfs_lookup: NFS version %d", (int) fp->fh_nfs_version); - - rpc_msg_init(&wnfs_msg, NFS_PROGRAM, fp->fh_nfs_version, proc); - len = make_rpc_packet(iobuf, - sizeof(iobuf), - proc, - &wnfs_msg, - argp, - (XDRPROC_T_TYPE) xdr_fn, - nfs_auth); - - if (len > 0) { - error = fwd_packet(MK_RPC_XID(RPC_XID_WEBNFS, fp->fh_id), - iobuf, - len, - &fp->fh_sin, - &fp->fh_sin, - (opaque_t) ((long) fp->fh_id), /* cast to long needed for 64-bit archs */ - fun); - } else { - error = -len; - } - - XFREE(wnfs_path); - return error; -} - - -/* - * NFS needs the local filesystem, remote filesystem - * remote hostname. - * Local filesystem defaults to remote and vice-versa. - */ -static char * -nfs_match(am_opts *fo) -{ - char *xmtab; - size_t l; - - if (fo->opt_fs && !fo->opt_rfs) - fo->opt_rfs = fo->opt_fs; - if (!fo->opt_rfs) { - plog(XLOG_USER, "nfs: no remote filesystem specified"); - return NULL; - } - if (!fo->opt_rhost) { - plog(XLOG_USER, "nfs: no remote host specified"); - return NULL; - } - - /* - * Determine magic cookie to put in mtab - */ - l = strlen(fo->opt_rhost) + strlen(fo->opt_rfs) + 2; - xmtab = (char *) xmalloc(l); - xsnprintf(xmtab, l, "%s:%s", fo->opt_rhost, fo->opt_rfs); - dlog("NFS: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"", - fo->opt_rhost, fo->opt_rfs, fo->opt_fs); - - return xmtab; -} - - -/* - * Initialize am structure for nfs - */ -static int -nfs_init(mntfs *mf) -{ - int error; - am_nfs_handle_t fhs; - char *colon; - - if (mf->mf_private) { - if (mf->mf_flags & MFF_NFS_SCALEDOWN) { - fserver *fs; - - /* tell remote mountd that we're done with this filehandle */ - mf->mf_ops->umounted(mf); - - mf->mf_prfree(mf->mf_private); - fs = mf->mf_ops->ffserver(mf); - free_srvr(mf->mf_server); - mf->mf_server = fs; - } else - return 0; - } - - colon = strchr(mf->mf_info, ':'); - if (colon == 0) - return ENOENT; - - error = prime_nfs_fhandle_cache(colon + 1, mf->mf_server, &fhs, mf); - if (!error) { - mf->mf_private = (opaque_t) ALLOC(am_nfs_handle_t); - mf->mf_prfree = (void (*)(opaque_t)) free; - memmove(mf->mf_private, (voidp) &fhs, sizeof(fhs)); - } - return error; -} - - -int -mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf) -{ - MTYPE_TYPE type; - char *colon; - char *xopts=NULL, transp_timeo_opts[40], transp_retrans_opts[40]; - char host[MAXHOSTNAMELEN + MAXPATHLEN + 2]; - fserver *fs = mf->mf_server; - u_long nfs_version = fs->fs_version; - char *nfs_proto = fs->fs_proto; /* "tcp" or "udp" */ - int on_autofs = mf->mf_flags & MFF_ON_AUTOFS; - int error; - int genflags; - int retry; - int proto = AMU_TYPE_NONE; - mntent_t mnt; - nfs_args_t nfs_args; - - /* - * Extract HOST name to give to kernel. - * Some systems like osf1/aix3/bsd44 variants may need old code - * for NFS_ARGS_NEEDS_PATH. - */ - if (!(colon = strchr(fs_name, ':'))) - return ENOENT; -#ifdef MOUNT_TABLE_ON_FILE - *colon = '\0'; -#endif /* MOUNT_TABLE_ON_FILE */ - xstrlcpy(host, fs_name, sizeof(host)); -#ifdef MOUNT_TABLE_ON_FILE - *colon = ':'; -#endif /* MOUNT_TABLE_ON_FILE */ -#ifdef MAXHOSTNAMELEN - /* most kernels have a name length restriction */ - if (strlen(host) >= MAXHOSTNAMELEN) - xstrlcpy(host + MAXHOSTNAMELEN - 3, "..", - sizeof(host) - MAXHOSTNAMELEN + 3); -#endif /* MAXHOSTNAMELEN */ - - /* - * Create option=VAL for udp/tcp specific timeouts and retrans values, but - * only if these options were specified. - */ - - transp_timeo_opts[0] = transp_retrans_opts[0] = '\0'; /* initialize */ - if (STREQ(nfs_proto, "udp")) - proto = AMU_TYPE_UDP; - else if (STREQ(nfs_proto, "tcp")) - proto = AMU_TYPE_TCP; - if (proto != AMU_TYPE_NONE) { - if (gopt.amfs_auto_timeo[proto] > 0) - xsnprintf(transp_timeo_opts, sizeof(transp_timeo_opts), "%s=%d,", - MNTTAB_OPT_TIMEO, gopt.amfs_auto_timeo[proto]); - if (gopt.amfs_auto_retrans[proto] > 0) - xsnprintf(transp_retrans_opts, sizeof(transp_retrans_opts), "%s=%d,", - MNTTAB_OPT_RETRANS, gopt.amfs_auto_retrans[proto]); - } - - if (mf->mf_remopts && *mf->mf_remopts && - !islocalnet(fs->fs_ip->sin_addr.s_addr)) { - plog(XLOG_INFO, "Using remopts=\"%s\"", mf->mf_remopts); - /* use transp_opts first, so map-specific opts will override */ - xopts = str3cat(xopts, transp_timeo_opts, transp_retrans_opts, mf->mf_remopts); - } else { - /* use transp_opts first, so map-specific opts will override */ - xopts = str3cat(xopts, transp_timeo_opts, transp_retrans_opts, mf->mf_mopts); - } - - memset((voidp) &mnt, 0, sizeof(mnt)); - mnt.mnt_dir = mntdir; - mnt.mnt_fsname = fs_name; - mnt.mnt_opts = xopts; - - /* - * Set mount types accordingly - */ -#ifndef HAVE_FS_NFS3 - type = MOUNT_TYPE_NFS; - mnt.mnt_type = MNTTAB_TYPE_NFS; -#else /* HAVE_FS_NFS3 */ - if (nfs_version == NFS_VERSION3) { - type = MOUNT_TYPE_NFS3; - /* - * Systems that include the mount table "vers" option generally do not - * set the mnttab entry to "nfs3", but to "nfs" and then they set - * "vers=3". Setting it to "nfs3" works, but it may break some things - * like "df -t nfs" and the "quota" program (esp. on Solaris and Irix). - * So on those systems, set it to "nfs". - * Note: MNTTAB_OPT_VERS is always set for NFS3 (see am_compat.h). - */ -# if defined(MNTTAB_OPT_VERS) && defined(MOUNT_TABLE_ON_FILE) - mnt.mnt_type = MNTTAB_TYPE_NFS; -# else /* defined(MNTTAB_OPT_VERS) && defined(MOUNT_TABLE_ON_FILE) */ - mnt.mnt_type = MNTTAB_TYPE_NFS3; -# endif /* defined(MNTTAB_OPT_VERS) && defined(MOUNT_TABLE_ON_FILE) */ - } else { - type = MOUNT_TYPE_NFS; - mnt.mnt_type = MNTTAB_TYPE_NFS; - } -#endif /* HAVE_FS_NFS3 */ - plog(XLOG_INFO, "mount_nfs_fh: NFS version %d", (int) nfs_version); - plog(XLOG_INFO, "mount_nfs_fh: using NFS transport %s", nfs_proto); - - retry = hasmntval(&mnt, MNTTAB_OPT_RETRY); - if (retry <= 0) - retry = 1; /* XXX */ - - genflags = compute_mount_flags(&mnt); -#ifdef HAVE_FS_AUTOFS - if (on_autofs) - genflags |= autofs_compute_mount_flags(&mnt); -#endif /* HAVE_FS_AUTOFS */ - - /* setup the many fields and flags within nfs_args */ - compute_nfs_args(&nfs_args, - &mnt, - genflags, - NULL, /* struct netconfig *nfsncp */ - fs->fs_ip, - nfs_version, - nfs_proto, - fhp, - host, - fs_name); - - /* finally call the mounting function */ - if (amuDebug(D_TRACE)) { - print_nfs_args(&nfs_args, nfs_version); - plog(XLOG_DEBUG, "Generic mount flags 0x%x used for NFS mount", genflags); - } - error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type, - nfs_version, nfs_proto, mnttab_file_name, on_autofs); - XFREE(xopts); - -#ifdef HAVE_TRANSPORT_TYPE_TLI - free_knetconfig(nfs_args.knconf); - if (nfs_args.addr) - XFREE(nfs_args.addr); /* allocated in compute_nfs_args() */ -#endif /* HAVE_TRANSPORT_TYPE_TLI */ - - return error; -} - - -static int -nfs_mount(am_node *am, mntfs *mf) -{ - int error = 0; - mntent_t mnt; - - if (!mf->mf_private) { - plog(XLOG_ERROR, "Missing filehandle for %s", mf->mf_info); - return EINVAL; - } - - mnt.mnt_opts = mf->mf_mopts; - if (amu_hasmntopt(&mnt, "softlookup") || - (amu_hasmntopt(&mnt, "soft") && !amu_hasmntopt(&mnt, "nosoftlookup"))) - am->am_flags |= AMF_SOFTLOOKUP; - - error = mount_nfs_fh((am_nfs_handle_t *) mf->mf_private, - mf->mf_mount, - mf->mf_info, - mf); - - if (error) { - errno = error; - dlog("mount_nfs: %m"); - } - - return error; -} - - -static int -nfs_umount(am_node *am, mntfs *mf) -{ - int unmount_flags, new_unmount_flags, error; - - unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0; - error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags); - -#if defined(HAVE_UMOUNT2) && (defined(MNT2_GEN_OPT_FORCE) || defined(MNT2_GEN_OPT_DETACH)) - /* - * If the attempt to unmount failed with EBUSY, and this fserver was - * marked for forced unmounts, then use forced/lazy unmounts. - */ - if (error == EBUSY && - gopt.flags & CFM_FORCED_UNMOUNTS && - mf->mf_server->fs_flags & FSF_FORCE_UNMOUNT) { - plog(XLOG_INFO, "EZK: nfs_umount: trying forced/lazy unmounts"); - /* - * XXX: turning off the FSF_FORCE_UNMOUNT may not be perfectly - * incorrect. Multiple nodes may need to be timed out and restarted for - * a single hung fserver. - */ - mf->mf_server->fs_flags &= ~FSF_FORCE_UNMOUNT; - new_unmount_flags = unmount_flags | AMU_UMOUNT_FORCE | AMU_UMOUNT_DETACH; - error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, new_unmount_flags); - } -#endif /* HAVE_UMOUNT2 && (MNT2_GEN_OPT_FORCE || MNT2_GEN_OPT_DETACH) */ - - /* - * Here is some code to unmount 'restarted' file systems. - * The restarted file systems are marked as 'nfs', not - * 'host', so we only have the map information for the - * the top-level mount. The unmount will fail (EBUSY) - * if there are anything else from the NFS server mounted - * below the mount-point. This code checks to see if there - * is anything mounted with the same prefix as the - * file system to be unmounted ("/a/b/c" when unmounting "/a/b"). - * If there is, and it is a 'restarted' file system, we unmount - * it. - * Added by Mike Mitchell, mcm@unx.sas.com, 09/08/93 - */ - if (error == EBUSY) { - mntfs *new_mf; - int len = strlen(mf->mf_mount); - int didsome = 0; - - ITER(new_mf, mntfs, &mfhead) { - if (new_mf->mf_ops != mf->mf_ops || - new_mf->mf_refc > 1 || - mf == new_mf || - ((new_mf->mf_flags & (MFF_MOUNTED | MFF_UNMOUNTING | MFF_RESTART)) == (MFF_MOUNTED | MFF_RESTART))) - continue; - - if (NSTREQ(mf->mf_mount, new_mf->mf_mount, len) && - new_mf->mf_mount[len] == '/') { - new_unmount_flags = - (new_mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0; - UMOUNT_FS(new_mf->mf_mount, mnttab_file_name, new_unmount_flags); - didsome = 1; - } - } - if (didsome) - error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags); - } - if (error) - return error; - - return 0; -} - - -static void -nfs_umounted(mntfs *mf) -{ - fserver *fs; - char *colon, *path; - - if (mf->mf_error || mf->mf_refc > 1) - return; - - /* - * No need to inform mountd when WebNFS is in use. - */ - if (mf->mf_flags & MFF_WEBNFS) - return; - - /* - * Call the mount daemon on the server to announce that we are not using - * the fs any more. - * - * XXX: This is *wrong*. The mountd should be called when the fhandle is - * flushed from the cache, and a reference held to the cached entry while - * the fs is mounted... - */ - fs = mf->mf_server; - colon = path = strchr(mf->mf_info, ':'); - if (fs && colon) { - fh_cache f; - - dlog("calling mountd for %s", mf->mf_info); - *path++ = '\0'; - f.fh_path = path; - f.fh_sin = *fs->fs_ip; - f.fh_sin.sin_port = (u_short) 0; - f.fh_nfs_version = fs->fs_version; - f.fh_fs = fs; - f.fh_id = 0; - f.fh_error = 0; - prime_nfs_fhandle_cache(colon + 1, mf->mf_server, (am_nfs_handle_t *) 0, mf); - call_mountd(&f, MOUNTPROC_UMNT, (fwd_fun *) 0, (wchan_t) 0); - *colon = ':'; - } -} diff --git a/contrib/amd/amd/ops_nfs3.c b/contrib/amd/amd/ops_nfs3.c deleted file mode 100644 index db3c7f9d265d..000000000000 --- a/contrib/amd/amd/ops_nfs3.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/ops_nfs3.c - * - */ - -/* - * Network file system version 3.0 - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* FEEL FREE TO IMPLEMENT THIS... :-) */ diff --git a/contrib/amd/amd/ops_nullfs.c b/contrib/amd/amd/ops_nullfs.c deleted file mode 100644 index cf621ec33ff5..000000000000 --- a/contrib/amd/amd/ops_nullfs.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/ops_nullfs.c - * - */ - -/* - * The null filesystem in BSD-4.4 is similar to the loopback one. - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* FEEL FREE TO IMPLEMENT THIS... :-) */ diff --git a/contrib/amd/amd/ops_pcfs.c b/contrib/amd/amd/ops_pcfs.c deleted file mode 100644 index 527dc926ca77..000000000000 --- a/contrib/amd/amd/ops_pcfs.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/ops_pcfs.c - * - */ - -/* - * PC (MS-DOS) file system - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* forward definitions */ -static char *pcfs_match(am_opts *fo); -static int pcfs_mount(am_node *am, mntfs *mf); -static int pcfs_umount(am_node *am, mntfs *mf); - -/* - * Ops structure - */ -am_ops pcfs_ops = -{ - "pcfs", - pcfs_match, - 0, /* pcfs_init */ - pcfs_mount, - pcfs_umount, - amfs_error_lookup_child, - amfs_error_mount_child, - amfs_error_readdir, - 0, /* pcfs_readlink */ - 0, /* pcfs_mounted */ - 0, /* pcfs_umounted */ - amfs_generic_find_srvr, - 0, /* pcfs_get_wchan */ - FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */ -#ifdef HAVE_FS_AUTOFS - AUTOFS_PCFS_FS_FLAGS, -#endif /* HAVE_FS_AUTOFS */ -}; - - - -/* - * PCFS needs remote filesystem. - */ -static char * -pcfs_match(am_opts *fo) -{ - if (!fo->opt_dev) { - plog(XLOG_USER, "pcfs: no source device specified"); - return 0; - } - dlog("PCFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs); - - /* - * Determine magic cookie to put in mtab - */ - return strdup(fo->opt_dev); -} - - -static int -mount_pcfs(char *mntdir, char *fs_name, char *opts, int on_autofs) -{ - pcfs_args_t pcfs_args; - mntent_t mnt; - int flags; -#if defined(HAVE_PCFS_ARGS_T_MASK) || defined(HAVE_PCFS_ARGS_T_DIRMASK) - int mask; -#endif /* defined(HAVE_PCFS_ARGS_T_MASK) || defined(HAVE_PCFS_ARGS_T_DIRMASK) */ -#if defined(HAVE_PCFS_ARGS_T_UID) || defined(HAVE_PCFS_ARGS_T_UID) - char *str; -#endif /* defined(HAVE_PCFS_ARGS_T_UID) || defined(HAVE_PCFS_ARGS_T_UID) */ - - /* - * Figure out the name of the file system type. - */ - MTYPE_TYPE type = MOUNT_TYPE_PCFS; - - memset((voidp) &pcfs_args, 0, sizeof(pcfs_args)); /* Paranoid */ - - /* - * Fill in the mount structure - */ - memset((voidp) &mnt, 0, sizeof(mnt)); - mnt.mnt_dir = mntdir; - mnt.mnt_fsname = fs_name; - mnt.mnt_type = MNTTAB_TYPE_PCFS; - mnt.mnt_opts = opts; - - flags = compute_mount_flags(&mnt); -#ifdef HAVE_FS_AUTOFS - if (on_autofs) - flags |= autofs_compute_mount_flags(&mnt); -#endif /* HAVE_FS_AUTOFS */ - if (amuDebug(D_TRACE)) - plog(XLOG_DEBUG, "mount_pcfs: flags=0x%x", (u_int) flags); - -#ifdef HAVE_PCFS_ARGS_T_FSPEC - pcfs_args.fspec = fs_name; -#endif /* HAVE_PCFS_ARGS_T_FSPEC */ - -#ifdef HAVE_PCFS_ARGS_T_MASK - pcfs_args.mask = 0777; /* this may be the msdos file modes */ - if ((mask = hasmntval(&mnt, MNTTAB_OPT_MASK)) > 0) - pcfs_args.mask = mask; - if (amuDebug(D_TRACE)) - plog(XLOG_DEBUG, "mount_pcfs: mask=%o (octal)", (u_int) pcfs_args.mask); -#endif /* HAVE_PCFS_ARGS_T_MASK */ - -#ifdef HAVE_PCFS_ARGS_T_DIRMASK - pcfs_args.dirmask = 0777; /* this may be the msdos dir modes */ - if ((mask = hasmntval(&mnt, MNTTAB_OPT_DIRMASK)) > 0) - pcfs_args.dirmask = mask; - if (amuDebug(D_TRACE)) - plog(XLOG_DEBUG, "mount_pcfs: dirmask=%o (octal)", (u_int) pcfs_args.dirmask); -#endif /* HAVE_PCFS_ARGS_T_DIRMASK */ - -#ifdef HAVE_PCFS_ARGS_T_UID - pcfs_args.uid = 0; /* default to root */ - if ((str = hasmntstr(&mnt, MNTTAB_OPT_USER)) != NULL) { - struct passwd *pw; - if ((pw = getpwnam(str)) != NULL) - pcfs_args.uid = pw->pw_uid; - else /* maybe used passed a UID number, not user name */ - pcfs_args.uid = atoi(str); /* atoi returns '0' if it failed */ - XFREE(str); - } - if (amuDebug(D_TRACE)) - plog(XLOG_DEBUG, "mount_pcfs: uid=%d", (int) pcfs_args.uid); -#endif /* HAVE_PCFS_ARGS_T_UID */ - -#ifdef HAVE_PCFS_ARGS_T_GID - pcfs_args.gid = 0; /* default to wheel/root group */ - if ((str = hasmntstr(&mnt, MNTTAB_OPT_GROUP)) != NULL) { - struct group *gr; - if ((gr = getgrnam(str)) != NULL) - pcfs_args.gid = gr->gr_gid; - else /* maybe used passed a GID number, not group name */ - pcfs_args.gid = atoi(str); /* atoi returns '0' if it failed */ - XFREE(str); - } - if (amuDebug(D_TRACE)) - plog(XLOG_DEBUG, "mount_pcfs: gid=%d", (int) pcfs_args.gid); -#endif /* HAVE_PCFS_ARGS_T_GID */ - -#ifdef HAVE_PCFS_ARGS_T_SECONDSWEST - pcfs_args.secondswest = 0; /* XXX: fill in correct values */ -#endif /* HAVE_PCFS_ARGS_T_SECONDSWEST */ -#ifdef HAVE_PCFS_ARGS_T_DSTTIME - pcfs_args.dsttime = 0; /* XXX: fill in correct values */ -#endif /* HAVE_PCFS_ARGS_T_DSTTIME */ - - /* - * Call generic mount routine - */ - return mount_fs(&mnt, flags, (caddr_t) & pcfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs); -} - - -static int -pcfs_mount(am_node *am, mntfs *mf) -{ - int on_autofs = mf->mf_flags & MFF_ON_AUTOFS; - int error; - - error = mount_pcfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs); - if (error) { - errno = error; - plog(XLOG_ERROR, "mount_pcfs: %m"); - return error; - } - - return 0; -} - - -static int -pcfs_umount(am_node *am, mntfs *mf) -{ - int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0; - - return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags); -} diff --git a/contrib/amd/amd/ops_tfs.c b/contrib/amd/amd/ops_tfs.c deleted file mode 100644 index 142c32022937..000000000000 --- a/contrib/amd/amd/ops_tfs.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/ops_tfs.c - * - */ - -/* - * Translucent file system - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* FEEL FREE TO IMPLEMENT THIS... :-) */ diff --git a/contrib/amd/amd/ops_tmpfs.c b/contrib/amd/amd/ops_tmpfs.c deleted file mode 100644 index eddd75569e9e..000000000000 --- a/contrib/amd/amd/ops_tmpfs.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/ops_tmpfs.c - * - */ - -/* - * TMPFS file system (combines RAM-fs and swap-fs) - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* FEEL FREE TO IMPLEMENT THIS... :-) */ diff --git a/contrib/amd/amd/ops_ufs.c b/contrib/amd/amd/ops_ufs.c deleted file mode 100644 index fd82a5cd2228..000000000000 --- a/contrib/amd/amd/ops_ufs.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/ops_ufs.c - * - */ - -/* - * UN*X file system - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* forward declarations */ -static char *ufs_match(am_opts *fo); -static int ufs_mount(am_node *am, mntfs *mf); -static int ufs_umount(am_node *am, mntfs *mf); - -/* - * Ops structure - */ -am_ops ufs_ops = -{ - "ufs", - ufs_match, - 0, /* ufs_init */ - ufs_mount, - ufs_umount, - amfs_error_lookup_child, - amfs_error_mount_child, - amfs_error_readdir, - 0, /* ufs_readlink */ - 0, /* ufs_mounted */ - 0, /* ufs_umounted */ - amfs_generic_find_srvr, - 0, /* ufs_get_wchan */ - FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */ -#ifdef HAVE_FS_AUTOFS - AUTOFS_UFS_FS_FLAGS, -#endif /* HAVE_FS_AUTOFS */ -}; - - -/* - * UFS needs local filesystem and device. - */ -static char * -ufs_match(am_opts *fo) -{ - - if (!fo->opt_dev) { - plog(XLOG_USER, "ufs: no device specified"); - return 0; - } - - dlog("UFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs); - - /* - * Determine magic cookie to put in mtab - */ - return strdup(fo->opt_dev); -} - - -static int -mount_ufs(char *mntdir, char *fs_name, char *opts, int on_autofs) -{ - ufs_args_t ufs_args; - mntent_t mnt; - int genflags; - - /* - * Figure out the name of the file system type. - */ - MTYPE_TYPE type = MOUNT_TYPE_UFS; - - memset((voidp) &ufs_args, 0, sizeof(ufs_args)); /* Paranoid */ - - /* - * Fill in the mount structure - */ - memset((voidp) &mnt, 0, sizeof(mnt)); - mnt.mnt_dir = mntdir; - mnt.mnt_fsname = fs_name; - mnt.mnt_type = MNTTAB_TYPE_UFS; - mnt.mnt_opts = opts; - - genflags = compute_mount_flags(&mnt); -#ifdef HAVE_FS_AUTOFS - if (on_autofs) - genflags |= autofs_compute_mount_flags(&mnt); -#endif /* HAVE_FS_AUTOFS */ - -#ifdef HAVE_UFS_ARGS_T_FLAGS - ufs_args.flags = genflags; /* XXX: is this correct? */ -#endif /* HAVE_UFS_ARGS_T_FLAGS */ - -#ifdef HAVE_UFS_ARGS_T_UFS_FLAGS - ufs_args.ufs_flags = genflags; -#endif /* HAVE_UFS_ARGS_T_UFS_FLAGS */ - -#ifdef HAVE_UFS_ARGS_T_FSPEC - ufs_args.fspec = fs_name; -#endif /* HAVE_UFS_ARGS_T_FSPEC */ - -#ifdef HAVE_UFS_ARGS_T_UFS_PGTHRESH - ufs_args.ufs_pgthresh = hasmntval(&mnt, MNTTAB_OPT_PGTHRESH); -#endif /* HAVE_UFS_ARGS_T_UFS_PGTHRESH */ - - /* - * Call generic mount routine - */ - return mount_fs(&mnt, genflags, (caddr_t) &ufs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs); -} - - -static int -ufs_mount(am_node *am, mntfs *mf) -{ - int on_autofs = mf->mf_flags & MFF_ON_AUTOFS; - int error; - - error = mount_ufs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs); - if (error) { - errno = error; - plog(XLOG_ERROR, "mount_ufs: %m"); - return error; - } - - return 0; -} - - -static int -ufs_umount(am_node *am, mntfs *mf) -{ - int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0; - - return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags); -} diff --git a/contrib/amd/amd/ops_umapfs.c b/contrib/amd/amd/ops_umapfs.c deleted file mode 100644 index 5ba735e39c61..000000000000 --- a/contrib/amd/amd/ops_umapfs.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/ops_umapfs.c - * - */ - -/* - * uid/gid mapping filesystem. - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* FEEL FREE TO IMPLEMENT THIS... :-) */ diff --git a/contrib/amd/amd/ops_unionfs.c b/contrib/amd/amd/ops_unionfs.c deleted file mode 100644 index 73f8d6676203..000000000000 --- a/contrib/amd/amd/ops_unionfs.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/ops_unionfs.c - * - */ - -/* - * Union filesystem (ala BSD-4.4) - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* FEEL FREE TO IMPLEMENT THIS... :-) */ diff --git a/contrib/amd/amd/ops_xfs.c b/contrib/amd/amd/ops_xfs.c deleted file mode 100644 index e0e740bc0a0e..000000000000 --- a/contrib/amd/amd/ops_xfs.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/ops_xfs.c - * - */ - -/* - * Irix UN*X file system: XFS (Extended File System) - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* forward declarations */ -static char *xfs_match(am_opts *fo); -static int xfs_mount(am_node *am, mntfs *mf); -static int xfs_umount(am_node *am, mntfs *mf); - -/* - * Ops structure - */ -am_ops xfs_ops = -{ - "xfs", - xfs_match, - 0, /* xfs_init */ - xfs_mount, - xfs_umount, - amfs_error_lookup_child, - amfs_error_mount_child, - amfs_error_readdir, - 0, /* xfs_readlink */ - 0, /* xfs_mounted */ - 0, /* xfs_umounted */ - amfs_generic_find_srvr, - 0, /* xfs_get_wchan */ - FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */ -#ifdef HAVE_FS_AUTOFS - AUTOFS_XFS_FS_FLAGS, -#endif /* HAVE_FS_AUTOFS */ -}; - - -/* - * XFS needs local filesystem and device. - */ -static char * -xfs_match(am_opts *fo) -{ - - if (!fo->opt_dev) { - plog(XLOG_USER, "xfs: no device specified"); - return 0; - } - - dlog("XFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs); - - /* - * Determine magic cookie to put in mtab - */ - return strdup(fo->opt_dev); -} - - -static int -mount_xfs(char *mntdir, char *fs_name, char *opts, int on_autofs) -{ - xfs_args_t xfs_args; - mntent_t mnt; - int flags; - - /* - * Figure out the name of the file system type. - */ - MTYPE_TYPE type = MOUNT_TYPE_XFS; - - memset((voidp) &xfs_args, 0, sizeof(xfs_args)); /* Paranoid */ - - /* - * Fill in the mount structure - */ - memset((voidp) &mnt, 0, sizeof(mnt)); - mnt.mnt_dir = mntdir; - mnt.mnt_fsname = fs_name; - mnt.mnt_type = MNTTAB_TYPE_XFS; - mnt.mnt_opts = opts; - - flags = compute_mount_flags(&mnt); -#ifdef HAVE_FS_AUTOFS - if (on_autofs) - flags |= autofs_compute_mount_flags(&mnt); -#endif /* HAVE_FS_AUTOFS */ - -#ifdef HAVE_XFS_ARGS_T_FLAGS - xfs_args.flags = 0; /* XXX: fix this to correct flags */ -#endif /* HAVE_XFS_ARGS_T_FLAGS */ -#ifdef HAVE_XFS_ARGS_T_FSPEC - xfs_args.fspec = fs_name; -#endif /* HAVE_XFS_ARGS_T_FSPEC */ - - /* - * Call generic mount routine - */ - return mount_fs(&mnt, flags, (caddr_t) &xfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs); -} - - -static int -xfs_mount(am_node *am, mntfs *mf) -{ - int on_autofs = mf->mf_flags & MFF_ON_AUTOFS; - int error; - - error = mount_xfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs); - if (error) { - errno = error; - plog(XLOG_ERROR, "mount_xfs: %m"); - return error; - } - - return 0; -} - - -static int -xfs_umount(am_node *am, mntfs *mf) -{ - int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0; - - return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags); -} diff --git a/contrib/amd/amd/opts.c b/contrib/amd/amd/opts.c deleted file mode 100644 index a3d35343adc0..000000000000 --- a/contrib/amd/amd/opts.c +++ /dev/null @@ -1,1519 +0,0 @@ -/* - * Copyright (c) 1997-2006 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 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. - * - * - * File: am-utils/amd/opts.c - * - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* - * MACROS: - */ -#define NLEN 16 /* Length of longest option name (conservative) */ -#define S(x) (x) , (sizeof(x)-1) -/* - * The BUFSPACE macros checks that there is enough space - * left in the expansion buffer. If there isn't then we - * give up completely. This is done to avoid crashing the - * automounter itself (which would be a bad thing to do). - */ -#define BUFSPACE(ep, len) (((ep) + (len)) < expbuf+MAXPATHLEN) - -/* - * TYPEDEFS: - */ -typedef int (*IntFuncPtr) (char *); -typedef struct opt_apply opt_apply; -enum vs_opt { SelEQ, SelNE, VarAss }; - -/* - * STRUCTURES - */ -struct opt { - char *name; /* Name of the option */ - int nlen; /* Length of option name */ - char **optp; /* Pointer to option value string */ - char **sel_p; /* Pointer to selector value string */ - int (*fxn_p)(char *); /* Pointer to boolean function */ - int case_insensitive; /* How to do selector comparisons */ -}; - -struct opt_apply { - char **opt; - char *val; -}; - -struct functable { - char *name; - IntFuncPtr func; -}; - -/* - * FORWARD DEFINITION: - */ -static int f_in_network(char *); -static int f_xhost(char *); -static int f_netgrp(char *); -static int f_netgrpd(char *); -static int f_exists(char *); -static int f_false(char *); -static int f_true(char *); -static inline char *expand_options(char *key); - -/* - * STATICS: - */ -static char NullStr[] = "<NULL>"; -static char nullstr[] = ""; -static char *opt_dkey = NullStr; -static char *opt_host = nullstr; /* XXX: was the global hostname */ -static char *opt_hostd = hostd; -static char *opt_key = nullstr; -static char *opt_keyd = nullstr; -static char *opt_map = nullstr; -static char *opt_path = nullstr; -char uid_str[SIZEOF_UID_STR], gid_str[SIZEOF_GID_STR]; -char *opt_uid = uid_str; -char *opt_gid = gid_str; -static char *vars[8]; -static char *literal_dollar = "$"; /* ${dollar}: a literal '$' in maps */ - -/* - * GLOBALS - */ -static struct am_opts fs_static; /* copy of the options to play with */ - - -/* - * Options in some order corresponding to frequency of use so that - * first-match algorithm is sped up. - */ -static struct opt opt_fields[] = { - /* Name and length. - Option str. Selector str. boolean fxn. case sensitive */ - { S("opts"), - &fs_static.opt_opts, 0, 0, FALSE }, - { S("host"), - 0, &opt_host, 0, TRUE }, - { S("hostd"), - 0, &opt_hostd, 0, TRUE }, - { S("type"), - &fs_static.opt_type, 0, 0, FALSE }, - { S("rhost"), - &fs_static.opt_rhost, 0, 0, TRUE }, - { S("rfs"), - &fs_static.opt_rfs, 0, 0, FALSE }, - { S("fs"), - &fs_static.opt_fs, 0, 0, FALSE }, - { S("key"), - 0, &opt_key, 0, FALSE }, - { S("map"), - 0, &opt_map, 0, FALSE }, - { S("sublink"), - &fs_static.opt_sublink, 0, 0, FALSE }, - { S("arch"), - 0, &gopt.arch, 0, TRUE }, - { S("dev"), - &fs_static.opt_dev, 0, 0, FALSE }, - { S("pref"), - &fs_static.opt_pref, 0, 0, FALSE }, - { S("path"), - 0, &opt_path, 0, FALSE }, - { S("autodir"), - 0, &gopt.auto_dir, 0, FALSE }, - { S("delay"), - &fs_static.opt_delay, 0, 0, FALSE }, - { S("domain"), - 0, &hostdomain, 0, TRUE }, - { S("karch"), - 0, &gopt.karch, 0, TRUE }, - { S("cluster"), - 0, &gopt.cluster, 0, TRUE }, - { S("wire"), - 0, 0, f_in_network, TRUE }, - { S("network"), - 0, 0, f_in_network, TRUE }, - { S("netnumber"), - 0, 0, f_in_network, TRUE }, - { S("byte"), - 0, &endian, 0, TRUE }, - { S("os"), - 0, &gopt.op_sys, 0, TRUE }, - { S("osver"), - 0, &gopt.op_sys_ver, 0, TRUE }, - { S("full_os"), - 0, &gopt.op_sys_full, 0, TRUE }, - { S("vendor"), - 0, &gopt.op_sys_vendor, 0, TRUE }, - { S("remopts"), - &fs_static.opt_remopts, 0, 0, FALSE }, - { S("mount"), - &fs_static.opt_mount, 0, 0, FALSE }, - { S("unmount"), - &fs_static.opt_unmount, 0, 0, FALSE }, - { S("umount"), - &fs_static.opt_umount, 0, 0, FALSE }, - { S("cache"), - &fs_static.opt_cache, 0, 0, FALSE }, - { S("user"), - &fs_static.opt_user, 0, 0, FALSE }, - { S("group"), - &fs_static.opt_group, 0, 0, FALSE }, - { S(".key"), - 0, &opt_dkey, 0, FALSE }, - { S("key."), - 0, &opt_keyd, 0, FALSE }, - { S("maptype"), - &fs_static.opt_maptype, 0, 0, FALSE }, - { S("cachedir"), - &fs_static.opt_cachedir, 0, 0, FALSE }, - { S("addopts"), - &fs_static.opt_addopts, 0, 0, FALSE }, - { S("uid"), - 0, &opt_uid, 0, FALSE }, - { S("gid"), - 0, &opt_gid, 0, FALSE }, - { S("mount_type"), - &fs_static.opt_mount_type, 0, 0, FALSE }, - { S("dollar"), - &literal_dollar, 0, 0, FALSE }, - { S("var0"), - &vars[0], 0, 0, FALSE }, - { S("var1"), - &vars[1], 0, 0, FALSE }, - { S("var2"), - &vars[2], 0, 0, FALSE }, - { S("var3"), - &vars[3], 0, 0, FALSE }, - { S("var4"), - &vars[4], 0, 0, FALSE }, - { S("var5"), - &vars[5], 0, 0, FALSE }, - { S("var6"), - &vars[6], 0, 0, FALSE }, - { S("var7"), - &vars[7], 0, 0, FALSE }, - { 0, 0, 0, 0, 0, FALSE }, -}; - -static struct functable functable[] = { - { "in_network", f_in_network }, - { "xhost", f_xhost }, - { "netgrp", f_netgrp }, - { "netgrpd", f_netgrpd }, - { "exists", f_exists }, - { "false", f_false }, - { "true", f_true }, - { 0, 0 }, -}; - -/* - * Specially expand the remote host name first - */ -static opt_apply rhost_expansion[] = -{ - {&fs_static.opt_rhost, "${host}"}, - {0, 0}, -}; - -/* - * List of options which need to be expanded - * Note that the order here _may_ be important. - */ -static opt_apply expansions[] = -{ - {&fs_static.opt_sublink, 0}, - {&fs_static.opt_rfs, "${path}"}, - {&fs_static.opt_fs, "${autodir}/${rhost}${rfs}"}, - {&fs_static.opt_opts, "rw"}, - {&fs_static.opt_remopts, "${opts}"}, - {&fs_static.opt_mount, 0}, - {&fs_static.opt_unmount, 0}, - {&fs_static.opt_umount, 0}, - {&fs_static.opt_cachedir, 0}, - {&fs_static.opt_addopts, 0}, - {0, 0}, -}; - -/* - * List of options which need to be free'ed before re-use - */ -static opt_apply to_free[] = -{ - {&fs_static.fs_glob, 0}, - {&fs_static.fs_local, 0}, - {&fs_static.fs_mtab, 0}, - {&fs_static.opt_sublink, 0}, - {&fs_static.opt_rfs, 0}, - {&fs_static.opt_fs, 0}, - {&fs_static.opt_rhost, 0}, - {&fs_static.opt_opts, 0}, - {&fs_static.opt_remopts, 0}, - {&fs_static.opt_mount, 0}, - {&fs_static.opt_unmount, 0}, - {&fs_static.opt_umount, 0}, - {&fs_static.opt_cachedir, 0}, - {&fs_static.opt_addopts, 0}, - {&vars[0], 0}, - {&vars[1], 0}, - {&vars[2], 0}, - {&vars[3], 0}, - {&vars[4], 0}, - {&vars[5], 0}, - {&vars[6], 0}, - {&vars[7], 0}, - {0, 0}, -}; - - -/* - * expand backslash escape sequences - * (escaped slash is handled separately in normalize_slash) - */ -static char -backslash(char **p) -{ - char c; - - if ((*p)[1] == '\0') { - plog(XLOG_USER, "Empty backslash escape"); - return **p; - } - - if (**p == '\\') { - (*p)++; - switch (**p) { - case 'g': - c = '\007'; /* Bell */ - break; - case 'b': - c = '\010'; /* Backspace */ - break; - case 't': - c = '\011'; /* Horizontal Tab */ - break; - case 'n': - c = '\012'; /* New Line */ - break; - case 'v': - c = '\013'; /* Vertical Tab */ - break; - case 'f': - c = '\014'; /* Form Feed */ - break; - case 'r': - c = '\015'; /* Carriage Return */ - break; - case 'e': - c = '\033'; /* Escape */ - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - { - int cnt, val, ch; - - for (cnt = 0, val = 0; cnt < 3; cnt++) { - ch = *(*p)++; - if (ch < '0' || ch > '7') { - (*p)--; - break; - } - val = (val << 3) | (ch - '0'); - } - - if ((val & 0xffffff00) != 0) - plog(XLOG_USER, - "Too large character constant %u\n", - val); - c = (char) val; - --(*p); - } - break; - - default: - c = **p; - break; - } - } else - c = **p; - - return c; -} - - -/* - * Skip to next option in the string - */ -static char * -opt(char **p) -{ - char *cp = *p; - char *dp = cp; - char *s = cp; - -top: - while (*cp && *cp != ';') { - if (*cp == '"') { - /* - * Skip past string - */ - for (cp++; *cp && *cp != '"'; cp++) - if (*cp == '\\') - *dp++ = backslash(&cp); - else - *dp++ = *cp; - if (*cp) - cp++; - } else { - *dp++ = *cp++; - } - } - - /* - * Skip past any remaining ';'s - */ - while (*cp == ';') - cp++; - - /* - * If we have a zero length string - * and there are more fields, then - * parse the next one. This allows - * sequences of empty fields. - */ - if (*cp && dp == s) - goto top; - - *dp = '\0'; - - *p = cp; - return s; -} - - -/* - * These routines add a new style of selector; function-style boolean - * operators. To add new ones, just define functions as in true, false, - * exists (below) and add them to the functable, above. - * - * Usage example: Some people have X11R5 local, some go to a server. I do - * this: - * - * * exists(/usr/pkg/${key});type:=link;fs:=/usr/pkg/${key} || \ - * -type:=nfs;rfs=/usr/pkg/${key} \ - * rhost:=server1 \ - * rhost:=server2 - * - * -Rens Troost <rens@imsi.com> - */ -static IntFuncPtr -functable_lookup(char *key) -{ - struct functable *fp; - - for (fp = functable; fp->name; fp++) - if (FSTREQ(fp->name, key)) - return (fp->func); - return (IntFuncPtr) NULL; -} - - -/* - * Fill in the global structure fs_static by - * cracking the string opts. opts may be - * scribbled on at will. Does NOT evaluate options. - * Returns 0 on error, 1 if no syntax errors were discovered. - */ -static int -split_opts(char *opts, char *mapkey) -{ - char *o = opts; - char *f; - - /* - * For each user-specified option - */ - for (f = opt(&o); *f; f = opt(&o)) { - struct opt *op; - char *eq = strchr(f, '='); - char *opt = NULL; - - if (!eq) - continue; - - if (*(eq-1) == '!' || - eq[1] == '=' || - eq[1] == '!') { /* != or == or =! */ - continue; /* we don't care about selectors */ - } - - if (*(eq-1) == ':') { /* := */ - *(eq-1) = '\0'; - } else { - /* old style assignment */ - eq[0] = '\0'; - } - opt = eq + 1; - - /* - * For each recognized option - */ - for (op = opt_fields; op->name; op++) { - /* - * Check whether they match - */ - if (FSTREQ(op->name, f)) { - if (op->sel_p) { - plog(XLOG_USER, "key %s: Can't assign to a selector (%s)", - mapkey, op->name); - return 0; - } - *op->optp = opt; /* actual assignment into fs_static */ - break; /* break out of for loop */ - } /* end of "if (FSTREQ(op->name, f))" statement */ - } /* end of "for (op = opt_fields..." statement */ - - if (!op->name) - plog(XLOG_USER, "key %s: Unrecognized key/option \"%s\"", mapkey, f); - } - - return 1; -} - - -/* - * Just evaluate selectors, which were split by split_opts. - * Returns 0 on error or no match, 1 if matched. - */ -static int -eval_selectors(char *opts, char *mapkey) -{ - char *o, *old_o; - char *f; - int ret = 0; - - o = old_o = strdup(opts); - - /* - * For each user-specified option - */ - for (f = opt(&o); *f; f = opt(&o)) { - struct opt *op; - enum vs_opt vs_opt; - char *eq = strchr(f, '='); - char *fx; - IntFuncPtr func; - char *opt = NULL; - char *arg; - - if (!eq) { - /* - * No value, is it a function call? - */ - arg = strchr(f, '('); - - if (!arg || arg[1] == '\0' || arg == f) { - /* - * No, just continue - */ - plog(XLOG_USER, "key %s: No value component in \"%s\"", mapkey, f); - continue; - } - - /* null-terminate the argument */ - *arg++ = '\0'; - fx = strchr(arg, ')'); - if (!arg || fx == arg) { - plog(XLOG_USER, "key %s: Malformed function in \"%s\"", mapkey, f); - continue; - } - *fx = '\0'; - - if (f[0] == '!') { - vs_opt = SelNE; - f++; - } else { - vs_opt = SelEQ; - } - /* - * look up f in functable and pass it arg. - * func must return 0 on failure, and 1 on success. - */ - if ((func = functable_lookup(f))) { - int funok; - - /* this allocates memory, don't forget to free */ - arg = expand_options(arg); - funok = func(arg); - XFREE(arg); - - if (vs_opt == SelNE) - funok = !funok; - if (!funok) - goto out; - - continue; - } else { - plog(XLOG_USER, "key %s: unknown function \"%s\"", mapkey, f); - goto out; - } - } else { - if (eq[1] == '\0' || eq == f) { - /* misformed selector */ - plog(XLOG_USER, "key %s: Bad selector \"%s\"", mapkey, f); - continue; - } - } - - /* - * Check what type of operation is happening - * !=, =! is SelNE - * == is SelEQ - * =, := is VarAss - */ - if (*(eq-1) == '!') { /* != */ - vs_opt = SelNE; - *(eq-1) = '\0'; - opt = eq + 1; - } else if (*(eq-1) == ':') { /* := */ - continue; - } else if (eq[1] == '=') { /* == */ - vs_opt = SelEQ; - eq[0] = '\0'; - opt = eq + 2; - } else if (eq[1] == '!') { /* =! */ - vs_opt = SelNE; - eq[0] = '\0'; - opt = eq + 2; - } else { - /* old style assignment */ - continue; - } - - /* - * For each recognized option - */ - for (op = opt_fields; op->name; op++) { - /* - * Check whether they match - */ - if (FSTREQ(op->name, f)) { - opt = expand_options(opt); - - if (op->sel_p != NULL) { - int selok; - if (op->case_insensitive) { - selok = STRCEQ(*op->sel_p, opt); - } else { - selok = STREQ(*op->sel_p, opt); - } - if (vs_opt == SelNE) - selok = !selok; - if (!selok) { - plog(XLOG_MAP, "key %s: map selector %s (=%s) did not %smatch %s", - mapkey, - op->name, - *op->sel_p, - vs_opt == SelNE ? "mis" : "", - opt); - XFREE(opt); - goto out; - } - XFREE(opt); - } - /* check if to apply a function */ - if (op->fxn_p) { - int funok; - - funok = op->fxn_p(opt); - if (vs_opt == SelNE) - funok = !funok; - if (!funok) { - plog(XLOG_MAP, "key %s: map function %s did not %smatch %s", - mapkey, - op->name, - vs_opt == SelNE ? "mis" : "", - opt); - XFREE(opt); - goto out; - } - XFREE(opt); - } - break; /* break out of for loop */ - } - } - - if (!op->name) - plog(XLOG_USER, "key %s: Unrecognized key/option \"%s\"", mapkey, f); - } - - /* all is ok */ - ret = 1; - - out: - free(old_o); - return ret; -} - - -/* - * Skip to next option in the string, but don't scribble over the string. - * However, *p gets repointed to the start of the next string past ';'. - */ -static char * -opt_no_scribble(char **p) -{ - char *cp = *p; - char *dp = cp; - char *s = cp; - -top: - while (*cp && *cp != ';') { - if (*cp == '\"') { - /* - * Skip past string - */ - cp++; - while (*cp && *cp != '\"') - *dp++ = *cp++; - if (*cp) - cp++; - } else { - *dp++ = *cp++; - } - } - - /* - * Skip past any remaining ';'s - */ - while (*cp == ';') - cp++; - - /* - * If we have a zero length string - * and there are more fields, then - * parse the next one. This allows - * sequences of empty fields. - */ - if (*cp && dp == s) - goto top; - - *p = cp; - return s; -} - - -/* - * Strip any selectors from a string. Selectors are all assumed to be - * first in the string. This is used for the new /defaults method which will - * use selectors as well. - */ -char * -strip_selectors(char *opts, char *mapkey) -{ - /* - * Fill in the global structure fs_static by - * cracking the string opts. opts may be - * scribbled on at will. - */ - char *o = opts; - char *oo = opts; - char *f; - - /* - * Scan options. Note that the opt() function scribbles on the opt string. - */ - while (*(f = opt_no_scribble(&o))) { - enum vs_opt vs_opt = VarAss; - char *eq = strchr(f, '='); - - if (!eq || eq[1] == '\0' || eq == f) { - /* - * No option or assignment? Return as is. - */ - plog(XLOG_USER, "key %s: No option or assignment in \"%s\"", mapkey, f); - return o; - } - /* - * Check what type of operation is happening - * !=, =! is SelNE - * == is SelEQ - * := is VarAss - */ - if (*(eq-1) == '!') { /* != */ - vs_opt = SelNE; - } else if (*(eq-1) == ':') { /* := */ - vs_opt = VarAss; - } else if (eq[1] == '=') { /* == */ - vs_opt = SelEQ; - } else if (eq[1] == '!') { /* =! */ - vs_opt = SelNE; - } - switch (vs_opt) { - case SelEQ: - case SelNE: - /* Skip this selector, maybe there's another one following it */ - plog(XLOG_USER, "skipping selector to \"%s\"", o); - /* store previous match. it may have been the first assignment */ - oo = o; - break; - - case VarAss: - /* found the first assignment, return the string starting with it */ - dlog("found first assignment past selectors \"%s\"", o); - return oo; - } - } - - /* return the same string by default. should not happen. */ - return oo; -} - - -/***************************************************************************** - *** BOOLEAN FUNCTIONS (return 0 if false, 1 if true): *** - *****************************************************************************/ - -/* test if arg is any of this host's network names or numbers */ -static int -f_in_network(char *arg) -{ - int status; - - if (!arg) - return 0; - - status = is_network_member(arg); - dlog("%s is %son a local network", arg, (status ? "" : "not ")); - return status; -} - - -/* - * Test if arg is any of this host's names or aliases (CNAMES). - * Note: this function compares against the fully expanded host name (hostd). - * XXX: maybe we also need to compare against the stripped host name? - */ -static int -f_xhost(char *arg) -{ - struct hostent *hp; - char **cp; - - if (!arg) - return 0; - - /* simple test: does it match main host name? */ - if (STREQ(arg, opt_hostd)) - return 1; - - /* now find all of the names of "arg" and compare against opt_hostd */ - hp = gethostbyname(arg); - if (hp == NULL) { -#ifdef HAVE_HSTRERROR - plog(XLOG_ERROR, "gethostbyname xhost(%s): %s", arg, hstrerror(h_errno)); -#else /* not HAVE_HSTRERROR */ - plog(XLOG_ERROR, "gethostbyname xhost(%s): h_errno %d", arg, h_errno); -#endif /* not HAVE_HSTRERROR */ - return 0; - } - /* check primary name */ - if (hp->h_name) { - dlog("xhost: compare %s==%s", hp->h_name, opt_hostd); - if (STREQ(hp->h_name, opt_hostd)) { - plog(XLOG_INFO, "xhost(%s): matched h_name %s", arg, hp->h_name); - return 1; - } - } - /* check all aliases, if any */ - if (hp->h_aliases == NULL) { - dlog("gethostbyname(%s) has no aliases", arg); - return 0; - } - cp = hp->h_aliases; - while (*cp) { - dlog("xhost: compare alias %s==%s", *cp, opt_hostd); - if (STREQ(*cp, opt_hostd)) { - plog(XLOG_INFO, "xhost(%s): matched alias %s", arg, *cp); - return 1; - } - cp++; - } - /* nothing matched */ - return 0; -} - - -/* test if this host (short hostname form) is in netgroup (arg) */ -static int -f_netgrp(char *arg) -{ - int status; - char *ptr, *nhost; - - if ((ptr = strchr(arg, ',')) != NULL) { - *ptr = '\0'; - nhost = ptr + 1; - } else { - nhost = opt_host; - } - status = innetgr(arg, nhost, NULL, NULL); - dlog("netgrp = %s status = %d host = %s", arg, status, nhost); - if (ptr) - *ptr = ','; - return status; -} - - -/* test if this host (fully-qualified name) is in netgroup (arg) */ -static int -f_netgrpd(char *arg) -{ - int status; - char *ptr, *nhost; - - if ((ptr = strchr(arg, ',')) != NULL) { - *ptr = '\0'; - nhost = ptr + 1; - } else { - nhost = opt_hostd; - } - status = innetgr(arg, nhost, NULL, NULL); - dlog("netgrp = %s status = %d hostd = %s", arg, status, nhost); - if (ptr) - *ptr = ','; - return status; -} - - -/* test if file (arg) exists via lstat */ -static int -f_exists(char *arg) -{ - struct stat buf; - - if (lstat(arg, &buf) < 0) - return (0); - else - return (1); -} - - -/* always false */ -static int -f_false(char *arg) -{ - return (0); -} - - -/* always true */ -static int -f_true(char *arg) -{ - return (1); -} - - -/* - * Free an option - */ -static void -free_op(opt_apply *p, int b) -{ - if (*p->opt) { - XFREE(*p->opt); - } -} - - -/* - * Normalize slashes in the string. - */ -void -normalize_slash(char *p) -{ - char *f, *f0; - - if (!(gopt.flags & CFM_NORMALIZE_SLASHES)) - return; - - f0 = f = strchr(p, '/'); - if (f) { - char *t = f; - do { - /* assert(*f == '/'); */ - if (f == f0 && f[0] == '/' && f[1] == '/') { - /* copy double slash iff first */ - *t++ = *f++; - *t++ = *f++; - } else { - /* copy a single / across */ - *t++ = *f++; - } - - /* assert(f[-1] == '/'); */ - /* skip past more /'s */ - while (*f == '/') - f++; - - /* assert(*f != '/'); */ - /* keep copying up to next / */ - while (*f && *f != '/') { - /* support escaped slashes '\/' */ - if (f[0] == '\\' && f[1] == '/') - f++; /* skip backslash */ - *t++ = *f++; - } - - /* assert(*f == 0 || *f == '/'); */ - - } while (*f); - *t = 0; /* derived from fix by Steven Glassman */ - } -} - - -/* - * Macro-expand an option. Note that this does not - * handle recursive expansions. They will go badly wrong. - * If sel_p is true then old expand selectors, otherwise - * don't expand selectors. - */ -static char * -expand_op(char *opt, int sel_p) -{ -#define EXPAND_ERROR "No space to expand \"%s\"" - char expbuf[MAXPATHLEN + 1]; - char nbuf[NLEN + 1]; - char *ep = expbuf; - char *cp = opt; - char *dp; - struct opt *op; - char *cp_orig = opt; - - while ((dp = strchr(cp, '$'))) { - char ch; - /* - * First copy up to the $ - */ - { - int len = dp - cp; - - if (len > 0) { - if (BUFSPACE(ep, len)) { - /* - * We use strncpy (not xstrlcpy) because 'ep' relies on its - * semantics. BUFSPACE guarantees that ep can hold len. - */ - strncpy(ep, cp, len); - ep += len; - } else { - plog(XLOG_ERROR, EXPAND_ERROR, opt); - goto out; - } - } - } - - cp = dp + 1; - ch = *cp++; - if (ch == '$') { - if (BUFSPACE(ep, 1)) { - *ep++ = '$'; - } else { - plog(XLOG_ERROR, EXPAND_ERROR, opt); - goto out; - } - } else if (ch == '{') { - /* Expansion... */ - enum { - E_All, E_Dir, E_File, E_Domain, E_Host - } todo; - /* - * Find closing brace - */ - char *br_p = strchr(cp, '}'); - int len; - - /* - * Check we found it - */ - if (!br_p) { - /* - * Just give up - */ - plog(XLOG_USER, "No closing '}' in \"%s\"", opt); - goto out; - } - len = br_p - cp; - - /* - * Figure out which part of the variable to grab. - */ - if (*cp == '/') { - /* - * Just take the last component - */ - todo = E_File; - cp++; - --len; - } else if (*(br_p-1) == '/') { - /* - * Take all but the last component - */ - todo = E_Dir; - --len; - } else if (*cp == '.') { - /* - * Take domain name - */ - todo = E_Domain; - cp++; - --len; - } else if (*(br_p-1) == '.') { - /* - * Take host name - */ - todo = E_Host; - --len; - } else { - /* - * Take the whole lot - */ - todo = E_All; - } - - /* - * Truncate if too long. Since it won't - * match anyway it doesn't matter that - * it has been cut short. - */ - if (len > NLEN) - len = NLEN; - - /* - * Put the string into another buffer so - * we can do comparisons. - * - * We use strncpy here (not xstrlcpy) because the dest is meant - * to be truncated and we don't want to log it as an error. The - * use of the BUFSPACE macro above guarantees the safe use of - * strncpy with nbuf. - */ - strncpy(nbuf, cp, len); - nbuf[len] = '\0'; - - /* - * Advance cp - */ - cp = br_p + 1; - - /* - * Search the option array - */ - for (op = opt_fields; op->name; op++) { - /* - * Check for match - */ - if (len == op->nlen && STREQ(op->name, nbuf)) { - char xbuf[NLEN + 3]; - char *val; - /* - * Found expansion. Copy - * the correct value field. - */ - if (!(!op->sel_p == !sel_p)) { - /* - * Copy the string across unexpanded - */ - xsnprintf(xbuf, sizeof(xbuf), "${%s%s%s}", - todo == E_File ? "/" : - todo == E_Domain ? "." : "", - nbuf, - todo == E_Dir ? "/" : - todo == E_Host ? "." : ""); - val = xbuf; - /* - * Make sure expansion doesn't - * munge the value! - */ - todo = E_All; - } else if (op->sel_p) { - val = *op->sel_p; - } else { - val = *op->optp; - } - - if (val) { - /* - * Do expansion: - * ${/var} means take just the last part - * ${var/} means take all but the last part - * ${.var} means take all but first part - * ${var.} means take just the first part - * ${var} means take the whole lot - */ - int vlen = strlen(val); - char *vptr = val; - switch (todo) { - case E_Dir: - vptr = strrchr(val, '/'); - if (vptr) - vlen = vptr - val; - vptr = val; - break; - case E_File: - vptr = strrchr(val, '/'); - if (vptr) { - vptr++; - vlen = strlen(vptr); - } else - vptr = val; - break; - case E_Domain: - vptr = strchr(val, '.'); - if (vptr) { - vptr++; - vlen = strlen(vptr); - } else { - vptr = ""; - vlen = 0; - } - break; - case E_Host: - vptr = strchr(val, '.'); - if (vptr) - vlen = vptr - val; - vptr = val; - break; - case E_All: - break; - } - - if (BUFSPACE(ep, vlen+1)) { - xstrlcpy(ep, vptr, vlen+1); - ep += vlen; - } else { - plog(XLOG_ERROR, EXPAND_ERROR, opt); - goto out; - } - } - /* - * Done with this variable - */ - break; - } - } - - /* - * Check that the search was successful - */ - if (!op->name) { - /* - * If it wasn't then scan the - * environment for that name - * and use any value found - */ - char *env = getenv(nbuf); - - if (env) { - int vlen = strlen(env); - - if (BUFSPACE(ep, vlen+1)) { - xstrlcpy(ep, env, vlen+1); - ep += vlen; - } else { - plog(XLOG_ERROR, EXPAND_ERROR, opt); - goto out; - } - if (amuDebug(D_STR)) - plog(XLOG_DEBUG, "Environment gave \"%s\" -> \"%s\"", nbuf, env); - } else { - plog(XLOG_USER, "Unknown sequence \"${%s}\"", nbuf); - } - } - } else { - /* - * Error, error - */ - plog(XLOG_USER, "Unknown $ sequence in \"%s\"", opt); - } - } - -out: - /* - * Handle common case - no expansion - */ - if (cp == opt) { - opt = strdup(cp); - } else { - /* - * Finish off the expansion - */ - int vlen = strlen(cp); - if (BUFSPACE(ep, vlen+1)) { - xstrlcpy(ep, cp, vlen+1); - /* ep += vlen; */ - } else { - plog(XLOG_ERROR, EXPAND_ERROR, opt); - } - - /* - * Save the expansion - */ - opt = strdup(expbuf); - } - - normalize_slash(opt); - - if (amuDebug(D_STR)) { - plog(XLOG_DEBUG, "Expansion of \"%s\"...", cp_orig); - plog(XLOG_DEBUG, "......... is \"%s\"", opt); - } - return opt; -} - - -/* - * Wrapper for expand_op - */ -static void -expand_opts(opt_apply *p, int sel_p) -{ - if (*p->opt) { - *p->opt = expand_op(*p->opt, sel_p); - } else if (p->val) { - /* - * Do double expansion, remembering - * to free the string from the first - * expansion... - */ - char *s = expand_op(p->val, TRUE); - *p->opt = expand_op(s, sel_p); - XFREE(s); - } -} - - -/* - * Apply a function to a list of options - */ -static void -apply_opts(void (*op) (opt_apply *, int), opt_apply ppp[], int b) -{ - opt_apply *pp; - - for (pp = ppp; pp->opt; pp++) - (*op) (pp, b); -} - - -/* - * Free the option table - */ -void -free_opts(am_opts *fo) -{ - /* - * Copy in the structure we are playing with - */ - fs_static = *fo; - - /* - * Free previously allocated memory - */ - apply_opts(free_op, to_free, FALSE); -} - - -/* - * Expand selectors (variables that cannot be assigned to or overridden) - */ -char * -expand_selectors(char *key) -{ - return expand_op(key, TRUE); -} - - -/* - * Expand options (i.e. non-selectors, see above for definition) - */ -static inline char * -expand_options(char *key) -{ - return expand_op(key, FALSE); -} - - -/* - * Remove trailing /'s from a string - * unless the string is a single / (Steven Glassman) - * or unless it is two slashes // (Kevin D. Bond) - * or unless amd.conf says not to touch slashes. - */ -void -deslashify(char *s) -{ - if (!(gopt.flags & CFM_NORMALIZE_SLASHES)) - return; - - if (s && *s) { - char *sl = s + strlen(s); - - while (*--sl == '/' && sl > s) - *sl = '\0'; - } -} - - -int -eval_fs_opts(am_opts *fo, char *opts, char *g_opts, char *path, char *key, char *map) -{ - int ok = TRUE; - - free_opts(fo); - - /* - * Clear out the option table - */ - memset((voidp) &fs_static, 0, sizeof(fs_static)); - memset((voidp) vars, 0, sizeof(vars)); - memset((voidp) fo, 0, sizeof(*fo)); - - /* set hostname */ - opt_host = (char *) am_get_hostname(); - - /* - * Set key, map & path before expansion - */ - opt_key = key; - opt_map = map; - opt_path = path; - - opt_dkey = strchr(key, '.'); - if (!opt_dkey) { - opt_dkey = NullStr; - opt_keyd = key; - } else { - opt_keyd = strnsave(key, opt_dkey - key); - opt_dkey++; - if (*opt_dkey == '\0') /* check for 'host.' */ - opt_dkey = NullStr; - } - - /* - * Expand global options - */ - fs_static.fs_glob = expand_selectors(g_opts); - - /* - * Expand local options - */ - fs_static.fs_local = expand_selectors(opts); - - /* break global options into fs_static fields */ - if ((ok = split_opts(fs_static.fs_glob, key))) { - dlog("global split_opts ok"); - /* - * evaluate local selectors - */ - if ((ok = eval_selectors(fs_static.fs_local, key))) { - dlog("local eval_selectors ok"); - /* if the local selectors matched, then do the local overrides */ - ok = split_opts(fs_static.fs_local, key); - if (ok) - dlog("local split_opts ok"); - } - } - - /* - * Normalize remote host name. - * 1. Expand variables - * 2. Normalize relative to host tables - * 3. Strip local domains from the remote host - * name before using it in other expansions. - * This makes mount point names and other things - * much shorter, while allowing cross domain - * sharing of mount maps. - */ - apply_opts(expand_opts, rhost_expansion, FALSE); - if (ok && fs_static.opt_rhost && *fs_static.opt_rhost) - host_normalize(&fs_static.opt_rhost); - - /* - * Macro expand the options. - * Do this regardless of whether we are accepting - * this mount - otherwise nasty things happen - * with memory allocation. - */ - apply_opts(expand_opts, expansions, FALSE); - - /* - * Strip trailing slashes from local pathname... - */ - deslashify(fs_static.opt_fs); - - /* - * ok... copy the data back out. - */ - *fo = fs_static; - - /* - * Clear defined options - */ - if (opt_keyd != key && opt_keyd != nullstr) - XFREE(opt_keyd); - opt_keyd = nullstr; - opt_dkey = NullStr; - opt_key = opt_map = opt_path = nullstr; - - return ok; -} diff --git a/contrib/amd/amd/readdir.c b/contrib/amd/amd/readdir.c deleted file mode 100644 index d025c9118c30..000000000000 --- a/contrib/amd/amd/readdir.c +++ /dev/null @@ -1,498 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/readdir.c - * - */ - - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - - -/**************************************************************************** - *** MACROS *** - ****************************************************************************/ -#define DOT_DOT_COOKIE (u_int) 1 -#define MAX_CHAIN 2048 - - -/**************************************************************************** - *** FORWARD DEFINITIONS *** - ****************************************************************************/ -static int key_already_in_chain(char *keyname, const nfsentry *chain); -static nfsentry *make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable); -static int amfs_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count, int fully_browsable); - - -/**************************************************************************** - *** FUNCTIONS *** - ****************************************************************************/ -/* - * Was: NEW_TOPLVL_READDIR - * Search a chain for an entry with some name. - * -Erez Zadok <ezk@cs.columbia.edu> - */ -static int -key_already_in_chain(char *keyname, const nfsentry *chain) -{ - const nfsentry *tmpchain = chain; - - while (tmpchain) { - if (keyname && tmpchain->ne_name && STREQ(keyname, tmpchain->ne_name)) - return 1; - tmpchain = tmpchain->ne_nextentry; - } - - return 0; -} - - -/* - * Create a chain of entries which are not linked. - * -Erez Zadok <ezk@cs.columbia.edu> - */ -static nfsentry * -make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable) -{ - static u_int last_cookie = (u_int) 2; /* monotonically increasing */ - static nfsentry chain[MAX_CHAIN]; - static int max_entries = MAX_CHAIN; - char *key; - int num_entries = 0, i; - u_int preflen = 0; - nfsentry *retval = (nfsentry *) NULL; - mntfs *mf; - mnt_map *mmp; - - if (!mp) { - plog(XLOG_DEBUG, "make_entry_chain: mp is (NULL)"); - return retval; - } - mf = mp->am_mnt; - if (!mf) { - plog(XLOG_DEBUG, "make_entry_chain: mp->am_mnt is (NULL)"); - return retval; - } - mmp = (mnt_map *) mf->mf_private; - if (!mmp) { - plog(XLOG_DEBUG, "make_entry_chain: mp->am_mnt->mf_private is (NULL)"); - return retval; - } - - if (mp->am_pref) - preflen = strlen(mp->am_pref); - - /* iterate over keys */ - for (i = 0; i < NKVHASH; i++) { - kv *k; - for (k = mmp->kvhash[i]; k ; k = k->next) { - - /* - * Skip unwanted entries which are either not real entries or - * very difficult to interpret (wildcards...) This test needs - * lots of improvement. Any takers? - */ - key = k->key; - if (!key) - continue; - - /* Skip '/defaults' */ - if (STREQ(key, "/defaults")) - continue; - - /* Skip '*' */ - if (!fully_browsable && strchr(key, '*')) - continue; - - /* - * If the map has a prefix-string then check if the key starts with - * this string, and if it does, skip over this prefix. If it has a - * prefix and it doesn't match the start of the key, skip it. - */ - if (preflen) { - if (preflen > strlen(key)) - continue; - if (!NSTREQ(key, mp->am_pref, preflen)) - continue; - key += preflen; - } - - /* no more '/' are allowed, unless browsable_dirs=full was used */ - if (!fully_browsable && strchr(key, '/')) - continue; - - /* no duplicates allowed */ - if (key_already_in_chain(key, current_chain)) - continue; - - /* fill in a cell and link the entry */ - if (num_entries >= max_entries) { - /* out of space */ - plog(XLOG_DEBUG, "make_entry_chain: no more space in chain"); - if (num_entries > 0) { - chain[num_entries - 1].ne_nextentry = 0; - retval = &chain[0]; - } - return retval; - } - - /* we have space. put entry in next cell */ - ++last_cookie; - chain[num_entries].ne_fileid = (u_int) last_cookie; - *(u_int *) chain[num_entries].ne_cookie = (u_int) last_cookie; - chain[num_entries].ne_name = key; - if (num_entries < max_entries - 1) { /* link to next one */ - chain[num_entries].ne_nextentry = &chain[num_entries + 1]; - } - ++num_entries; - } /* end of "while (k)" */ - } /* end of "for (i ... NKVHASH ..." */ - - /* terminate chain */ - if (num_entries > 0) { - chain[num_entries - 1].ne_nextentry = 0; - retval = &chain[0]; - } - - return retval; -} - - - -/* This one is called only if map is browsable */ -static int -amfs_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count, int fully_browsable) -{ - u_int gen = *(u_int *) cookie; - int chain_length, i; - static nfsentry *te, *te_next; - static int j; - - dp->dl_eof = FALSE; /* assume readdir not done */ - - if (amuDebug(D_READDIR)) - plog(XLOG_DEBUG, "amfs_readdir_browsable gen=%u, count=%d", - gen, count); - - if (gen == 0) { - /* - * In the default instance (which is used to start a search) we return - * "." and "..". - * - * This assumes that the count is big enough to allow both "." and ".." - * to be returned in a single packet. If it isn't (which would be - * fairly unbelievable) then tough. - */ - dlog("amfs_readdir_browsable: default search"); - /* - * Check for enough room. This is extremely approximate but is more - * than enough space. Really need 2 times: - * 4byte fileid - * 4byte cookie - * 4byte name length - * 4byte name - * plus the dirlist structure */ - if (count < (2 * (2 * (sizeof(*ep) + sizeof("..") + 4) + sizeof(*dp)))) - return EINVAL; - - /* - * compute # of entries to send in this chain. - * heuristics: 128 bytes per entry. - * This is too much probably, but it seems to work better because - * of the re-entrant nature of nfs_readdir, and esp. on systems - * like OpenBSD 2.2. - */ - chain_length = count / 128; - - /* reset static state counters */ - te = te_next = NULL; - - dp->dl_entries = ep; - - /* construct "." */ - ep[0].ne_fileid = mp->am_gen; - ep[0].ne_name = "."; - ep[0].ne_nextentry = &ep[1]; - *(u_int *) ep[0].ne_cookie = 0; - - /* construct ".." */ - if (mp->am_parent) - ep[1].ne_fileid = mp->am_parent->am_gen; - else - ep[1].ne_fileid = mp->am_gen; - - ep[1].ne_name = ".."; - ep[1].ne_nextentry = 0; - *(u_int *) ep[1].ne_cookie = DOT_DOT_COOKIE; - - /* - * If map is browsable, call a function make_entry_chain() to construct - * a linked list of unmounted keys, and return it. Then link the chain - * to the regular list. Get the chain only once, but return - * chunks of it each time. - */ - te = make_entry_chain(mp, dp->dl_entries, fully_browsable); - if (!te) - return 0; - if (amuDebug(D_READDIR)) { - nfsentry *ne; - for (j = 0, ne = te; ne; ne = ne->ne_nextentry) - plog(XLOG_DEBUG, "gen1 key %4d \"%s\"", j++, ne->ne_name); - } - - /* return only "chain_length" entries */ - te_next = te; - for (i=1; i<chain_length; ++i) { - te_next = te_next->ne_nextentry; - if (!te_next) - break; - } - if (te_next) { - nfsentry *te_saved = te_next->ne_nextentry; - te_next->ne_nextentry = NULL; /* terminate "te" chain */ - te_next = te_saved; /* save rest of "te" for next iteration */ - dp->dl_eof = FALSE; /* tell readdir there's more */ - } else { - dp->dl_eof = TRUE; /* tell readdir that's it */ - } - ep[1].ne_nextentry = te; /* append this chunk of "te" chain */ - if (amuDebug(D_READDIR)) { - nfsentry *ne; - for (j = 0, ne = te; ne; ne = ne->ne_nextentry) - plog(XLOG_DEBUG, "gen2 key %4d \"%s\"", j++, ne->ne_name); - for (j = 0, ne = ep; ne; ne = ne->ne_nextentry) - plog(XLOG_DEBUG, "gen2+ key %4d \"%s\" fi=%d ck=%d", - j++, ne->ne_name, ne->ne_fileid, *(u_int *)ne->ne_cookie); - plog(XLOG_DEBUG, "EOF is %d", dp->dl_eof); - } - return 0; - } /* end of "if (gen == 0)" statement */ - - dlog("amfs_readdir_browsable: real child"); - - if (gen == DOT_DOT_COOKIE) { - dlog("amfs_readdir_browsable: End of readdir in %s", mp->am_path); - dp->dl_eof = TRUE; - dp->dl_entries = 0; - return 0; - } - - /* - * If browsable directories, then continue serving readdir() with another - * chunk of entries, starting from where we left off (when gen was equal - * to 0). Once again, assume last chunk served to readdir. - */ - dp->dl_eof = TRUE; - dp->dl_entries = ep; - - te = te_next; /* reset 'te' from last saved te_next */ - if (!te) { /* another indicator of end of readdir */ - dp->dl_entries = 0; - return 0; - } - /* - * compute # of entries to send in this chain. - * heuristics: 128 bytes per entry. - */ - chain_length = count / 128; - - /* return only "chain_length" entries */ - for (i = 1; i < chain_length; ++i) { - te_next = te_next->ne_nextentry; - if (!te_next) - break; - } - if (te_next) { - nfsentry *te_saved = te_next->ne_nextentry; - te_next->ne_nextentry = NULL; /* terminate "te" chain */ - te_next = te_saved; /* save rest of "te" for next iteration */ - dp->dl_eof = FALSE; /* tell readdir there's more */ - } - ep = te; /* send next chunk of "te" chain */ - dp->dl_entries = ep; - if (amuDebug(D_READDIR)) { - nfsentry *ne; - plog(XLOG_DEBUG, "dl_entries=%p, te_next=%p, dl_eof=%d", - dp->dl_entries, te_next, dp->dl_eof); - for (ne = te; ne; ne = ne->ne_nextentry) - plog(XLOG_DEBUG, "gen3 key %4d \"%s\"", j++, ne->ne_name); - } - return 0; -} - - -/* - * This readdir function which call a special version of it that allows - * browsing if browsable_dirs=yes was set on the map. - */ -int -amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count) -{ - u_int gen = *(u_int *) cookie; - am_node *xp; - mntent_t mnt; - - dp->dl_eof = FALSE; /* assume readdir not done */ - - /* check if map is browsable */ - if (mp->am_mnt && mp->am_mnt->mf_mopts) { - mnt.mnt_opts = mp->am_mnt->mf_mopts; - if (amu_hasmntopt(&mnt, "fullybrowsable")) - return amfs_readdir_browsable(mp, cookie, dp, ep, count, TRUE); - if (amu_hasmntopt(&mnt, "browsable")) - return amfs_readdir_browsable(mp, cookie, dp, ep, count, FALSE); - } - - /* when gen is 0, we start reading from the beginning of the directory */ - if (gen == 0) { - /* - * In the default instance (which is used to start a search) we return - * "." and "..". - * - * This assumes that the count is big enough to allow both "." and ".." - * to be returned in a single packet. If it isn't (which would be - * fairly unbelievable) then tough. - */ - dlog("amfs_generic_readdir: default search"); - /* - * Check for enough room. This is extremely approximate but is more - * than enough space. Really need 2 times: - * 4byte fileid - * 4byte cookie - * 4byte name length - * 4byte name - * plus the dirlist structure */ - if (count < (2 * (2 * (sizeof(*ep) + sizeof("..") + 4) + sizeof(*dp)))) - return EINVAL; - - xp = next_nonerror_node(mp->am_child); - dp->dl_entries = ep; - - /* construct "." */ - ep[0].ne_fileid = mp->am_gen; - ep[0].ne_name = "."; - ep[0].ne_nextentry = &ep[1]; - *(u_int *) ep[0].ne_cookie = 0; - - /* construct ".." */ - if (mp->am_parent) - ep[1].ne_fileid = mp->am_parent->am_gen; - else - ep[1].ne_fileid = mp->am_gen; - ep[1].ne_name = ".."; - ep[1].ne_nextentry = 0; - *(u_int *) ep[1].ne_cookie = (xp ? xp->am_gen : DOT_DOT_COOKIE); - - if (!xp) - dp->dl_eof = TRUE; /* by default assume readdir done */ - - if (amuDebug(D_READDIR)) { - nfsentry *ne; - int j; - for (j = 0, ne = ep; ne; ne = ne->ne_nextentry) - plog(XLOG_DEBUG, "gen1 key %4d \"%s\" fi=%d ck=%d", - j++, ne->ne_name, ne->ne_fileid, *(u_int *)ne->ne_cookie); - } - return 0; - } - dlog("amfs_generic_readdir: real child"); - - if (gen == DOT_DOT_COOKIE) { - dlog("amfs_generic_readdir: End of readdir in %s", mp->am_path); - dp->dl_eof = TRUE; - dp->dl_entries = 0; - if (amuDebug(D_READDIR)) - plog(XLOG_DEBUG, "end of readdir eof=TRUE, dl_entries=0\n"); - return 0; - } - - /* non-browsable directories code */ - xp = mp->am_child; - while (xp && xp->am_gen != gen) - xp = xp->am_osib; - - if (xp) { - int nbytes = count / 2; /* conservative */ - int todo = MAX_READDIR_ENTRIES; - - dp->dl_entries = ep; - do { - am_node *xp_next = next_nonerror_node(xp->am_osib); - - if (xp_next) { - *(u_int *) ep->ne_cookie = xp_next->am_gen; - } else { - *(u_int *) ep->ne_cookie = DOT_DOT_COOKIE; - dp->dl_eof = TRUE; - } - - ep->ne_fileid = xp->am_gen; - ep->ne_name = xp->am_name; - nbytes -= sizeof(*ep) + 1; - if (xp->am_name) - nbytes -= strlen(xp->am_name); - - xp = xp_next; - - if (nbytes > 0 && !dp->dl_eof && todo > 1) { - ep->ne_nextentry = ep + 1; - ep++; - --todo; - } else { - todo = 0; - } - } while (todo > 0); - - ep->ne_nextentry = 0; - - if (amuDebug(D_READDIR)) { - nfsentry *ne; - int j; - for (j=0,ne=ep; ne; ne=ne->ne_nextentry) - plog(XLOG_DEBUG, "gen2 key %4d \"%s\" fi=%d ck=%d", - j++, ne->ne_name, ne->ne_fileid, *(u_int *)ne->ne_cookie); - } - return 0; - } - return ESTALE; -} diff --git a/contrib/amd/amd/restart.c b/contrib/amd/amd/restart.c deleted file mode 100644 index 4f71e381e25a..000000000000 --- a/contrib/amd/amd/restart.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/restart.c - * - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - - -static void -restart_fake_mntfs(mntent_t *me, am_ops *fs_ops) -{ - mntfs *mf; - am_opts mo; - char *cp; - - /* - * Partially fake up an opts structure - */ - memset(&mo, 0, sizeof(mo)); - mo.opt_rhost = 0; - mo.opt_rfs = 0; - cp = strchr(me->mnt_fsname, ':'); - if (cp) { - *cp = '\0'; - mo.opt_rhost = strdup(me->mnt_fsname); - mo.opt_rfs = strdup(cp + 1); - *cp = ':'; - } else if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) { - /* - * Hacky workaround for mnttab NFS entries that only list the server - */ - plog(XLOG_WARNING, "NFS server entry assumed to be %s:/", me->mnt_fsname); - mo.opt_rhost = strdup(me->mnt_fsname); - mo.opt_rfs = strdup("/"); - me->mnt_fsname = str3cat(me->mnt_fsname, mo.opt_rhost, ":", "/"); - } - mo.opt_fs = me->mnt_dir; - mo.opt_opts = me->mnt_opts; - - /* - * Make a new mounted filesystem - */ - mf = find_mntfs(fs_ops, &mo, me->mnt_dir, - me->mnt_fsname, "", me->mnt_opts, ""); - if (mf->mf_refc == 1) { - mf->mf_flags |= MFF_RESTART | MFF_MOUNTED; - mf->mf_error = 0; /* Already mounted correctly */ - mf->mf_fo = 0; - /* - * Only timeout non-NFS entries - */ - if (!STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) - mf->mf_flags |= MFF_RSTKEEP; - if (fs_ops->fs_init) { - /* - * Don't care whether this worked since - * it is checked again when the fs is - * inherited. - */ - (void) (*fs_ops->fs_init) (mf); - } - plog(XLOG_INFO, "%s restarted fstype %s on %s, flags 0x%x", - me->mnt_fsname, fs_ops->fs_type, me->mnt_dir, mf->mf_flags); - } else { - /* Something strange happened - two mounts at the same place! */ - free_mntfs(mf); - } - /* - * Clean up mo - */ - if (mo.opt_rhost) - XFREE(mo.opt_rhost); - if (mo.opt_rfs) - XFREE(mo.opt_rfs); -} - - -/* - * Handle an amd restart. - * - * Scan through the mount list finding all "interesting" mount points. - * Next hack up partial data structures and add the mounted file - * system to the list of known filesystems. - * - * This module relies on internal details of other components. If - * you change something else make *sure* restart() still works. - */ -void -restart(void) -{ - mntlist *ml, *mlp; - - /* - * Read the existing mount table. For each entry, find nfs, ufs or auto - * mounts and create a partial am_node to represent it. - */ - for (mlp = ml = read_mtab("restart", mnttab_file_name); - mlp; - mlp = mlp->mnext) { - mntent_t *me = mlp->mnt; - am_ops *fs_ops = 0; - - if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) { - /* - * NFS entry, or possibly an Amd entry... - * The mnt_fsname for daemon mount points is - * host:(pidXXX) - * or (seen on Solaris) - * host:daemon(pidXXX) - */ - char *colon = strchr(me->mnt_fsname, ':'); - if (colon && strstr(colon, "(pid")) - continue; - } - - /* Search for the correct filesystem ops */ - fs_ops = ops_search(me->mnt_type); - - /* - * Catch everything else with symlinks to - * avoid recursive mounts. This is debatable... - */ - if (!fs_ops) - fs_ops = &amfs_link_ops; - - restart_fake_mntfs(me, fs_ops); - } - - /* - * Free the mount list - */ - free_mntlist(ml); -} - - -/* - * Handle an amd restart for amd's own mount points. - * - * Scan through the mount list finding all daemon mount points - * (determined by the presence of a pid inside the mount info). - * Next hack up partial data structures and add the mounted file - * system to the list of known filesystems. - * - * This module relies on internal details of other components. If - * you change something else make *sure* restart() still works. - */ -void -restart_automounter_nodes(void) -{ - mntlist *ml, *mlp; - /* reasonably sized list of restarted nfs ports */ - u_short old_ports[256]; - - memset((voidp) &old_ports, 0, sizeof(u_short) * 256); - - /* - * Read the existing mount table. For each entry, find nfs, ufs or auto - * mounts and create a partial am_node to represent it. - */ - for (mlp = ml = read_mtab("restart", mnttab_file_name); - mlp; - mlp = mlp->mnext) { - mntent_t *me = mlp->mnt; - am_ops *fs_ops = 0; - char *colon; - long pid; - u_short port; - int err; - - if (!STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) - continue; /* to next mlp */ - /* - * NFS entry, or possibly an Amd entry... - * The mnt_fsname for daemon mount points is - * host:(pidXXX) - * or (seen on Solaris) - * host:daemon(pidXXX) - */ - colon = strchr(me->mnt_fsname, ':'); - if (!colon || !strstr(colon, "(pid")) - continue; - /* if got here, then we matched an existing Amd mount point */ - err = 1; - - plog(XLOG_WARNING, "%s is an existing automount point", me->mnt_dir); - - /* Is the old automounter still alive? */ - if (sscanf(colon, "%*[^(](pid%ld%*[,)]", &pid) != 1) { - plog(XLOG_WARNING, "Can't parse pid in %s", me->mnt_fsname); - goto give_up; - } - if (kill(pid, 0) != -1 || errno != ESRCH) { - plog(XLOG_WARNING, "Automounter (pid: %ld) still alive", pid); - goto give_up; - } - - /* - * Do we have a map for this mount point? Who cares, we'll restart - * anyway -- getting ESTALE is way better than hanging. - */ - - /* Can we restart it? Only if it tells us what port it was using... */ - if (sscanf(colon, "%*[^,],port%hu)", &port) != 1) { - plog(XLOG_WARNING, "No port specified for %s", me->mnt_fsname); - goto give_up; - } - - /* Maybe we already own that port... */ - if (port != nfs_port) { - int i; - for (i = 0; i < 256; i++) { - if (old_ports[i] == port || - old_ports[i] == 0) - break; - } - if (i == 256) { - plog(XLOG_WARNING, "Too many open ports (256)"); - goto give_up; - } - - if (old_ports[i] == 0) { - int soNFS; - SVCXPRT *nfsxprt; - if (create_nfs_service(&soNFS, &port, &nfsxprt, nfs_program_2) != 0) { - plog(XLOG_WARNING, "Can't bind to port %u", port); - goto give_up; - } - old_ports[i] = nfs_port = port; - } - } - err = 0; - - give_up: - if (err) { - plog(XLOG_WARNING, "Can't restart %s, leaving it alone", me->mnt_dir); - fs_ops = &amfs_link_ops; - } else { - fs_ops = &amfs_toplvl_ops; - } - - restart_fake_mntfs(me, fs_ops); - } /* end of "for (mlp" */ - - /* free the mount list */ - free_mntlist(ml); -} diff --git a/contrib/amd/amd/rpc_fwd.c b/contrib/amd/amd/rpc_fwd.c deleted file mode 100644 index b3c8be4fa3b7..000000000000 --- a/contrib/amd/amd/rpc_fwd.c +++ /dev/null @@ -1,478 +0,0 @@ -/* - * Copyright (c) 1997-2006 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 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. - * - * - * File: am-utils/amd/rpc_fwd.c - * - */ - -/* - * RPC packet forwarding - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* - * Note that the ID field in the external packet is only - * ever treated as a 32 bit opaque data object, so there - * is no need to convert to and from network byte ordering. - */ - -#define XID_ALLOC() (xid++) -#define MAX_PACKET_SIZE 8192 /* Maximum UDP packet size */ - -/* - * Each pending reply has an rpc_forward structure - * associated with it. These have a 15 second lifespan. - * If a new structure is required, then an expired - * one will be re-allocated if available, otherwise a fresh - * one is allocated. Whenever a reply is received the - * structure is discarded. - */ -typedef struct rpc_forward rpc_forward; -struct rpc_forward { - qelem rf_q; /* Linked list */ - time_t rf_ttl; /* Time to live */ - u_int rf_xid; /* Packet id */ - u_int rf_oldid; /* Original packet id */ - fwd_fun *rf_fwd; /* Forwarding function */ - voidp rf_ptr; - struct sockaddr_in rf_sin; -}; - -/* - * Head of list of pending replies - */ -qelem rpc_head = {&rpc_head, &rpc_head}; -int fwd_sock; -static u_int xid; - - -/* - * Allocate a rely structure - */ -static rpc_forward * -fwd_alloc(void) -{ - time_t now = clocktime(NULL); - rpc_forward *p = 0, *p2; - - /* - * First search for an existing expired one. - */ - ITER(p2, rpc_forward, &rpc_head) { - if (p2->rf_ttl <= now) { - p = p2; - break; - } - } - - /* - * If one couldn't be found then allocate - * a new structure and link it at the - * head of the list. - */ - if (p) { - /* - * Call forwarding function to say that - * this message was junked. - */ - dlog("Re-using packet forwarding slot - id %#x", p->rf_xid); - if (p->rf_fwd) - (*p->rf_fwd) (0, 0, 0, &p->rf_sin, p->rf_ptr, FALSE); - rem_que(&p->rf_q); - } else { - p = ALLOC(struct rpc_forward); - } - ins_que(&p->rf_q, &rpc_head); - - /* - * Set the time to live field - * Timeout in 43 seconds - */ - p->rf_ttl = now + 43; - - return p; -} - - -/* - * Free an allocated reply structure. - * First unlink it from the list, then - * discard it. - */ -static void -fwd_free(rpc_forward *p) -{ - rem_que(&p->rf_q); - XFREE(p); -} - - -/* - * Initialize the RPC forwarder - */ -int -fwd_init(void) -{ -#ifdef FIONBIO - int on = 1; -#endif /* FIONBIO */ - -#ifdef HAVE_TRANSPORT_TYPE_TLI - /* - * Create ping TLI socket (/dev/tcp and /dev/ticlts did not work) - * (HPUX-11 does not like using O_NDELAY in flags) - */ - fwd_sock = t_open("/dev/udp", O_RDWR|O_NONBLOCK, 0); - if (fwd_sock < 0) { - plog(XLOG_ERROR, "unable to create RPC forwarding TLI socket: %s", - t_errlist[t_errno]); - return errno; - } -#else /* not HAVE_TRANSPORT_TYPE_TLI */ - /* - * Create ping socket - */ - fwd_sock = socket(AF_INET, SOCK_DGRAM, 0); - if (fwd_sock < 0) { - plog(XLOG_ERROR, "unable to create RPC forwarding socket: %m"); - return errno; - } -#endif /* not HAVE_TRANSPORT_TYPE_TLI */ - - /* - * Some things we talk to require a priv port - so make one here - */ - if (bind_resv_port(fwd_sock, (u_short *) 0) < 0) - plog(XLOG_ERROR, "can't bind privileged port (rpc_fwd)"); - - if (fcntl(fwd_sock, F_SETFL, FNDELAY) < 0 -#ifdef FIONBIO - && ioctl(fwd_sock, FIONBIO, &on) < 0 -#endif /* FIONBIO */ - ) { - plog(XLOG_ERROR, "Can't set non-block on forwarding socket: %m"); - return errno; - } - - return 0; -} - - -/* - * Locate a packet in the forwarding list - */ -static rpc_forward * -fwd_locate(u_int id) -{ - rpc_forward *p; - - ITER(p, rpc_forward, &rpc_head) { - if (p->rf_xid == id) - return p; - } - - return 0; -} - - -/* - * This is called to forward a packet to another - * RPC server. The message id is changed and noted - * so that when a reply appears we can tie it up - * correctly. Just matching the reply's source address - * would not work because it might come from a - * different address. - */ -int -fwd_packet(int type_id, char *pkt, int len, struct sockaddr_in *fwdto, struct sockaddr_in *replyto, opaque_t cb_arg, fwd_fun cb) -{ - rpc_forward *p; - u_int *pkt_int; - int error; -#ifdef HAVE_TRANSPORT_TYPE_TLI - struct t_unitdata ud; -#endif /* HAVE_TRANSPORT_TYPE_TLI */ - - if ((int) amd_state >= (int) Finishing) - return ENOENT; - - /* - * See if the type_id is fully specified. - * If so, then discard any old entries - * for this id. - * Otherwise make sure the type_id is - * fully qualified by allocating an id here. - */ - switch (type_id & RPC_XID_MASK) { - case RPC_XID_PORTMAP: - dlog("Sending PORTMAP request %#x", type_id); - break; - case RPC_XID_MOUNTD: - dlog("Sending MOUNTD request %#x", type_id); - break; - case RPC_XID_NFSPING: - dlog("Sending NFS ping %#x", type_id); - break; - case RPC_XID_WEBNFS: - dlog("Sending WebNFS lookup %#x", type_id); - break; - default: - dlog("UNKNOWN RPC XID %#x", type_id); - break; - } - - if (type_id & ~RPC_XID_MASK) { - p = fwd_locate(type_id); - if (p) { - dlog("Discarding earlier rpc fwd handle"); - fwd_free(p); - } - } else { - dlog("Allocating a new xid..."); - type_id = MK_RPC_XID(type_id, XID_ALLOC()); - } - - p = fwd_alloc(); - if (!p) - return ENOBUFS; - - error = 0; - - pkt_int = (u_int *) pkt; - - /* - * Get the original packet id - */ - p->rf_oldid = ntohl(*pkt_int); - - /* - * Replace with newly allocated id - */ - p->rf_xid = type_id; - *pkt_int = htonl(type_id); - - /* - * The sendto may fail if, for example, the route - * to a remote host is lost because an intermediate - * gateway has gone down. Important to fill in the - * rest of "p" otherwise nasty things happen later... - */ -#ifdef DEBUG - { - char dq[20]; - if (p && fwdto) - dlog("Sending packet id %#x to %s:%d", - p->rf_xid, - inet_dquad(dq, sizeof(dq), fwdto->sin_addr.s_addr), - ntohs(fwdto->sin_port)); - } -#endif /* DEBUG */ - - /* if NULL, remote server probably down */ - if (!fwdto) { - error = AM_ERRNO_HOST_DOWN; - goto out; - } - -#ifdef HAVE_TRANSPORT_TYPE_TLI - ud.addr.buf = (char *) fwdto; - if (fwdto) /* if NULL, set sizes to zero */ - ud.addr.maxlen = ud.addr.len = sizeof(struct sockaddr_in); - else - ud.addr.maxlen = ud.addr.len = 0; - ud.opt.buf = (char *) NULL; - ud.opt.maxlen = ud.opt.len = 0; - ud.udata.buf = pkt; - ud.udata.maxlen = ud.udata.len = len; - if (t_sndudata(fwd_sock, &ud) < 0) { - plog(XLOG_ERROR,"fwd_packet failed: t_errno=%d, errno=%d",t_errno,errno); - error = errno; - } -#else /* not HAVE_TRANSPORT_TYPE_TLI */ - if (sendto(fwd_sock, (char *) pkt, len, 0, - (struct sockaddr *) fwdto, sizeof(*fwdto)) < 0) - error = errno; -#endif /* not HAVE_TRANSPORT_TYPE_TLI */ - - /* - * Save callback function and return address - */ -out: - p->rf_fwd = cb; - if (replyto) - p->rf_sin = *replyto; - else - memset((voidp) &p->rf_sin, 0, sizeof(p->rf_sin)); - p->rf_ptr = cb_arg; - - return error; -} - - -/* - * Called when some data arrives on the forwarding socket - */ -void -fwd_reply(void) -{ - int len; - u_int pkt[MAX_PACKET_SIZE / sizeof(u_int) + 1]; - u_int *pkt_int; - u_int pkt_xid; - int rc; - rpc_forward *p; - struct sockaddr_in src_addr; - RECVFROM_FROMLEN_TYPE src_addr_len; -#ifdef HAVE_TRANSPORT_TYPE_TLI - struct t_unitdata ud; - int flags = 0; -#endif /* HAVE_TRANSPORT_TYPE_TLI */ - - /* - * Determine the length of the packet - */ - len = MAX_PACKET_SIZE; - - /* - * Read the packet and check for validity - */ -again: - src_addr_len = sizeof(src_addr); -#ifdef HAVE_TRANSPORT_TYPE_TLI - ud.addr.buf = (char *) &src_addr; - ud.addr.maxlen = ud.addr.len = src_addr_len; - ud.opt.buf = (char *) NULL; - ud.opt.maxlen = ud.opt.len = 0; - ud.udata.buf = (char *) pkt; - ud.udata.maxlen = ud.udata.len = len; - /* XXX: use flags accordingly such as if T_MORE set */ - rc = t_rcvudata(fwd_sock, &ud, &flags); - if (rc == 0) /* success, reset rc to length */ - rc = ud.udata.len; - else { - plog(XLOG_ERROR,"fwd_reply failed: t_errno=%d, errno=%d, flags=%d",t_errno,errno, flags); - /* - * Clear error indication, otherwise the error condition persists and - * amd gets into an infinite loop. - */ - if (t_errno == TLOOK) - t_rcvuderr(fwd_sock, NULL); - } -#else /* not HAVE_TRANSPORT_TYPE_TLI */ - rc = recvfrom(fwd_sock, - (char *) pkt, - len, - 0, - (struct sockaddr *) &src_addr, - &src_addr_len); -#endif /* not HAVE_TRANSPORT_TYPE_TLI */ - - /* - * XXX: in svr4, if the T_MORE bit of flags is set, what do - * we then do? -Erez - */ - if (rc < 0 || src_addr_len != sizeof(src_addr) || - src_addr.sin_family != AF_INET) { - if (rc < 0 && errno == EINTR) - goto again; - plog(XLOG_ERROR, "Error reading RPC reply: %m"); - goto out; - } - - /* - * Do no more work if finishing soon - */ - if ((int) amd_state >= (int) Finishing) - goto out; - - /* - * Find packet reference - */ - pkt_int = (u_int *) pkt; - pkt_xid = ntohl(*pkt_int); - - switch (pkt_xid & RPC_XID_MASK) { - case RPC_XID_PORTMAP: - dlog("Receiving PORTMAP reply %#x", pkt_xid); - break; - case RPC_XID_MOUNTD: - dlog("Receiving MOUNTD reply %#x", pkt_xid); - break; - case RPC_XID_NFSPING: - dlog("Receiving NFS ping %#x", pkt_xid); - break; - case RPC_XID_WEBNFS: - dlog("Receiving WebNFS lookup %#x", pkt_xid); - break; - default: - dlog("UNKNOWN RPC XID %#x", pkt_xid); - break; - } - - p = fwd_locate(pkt_xid); - if (!p) { - dlog("Can't forward reply id %#x", pkt_xid); - goto out; - } - - if (p->rf_fwd) { - /* - * Put the original message id back - * into the packet. - */ - *pkt_int = htonl(p->rf_oldid); - - /* - * Call forwarding function - */ - (*p->rf_fwd) ((voidp) pkt, rc, &src_addr, &p->rf_sin, p->rf_ptr, TRUE); - } - - /* - * Free forwarding info - */ - fwd_free(p); - -out:; -} diff --git a/contrib/amd/amd/sched.c b/contrib/amd/amd/sched.c deleted file mode 100644 index 8efe57a3ab81..000000000000 --- a/contrib/amd/amd/sched.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/sched.c - * - */ - -/* - * Process scheduler - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - - -typedef struct pjob pjob; - -struct pjob { - qelem hdr; /* Linked list */ - int pid; /* Process ID of job */ - cb_fun *cb_fun; /* Callback function */ - opaque_t cb_arg; /* Argument for callback */ - int w; /* everyone these days uses int, not a "union wait" */ - wchan_t wchan; /* Wait channel */ -}; - -/* globals */ -qelem proc_list_head = {&proc_list_head, &proc_list_head}; -qelem proc_wait_list = {&proc_wait_list, &proc_wait_list}; -int task_notify_todo; - - -void -ins_que(qelem *elem, qelem *pred) -{ - qelem *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 = elem->q_forw; - qelem *p2 = elem->q_back; - - p2->q_forw = p; - p->q_back = p2; -} - - -static pjob * -sched_job(cb_fun *cf, opaque_t ca) -{ - pjob *p = ALLOC(struct pjob); - - p->cb_fun = cf; - p->cb_arg = ca; - - /* - * Now place on wait queue - */ - ins_que(&p->hdr, &proc_wait_list); - - return p; -} - - -/* - * tf: The task to execute (ta is its arguments) - * cf: Continuation function (ca is its arguments) - */ -void -run_task(task_fun *tf, opaque_t ta, cb_fun *cf, opaque_t ca) -{ - pjob *p = sched_job(cf, ca); -#ifdef HAVE_SIGACTION - sigset_t new, mask; -#else /* not HAVE_SIGACTION */ - int mask; -#endif /* not HAVE_SIGACTION */ - - p->wchan = (wchan_t) p; - -#ifdef HAVE_SIGACTION - sigemptyset(&new); /* initialize signal set we wish to block */ - sigaddset(&new, SIGCHLD); /* only block on SIGCHLD */ - sigprocmask(SIG_BLOCK, &new, &mask); -#else /* not HAVE_SIGACTION */ - mask = sigblock(sigmask(SIGCHLD)); -#endif /* not HAVE_SIGACTION */ - - if ((p->pid = background())) { -#ifdef HAVE_SIGACTION - sigprocmask(SIG_SETMASK, &mask, NULL); -#else /* not HAVE_SIGACTION */ - sigsetmask(mask); -#endif /* not HAVE_SIGACTION */ - return; - } - - /* child code runs here, parent has returned to caller */ - - exit((*tf) (ta)); - /* firewall... */ - abort(); -} - - -/* - * Schedule a task to be run when woken up - */ -void -sched_task(cb_fun *cf, opaque_t ca, wchan_t wchan) -{ - /* - * Allocate a new task - */ - pjob *p = sched_job(cf, ca); - - dlog("SLEEP on %p", wchan); - p->wchan = wchan; - p->pid = 0; - p->w = 0; /* was memset (when ->w was union) */ -} - - -static void -wakeupjob(pjob *p) -{ - rem_que(&p->hdr); - ins_que(&p->hdr, &proc_list_head); - task_notify_todo++; -} - - -void -wakeup(wchan_t wchan) -{ - pjob *p, *p2; - - if (!foreground) - return; - - /* - * Can't use ITER() here because - * wakeupjob() juggles the list. - */ - for (p = AM_FIRST(pjob, &proc_wait_list); - p2 = NEXT(pjob, p), p != HEAD(pjob, &proc_wait_list); - p = p2) { - if (p->wchan == wchan) { - wakeupjob(p); - } - } -} - - -void -wakeup_task(int rc, int term, wchan_t wchan) -{ - wakeup(wchan); -} - - -wchan_t -get_mntfs_wchan(mntfs *mf) -{ - if (mf && - mf->mf_ops && - mf->mf_ops->get_wchan) - return mf->mf_ops->get_wchan(mf); - return mf; -} - - -/* - * Run any pending tasks. - * This must be called with SIGCHLD disabled - */ -void -do_task_notify(void) -{ - /* - * Keep taking the first item off the list and processing it. - * - * Done this way because the callback can, quite reasonably, - * queue a new task, so no local reference into the list can be - * held here. - */ - while (AM_FIRST(pjob, &proc_list_head) != HEAD(pjob, &proc_list_head)) { - pjob *p = AM_FIRST(pjob, &proc_list_head); - rem_que(&p->hdr); - /* - * This job has completed - */ - --task_notify_todo; - - /* - * Do callback if it exists - */ - if (p->cb_fun) { - /* these two trigraphs will ensure compatibility with strict POSIX.1 */ - p->cb_fun(WIFEXITED(p->w) ? WEXITSTATUS(p->w) : 0, - WIFSIGNALED(p->w) ? WTERMSIG(p->w) : 0, - p->cb_arg); - } - XFREE(p); - } -} - - -RETSIGTYPE -sigchld(int sig) -{ - int w; /* everyone these days uses int, not a "union wait" */ - int pid; - -#ifdef HAVE_WAITPID - while ((pid = waitpid((pid_t) -1, &w, WNOHANG)) > 0) { -#else /* not HAVE_WAITPID */ - while ((pid = wait3( &w, WNOHANG, (struct rusage *) 0)) > 0) { -#endif /* not HAVE_WAITPID */ - pjob *p, *p2; - - if (WIFSIGNALED(w)) - plog(XLOG_ERROR, "Process %d exited with signal %d", - pid, WTERMSIG(w)); - else - dlog("Process %d exited with status %d", - pid, WEXITSTATUS(w)); - - for (p = AM_FIRST(pjob, &proc_wait_list); - p2 = NEXT(pjob, p), p != HEAD(pjob, &proc_wait_list); - p = p2) { - if (p->pid == pid) { - p->w = w; - wakeupjob(p); - break; - } - } /* end of for loop */ - - if (p == HEAD(pjob, &proc_wait_list)) - dlog("can't locate task block for pid %d", pid); - - /* - * Must count down children inside the while loop, otherwise we won't - * count them all, and NumChildren (and later backoff) will be set - * incorrectly. SH/RUNIT 940519. - */ - if (--NumChildren < 0) - NumChildren = 0; - } /* end of "while wait..." loop */ - -#ifdef REINSTALL_SIGNAL_HANDLER - signal(sig, sigchld); -#endif /* REINSTALL_SIGNAL_HANDLER */ - - if (select_intr_valid) - longjmp(select_intr, sig); -} diff --git a/contrib/amd/amd/srvr_amfs_auto.c b/contrib/amd/amd/srvr_amfs_auto.c deleted file mode 100644 index 4742cf6f750d..000000000000 --- a/contrib/amd/amd/srvr_amfs_auto.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (c) 1997-2006 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 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. - * - * - * File: am-utils/amd/srvr_amfs_auto.c - * - */ - -/* - * Automount FS server ("localhost") modeling - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* globals */ - -/* statics */ -static qelem amfs_auto_srvr_list = {&amfs_auto_srvr_list, &amfs_auto_srvr_list}; -static fserver *localhost; - - -/* - * Find an nfs server for the local host - */ -fserver * -amfs_generic_find_srvr(mntfs *mf) -{ - fserver *fs = localhost; - - if (!fs) { - fs = ALLOC(struct fserver); - fs->fs_refc = 0; - fs->fs_host = strdup("localhost"); - fs->fs_ip = 0; - fs->fs_cid = 0; - fs->fs_pinger = AM_PINGER; - fs->fs_flags = FSF_VALID | FSF_PING_UNINIT; - fs->fs_type = "local"; - fs->fs_private = 0; - fs->fs_prfree = 0; - - ins_que(&fs->fs_q, &amfs_auto_srvr_list); - - srvrlog(fs, "starts up"); - - localhost = fs; - } - fs->fs_refc++; - - return fs; -} - - -/***************************************************************************** - *** GENERIC ROUTINES FOLLOW - *****************************************************************************/ - -/* - * Wakeup anything waiting for this server - */ -void -wakeup_srvr(fserver *fs) -{ - fs->fs_flags &= ~FSF_WANT; - wakeup((voidp) fs); -} - - -/* - * Called when final ttl of server has expired - */ -static void -timeout_srvr(voidp v) -{ - fserver *fs = v; - - /* - * If the reference count is still zero then - * we are free to remove this node - */ - if (fs->fs_refc == 0) { - dlog("Deleting file server %s", fs->fs_host); - if (fs->fs_flags & FSF_WANT) - wakeup_srvr(fs); - - /* - * Remove from queue. - */ - rem_que(&fs->fs_q); - /* - * (Possibly) call the private free routine. - */ - if (fs->fs_private && fs->fs_prfree) - (*fs->fs_prfree) (fs->fs_private); - - /* - * Free the net address - */ - if (fs->fs_ip) - XFREE(fs->fs_ip); - - /* - * Free the host name. - */ - XFREE(fs->fs_host); - - /* - * Discard the fserver object. - */ - XFREE(fs); - } -} - - -/* - * Free a file server - */ -void -free_srvr(fserver *fs) -{ - if (--fs->fs_refc == 0) { - /* - * The reference count is now zero, - * so arrange for this node to be - * removed in AM_TTL seconds if no - * other mntfs is referencing it. - */ - int ttl = (FSRV_ERROR(fs) || FSRV_ISDOWN(fs)) ? 19 : AM_TTL; - - dlog("Last hard reference to file server %s - will timeout in %ds", fs->fs_host, ttl); - if (fs->fs_cid) { - untimeout(fs->fs_cid); - /* - * Turn off pinging - XXX - */ - fs->fs_flags &= ~FSF_PINGING; - } - - /* - * Keep structure lying around for a while - */ - fs->fs_cid = timeout(ttl, timeout_srvr, (voidp) fs); - - /* - * Mark the fileserver down and invalid again - */ - fs->fs_flags &= ~FSF_VALID; - fs->fs_flags |= FSF_DOWN; - } -} - - -/* - * Make a duplicate fserver reference - */ -fserver * -dup_srvr(fserver *fs) -{ - fs->fs_refc++; - return fs; -} - - -/* - * Log state change - */ -void -srvrlog(fserver *fs, char *state) -{ - plog(XLOG_INFO, "file server %s, type %s, state %s", fs->fs_host, fs->fs_type, state); -} diff --git a/contrib/amd/amd/srvr_nfs.c b/contrib/amd/amd/srvr_nfs.c deleted file mode 100644 index 0c74a658e5ee..000000000000 --- a/contrib/amd/amd/srvr_nfs.c +++ /dev/null @@ -1,1042 +0,0 @@ -/* - * Copyright (c) 1997-2006 Erez Zadok - * Copyright (c) 1990 Jan-Simon Pendry - * Copyright (c) 1990 Imperial College of Science, Technology & Medicine - * Copyright (c) 1990 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 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. - * - * - * File: am-utils/amd/srvr_nfs.c - * - */ - -/* - * NFS server modeling - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ -#include <am_defs.h> -#include <amd.h> - -/* - * Number of pings allowed to fail before host is declared down - * - three-fifths of the allowed mount time... - */ -#define MAX_ALLOWED_PINGS (3 + /* for luck ... */ 1) - -/* - * How often to ping when starting a new server - */ -#define FAST_NFS_PING 3 - -#if (FAST_NFS_PING * MAX_ALLOWED_PINGS) >= ALLOWED_MOUNT_TIME -# error: sanity check failed in srvr_nfs.c -/* - * you cannot do things this way... - * sufficient fast pings must be given the chance to fail - * within the allowed mount time - */ -#endif /* (FAST_NFS_PING * MAX_ALLOWED_PINGS) >= ALLOWED_MOUNT_TIME */ - -/* structures and typedefs */ -typedef struct nfs_private { - u_short np_mountd; /* Mount daemon port number */ - char np_mountd_inval; /* Port *may* be invalid */ - int np_ping; /* Number of failed ping attempts */ - time_t np_ttl; /* Time when server is thought dead */ - int np_xid; /* RPC transaction id for pings */ - int np_error; /* Error during portmap request */ -} nfs_private; - -/* globals */ -qelem nfs_srvr_list = {&nfs_srvr_list, &nfs_srvr_list}; - -/* statics */ -static int global_xid; /* For NFS pings */ -#define XID_ALLOC() (++global_xid) - -#ifdef HAVE_FS_NFS3 -# define NUM_NFS_VERS 2 -#else /* not HAVE_FS_NFS3 */ -# define NUM_NFS_VERS 1 -#endif /* not HAVE_FS_NFS3 */ -static int ping_len[NUM_NFS_VERS]; -static char ping_buf[NUM_NFS_VERS][sizeof(struct rpc_msg) + 32]; - -#if defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) -/* - * Protocols we know about, in order of preference. - * - * Note that Solaris 8 and newer NetBSD systems are switching to UDP first, - * so this order may have to be adjusted for Amd in the future once more - * vendors make that change. -Erez 11/24/2000 - * - * Or we might simply make this is a platform-specific order. -Ion 09/13/2003 - */ -static char *protocols[] = { "tcp", "udp", NULL }; -#endif /* defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */ - -/* forward definitions */ -static void nfs_keepalive(voidp); - - -/* - * Flush cached data for an fserver (or for all, if fs==NULL) - */ -void -flush_srvr_nfs_cache(fserver *fs) -{ - fserver *fs2 = NULL; - - ITER(fs2, fserver, &nfs_srvr_list) { - if (fs == NULL || fs == fs2) { - nfs_private *np = (nfs_private *) fs2->fs_private; - if (np) { - np->np_mountd_inval = TRUE; - np->np_error = -1; - } - } - } -} - - -/* - * Startup the NFS ping for a particular version. - */ -static void -create_ping_payload(u_long nfs_version) -{ - XDR ping_xdr; - struct rpc_msg ping_msg; - - /* - * Non nfs mounts like /afs/glue.umd.edu have ended up here. - */ - if (nfs_version == 0) { - nfs_version = NFS_VERSION; - plog(XLOG_WARNING, "create_ping_payload: nfs_version = 0, changed to 2"); - } else - plog(XLOG_INFO, "create_ping_payload: nfs_version: %d", (int) nfs_version); - - rpc_msg_init(&ping_msg, NFS_PROGRAM, nfs_version, NFSPROC_NULL); - - /* - * Create an XDR endpoint - */ - xdrmem_create(&ping_xdr, ping_buf[nfs_version - NFS_VERSION], sizeof(ping_buf[0]), XDR_ENCODE); - - /* - * Create the NFS ping message - */ - if (!xdr_callmsg(&ping_xdr, &ping_msg)) { - plog(XLOG_ERROR, "Couldn't create ping RPC message"); - going_down(3); - } - /* - * Find out how long it is - */ - ping_len[nfs_version - NFS_VERSION] = xdr_getpos(&ping_xdr); - - /* - * Destroy the XDR endpoint - we don't need it anymore - */ - xdr_destroy(&ping_xdr); -} - - -/* - * Called when a portmap reply arrives - */ -static void -got_portmap(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia, voidp idv, int done) -{ - fserver *fs2 = (fserver *) idv; - fserver *fs = 0; - - /* - * Find which fileserver we are talking about - */ - ITER(fs, fserver, &nfs_srvr_list) - if (fs == fs2) - break; - - if (fs == fs2) { - u_long port = 0; /* XXX - should be short but protocol is naff */ - int error = done ? pickup_rpc_reply(pkt, len, (voidp) &port, (XDRPROC_T_TYPE) xdr_u_long) : -1; - nfs_private *np = (nfs_private *) fs->fs_private; - - if (!error && port) { - dlog("got port (%d) for mountd on %s", (int) port, fs->fs_host); - /* - * Grab the port number. Portmap sends back - * an u_long in native ordering, so it - * needs converting to a u_short in - * network ordering. - */ - np->np_mountd = htons((u_short) port); - np->np_mountd_inval = FALSE; - np->np_error = 0; - } else { - dlog("Error fetching port for mountd on %s", fs->fs_host); - dlog("\t error=%d, port=%d", error, (int) port); - /* - * Almost certainly no mountd running on remote host - */ - np->np_error = error ? error : ETIMEDOUT; - } - - if (fs->fs_flags & FSF_WANT) - wakeup_srvr(fs); - } else if (done) { - dlog("Got portmap for old port request"); - } else { - dlog("portmap request timed out"); - } -} - - -/* - * Obtain portmap information - */ -static int -call_portmap(fserver *fs, AUTH *auth, u_long prog, u_long vers, u_long prot) -{ - struct rpc_msg pmap_msg; - int len; - char iobuf[UDPMSGSIZE]; - int error; - struct pmap pmap; - - rpc_msg_init(&pmap_msg, PMAPPROG, PMAPVERS, PMAPPROC_NULL); - pmap.pm_prog = prog; - pmap.pm_vers = vers; - pmap.pm_prot = prot; - pmap.pm_port = 0; - len = make_rpc_packet(iobuf, - sizeof(iobuf), - PMAPPROC_GETPORT, - &pmap_msg, - (voidp) &pmap, - (XDRPROC_T_TYPE) xdr_pmap, - auth); - if (len > 0) { - struct sockaddr_in sin; - memset((voidp) &sin, 0, sizeof(sin)); - sin = *fs->fs_ip; - sin.sin_port = htons(PMAPPORT); - error = fwd_packet(RPC_XID_PORTMAP, iobuf, len, - &sin, &sin, (voidp) fs, got_portmap); - } else { - error = -len; - } - - return error; -} - - -static void -recompute_portmap(fserver *fs) -{ - int error; - u_long mnt_version; - - /* - * No portmap calls for pure WebNFS servers. - */ - if (fs->fs_flags & FSF_WEBNFS) - return; - - if (nfs_auth) - error = 0; - else - error = make_nfs_auth(); - - if (error) { - nfs_private *np = (nfs_private *) fs->fs_private; - np->np_error = error; - return; - } - - if (fs->fs_version == 0) - plog(XLOG_WARNING, "recompute_portmap: nfs_version = 0 fixed"); - - plog(XLOG_INFO, "recompute_portmap: NFS version %d on %s", - (int) fs->fs_version, fs->fs_host); -#ifdef HAVE_FS_NFS3 - if (fs->fs_version == NFS_VERSION3) - mnt_version = AM_MOUNTVERS3; - else -#endif /* HAVE_FS_NFS3 */ - mnt_version = MOUNTVERS; - - plog(XLOG_INFO, "Using MOUNT version: %d", (int) mnt_version); - call_portmap(fs, nfs_auth, MOUNTPROG, mnt_version, (u_long) IPPROTO_UDP); -} - - -int -get_mountd_port(fserver *fs, u_short *port, wchan_t wchan) -{ - int error = -1; - if (FSRV_ISDOWN(fs)) - return EWOULDBLOCK; - - if (FSRV_ISUP(fs)) { - nfs_private *np = (nfs_private *) fs->fs_private; - if (np->np_error == 0) { - *port = np->np_mountd; - error = 0; - } else { - error = np->np_error; - } - /* - * Now go get the port mapping again in case it changed. - * Note that it is used even if (np_mountd_inval) - * is True. The flag is used simply as an - * indication that the mountd may be invalid, not - * that it is known to be invalid. - */ - if (np->np_mountd_inval) - recompute_portmap(fs); - else - np->np_mountd_inval = TRUE; - } - if (error < 0 && wchan && !(fs->fs_flags & FSF_WANT)) { - /* - * If a wait channel is supplied, and no - * error has yet occurred, then arrange - * that a wakeup is done on the wait channel, - * whenever a wakeup is done on this fs node. - * Wakeup's are done on the fs node whenever - * it changes state - thus causing control to - * come back here and new, better things to happen. - */ - fs->fs_flags |= FSF_WANT; - sched_task(wakeup_task, wchan, (wchan_t) fs); - } - return error; -} - - -/* - * This is called when we get a reply to an RPC ping. - * The value of id was taken from the nfs_private - * structure when the ping was transmitted. - */ -static void -nfs_keepalive_callback(voidp pkt, int len, struct sockaddr_in *sp, struct sockaddr_in *tsp, voidp idv, int done) -{ - int xid = (long) idv; /* cast needed for 64-bit archs */ - fserver *fs; - int found_map = 0; - - if (!done) - return; - - /* - * For each node... - */ - ITER(fs, fserver, &nfs_srvr_list) { - nfs_private *np = (nfs_private *) fs->fs_private; - if (np->np_xid == xid && (fs->fs_flags & FSF_PINGING)) { - /* - * Reset the ping counter. - * Update the keepalive timer. - * Log what happened. - */ - if (fs->fs_flags & FSF_DOWN) { - fs->fs_flags &= ~FSF_DOWN; - if (fs->fs_flags & FSF_VALID) { - srvrlog(fs, "is up"); - } else { - if (np->np_ping > 1) - srvrlog(fs, "ok"); - else - srvrlog(fs, "starts up"); - fs->fs_flags |= FSF_VALID; - } - - map_flush_srvr(fs); - } else { - if (fs->fs_flags & FSF_VALID) { - dlog("file server %s type nfs is still up", fs->fs_host); - } else { - if (np->np_ping > 1) - srvrlog(fs, "ok"); - fs->fs_flags |= FSF_VALID; - } - } - - /* - * Adjust ping interval - */ - untimeout(fs->fs_cid); - fs->fs_cid = timeout(fs->fs_pinger, nfs_keepalive, (voidp) fs); - - /* - * Update ttl for this server - */ - np->np_ttl = clocktime(NULL) + - (MAX_ALLOWED_PINGS - 1) * FAST_NFS_PING + fs->fs_pinger - 1; - - /* - * New RPC xid... - */ - np->np_xid = XID_ALLOC(); - - /* - * Failed pings is zero... - */ - np->np_ping = 0; - - /* - * Recompute portmap information if not known - */ - if (np->np_mountd_inval) - recompute_portmap(fs); - - found_map++; - break; - } - } - - if (found_map == 0) - dlog("Spurious ping packet"); -} - - -static void -check_fs_addr_change(fserver *fs) -{ - struct hostent *hp = NULL; - struct in_addr ia; - char *old_ipaddr, *new_ipaddr; - - hp = gethostbyname(fs->fs_host); - if (!hp || - hp->h_addrtype != AF_INET || - !STREQ((char *) hp->h_name, fs->fs_host) || - memcmp((voidp) &fs->fs_ip->sin_addr, - (voidp) hp->h_addr, - sizeof(fs->fs_ip->sin_addr)) == 0) - return; - /* if got here: downed server changed IP address */ - old_ipaddr = strdup(inet_ntoa(fs->fs_ip->sin_addr)); - memmove((voidp) &ia, (voidp) hp->h_addr, sizeof(struct in_addr)); - new_ipaddr = inet_ntoa(ia); /* ntoa uses static buf */ - plog(XLOG_WARNING, "EZK: down fileserver %s changed ip: %s -> %s", - fs->fs_host, old_ipaddr, new_ipaddr); - XFREE(old_ipaddr); - /* copy new IP addr */ - memmove((voidp) &fs->fs_ip->sin_addr, - (voidp) hp->h_addr, - sizeof(fs->fs_ip->sin_addr)); - /* XXX: do we need to un/set these flags? */ - fs->fs_flags &= ~FSF_DOWN; - fs->fs_flags |= FSF_VALID | FSF_WANT; - map_flush_srvr(fs); /* XXX: a race with flush_srvr_nfs_cache? */ - flush_srvr_nfs_cache(fs); - fs->fs_flags |= FSF_FORCE_UNMOUNT; - -#if 0 - flush_nfs_fhandle_cache(fs); /* done in caller: nfs_keepalive_timeout */ - /* XXX: need to purge nfs_private so that somehow it will get re-initialized? */ -#endif -} - - -/* - * Called when no ping-reply received - */ -static void -nfs_keepalive_timeout(voidp v) -{ - fserver *fs = v; - nfs_private *np = (nfs_private *) fs->fs_private; - - /* - * Another ping has failed - */ - np->np_ping++; - if (np->np_ping > 1) - srvrlog(fs, "not responding"); - - /* - * Not known to be up any longer - */ - if (FSRV_ISUP(fs)) - fs->fs_flags &= ~FSF_VALID; - - /* - * If ttl has expired then guess that it is dead - */ - if (np->np_ttl < clocktime(NULL)) { - int oflags = fs->fs_flags; - dlog("ttl has expired"); - if ((fs->fs_flags & FSF_DOWN) == 0) { - /* - * Server was up, but is now down. - */ - srvrlog(fs, "is down"); - fs->fs_flags |= FSF_DOWN | FSF_VALID; - /* - * Since the server is down, the portmap - * information may now be wrong, so it - * must be flushed from the local cache - */ - flush_nfs_fhandle_cache(fs); - np->np_error = -1; - check_fs_addr_change(fs); /* check if IP addr of fserver changed */ - } else { - /* - * Known to be down - */ - if ((fs->fs_flags & FSF_VALID) == 0) - srvrlog(fs, "starts down"); - fs->fs_flags |= FSF_VALID; - } - if (oflags != fs->fs_flags && (fs->fs_flags & FSF_WANT)) - wakeup_srvr(fs); - /* - * Reset failed ping count - */ - np->np_ping = 0; - } else { - if (np->np_ping > 1) - dlog("%d pings to %s failed - at most %d allowed", np->np_ping, fs->fs_host, MAX_ALLOWED_PINGS); - } - - /* - * New RPC xid, so any late responses to the previous ping - * get ignored... - */ - np->np_xid = XID_ALLOC(); - - /* - * Run keepalive again - */ - nfs_keepalive(fs); -} - - -/* - * Keep track of whether a server is alive - */ -static void -nfs_keepalive(voidp v) -{ - fserver *fs = v; - int error; - nfs_private *np = (nfs_private *) fs->fs_private; - int fstimeo = -1; - - /* - * Send an NFS ping to this node - */ - - if (ping_len[fs->fs_version - NFS_VERSION] == 0) - create_ping_payload(fs->fs_version); - - /* - * Queue the packet... - */ - error = fwd_packet(MK_RPC_XID(RPC_XID_NFSPING, np->np_xid), - ping_buf[fs->fs_version - NFS_VERSION], - ping_len[fs->fs_version - NFS_VERSION], - fs->fs_ip, - (struct sockaddr_in *) 0, - (voidp) ((long) np->np_xid), /* cast needed for 64-bit archs */ - nfs_keepalive_callback); - - /* - * See if a hard error occurred - */ - switch (error) { - case ENETDOWN: - case ENETUNREACH: - case EHOSTDOWN: - case EHOSTUNREACH: - np->np_ping = MAX_ALLOWED_PINGS; /* immediately down */ - np->np_ttl = (time_t) 0; - /* - * This causes an immediate call to nfs_keepalive_timeout - * whenever the server was thought to be up. - * See +++ below. - */ - fstimeo = 0; - break; - - case 0: - dlog("Sent NFS ping to %s", fs->fs_host); - break; - } - - /* - * Back off the ping interval if we are not getting replies and - * the remote system is known to be down. - */ - switch (fs->fs_flags & (FSF_DOWN | FSF_VALID)) { - case FSF_VALID: /* Up */ - if (fstimeo < 0) /* +++ see above */ - fstimeo = FAST_NFS_PING; - break; - - case FSF_VALID | FSF_DOWN: /* Down */ - fstimeo = fs->fs_pinger; - break; - - default: /* Unknown */ - fstimeo = FAST_NFS_PING; - break; - } - - dlog("NFS timeout in %d seconds", fstimeo); - - fs->fs_cid = timeout(fstimeo, nfs_keepalive_timeout, (voidp) fs); -} - - -static void -start_nfs_pings(fserver *fs, int pingval) -{ - if (pingval == 0) /* could be because ping mnt option not found */ - pingval = AM_PINGER; - /* if pings haven't been initalized, then init them for first time */ - if (fs->fs_flags & FSF_PING_UNINIT) { - fs->fs_flags &= ~FSF_PING_UNINIT; - plog(XLOG_INFO, "initializing %s's pinger to %d sec", fs->fs_host, pingval); - goto do_pings; - } - - if ((fs->fs_flags & FSF_PINGING) && fs->fs_pinger == pingval) { - dlog("already running pings to %s", fs->fs_host); - return; - } - - /* if got here, then we need to update the ping value */ - plog(XLOG_INFO, "changing %s's ping value from %d%s to %d%s", - fs->fs_host, - fs->fs_pinger, (fs->fs_pinger < 0 ? " (off)" : ""), - pingval, (pingval < 0 ? " (off)" : "")); - do_pings: - fs->fs_pinger = pingval; - - if (fs->fs_cid) - untimeout(fs->fs_cid); - if (pingval < 0) { - srvrlog(fs, "wired up (pings disabled)"); - fs->fs_flags |= FSF_VALID; - fs->fs_flags &= ~FSF_DOWN; - } else { - fs->fs_flags |= FSF_PINGING; - nfs_keepalive(fs); - } -} - - -/* - * Find an nfs server for a host. - */ -fserver * -find_nfs_srvr(mntfs *mf) -{ - char *host = mf->mf_fo->opt_rhost; - fserver *fs; - int pingval; - mntent_t mnt; - nfs_private *np; - struct hostent *hp = NULL; - struct sockaddr_in *ip = NULL; - u_long nfs_version = 0; /* default is no version specified */ - u_long best_nfs_version = 0; - char *nfs_proto = NULL; /* no IP protocol either */ - int nfs_port = 0; - int nfs_port_opt = 0; - int fserver_is_down = 0; - - /* - * Get ping interval from mount options. - * Current only used to decide whether pings - * are required or not. < 0 = no pings. - */ - mnt.mnt_opts = mf->mf_mopts; - pingval = hasmntval(&mnt, "ping"); - - if (mf->mf_flags & MFF_NFS_SCALEDOWN) { - /* - * the server granted us a filehandle, but we were unable to mount it. - * therefore, scale down to NFSv2/UDP and try again. - */ - nfs_version = NFS_VERSION; - nfs_proto = "udp"; - plog(XLOG_WARNING, "find_nfs_srvr: NFS mount failed, trying again with NFSv2/UDP"); - mf->mf_flags &= ~MFF_NFS_SCALEDOWN; - } else { - /* - * Get the NFS version from the mount options. This is used - * to decide the highest NFS version to try. - */ -#ifdef MNTTAB_OPT_VERS - nfs_version = hasmntval(&mnt, MNTTAB_OPT_VERS); -#endif /* MNTTAB_OPT_VERS */ - -#ifdef MNTTAB_OPT_PROTO - { - char *proto_opt = hasmnteq(&mnt, MNTTAB_OPT_PROTO); - if (proto_opt) { - char **p; - for (p = protocols; *p; p++) - if (NSTREQ(proto_opt, *p, strlen(*p))) { - nfs_proto = *p; - break; - } - if (*p == NULL) - plog(XLOG_WARNING, "ignoring unknown protocol option for %s:%s", - host, mf->mf_fo->opt_rfs); - } - } -#endif /* MNTTAB_OPT_PROTO */ - -#ifdef HAVE_NFS_NFSV2_H - /* allow overriding if nfsv2 option is specified in mount options */ - if (amu_hasmntopt(&mnt, "nfsv2")) { - nfs_version = NFS_VERSION;/* nullify any ``vers=X'' statements */ - nfs_proto = "udp"; /* nullify any ``proto=tcp'' statements */ - plog(XLOG_WARNING, "found compatibility option \"nfsv2\": set options vers=2,proto=udp for host %s", host); - } -#endif /* HAVE_NFS_NFSV2_H */ - - /* check if we've globally overridden the NFS version/protocol */ - if (gopt.nfs_vers) { - nfs_version = gopt.nfs_vers; - plog(XLOG_INFO, "find_nfs_srvr: force NFS version to %d", - (int) nfs_version); - } - if (gopt.nfs_proto) { - nfs_proto = gopt.nfs_proto; - plog(XLOG_INFO, "find_nfs_srvr: force NFS protocol transport to %s", nfs_proto); - } - } - - /* - * lookup host address and canonical name - */ - hp = gethostbyname(host); - - /* - * New code from Bob Harris <harris@basil-rathbone.mit.edu> - * Use canonical name to keep track of file server - * information. This way aliases do not generate - * multiple NFS pingers. (Except when we're normalizing - * hosts.) - */ - if (hp && !(gopt.flags & CFM_NORMALIZE_HOSTNAMES)) - host = (char *) hp->h_name; - - if (hp) { - switch (hp->h_addrtype) { - case AF_INET: - ip = ALLOC(struct sockaddr_in); - memset((voidp) ip, 0, sizeof(*ip)); - /* as per POSIX, sin_len need not be set (used internally by kernel) */ - ip->sin_family = AF_INET; - memmove((voidp) &ip->sin_addr, (voidp) hp->h_addr, sizeof(ip->sin_addr)); - break; - - default: - plog(XLOG_USER, "No IP address for host %s", host); - goto no_dns; - } - } else { - plog(XLOG_USER, "Unknown host: %s", host); - goto no_dns; - } - - /* - * This may not be the best way to do things, but it really doesn't make - * sense to query a file server which is marked as 'down' for any - * version/proto combination. - */ - ITER(fs, fserver, &nfs_srvr_list) { - if (FSRV_ISDOWN(fs) && - STREQ(host, fs->fs_host)) { - plog(XLOG_WARNING, "fileserver %s is already hung - not running NFS proto/version discovery", host); - fs->fs_refc++; - if (ip) - XFREE(ip); - return fs; - } - } - - /* - * Get the NFS Version, and verify server is up. - * If the client only supports NFSv2, hardcode it but still try to - * contact the remote portmapper to see if the service is running. - */ -#ifndef HAVE_FS_NFS3 - nfs_version = NFS_VERSION; - nfs_proto = "udp"; - plog(XLOG_INFO, "The client supports only NFS(2,udp)"); -#endif /* not HAVE_FS_NFS3 */ - - - if (amu_hasmntopt(&mnt, MNTTAB_OPT_PUBLIC)) { - /* - * Use WebNFS to obtain file handles. - */ - mf->mf_flags |= MFF_WEBNFS; - plog(XLOG_INFO, "%s option used, NOT contacting the portmapper on %s", - MNTTAB_OPT_PUBLIC, host); - /* - * Prefer NFSv3/tcp if the client supports it (cf. RFC 2054, 7). - */ - if (!nfs_version) { -#ifdef HAVE_FS_NFS3 - nfs_version = NFS_VERSION3; -#else /* not HAVE_FS_NFS3 */ - nfs_version = NFS_VERSION; -#endif /* not HAVE_FS_NFS3 */ - plog(XLOG_INFO, "No NFS version specified, will use NFSv%d", - (int) nfs_version); - } - if (!nfs_proto) { -#if defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) - nfs_proto = "tcp"; -#else /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */ - nfs_proto = "udp"; -#endif /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */ - plog(XLOG_INFO, "No NFS protocol transport specified, will use %s", - nfs_proto); - } - } else { - /* - * Find the best combination of NFS version and protocol. - * When given a choice, use the highest available version, - * and use TCP over UDP if available. - */ - if (check_pmap_up(host, ip)) { - if (nfs_proto) { - best_nfs_version = get_nfs_version(host, ip, nfs_version, nfs_proto); - nfs_port = ip->sin_port; - } -#ifdef MNTTAB_OPT_PROTO - else { - u_int proto_nfs_version; - char **p; - - for (p = protocols; *p; p++) { - proto_nfs_version = get_nfs_version(host, ip, nfs_version, *p); - - if (proto_nfs_version > best_nfs_version) { - best_nfs_version = proto_nfs_version; - nfs_proto = *p; - nfs_port = ip->sin_port; - } - } - } -#endif /* MNTTAB_OPT_PROTO */ - } else { - plog(XLOG_INFO, "portmapper service not running on %s", host); - } - - /* use the portmapper results only nfs_version is not set yet */ - if (!best_nfs_version) { - /* - * If the NFS server is down or does not support the portmapper call - * (such as certain Novell NFS servers) we mark it as version 2 and we - * let the nfs code deal with the case when it is down. If/when the - * server comes back up and it can support NFSv3 and/or TCP, it will - * use those. - */ - if (nfs_version == 0) { - nfs_version = NFS_VERSION; - nfs_proto = "udp"; - } - plog(XLOG_INFO, "NFS service not running on %s", host); - fserver_is_down = 1; - } else { - if (nfs_version == 0) - nfs_version = best_nfs_version; - plog(XLOG_INFO, "Using NFS version %d, protocol %s on host %s", - (int) nfs_version, nfs_proto, host); - } - } - - /* - * Determine the NFS port. - * - * A valid "port" mount option overrides anything else. - * If the port has been determined from the portmapper, use that. - * Default to NFS_PORT otherwise (cf. RFC 2054, 3). - */ - nfs_port_opt = hasmntval(&mnt, MNTTAB_OPT_PORT); - if (nfs_port_opt > 0) - nfs_port = htons(nfs_port_opt); - if (!nfs_port) - nfs_port = htons(NFS_PORT); - - dlog("find_nfs_srvr: using port %d for nfs on %s", - (int) ntohs(nfs_port), host); - ip->sin_port = nfs_port; - -no_dns: - /* - * Try to find an existing fs server structure for this host. - * Note that differing versions or protocols have their own structures. - * XXX: Need to fix the ping mechanism to actually use the NFS protocol - * chosen here (right now it always uses datagram sockets). - */ - ITER(fs, fserver, &nfs_srvr_list) { - if (STREQ(host, fs->fs_host) && - nfs_version == fs->fs_version && - STREQ(nfs_proto, fs->fs_proto)) { - /* - * fill in the IP address -- this is only needed - * if there is a chance an IP address will change - * between mounts. - * Mike Mitchell, mcm@unx.sas.com, 09/08/93 - */ - if (hp && fs->fs_ip && - memcmp((voidp) &fs->fs_ip->sin_addr, - (voidp) hp->h_addr, - sizeof(fs->fs_ip->sin_addr)) != 0) { - struct in_addr ia; - char *old_ipaddr, *new_ipaddr; - old_ipaddr = strdup(inet_ntoa(fs->fs_ip->sin_addr)); - memmove((voidp) &ia, (voidp) hp->h_addr, sizeof(struct in_addr)); - new_ipaddr = inet_ntoa(ia); /* ntoa uses static buf */ - plog(XLOG_WARNING, "fileserver %s changed ip: %s -> %s", - fs->fs_host, old_ipaddr, new_ipaddr); - XFREE(old_ipaddr); - flush_nfs_fhandle_cache(fs); - memmove((voidp) &fs->fs_ip->sin_addr, (voidp) hp->h_addr, sizeof(fs->fs_ip->sin_addr)); - } - - /* - * If the new file systems doesn't use WebNFS, the nfs pings may - * try to contact the portmapper. - */ - if (!(mf->mf_flags & MFF_WEBNFS)) - fs->fs_flags &= ~FSF_WEBNFS; - - /* check if pingval needs to be updated/set/reset */ - start_nfs_pings(fs, pingval); - - /* - * Following if statement from Mike Mitchell <mcm@unx.sas.com> - * Initialize the ping data if we aren't pinging now. The np_ttl and - * np_ping fields are especially important. - */ - if (!(fs->fs_flags & FSF_PINGING)) { - np = (nfs_private *) fs->fs_private; - np->np_mountd_inval = TRUE; - np->np_xid = XID_ALLOC(); - np->np_error = -1; - np->np_ping = 0; - /* - * Initially the server will be deemed dead - * after MAX_ALLOWED_PINGS of the fast variety - * have failed. - */ - np->np_ttl = MAX_ALLOWED_PINGS * FAST_NFS_PING + clocktime(NULL) - 1; - start_nfs_pings(fs, pingval); - if (fserver_is_down) - fs->fs_flags |= FSF_VALID | FSF_DOWN; - } - - fs->fs_refc++; - if (ip) - XFREE(ip); - return fs; - } - } - - /* - * Get here if we can't find an entry - */ - - /* - * Allocate a new server - */ - fs = ALLOC(struct fserver); - fs->fs_refc = 1; - fs->fs_host = strdup(hp ? hp->h_name : "unknown_hostname"); - if (gopt.flags & CFM_NORMALIZE_HOSTNAMES) - host_normalize(&fs->fs_host); - fs->fs_ip = ip; - fs->fs_cid = 0; - if (ip) { - fs->fs_flags = FSF_DOWN; /* Starts off down */ - } else { - fs->fs_flags = FSF_ERROR | FSF_VALID; - mf->mf_flags |= MFF_ERROR; - mf->mf_error = ENOENT; - } - if (mf->mf_flags & MFF_WEBNFS) - fs->fs_flags |= FSF_WEBNFS; - fs->fs_version = nfs_version; - fs->fs_proto = nfs_proto; - fs->fs_type = MNTTAB_TYPE_NFS; - fs->fs_pinger = AM_PINGER; - fs->fs_flags |= FSF_PING_UNINIT; /* pinger hasn't been initialized */ - np = ALLOC(struct nfs_private); - memset((voidp) np, 0, sizeof(*np)); - np->np_mountd_inval = TRUE; - np->np_xid = XID_ALLOC(); - np->np_error = -1; - - /* - * Initially the server will be deemed dead after - * MAX_ALLOWED_PINGS of the fast variety have failed. - */ - np->np_ttl = clocktime(NULL) + MAX_ALLOWED_PINGS * FAST_NFS_PING - 1; - fs->fs_private = (voidp) np; - fs->fs_prfree = (void (*)(voidp)) free; - - if (!FSRV_ERROR(fs)) { - /* start of keepalive timer, first updating pingval */ - start_nfs_pings(fs, pingval); - if (fserver_is_down) - fs->fs_flags |= FSF_VALID | FSF_DOWN; - } - - /* - * Add to list of servers - */ - ins_que(&fs->fs_q, &nfs_srvr_list); - - return fs; -} |