aboutsummaryrefslogtreecommitdiffstats
path: root/amd
diff options
context:
space:
mode:
Diffstat (limited to 'amd')
-rw-r--r--amd/Makefile.am171
-rw-r--r--amd/Makefile.in1379
-rw-r--r--amd/am_ops.c45
-rw-r--r--amd/amd.820
-rw-r--r--amd/amd.c19
-rw-r--r--amd/amd.h98
-rw-r--r--amd/amfs_auto.c18
-rw-r--r--amd/amfs_direct.c12
-rw-r--r--amd/amfs_error.c12
-rw-r--r--amd/amfs_generic.c243
-rw-r--r--amd/amfs_host.c37
-rw-r--r--amd/amfs_link.c14
-rw-r--r--amd/amfs_linkx.c8
-rw-r--r--amd/amfs_nfsl.c29
-rw-r--r--amd/amfs_nfsx.c41
-rw-r--r--amd/amfs_program.c30
-rw-r--r--amd/amfs_root.c10
-rw-r--r--amd/amfs_toplvl.c17
-rw-r--r--amd/amfs_union.c14
-rw-r--r--amd/amq_subr.c155
-rw-r--r--amd/amq_svc.c175
-rw-r--r--amd/autil.c123
-rw-r--r--amd/clock.c8
-rw-r--r--amd/conf.c145
-rw-r--r--amd/conf_parse.y8
-rw-r--r--amd/conf_tok.l31
-rw-r--r--amd/get_args.c49
-rw-r--r--amd/info_exec.c31
-rw-r--r--amd/info_file.c45
-rw-r--r--amd/info_hesiod.c15
-rw-r--r--amd/info_ldap.c81
-rw-r--r--amd/info_ndbm.c18
-rw-r--r--amd/info_nis.c24
-rw-r--r--amd/info_nisplus.c16
-rw-r--r--amd/info_passwd.c19
-rw-r--r--amd/info_sun.c53
-rw-r--r--amd/info_union.c27
-rw-r--r--amd/map.c294
-rw-r--r--amd/mapc.c160
-rw-r--r--amd/mntfs.c102
-rw-r--r--amd/nfs_prot_svc.c199
-rw-r--r--amd/nfs_start.c62
-rw-r--r--amd/nfs_subr.c1197
-rw-r--r--amd/ops_TEMPLATE.c12
-rw-r--r--amd/ops_autofs.c1279
-rw-r--r--amd/ops_cachefs.c12
-rw-r--r--amd/ops_cdfs.c27
-rw-r--r--amd/ops_efs.c13
-rw-r--r--amd/ops_ext.c223
-rw-r--r--amd/ops_lofs.c10
-rw-r--r--amd/ops_lustre.c203
-rw-r--r--amd/ops_mfs.c8
-rw-r--r--amd/ops_nfs.c138
-rw-r--r--amd/ops_nfs3.c8
-rw-r--r--amd/ops_nfs4.c50
-rw-r--r--amd/ops_nullfs.c8
-rw-r--r--amd/ops_pcfs.c10
-rw-r--r--amd/ops_tfs.c8
-rw-r--r--amd/ops_tmpfs.c152
-rw-r--r--amd/ops_udf.c272
-rw-r--r--amd/ops_ufs.c14
-rw-r--r--amd/ops_umapfs.c8
-rw-r--r--amd/ops_unionfs.c8
-rw-r--r--amd/ops_xfs.c10
-rw-r--r--amd/opts.c73
-rw-r--r--amd/readdir.c528
-rw-r--r--amd/restart.c34
-rw-r--r--amd/rpc_fwd.c12
-rw-r--r--amd/sched.c10
-rw-r--r--amd/srvr_amfs_auto.c19
-rw-r--r--amd/srvr_nfs.c159
-rw-r--r--amd/sun2amd.892
-rw-r--r--amd/sun2amd.c203
-rw-r--r--amd/sun_map.c595
-rw-r--r--amd/sun_map.h123
-rw-r--r--amd/sun_map_parse.y492
-rw-r--r--amd/sun_map_tok.l233
-rwxr-xr-xamd/test1.sh2
78 files changed, 7722 insertions, 2580 deletions
diff --git a/amd/Makefile.am b/amd/Makefile.am
new file mode 100644
index 000000000000..8be0bfc524f3
--- /dev/null
+++ b/amd/Makefile.am
@@ -0,0 +1,171 @@
+## Process this file with automake to produce Makefile.in
+
+# Package: am-utils
+# Level: Makefile for amd/ directory
+# Author: Erez Zadok
+
+# no need for libaminfo to be yet another dynamic library
+noinst_LIBRARIES = libaminfo.a
+sbin_PROGRAMS = amd sun2amd
+
+# man pages
+man_MANS = amd.8 sun2amd.8
+
+YLWRAP= $(top_srcdir)/ylwrap.amd
+
+# test scripts
+TESTS = test1.sh
+
+# headers this depends on, not to be installed
+noinst_HEADERS = amd.h sun_map.h
+
+# sources which get auto-built (from yacc/lex)
+BUILT_SOURCES = \
+ conf_parse.c conf_parse.h conf_tok.c \
+ sun_map_parse.c sun_map_parse.h sun_map_tok.c
+AM_YFLAGS = -d
+
+##############################################################################
+# *.y must be listed before *.l, because of a bug in automake-1.2
+# which will not generate the .h needs for the lex file from the yacc file.
+# I took out the conf .y/.l files b/c of bad interaction between bsd44 make
+# and automake-1.2 rules.
+libaminfo_a_SOURCES = \
+ sun_map_parse.y \
+ sun_map_tok.l \
+ sun_map.c
+
+# the complete list of all optional sources for libaminfo
+EXTRA_libaminfo_a_SOURCES = \
+ info_file.c \
+ info_exec.c \
+ info_hesiod.c \
+ info_ldap.c \
+ info_ndbm.c \
+ info_nis.c \
+ info_nisplus.c \
+ info_passwd.c \
+ info_sun.c \
+ info_union.c
+
+# AMD_INFO_OBJS: a list of info_*.o objects added, depending on which map
+# types this system supports.
+EXTRA_libaminfo_a_OBJECTS = @AMD_INFO_OBJS@
+libaminfo_a_LIBADD = @AMD_INFO_OBJS@
+libaminfo_a_DEPENDENCIES = @AMD_INFO_OBJS@
+
+##############################################################################
+# sources needed: note .y and .l files have to be first
+# get_args.c is handled separately
+amd_SOURCES = \
+ conf_parse.y \
+ conf_tok.l \
+ \
+ am_ops.c \
+ amd.c \
+ amfs_auto.c \
+ amfs_direct.c \
+ amfs_error.c \
+ amfs_generic.c \
+ amfs_host.c \
+ amfs_link.c \
+ amfs_linkx.c \
+ amfs_nfsl.c \
+ amfs_nfsx.c \
+ amfs_program.c \
+ amfs_root.c \
+ amfs_toplvl.c \
+ amfs_union.c \
+ amq_subr.c \
+ amq_svc.c \
+ autil.c \
+ clock.c \
+ conf.c \
+ map.c \
+ mapc.c \
+ mntfs.c \
+ nfs_prot_svc.c \
+ nfs_start.c \
+ nfs_subr.c \
+ opts.c \
+ readdir.c \
+ restart.c \
+ rpc_fwd.c \
+ sched.c \
+ srvr_amfs_auto.c \
+ srvr_nfs.c
+
+# the complete list of all optional sources for amd
+EXTRA_amd_SOURCES = \
+ ops_cachefs.c \
+ ops_cdfs.c \
+ ops_efs.c \
+ ops_ext.c \
+ ops_lofs.c \
+ ops_lustre.c \
+ ops_mfs.c \
+ ops_nfs.c \
+ ops_nfs3.c \
+ ops_nfs4.c \
+ ops_nullfs.c \
+ ops_pcfs.c \
+ ops_tfs.c \
+ ops_tmpfs.c \
+ ops_udf.c \
+ ops_ufs.c \
+ ops_umapfs.c \
+ ops_unionfs.c \
+ ops_xfs.c \
+ \
+ get_args.c
+
+# AMD_FS_OBJS: a list of ops_*.o objects added, depending on which
+# filesystem types this system supports.
+EXTRA_amd_OBJECTS = @AMD_FS_OBJS@
+amd_LDADD = $(EXTRA_amd_OBJECTS) get_args.o libaminfo.a ../libamu/libamu.la
+
+##############################################################################
+sun2amd_SOURCES = \
+ sun2amd.c
+
+sun2amd_LDADD = libaminfo.a ../libamu/libamu.la
+
+##############################################################################
+# must manually add f/lex library to LIBS, and not to LDADD.
+##LIBS = @LIBS@ @LEXLIB@ @WRAPLIB@
+# f/lex libraries are incomatible with multiple scanners: don't include
+LIBS = @LIBS@ @WRAPLIB@
+
+# additional files to distribute and clean
+EXTRA_DIST = ops_TEMPLATE.c $(man_MANS) $(TESTS)
+CLEANFILES = $(BUILT_SOURCES)
+DISTCLEANFILES = build_version.h ops_autofs.c
+
+# do not distribute files that should be generated by lex/yacc locally
+dist-hook:
+ (cd $(distdir) && rm -f $(BUILT_SOURCES))
+
+AM_CPPFLAGS = -I$(top_srcdir)/include
+
+# allow users to add their own flags via "configure --enable-am-flags=ARG"
+AMU_CFLAGS = @AMU_CFLAGS@
+AM_CFLAGS = $(AMU_CFLAGS)
+
+# dependencies
+$(PROGRAMS): $(LDADD)
+get_args.o: build_version.h
+$(amd_OBJECTS) $(EXTRA_amd_OBJECTS) $(sun2amd_OBJECTS) $(libaminfo_a_OBJECTS) $(EXTRA_libaminfo_a_OBJECTS): \
+ ../config.h \
+ ../aux_conf.h \
+ $(top_srcdir)/include/am_compat.h \
+ $(top_srcdir)/include/am_defs.h \
+ $(top_srcdir)/include/am_utils.h \
+ $(top_srcdir)/include/am_xdr_func.h \
+ $(top_srcdir)/include/amq_defs.h \
+ @AMU_NFS_PROT_HEADER@ \
+ @AMU_AUTOFS_PROT_HEADER@ \
+ $(noinst_HEADERS)
+
+# auto-generate build number
+build_version.h: $(amd_OBJECTS) $(EXTRA_amd_OBJECTS) $(libaminfo_a_OBJECTS) $(EXTRA_libaminfo_a_OBJECTS) get_args.c
+ $(top_srcdir)/m4/update_build_version
diff --git a/amd/Makefile.in b/amd/Makefile.in
new file mode 100644
index 000000000000..03b654e439da
--- /dev/null
+++ b/amd/Makefile.in
@@ -0,0 +1,1379 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Package: am-utils
+# Level: Makefile for amd/ directory
+# Author: Erez Zadok
+
+
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+sbin_PROGRAMS = amd$(EXEEXT) sun2amd$(EXEEXT)
+subdir = amd
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/mkinstalldirs sun_map_parse.h sun_map_parse.c \
+ sun_map_tok.c conf_parse.h conf_parse.c conf_tok.c \
+ $(top_srcdir)/depcomp $(top_srcdir)/ylwrap $(noinst_HEADERS) \
+ $(top_srcdir)/test-driver
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 $(top_srcdir)/vers.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+AM_V_AR = $(am__v_AR_@AM_V@)
+am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@)
+am__v_AR_0 = @echo " AR " $@;
+am__v_AR_1 =
+libaminfo_a_AR = $(AR) $(ARFLAGS)
+am_libaminfo_a_OBJECTS = sun_map_parse.$(OBJEXT) sun_map_tok.$(OBJEXT) \
+ sun_map.$(OBJEXT)
+libaminfo_a_OBJECTS = $(am_libaminfo_a_OBJECTS)
+am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"
+PROGRAMS = $(sbin_PROGRAMS)
+am_amd_OBJECTS = conf_parse.$(OBJEXT) conf_tok.$(OBJEXT) \
+ am_ops.$(OBJEXT) amd.$(OBJEXT) amfs_auto.$(OBJEXT) \
+ amfs_direct.$(OBJEXT) amfs_error.$(OBJEXT) \
+ amfs_generic.$(OBJEXT) amfs_host.$(OBJEXT) amfs_link.$(OBJEXT) \
+ amfs_linkx.$(OBJEXT) amfs_nfsl.$(OBJEXT) amfs_nfsx.$(OBJEXT) \
+ amfs_program.$(OBJEXT) amfs_root.$(OBJEXT) \
+ amfs_toplvl.$(OBJEXT) amfs_union.$(OBJEXT) amq_subr.$(OBJEXT) \
+ amq_svc.$(OBJEXT) autil.$(OBJEXT) clock.$(OBJEXT) \
+ conf.$(OBJEXT) map.$(OBJEXT) mapc.$(OBJEXT) mntfs.$(OBJEXT) \
+ nfs_prot_svc.$(OBJEXT) nfs_start.$(OBJEXT) nfs_subr.$(OBJEXT) \
+ opts.$(OBJEXT) readdir.$(OBJEXT) restart.$(OBJEXT) \
+ rpc_fwd.$(OBJEXT) sched.$(OBJEXT) srvr_amfs_auto.$(OBJEXT) \
+ srvr_nfs.$(OBJEXT)
+amd_OBJECTS = $(am_amd_OBJECTS)
+am__DEPENDENCIES_1 =
+amd_DEPENDENCIES = $(am__DEPENDENCIES_1) get_args.o libaminfo.a \
+ ../libamu/libamu.la
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+am_sun2amd_OBJECTS = sun2amd.$(OBJEXT)
+sun2amd_OBJECTS = $(am_sun2amd_OBJECTS)
+sun2amd_DEPENDENCIES = libaminfo.a ../libamu/libamu.la
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+@MAINTAINER_MODE_FALSE@am__skiplex = test -f $@ ||
+LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS)
+LTLEXCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(LEX) $(AM_LFLAGS) $(LFLAGS)
+AM_V_LEX = $(am__v_LEX_@AM_V@)
+am__v_LEX_ = $(am__v_LEX_@AM_DEFAULT_V@)
+am__v_LEX_0 = @echo " LEX " $@;
+am__v_LEX_1 =
+@MAINTAINER_MODE_FALSE@am__skipyacc = test -f $@ ||
+am__yacc_c2h = sed -e s/cc$$/hh/ -e s/cpp$$/hpp/ -e s/cxx$$/hxx/ \
+ -e s/c++$$/h++/ -e s/c$$/h/
+YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS)
+LTYACCCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(YACC) $(AM_YFLAGS) $(YFLAGS)
+AM_V_YACC = $(am__v_YACC_@AM_V@)
+am__v_YACC_ = $(am__v_YACC_@AM_DEFAULT_V@)
+am__v_YACC_0 = @echo " YACC " $@;
+am__v_YACC_1 =
+SOURCES = $(libaminfo_a_SOURCES) $(EXTRA_libaminfo_a_SOURCES) \
+ $(amd_SOURCES) $(EXTRA_amd_SOURCES) $(sun2amd_SOURCES)
+DIST_SOURCES = $(libaminfo_a_SOURCES) $(EXTRA_libaminfo_a_SOURCES) \
+ $(amd_SOURCES) $(EXTRA_amd_SOURCES) $(sun2amd_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+man8dir = $(mandir)/man8
+NROFF = nroff
+MANS = $(man_MANS)
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red=''; \
+ grn=''; \
+ lgn=''; \
+ blu=''; \
+ mgn=''; \
+ brg=''; \
+ std=''; \
+ fi; \
+}
+am__recheck_rx = ^[ ]*:recheck:[ ]*
+am__global_test_result_rx = ^[ ]*:global-test-result:[ ]*
+am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]*
+# A command that, given a newline-separated list of test names on the
+# standard input, print the name of the tests that are to be re-run
+# upon "make recheck".
+am__list_recheck_tests = $(AWK) '{ \
+ recheck = 1; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ { \
+ if ((getline line2 < ($$0 ".log")) < 0) \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
+ { \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
+ { \
+ break; \
+ } \
+ }; \
+ if (recheck) \
+ print $$0; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# A command that, given a newline-separated list of test names on the
+# standard input, create the global log from their .trs and .log files.
+am__create_global_log = $(AWK) ' \
+function fatal(msg) \
+{ \
+ print "fatal: making $@: " msg | "cat >&2"; \
+ exit 1; \
+} \
+function rst_section(header) \
+{ \
+ print header; \
+ len = length(header); \
+ for (i = 1; i <= len; i = i + 1) \
+ printf "="; \
+ printf "\n\n"; \
+} \
+{ \
+ copy_in_global_log = 1; \
+ global_test_result = "RUN"; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".trs"); \
+ if (line ~ /$(am__global_test_result_rx)/) \
+ { \
+ sub("$(am__global_test_result_rx)", "", line); \
+ sub("[ ]*$$", "", line); \
+ global_test_result = line; \
+ } \
+ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
+ copy_in_global_log = 0; \
+ }; \
+ if (copy_in_global_log) \
+ { \
+ rst_section(global_test_result ": " $$0); \
+ while ((rc = (getline line < ($$0 ".log"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".log"); \
+ print line; \
+ }; \
+ printf "\n"; \
+ }; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# Restructured Text title.
+am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+# Solaris 10 'make', and several other traditional 'make' implementations,
+# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it
+# by disabling -e (using the XSI extension "set +e") if it's set.
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+# Default flags passed to test drivers.
+am__common_driver_flags = \
+ --color-tests "$$am__color_tests" \
+ --enable-hard-errors "$$am__enable_hard_errors" \
+ --expect-failure "$$am__expect_failure"
+# To be inserted before the command running the test. Creates the
+# directory for the log if needed. Stores in $dir the directory
+# containing $f, in $tst the test, in $log the log. Executes the
+# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# passes TESTS_ENVIRONMENT. Set up options for the wrapper that
+# will run the test scripts (or their associated LOG_COMPILER, if
+# thy have one).
+am__check_pre = \
+$(am__sh_e_setup); \
+$(am__vpath_adj_setup) $(am__vpath_adj) \
+$(am__tty_colors); \
+srcdir=$(srcdir); export srcdir; \
+case "$@" in \
+ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \
+ *) am__odir=.;; \
+esac; \
+test "x$$am__odir" = x"." || test -d "$$am__odir" \
+ || $(MKDIR_P) "$$am__odir" || exit $$?; \
+if test -f "./$$f"; then dir=./; \
+elif test -f "$$f"; then dir=; \
+else dir="$(srcdir)/"; fi; \
+tst=$$dir$$f; log='$@'; \
+if test -n '$(DISABLE_HARD_ERRORS)'; then \
+ am__enable_hard_errors=no; \
+else \
+ am__enable_hard_errors=yes; \
+fi; \
+case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \
+ am__expect_failure=yes;; \
+ *) \
+ am__expect_failure=no;; \
+esac; \
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+# A shell command to get the names of the tests scripts with any registered
+# extension removed (i.e., equivalently, the names of the test logs, with
+# the '.log' extension removed). The result is saved in the shell variable
+# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly,
+# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
+# since that might cause problem with VPATH rewrites for suffix-less tests.
+# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
+am__set_TESTS_bases = \
+ bases='$(TEST_LOGS)'; \
+ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+ bases=`echo $$bases`
+RECHECK_LOGS = $(TEST_LOGS)
+AM_RECURSIVE_TARGETS = check recheck
+TEST_SUITE_LOG = test-suite.log
+TEST_EXTENSIONS = @EXEEXT@ .test
+LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
+am__set_b = \
+ case '$@' in \
+ */*) \
+ case '$*' in \
+ */*) b='$*';; \
+ *) b=`echo '$@' | sed 's/\.log$$//'`; \
+ esac;; \
+ *) \
+ b='$*';; \
+ esac
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+TEST_LOGS = $(am__test_logs2:.test.log=.log)
+TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
+ $(TEST_LOG_FLAGS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMD_FS_OBJS = @AMD_FS_OBJS@
+AMD_INFO_OBJS = @AMD_INFO_OBJS@
+AMTAR = @AMTAR@
+AMU_AUTOFS_PROT_HEADER = @AMU_AUTOFS_PROT_HEADER@
+
+# allow users to add their own flags via "configure --enable-am-flags=ARG"
+AMU_CFLAGS = @AMU_CFLAGS@
+AMU_LIB_OBJS = @AMU_LIB_OBJS@
+AMU_NFS_PROT_HEADER = @AMU_NFS_PROT_HEADER@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+
+##############################################################################
+# must manually add f/lex library to LIBS, and not to LDADD.
+# f/lex libraries are incomatible with multiple scanners: don't include
+LIBS = @LIBS@ @WRAPLIB@
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+LIBTOOL_LDFLAGS = @LIBTOOL_LDFLAGS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+UNMOUNT_PROGRAM = @UNMOUNT_PROGRAM@
+VERSION = @VERSION@
+WRAPLIB = @WRAPLIB@
+YACC = @YACC@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+am_utils_unmount_args = @am_utils_unmount_args@
+am_utils_unmount_call = @am_utils_unmount_call@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+# no need for libaminfo to be yet another dynamic library
+noinst_LIBRARIES = libaminfo.a
+
+# man pages
+man_MANS = amd.8 sun2amd.8
+YLWRAP = $(top_srcdir)/ylwrap.amd
+
+# test scripts
+TESTS = test1.sh
+
+# headers this depends on, not to be installed
+noinst_HEADERS = amd.h sun_map.h
+
+# sources which get auto-built (from yacc/lex)
+BUILT_SOURCES = \
+ conf_parse.c conf_parse.h conf_tok.c \
+ sun_map_parse.c sun_map_parse.h sun_map_tok.c
+
+AM_YFLAGS = -d
+
+##############################################################################
+# *.y must be listed before *.l, because of a bug in automake-1.2
+# which will not generate the .h needs for the lex file from the yacc file.
+# I took out the conf .y/.l files b/c of bad interaction between bsd44 make
+# and automake-1.2 rules.
+libaminfo_a_SOURCES = \
+ sun_map_parse.y \
+ sun_map_tok.l \
+ sun_map.c
+
+
+# the complete list of all optional sources for libaminfo
+EXTRA_libaminfo_a_SOURCES = \
+ info_file.c \
+ info_exec.c \
+ info_hesiod.c \
+ info_ldap.c \
+ info_ndbm.c \
+ info_nis.c \
+ info_nisplus.c \
+ info_passwd.c \
+ info_sun.c \
+ info_union.c
+
+
+# AMD_INFO_OBJS: a list of info_*.o objects added, depending on which map
+# types this system supports.
+EXTRA_libaminfo_a_OBJECTS = @AMD_INFO_OBJS@
+libaminfo_a_LIBADD = @AMD_INFO_OBJS@
+libaminfo_a_DEPENDENCIES = @AMD_INFO_OBJS@
+
+##############################################################################
+# sources needed: note .y and .l files have to be first
+# get_args.c is handled separately
+amd_SOURCES = \
+ conf_parse.y \
+ conf_tok.l \
+ \
+ am_ops.c \
+ amd.c \
+ amfs_auto.c \
+ amfs_direct.c \
+ amfs_error.c \
+ amfs_generic.c \
+ amfs_host.c \
+ amfs_link.c \
+ amfs_linkx.c \
+ amfs_nfsl.c \
+ amfs_nfsx.c \
+ amfs_program.c \
+ amfs_root.c \
+ amfs_toplvl.c \
+ amfs_union.c \
+ amq_subr.c \
+ amq_svc.c \
+ autil.c \
+ clock.c \
+ conf.c \
+ map.c \
+ mapc.c \
+ mntfs.c \
+ nfs_prot_svc.c \
+ nfs_start.c \
+ nfs_subr.c \
+ opts.c \
+ readdir.c \
+ restart.c \
+ rpc_fwd.c \
+ sched.c \
+ srvr_amfs_auto.c \
+ srvr_nfs.c
+
+
+# the complete list of all optional sources for amd
+EXTRA_amd_SOURCES = \
+ ops_cachefs.c \
+ ops_cdfs.c \
+ ops_efs.c \
+ ops_ext.c \
+ ops_lofs.c \
+ ops_lustre.c \
+ ops_mfs.c \
+ ops_nfs.c \
+ ops_nfs3.c \
+ ops_nfs4.c \
+ ops_nullfs.c \
+ ops_pcfs.c \
+ ops_tfs.c \
+ ops_tmpfs.c \
+ ops_udf.c \
+ ops_ufs.c \
+ ops_umapfs.c \
+ ops_unionfs.c \
+ ops_xfs.c \
+ \
+ get_args.c
+
+
+# AMD_FS_OBJS: a list of ops_*.o objects added, depending on which
+# filesystem types this system supports.
+EXTRA_amd_OBJECTS = @AMD_FS_OBJS@
+amd_LDADD = $(EXTRA_amd_OBJECTS) get_args.o libaminfo.a ../libamu/libamu.la
+
+##############################################################################
+sun2amd_SOURCES = \
+ sun2amd.c
+
+sun2amd_LDADD = libaminfo.a ../libamu/libamu.la
+
+# additional files to distribute and clean
+EXTRA_DIST = ops_TEMPLATE.c $(man_MANS) $(TESTS)
+CLEANFILES = $(BUILT_SOURCES)
+DISTCLEANFILES = build_version.h ops_autofs.c
+AM_CPPFLAGS = -I$(top_srcdir)/include
+AM_CFLAGS = $(AMU_CFLAGS)
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .l .lo .log .o .obj .test .test$(EXEEXT) .trs .y
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu amd/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu amd/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+sun_map_parse.h: sun_map_parse.c
+ @if test ! -f $@; then rm -f sun_map_parse.c; else :; fi
+ @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) sun_map_parse.c; else :; fi
+
+libaminfo.a: $(libaminfo_a_OBJECTS) $(libaminfo_a_DEPENDENCIES) $(EXTRA_libaminfo_a_DEPENDENCIES)
+ $(AM_V_at)-rm -f libaminfo.a
+ $(AM_V_AR)$(libaminfo_a_AR) libaminfo.a $(libaminfo_a_OBJECTS) $(libaminfo_a_LIBADD)
+ $(AM_V_at)$(RANLIB) libaminfo.a
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-sbinPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(sbindir)" && rm -f $$files
+
+clean-sbinPROGRAMS:
+ @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+conf_parse.h: conf_parse.c
+ @if test ! -f $@; then rm -f conf_parse.c; else :; fi
+ @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) conf_parse.c; else :; fi
+
+amd$(EXEEXT): $(amd_OBJECTS) $(amd_DEPENDENCIES) $(EXTRA_amd_DEPENDENCIES)
+ @rm -f amd$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(amd_OBJECTS) $(amd_LDADD) $(LIBS)
+
+sun2amd$(EXEEXT): $(sun2amd_OBJECTS) $(sun2amd_DEPENDENCIES) $(EXTRA_sun2amd_DEPENDENCIES)
+ @rm -f sun2amd$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(sun2amd_OBJECTS) $(sun2amd_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/am_ops.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amfs_auto.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amfs_direct.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amfs_error.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amfs_generic.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amfs_host.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amfs_link.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amfs_linkx.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amfs_nfsl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amfs_nfsx.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amfs_program.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amfs_root.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amfs_toplvl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amfs_union.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amq_subr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amq_svc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/autil.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clock.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf_parse.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf_tok.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/get_args.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/info_exec.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/info_file.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/info_hesiod.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/info_ldap.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/info_ndbm.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/info_nis.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/info_nisplus.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/info_passwd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/info_sun.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/info_union.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mapc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mntfs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nfs_prot_svc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nfs_start.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nfs_subr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops_cachefs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops_cdfs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops_efs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops_ext.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops_lofs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops_lustre.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops_mfs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops_nfs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops_nfs3.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops_nfs4.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops_nullfs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops_pcfs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops_tfs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops_tmpfs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops_udf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops_ufs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops_umapfs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops_unionfs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops_xfs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opts.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readdir.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/restart.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpc_fwd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sched.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/srvr_amfs_auto.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/srvr_nfs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sun2amd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sun_map.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sun_map_parse.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sun_map_tok.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+.l.c:
+ $(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
+
+.y.c:
+ $(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h `echo $@ | $(am__yacc_c2h)` y.output $*.output -- $(YACCCOMPILE)
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-man8: $(man_MANS)
+ @$(NORMAL_INSTALL)
+ @list1=''; \
+ list2='$(man_MANS)'; \
+ test -n "$(man8dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.8[a-z]*$$/p'; \
+ fi; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man8:
+ @$(NORMAL_UNINSTALL)
+ @list=''; test -n "$(man8dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.8[a-z]*$$/p'; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+# Recover from deleted '.trs' file; this should ensure that
+# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
+# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells
+# to avoid problems with "make -n".
+.log.trs:
+ rm -f $< $@
+ $(MAKE) $(AM_MAKEFLAGS) $<
+
+# Leading 'am--fnord' is there to ensure the list of targets does not
+# expand to empty, as could happen e.g. with make check TESTS=''.
+am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
+am--force-recheck:
+ @:
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+ @$(am__set_TESTS_bases); \
+ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
+ redo_bases=`for i in $$bases; do \
+ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
+ done`; \
+ if test -n "$$redo_bases"; then \
+ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
+ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
+ if $(am__make_dryrun); then :; else \
+ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
+ fi; \
+ fi; \
+ if test -n "$$am__remaking_logs"; then \
+ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
+ "recursion detected" >&2; \
+ else \
+ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
+ fi; \
+ if $(am__make_dryrun); then :; else \
+ st=0; \
+ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
+ for i in $$redo_bases; do \
+ test -f $$i.trs && test -r $$i.trs \
+ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \
+ test -f $$i.log && test -r $$i.log \
+ || { echo "$$errmsg $$i.log" >&2; st=1; }; \
+ done; \
+ test $$st -eq 0 || exit 1; \
+ fi
+ @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+ ws='[ ]'; \
+ results=`for b in $$bases; do echo $$b.trs; done`; \
+ test -n "$$results" || results=/dev/null; \
+ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \
+ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \
+ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \
+ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \
+ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+ if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+ success=true; \
+ else \
+ success=false; \
+ fi; \
+ br='==================='; br=$$br$$br$$br$$br; \
+ result_count () \
+ { \
+ if test x"$$1" = x"--maybe-color"; then \
+ maybe_colorize=yes; \
+ elif test x"$$1" = x"--no-color"; then \
+ maybe_colorize=no; \
+ else \
+ echo "$@: invalid 'result_count' usage" >&2; exit 4; \
+ fi; \
+ shift; \
+ desc=$$1 count=$$2; \
+ if test $$maybe_colorize = yes && test $$count -gt 0; then \
+ color_start=$$3 color_end=$$std; \
+ else \
+ color_start= color_end=; \
+ fi; \
+ echo "$${color_start}# $$desc $$count$${color_end}"; \
+ }; \
+ create_testsuite_report () \
+ { \
+ result_count $$1 "TOTAL:" $$all "$$brg"; \
+ result_count $$1 "PASS: " $$pass "$$grn"; \
+ result_count $$1 "SKIP: " $$skip "$$blu"; \
+ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+ result_count $$1 "FAIL: " $$fail "$$red"; \
+ result_count $$1 "XPASS:" $$xpass "$$red"; \
+ result_count $$1 "ERROR:" $$error "$$mgn"; \
+ }; \
+ { \
+ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \
+ $(am__rst_title); \
+ create_testsuite_report --no-color; \
+ echo; \
+ echo ".. contents:: :depth: 2"; \
+ echo; \
+ for b in $$bases; do echo $$b; done \
+ | $(am__create_global_log); \
+ } >$(TEST_SUITE_LOG).tmp || exit 1; \
+ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \
+ if $$success; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \
+ fi; \
+ echo "$${col}$$br$${std}"; \
+ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \
+ echo "$${col}$$br$${std}"; \
+ create_testsuite_report --maybe-color; \
+ echo "$$col$$br$$std"; \
+ if $$success; then :; else \
+ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \
+ if test -n "$(PACKAGE_BUGREPORT)"; then \
+ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \
+ fi; \
+ echo "$$col$$br$$std"; \
+ fi; \
+ $$success || exit 1
+
+check-TESTS:
+ @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list
+ @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ trs_list=`for i in $$bases; do echo $$i.trs; done`; \
+ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
+ exit $$?;
+recheck: all
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ bases=`for i in $$bases; do echo $$i; done \
+ | $(am__list_recheck_tests)` || exit 1; \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ log_list=`echo $$log_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
+ am__force_recheck=am--force-recheck \
+ TEST_LOGS="$$log_list"; \
+ exit $$?
+test1.sh.log: test1.sh
+ @p='test1.sh'; \
+ b='test1.sh'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+.test.log:
+ @p='$<'; \
+ $(am__set_b); \
+ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+@am__EXEEXT_TRUE@.test$(EXEEXT).log:
+@am__EXEEXT_TRUE@ @p='$<'; \
+@am__EXEEXT_TRUE@ $(am__set_b); \
+@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \
+@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT)
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$(top_distdir)" distdir="$(distdir)" \
+ dist-hook
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(MANS) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+ -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+ -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
+ -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -rm -f conf_parse.c
+ -rm -f conf_parse.h
+ -rm -f conf_tok.c
+ -rm -f sun_map_parse.c
+ -rm -f sun_map_parse.h
+ -rm -f sun_map_tok.c
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \
+ clean-sbinPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-man
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-sbinPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man: install-man8
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-man uninstall-sbinPROGRAMS
+
+uninstall-man: uninstall-man8
+
+.MAKE: all check check-am install install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \
+ clean-generic clean-libtool clean-noinstLIBRARIES \
+ clean-sbinPROGRAMS cscopelist-am ctags ctags-am dist-hook \
+ distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-man8 install-pdf \
+ install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am recheck tags tags-am uninstall \
+ uninstall-am uninstall-man uninstall-man8 \
+ uninstall-sbinPROGRAMS
+
+
+# do not distribute files that should be generated by lex/yacc locally
+dist-hook:
+ (cd $(distdir) && rm -f $(BUILT_SOURCES))
+
+# dependencies
+$(PROGRAMS): $(LDADD)
+get_args.o: build_version.h
+$(amd_OBJECTS) $(EXTRA_amd_OBJECTS) $(sun2amd_OBJECTS) $(libaminfo_a_OBJECTS) $(EXTRA_libaminfo_a_OBJECTS): \
+ ../config.h \
+ ../aux_conf.h \
+ $(top_srcdir)/include/am_compat.h \
+ $(top_srcdir)/include/am_defs.h \
+ $(top_srcdir)/include/am_utils.h \
+ $(top_srcdir)/include/am_xdr_func.h \
+ $(top_srcdir)/include/amq_defs.h \
+ @AMU_NFS_PROT_HEADER@ \
+ @AMU_AUTOFS_PROT_HEADER@ \
+ $(noinst_HEADERS)
+
+# auto-generate build number
+build_version.h: $(amd_OBJECTS) $(EXTRA_amd_OBJECTS) $(libaminfo_a_OBJECTS) $(EXTRA_libaminfo_a_OBJECTS) get_args.c
+ $(top_srcdir)/m4/update_build_version
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/amd/am_ops.c b/amd/am_ops.c
index 5a5c33650eca..4d07dc807d90 100644
--- a/amd/am_ops.c
+++ b/amd/am_ops.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -96,6 +92,11 @@ static am_ops *vops[] =
#ifdef HAVE_FS_XFS
&xfs_ops, /* Unix (irix) F/S */
#endif /* HAVE_FS_XFS */
+#ifdef HAVE_FS_EXT
+ &ext2_ops, /* Unix (linux) F/S */
+ &ext3_ops, /* Unix (linux) F/S */
+ &ext4_ops, /* Unix (linux) F/S */
+#endif /* HAVE_FS_EXT */
#ifdef HAVE_FS_EFS
&efs_ops, /* Unix (irix) F/S */
#endif /* HAVE_FS_EFS */
@@ -111,6 +112,9 @@ static am_ops *vops[] =
#ifdef HAVE_FS_CACHEFS
&cachefs_ops, /* caching F/S */
#endif /* HAVE_FS_CACHEFS */
+#ifdef HAVE_FS_TMPFS
+ &tmpfs_ops, /* /tmp (in memory) F/S */
+#endif /* HAVE_FS_TMPFS */
#ifdef HAVE_FS_NULLFS
/* FILL IN */ /* null (loopback) F/S */
#endif /* HAVE_FS_NULLFS */
@@ -120,6 +124,12 @@ static am_ops *vops[] =
#ifdef HAVE_FS_UMAPFS
/* FILL IN */ /* uid/gid mapping F/S */
#endif /* HAVE_FS_UMAPFS */
+#ifdef HAVE_FS_UDF
+ &udf_ops, /* UDF F/S */
+#endif /* HAVE_FS_UDF */
+#ifdef HAVE_FS_LUSTRE
+ &lustre_ops, /* Lustre */
+#endif /* HAVE_FS_LUSTRE */
/*
* These 4 should be last, in the order:
@@ -316,7 +326,7 @@ merge_opts(const char *opts1, const char *opts2)
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 */
+ char *s1 = xstrdup(opts1); /* copy of opts1 to munge */
/* initialization */
mnt2.mnt_opts = (char *) opts2;
@@ -327,13 +337,13 @@ merge_opts(const char *opts1, const char *opts2)
tmpstr;
tmpstr = strtok(NULL, ",")) {
/* copy option to temp buffer */
- xstrlcpy(oneopt, tmpstr, 80);
+ xstrlcpy(oneopt, tmpstr, sizeof(oneopt));
/* if option has a value such as rsize=1024, chop the value part */
- if ((eq = haseq(oneopt)))
+ if ((eq = strchr(oneopt, '=')))
*eq = '\0';
/* find reverse option of oneopt */
revoneopt = reverse_option(oneopt);
- /* if option orits reverse exist in opts2, ignore it */
+ /* if option or its reverse exist in opts2, ignore it */
if (amu_hasmntopt(&mnt2, oneopt) || amu_hasmntopt(&mnt2, revoneopt))
continue;
/* add option to returned string */
@@ -362,7 +372,7 @@ am_ops *
ops_search(char *type)
{
am_ops **vp;
- am_ops *rop = 0;
+ am_ops *rop = NULL;
for (vp = vops; (rop = *vp); vp++)
if (STREQ(rop->fs_type, type))
break;
@@ -373,7 +383,7 @@ ops_search(char *type)
am_ops *
ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map)
{
- am_ops *rop = 0;
+ am_ops *rop = NULL;
char *link_dir;
/*
@@ -400,7 +410,7 @@ ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map
* Otherwise skip past any leading '-'.
*/
if (fo->opt_opts == 0)
- fo->opt_opts = strdup("rw,defaults");
+ fo->opt_opts = xstrdup("rw,defaults");
else if (*fo->opt_opts == '-') {
/*
* We cannot simply do fo->opt_opts++ here since the opts
@@ -408,7 +418,7 @@ ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map
* So just reallocate the thing -- stolcke 11/11/94
*/
char *old = fo->opt_opts;
- fo->opt_opts = strdup(old + 1);
+ fo->opt_opts = xstrdup(old + 1);
XFREE(old);
}
@@ -426,7 +436,7 @@ ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map
XFREE(fo->opt_opts);
XFREE(fo->opt_remopts);
fo->opt_opts = mergedstr;
- fo->opt_remopts = strdup(mergedstr);
+ fo->opt_remopts = xstrdup(mergedstr);
} else {
char *mergedstr, *remmergedstr;
mergedstr = merge_opts(fo->opt_opts, fo->opt_addopts);
@@ -451,7 +461,7 @@ ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map
/* 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);
+ link_dir = str3cat((char *) NULL, fo->opt_fs, "/", link_dir);
normalize_slash(link_dir);
XFREE(fo->opt_sublink);
fo->opt_sublink = link_dir;
@@ -460,8 +470,7 @@ ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map
/*
* Check the filesystem is happy
*/
- if (fo->fs_mtab)
- XFREE(fo->fs_mtab);
+ XFREE(fo->fs_mtab);
fo->fs_mtab = rop->fs_match(fo);
if (fo->fs_mtab)
diff --git a/amd/amd.8 b/amd/amd.8
index 565a5505b8c2..0440c7b8d463 100644
--- a/amd/amd.8
+++ b/amd/amd.8
@@ -1,5 +1,5 @@
.\"
-.\" Copyright (c) 1997-2006 Erez Zadok
+.\" Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
.\" 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
+.\" 3. 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.
.\"
@@ -36,9 +32,8 @@
.\" 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 $
+.\" File: am-utils/amd/amd.8
.\"
.TH AMD 8 "3 November 1989"
.SH NAME
@@ -237,7 +232,8 @@ 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.
+list chosen from: fatal, error, user, warn, info, map, stats, defaults, and
+all. Note that "fatal" and "error" are mandatory and cannot be turned off.
.TP
.BI \-y " domain"
@@ -340,15 +336,15 @@ number of process context switches.
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 syslog (3).
+.BR amd.conf (5),
+.BR mtab (5),
.BR automount (8),
.BR mount (8),
.BR umount (8),
-.BR mtab (5),
-.BR syslog (3).
.LP
``am-utils''
.BR info (1)
diff --git a/amd/amd.c b/amd/amd.c
index 37eab5d8442c..d06b713c0e21 100644
--- a/amd/amd.c
+++ b/amd/amd.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -375,7 +371,7 @@ do_memory_locking(void)
#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 */
+ madvise(NULL, 0, MADV_PROTECT); /* may be redundant of the above worked out */
#endif /* defined(HAVE_MADVISE) && defined(MADV_PROTECT) */
}
@@ -427,6 +423,7 @@ main(int argc, char *argv[])
if (gethostname(hostname, sizeof(hostname)) < 0) {
plog(XLOG_FATAL, "gethostname: %m");
going_down(1);
+ return 1;
}
hostname[sizeof(hostname) - 1] = '\0';
@@ -436,6 +433,7 @@ main(int argc, char *argv[])
if (!*hostname) {
plog(XLOG_FATAL, "host name is not set");
going_down(1);
+ return 1;
}
/*
@@ -494,7 +492,8 @@ main(int argc, char *argv[])
getwire(&PrimNetName, &PrimNetNum);
/*
- * Determine command-line arguments
+ * Determine command-line arguments.
+ * (Also initialize amd.conf parameters, maps, and more.)
*/
get_args(argc, argv);
@@ -528,6 +527,7 @@ main(int argc, char *argv[])
if (geteuid() != 0) {
plog(XLOG_FATAL, "Must be root to mount filesystems (euid = %ld)", (long) geteuid());
going_down(1);
+ return 1;
}
#ifdef HAVE_MAP_NIS
@@ -539,10 +539,11 @@ main(int argc, char *argv[])
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);
+ return 1;
}
#endif /* HAVE_MAP_NIS */
- if (!amuDebug(D_DAEMON))
+ if (amuDebug(D_DAEMON))
ppid = daemon_mode();
/*
diff --git a/amd/amd.h b/amd/amd.h
index 0e371b72a5b0..f66f5b75169f 100644
--- a/amd/amd.h
+++ b/amd/amd.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -54,9 +50,12 @@
* that support mtab on file.
*/
#ifdef MOUNT_TABLE_ON_FILE
-# define DEBUG_MNTTAB_FILE "/tmp/mnttab"
+# define DEBUG_MNTTAB_FILE "/tmp/mtab"
#endif /* MOUNT_TABLE_ON_FILE */
+/* Max line length that info services can handle */
+#define INFO_MAX_LINE_LEN 1500
+
/* options for amd.conf */
#define CFM_BROWSABLE_DIRS 0x00000001
#define CFM_MOUNT_TYPE_AUTOFS 0x00000002 /* use kernel autofs support */
@@ -76,10 +75,7 @@
#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 */
@@ -212,6 +208,7 @@ typedef struct cf_map cf_map_t;
typedef struct kv kv;
typedef struct am_node am_node;
typedef struct mntfs mntfs;
+typedef struct am_loc am_loc;
typedef struct am_opts am_opts;
typedef struct am_ops am_ops;
typedef struct am_stats am_stats;
@@ -245,13 +242,17 @@ 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 int (*vreaddir) (am_node *, voidp, voidp, voidp, 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 *);
+/*
+ * NFS progran dispatcher
+ */
+typedef void (*dispatcher_t)(struct svc_req *rqstp, SVCXPRT *transp);
/*
@@ -314,6 +315,7 @@ struct amu_global_options {
#endif /* HAVE_MAP_NIS */
char *nfs_proto; /* NFS protocol (NULL, udp, tcp) */
int nfs_vers; /* NFS version (0, 2, 3, 4) */
+ int nfs_vers_ping; /* NFS rpc ping version (0, 2, 3, 4) */
u_int exec_map_timeout; /* timeout (seconds) for executable maps */
};
@@ -349,6 +351,7 @@ struct mnt_map {
short alloc; /* Allocation mode */
time_t modify; /* Modify time of map */
u_int reloads; /* Number of times map was reloaded */
+ u_int nentries; /* Number of entries in the map */
char *map_name; /* Name of this map */
char *wildcard; /* Wildcard value */
reload_fn *reload; /* Function to be used for reloads */
@@ -420,7 +423,7 @@ struct mntfs {
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_auto; /* Mount info */
char *mf_mopts; /* FS mount opts */
char *mf_remopts; /* Remote FS mount opts */
char *mf_loopdev; /* loop device name for /dev/loop mounts */
@@ -435,6 +438,16 @@ struct mntfs {
};
/*
+ * Locations: bindings between keys and mntfs
+ */
+struct am_loc {
+ am_opts *al_fo;
+ mntfs *al_mnt;
+ int al_refc;
+};
+
+
+/*
* List of fileservers
*/
struct fserver {
@@ -463,6 +476,8 @@ struct am_stats {
int s_readdir; /* Count of readdirs */
int s_readlink; /* Count of readlinks */
int s_statfs; /* Count of statfs */
+ int s_fsinfo; /* Count of fsinfo */
+ int s_pathconf; /* Count of pathconf */
};
/*
@@ -482,8 +497,8 @@ extern struct amd_stats amd_stats;
*/
struct am_node {
int am_mapno; /* Map number */
- mntfs *am_mnt; /* Mounted filesystem */
- mntfs **am_mfarray; /* Filesystem sources to try to mount */
+ am_loc *am_al; /* Mounted filesystem */
+ am_loc **am_alarray; /* 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 */
@@ -508,6 +523,7 @@ struct am_node {
autofs_fh_t *am_autofs_fh;
time_t am_autofs_ttl; /* Time to expire autofs nodes */
#endif /* HAVE_FS_AUTOFS */
+ int am_fd[2]; /* parent child pipe fd's for sync umount */
};
/*
@@ -527,13 +543,18 @@ 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);
+extern int *amqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp);
+extern int *amqproc_sync_umnt_1_svc_parent(voidp argp, struct svc_req *rqstp);
+extern amq_sync_umnt *amqproc_sync_umnt_1_svc_child(voidp argp, struct svc_req *rqstp);
+extern amq_sync_umnt *amqproc_sync_umnt_1_svc_async(voidp argp, struct svc_req *rqstp);
+extern amq_map_info_list *amqproc_getmapinfo_1_svc(voidp argp, struct svc_req *rqstp);
/* other external definitions */
-extern am_nfs_fh *get_root_nfs_fh(char *dir);
+extern am_nfs_handle_t *get_root_nfs_fh(char *dir, am_nfs_handle_t *nfh);
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 bool_t xdr_amq_map_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);
@@ -541,7 +562,8 @@ 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 int conf_parse(void); /* "yyparse" renamed */
+extern FILE *conf_in; /* "yyin" renamed */
extern void amfs_mkcacheref(mntfs *mf);
extern int amfs_mount(am_node *mp, mntfs *mf, char *opts);
@@ -566,12 +588,15 @@ extern int get_mountd_port(fserver *, u_short *, wchan_t);
extern void flush_nfs_fhandle_cache(fserver *);
extern mntfs *dup_mntfs(mntfs *);
+extern am_loc *dup_loc(am_loc *);
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 am_loc *new_loc(void);
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 free_loc(voidp);
extern void amq_program_1(struct svc_req *rqstp, SVCXPRT *transp);
@@ -579,9 +604,11 @@ 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 int file_read_line(char *, int, FILE *);
extern void forcibly_timeout_mp(am_node *);
extern void free_map(am_node *);
extern void free_opts(am_opts *);
+extern am_opts *copy_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 *);
@@ -596,7 +623,7 @@ 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 mnt_map *mapc_find(char *, char *, const char *, const char *);
extern void mapc_free(opaque_t);
extern int mapc_keyiter(mnt_map *, key_fun, opaque_t);
extern void mapc_reload(void);
@@ -608,9 +635,11 @@ 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 mp_to_fh3(am_node *mp, am_nfs_fh3 *fhp);
extern void new_ttl(am_node *);
extern void nfs_quick_reply(am_node *mp, int error);
extern void normalize_slash(char *);
+extern void notify_child(am_node *, au_etype, int, int);
extern void ops_showamfstypes(char *buf, size_t l);
extern void ops_showfstypes(char *outbuf, size_t l);
extern void rem_que(qelem *);
@@ -639,8 +668,8 @@ extern char hostd[SIZEOF_HOSTD]; /* Host+domain */
/*
* Global variables.
*/
-extern FILE *yyin;
extern SVCXPRT *current_transp; /* For nfs_quick_reply() */
+extern dispatcher_t nfs_dispatcher;
extern char *conf_tag;
#define SIZEOF_UID_STR 12
#define SIZEOF_GID_STR 12
@@ -724,6 +753,19 @@ extern am_ops pcfs_ops;
#endif /* HAVE_FS_PCFS */
/*
+ * UDF File System
+ * Many systems can't support this, and in any case most of the
+ * functionality is available with program FS.
+ */
+#ifdef HAVE_FS_UDF
+extern am_ops udf_ops;
+#endif /* HAVE_FS_UDF */
+
+#ifdef HAVE_FS_LUSTRE
+extern am_ops lustre_ops;
+#endif /* HAVE_FS_LUSTRE */
+
+/*
* Caching File System (Solaris)
*/
#ifdef HAVE_FS_CACHEFS
@@ -731,6 +773,12 @@ extern am_ops cachefs_ops;
#endif /* HAVE_FS_CACHEFS */
/*
+ * In memory /tmp filesystem (Linux, NetBSD)
+ */
+#ifdef HAVE_FS_TMPFS
+extern am_ops tmpfs_ops;
+#endif /* HAVE_FS_TMPFS */
+/*
* Network File System
* Good, slow, NFS V.2.
*/
@@ -753,6 +801,13 @@ extern am_ops ufs_ops; /* Un*x file system */
extern am_ops xfs_ops; /* Un*x file system */
#endif /* HAVE_FS_XFS */
+/* Unix file system (ext*) */
+#ifdef HAVE_FS_EXT
+extern am_ops ext2_ops; /* Un*x file system */
+extern am_ops ext3_ops; /* Un*x file system */
+extern am_ops ext4_ops; /* Un*x file system */
+#endif /* HAVE_FS_EXT */
+
/* Unix file system (irix) */
#ifdef HAVE_FS_EFS
extern am_ops efs_ops; /* Un*x file system */
@@ -772,7 +827,7 @@ extern am_ops amfs_root_ops; /* Root file system */
*/
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_readdir(am_node *mp, voidp cookie, voidp dp, voidp 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);
@@ -808,7 +863,8 @@ extern am_ops amfs_direct_ops; /* Direct Automount file system (this too) */
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);
+extern int amfs_error_readdir(am_node *mp, voidp cookie, voidp dp, voidp ep, u_int count);
+
#endif /* HAVE_AMU_FS_ERROR */
/*
diff --git a/amd/amfs_auto.c b/amd/amfs_auto.c
index 75a451fd111d..34fdb00f501c 100644
--- a/amd/amfs_auto.c
+++ b/amd/amfs_auto.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -101,6 +97,8 @@ am_ops amfs_auto_ops =
static int
amfs_auto_mount(am_node *mp, mntfs *mf)
{
+ if (mp->am_parent == NULL)
+ return EINVAL;
/*
* Pseudo-directories are used to provide some structure
* to the automounted directories instead
@@ -115,7 +113,7 @@ amfs_auto_mount(am_node *mp, mntfs *mf)
* 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);
+ mf->mf_info = strealloc(mf->mf_info, mp->am_parent->am_al->al_mnt->mf_info);
/*
* Compute prefix:
@@ -131,12 +129,12 @@ amfs_auto_mount(am_node *mp, mntfs *mf)
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("");
+ mp->am_pref = xstrdup("");
} else {
/*
* the prefix specified as an option
*/
- mp->am_pref = strdup(mf->mf_fo->opt_pref);
+ mp->am_pref = xstrdup(mf->mf_fo->opt_pref);
}
} else {
/*
@@ -147,7 +145,7 @@ amfs_auto_mount(am_node *mp, mntfs *mf)
char *ppref = mp->am_parent->am_pref;
if (ppref == 0)
ppref = "";
- mp->am_pref = str3cat((char *) 0, ppref, mp->am_name, "/");
+ mp->am_pref = str3cat((char *) NULL, ppref, mp->am_name, "/");
}
#ifdef HAVE_FS_AUTOFS
diff --git a/amd/amfs_direct.c b/amd/amfs_direct.c
index dbef743d0d7e..b911c2a1e2ce 100644
--- a/amd/amfs_direct.c
+++ b/amd/amfs_direct.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -93,8 +89,8 @@ amfs_direct_readlink(am_node *mp, int *error_return)
xp = next_nonerror_node(mp->am_child);
if (!xp) {
- if (!mp->am_mnt->mf_private)
- amfs_mkcacheref(mp->am_mnt); /* XXX */
+ if (!mp->am_al->al_mnt->mf_private)
+ amfs_mkcacheref(mp->am_al->al_mnt);
xp = amfs_generic_lookup_child(mp, mp->am_path + 1, &rc, VLOOK_CREATE);
if (xp && rc < 0)
xp = amfs_generic_mount_child(xp, &rc);
diff --git a/amd/amfs_error.c b/amd/amfs_error.c
index 51bdaa6db14d..58a623102c1e 100644
--- a/amd/amfs_error.c
+++ b/amd/amfs_error.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -92,7 +88,7 @@ am_ops amfs_error_ops =
static char *
amfs_error_match(am_opts *fo)
{
- return strdup("(error-hook)");
+ return xstrdup("(error-hook)");
}
@@ -145,7 +141,7 @@ amfs_error_mount_child(am_node *ap, int *error_return)
* If we do then just give an error.
*/
int
-amfs_error_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count)
+amfs_error_readdir(am_node *mp, voidp cookie, voidp dp, voidp ep, u_int count)
{
return ESTALE;
}
diff --git a/amd/amfs_generic.c b/amd/amfs_generic.c
index 0d5996969cf8..25d734bbde00 100644
--- a/amd/amfs_generic.c
+++ b/amd/amfs_generic.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -55,7 +51,7 @@
/****************************************************************************
*** MACROS ***
****************************************************************************/
-#define IN_PROGRESS(cp) ((cp)->mp->am_mnt->mf_flags & MFF_MOUNTING)
+#define IN_PROGRESS(cp) ((cp)->mp->am_al->al_mnt->mf_flags & MFF_MOUNTING)
/****************************************************************************
@@ -80,7 +76,7 @@ struct continuation {
int retry; /* Try again? */
time_t start; /* Time we started this mount */
int callout; /* Callout identifier */
- mntfs **mf; /* Current mntfs */
+ am_loc **al; /* Current location */
};
@@ -88,9 +84,9 @@ struct continuation {
*** 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,
+static am_loc *amfs_lookup_one_location(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 am_loc **amfs_lookup_loc(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);
@@ -108,7 +104,7 @@ amfs_lookup_node(am_node *mp, char *fname, int *error_return)
int error = 0; /* Error so far */
int in_progress = 0; /* # of (un)mount in progress */
mntfs *mf;
- char *expanded_fname = 0;
+ char *expanded_fname = NULL;
dlog("in amfs_lookup_node");
@@ -118,7 +114,7 @@ amfs_lookup_node(am_node *mp, char *fname, int *error_return)
* about the mount point.
*/
if (amd_state == Finishing) {
- if (mp->am_mnt == 0 || mp->am_mnt->mf_fsflags & FS_DIRECT) {
+ if (mp->am_al == NULL || mp->am_al->al_mnt == NULL || mp->am_al->al_mnt->mf_fsflags & FS_DIRECT) {
dlog("%s mount ignored - going down", fname);
} else {
dlog("%s/%s mount ignored - going down", mp->am_path, fname);
@@ -170,7 +166,7 @@ amfs_lookup_node(am_node *mp, char *fname, int *error_return)
* If the error code is undefined then it must be
* in progress.
*/
- mf = new_mp->am_mnt;
+ mf = new_mp->am_al->al_mnt;
if (mf->mf_error < 0)
goto in_progrss;
@@ -240,7 +236,7 @@ amfs_lookup_node(am_node *mp, char *fname, int *error_return)
*/
new_mp = get_ap_child(mp, expanded_fname);
XFREE(expanded_fname);
- if (new_mp == 0)
+ if (new_mp == NULL)
ereturn(ENOSPC);
*error_return = -1;
@@ -249,19 +245,25 @@ 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 am_loc *
+amfs_lookup_one_location(am_node *new_mp, mntfs *mf, char *ivec,
+ char *def_opts, char *pfname)
{
am_ops *p;
am_opts *fs_opts;
+ am_loc *new_al;
mntfs *new_mf;
- char *mp_dir = 0;
+ char *mp_dir = NULL;
#ifdef HAVE_FS_AUTOFS
int on_autofs = 1;
#endif /* HAVE_FS_AUTOFS */
/* match the operators */
+ /*
+ * although we alloc the fs_opts here, the pointer is 'owned' by the am_loc and will
+ * be free'd on destruction of the am_loc. If we don't allocate a loc, then we need
+ * to free this.
+ */
fs_opts = CALLOC(am_opts);
p = ops_match(fs_opts, ivec, def_opts, new_mp->am_path,
pfname, mf->mf_info);
@@ -269,7 +271,7 @@ amfs_lookup_one_mntfs(am_node *new_mp, mntfs *mf, char *ivec,
/* 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) {
+ if (fs_opts->opt_sublink && fs_opts->opt_sublink[0]) {
/*
* For sublinks we need to use a hack with autofs:
* mount the filesystem on the original opt_fs (which is NOT an
@@ -292,6 +294,9 @@ amfs_lookup_one_mntfs(am_node *new_mp, mntfs *mf, char *ivec,
/*
* Find or allocate a filesystem for this node.
+ * we search for a matching backend share, since
+ * we will construct our own al_loc to handle
+ * any customisations for this usage.
*/
new_mf = find_mntfs(p, fs_opts,
mp_dir,
@@ -300,6 +305,7 @@ amfs_lookup_one_mntfs(am_node *new_mp, mntfs *mf, char *ivec,
fs_opts->opt_opts,
fs_opts->opt_remopts);
+
/*
* See whether this is a real filesystem
*/
@@ -307,10 +313,16 @@ amfs_lookup_one_mntfs(am_node *new_mp, mntfs *mf, char *ivec,
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);
+ free_opts(fs_opts);
+ XFREE(fs_opts);
return NULL;
}
dlog("Got a hit with %s", p->fs_type);
+ new_al = new_loc();
+ free_mntfs(new_al->al_mnt);
+ new_al->al_mnt = new_mf;
+ new_al->al_fo = fs_opts; /* now the loc is in charge of free'ing this mem */
#ifdef HAVE_FS_AUTOFS
if (new_mp->am_flags & AMF_AUTOFS && on_autofs) {
@@ -332,12 +344,12 @@ amfs_lookup_one_mntfs(am_node *new_mp, mntfs *mf, char *ivec,
new_mf->mf_flags |= MFF_IS_AUTOFS;
#endif /* HAVE_FS_AUTOFS */
- return new_mf;
+ return new_al;
}
-static mntfs **
-amfs_lookup_mntfs(am_node *new_mp, int *error_return)
+static am_loc **
+amfs_lookup_loc(am_node *new_mp, int *error_return)
{
am_node *mp;
char *info; /* Mount info - where to get the file system */
@@ -348,10 +360,11 @@ amfs_lookup_mntfs(am_node *new_mp, int *error_return)
int error = 0; /* Error so far */
char path_name[MAXPATHLEN]; /* General path name buffer */
char *pfname; /* Path for database lookup */
- mntfs *mf, **mf_array;
+ mntfs* mf; /* The mntfs for the map of our parent */
+ am_loc **al_array; /* the generated list of locations */
int count;
- dlog("in amfs_lookup_mntfs");
+ dlog("in amfs_lookup_loc");
mp = new_mp->am_parent;
@@ -369,7 +382,7 @@ amfs_lookup_mntfs(am_node *new_mp, int *error_return)
pfname = new_mp->am_name;
}
- mf = mp->am_mnt;
+ mf = mp->am_al->al_mnt;
dlog("will search map info in %s to find %s", mf->mf_info, pfname);
/*
@@ -404,8 +417,8 @@ amfs_lookup_mntfs(am_node *new_mp, int *error_return)
else
def_opts = "";
- orig_def_opts = amfs_parse_defaults(mp, mf, strdup(def_opts));
- def_opts = strdup(orig_def_opts);
+ orig_def_opts = amfs_parse_defaults(mp, mf, xstrdup(def_opts));
+ def_opts = xstrdup(orig_def_opts);
/* first build our defaults */
num_ivecs = 0;
@@ -423,11 +436,11 @@ amfs_lookup_mntfs(am_node *new_mp, int *error_return)
num_ivecs++;
}
- mf_array = calloc(num_ivecs + 1, sizeof(mntfs *));
+ al_array = calloc(num_ivecs + 1, sizeof(am_loc *));
- /* construct the array of struct mntfs for this mount point */
+ /* construct the array of struct locations for this key */
for (count = 0, cur_ivec = ivecs; *cur_ivec; cur_ivec++) {
- mntfs *new_mf;
+ am_loc *new_al;
if (**cur_ivec == '-') {
XFREE(def_opts);
@@ -436,18 +449,18 @@ amfs_lookup_mntfs(am_node *new_mp, int *error_return)
* If we have a single dash '-' than we need to reset the
* default options.
*/
- def_opts = strdup(orig_def_opts);
+ def_opts = xstrdup(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);
+ def_opts = str3cat((char *) NULL, 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
+ * If a loc 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 "||".
@@ -455,16 +468,16 @@ amfs_lookup_mntfs(am_node *new_mp, int *error_return)
*/
if (STREQ(*cur_ivec, "/") || STREQ(*cur_ivec, "||")) {
if (count > 0) {
- dlog("Cut: not trying any more locations for %s", mp->am_path);
+ dlog("Cut: not trying any more locations for %s", pfname);
break;
}
continue;
}
- new_mf = amfs_lookup_one_mntfs(new_mp, mf, *cur_ivec, def_opts, pfname);
- if (new_mf == NULL)
+ new_al = amfs_lookup_one_location(new_mp, mf, *cur_ivec, def_opts, pfname);
+ if (new_al == NULL)
continue;
- mf_array[count++] = new_mf;
+ al_array[count++] = new_al;
}
/* We're done with ivecs */
@@ -473,11 +486,11 @@ amfs_lookup_mntfs(am_node *new_mp, int *error_return)
XFREE(orig_def_opts);
XFREE(def_opts);
if (count == 0) { /* no match */
- XFREE(mf_array);
+ XFREE(al_array);
ereturn(ENOENT);
}
- return mf_array;
+ return al_array;
}
@@ -491,7 +504,7 @@ 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;
+ mntfs *mf = mp->am_al->al_mnt;
dlog("amfs_cont: '%s'", mp->am_path);
@@ -556,7 +569,7 @@ amfs_cont(int rc, int term, opaque_t arg)
mf->mf_error = rc;
mf->mf_flags |= MFF_ERROR;
errno = rc; /* XXX */
- if (!STREQ(mp->am_mnt->mf_ops->fs_type, "linkx"))
+ if (!STREQ(mp->am_al->al_mnt->mf_ops->fs_type, "linkx"))
plog(XLOG_ERROR, "%s: mount (amfs_cont): %m", mp->am_path);
}
}
@@ -568,7 +581,7 @@ amfs_cont(int rc, int term, opaque_t arg)
* call the background mount routine again
*/
amd_stats.d_merr++;
- cp->mf++;
+ cp->al++;
}
amfs_bgmount(cp);
if (mp->am_error > 0)
@@ -608,13 +621,21 @@ amfs_retry(int rc, int term, opaque_t arg)
*/
plog(XLOG_INFO, "mount of \"%s\" has timed out", mp->am_path);
error = ETIMEDOUT;
- while (*cp->mf)
- cp->mf++;
+ while (*cp->al)
+ cp->al++;
/* explicitly forbid further retries after timeout */
cp->retry = FALSE;
}
if (error || !IN_PROGRESS(cp))
error = amfs_bgmount(cp);
+ else
+ /* Normally it's amfs_bgmount() which frees the continuation. However, if
+ * the mount is already in progress and we're in amfs_retry() for another
+ * node we don't try mounting the filesystem once again. Still, we have
+ * to free the continuation as we won't get called again and thus would
+ * leak the continuation structure and our am_loc references.
+ */
+ free_continuation(cp);
reschedule_timeout_mp();
}
@@ -626,7 +647,7 @@ amfs_retry(int rc, int term, opaque_t arg)
static void
free_continuation(struct continuation *cp)
{
- mntfs **mfp;
+ am_loc **alp;
dlog("free_continuation");
if (cp->callout)
@@ -634,13 +655,12 @@ free_continuation(struct continuation *cp)
/*
* 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);
+ for (alp = cp->mp->am_alarray; *alp; alp++) {
+ free_loc(*alp);
}
- XFREE(cp->mp->am_mfarray);
- cp->mp->am_mfarray = 0;
+ XFREE(cp->mp->am_alarray);
+ cp->mp->am_alarray = 0;
XFREE(cp);
}
@@ -690,12 +710,13 @@ static int
amfs_bgmount(struct continuation *cp)
{
am_node *mp = cp->mp;
- mntfs *mf; /* Current mntfs */
+ am_loc *loc;
+ mntfs *mf;
int this_error = -1; /* Per-mount error */
int hard_error = -1; /* Cumulative per-node error */
- if (mp->am_mnt)
- free_mntfs(mp->am_mnt);
+ if (mp->am_al)
+ free_loc(mp->am_al);
/*
* Try to mount each location.
@@ -704,10 +725,11 @@ amfs_bgmount(struct continuation *cp)
* 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) {
+ for (mp->am_al = *cp->al; *cp->al; cp->al++, mp->am_al = *cp->al) {
am_ops *p;
- mf = dup_mntfs(mp->am_mnt);
+ loc = dup_loc(mp->am_al);
+ mf = loc->al_mnt;
p = mf->mf_ops;
if (hard_error < 0)
@@ -737,12 +759,11 @@ amfs_bgmount(struct continuation *cp)
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);
+ XFREE(mp->am_link);
+ mp->am_link = NULL;
+
+ if (loc->al_fo && loc->al_fo->opt_sublink && loc->al_fo->opt_sublink[0])
+ mp->am_link = xstrdup(loc->al_fo->opt_sublink);
/*
* Will usually need to play around with the mount nodes
@@ -784,13 +805,13 @@ amfs_bgmount(struct continuation *cp)
if (this_error < 0)
goto retry;
- if (mf->mf_fo && mf->mf_fo->opt_delay) {
+ if (loc->al_fo && loc->al_fo->opt_delay) {
/*
- * If there is a delay timer on the mount
+ * If there is a delay timer on the location
* then don't try to mount if the timer
* has not expired.
*/
- int i = atoi(mf->mf_fo->opt_delay);
+ int i = atoi(loc->al_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));
@@ -866,22 +887,25 @@ amfs_bgmount(struct continuation *cp)
return -1;
failed:
- amd_stats.d_merr++;
- mf->mf_error = this_error;
- mf->mf_flags |= MFF_ERROR;
+ if (!FSRV_ISDOWN(mf->mf_server)) {
+ /* mark the mount as failed unless the server is down */
+ 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);
+ 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;
+ 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);
+ free_loc(loc);
/* continue */
}
@@ -890,7 +914,10 @@ amfs_bgmount(struct continuation *cp)
* there is no more mount information available.
*/
if (this_error) {
- mp->am_mnt = mf = new_mntfs();
+ if (mp->am_al)
+ free_loc(mp->am_al);
+ mp->am_al = loc = new_loc();
+ mf = loc->al_mnt;
#ifdef HAVE_FS_AUTOFS
if (mp->am_flags & AMF_AUTOFS)
@@ -920,7 +947,7 @@ amfs_bgmount(struct continuation *cp)
}
new_ttl(mp);
} else {
- mf = mp->am_mnt;
+ mf = loc->al_mnt;
/*
* Wakeup anything waiting for this mount
*/
@@ -959,19 +986,10 @@ amfs_parse_defaults(am_node *mp, mntfs *mf, char *def_opts)
/*
* 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);
+ dflts = xstrdup(mm->cfm->cfm_defaults);
} else if (mapc_search(mm, "/defaults", &dflts) == 0) {
dlog("/defaults gave %s", dflts);
} else {
@@ -1009,7 +1027,7 @@ amfs_parse_defaults(am_node *mp, mntfs *mf, char *def_opts)
* get expanded to "/defaults"
*/
pt = ops_match(&ap, *sp, "", mp->am_path, "/defaults",
- mp->am_parent->am_mnt->mf_info);
+ mp->am_parent->am_al->al_mnt->mf_info);
free_opts(&ap); /* don't leak */
if (pt == &amfs_error_ops) {
plog(XLOG_MAP, "did not match defaults for \"%s\"", *sp);
@@ -1076,8 +1094,9 @@ amfs_generic_mount_child(am_node *new_mp, int *error_return)
*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;
+ if (new_mp->am_al)
+ free_loc(new_mp->am_al);
+ new_mp->am_al = NULL;
/*
* Construct a continuation
@@ -1087,7 +1106,7 @@ amfs_generic_mount_child(am_node *new_mp, int *error_return)
cp->mp = new_mp;
cp->retry = TRUE;
cp->start = clocktime(NULL);
- cp->mf = new_mp->am_mfarray;
+ cp->al = new_mp->am_alarray;
/*
* Try and mount the file system. If this succeeds immediately (possible
@@ -1101,7 +1120,7 @@ amfs_generic_mount_child(am_node *new_mp, int *error_return)
/*
* 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
+ * transp that's been passed down from nfs_dispatcher() 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
@@ -1113,7 +1132,8 @@ amfs_generic_mount_child(am_node *new_mp, int *error_return)
new_mp->am_transp = (SVCXPRT *) xmalloc(sizeof(SVCXPRT));
*(new_mp->am_transp) = *current_transp;
}
- if (error && new_mp->am_mnt && (new_mp->am_mnt->mf_ops == &amfs_error_ops))
+ if (error && new_mp->am_al && new_mp->am_al->al_mnt &&
+ (new_mp->am_al->al_mnt->mf_ops == &amfs_error_ops))
new_mp->am_error = error;
if (new_mp->am_error > 0)
@@ -1132,7 +1152,7 @@ am_node *
amfs_generic_lookup_child(am_node *mp, char *fname, int *error_return, int op)
{
am_node *new_mp;
- mntfs **mf_array;
+ am_loc **al_array;
int mp_error;
dlog("in amfs_generic_lookup_child");
@@ -1145,7 +1165,7 @@ amfs_generic_lookup_child(am_node *mp, char *fname, int *error_return, int op)
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))
+ if (*error_return == 0 && FSRV_ISUP(new_mp->am_al->al_mnt->mf_server))
return new_mp;
switch (op) {
@@ -1161,42 +1181,15 @@ amfs_generic_lookup_child(am_node *mp, char *fname, int *error_return, int op)
/* 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;
+ al_array = amfs_lookup_loc(new_mp, error_return);
+ if (!al_array) {
+ new_mp->am_error = new_mp->am_al->al_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;
+ new_mp->am_alarray = al_array;
/*
* Note: while it might seem like a good idea to prioritize
@@ -1258,5 +1251,5 @@ amfs_generic_match(am_opts *fo)
/*
* mtab entry turns out to be the name of the mount map
*/
- return strdup(fo->opt_rfs ? fo->opt_rfs : ".");
+ return xstrdup(fo->opt_rfs ? fo->opt_rfs : ".");
}
diff --git a/amd/amfs_host.c b/amd/amfs_host.c
index 55423c46ea33..a3468ecd4b65 100644
--- a/amd/amfs_host.c
+++ b/amd/amfs_host.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -227,7 +223,14 @@ fetch_fhandle(CLIENT *client, char *dir, am_nfs_handle_t *fhp, u_long nfs_versio
plog(XLOG_INFO, "fetch_fhandle: NFS version %d", (int) nfs_version);
#ifdef HAVE_FS_NFS3
- if (nfs_version == NFS_VERSION3) {
+ if (nfs_version == NFS_VERSION3
+#ifdef HAVE_FS_NFS4
+#ifndef NO_FALLBACK
+ || nfs_version == NFS_VERSION4
+#endif /* NO_FALLBACK */
+#endif /* HAVE_FS_NFS4 */
+ ) {
+
memset((char *) &res3, 0, sizeof(res3));
clnt_stat = clnt_call(client,
MOUNTPROC_MNT,
@@ -303,8 +306,8 @@ amfs_host_mount(am_node *am, mntfs *mf)
int n_export;
int j, k;
exports exlist = 0, ex;
- exports *ep = 0;
- am_nfs_handle_t *fp = 0;
+ exports *ep = NULL;
+ am_nfs_handle_t *fp = NULL;
char *host;
int error = 0;
struct sockaddr_in sin;
@@ -449,13 +452,13 @@ amfs_host_mount(am_node *am, mntfs *mf)
/* 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;
+ ep[j] = NULL;
} else {
k = j;
error = fetch_fhandle(client, ep[j]->ex_dir, &fp[j],
mf->mf_server->fs_version);
if (error)
- ep[j] = 0;
+ ep[j] = NULL;
}
}
@@ -465,8 +468,8 @@ amfs_host_mount(am_node *am, mntfs *mf)
* 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) {
+ xstrlcpy(fs_name, mf->mf_info, sizeof(fs_name));
+ if ((rfs_dir = strchr(fs_name, ':')) == (char *) NULL) {
plog(XLOG_FATAL, "amfs_host_mount: mf_info has no colon");
error = EINVAL;
goto out;
@@ -493,10 +496,8 @@ amfs_host_mount(am_node *am, mntfs *mf)
*/
out:
discard_mntlist(mlist);
- if (ep)
- XFREE(ep);
- if (fp)
- XFREE(fp);
+ XFREE(ep);
+ XFREE(fp);
if (sock != RPC_ANYSOCK)
(void) amu_close(sock);
if (client)
@@ -554,7 +555,7 @@ amfs_host_umount(am_node *am, mntfs *mf)
* Reverse list...
*/
ml = mlist;
- mprev = 0;
+ mprev = NULL;
while (ml) {
mntlist *ml2 = ml->mnext;
ml->mnext = mprev;
diff --git a/amd/amfs_link.c b/amd/amfs_link.c
index e75ab862f8bc..0751dd7047a0 100644
--- a/amd/amfs_link.c
+++ b/amd/amfs_link.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -109,13 +105,13 @@ amfs_link_match(am_opts *fo)
*/
if (fo->opt_fs[0] == '/') {
char *link_hack = str3cat(NULL, ".", fo->opt_fs, "");
- if (!fo->opt_sublink)
- fo->opt_sublink = strdup(fo->opt_fs);
+ if (fo->opt_sublink == NULL || fo->opt_sublink[0] == '\0')
+ fo->opt_sublink = xstrdup(fo->opt_fs);
XFREE(fo->opt_fs);
fo->opt_fs = link_hack;
}
- return strdup(fo->opt_fs);
+ return xstrdup(fo->opt_fs);
}
diff --git a/amd/amfs_linkx.c b/amd/amfs_linkx.c
index e306eda91d3b..be95fe5e1a27 100644
--- a/amd/amfs_linkx.c
+++ b/amd/amfs_linkx.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
diff --git a/amd/amfs_nfsl.c b/amd/amfs_nfsl.c
index bb48f0efd255..c70a3eeb97c4 100644
--- a/amd/amfs_nfsl.c
+++ b/amd/amfs_nfsl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -101,7 +97,7 @@ amfs_nfsl_match(am_opts *fo)
char *retval;
struct stat stb;
- if (fo->opt_sublink)
+ if (fo->opt_sublink && fo->opt_sublink[0])
cp = fo->opt_sublink;
else
cp = fo->opt_fs;
@@ -116,8 +112,9 @@ amfs_nfsl_match(am_opts *fo)
* 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);
+ if (!STRCEQ(ho, am_get_hostname()) && !STRCEQ(ho, hostd)) {
+ plog(XLOG_INFO, "amfs_nfsl: \"%s\" is not the local host \"%s\", "
+ "or \"%s\" using type:=nfs", ho, am_get_hostname(), hostd);
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);
@@ -213,11 +210,16 @@ amfs_nfsl_umounted(mntfs *mf)
static fserver *
amfs_nfsl_ffserver(mntfs *mf)
{
- char *cp;
- char *ho = mf->mf_fo->opt_rhost;
+ char *cp, *ho;
struct stat stb;
- if (mf->mf_fo->opt_sublink)
+ if (mf->mf_fo == NULL) {
+ plog(XLOG_ERROR, "%s: NULL mf_fo", __func__);
+ return NULL;
+ }
+ ho = mf->mf_fo->opt_rhost;
+
+ if (mf->mf_fo->opt_sublink && mf->mf_fo->opt_sublink[0])
cp = mf->mf_fo->opt_sublink;
else
cp = mf->mf_fo->opt_fs;
@@ -227,7 +229,8 @@ amfs_nfsl_ffserver(mntfs *mf)
* 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) {
+ if ((!STRCEQ(ho, am_get_hostname()) &&
+ !STRCEQ(ho, hostd)) || lstat(cp, &stb) < 0) {
return nfs_ops.ffserver(mf);
} else {
mf->mf_flags |= MFF_NFSLINK;
diff --git a/amd/amfs_nfsx.c b/amd/amfs_nfsx.c
index 91be8af47e11..db1b9fafd119 100644
--- a/amd/amfs_nfsx.c
+++ b/amd/amfs_nfsx.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -118,7 +114,7 @@ amfs_nfsx_match(am_opts *fo)
}
/* set default sublink */
- if (fo->opt_sublink == 0) {
+ if (fo->opt_sublink == NULL || fo->opt_sublink[0] == '\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);
@@ -149,7 +145,7 @@ amfs_nfsx_match(am_opts *fo)
/*
* Determine magic cookie to put in mtab
*/
- xmtab = str3cat((char *) 0, fo->opt_rhost, ":", fo->opt_rfs);
+ xmtab = str3cat((char *) NULL, 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);
@@ -190,12 +186,15 @@ amfs_nfsx_init(mntfs *mf)
if (nx == 0) {
char **ivec;
- char *info = 0;
+ char *info = NULL;
char *host;
char *pref;
int error = 0;
- info = strdup(mf->mf_info);
+ info = xstrdup(mf->mf_info);
+ if (info == NULL)
+ return errno;
+
host = strchr(info, ':');
if (!host) {
error = EINVAL;
@@ -221,12 +220,12 @@ amfs_nfsx_init(mntfs *mf)
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;
+ nx->nx_mp = NULL;
{
- char *mp = 0;
- char *xinfo = 0;
+ char *mp = NULL;
+ char *xinfo = NULL;
char *fs = mf->mf_fo->opt_fs;
- char *rfs = 0;
+ char *rfs = NULL;
for (i = 0; i < nx->nx_c; i++) {
char *path = ivec[i + 1];
rfs = str3cat(rfs, pref, "/", path);
@@ -251,18 +250,14 @@ amfs_nfsx_init(mntfs *mf)
/* 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(rfs);
+ XFREE(mp);
+ XFREE(xinfo);
}
XFREE(ivec);
errexit:
- if (info)
- XFREE(info);
+ XFREE(info);
if (error)
return error;
}
@@ -503,7 +498,7 @@ amfs_nfsx_umount(am_node *am, mntfs *mf)
}
}
free_mntfs(m);
- n->n_mnt = 0;
+ n->n_mnt = NULL;
n->n_error = -1;
}
}
diff --git a/amd/amfs_program.c b/amd/amfs_program.c
index b0aed3752d75..6bf003fb2cf7 100644
--- a/amd/amfs_program.c
+++ b/amd/amfs_program.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -105,7 +101,7 @@ amfs_program_match(am_opts *fo)
}
prog = strchr(fo->opt_mount, ' ');
- return strdup(prog ? prog + 1 : fo->opt_mount);
+ return xstrdup(prog ? prog + 1 : fo->opt_mount);
}
@@ -116,11 +112,14 @@ amfs_program_init(mntfs *mf)
if (mf->mf_private != NULL)
return 0;
+ if (mf->mf_fo == 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);
+ mf->mf_private = (opaque_t) xstrdup(mf->mf_fo->opt_unmount);
else
- mf->mf_private = (opaque_t) strdup(mf->mf_fo->opt_umount);
+ mf->mf_private = (opaque_t) xstrdup(mf->mf_fo->opt_umount);
mf->mf_prfree = (void (*)(opaque_t)) free;
return 0;
@@ -136,9 +135,7 @@ amfs_program_exec(char *info)
/*
* Split copy of command info string
*/
- info = strdup(info);
- if (info == 0)
- return ENOBUFS;
+ info = xstrdup(info);
xivec = strsplit(info, ' ', '\'');
/*
@@ -148,11 +145,11 @@ amfs_program_exec(char *info)
if (!logfp)
logfp = stderr; /* initialize before possible first use */
if (dup(fileno(logfp)) == -1)
- return errno;
+ goto out;
if (fileno(logfp) != fileno(stderr)) {
(void) fclose(stderr);
if (dup(fileno(logfp)) == -1)
- return errno;
+ goto out;
}
/*
@@ -172,13 +169,16 @@ amfs_program_exec(char *info)
plog(XLOG_USER, "1st/2nd args missing to (un)mount program");
} else {
(void) execv(xivec[0], xivec + 1);
+ error = errno;
+ plog(XLOG_ERROR, "exec failed: %m");
+ errno = error;
}
+out:
/*
* Save error number
*/
error = errno;
- plog(XLOG_ERROR, "exec failed: %m");
/*
* Free allocate memory
diff --git a/amd/amfs_root.c b/amd/amfs_root.c
index 243267e71e86..f06c43ce0bac 100644
--- a/amd/amfs_root.c
+++ b/amd/amfs_root.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -92,7 +88,7 @@ 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_private = (opaque_t) mapc_find(mf->mf_info, "", NULL, NULL);
mf->mf_prfree = mapc_free;
return 0;
diff --git a/amd/amfs_toplvl.c b/amd/amfs_toplvl.c
index 1b968f197f55..1b143157b4c7 100644
--- a/amd/amfs_toplvl.c
+++ b/amd/amfs_toplvl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -148,7 +144,7 @@ amfs_toplvl_init(mntfs *mf)
{
int error = 0;
-#if defined(MNT2_GEN_OPT_FORCE) || defined(MNT2_GEN_OPT_DETACH)
+#if (defined(MNT2_GEN_OPT_FORCE) || defined(MNT2_GEN_OPT_DETACH)) && (defined(HAVE_UVMOUNT) || defined(HAVE_UMOUNT2))
if (gopt.flags & CFM_FORCED_UNMOUNTS) {
plog(XLOG_INFO, "amfs_toplvl_init: trying forced/lazy unmount of %s",
mf->mf_mount);
@@ -158,7 +154,7 @@ amfs_toplvl_init(mntfs *mf)
else
dlog("amfs_toplvl_init: forced/lazy unmount succeeded");
}
-#endif /* MNT2_GEN_OPT_FORCE || MNT2_GEN_OPT_DETACH */
+#endif /* (MNT2_GEN_OPT_FORCE || MNT2_GEN_OPT_DETACH) && (HAVE_UVMOUNT || HAVE_UMOUNT2) */
return error;
}
@@ -227,6 +223,11 @@ amfs_toplvl_mount(am_node *mp, mntfs *mf)
xstrlcat(opts, toplvl_opts, sizeof(opts));
}
+#ifdef MNTTAB_OPT_NOLOCK
+ xstrlcat(opts, ",", sizeof(opts));
+ xstrlcat(opts, MNTTAB_OPT_NOLOCK, sizeof(opts));
+#endif /* MNTTAB_OPT_NOLOCK */
+
#ifdef MNTTAB_OPT_NOAC
if (gopt.auto_attrcache == 0) {
xstrlcat(opts, ",", sizeof(opts));
diff --git a/amd/amfs_union.c b/amd/amfs_union.c
index 6adb5b0bd9cb..9f37a1b04dd1 100644
--- a/amd/amfs_union.c
+++ b/amd/amfs_union.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -95,7 +91,7 @@ create_amfs_union_node(char *dir, opaque_t arg)
am_node *am;
am = amfs_generic_lookup_child(arg, dir, &error, VLOOK_CREATE);
if (am && error < 0)
- am = amfs_generic_mount_child(am, &error);
+ (void)amfs_generic_mount_child(am, &error);
if (error > 0) {
errno = error; /* XXX */
plog(XLOG_ERROR, "unionfs: could not mount %s: %m", dir);
@@ -121,9 +117,9 @@ amfs_union_mounted(mntfs *mf)
for (mp = get_first_exported_ap(&index);
mp;
mp = get_next_exported_ap(&index)) {
- if (mp->am_mnt == mf) {
+ if (mp->am_al->al_mnt == mf) {
/* return value from create_amfs_union_node is ignored by mapc_keyiter */
- (void) mapc_keyiter((mnt_map *) mp->am_mnt->mf_private,
+ (void) mapc_keyiter((mnt_map *) mp->am_al->al_mnt->mf_private,
create_amfs_union_node,
mp);
break;
diff --git a/amd/amq_subr.c b/amd/amq_subr.c
index 79ecafc3d9b3..878361105652 100644
--- a/amd/amq_subr.c
+++ b/amd/amq_subr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -80,16 +76,68 @@ amqproc_mnttree_1_svc(voidp argp, struct svc_req *rqstp)
/*
* Unmount a single node
*/
-voidp
+int *
amqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp)
{
- static char res;
+ static int res = AMQ_UMNT_OK;
am_node *mp = find_ap(*(char **) argp);
if (mp)
forcibly_timeout_mp(mp);
- return (voidp) &res;
+ return &res;
+}
+
+
+/*
+ * Synchronously unmount a single node - parent side.
+ */
+int *
+amqproc_sync_umnt_1_svc_parent(voidp argp, struct svc_req *rqstp)
+{
+ amqproc_umnt_1_svc(argp, rqstp);
+ return NULL;
+}
+
+
+/*
+ * Synchronously unmount a single node - child side.
+ */
+amq_sync_umnt *
+amqproc_sync_umnt_1_svc_child(voidp argp, struct svc_req *rqstp)
+{
+ static amq_sync_umnt rv;
+ amq_sync_umnt buf;
+ ssize_t n;
+
+ am_node *mp = find_ap(*(char **) argp);
+
+ memset(&rv, 0, sizeof(rv));
+ rv.au_etype = AMQ_UMNT_READ;
+ if (mp && mp->am_fd[0] >= 0) {
+ n = read(mp->am_fd[0], &buf, sizeof(buf));
+ if (n == sizeof(buf))
+ rv = buf;
+ }
+ return &rv;
+}
+
+
+/*
+ * Synchronously unmount a single node - use if we can't fork (asynchronous).
+ */
+amq_sync_umnt *
+amqproc_sync_umnt_1_svc_async(voidp argp, struct svc_req *rqstp)
+{
+ static amq_sync_umnt rv;
+
+ memset(&rv, 0, sizeof(rv));
+ rv.au_etype = AMQ_UMNT_FORK;
+ rv.au_errno = errno;
+
+ amqproc_umnt_1_svc(argp, rqstp);
+
+ return &rv;
}
@@ -170,6 +218,12 @@ amqproc_getmntfs_1_svc(voidp argp, struct svc_req *rqstp)
return (amq_mount_info_list *) ((void *)&mfhead); /* XXX */
}
+extern qelem map_list_head;
+amq_map_info_list *
+amqproc_getmapinfo_1_svc(voidp argp, struct svc_req *rqstp)
+{
+ return (amq_map_info_list *) ((void *)&map_list_head); /* XXX */
+}
amq_string *
amqproc_getvers_1_svc(voidp argp, struct svc_req *rqstp)
@@ -218,11 +272,11 @@ amqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp)
for (mp = get_first_exported_ap(&index);
mp;
mp = get_next_exported_ap(&index)) {
- if (STREQ(mp->am_mnt->mf_ops->fs_type, "toplvl"))
+ if (STREQ(mp->am_al->al_mnt->mf_ops->fs_type, "toplvl"))
continue;
- if (STREQ(mp->am_mnt->mf_ops->fs_type, "auto"))
+ if (STREQ(mp->am_al->al_mnt->mf_ops->fs_type, "auto"))
continue;
- mountpoint = (mp->am_link ? mp->am_link : mp->am_mnt->mf_mount);
+ mountpoint = (mp->am_link ? mp->am_link : mp->am_al->al_mnt->mf_mount);
len = strlen(mountpoint);
if (len == 0)
continue;
@@ -277,16 +331,16 @@ 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)) {
+ if (!xdr_amq_string(xdrs, &mp->am_al->al_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)) {
+ if (!xdr_amq_string(xdrs, mp->am_link ? &mp->am_link : &mp->am_al->al_mnt->mf_mount)) {
return (FALSE);
}
- if (!xdr_amq_string(xdrs, &mp->am_mnt->mf_ops->fs_type)) {
+ if (!xdr_amq_string(xdrs, &mp->am_al->al_mnt->mf_ops->fs_type)) {
return (FALSE);
}
mtime = mp->am_stats.s_mtime;
@@ -412,16 +466,15 @@ xdr_amq_mount_tree_list(XDR *xdrs, amq_mount_tree_list *objp)
}
-
-/*
- * Compute length of list
- */
bool_t
xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead)
{
mntfs *mf;
u_int len = 0;
+ /*
+ * Compute length of list
+ */
for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) {
if (!(mf->mf_fsflags & FS_AMQINFO))
continue;
@@ -468,6 +521,70 @@ xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead)
return (TRUE);
}
+bool_t
+xdr_amq_map_info_qelem(XDR *xdrs, qelem *qhead)
+{
+ mnt_map *m;
+ u_int len = 0;
+ int x;
+ char *n;
+
+ /*
+ * Compute length of list
+ */
+ ITER(m, mnt_map, qhead) {
+ len++;
+ }
+
+ if (!xdr_u_int(xdrs, &len))
+ return (FALSE);
+
+ /*
+ * Send individual data items
+ */
+ ITER(m, mnt_map, qhead) {
+ if (!xdr_amq_string(xdrs, &m->map_name)) {
+ return (FALSE);
+ }
+
+ n = m->wildcard ? m->wildcard : "";
+ if (!xdr_amq_string(xdrs, &n)) {
+ return (FALSE);
+ }
+
+ if (!xdr_long(xdrs, &m->modify)) {
+ return (FALSE);
+ }
+
+ x = m->flags;
+ if (!xdr_int(xdrs, &x)) {
+ return (FALSE);
+ }
+
+ x = m->nentries;
+ if (!xdr_int(xdrs, &x)) {
+ return (FALSE);
+ }
+
+ x = m->reloads;
+ if (!xdr_int(xdrs, &x)) {
+ return (FALSE);
+ }
+
+ if (!xdr_int(xdrs, &m->refc)) {
+ return (FALSE);
+ }
+
+ if (m->isup)
+ x = (*m->isup)(m, m->map_name);
+ else
+ x = -1;
+ if (!xdr_int(xdrs, &x)) {
+ return (FALSE);
+ }
+ }
+ return (TRUE);
+}
bool_t
xdr_pri_free(XDRPROC_T_TYPE xdr_args, caddr_t args_ptr)
diff --git a/amd/amq_svc.c b/amd/amq_svc.c
index 6fadb160c121..1f2b3d6ff8d9 100644
--- a/amd/amq_svc.c
+++ b/amd/amq_svc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -57,7 +53,7 @@ typedef char *(*amqsvcproc_t)(voidp, struct svc_req *);
* 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;
+int allow_severity=0, deny_severity=0, rfc931_timeout=0;
# endif /* NEED_LIBWRAP_SEVERITY_VARIABLES */
/*
@@ -65,49 +61,88 @@ int allow_severity=0, deny_severity=0;
* Returns: 1=allowed, 0=denied.
*/
static int
-amqsvc_is_client_allowed(const struct sockaddr_in *addr, char *remote)
+amqsvc_is_client_allowed(const struct sockaddr_in *addr)
{
- 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;
+ struct request_info req;
+
+ request_init(&req, RQ_DAEMON, AMD_SERVICE_NAME, RQ_CLIENT_SIN, addr, 0);
+ sock_methods(&req);
+
+ if (hosts_access(&req))
+ return 1;
+
+ return 0;
+}
+#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
+
+
+/*
+ * Prepare the parent and child:
+ * 1) Setup IPC pipe.
+ * 2) Set signal masks.
+ * 3) Fork by calling background() so that NumChildren is updated.
+ */
+static int
+amq_fork(opaque_t argp)
+{
+#ifdef HAVE_SIGACTION
+ sigset_t new, mask;
+#else /* not HAVE_SIGACTION */
+ int mask;
+#endif /* not HAVE_SIGACTION */
+ am_node *mp;
+ pid_t pid;
+
+ mp = find_ap(*(char **) argp);
+ if (mp == NULL) {
+ errno = 0;
+ return -1;
}
- /* 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;
+
+ if (pipe(mp->am_fd) == -1) {
+ mp->am_fd[0] = -1;
+ mp->am_fd[1] = -1;
+ return -1;
}
- /* 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;
+#ifdef HAVE_SIGACTION
+ sigemptyset(&new); /* initialize signal set we wish to block */
+ sigaddset(&new, SIGHUP);
+ sigaddset(&new, SIGINT);
+ sigaddset(&new, SIGQUIT);
+ sigaddset(&new, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &new, &mask);
+#else /* not HAVE_SIGACTION */
+ mask =
+ sigmask(SIGHUP) |
+ sigmask(SIGINT) |
+ sigmask(SIGQUIT) |
+ sigmask(SIGCHLD);
+ mask = sigblock(mask);
+#endif /* not HAVE_SIGACTION */
+
+ switch ((pid = background())) {
+ case -1: /* error */
+ dlog("amq_fork failed");
+ return -1;
+
+ case 0: /* child */
+ close(mp->am_fd[1]); /* close output end of pipe */
+ mp->am_fd[1] = -1;
+ return 0;
+
+ default: /* parent */
+ close(mp->am_fd[0]); /* close input end of pipe */
+ mp->am_fd[0] = -1;
+
+#ifdef HAVE_SIGACTION
+ sigprocmask(SIG_SETMASK, &mask, NULL);
+#else /* not HAVE_SIGACTION */
+ sigsetmask(mask);
+#endif /* not HAVE_SIGACTION */
+ return pid;
+ }
}
-#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
void
@@ -121,13 +156,16 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp)
char *result;
xdrproc_t xdr_argument, xdr_result;
amqsvcproc_t local;
+ amqsvcproc_t child;
+ amqsvcproc_t parent;
+ pid_t pid;
#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)) {
+ if (!amqsvc_is_client_allowed(remote_addr)) {
plog(XLOG_WARNING, "Amd denied remote amq service to %s", remote_hostname);
svcerr_auth(transp, AUTH_FAILED);
return;
@@ -137,6 +175,10 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp)
}
#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
+ local = NULL;
+ child = NULL;
+ parent = NULL;
+
switch (rqstp->rq_proc) {
case AMQPROC_NULL:
@@ -199,6 +241,21 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp)
local = (amqsvcproc_t) amqproc_pawd_1_svc;
break;
+ case AMQPROC_SYNC_UMNT:
+ xdr_argument = (xdrproc_t) xdr_amq_string;
+ xdr_result = (xdrproc_t) xdr_amq_sync_umnt;
+ parent = (amqsvcproc_t) amqproc_sync_umnt_1_svc_parent;
+ child = (amqsvcproc_t) amqproc_sync_umnt_1_svc_child;
+ /* used if fork fails */
+ local = (amqsvcproc_t) amqproc_sync_umnt_1_svc_async;
+ break;
+
+ case AMQPROC_GETMAPINFO:
+ xdr_argument = (xdrproc_t) xdr_void;
+ xdr_result = (xdrproc_t) xdr_amq_map_info_qelem;
+ local = (amqsvcproc_t) amqproc_getmapinfo_1_svc;
+ break;
+
default:
svcerr_noproc(transp);
return;
@@ -212,7 +269,28 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp)
return;
}
- result = (*local) (&argument, rqstp);
+ pid = -1;
+ result = NULL;
+
+ if (child) {
+ switch ((pid = amq_fork(&argument))) {
+ case -1: /* error */
+ break;
+
+ case 0: /* child */
+ result = (*child) (&argument, rqstp);
+ local = NULL;
+ break;
+
+ default: /* parent */
+ result = (*parent) (&argument, rqstp);
+ local = NULL;
+ break;
+ }
+ }
+
+ if (local)
+ result = (*local) (&argument, rqstp);
if (result != NULL && !svc_sendreply(transp,
(XDRPROC_T_TYPE) xdr_result,
@@ -226,4 +304,7 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp)
plog(XLOG_FATAL, "unable to free rpc arguments in amqprog_1");
going_down(1);
}
+
+ if (pid == 0)
+ exit(0); /* the child is done! */
}
diff --git a/amd/autil.c b/amd/autil.c
index a5ecd6d0d1f3..cd9514d44ef4 100644
--- a/amd/autil.c
+++ b/amd/autil.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -160,16 +156,23 @@ valid_key(char *key)
void
forcibly_timeout_mp(am_node *mp)
{
- mntfs *mf = mp->am_mnt;
+ mntfs *mf = mp->am_al->al_mnt;
/*
* Arrange to timeout this node
*/
if (mf && ((mp->am_flags & AMF_ROOT) ||
(mf->mf_flags & (MFF_MOUNTING | MFF_UNMOUNTING)))) {
+ /*
+ * We aren't going to schedule a timeout, so we need to notify the
+ * child here unless we are already unmounting, in which case that
+ * process is responsible for notifying the child.
+ */
if (mf->mf_flags & MFF_UNMOUNTING)
plog(XLOG_WARNING, "node %s is currently being unmounted, ignoring timeout request", mp->am_path);
- else
+ else {
plog(XLOG_WARNING, "ignoring timeout request for active node %s", mp->am_path);
+ notify_child(mp, AMQ_UMNT_FAILED, EBUSY, 0);
+ }
} else {
plog(XLOG_INFO, "\"%s\" forcibly timed out", mp->am_path);
mp->am_flags &= ~AMF_NOTIMEOUT;
@@ -207,24 +210,11 @@ mf_mounted(mntfs *mf, bool_t call_free_opts)
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).
+ * We used to free the mf_mo (options) here, however they're now stored
+ * and managed with the mntfs and do not need to be free'd here (this ensures
+ * that we use the same options to monitor/unmount the system as we used
+ * to mount it).
*/
- 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) {
@@ -249,7 +239,7 @@ void
am_mounted(am_node *mp)
{
int notimeout = 0; /* assume normal timeouts initially */
- mntfs *mf = mp->am_mnt;
+ mntfs *mf = mp->am_al->al_mnt;
/*
* This is the parent mntfs which does the mf->mf_fo (am_opts type), and
@@ -266,7 +256,7 @@ am_mounted(am_node *mp)
/*
* Patch up path for direct mounts
*/
- if (mp->am_parent && mp->am_parent->am_mnt->mf_fsflags & FS_DIRECT)
+ if (mp->am_parent && mp->am_parent->am_al->al_mnt->mf_fsflags & FS_DIRECT)
mp->am_path = str3cat(mp->am_path, mp->am_parent->am_path, "/", ".");
/*
@@ -277,6 +267,7 @@ am_mounted(am_node *mp)
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;
@@ -321,7 +312,7 @@ am_mounted(am_node *mp)
/*
* Update mtime of parent node (copying "struct nfstime" in '=' below)
*/
- if (mp->am_parent && mp->am_parent->am_mnt)
+ if (mp->am_parent && mp->am_parent->am_al->al_mnt)
mp->am_parent->am_fattr.na_mtime = mp->am_fattr.na_mtime;
/*
@@ -360,21 +351,27 @@ assign_error_mntfs(am_node *mp)
{
int error;
dlog("assign_error_mntfs");
+
+ if (mp->am_al == NULL) {
+ plog(XLOG_ERROR, "%s: Can't assign error", __func__);
+ return;
+ }
/*
* Save the old error code
*/
error = mp->am_error;
if (error <= 0)
- error = mp->am_mnt->mf_error;
+ error = mp->am_al->al_mnt->mf_error;
/*
* Allocate a new error reference
*/
- mp->am_mnt = new_mntfs();
+ free_loc(mp->am_al);
+ mp->am_al = new_loc();
/*
* Put back the error code
*/
- mp->am_mnt->mf_error = error;
- mp->am_mnt->mf_flags |= MFF_ERROR;
+ mp->am_al->al_mnt->mf_error = error;
+ mp->am_al->al_mnt->mf_flags |= MFF_ERROR;
/*
* Zero the error in the mount point
*/
@@ -397,7 +394,8 @@ amfs_mkcacheref(mntfs *mf)
cache = "none";
mf->mf_private = (opaque_t) mapc_find(mf->mf_info,
cache,
- (mf->mf_fo ? mf->mf_fo->opt_maptype : NULL));
+ (mf->mf_fo ? mf->mf_fo->opt_maptype : NULL),
+ mf->mf_mount);
mf->mf_prfree = mapc_free;
}
@@ -418,7 +416,7 @@ next_nonerror_node(am_node *xp)
* containing hung automounts.
*/
while (xp &&
- (!(mf = xp->am_mnt) || /* No mounted filesystem */
+ (!(mf = xp->am_al->al_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 */
@@ -453,8 +451,9 @@ amfs_mount(am_node *mp, mntfs *mf, char *opts)
mntent_t mnt;
MTYPE_TYPE type;
int forced_unmount = 0; /* are we using forced unmounts? */
+ u_long nfs_version = get_nfs_dispatcher_version(nfs_dispatcher);
- memset((voidp) &mnt, 0, sizeof(mnt));
+ memset(&mnt, 0, sizeof(mnt));
mnt.mnt_dir = dir;
mnt.mnt_fsname = pid_fsname;
mnt.mnt_opts = opts;
@@ -525,8 +524,7 @@ amfs_mount(am_node *mp, mntfs *mf, char *opts)
again:
if (!(mf->mf_flags & MFF_IS_AUTOFS)) {
nfs_args_t nfs_args;
- am_nfs_fh *fhp;
- am_nfs_handle_t anh;
+ am_nfs_handle_t *fhp, anh;
#ifndef HAVE_TRANSPORT_TYPE_TLI
u_short port;
struct sockaddr_in sin;
@@ -535,7 +533,7 @@ again:
/*
* get fhandle of remote path for automount point
*/
- fhp = get_root_nfs_fh(dir);
+ fhp = get_root_nfs_fh(dir, &anh);
if (!fhp) {
plog(XLOG_FATAL, "Can't find root file handle for %s", dir);
return EINVAL;
@@ -545,7 +543,7 @@ again:
/*
* Create sockaddr to point to the local machine.
*/
- memset((voidp) &sin, 0, sizeof(sin));
+ memset(&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;
@@ -559,16 +557,15 @@ again:
#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 */
+ nfs_version,
"udp",
- &anh,
+ fhp,
fs_hostname,
pid_fsname);
/*
@@ -587,9 +584,9 @@ again:
genflags,
NULL,
&sin,
- NFS_VERSION, /* version 2 */
+ nfs_version,
"udp",
- &anh,
+ fhp,
fs_hostname,
pid_fsname);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
@@ -656,10 +653,17 @@ again:
void
am_unmounted(am_node *mp)
{
- mntfs *mf = mp->am_mnt;
+ mntfs *mf = mp->am_al->al_mnt;
- if (!foreground) /* firewall - should never happen */
+ if (!foreground) { /* firewall - should never happen */
+ /*
+ * This is a coding error. Make sure we hear about it!
+ */
+ plog(XLOG_FATAL, "am_unmounted: illegal use in background (%s)",
+ mp->am_name);
+ notify_child(mp, AMQ_UMNT_OK, 0, 0); /* XXX - be safe? */
return;
+ }
/*
* Do unmounted callback
@@ -707,26 +711,37 @@ am_unmounted(am_node *mp)
/*
* Update mtime of parent node
*/
- if (mp->am_parent && mp->am_parent->am_mnt)
+ if (mp->am_parent && mp->am_parent->am_al->al_mnt)
clocktime(&mp->am_parent->am_fattr.na_mtime);
if (mp->am_parent && (mp->am_flags & AMF_REMOUNT)) {
- char *fname = strdup(mp->am_name);
+ char *fname = xstrdup(mp->am_name);
am_node *mp_parent = mp->am_parent;
- mntfs *mf_parent = mp_parent->am_mnt;
+ mntfs *mf_parent = mp_parent->am_al->al_mnt;
+ am_node fake_mp;
int error = 0;
+ /*
+ * We need to use notify_child() after free_map(), so save enough
+ * to do that in fake_mp.
+ */
+ fake_mp.am_fd[1] = mp->am_fd[1];
+ mp->am_fd[1] = -1;
+
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);
+ (void)mf_parent->mf_ops->mount_child(mp, &error);
if (error > 0) {
errno = error;
plog(XLOG_ERROR, "am_unmounted: could not remount %s: %m", fname);
+ notify_child(&fake_mp, AMQ_UMNT_OK, 0, 0);
+ } else {
+ notify_child(&fake_mp, AMQ_UMNT_FAILED, EBUSY, 0);
}
XFREE(fname);
- } else
+ } else {
/*
* We have a race here.
* If this node has a pending mount and amd is going down (unmounting
@@ -734,10 +749,12 @@ am_unmounted(am_node *mp)
* 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).
+ * pending mounts (defined as having a non-NULL am_alarray).
*/
- if (!mp->am_mfarray)
+ notify_child(mp, AMQ_UMNT_OK, 0, 0); /* do this regardless */
+ if (!mp->am_alarray)
free_map(mp);
+ }
}
diff --git a/amd/clock.c b/amd/clock.c
index 0caa7dff2c73..4c6aa5413763 100644
--- a/amd/clock.c
+++ b/amd/clock.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
diff --git a/amd/conf.c b/amd/conf.c
index 2fc587b0cadb..57e1b9ddbd02 100644
--- a/amd/conf.c
+++ b/amd/conf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -77,6 +73,7 @@ struct _func_map {
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_auto_nfs_version(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);
@@ -120,6 +117,7 @@ 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_nfs_vers_ping(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);
@@ -132,6 +130,7 @@ 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_sun_map_syntax(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);
@@ -146,6 +145,7 @@ 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_sun_map_syntax(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);
@@ -159,6 +159,7 @@ static struct _func_map glob_functable[] = {
{"arch", gopt_arch},
{"auto_attrcache", gopt_auto_attrcache},
{"auto_dir", gopt_auto_dir},
+ {"auto_nfs_version", gopt_auto_nfs_version},
{"autofs_use_lofs", gopt_autofs_use_lofs},
{"browsable_dirs", gopt_browsable_dirs},
{"cache_duration", gopt_cache_duration},
@@ -202,6 +203,7 @@ static struct _func_map glob_functable[] = {
{"nfs_retry_interval_tcp", gopt_nfs_retry_interval_tcp},
{"nfs_retry_interval_toplvl", gopt_nfs_retry_interval_toplvl},
{"nfs_vers", gopt_nfs_vers},
+ {"nfs_vers_ping", gopt_nfs_vers_ping},
{"nis_domain", gopt_nis_domain},
{"normalize_hostnames", gopt_normalize_hostnames},
{"normalize_slashes", gopt_normalize_slashes},
@@ -215,6 +217,7 @@ static struct _func_map glob_functable[] = {
{"selectors_on_default", gopt_selectors_in_defaults},
{"selectors_in_defaults", gopt_selectors_in_defaults},
{"show_statfs_entries", gopt_show_statfs_entries},
+ {"sun_map_syntax", gopt_sun_map_syntax},
{"truncate_log", gopt_truncate_log},
{"unmount_on_exit", gopt_unmount_on_exit},
{"use_tcpwrappers", gopt_use_tcpwrappers},
@@ -255,12 +258,14 @@ init_cf_map(cf_map_t *cfm)
cfm->cfm_search_path = gopt.search_path;
/*
- * Initialize flags that are common both to [global] and a local map.
+ * Initialize flags that are common both to [global] and a local map
+ * (that is, they could be inherited from the global section).
*/
cfm->cfm_flags = gopt.flags & (CFM_BROWSABLE_DIRS |
CFM_BROWSABLE_DIRS_FULL |
CFM_MOUNT_TYPE_AUTOFS |
- CFM_SELECTORS_IN_DEFAULTS);
+ CFM_SELECTORS_IN_DEFAULTS |
+ CFM_SUN_MAP_SYNTAX );
}
@@ -366,7 +371,7 @@ process_global_option(const char *key, const char *val)
static int
gopt_arch(const char *val)
{
- gopt.arch = strdup((char *)val);
+ gopt.arch = xstrdup(val);
return 0;
}
@@ -386,10 +391,23 @@ gopt_auto_attrcache(const char *val)
static int
gopt_auto_dir(const char *val)
{
- gopt.auto_dir = strdup((char *)val);
+ gopt.auto_dir = xstrdup(val);
return 0;
}
+static int
+gopt_auto_nfs_version(const char *val)
+{
+ if (strcmp(val, "2") == 0)
+ nfs_dispatcher = nfs_program_2;
+ else if (strcmp(val, "3") == 0)
+ nfs_dispatcher = nfs_program_3;
+ else {
+ fprintf(stderr, "conf: bad auto nfs version : \"%s\"\n", val);
+ return 1;
+ }
+ return 0;
+}
static int
gopt_autofs_use_lofs(const char *val)
@@ -439,7 +457,7 @@ gopt_cache_duration(const char *val)
static int
gopt_cluster(const char *val)
{
- gopt.cluster = strdup((char *)val);
+ gopt.cluster = xstrdup(val);
return 0;
}
@@ -447,7 +465,7 @@ gopt_cluster(const char *val)
static int
gopt_debug_mtab_file(const char *val)
{
- gopt.debug_mtab_file = strdup((char*)val);
+ gopt.debug_mtab_file = xstrdup(val);
return 0;
}
@@ -547,7 +565,7 @@ gopt_forced_unmounts(const char *val)
static int
gopt_full_os(const char *val)
{
- gopt.op_sys_full = strdup((char *)val);
+ gopt.op_sys_full = xstrdup(val);
return 0;
}
@@ -572,7 +590,7 @@ static int
gopt_hesiod_base(const char *val)
{
#ifdef HAVE_MAP_HESIOD
- gopt.hesiod_base = strdup((char *)val);
+ gopt.hesiod_base = xstrdup(val);
return 0;
#else /* not HAVE_MAP_HESIOD */
fprintf(stderr, "conf: hesiod_base option ignored. No Hesiod support available.\n");
@@ -584,7 +602,7 @@ gopt_hesiod_base(const char *val)
static int
gopt_karch(const char *val)
{
- gopt.karch = strdup((char *)val);
+ gopt.karch = xstrdup(val);
return 0;
}
@@ -592,7 +610,7 @@ gopt_karch(const char *val)
static int
gopt_pid_file(const char *val)
{
- gopt.pid_file = strdup((char *)val);
+ gopt.pid_file = xstrdup(val);
return 0;
}
@@ -600,7 +618,7 @@ gopt_pid_file(const char *val)
static int
gopt_local_domain(const char *val)
{
- gopt.sub_domain = strdup((char *)val);
+ gopt.sub_domain = xstrdup(val);
return 0;
}
@@ -608,7 +626,7 @@ gopt_local_domain(const char *val)
static int
gopt_localhost_address(const char *val)
{
- gopt.localhost_address = strdup((char *)val);
+ gopt.localhost_address = xstrdup(val);
return 0;
}
@@ -617,7 +635,7 @@ static int
gopt_ldap_base(const char *val)
{
#ifdef HAVE_MAP_LDAP
- gopt.ldap_base = strdup((char *)val);
+ gopt.ldap_base = xstrdup(val);
return 0;
#else /* not HAVE_MAP_LDAP */
fprintf(stderr, "conf: ldap_base option ignored. No LDAP support available.\n");
@@ -668,7 +686,7 @@ static int
gopt_ldap_hostports(const char *val)
{
#ifdef HAVE_MAP_LDAP
- gopt.ldap_hostports = strdup((char *)val);
+ gopt.ldap_hostports = xstrdup(val);
return 0;
#else /* not HAVE_MAP_LDAP */
fprintf(stderr, "conf: ldap_hostports option ignored. No LDAP support available.\n");
@@ -719,7 +737,7 @@ gopt_ldap_proto_version(const char *val)
static int
gopt_log_file(const char *val)
{
- gopt.logfile = strdup((char *)val);
+ gopt.logfile = xstrdup(val);
return 0;
}
@@ -735,7 +753,7 @@ gopt_log_options(const char *val)
static int
gopt_map_defaults(const char *val)
{
- gopt.map_defaults = strdup((char *)val);
+ gopt.map_defaults = xstrdup(val);
return 0;
}
@@ -743,7 +761,7 @@ gopt_map_defaults(const char *val)
static int
gopt_map_options(const char *val)
{
- gopt.map_options = strdup((char *)val);
+ gopt.map_options = xstrdup(val);
return 0;
}
@@ -766,7 +784,7 @@ gopt_map_type(const char *val)
fprintf(stderr, "conf: no such map type \"%s\"\n", val);
return 1;
}
- gopt.map_type = strdup((char *)val);
+ gopt.map_type = xstrdup(val);
return 0;
}
@@ -863,7 +881,7 @@ static int
gopt_nfs_proto(const char *val)
{
if (STREQ(val, "udp") || STREQ(val, "tcp")) {
- gopt.nfs_proto = strdup((char *)val);
+ gopt.nfs_proto = xstrdup(val);
return 0;
}
fprintf(stderr, "conf: illegal nfs_proto \"%s\"\n", val);
@@ -946,7 +964,7 @@ gopt_nfs_vers(const char *val)
{
int i = atoi(val);
- if (i == 2 || i == 3) {
+ if (i == 2 || i == 3 || i == 4) {
gopt.nfs_vers = i;
return 0;
}
@@ -956,10 +974,23 @@ gopt_nfs_vers(const char *val)
static int
+gopt_nfs_vers_ping(const char *val)
+{
+ int i = atoi(val);
+
+ if (i == 2 || i == 3 || i == 4) {
+ gopt.nfs_vers_ping = i;
+ return 0;
+ }
+ fprintf(stderr, "conf: illegal nfs_vers_ping \"%s\"\n", val);
+ return 1;
+}
+
+static int
gopt_nis_domain(const char *val)
{
#ifdef HAVE_MAP_NIS
- gopt.nis_domain = strdup((char *)val);
+ gopt.nis_domain = xstrdup(val);
return 0;
#else /* not HAVE_MAP_NIS */
fprintf(stderr, "conf: nis_domain option ignored. No NIS support available.\n");
@@ -1003,7 +1034,7 @@ gopt_normalize_slashes(const char *val)
static int
gopt_os(const char *val)
{
- gopt.op_sys = strdup((char *)val);
+ gopt.op_sys = xstrdup(val);
return 0;
}
@@ -1011,7 +1042,7 @@ gopt_os(const char *val)
static int
gopt_osver(const char *val)
{
- gopt.op_sys_ver = strdup((char *)val);
+ gopt.op_sys_ver = xstrdup(val);
return 0;
}
@@ -1084,7 +1115,7 @@ gopt_restart_mounts(const char *val)
static int
gopt_search_path(const char *val)
{
- gopt.search_path = strdup((char *)val);
+ gopt.search_path = xstrdup(val);
return 0;
}
@@ -1122,6 +1153,22 @@ gopt_show_statfs_entries(const char *val)
static int
+gopt_sun_map_syntax(const char *val)
+{
+ if (STREQ(val, "yes")) {
+ gopt.flags |= CFM_SUN_MAP_SYNTAX;
+ return 0;
+ } else if (STREQ(val, "no")) {
+ gopt.flags &= ~CFM_SUN_MAP_SYNTAX;
+ return 0;
+ }
+
+ fprintf(stderr, "conf: unknown value to sun_map_syntax \"%s\"\n", val);
+ return 1; /* unknown value */
+}
+
+
+static int
gopt_truncate_log(const char *val)
{
if (STREQ(val, "yes")) {
@@ -1177,7 +1224,7 @@ gopt_use_tcpwrappers(const char *val)
static int
gopt_vendor(const char *val)
{
- gopt.op_sys_vendor = strdup((char *)val);
+ gopt.op_sys_vendor = xstrdup(val);
return 0;
}
@@ -1199,7 +1246,7 @@ process_regular_option(const char *section, const char *key, const char *val, cf
/* check if initializing a new map */
if (!cfm->cfm_dir)
- cfm->cfm_dir = strdup((char *)section);
+ cfm->cfm_dir = xstrdup(section);
/* check for each possible field */
if (STREQ(key, "browsable_dirs"))
@@ -1223,6 +1270,9 @@ process_regular_option(const char *section, const char *key, const char *val, cf
if (STREQ(key, "search_path"))
return ropt_search_path(val, cfm);
+ if (STREQ(key, "sun_map_syntax"))
+ return ropt_sun_map_syntax(val, cfm);
+
if (STREQ(key, "tag"))
return ropt_tag(val, cfm);
@@ -1254,7 +1304,7 @@ ropt_browsable_dirs(const char *val, cf_map_t *cfm)
static int
ropt_map_name(const char *val, cf_map_t *cfm)
{
- cfm->cfm_name = strdup((char *)val);
+ cfm->cfm_name = xstrdup(val);
return 0;
}
@@ -1262,7 +1312,7 @@ ropt_map_name(const char *val, cf_map_t *cfm)
static int
ropt_map_defaults(const char *val, cf_map_t *cfm)
{
- cfm->cfm_defaults = strdup((char *)val);
+ cfm->cfm_defaults = xstrdup(val);
return 0;
}
@@ -1270,7 +1320,7 @@ ropt_map_defaults(const char *val, cf_map_t *cfm)
static int
ropt_map_options(const char *val, cf_map_t *cfm)
{
- cfm->cfm_opts = strdup((char *)val);
+ cfm->cfm_opts = xstrdup(val);
return 0;
}
@@ -1283,7 +1333,7 @@ ropt_map_type(const char *val, cf_map_t *cfm)
fprintf(stderr, "conf: no such map type \"%s\"\n", val);
return 1;
}
- cfm->cfm_type = strdup((char *)val);
+ cfm->cfm_type = xstrdup(val);
return 0;
}
@@ -1313,15 +1363,32 @@ ropt_mount_type(const char *val, cf_map_t *cfm)
static int
ropt_search_path(const char *val, cf_map_t *cfm)
{
- cfm->cfm_search_path = strdup((char *)val);
+ cfm->cfm_search_path = xstrdup(val);
return 0;
}
static int
+ropt_sun_map_syntax(const char *val, cf_map_t *cfm)
+{
+ if (STREQ(val, "yes")) {
+ cfm->cfm_flags |= CFM_SUN_MAP_SYNTAX;
+ return 0;
+
+ } else if (STREQ(val, "no")) {
+ cfm->cfm_flags &= ~CFM_SUN_MAP_SYNTAX;
+ return 0;
+ }
+
+ fprintf(stderr, "conf: unknown value to sun_map_syntax \"%s\"\n", val);
+ return 1; /* unknown value */
+}
+
+
+static int
ropt_tag(const char *val, cf_map_t *cfm)
{
- cfm->cfm_tag = strdup((char *)val);
+ cfm->cfm_tag = xstrdup(val);
return 0;
}
@@ -1397,7 +1464,7 @@ find_cf_map(const char *name)
return NULL;
while (tmp_map) {
- if (STREQ(tmp_map->cfm_dir,name)) {
+ if (STREQ(tmp_map->cfm_dir, name)) {
return tmp_map;
}
tmp_map = tmp_map->cfm_next;
diff --git a/amd/conf_parse.y b/amd/conf_parse.y
index b397b0573242..26c1b7ac7903 100644
--- a/amd/conf_parse.y
+++ b/amd/conf_parse.y
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
diff --git a/amd/conf_tok.l b/amd/conf_tok.l
index b572e4d7d5a3..fea2d8bf43f5 100644
--- a/amd/conf_tok.l
+++ b/amd/conf_tok.l
@@ -1,6 +1,6 @@
%{
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -17,11 +17,7 @@
* 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
+ * 3. 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.
*
@@ -74,7 +70,7 @@
*/
#ifdef FLEX_SCANNER
# ifndef ECHO
-# define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+# define ECHO __IGNORE(fwrite( yytext, yyleng, 1, yyout ))
# endif /* not ECHO */
#endif /* FLEX_SCANNER */
@@ -86,9 +82,9 @@ int yylex(void);
* which automatically generates yywrap macros and symbols. So I must
* distinguish between them and when yywrap is actually needed.
*/
-#ifndef yywrap
+#if !defined(yywrap) || defined(yylex)
int yywrap(void);
-#endif /* not yywrap */
+#endif /* not yywrap or yylex */
#define TOK_DEBUG 0
@@ -108,6 +104,7 @@ int yywrap(void);
/* This option causes Solaris lex to fail. Use flex. See BUGS file */
/* no need to use yyunput() */
%option nounput
+%option noinput
/* allocate more output slots so lex scanners don't run out of mem */
%o 1024
@@ -131,19 +128,19 @@ NONQUOTE [^\"]
\[ {
dprintf("%8d: Left bracket \"%s\"\n", yytext);
- yylval.strtype = strdup((char *)yytext);
+ conf_lval.strtype = xstrdup(yytext);
amu_return(LEFT_BRACKET);
}
\] {
dprintf("%8d: Right bracket \"%s\"\n", yytext);
- yylval.strtype = strdup((char *)yytext);
+ conf_lval.strtype = xstrdup(yytext);
amu_return(RIGHT_BRACKET);
}
= {
dprintf("%8d: Equal \"%s\"\n", yytext);
- yylval.strtype = strdup((char *)yytext);
+ conf_lval.strtype = xstrdup(yytext);
amu_return(EQUAL);
}
@@ -159,7 +156,7 @@ NONQUOTE [^\"]
{NONWSCHAR}{NONWSCHAR}* {
dprintf("%8d: Non-WS string \"%s\"\n", yytext);
- yylval.strtype = strdup((char *)yytext);
+ conf_lval.strtype = xstrdup(yytext);
amu_return(NONWS_STRING);
}
@@ -167,13 +164,13 @@ 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]);
+ conf_lval.strtype = xstrdup(&yytext[1]);
amu_return(QUOTED_NONWSEQ_STRING);
}
{NONWSEQCHAR}{NONWSEQCHAR}* {
dprintf("%8d: Non-WS-EQ string \"%s\"\n", yytext);
- yylval.strtype = strdup((char *)yytext);
+ conf_lval.strtype = xstrdup(yytext);
amu_return(NONWSEQ_STRING);
}
@@ -184,9 +181,9 @@ NONQUOTE [^\"]
* which automatically generates yywrap macros and symbols. So I must
* distinguish between them and when yywrap is actually needed.
*/
-#ifndef yywrap
+#if !defined(yywrap) || defined(yylex)
int yywrap(void)
{
return 1;
}
-#endif /* not yywrap */
+#endif /* not yywrap or yylex */
diff --git a/amd/get_args.c b/amd/get_args.c
index 12a7d07efd59..b6c7a99de337 100644
--- a/amd/get_args.c
+++ b/amd/get_args.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -84,44 +80,44 @@ get_version_string(void)
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) 1997-2014 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);
+ xstrlcat(vers, tmpbuf, len);
xsnprintf(tmpbuf, sizeof(tmpbuf), "Report bugs to %s.\n", PACKAGE_BUGREPORT);
- strlcat(vers, tmpbuf, len);
+ xstrlcat(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);
+ xstrlcat(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);
+ xstrlcat(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);
+ xstrlcat(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);
+ xstrlcat(vers, tmpbuf, len);
xsnprintf(tmpbuf, sizeof(tmpbuf), "domain=%s, host=%s, hostd=%s.\n",
hostdomain, am_get_hostname(), hostd);
- strlcat(vers, tmpbuf, len);
+ xstrlcat(vers, tmpbuf, len);
- strlcat(vers, "Map support for: ", len);
+ xstrlcat(vers, "Map support for: ", len);
mapc_showtypes(tmpbuf, sizeof(tmpbuf));
- strlcat(vers, tmpbuf, len);
- strlcat(vers, ".\nAMFS: ", len);
+ xstrlcat(vers, tmpbuf, len);
+ xstrlcat(vers, ".\nAMFS: ", len);
ops_showamfstypes(tmpbuf, sizeof(tmpbuf));
- strlcat(vers, tmpbuf, len);
- strlcat(vers, ", inherit.\nFS: ", len); /* hack: "show" that we support type:=inherit */
+ xstrlcat(vers, tmpbuf, len);
+ xstrlcat(vers, ", inherit.\nFS: ", len); /* hack: "show" that we support type:=inherit */
ops_showfstypes(tmpbuf, sizeof(tmpbuf));
- strlcat(vers, tmpbuf, len);
+ xstrlcat(vers, tmpbuf, len);
/* append list of networks if available */
if (wire_buf) {
- strlcat(vers, wire_buf, len);
+ xstrlcat(vers, wire_buf, len);
XFREE(wire_buf);
}
@@ -331,19 +327,18 @@ get_args(int argc, char *argv[])
perror(buf);
exit(1);
}
- yyin = fp;
- yyparse();
+ conf_in = fp;
+ conf_parse();
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");
+ /* initialize debug options */
+ if (!debug_flags)
+ debug_flags = D_CONTROL; /* CONTROL = "daemon,amq,fork" */
#endif /* DEBUG */
/* log information regarding amd.conf file */
diff --git a/amd/info_exec.c b/amd/info_exec.c
index 8ccab9aee579..95216c90e2e9 100644
--- a/amd/info_exec.c
+++ b/amd/info_exec.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -52,8 +48,8 @@
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
+#include <sun_map.h>
-#define MAX_LINE_LEN 1500
/* forward declarations */
int exec_init(mnt_map *m, char *map, time_t *tp);
@@ -74,13 +70,13 @@ fgets_timed(char *s, int size, int rdfd, int secs)
if (!s || size < 0 || rdfd < 0)
return 0;
- s[0] = 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' */
+ s[i+1] = '\0'; /* places the requisite trailing '\0' */
/* ready for reading */
rval = read(rdfd, (void *)(s+i), 1);
@@ -114,7 +110,7 @@ fgets_timed(char *s, int size, int rdfd, int secs)
FD_ZERO(&fds);
FD_SET(rdfd, &fds);
- rval = select(rdfd+1, &fds, 0, 0, &timeo);
+ rval = select(rdfd+1, &fds, NULL, NULL, &timeo);
if (rval < 0) {
/* error selecting */
plog(XLOG_WARNING, "fgets_timed select error: %m");
@@ -165,9 +161,9 @@ read_line(char *buf, int size, int fd)
* 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)
+exec_parse_qanswer(mnt_map *m, int fd, char *map, char *key, char **pval, time_t *tp)
{
- char qanswer[MAX_LINE_LEN], *dc = 0;
+ char qanswer[INFO_MAX_LINE_LEN], *dc = NULL;
int chuck = 0;
int line_no = 0;
@@ -197,7 +193,7 @@ exec_parse_qanswer(int fd, char *map, char *key, char **pval, time_t *tp)
/*
* Find beginning of value (query answer)
*/
- for (cp = qanswer; *cp && !isascii((int)*cp) && !isspace((int)*cp); cp++)
+ for (cp = qanswer; *cp && !isascii((unsigned char)*cp) && !isspace((unsigned char)*cp); cp++)
;;
/* Ignore blank lines */
@@ -207,7 +203,10 @@ exec_parse_qanswer(int fd, char *map, char *key, char **pval, time_t *tp)
/*
* Return a copy of the data
*/
- dc = strdup(cp);
+ if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX))
+ dc = sun_entry2amd(key, cp);
+ else
+ dc = xstrdup(cp);
*pval = dc;
dlog("%s returns %s", key, dc);
@@ -324,7 +323,7 @@ exec_map_open(char *emap, char *key)
close(pdes[1]);
/* anti-zombie insurance */
- while (waitpid(p1,0,0) < 0)
+ while (waitpid(p1, 0, 0) < 0)
if (errno != EINTR)
exit(errno);
@@ -416,7 +415,7 @@ exec_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
if (tp)
*tp = clocktime(NULL);
- return exec_parse_qanswer(mapfd, map, key, pval, tp);
+ return exec_parse_qanswer(m, mapfd, map, key, pval, tp);
}
return errno;
diff --git a/amd/info_file.c b/amd/info_file.c
index 3777a2aebe94..738c7bfa5776 100644
--- a/amd/info_file.c
+++ b/amd/info_file.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -50,8 +46,8 @@
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
+#include <sun_map.h>
-#define MAX_LINE_LEN 1500
/* forward declarations */
int file_init_or_mtime(mnt_map *m, char *map, time_t *tp);
@@ -59,8 +55,8 @@ 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
+file_read_line(char *buf, int size, FILE *fp)
{
int done = 0;
@@ -79,7 +75,7 @@ read_line(char *buf, int size, FILE *fp)
* Skip leading white space on next line
*/
while ((ch = getc(fp)) != EOF &&
- isascii(ch) && isspace(ch)) ;
+ isascii((unsigned char)ch) && isspace((unsigned char)ch)) ;
(void) ungetc(ch, fp);
} else {
return done;
@@ -95,18 +91,18 @@ read_line(char *buf, int size, FILE *fp)
* Try to locate a key in a file
*/
static int
-file_search_or_reload(FILE *fp,
+file_search_or_reload(mnt_map *m,
+ FILE *fp,
char *map,
char *key,
char **val,
- mnt_map *m,
void (*fn) (mnt_map *m, char *, char *))
{
- char key_val[MAX_LINE_LEN];
+ char key_val[INFO_MAX_LINE_LEN];
int chuck = 0;
int line_no = 0;
- while (read_line(key_val, sizeof(key_val), fp)) {
+ while (file_read_line(key_val, sizeof(key_val), fp)) {
char *kp;
char *cp;
char *hash;
@@ -133,7 +129,7 @@ file_search_or_reload(FILE *fp,
/*
* Find start of key
*/
- for (kp = key_val; *kp && isascii(*kp) && isspace((int)*kp); kp++) ;
+ for (kp = key_val; *kp && isascii((unsigned char)*kp) && isspace((unsigned char)*kp); kp++) ;
/*
* Ignore blank lines
@@ -144,7 +140,7 @@ file_search_or_reload(FILE *fp,
/*
* Find end of key
*/
- for (cp = kp; *cp && (!isascii(*cp) || !isspace((int)*cp)); cp++) ;
+ for (cp = kp; *cp && (!isascii((unsigned char)*cp) || !isspace((unsigned char)*cp)); cp++) ;
/*
* Check whether key matches
@@ -153,15 +149,20 @@ file_search_or_reload(FILE *fp,
*cp++ = '\0';
if (fn || (*key == *kp && STREQ(key, kp))) {
- while (*cp && isascii(*cp) && isspace((int)*cp))
+ while (*cp && isascii((unsigned char)*cp) && isspace((unsigned char)*cp))
cp++;
if (*cp) {
/*
* Return a copy of the data
*/
- char *dc = strdup(cp);
+ char *dc;
+ /* if m->cfm == NULL, not using amd.conf file */
+ if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX))
+ dc = sun_entry2amd(kp, cp);
+ else
+ dc = xstrdup(cp);
if (fn) {
- (*fn) (m, strdup(kp), dc);
+ (*fn) (m, xstrdup(kp), dc);
} else {
*val = dc;
dlog("%s returns %s", key, dc);
@@ -221,10 +222,10 @@ 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 *))
{
- FILE *mapf = file_open(map, (time_t *) 0);
+ FILE *mapf = file_open(map, (time_t *) NULL);
if (mapf) {
- int error = file_search_or_reload(mapf, map, 0, 0, m, fn);
+ int error = file_search_or_reload(m, mapf, map, NULL, NULL, fn);
(void) fclose(mapf);
return error;
}
@@ -244,7 +245,7 @@ file_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
*tp = t;
error = -1;
} else {
- error = file_search_or_reload(mapf, map, key, pval, 0, 0);
+ error = file_search_or_reload(m, mapf, map, key, pval, NULL);
}
(void) fclose(mapf);
return error;
diff --git a/amd/info_hesiod.c b/amd/info_hesiod.c
index e345c9961508..0293f435a262 100644
--- a/amd/info_hesiod.c
+++ b/amd/info_hesiod.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -50,6 +46,7 @@
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
+#include <sun_map.h>
#define HES_PREFIX "hesiod."
#define HES_PREFLEN 7
@@ -127,7 +124,11 @@ hesiod_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
* it (and free subsequent replies)
*/
if (rvec && *rvec) {
- *pval = *rvec;
+ if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX)) {
+ *pval = sun_entry2amd(key, *rvec);
+ XFREE(*rvec);
+ } else
+ *pval = *rvec;
while (*++rvec)
XFREE(*rvec);
return 0;
diff --git a/amd/info_ldap.c b/amd/info_ldap.c
index 36ce1c8693d3..cfed6fd773d7 100644
--- a/amd/info_ldap.c
+++ b/amd/info_ldap.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -66,6 +62,7 @@
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
+#include <sun_map.h>
/*
@@ -118,12 +115,17 @@ struct he_ent {
struct he_ent *next;
};
+static ALD *ldap_connection;
+
/*
* FORWARD DECLARATIONS:
*/
static int amu_ldap_rebind(ALD *a);
static int get_ldap_timestamp(ALD *a, char *map, time_t *ts);
+int amu_ldap_init(mnt_map *m, char *map, time_t *tsu);
+int amu_ldap_search(mnt_map *m, char *map, char *key, char **pval, time_t *ts);
+int amu_ldap_mtime(mnt_map *m, char *map, time_t *ts);
/*
* FUNCTIONS:
@@ -144,30 +146,33 @@ string2he(char *s_orig)
{
char *c, *p;
char *s;
- HE_ENT *new, *old = NULL;
+ HE_ENT *first = NULL, *cur = NULL;
- if (NULL == s_orig || NULL == (s = strdup(s_orig)))
+ if (NULL == 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;
- }
+ s = xstrdup(s_orig);
+ for (p = strtok(s, ","); p; p = strtok(NULL, ",")) {
+ if (cur != NULL) {
+ cur->next = ALLOC(HE_ENT);
+ cur = cur->next;
+ } else
+ first = cur = ALLOC(HE_ENT);
+
+ cur->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);
-
+ cur->host = xstrdup(p);
+ cur->port = atoi(c);
+ } else {
+ cur->host = xstrdup(p);
+ cur->port = LDAP_PORT;
+ }
+ plog(XLOG_USER, "Adding ldap server %s:%d",
+ cur->host, cur->port);
}
XFREE(s);
- return (old);
+ return first;
}
@@ -248,10 +253,18 @@ amu_ldap_init(mnt_map *m, char *map, time_t *ts)
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"));
+ return ENOENT;
} else {
dlog("Map %s is ldap\n", map);
}
+#ifndef LDAP_CONNECTION_PER_MAP
+ if (ldap_connection != NULL) {
+ m->map_data = (void *) ldap_connection;
+ return 0;
+ }
+#endif
+
aldh = ALLOC(ALD);
creds = ALLOC(CR);
aldh->ldap = NULL;
@@ -274,11 +287,14 @@ amu_ldap_init(mnt_map *m, char *map, time_t *ts)
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))
+ if (get_ldap_timestamp(aldh, map, ts)) {
+ ald_free(aldh);
return (ENOENT);
+ }
dlog("Got timestamp for map %s: %ld\n", map, (u_long) *ts);
+ ldap_connection = aldh;
+ m->map_data = (void *) ldap_connection;
return (0);
}
@@ -312,7 +328,7 @@ amu_ldap_rebind(ALD *a)
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;
+ continue;
}
#if LDAP_VERSION_MAX > LDAP_VERSION2
/* handle LDAPv3 and heigher, if available and amd.conf-igured */
@@ -321,16 +337,16 @@ amu_ldap_rebind(ALD *a)
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;
+ plog(XLOG_WARNING, "Unable to set ldap protocol version to %ld for "
+ "%s:%d\n", gopt.ldap_proto_version, h->host, h->port);
+ continue;
}
}
#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;
+ continue;
}
if (gopt.ldap_cache_seconds > 0) {
#if defined(HAVE_LDAP_ENABLE_CACHE) && defined(HAVE_EXTERN_LDAP_ENABLE_CACHE)
@@ -541,7 +557,10 @@ amu_ldap_search(mnt_map *m, char *map, char *key, char **pval, time_t *ts)
}
dlog("Map %s, %s => %s\n", map, key, vals[0]);
if (vals[0]) {
- *pval = strdup(vals[0]);
+ if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX))
+ *pval = sun_entry2amd(key, vals[0]);
+ else
+ *pval = xstrdup(vals[0]);
err = 0;
} else {
plog(XLOG_USER, "Empty value for %s in map %s\n", key, map);
diff --git a/amd/info_ndbm.c b/amd/info_ndbm.c
index 8a52ba9e201d..5f2f52b5330e 100644
--- a/amd/info_ndbm.c
+++ b/amd/info_ndbm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -50,6 +46,7 @@
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
+#include <sun_map.h>
/* forward declarations */
int ndbm_init(mnt_map *m, char *map, time_t *tp);
@@ -58,7 +55,7 @@ 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)
+search_ndbm(mnt_map *m, DBM *db, char *key, char **val)
{
datum k, v;
@@ -66,7 +63,10 @@ search_ndbm(DBM *db, char *key, char **val)
k.dsize = strlen(key) + 1;
v = dbm_fetch(db, k);
if (v.dptr) {
- *val = strdup(v.dptr);
+ if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX))
+ *val = sun_entry2amd(key, v.dptr);
+ else
+ *val = xstrdup(v.dptr);
return 0;
}
return ENOENT;
@@ -95,7 +95,7 @@ ndbm_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
*tp = stb.st_mtime;
error = -1;
} else {
- error = search_ndbm(db, key, pval);
+ error = search_ndbm(m, db, key, pval);
}
(void) dbm_close(db);
return error;
diff --git a/amd/info_nis.c b/amd/info_nis.c
index bcb87d5d02aa..83dc4b7a84fc 100644
--- a/amd/info_nis.c
+++ b/amd/info_nis.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -50,6 +46,7 @@
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
+#include <sun_map.h>
/*
@@ -109,7 +106,7 @@ determine_nis_domain(void)
plog(XLOG_WARNING, "NIS domain name is not set. NIS ignored.");
return ENOENT;
}
- gopt.nis_domain = strdup(default_domain);
+ gopt.nis_domain = xstrdup(default_domain);
return 0;
}
@@ -167,6 +164,7 @@ nis_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
cbinfo.data = (voidp) &data;
cbinfo.foreach = (ypall_callback_fxn_t) callback;
+ plog(XLOG_INFO, "NIS map %s reloading using yp_all", map);
/*
* 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
@@ -247,7 +245,7 @@ nis_isup(mnt_map *m, char *map)
* Try to locate a key using NIS.
*/
int
-nis_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
+nis_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
{
int outlen;
int res;
@@ -301,7 +299,15 @@ nis_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
/*
* Lookup key
*/
- res = yp_match(gopt.nis_domain, map, key, strlen(key), val, &outlen);
+ res = yp_match(gopt.nis_domain, map, key, strlen(key), pval, &outlen);
+ if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX) && res == 0) {
+ char *oldval = *pval;
+ *pval = sun_entry2amd(key, oldval);
+ /* We always need to free the output of the yp_match call. */
+ XFREE(oldval);
+ if (*pval == NULL)
+ return -1; /* sun2amd parser error */
+ }
/*
* Do something interesting with the return code
diff --git a/amd/info_nisplus.c b/amd/info_nisplus.c
index d392b48fed6a..79df83614700 100644
--- a/amd/info_nisplus.c
+++ b/amd/info_nisplus.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -50,6 +46,7 @@
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
+#include <sun_map.h>
#define NISPLUS_KEY "key="
#define NISPLUS_ORGDIR ".org_dir"
@@ -221,7 +218,12 @@ nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
if (value != NULL)
data.value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
}
- *val = data.value;
+
+ if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX)) {
+ *val = sun_entry2amd(key, data.value);
+ XFREE(data.value); /* strnsave malloc'ed it above */
+ } else
+ *val = data.value;
if (*val) {
error = 0;
diff --git a/amd/info_passwd.c b/amd/info_passwd.c
index c8bf388b1d65..3c4486693c60 100644
--- a/amd/info_passwd.c
+++ b/amd/info_passwd.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -94,11 +90,11 @@ 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)
{
- char *dir = 0;
+ char *dir = NULL;
struct passwd *pw;
if (STREQ(key, "/defaults")) {
- *pval = strdup("type:=nfs");
+ *pval = xstrdup("type:=nfs");
return 0;
}
pw = getpwnam(key);
@@ -123,7 +119,7 @@ passwd_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
char *p, *q;
char val[MAXPATHLEN];
char rhost[MAXHOSTNAMELEN];
- dir = strdup(pw->pw_dir);
+ dir = xstrdup(pw->pw_dir);
/*
* Find user name. If no / then Invalid...
@@ -180,13 +176,12 @@ passwd_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
dlog("passwd_search: map=%s key=%s -> %s", map, key, val);
if (q)
*q = '.';
- *pval = strdup(val);
+ *pval = xstrdup(val);
return 0;
}
enoent:
- if (dir)
- XFREE(dir);
+ XFREE(dir);
return ENOENT;
}
diff --git a/amd/info_sun.c b/amd/info_sun.c
new file mode 100644
index 000000000000..3f56965ff747
--- /dev/null
+++ b/amd/info_sun.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1997-2014 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. 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_sun.c
+ *
+ */
+
+/*
+ * Get info from Sun automount-style /etc/auto_master, possibly following
+ * into multiple info services (via /etc/nsswitch.conf).
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amd.h>
+#include <sun_map.h>
+
+
+/* XXX: just a placeholder. fill in */
diff --git a/amd/info_union.c b/amd/info_union.c
index 8f0631c64ac9..df480317bddf 100644
--- a/amd/info_union.c
+++ b/amd/info_union.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -77,7 +73,7 @@ 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)
{
- char *mapd = strdup(map + UNION_PREFLEN);
+ char *mapd = xstrdup(map + UNION_PREFLEN);
char **v = strsplit(mapd, ':', '\"');
char **p;
size_t l;
@@ -95,14 +91,15 @@ 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 *))
{
- char *mapd = strdup(map + UNION_PREFLEN);
+ static const char fseq[] = "fs:=";
+ char *mapd = xstrdup(map + UNION_PREFLEN);
char **v = strsplit(mapd, ':', '\"');
char **dir;
/*
* Add fake /defaults entry
*/
- (*fn) (m, strdup("/defaults"), strdup("type:=link;opts:=nounmount;sublink:=${key}"));
+ (*fn) (m, xstrdup("/defaults"), xstrdup("type:=link;opts:=nounmount;sublink:=${key}"));
for (dir = v; *dir; dir++) {
size_t l;
@@ -113,7 +110,7 @@ union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
plog(XLOG_USER, "Cannot read directory %s: %m", *dir);
continue;
}
- l = strlen(*dir) + 5;
+ l = strlen(*dir) + sizeof(fseq);
dlog("Reading directory %s...", *dir);
while ((dp = readdir(dirp))) {
@@ -125,8 +122,8 @@ union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
dlog("... gives %s", dp->d_name);
val = xmalloc(l);
- xsnprintf(val, l + 5, "fs:=%s", *dir);
- (*fn) (m, strdup(dp->d_name), val);
+ xsnprintf(val, l, "%s%s", fseq, *dir);
+ (*fn) (m, xstrdup(dp->d_name), val);
}
closedir(dirp);
}
@@ -135,11 +132,11 @@ union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
* Add wildcard entry
*/
{
- size_t l = strlen(*(dir-1)) + 5;
+ size_t l = strlen(*(dir-1)) + sizeof(fseq);
char *val = xmalloc(l);
- xsnprintf(val, l, "fs:=%s", *(dir-1));
- (*fn) (m, strdup("*"), val);
+ xsnprintf(val, l, "%s%s", fseq, *(dir-1));
+ (*fn) (m, xstrdup("*"), val);
}
XFREE(mapd);
XFREE(v);
diff --git a/amd/map.c b/amd/map.c
index 8696dfd6984d..fce8273e4ef6 100644
--- a/amd/map.c
+++ b/amd/map.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -69,7 +65,7 @@ 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 am_node **exported_ap = (am_node **) NULL;
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 */
@@ -190,7 +186,7 @@ am_node *
get_ap_child(am_node *mp, char *fname)
{
am_node *new_mp;
- mntfs *mf = mp->am_mnt;
+ mntfs *mf = mp->am_al->al_mnt;
/*
* Allocate a new map
@@ -280,7 +276,7 @@ exported_ap_free(am_node *mp)
/*
* Zero the slot pointer to avoid double free's
*/
- exported_ap[mp->am_mapno] = 0;
+ exported_ap[mp->am_mapno] = NULL;
/*
* Update the free and last_used indices
@@ -325,7 +321,7 @@ insert_am(am_node *mp, am_node *p_mp)
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)
+ if (p_mp->am_al->al_mnt->mf_flags & MFF_IS_AUTOFS)
mp->am_flags |= AMF_AUTOFS;
#endif /* HAVE_FS_AUTOFS */
}
@@ -408,13 +404,14 @@ 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_al = new_loc();
+ mp->am_alarray = NULL;
+ mp->am_name = xstrdup(dir);
+ mp->am_path = xstrdup(dir);
mp->am_gen = new_gen();
#ifdef HAVE_FS_AUTOFS
- mp->am_autofs_fh = 0;
+ mp->am_autofs_fh = NULL;
#endif /* HAVE_FS_AUTOFS */
mp->am_timeo = gopt.am_timeo;
@@ -430,6 +427,30 @@ init_map(am_node *mp, char *dir)
mp->am_stats.s_mtime = mp->am_fattr.na_atime.nt_seconds;
mp->am_dev = -1;
mp->am_rdev = -1;
+ mp->am_fd[0] = -1;
+ mp->am_fd[1] = -1;
+}
+
+
+void
+notify_child(am_node *mp, au_etype au_etype, int au_errno, int au_signal)
+{
+ amq_sync_umnt rv;
+ int err;
+
+ if (mp->am_fd[1] >= 0) { /* we have a child process */
+ rv.au_etype = au_etype;
+ rv.au_signal = au_signal;
+ rv.au_errno = au_errno;
+
+ err = write(mp->am_fd[1], &rv, sizeof(rv));
+ /* XXX: do something else on err? */
+ if (err < sizeof(rv))
+ plog(XLOG_INFO, "notify_child: write returned %d instead of %d.",
+ err, (int) sizeof(rv));
+ close(mp->am_fd[1]);
+ mp->am_fd[1] = -1;
+ }
}
@@ -442,25 +463,24 @@ 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);
+ if (mp->am_fd[1] != -1)
+ plog(XLOG_FATAL, "free_map: called prior to notifying the child for %s.",
+ mp->am_path);
+
+ XFREE(mp->am_link);
+ XFREE(mp->am_name);
+ XFREE(mp->am_path);
+ XFREE(mp->am_pref);
+ XFREE(mp->am_transp);
+
+ if (mp->am_al)
+ free_loc(mp->am_al);
+
+ if (mp->am_alarray) {
+ am_loc **temp_al;
+ for (temp_al = mp->am_alarray; *temp_al; temp_al++)
+ free_loc(*temp_al);
+ XFREE(mp->am_alarray);
}
#ifdef HAVE_FS_AUTOFS
@@ -480,8 +500,8 @@ find_ap_recursive(char *dir, am_node *mp)
if (STREQ(mp->am_path, dir))
return mp;
- if ((mp->am_mnt->mf_flags & MFF_MOUNTED) &&
- STREQ(mp->am_mnt->mf_mount, dir))
+ if ((mp->am_al->al_mnt->mf_flags & MFF_MOUNTED) &&
+ STREQ(mp->am_al->al_mnt->mf_mount, dir))
return mp;
mp2 = find_ap_recursive(dir, mp->am_osib);
@@ -518,37 +538,20 @@ find_ap(char *dir)
/*
- * 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)
+am_nfs_handle_t *
+get_root_nfs_fh(char *dir, am_nfs_handle_t *nfh)
{
- static am_nfs_fh nfh;
am_node *mp = get_root_ap(dir);
if (mp) {
- mp_to_fh(mp, &nfh);
- return &nfh;
+ if (nfs_dispatcher == nfs_program_2)
+ mp_to_fh(mp, &nfh->v2);
+ else
+ mp_to_fh3(mp, &nfh->v3);
+ return nfh;
}
/*
@@ -584,7 +587,8 @@ map_flush_srvr(fserver *fs)
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) {
+
+ if (mp && mp->am_al->al_mnt && mp->am_al->al_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;
@@ -608,7 +612,7 @@ mount_auto_node(char *dir, opaque_t arg)
am_node *mp = (am_node *) arg;
am_node *new_mp;
- new_mp = mp->am_mnt->mf_ops->lookup_child(mp, dir, &error, VLOOK_CREATE);
+ new_mp = mp->am_al->al_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.
@@ -616,7 +620,7 @@ mount_auto_node(char *dir, opaque_t arg)
*/
new_mp->am_gen = new_mp->am_fattr.na_fileid = 1;
- new_mp = mp->am_mnt->mf_ops->mount_child(new_mp, &error);
+ (void) mp->am_al->al_mnt->mf_ops->mount_child(new_mp, &error);
}
if (error > 0) {
@@ -647,7 +651,7 @@ mount_exported(void)
void
make_root_node(void)
{
- mntfs *root_mnt;
+ mntfs *root_mf;
char *rootmap = ROOT_MAP;
root_node = exported_ap_alloc();
@@ -659,24 +663,24 @@ make_root_node(void)
/*
* Allocate a new mounted filesystem
*/
- root_mnt = find_mntfs(&amfs_root_ops, (am_opts *) 0, "", rootmap, "", "", "");
+ root_mf = find_mntfs(&amfs_root_ops, (am_opts *) NULL, "", rootmap, "", "", "");
/*
* Replace the initial null reference
*/
- free_mntfs(root_node->am_mnt);
- root_node->am_mnt = root_mnt;
+ free_mntfs(root_node->am_al->al_mnt);
+ root_node->am_al->al_mnt = root_mf;
/*
* Initialize the root
*/
- if (root_mnt->mf_ops->fs_init)
- (*root_mnt->mf_ops->fs_init) (root_mnt);
+ if (root_mf->mf_ops->fs_init)
+ (*root_mf->mf_ops->fs_init) (root_mf);
/*
* Mount the root
*/
- root_mnt->mf_error = root_mnt->mf_ops->mount_fs(root_node, root_mnt);
+ root_mf->mf_error = root_mf->mf_ops->mount_fs(root_node, root_mf);
}
@@ -687,68 +691,81 @@ make_root_node(void)
void
umount_exported(void)
{
- int i;
+ int i, work_done;
- for (i = last_used_map; i >= 0; --i) {
- am_node *mp = exported_ap[i];
- mntfs *mf;
+ do {
+ work_done = 0;
- if (!mp)
- continue;
+ for (i = last_used_map; i >= 0; --i) {
+ am_node *mp = exported_ap[i];
+ mntfs *mf;
- 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 (!mp)
+ continue;
- if (!(mf->mf_fsflags & FS_DIRECTORY))
/*
- * When shutting down this had better
- * look like a directory, otherwise it
- * can't be unmounted!
+ * Wait for children to be removed first
*/
- mk_fattr(&mp->am_fattr, NFDIR);
+ if (mp->am_child)
+ continue;
- if ((--immediate_abort < 0 &&
- !(mp->am_flags & AMF_ROOT) && mp->am_parent) ||
- (mf->mf_flags & MFF_RESTART)) {
+ mf = mp->am_al->al_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)) {
+
+ work_done++;
- /*
- * 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.
+ * 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...
*/
- unmount_mp((opaque_t) mp);
+ 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);
+ }
+ if (!(mf->mf_flags && (MFF_UNMOUNTING|MFF_MOUNTED)))
+ exported_ap[i] = NULL;
} else {
- am_unmounted(mp);
+ /*
+ * Any other node gets forcibly timed out.
+ */
+ mp->am_flags &= ~AMF_NOTIMEOUT;
+ mp->am_al->al_mnt->mf_flags &= ~MFF_RSTKEEP;
+ mp->am_ttl = 0;
+ mp->am_timeo = 1;
+ mp->am_timeo_w = 0;
}
- 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;
}
- }
+ } while (work_done);
}
@@ -762,7 +779,7 @@ int
mount_node(opaque_t arg)
{
am_node *mp = (am_node *) arg;
- mntfs *mf = mp->am_mnt;
+ mntfs *mf = mp->am_al->al_mnt;
int error = 0;
#ifdef HAVE_FS_AUTOFS
@@ -784,7 +801,7 @@ static int
unmount_node(opaque_t arg)
{
am_node *mp = (am_node *) arg;
- mntfs *mf = mp->am_mnt;
+ mntfs *mf = mp->am_al->al_mnt;
int error = 0;
if (mf->mf_flags & MFF_ERROR) {
@@ -805,7 +822,7 @@ unmount_node(opaque_t arg)
}
/* do this again, it might have changed */
- mf = mp->am_mnt;
+ mf = mp->am_al->al_mnt;
if (error) {
errno = error; /* XXX */
dlog("%s: unmount: %m", mf->mf_mount);
@@ -819,7 +836,7 @@ static void
free_map_if_success(int rc, int term, opaque_t arg)
{
am_node *mp = (am_node *) arg;
- mntfs *mf = mp->am_mnt;
+ mntfs *mf = mp->am_al->al_mnt;
wchan_t wchan = get_mntfs_wchan(mf);
/*
@@ -836,6 +853,7 @@ free_map_if_success(int rc, int term, opaque_t arg)
reschedule_timeout_mp();
}
if (term) {
+ notify_child(mp, AMQ_UMNT_SIGNAL, 0, term);
plog(XLOG_ERROR, "unmount for %s got signal %d", mp->am_path, term);
#if defined(DEBUG) && defined(SIGTRAP)
/*
@@ -852,18 +870,24 @@ free_map_if_success(int rc, int term, opaque_t arg)
#endif /* HAVE_FS_AUTOFS */
amd_stats.d_uerr++;
} else if (rc) {
+ notify_child(mp, AMQ_UMNT_FAILED, rc, 0);
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);
+ if (rc != ENOENT) {
+ 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() will call notify_child() appropriately.
+ */
am_unmounted(mp);
}
@@ -878,11 +902,11 @@ int
unmount_mp(am_node *mp)
{
int was_backgrounded = 0;
- mntfs *mf = mp->am_mnt;
+ mntfs *mf = mp->am_al->al_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);
+ mp->am_path, mf->mf_mount, (int) mf->mf_flags);
#endif /* notdef */
#ifndef MNT2_NFS_OPT_SYMTTL
@@ -914,10 +938,11 @@ unmount_mp(am_node *mp)
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;
}
+ notify_child(mp, AMQ_UMNT_SERVER, 0, 0);
return 0;
}
- dlog("\"%s\" on %s timed out", mp->am_path, mp->am_mnt->mf_mount);
+ dlog("\"%s\" on %s timed out", mp->am_path, mf->mf_mount);
mf->mf_flags |= MFF_UNMOUNTING;
#ifdef HAVE_FS_AUTOFS
@@ -926,7 +951,8 @@ unmount_mp(am_node *mp)
#endif /* HAVE_FS_AUTOFS */
if ((mf->mf_fsflags & FS_UBACKGROUND) &&
- (mf->mf_flags & MFF_MOUNTED)) {
+ (mf->mf_flags & MFF_MOUNTED) &&
+ !(mf->mf_flags & MFF_ON_AUTOFS)) {
dlog("Trying unmount in background");
run_task(unmount_node, (opaque_t) mp,
free_map_if_success, (opaque_t) mp);
@@ -964,7 +990,7 @@ timeout_mp(opaque_t v) /* argument not used?! */
/*
* Pick up mounted filesystem
*/
- mf = mp->am_mnt;
+ mf = mp->am_al->al_mnt;
if (!mf)
continue;
@@ -1056,7 +1082,7 @@ timeout_mp(opaque_t v) /* argument not used?! */
t = now + 1;
dlog("Next mount timeout in %lds", (long) (t - now));
- timeout_mp_id = timeout(t - now, timeout_mp, 0);
+ timeout_mp_id = timeout(t - now, timeout_mp, NULL);
}
@@ -1068,5 +1094,5 @@ reschedule_timeout_mp(void)
{
if (timeout_mp_id)
untimeout(timeout_mp_id);
- timeout_mp_id = timeout(0, timeout_mp, 0);
+ timeout_mp_id = timeout(0, timeout_mp, NULL);
}
diff --git a/amd/mapc.c b/amd/mapc.c
index d7efdbcfd217..cd4b9b956a05 100644
--- a/amd/mapc.c
+++ b/amd/mapc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -96,7 +92,7 @@ static struct opt_tab mapc_opt[] =
{"regexp", MAPC_RE},
#endif /* HAVE_REGEXEC */
{"sync", MAPC_SYNC},
- {0, 0}
+ {NULL, 0}
};
/*
@@ -137,6 +133,7 @@ static const char *get_full_path(const char *map, const char *path, const char *
static int mapc_meta_search(mnt_map *, char *, char **, int);
static void mapc_sync(mnt_map *);
static void mapc_clear(mnt_map *);
+static void mapc_clear_kvhash(kv **);
/* ROOT MAP */
static int root_init(mnt_map *, char *, time_t *);
@@ -198,12 +195,6 @@ 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 *);
@@ -211,6 +202,16 @@ extern int file_reload(mnt_map *, char *, add_fn *);
extern int file_search(mnt_map *, char *, char *, char **, time_t *);
#endif /* HAVE_MAP_FILE */
+/* 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 */
+
+/* Sun-syntax MAPS */
+#ifdef HAVE_MAP_SUN
+/* XXX: fill in */
+#endif /* HAVE_MAP_SUN */
/* note that the choice of MAPC_{INC,ALL} will affect browsable_dirs */
static map_type maptypes[] =
@@ -323,6 +324,20 @@ static map_type maptypes[] =
MAPC_INC
},
#endif /* HAVE_MAP_EXEC */
+#ifdef notyet /* probe function needs to be there or SEGV */
+#ifdef HAVE_MAP_SUN
+ {
+ /* XXX: fill in */
+ "sun",
+ NULL,
+ NULL,
+ NULL, /* isup function */
+ NULL,
+ NULL,
+ 0
+ },
+#endif /* HAVE_MAP_SUN */
+#endif
{
"error",
error_init,
@@ -412,6 +427,44 @@ mapc_add_kv(mnt_map *m, char *key, char *val)
dlog("add_kv: %s -> %s", key, val);
+ if (val != NULL && strchr(val, '\n') != NULL) {
+ /*
+ * If the entry value contains multiple lines we need to break
+ * them up and add them recursively. This is a workaround to
+ * support Sun style multi-mounts. Amd converts Sun style
+ * mulit-mounts to type:=auto. The problem is that Sun packs all
+ * the entries on one line. When Amd does the conversion it puts
+ * each type:=auto entry on the same line separated by '\n'.
+ */
+ char *entry, *tok;
+
+ /*
+ * The first line should contain the first entry. The key for
+ * this entry is the key passed into this function.
+ */
+ if ((tok = strtok(val, "\n")) != NULL) {
+ mapc_add_kv(m, key, xstrdup(tok));
+ }
+
+ /*
+ * For the rest of the entries we need to tokenize them by '\n'
+ * and separate the keys from there entries.
+ */
+ while ((tok = strtok(NULL, "\n")) != NULL) {
+ key = tok;
+ /* find the entry */
+ for (entry = key; *entry && !isspace((unsigned char)*entry); entry++);
+ if (*entry) {
+ *entry++ = '\0';
+ }
+
+ mapc_add_kv(m, xstrdup(key), xstrdup(entry));
+ }
+
+ XFREE(val);
+ return;
+ }
+
#ifdef HAVE_REGEXEC
if (MAPC_ISRE(m)) {
char pattern[MAXPATHLEN];
@@ -431,7 +484,8 @@ mapc_add_kv(mnt_map *m, char *key, char *val)
plog(XLOG_USER, "error compiling RE \"%s\": %s", pattern, errstr);
return;
}
- }
+ } else
+ memset(&re, 0, sizeof(re));
#endif /* HAVE_REGEXEC */
h = &m->kvhash[hash];
@@ -443,6 +497,7 @@ mapc_add_kv(mnt_map *m, char *key, char *val)
n->val = val;
n->next = *h;
*h = n;
+ m->nentries++;
}
@@ -506,7 +561,7 @@ mapc_find_wildcard(mnt_map *m)
int rc = search_map(m, wildcard, &m->wildcard);
if (rc != 0)
- m->wildcard = 0;
+ m->wildcard = NULL;
}
@@ -520,7 +575,7 @@ static int
mapc_reload_map(mnt_map *m)
{
int error, ret = 0;
- kv *maphash[NKVHASH], *tmphash[NKVHASH];
+ kv *maphash[NKVHASH];
time_t t;
error = (*m->mtime) (m, m->map_name, &t);
@@ -546,6 +601,7 @@ mapc_reload_map(mnt_map *m)
memset((voidp) m->kvhash, 0, sizeof(m->kvhash));
dlog("calling map reload on %s", m->map_name);
+ m->nentries = 0;
error = (*m->reload) (m, m->map_name, mapc_add_kv);
if (error) {
if (m->reloads == 0)
@@ -561,19 +617,19 @@ mapc_reload_map(mnt_map *m)
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));
+ mapc_clear_kvhash(maphash);
+ if (m->wildcard) {
+ XFREE(m->wildcard);
+ m->wildcard = NULL;
+ }
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;
+ m->wildcard = NULL;
return ret;
}
@@ -582,12 +638,12 @@ mapc_reload_map(mnt_map *m)
* Create a new map
*/
static mnt_map *
-mapc_create(char *map, char *opt, const char *type)
+mapc_create(char *map, char *opt, const char *type, const char *mntpt)
{
mnt_map *m = ALLOC(struct mnt_map);
map_type *mt;
time_t modify = 0;
- int alloc = 0;
+ u_int alloc = 0;
cmdoption(opt, mapc_opt, &alloc);
@@ -632,6 +688,7 @@ mapc_create(char *map, char *opt, const char *type)
/* assert: mt in maptypes */
m->flags = alloc & ~MAPC_CACHE_MASK;
+ m->nentries = 0;
alloc &= MAPC_CACHE_MASK;
if (alloc == MAPC_DFLT)
@@ -678,12 +735,12 @@ mapc_create(char *map, char *opt, const char *type)
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->map_name = xstrdup(map);
m->refc = 1;
- m->wildcard = 0;
+ m->wildcard = NULL;
m->reloads = 0;
- /* Unfortunately with current code structure, this cannot be initialized here */
- m->cfm = NULL;
+ /* initialize per-map information (flags, etc.) */
+ m->cfm = find_cf_map(mntpt);
/*
* synchronize cache with reality
@@ -695,10 +752,10 @@ mapc_create(char *map, char *opt, const char *type)
/*
- * Free the cached data in a map
+ * Free the cached data in a map hash
*/
static void
-mapc_clear(mnt_map *m)
+mapc_clear_kvhash(kv **kvhash)
{
int i;
@@ -707,16 +764,25 @@ mapc_clear(mnt_map *m)
* along free'ing the data.
*/
for (i = 0; i < NKVHASH; i++) {
- kv *k = m->kvhash[i];
+ kv *k = kvhash[i];
while (k) {
kv *n = k->next;
XFREE(k->key);
- if (k->val)
- XFREE(k->val);
+ XFREE(k->val);
XFREE(k);
k = n;
}
}
+}
+
+
+/*
+ * Free the cached data in a map
+ */
+static void
+mapc_clear(mnt_map *m)
+{
+ mapc_clear_kvhash(m->kvhash);
/*
* Zero the hash slots
@@ -726,10 +792,10 @@ mapc_clear(mnt_map *m)
/*
* Free the wildcard if it exists
*/
- if (m->wildcard) {
- XFREE(m->wildcard);
- m->wildcard = 0;
- }
+ XFREE(m->wildcard);
+ m->wildcard = NULL;
+
+ m->nentries = 0;
}
@@ -737,7 +803,7 @@ mapc_clear(mnt_map *m)
* Find a map, or create one if it does not exist
*/
mnt_map *
-mapc_find(char *map, char *opt, const char *maptype)
+mapc_find(char *map, char *opt, const char *maptype, const char *mntpt)
{
mnt_map *m;
@@ -751,7 +817,7 @@ mapc_find(char *map, char *opt, const char *maptype)
ITER(m, mnt_map, &map_list_head)
if (STREQ(m->map_name, map))
return mapc_dup(m);
- m = mapc_create(map, opt, maptype);
+ m = mapc_create(map, opt, maptype, mntpt);
ins_que(&m->hdr, &map_list_head);
return m;
@@ -788,7 +854,7 @@ static int
mapc_meta_search(mnt_map *m, char *key, char **pval, int recurse)
{
int error = 0;
- kv *k = 0;
+ kv *k = NULL;
/*
* Firewall
@@ -839,7 +905,7 @@ mapc_meta_search(mnt_map *m, char *key, char **pval, int recurse)
int retval;
/* XXX: this code was recently ported, and must be tested -Erez */
- retval = regexec(&k->re, key, 0, 0, 0);
+ retval = regexec(&k->re, key, 0, NULL, 0);
if (retval == 0) { /* succeeded */
break;
} else { /* failed to match, log error */
@@ -863,7 +929,7 @@ mapc_meta_search(mnt_map *m, char *key, char **pval, int recurse)
*/
if (k) {
if (k->val)
- *pval = strdup(k->val);
+ *pval = xstrdup(k->val);
else
error = ENOENT;
} else if (m->alloc >= MAPC_ALL) {
@@ -880,7 +946,7 @@ mapc_meta_search(mnt_map *m, char *key, char **pval, int recurse)
*/
error = search_map(m, key, pval);
if (!error && m->alloc == MAPC_INC)
- mapc_add_kv(m, strdup(key), strdup(*pval));
+ mapc_add_kv(m, xstrdup(key), xstrdup(*pval));
}
/*
@@ -911,11 +977,11 @@ mapc_meta_search(mnt_map *m, char *key, char **pval, int recurse)
dlog("mapc recurses on %s", wildname);
error = mapc_meta_search(m, wildname, pval, MREC_PART);
if (error)
- *subp = 0;
+ *subp = '\0';
}
if (error > 0 && m->wildcard) {
- *pval = strdup(m->wildcard);
+ *pval = xstrdup(m->wildcard);
error = 0;
}
}
@@ -1031,7 +1097,7 @@ root_newmap(const char *dir, const char *opts, const char *map, const cf_map_t *
* First make sure we have a root map to talk about...
*/
if (!root_map)
- root_map = mapc_find(ROOT_MAP, "mapdefault", NULL);
+ root_map = mapc_find(ROOT_MAP, "mapdefault", NULL, NULL);
/*
* Then add the entry...
@@ -1071,7 +1137,7 @@ root_newmap(const char *dir, const char *opts, const char *map, const cf_map_t *
else
xstrlcpy(str, opts, sizeof(str));
}
- mapc_repl_kv(root_map, strdup((char *)dir), strdup(str));
+ mapc_repl_kv(root_map, xstrdup(dir), xstrdup(str));
}
diff --git a/amd/mntfs.c b/amd/mntfs.c
index 6021838425c0..a26ff8f553f6 100644
--- a/amd/mntfs.c
+++ b/amd/mntfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -52,6 +48,16 @@ qelem mfhead = {&mfhead, &mfhead};
int mntfs_allocated;
+am_loc *
+dup_loc(am_loc *loc)
+{
+ loc->al_refc++;
+ if (loc->al_mnt) {
+ dup_mntfs(loc->al_mnt);
+ }
+ return loc;
+}
+
mntfs *
dup_mntfs(mntfs *mf)
{
@@ -71,24 +77,27 @@ init_mntfs(mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *auto
{
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_fo = 0;
+ if (mo)
+ mf->mf_fo = copy_opts(mo);
+
+ mf->mf_mount = xstrdup(mp);
+ mf->mf_info = xstrdup(info);
+ mf->mf_auto = xstrdup(auto_opts);
+ mf->mf_mopts = xstrdup(mopts);
+ mf->mf_remopts = xstrdup(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;
+ mf->mf_private = NULL;
+ mf->mf_prfree = NULL;
if (ops->ffserver)
mf->mf_server = (*ops->ffserver) (mf);
else
- mf->mf_server = 0;
+ mf->mf_server = NULL;
}
@@ -138,7 +147,7 @@ locate_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, ch
}
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.
@@ -171,7 +180,7 @@ locate_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, ch
if (mf->mf_private && mf->mf_prfree) {
mf->mf_prfree(mf->mf_private);
- mf->mf_private = 0;
+ mf->mf_private = NULL;
}
fs = ops->ffserver ? (*ops->ffserver) (mf) : (fserver *) NULL;
@@ -202,26 +211,35 @@ find_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char
mntfs *
new_mntfs(void)
{
- return alloc_mntfs(&amfs_error_ops, (am_opts *) 0, "//nil//", ".", "", "", "");
+ return alloc_mntfs(&amfs_error_ops, (am_opts *) NULL, "//nil//", ".", "", "", "");
+}
+
+am_loc *
+new_loc(void)
+{
+ am_loc *loc = CALLOC(struct am_loc);
+ loc->al_fo = 0;
+ loc->al_mnt = new_mntfs();
+ loc->al_refc = 1;
+ return loc;
}
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_fo) {
+ free_opts(mf->mf_fo);
+ XFREE(mf->mf_fo);
+ }
+ XFREE(mf->mf_auto);
+ XFREE(mf->mf_mopts);
+ XFREE(mf->mf_remopts);
+ 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);
+ XFREE(mf->mf_mount);
/*
* Clean up the file server
@@ -255,6 +273,16 @@ discard_mntfs(voidp v)
--mntfs_allocated;
}
+static void
+discard_loc(voidp v)
+{
+ am_loc *loc = v;
+ if (loc->al_fo) {
+ free_opts(loc->al_fo);
+ XFREE(loc->al_fo);
+ }
+ XFREE(loc);
+}
void
flush_mntfs(void)
@@ -270,6 +298,23 @@ flush_mntfs(void)
}
}
+void
+free_loc(opaque_t arg)
+{
+ am_loc *loc = (am_loc *) arg;
+ dlog("free_loc %p", loc);
+
+ if (loc->al_refc <= 0) {
+ plog(XLOG_ERROR, "IGNORING free_loc for 0x%p", loc);
+ return;
+ }
+
+ if (loc->al_mnt)
+ free_mntfs(loc->al_mnt);
+ if (--loc->al_refc == 0) {
+ discard_loc(loc);
+ }
+}
void
free_mntfs(opaque_t arg)
@@ -356,7 +401,6 @@ realloc_mntfs(mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *a
if (mf->mf_ops != &amfs_error_ops &&
(mf->mf_flags & MFF_MOUNTED) &&
!FSRV_ISDOWN(mf->mf_server)) {
- mf->mf_fo = mo;
return mf;
}
diff --git a/amd/nfs_prot_svc.c b/amd/nfs_prot_svc.c
index 0dd6992cf9e7..cbde17274aea 100644
--- a/amd/nfs_prot_svc.c
+++ b/amd/nfs_prot_svc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -69,6 +65,7 @@ extern nfsstatfsres *nfsproc_statfs_2_svc(am_nfs_fh *, struct svc_req *);
/* global variables */
SVCXPRT *current_transp;
+dispatcher_t nfs_dispatcher = nfs_program_2;
/* typedefs */
typedef char *(*nfssvcproc_t)(voidp, struct svc_req *);
@@ -299,3 +296,193 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
going_down(1);
}
}
+
+void
+nfs_program_3(struct svc_req *rqstp, register SVCXPRT *transp)
+{
+ union {
+ am_GETATTR3args am_nfs3_getattr_3_arg;
+ am_SETATTR3args am_nfs3_setattr_3_arg;
+ am_LOOKUP3args am_nfs3_lookup_3_arg;
+ am_ACCESS3args am_nfs3_access_3_arg;
+ am_READLINK3args am_nfs3_readlink_3_arg;
+ am_READ3args am_nfs3_read_3_arg;
+ am_WRITE3args am_nfs3_write_3_arg;
+ am_CREATE3args am_nfs3_create_3_arg;
+ am_MKDIR3args am_nfs3_mkdir_3_arg;
+ am_SYMLINK3args am_nfs3_symlink_3_arg;
+ am_MKNOD3args am_nfs3_mknod_3_arg;
+ am_REMOVE3args am_nfs3_remove_3_arg;
+ am_RMDIR3args am_nfs3_rmdir_3_arg;
+ am_RENAME3args am_nfs3_rename_3_arg;
+ am_LINK3args am_nfs3_link_3_arg;
+ am_READDIR3args am_nfs3_readdir_3_arg;
+ am_READDIRPLUS3args am_nfs3_readdirplus_3_arg;
+ am_FSSTAT3args am_nfs3_fsstat_3_arg;
+ am_FSINFO3args am_nfs3_fsinfo_3_arg;
+ am_PATHCONF3args am_nfs3_pathconf_3_arg;
+ am_COMMIT3args am_nfs3_commit_3_arg;
+ } argument;
+ char *result;
+ xdrproc_t _xdr_argument, _xdr_result;
+ nfssvcproc_t local;
+
+ switch (rqstp->rq_proc) {
+ case AM_NFS3_NULL:
+ _xdr_argument = (xdrproc_t) xdr_void;
+ _xdr_result = (xdrproc_t) xdr_void;
+ local = (nfssvcproc_t) am_nfs3_null_3_svc;
+ break;
+
+ case AM_NFS3_GETATTR:
+ _xdr_argument = (xdrproc_t) xdr_am_GETATTR3args;
+ _xdr_result = (xdrproc_t) xdr_am_GETATTR3res;
+ local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_getattr_3_svc;
+ break;
+
+ case AM_NFS3_SETATTR:
+ _xdr_argument = (xdrproc_t) xdr_am_SETATTR3args;
+ _xdr_result = (xdrproc_t) xdr_am_SETATTR3res;
+ local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_setattr_3_svc;
+ break;
+
+ case AM_NFS3_LOOKUP:
+ _xdr_argument = (xdrproc_t) xdr_am_LOOKUP3args;
+ _xdr_result = (xdrproc_t) xdr_am_LOOKUP3res;
+ local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_lookup_3_svc;
+ break;
+
+ case AM_NFS3_ACCESS:
+ _xdr_argument = (xdrproc_t) xdr_am_ACCESS3args;
+ _xdr_result = (xdrproc_t) xdr_am_ACCESS3res;
+ local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_access_3_svc;
+ break;
+
+ case AM_NFS3_READLINK:
+ _xdr_argument = (xdrproc_t) xdr_am_READLINK3args;
+ _xdr_result = (xdrproc_t) xdr_am_READLINK3res;
+ local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_readlink_3_svc;
+ break;
+
+ case AM_NFS3_READ:
+ _xdr_argument = (xdrproc_t) xdr_am_READ3args;
+ _xdr_result = (xdrproc_t) xdr_am_READ3res;
+ local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_read_3_svc;
+ break;
+
+ case AM_NFS3_WRITE:
+ _xdr_argument = (xdrproc_t) xdr_am_WRITE3args;
+ _xdr_result = (xdrproc_t) xdr_am_WRITE3res;
+ local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_write_3_svc;
+ break;
+
+ case AM_NFS3_CREATE:
+ _xdr_argument = (xdrproc_t) xdr_am_CREATE3args;
+ _xdr_result = (xdrproc_t) xdr_am_CREATE3res;
+ local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_create_3_svc;
+ break;
+
+ case AM_NFS3_MKDIR:
+ _xdr_argument = (xdrproc_t) xdr_am_MKDIR3args;
+ _xdr_result = (xdrproc_t) xdr_am_MKDIR3res;
+ local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_mkdir_3_svc;
+ break;
+
+ case AM_NFS3_SYMLINK:
+ _xdr_argument = (xdrproc_t) xdr_am_SYMLINK3args;
+ _xdr_result = (xdrproc_t) xdr_am_SYMLINK3res;
+ local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_symlink_3_svc;
+ break;
+
+ case AM_NFS3_MKNOD:
+ _xdr_argument = (xdrproc_t) xdr_am_MKNOD3args;
+ _xdr_result = (xdrproc_t) xdr_am_MKNOD3res;
+ local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_mknod_3_svc;
+ break;
+
+ case AM_NFS3_REMOVE:
+ _xdr_argument = (xdrproc_t) xdr_am_REMOVE3args;
+ _xdr_result = (xdrproc_t) xdr_am_REMOVE3res;
+ local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_remove_3_svc;
+ break;
+
+ case AM_NFS3_RMDIR:
+ _xdr_argument = (xdrproc_t) xdr_am_RMDIR3args;
+ _xdr_result = (xdrproc_t) xdr_am_RMDIR3res;
+ local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_rmdir_3_svc;
+ break;
+
+ case AM_NFS3_RENAME:
+ _xdr_argument = (xdrproc_t) xdr_am_RENAME3args;
+ _xdr_result = (xdrproc_t) xdr_am_RENAME3res;
+ local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_rename_3_svc;
+ break;
+
+ case AM_NFS3_LINK:
+ _xdr_argument = (xdrproc_t) xdr_am_LINK3args;
+ _xdr_result = (xdrproc_t) xdr_am_LINK3res;
+ local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_link_3_svc;
+ break;
+
+ case AM_NFS3_READDIR:
+ _xdr_argument = (xdrproc_t) xdr_am_READDIR3args;
+ _xdr_result = (xdrproc_t) xdr_am_READDIR3res;
+ local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_readdir_3_svc;
+ break;
+
+ case AM_NFS3_READDIRPLUS:
+ _xdr_argument = (xdrproc_t) xdr_am_READDIRPLUS3args;
+ _xdr_result = (xdrproc_t) xdr_am_READDIRPLUS3res;
+ local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_readdirplus_3_svc;
+ break;
+
+ case AM_NFS3_FSSTAT:
+ _xdr_argument = (xdrproc_t) xdr_am_FSSTAT3args;
+ _xdr_result = (xdrproc_t) xdr_am_FSSTAT3res;
+ local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_fsstat_3_svc;
+ break;
+
+ case AM_NFS3_FSINFO:
+ _xdr_argument = (xdrproc_t) xdr_am_FSINFO3args;
+ _xdr_result = (xdrproc_t) xdr_am_FSINFO3res;
+ local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_fsinfo_3_svc;
+ break;
+
+ case AM_NFS3_PATHCONF:
+ _xdr_argument = (xdrproc_t) xdr_am_PATHCONF3args;
+ _xdr_result = (xdrproc_t) xdr_am_PATHCONF3res;
+ local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_pathconf_3_svc;
+ break;
+
+ case AM_NFS3_COMMIT:
+ _xdr_argument = (xdrproc_t) xdr_am_COMMIT3args;
+ _xdr_result = (xdrproc_t) xdr_am_COMMIT3res;
+ local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_commit_3_svc;
+ break;
+
+ default:
+ svcerr_noproc (transp);
+ return;
+ }
+
+ memset ((char *)&argument, 0, sizeof (argument));
+
+ if (!svc_getargs(transp, (xdrproc_t) _xdr_argument, (caddr_t) &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);
+ if (result != NULL && !svc_sendreply(transp, (xdrproc_t) _xdr_result, result)) {
+ svcerr_systemerr (transp);
+ }
+
+ if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) {
+ plog(XLOG_FATAL, "unable to free rpc arguments in nfs_program_3");
+ going_down(1);
+ }
+ return;
+}
diff --git a/amd/nfs_start.c b/amd/nfs_start.c
index f6aba94e2b6d..b6c544ddf178 100644
--- a/amd/nfs_start.c
+++ b/amd/nfs_start.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -65,12 +61,11 @@ u_short nfs_port = 0;
static void
checkup(void)
{
-
static int max_fd = 0;
- static char *max_mem = 0;
-
+ static char *max_mem = NULL;
int next_fd = dup(0);
caddr_t next_mem = sbrk(0);
+
close(next_fd);
if (max_fd < next_fd) {
@@ -135,8 +130,8 @@ do_select(int smask, int fds, fd_set *fdp, struct timeval *tvp)
/*
* Wait for input
*/
- nsel = select(fds, fdp, (fd_set *) 0, (fd_set *) 0,
- tvp->tv_sec ? tvp : (struct timeval *) 0);
+ nsel = select(fds, fdp, (fd_set *) NULL, (fd_set *) NULL,
+ tvp->tv_sec ? tvp : (struct timeval *) NULL);
}
#ifdef HAVE_SIGACTION
@@ -171,7 +166,7 @@ rpc_pending_now(void)
FD_SET(fwd_sock, &readfds);
tvv.tv_sec = tvv.tv_usec = 0;
- nsel = select(FD_SETSIZE, &readfds, (fd_set *) 0, (fd_set *) 0, &tvv);
+ nsel = select(FD_SETSIZE, &readfds, (fd_set *) NULL, (fd_set *) NULL, &tvv);
if (nsel < 1)
return (0);
if (FD_ISSET(fwd_sock, &readfds))
@@ -365,15 +360,16 @@ mount_automounter(int ppid)
* already created the service during restart_automounter_nodes().
*/
if (nfs_port == 0) {
- ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
+ ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_dispatcher,
+ get_nfs_dispatcher_version(nfs_dispatcher));
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)) {
+ /* security: if user sets -D noamq, don't even create listening socket */
+ if (amuDebug(D_AMQ)) {
ret = create_amq_service(&udp_soAMQ,
&udp_amqp,
&udp_amqncp,
@@ -416,25 +412,33 @@ mount_automounter(int ppid)
return 0;
}
- if (!amuDebug(D_AMQ)) {
+ 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());
+ int tcp_ok = 0, udp_ok = 0;
+
+ unregister_amq(); /* unregister leftover Amd, if any, just in case */
+
+ tcp_ok = amu_svc_register(tcp_amqp, get_amd_program_number(), AMQ_VERSION,
+ amq_program_1, IPPROTO_TCP, tcp_amqncp);
+ if (!tcp_ok)
+ plog(XLOG_FATAL,
+ "unable to register (AMQ_PROGRAM=%lu, AMQ_VERSION, tcp)",
+ get_amd_program_number());
+
+ udp_ok = amu_svc_register(udp_amqp, get_amd_program_number(), AMQ_VERSION,
+ amq_program_1, IPPROTO_UDP, udp_amqncp);
+ if (!udp_ok)
+ plog(XLOG_FATAL,
+ "unable to register (AMQ_PROGRAM=%lu, AMQ_VERSION, udp)",
+ get_amd_program_number());
+
+ /* return error only if both failed */
+ if (!tcp_ok && !udp_ok) {
+ amd_state = Done;
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;
- }
}
/*
diff --git a/amd/nfs_subr.c b/amd/nfs_subr.c
index 80d3ca8e311c..e463ff72c63a 100644
--- a/amd/nfs_subr.c
+++ b/amd/nfs_subr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -78,6 +74,17 @@ struct am_fh {
} u;
};
+struct am_fh3 {
+ 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[AM_FHSIZE3-sizeof(u_int)]; /* path to am_node */
+ } u;
+};
/* forward declarations */
/* converting am-filehandles to mount-points */
@@ -96,10 +103,10 @@ do_readlink(am_node *mp, int *error_return)
* otherwise if a link exists use that,
* otherwise use the mount point.
*/
- if (mp->am_mnt->mf_ops->readlink) {
+ if (mp->am_al->al_mnt->mf_ops->readlink) {
int retry = 0;
- mp = (*mp->am_mnt->mf_ops->readlink) (mp, &retry);
- if (mp == 0) {
+ mp = (*mp->am_al->al_mnt->mf_ops->readlink) (mp, &retry);
+ if (mp == NULL) {
*error_return = retry;
return 0;
}
@@ -109,7 +116,7 @@ do_readlink(am_node *mp, int *error_return)
if (mp->am_link) {
ln = mp->am_link;
} else {
- ln = mp->am_mnt->mf_mount;
+ ln = mp->am_al->al_mnt->mf_mount;
}
return ln;
@@ -130,14 +137,14 @@ nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
{
static nfsattrstat res;
am_node *mp;
- int retry;
+ int retry = 0;
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 (mp == NULL) {
if (amuDebug(D_TRACE))
plog(XLOG_DEBUG, "\tretry=%d", retry);
@@ -209,7 +216,7 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
xsnprintf(opt_gid, sizeof(gid_str), "%d", (int) gid);
mp = fh_to_mp3(&argp->da_fhandle, &retry, VLOOK_CREATE);
- if (mp == 0) {
+ if (mp == NULL) {
if (retry < 0) {
amd_stats.d_drops++;
return 0;
@@ -220,9 +227,9 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
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);
+ ap = mp->am_al->al_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);
+ ap = mp->am_al->al_mnt->mf_ops->mount_child(ap, &error);
if (ap == 0) {
if (error < 0) {
amd_stats.d_drops++;
@@ -285,7 +292,7 @@ nfs_quick_reply(am_node *mp, int error)
* 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);
+ dlog("Quick reply sent for %s", mp->am_al->al_mnt->mf_mount);
}
}
@@ -301,7 +308,7 @@ nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
plog(XLOG_DEBUG, "readlink:");
mp = fh_to_mp3(argp, &retry, VLOOK_CREATE);
- if (mp == 0) {
+ if (mp == NULL) {
readlink_retry:
if (retry < 0) {
amd_stats.d_drops++;
@@ -379,7 +386,7 @@ unlink_or_rmdir(nfsdiropargs *argp, struct svc_req *rqstp, int unlinkp)
int retry;
am_node *mp = fh_to_mp3(&argp->da_fhandle, &retry, VLOOK_DELETE);
- if (mp == 0) {
+ if (mp == NULL) {
if (retry < 0) {
amd_stats.d_drops++;
return 0;
@@ -396,8 +403,8 @@ unlink_or_rmdir(nfsdiropargs *argp, struct svc_req *rqstp, int unlinkp)
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) {
+ mp = mp->am_al->al_mnt->mf_ops->lookup_child(mp, argp->da_name, &retry, VLOOK_DELETE);
+ if (mp == NULL) {
/*
* Ignore retries...
*/
@@ -510,7 +517,7 @@ nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp)
plog(XLOG_DEBUG, "readdir:");
mp = fh_to_mp3(&argp->rda_fhandle, &retry, VLOOK_CREATE);
- if (mp == 0) {
+ if (mp == NULL) {
if (retry < 0) {
amd_stats.d_drops++;
return 0;
@@ -519,7 +526,7 @@ nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp)
} else {
if (amuDebug(D_TRACE))
plog(XLOG_DEBUG, "\treaddir(%s)", mp->am_path);
- res.rdr_status = nfs_error((*mp->am_mnt->mf_ops->readdir)
+ res.rdr_status = nfs_error((*mp->am_al->al_mnt->mf_ops->readdir)
(mp, argp->rda_cookie,
&res.rdr_u.rdr_reply_u, e_res, argp->rda_count));
mp->am_stats.s_readdir++;
@@ -541,7 +548,7 @@ nfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
plog(XLOG_DEBUG, "statfs:");
mp = fh_to_mp3(argp, &retry, VLOOK_CREATE);
- if (mp == 0) {
+ if (mp == NULL) {
if (retry < 0) {
amd_stats.d_drops++;
return 0;
@@ -562,8 +569,8 @@ nfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
/* 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;
+ mp->am_al->al_mnt && mp->am_al->al_mnt->mf_mopts) {
+ mnt.mnt_opts = mp->am_al->al_mnt->mf_mopts;
if (amu_hasmntopt(&mnt, "browsable")) {
count_map_entries(mp,
&fp->sfrok_blocks,
@@ -599,7 +606,7 @@ count_map_entries(const am_node *mp, u_int *out_blocks, u_int *out_bfree, u_int
blocks = bfree = bavail = 0;
if (!mp)
goto out;
- mf = mp->am_mnt;
+ mf = mp->am_al->al_mnt;
if (!mf)
goto out;
mmp = (mnt_map *) mf->mf_private;
@@ -625,58 +632,18 @@ out:
*out_bavail = bavail;
}
-
-/*
- * Convert from file handle to automount node.
- */
static am_node *
-fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop)
+validate_ap(am_node *node, int *rp, u_int fhh_gen)
{
- 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);
- }
-
+ am_node *ap = node;
/*
* 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 (node != NULL && node->am_gen != fhh_gen)
+ ap = NULL;
/*
* If it doesn't exists then drop the request
@@ -690,12 +657,12 @@ fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop)
* for it. This implements the replicated filesystem
* retries.
*/
- if (ap->am_mnt && FSRV_ISDOWN(ap->am_mnt->mf_server) && ap->am_parent) {
+ if (ap->am_al->al_mnt && FSRV_ISDOWN(ap->am_al->al_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);
+ dlog("%s: %s (%s) is hung: lookup alternative file server", __func__,
+ orig_ap->am_path, orig_ap->am_al->al_mnt->mf_info);
/*
* Update modify time of parent node.
@@ -712,11 +679,11 @@ fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop)
* 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);
+ ap = orig_ap->am_parent->am_al->al_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);
+ ap = orig_ap->am_parent->am_al->al_mnt->mf_ops->mount_child(ap, &error);
} else {
- ap = 0;
+ ap = NULL;
error = ESTALE;
}
if (ap == 0) {
@@ -735,13 +702,13 @@ fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop)
new_ttl(orig_ap);
}
-#endif
+#endif /* 0 */
/*
* Disallow references to objects being unmounted, unless
* they are automount points.
*/
- if (ap->am_mnt && (ap->am_mnt->mf_flags & MFF_UNMOUNTING) &&
+ if (ap->am_al->al_mnt && (ap->am_al->al_mnt->mf_flags & MFF_UNMOUNTING) &&
!(ap->am_flags & AMF_ROOT)) {
if (amd_state == Finishing)
*rp = ENOENT;
@@ -752,7 +719,7 @@ fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop)
new_ttl(ap);
drop:
- if (!ap || !ap->am_mnt) {
+ if (!ap || !ap->am_al->al_mnt) {
/*
* If we are shutting down then it is likely
* that this node has disappeared because of
@@ -764,14 +731,60 @@ drop:
*/
if (amd_state == Finishing)
*rp = ENOENT;
- else
+ else {
*rp = ESTALE;
- amd_stats.d_stale++;
+ amd_stats.d_stale++;
+ }
}
return ap;
}
+/*
+ * 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 = NULL;
+
+ 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("%s: new filehandle: %s", __func__, path);
+
+ ap = path_to_exported_ap(path);
+ XFREE(path);
+ } else {
+ dlog("%s: old filehandle: %d", __func__, 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("%s: wrong pid %ld != my pid %ld", __func__,
+ (long) fp->u.s.fhh_pid, get_server_pid());
+ goto done;
+ }
+
+ /*
+ * Get hold of the supposed mount node
+ */
+ ap = get_exported_ap(fp->u.s.fhh_id);
+ }
+done:
+ return validate_ap(ap, rp, fp->fhh_gen);
+}
static am_node *
fh_to_mp(am_nfs_fh *fhp)
@@ -781,6 +794,56 @@ fh_to_mp(am_nfs_fh *fhp)
return fh_to_mp3(fhp, &dummy, VLOOK_CREATE);
}
+static am_node *
+fh3_to_mp3(am_nfs_fh3 *fhp, int *rp, int vop)
+{
+ struct am_fh3 *fp = (struct am_fh3 *) fhp->am_fh3_data;
+ am_node *ap = NULL;
+
+ if (fp->u.s.fhh_type != 0) {
+ /* New filehandle type */
+ int len = sizeof(*fp) - 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("%s: new filehandle: %s", __func__, path);
+
+ ap = path_to_exported_ap(path);
+ XFREE(path);
+ } else {
+ dlog("%s: old filehandle: %d", __func__, 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("%s: wrong pid %ld != my pid %ld", __func__,
+ (long) fp->u.s.fhh_pid, get_server_pid());
+ goto done;
+ }
+
+ /*
+ * Get hold of the supposed mount node
+ */
+ ap = get_exported_ap(fp->u.s.fhh_id);
+ }
+done:
+ return validate_ap(ap, rp, fp->fhh_gen);
+}
+
+static am_node *
+fh3_to_mp(am_nfs_fh3 *fhp)
+{
+ int dummy;
+
+ return fh3_to_mp3(fhp, &dummy, VLOOK_CREATE);
+}
/*
* Convert from automount node to file handle.
@@ -826,3 +889,975 @@ mp_to_fh(am_node *mp, am_nfs_fh *fhp)
/* dlog("mp_to_fh: old filehandle: %d", fp->u.s.fhh_id); */
}
}
+void
+mp_to_fh3(am_node *mp, am_nfs_fh3 *fhp)
+{
+ u_int pathlen;
+ struct am_fh3 *fp = (struct am_fh3 *) fhp->am_fh3_data;
+
+ memset((char *) fhp, 0, sizeof(am_nfs_fh3));
+ fhp->am_fh3_length = AM_FHSIZE3;
+
+ /* Store the generation number */
+ fp->fhh_gen = mp->am_gen;
+
+ pathlen = strlen(mp->am_path);
+ if (pathlen <= sizeof(*fp) - 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); */
+ }
+}
+
+#ifdef HAVE_FS_NFS3
+static am_ftype3 ftype_to_ftype3(nfsftype ftype)
+{
+ if (ftype == NFFIFO)
+ return AM_NF3FIFO;
+ else
+ return ftype;
+}
+
+static void nfstime_to_am_nfstime3(nfstime *time, am_nfstime3 *time3)
+{
+ time3->seconds = time->seconds;
+ time3->nseconds = time->useconds * 1000;
+}
+
+static void rdev_to_am_specdata3(u_int rdev, am_specdata3 *rdev3)
+{
+ /* No device node here */
+ rdev3->specdata1 = (u_int) -1;
+ rdev3->specdata2 = (u_int) -1;
+}
+
+static void fattr_to_fattr3(nfsfattr *fattr, am_fattr3 *fattr3)
+{
+ fattr3->type = ftype_to_ftype3(fattr->na_type);
+ fattr3->mode = (am_mode3) fattr->na_mode;
+ fattr3->nlink = fattr->na_nlink;
+ fattr3->uid = (am_uid3) fattr->na_uid;
+ fattr3->gid = (am_uid3) fattr->na_gid;
+ fattr3->size = (am_size3) fattr->na_size;
+ fattr3->used = (am_size3) fattr->na_size;
+ rdev_to_am_specdata3(fattr->na_rdev, &fattr3->rdev);
+ fattr3->fsid = (uint64) fattr->na_fsid;
+ fattr3->fileid = (uint64) fattr->na_fileid;
+ nfstime_to_am_nfstime3(&fattr->na_atime, &fattr3->atime);
+ nfstime_to_am_nfstime3(&fattr->na_mtime, &fattr3->mtime);
+ nfstime_to_am_nfstime3(&fattr->na_ctime, &fattr3->ctime);
+}
+
+static void fattr_to_wcc_attr(nfsfattr *fattr, am_wcc_attr *wcc_attr)
+{
+ wcc_attr->size = (am_size3) fattr->na_size;
+ nfstime_to_am_nfstime3(&fattr->na_mtime, &wcc_attr->mtime);
+ nfstime_to_am_nfstime3(&fattr->na_ctime, &wcc_attr->ctime);
+}
+
+static am_nfsstat3 return_estale_or_rofs(am_nfs_fh3 *fh,
+ am_pre_op_attr *pre_op,
+ am_post_op_attr *post_op)
+{
+ am_node *mp;
+
+ mp = fh3_to_mp(fh);
+ if (!mp) {
+ pre_op->attributes_follow = 0;
+ post_op->attributes_follow = 0;
+ return nfs_error(ESTALE);
+ } else {
+ am_fattr3 *fattr3 = &post_op->am_post_op_attr_u.attributes;
+ am_wcc_attr *wcc_attr = &pre_op->am_pre_op_attr_u.attributes;
+ nfsfattr *fattr = &mp->am_fattr;
+ pre_op->attributes_follow = 1;
+ fattr_to_wcc_attr(fattr, wcc_attr);
+ post_op->attributes_follow = 1;
+ fattr_to_fattr3(fattr, fattr3);
+ return nfs_error(EROFS);
+ }
+}
+
+static am_nfsstat3 unlink3_or_rmdir3(am_diropargs3 *argp,
+ am_wcc_data *wcc_data, int unlinkp)
+{
+ static am_nfsstat3 res;
+ am_nfs_fh3 *dir = &argp->dir;
+ am_filename3 name = argp->name;
+ am_pre_op_attr *pre_op_dir = &wcc_data->before;
+ am_post_op_attr *post_op_dir = &wcc_data->after;
+ nfsfattr *fattr;
+ am_wcc_attr *wcc_attr;
+ am_node *mp, *ap;
+ int retry;
+
+ post_op_dir->attributes_follow = 0;
+
+ mp = fh3_to_mp3(dir, &retry, VLOOK_DELETE);
+ if (!mp) {
+ pre_op_dir->attributes_follow = 0;
+ if (retry < 0) {
+ amd_stats.d_drops++;
+ return 0;
+ }
+ res = nfs_error(retry);
+ goto out;
+ }
+
+ pre_op_dir->attributes_follow = 1;
+ fattr = &mp->am_fattr;
+ wcc_attr = &pre_op_dir->am_pre_op_attr_u.attributes;
+ fattr_to_wcc_attr(fattr, wcc_attr);
+
+ 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, name);
+
+ ap = mp->am_al->al_mnt->mf_ops->lookup_child(mp, name, &retry, VLOOK_DELETE);
+ if (!ap) {
+ /*
+ * 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 = AM_NFS3_OK;
+ }
+
+out:
+ return res;
+}
+
+voidp
+am_nfs3_null_3_svc(voidp argp, struct svc_req *rqstp)
+{
+ static char * result;
+
+ return (voidp) &result;
+}
+
+am_GETATTR3res *
+am_nfs3_getattr_3_svc(am_GETATTR3args *argp, struct svc_req *rqstp)
+{
+ static am_GETATTR3res result;
+ am_nfs_fh3 *fh = (am_nfs_fh3 *) &argp->object;
+ am_fattr3 *fattr3;
+ nfsfattr *fattr;
+ am_node *mp;
+ int retry = 0;
+ time_t now = clocktime(NULL);
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "getattr_3:");
+
+ mp = fh3_to_mp3(fh, &retry, VLOOK_CREATE);
+ if (!mp) {
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "\tretry=%d", retry);
+
+ if (retry < 0) {
+ amd_stats.d_drops++;
+ return 0;
+ }
+ result.status = nfs_error(retry);
+ return &result;
+ }
+
+ fattr = &mp->am_fattr;
+ fattr3 = (am_fattr3 *) &result.res_u.ok.obj_attributes;
+ fattr_to_fattr3(fattr, fattr3);
+
+ result.status = AM_NFS3_OK;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "\tstat(%s), size = %lu, mtime=%d.%d",
+ mp->am_path,
+ (am_size3) fattr3->size,
+ (u_int) fattr3->mtime.seconds,
+ (u_int) fattr3->mtime.nseconds);
+
+ /* 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 &result;
+}
+
+am_SETATTR3res *
+am_nfs3_setattr_3_svc(am_SETATTR3args *argp, struct svc_req *rqstp)
+{
+ static am_SETATTR3res result;
+ am_nfs_fh3 *fh = (am_nfs_fh3 *) &argp->object;
+ am_pre_op_attr *pre_op_obj = &result.res_u.fail.obj_wcc.before;
+ am_post_op_attr *post_op_obj = &result.res_u.fail.obj_wcc.after;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "setattr_3:");
+
+ result.status = return_estale_or_rofs(fh, pre_op_obj, post_op_obj);
+
+ return &result;
+}
+
+am_LOOKUP3res *
+am_nfs3_lookup_3_svc(am_LOOKUP3args *argp, struct svc_req *rqstp)
+{
+ static am_LOOKUP3res result;
+ am_nfs_fh3 *dir = &argp->what.dir;
+ am_post_op_attr *post_op_dir;
+ am_post_op_attr *post_op_obj;
+ am_node *mp;
+ int retry;
+ uid_t uid;
+ gid_t gid;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "lookup_3:");
+
+ /* 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 = fh3_to_mp3(dir, &retry, VLOOK_CREATE);
+ if (!mp) {
+ post_op_dir = &result.res_u.fail.dir_attributes;
+ post_op_dir->attributes_follow = 0;
+ if (retry < 0) {
+ amd_stats.d_drops++;
+ return 0;
+ }
+ result.status = nfs_error(retry);
+ } else {
+ post_op_dir = &result.res_u.ok.dir_attributes;
+ post_op_obj = &result.res_u.ok.obj_attributes;
+ am_filename3 name;
+ am_fattr3 *fattr3;
+ nfsfattr *fattr;
+ am_node *ap;
+ int error;
+
+ /* dir attributes */
+ post_op_dir->attributes_follow = 1;
+ fattr = &mp->am_fattr;
+ fattr3 = &post_op_dir->am_post_op_attr_u.attributes;
+ fattr_to_fattr3(fattr, fattr3);
+
+ post_op_obj->attributes_follow = 0;
+
+ name = argp->what.name;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "\tlookup_3(%s, %s)", mp->am_path, name);
+
+ ap = mp->am_al->al_mnt->mf_ops->lookup_child(mp, name, &error, VLOOK_CREATE);
+ if (ap && error < 0)
+ ap = mp->am_al->al_mnt->mf_ops->mount_child(ap, &error);
+ if (ap == 0) {
+ if (error < 0) {
+ amd_stats.d_drops++;
+ return 0;
+ }
+ result.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_fh3(ap, &result.res_u.ok.object);
+
+ /* mount attributes */
+ post_op_obj->attributes_follow = 1;
+ fattr = &ap->am_fattr;
+ fattr3 = &post_op_obj->am_post_op_attr_u.attributes;
+ fattr_to_fattr3(fattr, fattr3);
+
+ result.status = AM_NFS3_OK;
+ }
+ mp->am_stats.s_lookup++;
+ }
+ return &result;
+}
+
+am_ACCESS3res *
+am_nfs3_access_3_svc(am_ACCESS3args *argp, struct svc_req *rqstp)
+{
+ static am_ACCESS3res result;
+
+ am_nfs_fh3 *obj = &argp->object;
+ u_int accessbits = argp->access;
+ u_int accessmask = AM_ACCESS3_LOOKUP|AM_ACCESS3_READ;
+ am_post_op_attr *post_op_obj;
+ am_node *mp;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "access_3:");
+
+ mp = fh3_to_mp(obj);
+ if (!mp) {
+ post_op_obj = &result.res_u.fail.obj_attributes;
+ post_op_obj->attributes_follow = 0;
+ result.status = nfs_error(ENOENT);
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "access_3: ENOENT");
+ } else {
+ nfsfattr *fattr = &mp->am_fattr;
+ am_fattr3 *fattr3;
+ post_op_obj = &result.res_u.ok.obj_attributes;
+ fattr3 = &post_op_obj->am_post_op_attr_u.attributes;
+ post_op_obj->attributes_follow = 1;
+ fattr_to_fattr3(fattr, fattr3);
+
+ result.res_u.ok.access = accessbits & accessmask;
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "access_3: b=%x m=%x", accessbits, accessmask);
+
+ result.status = AM_NFS3_OK;
+ }
+
+ return &result;
+}
+
+am_READLINK3res *
+am_nfs3_readlink_3_svc(am_READLINK3args *argp, struct svc_req *rqstp)
+{
+ static am_READLINK3res result;
+
+ am_nfs_fh3 *symlink = (am_nfs_fh3 *) &argp->symlink;
+ am_post_op_attr *post_op_sym;
+ am_node *mp;
+ int retry = 0;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "readlink_3:");
+
+ mp = fh3_to_mp3(symlink, &retry, VLOOK_CREATE);
+ if (!mp) {
+ readlink_retry:
+ if (retry < 0) {
+ amd_stats.d_drops++;
+ return 0;
+ }
+ post_op_sym = &result.res_u.fail.symlink_attributes;
+ post_op_sym->attributes_follow = 0;
+ result.status = nfs_error(retry);
+ } else {
+ nfsfattr *fattr;
+ am_fattr3 *fattr3;
+ char *ln;
+
+ ln = do_readlink(mp, &retry);
+ if (!ln)
+ goto readlink_retry;
+
+ if (amuDebug(D_TRACE) && ln)
+ plog(XLOG_DEBUG, "\treadlink_3(%s) = %s", mp->am_path, ln);
+
+ result.res_u.ok.data = ln;
+
+ post_op_sym = &result.res_u.ok.symlink_attributes;
+ post_op_sym->attributes_follow = 1;
+ fattr = &mp->am_fattr;
+ fattr3 = &post_op_sym->am_post_op_attr_u.attributes;
+ fattr_to_fattr3(fattr, fattr3);
+
+ mp->am_stats.s_readlink++;
+ result.status = AM_NFS3_OK;
+ }
+
+ return &result;
+}
+
+am_READ3res *
+am_nfs3_read_3_svc(am_READ3args *argp, struct svc_req *rqstp)
+{
+ static am_READ3res result;
+
+ am_nfs_fh3 *file = (am_nfs_fh3 *) &argp->file;
+ am_post_op_attr *post_op_file;
+ am_node *mp;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "read_3:");
+
+ post_op_file = &result.res_u.fail.file_attributes;
+ result.status = nfs_error(EACCES);
+
+ mp = fh3_to_mp(file);
+ if (!mp)
+ post_op_file->attributes_follow = 0;
+ else {
+ nfsfattr *fattr = &mp->am_fattr;
+ am_fattr3 *fattr3 = &post_op_file->am_post_op_attr_u.attributes;
+ post_op_file->attributes_follow = 1;
+ fattr_to_fattr3(fattr, fattr3);
+ }
+
+ return &result;
+}
+
+am_WRITE3res *
+am_nfs3_write_3_svc(am_WRITE3args *argp, struct svc_req *rqstp)
+{
+ static am_WRITE3res result;
+
+ am_nfs_fh3 *file = (am_nfs_fh3 *) &argp->file;
+ am_pre_op_attr *pre_op_file = &result.res_u.fail.file_wcc.before;
+ am_post_op_attr *post_op_file = &result.res_u.fail.file_wcc.after;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "write_3:");
+
+ result.status = return_estale_or_rofs(file, pre_op_file, post_op_file);
+
+ return &result;
+}
+
+am_CREATE3res *
+am_nfs3_create_3_svc(am_CREATE3args *argp, struct svc_req *rqstp)
+{
+ static am_CREATE3res result;
+
+ am_nfs_fh3 *dir = (am_nfs_fh3 *) &argp->where.dir;
+ am_pre_op_attr *pre_op_dir = &result.res_u.fail.dir_wcc.before;
+ am_post_op_attr *post_op_dir = &result.res_u.fail.dir_wcc.after;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "create_3:");
+
+ result.status = return_estale_or_rofs(dir, pre_op_dir, post_op_dir);
+
+ return &result;
+}
+
+am_MKDIR3res *
+am_nfs3_mkdir_3_svc(am_MKDIR3args *argp, struct svc_req *rqstp)
+{
+ static am_MKDIR3res result;
+
+ am_nfs_fh3 *dir = (am_nfs_fh3 *) &argp->where.dir;
+ am_pre_op_attr *pre_op_dir = &result.res_u.fail.dir_wcc.before;
+ am_post_op_attr *post_op_dir = &result.res_u.fail.dir_wcc.after;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "mkdir_3:");
+
+ result.status = return_estale_or_rofs(dir, pre_op_dir, post_op_dir);
+
+ return &result;
+}
+
+am_SYMLINK3res *
+am_nfs3_symlink_3_svc(am_SYMLINK3args *argp, struct svc_req *rqstp)
+{
+ static am_SYMLINK3res result;
+
+ am_nfs_fh3 *dir = (am_nfs_fh3 *) &argp->where.dir;
+ am_pre_op_attr *pre_op_dir = &result.res_u.fail.dir_wcc.before;
+ am_post_op_attr *post_op_dir = &result.res_u.fail.dir_wcc.after;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "symlink_3:");
+
+ result.status = return_estale_or_rofs(dir, pre_op_dir, post_op_dir);
+
+ return &result;
+}
+
+am_MKNOD3res *
+am_nfs3_mknod_3_svc(am_MKNOD3args *argp, struct svc_req *rqstp)
+{
+ static am_MKNOD3res result;
+
+ am_nfs_fh3 *dir = (am_nfs_fh3 *) &argp->where.dir;
+ am_pre_op_attr *pre_op_dir = &result.res_u.fail.dir_wcc.before;
+ am_post_op_attr *post_op_dir = &result.res_u.fail.dir_wcc.after;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "mknod_3:");
+
+ result.status = return_estale_or_rofs(dir, pre_op_dir, post_op_dir);
+ return &result;
+}
+
+am_REMOVE3res *
+am_nfs3_remove_3_svc(am_REMOVE3args *argp, struct svc_req *rqstp)
+{
+ static am_REMOVE3res result;
+
+ am_diropargs3 *obj = &argp->object;
+ am_wcc_data dir_wcc;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "remove_3:");
+
+ result.status = unlink3_or_rmdir3(obj, &dir_wcc, TRUE);
+
+ result.res_u.ok.dir_wcc = dir_wcc;
+
+ return &result;
+}
+
+am_RMDIR3res *
+am_nfs3_rmdir_3_svc(am_RMDIR3args *argp, struct svc_req *rqstp)
+{
+ static am_RMDIR3res result;
+
+ am_diropargs3 *obj = &argp->object;
+ am_wcc_data dir_wcc;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "rmdir_3:");
+
+ result.status = unlink3_or_rmdir3(obj, &dir_wcc, TRUE);
+
+ result.res_u.ok.dir_wcc = dir_wcc;
+
+ return &result;
+}
+
+am_RENAME3res *
+am_nfs3_rename_3_svc(am_RENAME3args *argp, struct svc_req *rqstp)
+{
+ static am_RENAME3res result;
+
+ am_nfs_fh3 *fromdir = (am_nfs_fh3 *) &argp->from.dir;
+ am_nfs_fh3 *todir = (am_nfs_fh3 *) &argp->to.dir;
+ am_filename3 name = argp->to.name;
+ am_node *to_mp, *from_mp;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "rename_3:");
+
+ if (!(from_mp = fh3_to_mp(fromdir)) || !(to_mp = fh3_to_mp(todir)))
+ result.status = nfs_error(ESTALE);
+ /*
+ * If the kernel is doing clever things with referenced files
+ * then let it pretend...
+ */
+ else {
+ am_wcc_attr *wcc_attr;
+ am_fattr3 *fattr3;
+ am_wcc_data *to_wcc_data, *from_wcc_data;
+ am_pre_op_attr *pre_op_to, *pre_op_from;
+ am_post_op_attr *post_op_to, *post_op_from;
+ nfsfattr *fattr;
+
+ to_wcc_data = &result.res_u.ok.todir_wcc;
+
+ pre_op_to = &to_wcc_data->before;
+ post_op_to = &to_wcc_data->after;
+
+ pre_op_to->attributes_follow = 1;
+ fattr = &to_mp->am_fattr;
+ wcc_attr = &pre_op_to->am_pre_op_attr_u.attributes;
+ fattr_to_wcc_attr(fattr, wcc_attr);
+ post_op_to->attributes_follow = 1;
+ fattr3 = &post_op_to->am_post_op_attr_u.attributes;
+ fattr_to_fattr3(fattr, fattr3);
+
+ from_wcc_data = &result.res_u.ok.fromdir_wcc;
+
+ pre_op_from = &from_wcc_data->before;
+ post_op_from = &from_wcc_data->after;
+
+ pre_op_from->attributes_follow = 1;
+ fattr = &from_mp->am_fattr;
+ wcc_attr = &pre_op_from->am_pre_op_attr_u.attributes;
+ fattr_to_wcc_attr(fattr, wcc_attr);
+ post_op_from->attributes_follow = 1;
+ fattr3 = &post_op_from->am_post_op_attr_u.attributes;
+ fattr_to_fattr3(fattr, fattr3);
+
+ if (NSTREQ(name, ".nfs", 4))
+ result.status = AM_NFS3_OK;
+ /*
+ * otherwise a failure
+ */
+ else
+ result.status = nfs_error(EROFS);
+ }
+
+ return &result;
+}
+
+am_LINK3res *
+am_nfs3_link_3_svc(am_LINK3args *argp, struct svc_req *rqstp)
+{
+ static am_LINK3res result;
+
+ am_nfs_fh3 *file = (am_nfs_fh3 *) &argp->file;
+ am_nfs_fh3 *dir = (am_nfs_fh3 *) &argp->link.dir;
+ am_post_op_attr *post_op_file;
+ am_pre_op_attr *pre_op_dir;
+ am_post_op_attr *post_op_dir;
+ am_node *mp_file, *mp_dir;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "link_3:");
+
+ post_op_file = &result.res_u.fail.file_attributes;
+ post_op_file->attributes_follow = 0;
+
+ mp_file = fh3_to_mp(file);
+ if (mp_file) {
+ nfsfattr *fattr = &mp_file->am_fattr;
+ am_fattr3 *fattr3 = &post_op_file->am_post_op_attr_u.attributes;
+ fattr_to_fattr3(fattr, fattr3);
+ }
+
+ pre_op_dir = &result.res_u.fail.linkdir_wcc.before;
+ pre_op_dir->attributes_follow = 0;
+ post_op_dir = &result.res_u.fail.linkdir_wcc.after;
+ post_op_dir->attributes_follow = 0;
+
+ mp_dir = fh3_to_mp(dir);
+ if (mp_dir) {
+ nfsfattr *fattr = &mp_dir->am_fattr;
+ am_fattr3 *fattr3 = &post_op_dir->am_post_op_attr_u.attributes;
+ am_wcc_attr *wcc_attr = &pre_op_dir->am_pre_op_attr_u.attributes;
+
+ pre_op_dir->attributes_follow = 1;
+ fattr_to_wcc_attr(fattr, wcc_attr);
+ post_op_dir->attributes_follow = 1;
+ fattr_to_fattr3(fattr, fattr3);
+ }
+
+ if (!mp_file || !mp_dir)
+ result.status = nfs_error(ESTALE);
+ else
+ result.status = nfs_error(EROFS);
+
+ return &result;
+}
+
+am_READDIR3res *
+am_nfs3_readdir_3_svc(am_READDIR3args *argp, struct svc_req *rqstp)
+{
+ static am_READDIR3res result;
+ static am_entry3 entries[MAX_READDIR_ENTRIES];
+ am_nfs_fh3 *dir = (am_nfs_fh3 *) &argp->dir;
+ am_cookie3 cookie = argp->cookie;
+ am_cookieverf3 cookieverf;
+ am_count3 count = argp->count;
+ am_post_op_attr *post_op_dir;
+ am_node *mp;
+ int retry;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "readdir_3:");
+
+ memcpy(&cookieverf, &argp->cookieverf, sizeof(am_cookieverf3));
+
+ mp = fh3_to_mp3(dir, &retry, VLOOK_CREATE);
+ if (mp == NULL) {
+ if (retry < 0) {
+ amd_stats.d_drops++;
+ return 0;
+ }
+ post_op_dir = &result.res_u.fail.dir_attributes;
+ post_op_dir->attributes_follow = 0;
+ result.status = nfs_error(retry);
+ } else {
+ am_dirlist3 *list = &result.res_u.ok.reply;
+ am_nfsstat3 status;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "\treaddir_3(%s)", mp->am_path);
+
+ status = mp->am_al->al_mnt->mf_ops->readdir(mp,
+ (voidp)&cookie, list, entries, count);
+ if (status == 0) {
+ post_op_dir = &result.res_u.ok.dir_attributes;
+ nfsfattr *fattr;
+ am_fattr3 *fattr3;
+
+ fattr = &mp->am_fattr;
+ fattr3 = &post_op_dir->am_post_op_attr_u.attributes;
+ post_op_dir->attributes_follow = 1;
+ fattr_to_fattr3(fattr, fattr3);
+ result.status = AM_NFS3_OK;
+ } else {
+ post_op_dir = &result.res_u.fail.dir_attributes;
+ post_op_dir->attributes_follow = 0;
+ result.status = nfs_error(status);
+ }
+
+ mp->am_stats.s_readdir++;
+ }
+
+ return &result;
+}
+
+am_READDIRPLUS3res *
+am_nfs3_readdirplus_3_svc(am_READDIRPLUS3args *argp, struct svc_req *rqstp)
+{
+ static am_READDIRPLUS3res result;
+ am_nfs_fh3 *dir = (am_nfs_fh3 *) &argp->dir;
+ am_post_op_attr *post_op_dir;
+ nfsfattr *fattr;
+ am_fattr3 *fattr3;
+ am_node *mp;
+ int retry;
+
+ mp = fh3_to_mp3(dir, &retry, VLOOK_CREATE);
+ if (mp == NULL) {
+ if (retry < 0) {
+ amd_stats.d_drops++;
+ return 0;
+ }
+ post_op_dir = &result.res_u.fail.dir_attributes;
+ post_op_dir->attributes_follow = 0;
+ result.status = nfs_error(retry);
+ } else {
+ post_op_dir = &result.res_u.ok.dir_attributes;
+ fattr = &mp->am_fattr;
+ fattr3 = &post_op_dir->am_post_op_attr_u.attributes;
+ post_op_dir->attributes_follow = 1;
+ fattr_to_fattr3(fattr, fattr3);
+ result.status = AM_NFS3ERR_NOTSUPP;
+ }
+
+ return &result;
+}
+
+am_FSSTAT3res *
+am_nfs3_fsstat_3_svc(am_FSSTAT3args *argp, struct svc_req *rqstp)
+{
+ static am_FSSTAT3res result;
+
+ am_nfs_fh3 *fsroot = (am_nfs_fh3 *) &argp->fsroot;
+ am_post_op_attr *post_op_fsroot;
+ am_node *mp;
+ int retry;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "fsstat_3:");
+
+ mp = fh3_to_mp3(fsroot, &retry, VLOOK_CREATE);
+ if (!mp) {
+ if (retry < 0) {
+ amd_stats.d_drops++;
+ return 0;
+ }
+ post_op_fsroot = &result.res_u.fail.obj_attributes;
+ post_op_fsroot->attributes_follow = 0;
+ result.status = nfs_error(retry);
+ } else {
+ am_FSSTAT3resok *ok = &result.res_u.ok;
+ u_int blocks, bfree, bavail;
+ nfsfattr *fattr;
+ am_fattr3 *fattr3;
+ mntent_t mnt;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "\tfsstat_3(%s)", mp->am_path);
+
+ fattr = &mp->am_fattr;
+ post_op_fsroot = &ok->obj_attributes;
+ post_op_fsroot->attributes_follow = 1;
+ fattr3 = &post_op_fsroot->am_post_op_attr_u.attributes;
+ fattr_to_fattr3(fattr, fattr3);
+
+ /*
+ * just return faked up file system information
+ */
+ ok->tbytes = 1024;
+ ok->invarsec = 0;
+
+ /* check if map is browsable and show_statfs_entries=yes */
+ if ((gopt.flags & CFM_SHOW_STATFS_ENTRIES) &&
+ mp->am_al->al_mnt && mp->am_al->al_mnt->mf_mopts) {
+ mnt.mnt_opts = mp->am_al->al_mnt->mf_mopts;
+ if (amu_hasmntopt(&mnt, "browsable")) {
+ count_map_entries(mp, &blocks, &bfree, &bavail);
+ }
+ ok->fbytes = bfree;
+ ok->abytes = bavail;
+ ok->ffiles = bfree;
+ ok->afiles = bavail;
+ ok->tfiles = blocks;
+ } else {
+ ok->fbytes = 0;
+ ok->abytes = 0;
+ ok->ffiles = 0;
+ ok->afiles = 0;
+ ok->tfiles = 0; /* set to 1 if you don't want empty automounts */
+ }
+
+ result.status = AM_NFS3_OK;
+ mp->am_stats.s_statfs++;
+ }
+
+ return &result;
+}
+
+#define FSF3_HOMOGENEOUS 0x0008
+
+am_FSINFO3res *
+am_nfs3_fsinfo_3_svc(am_FSINFO3args *argp, struct svc_req *rqstp)
+{
+ static am_FSINFO3res result;
+
+ am_nfs_fh3 *fsroot = (am_nfs_fh3 *) &argp->fsroot;
+ am_post_op_attr *post_op_fsroot;
+ am_node *mp;
+ int retry;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "fsinfo_3:");
+
+ mp = fh3_to_mp3(fsroot, &retry, VLOOK_CREATE);
+ if (!mp) {
+ if (retry < 0) {
+ amd_stats.d_drops++;
+ return 0;
+ }
+ post_op_fsroot = &result.res_u.fail.obj_attributes;
+ post_op_fsroot->attributes_follow = 0;
+ result.status = nfs_error(retry);
+ } else {
+ am_FSINFO3resok *ok = &result.res_u.ok;
+ nfsfattr *fattr;
+ am_fattr3 *fattr3;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "\tfsinfo_3(%s)", mp->am_path);
+
+ fattr = &mp->am_fattr;
+ post_op_fsroot = &ok->obj_attributes;
+ post_op_fsroot->attributes_follow = 1;
+ fattr3 = &post_op_fsroot->am_post_op_attr_u.attributes;
+ fattr_to_fattr3(fattr, fattr3);
+
+ /*
+ * just return faked up file system information
+ */
+ ok->rtmax = 0;
+ ok->rtpref = 0;
+ ok->rtmult = 0;
+ ok->wtmax = 0;
+ ok->wtpref = 0;
+ ok->wtmult = 0;
+ ok->dtpref = 1024;
+ ok->maxfilesize = 0;
+ ok->time_delta.seconds = 1;
+ ok->time_delta.nseconds = 0;
+ ok->properties = FSF3_HOMOGENEOUS;
+
+ result.status = AM_NFS3_OK;
+ mp->am_stats.s_fsinfo++;
+ }
+
+ return &result;
+}
+
+am_PATHCONF3res *
+am_nfs3_pathconf_3_svc(am_PATHCONF3args *argp, struct svc_req *rqstp)
+{
+ static am_PATHCONF3res result;
+
+ am_nfs_fh3 *obj = (am_nfs_fh3 *) &argp->object;
+ am_post_op_attr *post_op_obj;
+ am_node *mp;
+ int retry;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "pathconf_3:");
+
+ mp = fh3_to_mp3(obj, &retry, VLOOK_CREATE);
+ if (!mp) {
+ if (retry < 0) {
+ amd_stats.d_drops++;
+ return 0;
+ }
+ post_op_obj = &result.res_u.fail.obj_attributes;
+ post_op_obj->attributes_follow = 0;
+ result.status = nfs_error(retry);
+ } else {
+ am_PATHCONF3resok *ok = &result.res_u.ok;
+ nfsfattr *fattr;
+ am_fattr3 *fattr3;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "\tpathconf_3(%s)", mp->am_path);
+
+ fattr = &mp->am_fattr;
+ post_op_obj = &ok->obj_attributes;
+ post_op_obj->attributes_follow = 1;
+ fattr3 = &post_op_obj->am_post_op_attr_u.attributes;
+ fattr_to_fattr3(fattr, fattr3);
+
+ ok->linkmax = 0;
+ ok->name_max = NAME_MAX;
+ ok->no_trunc = 1;
+ ok->chown_restricted = 1;
+ ok->case_insensitive = 0;
+ ok->case_preserving = 1;
+
+ result.status = AM_NFS3_OK;
+ mp->am_stats.s_pathconf++;
+ }
+
+ return &result;
+}
+
+am_COMMIT3res *
+am_nfs3_commit_3_svc(am_COMMIT3args *argp, struct svc_req *rqstp)
+{
+ static am_COMMIT3res result;
+
+ am_nfs_fh3 *file = (am_nfs_fh3 *) &argp->file;
+ am_pre_op_attr *pre_op_file = &result.res_u.fail.file_wcc.before;
+ am_post_op_attr *post_op_file = &result.res_u.fail.file_wcc.after;
+
+ if (amuDebug(D_TRACE))
+ plog(XLOG_DEBUG, "commit_3:");
+
+ result.status = return_estale_or_rofs(file, pre_op_file, post_op_file);
+
+ return &result;
+}
+#endif /* HAVE_FS_NFS3 */
diff --git a/amd/ops_TEMPLATE.c b/amd/ops_TEMPLATE.c
index 3f7421984412..b873c8ece271 100644
--- a/amd/ops_TEMPLATE.c
+++ b/amd/ops_TEMPLATE.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -64,7 +60,7 @@ 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 int foofs_readdir(am_node *mp, void cookie, voidp dp, voidp 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);
@@ -220,7 +216,7 @@ foofs_lookuppn(am_node *mp, char *fname, int *error_return, int op)
* 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)
+foofs_readdir(am_node *mp, void cookie, voidp dp, voidp ep, u_int count)
{
int error = 0;
diff --git a/amd/ops_autofs.c b/amd/ops_autofs.c
deleted file mode 100644
index bd0bb122fe03..000000000000
--- a/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/amd/ops_cachefs.c b/amd/ops_cachefs.c
index d3e303bc2bf9..26a333527457 100644
--- a/amd/ops_cachefs.c
+++ b/amd/ops_cachefs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -99,7 +95,7 @@ cachefs_match(am_opts *fo)
dlog("CACHEFS: using cache directory \"%s\"", fo->opt_cachedir);
/* determine magic cookie to put in mtab */
- return strdup(fo->opt_cachedir);
+ return xstrdup(fo->opt_cachedir);
}
@@ -114,7 +110,7 @@ cachefs_init(mntfs *mf)
* Save cache directory name
*/
if (!mf->mf_private) {
- mf->mf_private = (voidp) strdup(mf->mf_fo->opt_cachedir);
+ mf->mf_private = (voidp) xstrdup(mf->mf_fo->opt_cachedir);
mf->mf_prfree = (void (*)(voidp)) free;
}
diff --git a/amd/ops_cdfs.c b/amd/ops_cdfs.c
index 40355ac5c078..6ceb76408b03 100644
--- a/amd/ops_cdfs.c
+++ b/amd/ops_cdfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -97,7 +93,7 @@ cdfs_match(am_opts *fo)
/*
* Determine magic cookie to put in mtab
*/
- return strdup(fo->opt_dev);
+ return xstrdup(fo->opt_dev);
}
@@ -148,6 +144,7 @@ mount_cdfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
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;
@@ -157,11 +154,27 @@ mount_cdfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
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) */
+#if defined(MNT2_CDFS_OPT_NOCASETRANS) && defined(MNTTAB_OPT_NOCASETRANS)
+ if (amu_hasmntopt(&mnt, MNTTAB_OPT_NOCASETRANS))
+ cdfs_flags |= MNT2_CDFS_OPT_NOCASETRANS;
+#endif /* defined(MNT2_CDFS_OPT_NOCASETRANS) && defined(MNTTAB_OPT_NOCASETRANS) */
+
+#if defined(MNT2_CDFS_OPT_NOJOLIET) && defined(MNTTAB_OPT_NOJOLIET)
+ if (amu_hasmntopt(&mnt, MNTTAB_OPT_NOJOLIET))
+ cdfs_flags |= MNT2_CDFS_OPT_NOJOLIET;
+#endif /* defined(MNT2_CDFS_OPT_NOJOLIET) && defined(MNTTAB_OPT_NOJOLIET) */
+
+#if defined(MNT2_CDFS_OPT_RRCASEINS) && defined(MNTTAB_OPT_RRCASEINS)
+ if (amu_hasmntopt(&mnt, MNTTAB_OPT_RRCASEINS))
+ cdfs_flags |= MNT2_CDFS_OPT_RRCASEINS;
+#endif /* defined(MNT2_CDFS_OPT_RRCASEINS) && defined(MNTTAB_OPT_RRCASEINS) */
+
genflags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
if (on_autofs)
diff --git a/amd/ops_efs.c b/amd/ops_efs.c
index 047fe1e4690c..58bf8f0b76cb 100644
--- a/amd/ops_efs.c
+++ b/amd/ops_efs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -98,7 +94,7 @@ efs_match(am_opts *fo)
/*
* Determine magic cookie to put in mtab
*/
- return strdup(fo->opt_dev);
+ return xstrdup(fo->opt_dev);
}
@@ -137,6 +133,9 @@ mount_efs(char *mntdir, char *fs_name, char *opts, int on_autofs)
#ifdef HAVE_EFS_ARGS_T_FSPEC
efs_args.fspec = fs_name;
#endif /* HAVE_EFS_ARGS_T_FSPEC */
+#if defined(HAVE_EFS_ARGS_T_VERSION) && defined(EFS_MNT_VERSION)
+ efs_args.version = EFS_MNT_VERSION;
+#endif /* HAVE_EFS_ARGS_T_VERSION && EFS_MNT_VERSION */
/*
* Call generic mount routine
diff --git a/amd/ops_ext.c b/amd/ops_ext.c
new file mode 100644
index 000000000000..106ab31f3748
--- /dev/null
+++ b/amd/ops_ext.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 1997-2014 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. 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_ext.c
+ *
+ */
+
+/*
+ * Irix UN*X file system: EXT (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 *ext_match(am_opts *fo);
+static int ext2_mount(am_node *am, mntfs *mf);
+static int ext3_mount(am_node *am, mntfs *mf);
+static int ext4_mount(am_node *am, mntfs *mf);
+static int ext_umount(am_node *am, mntfs *mf);
+
+/*
+ * Ops structure
+ */
+am_ops ext2_ops =
+{
+ "ext2",
+ ext_match,
+ 0, /* ext_init */
+ ext2_mount,
+ ext_umount,
+ amfs_error_lookup_child,
+ amfs_error_mount_child,
+ amfs_error_readdir,
+ 0, /* ext_readlink */
+ 0, /* ext_mounted */
+ 0, /* ext_umounted */
+ amfs_generic_find_srvr,
+ 0, /* ext_get_wchan */
+ FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+ AUTOFS_EXT_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
+};
+
+am_ops ext3_ops =
+{
+ "ext3",
+ ext_match,
+ 0, /* ext_init */
+ ext3_mount,
+ ext_umount,
+ amfs_error_lookup_child,
+ amfs_error_mount_child,
+ amfs_error_readdir,
+ 0, /* ext_readlink */
+ 0, /* ext_mounted */
+ 0, /* ext_umounted */
+ amfs_generic_find_srvr,
+ 0, /* ext_get_wchan */
+ FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+ AUTOFS_EXT_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
+};
+
+am_ops ext4_ops =
+{
+ "ext4",
+ ext_match,
+ 0, /* ext_init */
+ ext4_mount,
+ ext_umount,
+ amfs_error_lookup_child,
+ amfs_error_mount_child,
+ amfs_error_readdir,
+ 0, /* ext_readlink */
+ 0, /* ext_mounted */
+ 0, /* ext_umounted */
+ amfs_generic_find_srvr,
+ 0, /* ext_get_wchan */
+ FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+ AUTOFS_EXT_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
+};
+
+/*
+ * EXT needs local filesystem and device.
+ */
+static char *
+ext_match(am_opts *fo)
+{
+
+ if (!fo->opt_dev) {
+ plog(XLOG_USER, "ext: no device specified");
+ return 0;
+ }
+
+ dlog("EXT: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
+
+ /*
+ * Determine magic cookie to put in mtab
+ */
+ return xstrdup(fo->opt_dev);
+}
+
+
+static int
+mount_ext(char *mntdir, char *fs_name, char *opts, int on_autofs, char *
+ mount_type, const char *mnttab_type)
+{
+ ext_args_t ext_args;
+ mntent_t mnt;
+ int flags;
+
+ /*
+ * Figure out the name of the file system type.
+ */
+ MTYPE_TYPE type = mount_type;
+
+ memset((voidp) &ext_args, 0, sizeof(ext_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;
+ 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, (caddr_t) &ext_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
+}
+
+
+static int
+ext_mount(am_node *am, mntfs *mf, char *mount_type,
+ const char *mnttab_type)
+{
+ int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
+ int error;
+
+ error = mount_ext(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs,
+ mount_type, mnttab_type);
+ if (error) {
+ errno = error;
+ plog(XLOG_ERROR, "mount_ext: %m");
+ return error;
+ }
+
+ return 0;
+}
+
+static int
+ext2_mount(am_node *am, mntfs *mf)
+{
+ return ext_mount(am, mf, MOUNT_TYPE_EXT2, MNTTAB_TYPE_EXT2);
+}
+
+static int
+ext3_mount(am_node *am, mntfs *mf)
+{
+ return ext_mount(am, mf, MOUNT_TYPE_EXT3, MNTTAB_TYPE_EXT3);
+}
+
+static int
+ext4_mount(am_node *am, mntfs *mf)
+{
+ return ext_mount(am, mf, MOUNT_TYPE_EXT4, MNTTAB_TYPE_EXT4);
+}
+
+static int
+ext_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/amd/ops_lofs.c b/amd/ops_lofs.c
index 26fdc9f9b626..b04f64399c18 100644
--- a/amd/ops_lofs.c
+++ b/amd/ops_lofs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -97,7 +93,7 @@ lofs_match(am_opts *fo)
/*
* Determine magic cookie to put in mtab
*/
- return strdup(fo->opt_rfs);
+ return xstrdup(fo->opt_rfs);
}
diff --git a/amd/ops_lustre.c b/amd/ops_lustre.c
new file mode 100644
index 000000000000..1b321ce4e8c4
--- /dev/null
+++ b/amd/ops_lustre.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2011 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 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_lustre.c
+ *
+ */
+
+/*
+ * Lustre file system
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#ifdef HAVE_FS_LUSTRE
+#include <am_defs.h>
+#include <amd.h>
+
+/* forward declarations */
+static char *lustre_match(am_opts *fo);
+static int lustre_mount(am_node *am, mntfs *mf);
+static int lustre_umount(am_node *am, mntfs *mf);
+
+/*
+ * Ops structure
+ */
+am_ops lustre_ops =
+{
+ "lustre",
+ lustre_match,
+ 0, /* lustre_init */
+ lustre_mount,
+ lustre_umount,
+ amfs_error_lookup_child,
+ amfs_error_mount_child,
+ amfs_error_readdir,
+ 0, /* lustre_readlink */
+ 0, /* lustre_mounted */
+ 0, /* lustre_umounted */
+ amfs_generic_find_srvr,
+ 0, /* lustre_get_wchan */
+ FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+ AUTOFS_LUSTRE_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
+};
+
+
+/*
+ * Lustre needs remote filesystem and host.
+ */
+static char *
+lustre_match(am_opts *fo)
+{
+ char *xmtab, *cp;
+ size_t l;
+ char *rhost, *ptr, *remhost;
+ struct in_addr addr;
+
+ if (fo->opt_fs && !fo->opt_rfs)
+ fo->opt_rfs = fo->opt_fs;
+ if (!fo->opt_rfs) {
+ plog(XLOG_USER, "lustre: no remote filesystem specified");
+ return NULL;
+ }
+ if (!fo->opt_rhost) {
+ plog(XLOG_USER, "lustre: no remote host specified");
+ return NULL;
+ }
+
+ /*
+ * Determine magic cookie to put in mtab
+ */
+ rhost = xstrdup(fo->opt_rhost);
+ remhost = NULL;
+ for (ptr = strtok(rhost, ":"); ptr; ptr = strtok(NULL, ":")) {
+ char *at = strchr(ptr, '@');
+ if (at == NULL) {
+ plog(XLOG_USER, "lustre: missing protocol in host `%s'", ptr);
+ XFREE(rhost);
+ return NULL;
+ }
+ *at = '\0';
+ /*
+ * Convert symbolic addresses to numbers that the kernel likes
+ */
+ if (inet_aton(ptr, &addr) == 0) {
+ struct hostent *hp;
+ if ((hp = gethostbyname(ptr)) == NULL) {
+ plog(XLOG_USER, "lustre: unknown host `%s'", ptr);
+ XFREE(rhost);
+ return NULL;
+ }
+ if (hp->h_length != sizeof(addr.s_addr)) {
+ plog(XLOG_USER, "lustre: bad address length %zu != %d for %s",
+ sizeof(addr), hp->h_length, ptr);
+ XFREE(rhost);
+ return NULL;
+ }
+ memcpy(&addr.s_addr, hp->h_addr, sizeof(addr));
+ }
+ *at = '@';
+
+ cp = remhost;
+ if (remhost)
+ remhost = strvcat(cp, ":", inet_ntoa(addr), at, NULL);
+ else
+ remhost = strvcat(inet_ntoa(addr), at, NULL);
+ XFREE(cp);
+ }
+ if (remhost == NULL) {
+ plog(XLOG_USER, "lustre: empty host");
+ XFREE(rhost);
+ return NULL;
+ }
+
+ XFREE(rhost);
+ XFREE(fo->opt_rhost);
+ fo->opt_rhost = remhost;
+
+ l = strlen(fo->opt_rhost) + strlen(fo->opt_rfs) + 2;
+ xmtab = xmalloc(l);
+ xsnprintf(xmtab, l, "%s:%s", fo->opt_rhost, fo->opt_rfs);
+ dlog("lustre: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"",
+ fo->opt_rhost, fo->opt_rfs, fo->opt_fs);
+
+
+ return xmtab;
+}
+
+static int
+lustre_mount(am_node *am, mntfs *mf)
+{
+ mntent_t mnt;
+ int genflags, error;
+ int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
+
+ /*
+ * Figure out the name of the file system type.
+ */
+ MTYPE_TYPE type = MOUNT_TYPE_LUSTRE;
+
+ /*
+ * Fill in the mount structure
+ */
+ memset(&mnt, 0, sizeof(mnt));
+ mnt.mnt_dir = mf->mf_mount;
+ mnt.mnt_fsname = mf->mf_info;
+ mnt.mnt_type = MNTTAB_TYPE_LUSTRE;
+ mnt.mnt_opts = mf->mf_mopts;
+
+ genflags = compute_mount_flags(&mnt);
+#ifdef HAVE_FS_AUTOFS
+ if (on_autofs)
+ genflags |= autofs_compute_mount_flags(&mnt);
+#endif /* HAVE_FS_AUTOFS */
+
+ /*
+ * Call generic mount routine
+ */
+ error = mount_fs(&mnt, genflags, NULL, 0, type, 0,
+ NULL, mnttab_file_name, on_autofs);
+ if (error) {
+ errno = error;
+ plog(XLOG_ERROR, "mount_lustre: %m");
+ return error;
+ }
+
+ return 0;
+}
+
+
+static int
+lustre_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);
+}
+#endif
diff --git a/amd/ops_mfs.c b/amd/ops_mfs.c
index ccaa49c569cd..822a2659317b 100644
--- a/amd/ops_mfs.c
+++ b/amd/ops_mfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
diff --git a/amd/ops_nfs.c b/amd/ops_nfs.c
index a6a85858d484..2dbfa5b5e2ee 100644
--- a/amd/ops_nfs.c
+++ b/amd/ops_nfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -113,6 +109,13 @@ 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;
+/*
+ * clamp the filehandle version to 3, so that we can fail back to nfsv3
+ * since nfsv4 does not have file handles
+ */
+#define SET_FH_VERSION(fs) \
+ (fs)->fs_version > NFS_VERSION3 ? NFS_VERSION3 : (fs)->fs_version;
+
/* globals */
AUTH *nfs_auth;
qelem fh_head = {&fh_head, &fh_head};
@@ -145,7 +148,7 @@ am_ops nfs_ops =
static fh_cache *
find_nfs_fhandle_cache(opaque_t arg, int done)
{
- fh_cache *fp, *fp2 = 0;
+ fh_cache *fp, *fp2 = NULL;
int id = (long) arg; /* for 64-bit archs */
ITER(fp, fh_cache, &fh_head) {
@@ -201,6 +204,10 @@ got_nfs_fh_mount(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in
memmove(fp->fh_nfs_handle.v3.am_fh3_data,
res3.mountres3_u.mountinfo.fhandle.fhandle3_val,
fp->fh_nfs_handle.v3.am_fh3_length);
+
+ XFREE(res3.mountres3_u.mountinfo.fhandle.fhandle3_val);
+ if (res3.mountres3_u.mountinfo.auth_flavors.auth_flavors_val)
+ XFREE(res3.mountres3_u.mountinfo.auth_flavors.auth_flavors_val);
} else {
#endif /* HAVE_FS_NFS3 */
memset(&res, 0, sizeof(res));
@@ -326,8 +333,7 @@ discard_fh(opaque_t arg)
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->fh_path);
XFREE(fp);
}
@@ -338,7 +344,7 @@ discard_fh(opaque_t arg)
static int
prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, mntfs *mf)
{
- fh_cache *fp, *fp_save = 0;
+ fh_cache *fp, *fp_save = NULL;
int error;
int reuse_id = FALSE;
@@ -466,11 +472,11 @@ prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, mntfs *
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_nfs_version = SET_FH_VERSION(fs);
}
fp->fh_fs = dup_srvr(fs);
- fp->fh_path = strdup(path);
+ fp->fh_path = xstrdup(path);
if (mf->mf_flags & MFF_WEBNFS)
error = webnfs_lookup(fp, got_nfs_fh_webnfs, get_mntfs_wchan(mf));
@@ -544,7 +550,9 @@ call_mountd(fh_cache *fp, u_long proc, fwd_fun fun, wchan_t wchan)
if (error)
return error;
fp->fh_sin.sin_port = mountd_port;
- }
+ dlog("%s: New %d mountd port", __func__, fp->fh_sin.sin_port);
+ } else
+ dlog("%s: Already had %d mountd port", __func__, fp->fh_sin.sin_port);
/* find the right version of the mount protocol */
#ifdef HAVE_FS_NFS3
@@ -605,7 +613,7 @@ webnfs_lookup(fh_cache *fp, fwd_fun fun, wchan_t wchan)
nfsdiropargs args;
#ifdef HAVE_FS_NFS3
am_LOOKUP3args args3;
-#endif
+#endif /* HAVE_FS_NFS3 */
char *wnfs_path;
size_t l;
@@ -724,6 +732,17 @@ nfs_init(mntfs *mf)
am_nfs_handle_t fhs;
char *colon;
+#ifdef NO_FALLBACK
+ /*
+ * We don't need file handles for NFS version 4, but we can fall back to
+ * version 3, so we allocate anyway
+ */
+#ifdef HAVE_FS_NFS4
+ if (mf->mf_server->fs_version == NFS_VERSION4)
+ return 0;
+#endif /* HAVE_FS_NFS4 */
+#endif /* NO_FALLBACK */
+
if (mf->mf_private) {
if (mf->mf_flags & MFF_NFS_SCALEDOWN) {
fserver *fs;
@@ -732,6 +751,9 @@ nfs_init(mntfs *mf)
mf->mf_ops->umounted(mf);
mf->mf_prfree(mf->mf_private);
+ mf->mf_private = NULL;
+ mf->mf_prfree = NULL;
+
fs = mf->mf_ops->ffserver(mf);
free_srvr(mf->mf_server);
mf->mf_server = fs;
@@ -769,7 +791,11 @@ mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf)
int retry;
int proto = AMU_TYPE_NONE;
mntent_t mnt;
+ void *argsp;
nfs_args_t nfs_args;
+#ifdef HAVE_FS_NFS4
+ nfs4_args_t nfs4_args;
+#endif /* HAVE_FS_NFS4 */
/*
* Extract HOST name to give to kernel.
@@ -829,10 +855,7 @@ mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf)
/*
* Set mount types accordingly
*/
-#ifndef HAVE_FS_NFS3
- type = MOUNT_TYPE_NFS;
- mnt.mnt_type = MNTTAB_TYPE_NFS;
-#else /* HAVE_FS_NFS3 */
+#ifdef HAVE_FS_NFS3
if (nfs_version == NFS_VERSION3) {
type = MOUNT_TYPE_NFS3;
/*
@@ -843,16 +866,25 @@ mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf)
* So on those systems, set it to "nfs".
* Note: MNTTAB_OPT_VERS is always set for NFS3 (see am_compat.h).
*/
+ argsp = &nfs_args;
# 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 {
+# ifdef HAVE_FS_NFS4
+ } else if (nfs_version == NFS_VERSION4) {
+ argsp = &nfs4_args;
+ type = MOUNT_TYPE_NFS4;
+ mnt.mnt_type = MNTTAB_TYPE_NFS4;
+# endif /* HAVE_FS_NFS4 */
+ } else
+#endif /* HAVE_FS_NFS3 */
+ {
+ argsp = &nfs_args;
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);
@@ -866,32 +898,44 @@ mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf)
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);
+ /* setup the many fields and flags within nfs_args */
+ compute_nfs_args(argsp,
+ &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);
+ print_nfs_args(argsp, 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);
+ error = mount_fs(&mnt, genflags, argsp, retry, type,
+ nfs_version, nfs_proto, mnttab_file_name, on_autofs);
+ XFREE(mnt.mnt_opts);
+ discard_nfs_args(argsp, nfs_version);
-#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 */
+#ifdef HAVE_FS_NFS4
+# ifndef NO_FALLBACK
+ /*
+ * If we are using a v4 file handle, we try a v3 if we get back:
+ * ENOENT: NFS v4 has a different export list than v3
+ * EPERM: Kernels <= 2.6.18 return that, instead of ENOENT
+ */
+ if ((error == ENOENT || error == EPERM) && nfs_version == NFS_VERSION4) {
+ plog(XLOG_DEBUG, "Could not find NFS 4 mount, trying again with NFS 3");
+ fs->fs_version = NFS_VERSION3;
+ error = mount_nfs_fh(fhp, mntdir, fs_name, mf);
+ if (error)
+ fs->fs_version = NFS_VERSION4;
+ }
+# endif /* NO_FALLBACK */
+#endif /* HAVE_FS_NFS4 */
return error;
}
@@ -903,11 +947,16 @@ nfs_mount(am_node *am, mntfs *mf)
int error = 0;
mntent_t mnt;
- if (!mf->mf_private) {
+ if (!mf->mf_private && mf->mf_server->fs_version != 4) {
plog(XLOG_ERROR, "Missing filehandle for %s", mf->mf_info);
return EINVAL;
}
+ if (mf->mf_mopts == NULL) {
+ plog(XLOG_ERROR, "Missing mount options 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")))
@@ -932,6 +981,7 @@ nfs_umount(am_node *am, mntfs *mf)
{
int unmount_flags, new_unmount_flags, error;
+ dlog("attempting nfs umount");
unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
@@ -1031,12 +1081,12 @@ nfs_umounted(mntfs *mf)
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_nfs_version = SET_FH_VERSION(fs);
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);
+ prime_nfs_fhandle_cache(colon + 1, mf->mf_server, (am_nfs_handle_t *) NULL, mf);
+ call_mountd(&f, MOUNTPROC_UMNT, (fwd_fun *) NULL, (wchan_t) NULL);
*colon = ':';
}
}
diff --git a/amd/ops_nfs3.c b/amd/ops_nfs3.c
index db3c7f9d265d..e07811b808e2 100644
--- a/amd/ops_nfs3.c
+++ b/amd/ops_nfs3.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
diff --git a/amd/ops_nfs4.c b/amd/ops_nfs4.c
new file mode 100644
index 000000000000..3798590837f3
--- /dev/null
+++ b/amd/ops_nfs4.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1997-2014 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. 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_nfs4.c
+ *
+ */
+
+/*
+ * Network file system version 4.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/amd/ops_nullfs.c b/amd/ops_nullfs.c
index cf621ec33ff5..73d1f0e53f1c 100644
--- a/amd/ops_nullfs.c
+++ b/amd/ops_nullfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
diff --git a/amd/ops_pcfs.c b/amd/ops_pcfs.c
index 527dc926ca77..b4c8dcd5fecc 100644
--- a/amd/ops_pcfs.c
+++ b/amd/ops_pcfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -97,7 +93,7 @@ pcfs_match(am_opts *fo)
/*
* Determine magic cookie to put in mtab
*/
- return strdup(fo->opt_dev);
+ return xstrdup(fo->opt_dev);
}
diff --git a/amd/ops_tfs.c b/amd/ops_tfs.c
index 142c32022937..3276a6e62ff1 100644
--- a/amd/ops_tfs.c
+++ b/amd/ops_tfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
diff --git a/amd/ops_tmpfs.c b/amd/ops_tmpfs.c
index eddd75569e9e..d9a15ea0434d 100644
--- a/amd/ops_tmpfs.c
+++ b/amd/ops_tmpfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -51,4 +47,146 @@
#include <am_defs.h>
#include <amd.h>
-/* FEEL FREE TO IMPLEMENT THIS... :-) */
+/* forward declarations */
+static char *tmpfs_match(am_opts *fo);
+static int tmpfs_mount(am_node *am, mntfs *mf);
+static int tmpfs_umount(am_node *am, mntfs *mf);
+
+/*
+ * Ops structure
+ */
+am_ops tmpfs_ops =
+{
+ "tmpfs",
+ tmpfs_match,
+ 0, /* tmpfs_init */
+ tmpfs_mount,
+ tmpfs_umount,
+ amfs_error_lookup_child,
+ amfs_error_mount_child,
+ amfs_error_readdir,
+ 0, /* tmpfs_readlink */
+ 0, /* tmpfs_mounted */
+ 0, /* tmpfs_umounted */
+ amfs_generic_find_srvr,
+ 0, /* tmpfs_get_wchan */
+ FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
+#if defined(HAVE_FS_AUTOFS) && defined(AUTOFS_TMPFS_FS_FLAGS)
+ AUTOFS_TMPFS_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
+};
+
+
+/*
+ * EFS needs local filesystem and device.
+ */
+static char *
+tmpfs_match(am_opts *fo)
+{
+
+ if (!fo->opt_dev) {
+ plog(XLOG_USER, "tmpfs: 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 xstrdup(fo->opt_dev);
+}
+
+
+static int
+mount_tmpfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
+{
+ tmpfs_args_t tmpfs_args;
+ mntent_t mnt;
+ int flags;
+ const char *p;
+
+ /*
+ * Figure out the name of the file system type.
+ */
+ MTYPE_TYPE type = MOUNT_TYPE_TMPFS;
+
+ p = NULL;
+ memset((voidp) &tmpfs_args, 0, sizeof(tmpfs_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_TMPFS;
+ 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 defined(HAVE_TMPFS_ARGS_T_TA_VERSION) && defined(TMPFS_ARGS_VERSION)
+ tmpfs_args.ta_version = TMPFS_ARGS_VERSION;
+#endif /* HAVE_TMPFS_ARGS_T_TA_VERSION && TMPFS_ARGS_VERSION */
+#ifdef HAVE_TMPFS_ARGS_T_TA_NODES_MAX
+ if ((p = amu_hasmntopt(&mnt, "nodes")) == NULL)
+ p = "1000000";
+ tmpfs_args.ta_nodes_max = atoi(p);
+#endif /* HAVE_TMPFS_ARGS_T_TA_SIZE_MAX */
+#ifdef HAVE_TMPFS_ARGS_T_TA_SIZE_MAX
+ if ((p = amu_hasmntopt(&mnt, "size")) == NULL)
+ p = "10000000";
+ tmpfs_args.ta_size_max = atoi(p);
+#endif /* HAVE_TMPFS_ARGS_T_TA_SIZE_MAX */
+#ifdef HAVE_TMPFS_ARGS_T_TA_ROOT_UID
+ if ((p = amu_hasmntopt(&mnt, "uid")) == NULL)
+ p = "0";
+ tmpfs_args.ta_root_uid = atoi(p);
+#endif /* HAVE_TMPFS_ARGS_T_TA_ROOT_UID */
+#ifdef HAVE_TMPFS_ARGS_T_TA_ROOT_GID
+ if ((p = amu_hasmntopt(&mnt, "gid")) == NULL)
+ p = "0";
+ tmpfs_args.ta_root_gid = atoi(p);
+#endif /* HAVE_TMPFS_ARGS_T_TA_ROOT_GID */
+#ifdef HAVE_TMPFS_ARGS_T_TA_ROOT_MODE
+ if ((p = amu_hasmntopt(&mnt, "mode")) == NULL)
+ p = "01777";
+ tmpfs_args.ta_root_mode = strtol(p, NULL, 8);
+#endif /* HAVE_TMPFS_ARGS_T_TA_ROOT_MODE */
+
+ /*
+ * Call generic mount routine
+ */
+ return mount_fs(&mnt, flags, (caddr_t) &tmpfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
+}
+
+
+static int
+tmpfs_mount(am_node *am, mntfs *mf)
+{
+ int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
+ int error;
+
+ error = mount_tmpfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
+ if (error) {
+ errno = error;
+ plog(XLOG_ERROR, "mount_tmpfs: %m");
+ return error;
+ }
+
+ return 0;
+}
+
+
+static int
+tmpfs_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/amd/ops_udf.c b/amd/ops_udf.c
new file mode 100644
index 000000000000..b029365c68f2
--- /dev/null
+++ b/amd/ops_udf.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 1997-2014 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. 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_udf.c
+ *
+ */
+
+/*
+ * UDF file system
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amd.h>
+
+/* forward definitions */
+static char *udf_match(am_opts *fo);
+static int udf_mount(am_node *am, mntfs *mf);
+static int udf_umount(am_node *am, mntfs *mf);
+
+/*
+ * Ops structure
+ */
+am_ops udf_ops =
+{
+ "udf",
+ udf_match,
+ 0, /* udf_init */
+ udf_mount,
+ udf_umount,
+ amfs_error_lookup_child,
+ amfs_error_mount_child,
+ amfs_error_readdir,
+ 0, /* udf_readlink */
+ 0, /* udf_mounted */
+ 0, /* udf_umounted */
+ amfs_generic_find_srvr,
+ 0, /* udf_get_wchan */
+ FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+ AUTOFS_UDF_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
+};
+
+#if defined(HAVE_UDF_ARGS_T_NOBODY_GID) || defined(HAVE_UDF_ARGS_T_NOBODY_UID)
+static int
+a_num(const char *s, const char *id_type)
+{
+ int id;
+ char *ep;
+
+ id = strtol(s, &ep, 0);
+ if (*ep || s == ep || id < 0) {
+ plog(XLOG_ERROR, "mount_udf: unknown %s: %s", id_type, s);
+ return 0;
+ }
+ return id;
+}
+#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_GID) || defined(HAVE_UDF_ARGS_T_NOBODY_UID) */
+
+#if defined(HAVE_UDF_ARGS_T_NOBODY_GID)
+static gid_t
+a_gid(const char *s, const char *id_type)
+{
+ struct group *gr;
+
+ if ((gr = getgrnam(s)) != NULL)
+ return gr->gr_gid;
+ return a_num(s, id_type);
+}
+#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_GID) */
+
+#if defined(HAVE_UDF_ARGS_T_NOBODY_UID)
+static uid_t
+a_uid(const char *s, const char *id_type)
+{
+ struct passwd *pw;
+
+ if ((pw = getpwnam(s)) != NULL)
+ return pw->pw_uid;
+ return a_num(s, id_type);
+}
+#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_UID) */
+
+/*
+ * UDF needs remote filesystem.
+ */
+static char *
+udf_match(am_opts *fo)
+{
+
+ if (!fo->opt_dev) {
+ plog(XLOG_USER, "udf: no source device specified");
+ return 0;
+ }
+ dlog("UDF: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
+
+ /*
+ * Determine magic cookie to put in mtab
+ */
+ return xstrdup(fo->opt_dev);
+}
+
+static int
+mount_udf(char *mntdir, char *fs_name, char *opts, int on_autofs)
+{
+ udf_args_t udf_args;
+ mntent_t mnt;
+ int flags;
+ char *str;
+#if defined(HAVE_UDF_ARGS_T_NOBODY_UID) || defined(HAVE_UDF_ARGS_T_ANON_UID)
+ uid_t uid_nobody;
+ gid_t gid_nobody;
+#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_UID) || defined(HAVE_UDF_ARGS_T_ANON_UID) */
+ /*
+ * Figure out the name of the file system type.
+ */
+ MTYPE_TYPE type = MOUNT_TYPE_UDF;
+
+#if defined(HAVE_UDF_ARGS_T_NOBODY_UID) || defined(HAVE_UDF_ARGS_T_ANON_UID)
+ uid_nobody = a_uid("nobody", "user");
+ if (uid_nobody == 0) {
+ plog(XLOG_ERROR, "mount_udf: invalid uid for nobody");
+ return EPERM;
+ }
+#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_UID) || defined(HAVE_UDF_ARGS_T_ANON_UID) */
+
+#if defined(HAVE_UDF_ARGS_T_NOBODY_GID) || defined(HAVE_UDF_ARGS_T_ANON_GID)
+ gid_nobody = a_gid("nobody", "group");
+ if (gid_nobody == 0) {
+ plog(XLOG_ERROR, "mount_udf: invalid gid for nobody");
+ return EPERM;
+ }
+#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_GID) || defined(HAVE_UDF_ARGS_T_ANON_GID) */
+
+ str = NULL;
+ memset((voidp) &udf_args, 0, sizeof(udf_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_UDF;
+ mnt.mnt_opts = opts;
+
+ flags = compute_mount_flags(&mnt);
+
+#ifdef HAVE_UDF_ARGS_T_UDFMFLAGS
+# if defined(MNT2_UDF_OPT_CLOSESESSION) && defined(MNTTAB_OPT_CLOSESESSION)
+ if (amu_hasmntopt(&mnt, MNTTAB_OPT_CLOSESESSION))
+ udf_args.udfmflags |= MNT2_UDF_OPT_CLOSESESSION;
+# endif /* defined(MNT2_UDF_OPT_CLOSESESSION) && defined(MNTTAB_OPT_CLOSESESSION) */
+#endif /* HAVE_UDF_ARGS_T_UDFMFLAGS */
+
+#ifdef HAVE_UDF_ARGS_T_NOBODY_UID
+ udf_args.nobody_uid = uid_nobody;
+#endif /* HAVE_UDF_ARGS_T_NOBODY_UID */
+
+#ifdef HAVE_UDF_ARGS_T_NOBODY_GID
+ udf_args.nobody_gid = gid_nobody;
+#endif /* HAVE_UDF_ARGS_T_NOBODY_GID */
+
+#ifdef HAVE_UDF_ARGS_T_ANON_UID
+ udf_args.anon_uid = uid_nobody; /* default to nobody */
+ if ((str = hasmntstr(&mnt, MNTTAB_OPT_USER)) != NULL) {
+ udf_args.anon_uid = a_uid(str, MNTTAB_OPT_USER);
+ XFREE(str);
+ }
+#endif /* HAVE_UDF_ARGS_T_ANON_UID */
+
+#ifdef HAVE_UDF_ARGS_T_ANON_GID
+ udf_args.anon_gid = gid_nobody; /* default to nobody */
+ if ((str = hasmntstr(&mnt, MNTTAB_OPT_GROUP)) != NULL) {
+ udf_args.anon_gid = a_gid(str, MNTTAB_OPT_GROUP);
+ XFREE(str);
+ }
+#endif /* HAVE_UDF_ARGS_T_ANON_GID */
+
+#ifdef HAVE_UDF_ARGS_T_GMTOFF
+ udf_args.gmtoff = 0;
+ if ((str = hasmntstr(&mnt, MNTTAB_OPT_GMTOFF)) != NULL) {
+ udf_args.gmtoff = a_num(str, MNTTAB_OPT_GMTOFF);
+ XFREE(str);
+ }
+#endif /* HAVE_UDF_ARGS_T_GMTOFF */
+
+#ifdef HAVE_UDF_ARGS_T_SESSIONNR
+ udf_args.sessionnr = 0;
+ if ((str = hasmntstr(&mnt, MNTTAB_OPT_SESSIONNR)) != NULL) {
+ udf_args.sessionnr = a_num(str, MNTTAB_OPT_SESSIONNR);
+ XFREE(str);
+ }
+#endif /* HAVE_UDF_ARGS_T_SESSIONNR */
+
+#ifdef HAVE_UDF_ARGS_T_VERSION
+# ifdef UDFMNT_VERSION
+ udf_args.version = UDFMNT_VERSION;
+# endif /* UDFMNT_VERSION */
+#endif /* HAVE_UDF_ARGS_T_VERSION */
+
+#ifdef HAVE_UFS_ARGS_T_FSPEC
+ udf_args.fspec = fs_name;
+#endif /* HAVE_UFS_ARGS_T_FSPEC */
+
+ /*
+ * Call generic mount routine
+ */
+ return mount_fs(&mnt, flags, (caddr_t)&udf_args, 0, type, 0, NULL,
+ mnttab_file_name, on_autofs);
+}
+
+static int
+udf_mount(am_node *am, mntfs *mf)
+{
+ int on_autofs;
+ int error;
+
+ on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
+ error = mount_udf(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
+ if (error) {
+ errno = error;
+ plog(XLOG_ERROR, "mount_udf: %m");
+ return error;
+ }
+ return 0;
+}
+
+
+static int
+udf_umount(am_node *am, mntfs *mf)
+{
+ int unmount_flags;
+
+ 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/amd/ops_ufs.c b/amd/ops_ufs.c
index fd82a5cd2228..0d8f3068dbe5 100644
--- a/amd/ops_ufs.c
+++ b/amd/ops_ufs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -61,7 +57,11 @@ static int ufs_umount(am_node *am, mntfs *mf);
*/
am_ops ufs_ops =
{
+#ifndef __NetBSD__
"ufs",
+#else
+ "ffs",
+#endif
ufs_match,
0, /* ufs_init */
ufs_mount,
@@ -98,7 +98,7 @@ ufs_match(am_opts *fo)
/*
* Determine magic cookie to put in mtab
*/
- return strdup(fo->opt_dev);
+ return xstrdup(fo->opt_dev);
}
diff --git a/amd/ops_umapfs.c b/amd/ops_umapfs.c
index 5ba735e39c61..6f9d39d9d5db 100644
--- a/amd/ops_umapfs.c
+++ b/amd/ops_umapfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
diff --git a/amd/ops_unionfs.c b/amd/ops_unionfs.c
index 73f8d6676203..e6286133cbfa 100644
--- a/amd/ops_unionfs.c
+++ b/amd/ops_unionfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
diff --git a/amd/ops_xfs.c b/amd/ops_xfs.c
index e0e740bc0a0e..6e1495e295f4 100644
--- a/amd/ops_xfs.c
+++ b/amd/ops_xfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -98,7 +94,7 @@ xfs_match(am_opts *fo)
/*
* Determine magic cookie to put in mtab
*/
- return strdup(fo->opt_dev);
+ return xstrdup(fo->opt_dev);
}
diff --git a/amd/opts.c b/amd/opts.c
index a3d35343adc0..4bc833a8dd85 100644
--- a/amd/opts.c
+++ b/amd/opts.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -539,7 +535,7 @@ eval_selectors(char *opts, char *mapkey)
char *f;
int ret = 0;
- o = old_o = strdup(opts);
+ o = old_o = xstrdup(opts);
/*
* For each user-specified option
@@ -570,7 +566,7 @@ eval_selectors(char *opts, char *mapkey)
/* null-terminate the argument */
*arg++ = '\0';
fx = strchr(arg, ')');
- if (!arg || fx == arg) {
+ if (fx == NULL || fx == arg) {
plog(XLOG_USER, "key %s: Malformed function in \"%s\"", mapkey, f);
continue;
}
@@ -606,8 +602,10 @@ eval_selectors(char *opts, char *mapkey)
}
} else {
if (eq[1] == '\0' || eq == f) {
- /* misformed selector */
+#ifdef notdef
+ /* We allow empty assignments */
plog(XLOG_USER, "key %s: Bad selector \"%s\"", mapkey, f);
+#endif
continue;
}
}
@@ -968,9 +966,7 @@ f_true(char *arg)
static void
free_op(opt_apply *p, int b)
{
- if (*p->opt) {
- XFREE(*p->opt);
- }
+ XFREE(*p->opt);
}
@@ -1016,7 +1012,7 @@ normalize_slash(char *p)
/* assert(*f == 0 || *f == '/'); */
} while (*f);
- *t = 0; /* derived from fix by Steven Glassman */
+ *t = '\0'; /* derived from fix by Steven Glassman */
}
}
@@ -1238,8 +1234,14 @@ expand_op(char *opt, int sel_p)
}
if (BUFSPACE(ep, vlen+1)) {
- xstrlcpy(ep, vptr, vlen+1);
+ /*
+ * Don't call xstrlcpy() to truncate a string here. It causes
+ * spurious xstrlcpy() syslog() errors. Use memcpy() and
+ * explicitly terminate the string.
+ */
+ memcpy(ep, vptr, vlen+1);
ep += vlen;
+ *ep = '\0';
} else {
plog(XLOG_ERROR, EXPAND_ERROR, opt);
goto out;
@@ -1292,7 +1294,7 @@ out:
* Handle common case - no expansion
*/
if (cp == opt) {
- opt = strdup(cp);
+ opt = xstrdup(cp);
} else {
/*
* Finish off the expansion
@@ -1308,7 +1310,7 @@ out:
/*
* Save the expansion
*/
- opt = strdup(expbuf);
+ opt = xstrdup(expbuf);
}
normalize_slash(opt);
@@ -1372,6 +1374,45 @@ free_opts(am_opts *fo)
apply_opts(free_op, to_free, FALSE);
}
+am_opts *
+copy_opts(am_opts *old)
+{
+ am_opts *newopts;
+ newopts = CALLOC(struct am_opts);
+
+#define _AM_OPT_COPY(field) do { \
+ if (old->field) \
+ newopts->field = xstrdup(old->field); \
+ } while (0)
+
+ _AM_OPT_COPY(fs_glob);
+ _AM_OPT_COPY(fs_local);
+ _AM_OPT_COPY(fs_mtab);
+ _AM_OPT_COPY(opt_dev);
+ _AM_OPT_COPY(opt_delay);
+ _AM_OPT_COPY(opt_dir);
+ _AM_OPT_COPY(opt_fs);
+ _AM_OPT_COPY(opt_group);
+ _AM_OPT_COPY(opt_mount);
+ _AM_OPT_COPY(opt_opts);
+ _AM_OPT_COPY(opt_remopts);
+ _AM_OPT_COPY(opt_pref);
+ _AM_OPT_COPY(opt_cache);
+ _AM_OPT_COPY(opt_rfs);
+ _AM_OPT_COPY(opt_rhost);
+ _AM_OPT_COPY(opt_sublink);
+ _AM_OPT_COPY(opt_type);
+ _AM_OPT_COPY(opt_mount_type);
+ _AM_OPT_COPY(opt_unmount);
+ _AM_OPT_COPY(opt_umount);
+ _AM_OPT_COPY(opt_user);
+ _AM_OPT_COPY(opt_maptype);
+ _AM_OPT_COPY(opt_cachedir);
+ _AM_OPT_COPY(opt_addopts);
+
+ return newopts;
+}
+
/*
* Expand selectors (variables that cannot be assigned to or overridden)
diff --git a/amd/readdir.c b/amd/readdir.c
index 49f89943cfb4..4b5e61b3d56d 100644
--- a/amd/readdir.c
+++ b/amd/readdir.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -109,14 +105,14 @@ make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable
plog(XLOG_DEBUG, "make_entry_chain: mp is (NULL)");
return retval;
}
- mf = mp->am_mnt;
+ mf = mp->am_al->al_mnt;
if (!mf) {
- plog(XLOG_DEBUG, "make_entry_chain: mp->am_mnt is (NULL)");
+ plog(XLOG_DEBUG, "make_entry_chain: mp->am_al->al_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)");
+ plog(XLOG_DEBUG, "make_entry_chain: mp->am_al->al_mnt->mf_private is (NULL)");
return retval;
}
@@ -171,7 +167,7 @@ make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable
/* 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;
+ chain[num_entries - 1].ne_nextentry = NULL;
retval = &chain[0];
}
return retval;
@@ -192,7 +188,7 @@ make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable
/* terminate chain */
if (num_entries > 0) {
- chain[num_entries - 1].ne_nextentry = 0;
+ chain[num_entries - 1].ne_nextentry = NULL;
retval = &chain[0];
}
@@ -225,7 +221,7 @@ amfs_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *
* to be returned in a single packet. If it isn't (which would be
* fairly unbelievable) then tough.
*/
- dlog("amfs_readdir_browsable: default search");
+ dlog("%s: default search", __func__);
/*
* Check for enough room. This is extremely approximate but is more
* than enough space. Really need 2 times:
@@ -264,8 +260,8 @@ amfs_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *
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;
+ ep[1].ne_nextentry = NULL;
+ (void)memcpy(ep[1].ne_cookie, &dotdotcookie, sizeof(dotdotcookie));
/*
* If map is browsable, call a function make_entry_chain() to construct
@@ -313,12 +309,12 @@ amfs_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *
return 0;
} /* end of "if (gen == 0)" statement */
- dlog("amfs_readdir_browsable: real child");
+ dlog("%s: real child", __func__);
if (gen == DOT_DOT_COOKIE) {
- dlog("amfs_readdir_browsable: End of readdir in %s", mp->am_path);
+ dlog("%s: End of readdir in %s", __func__, mp->am_path);
dp->dl_eof = TRUE;
- dp->dl_entries = 0;
+ dp->dl_entries = NULL;
return 0;
}
@@ -332,7 +328,7 @@ amfs_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *
te = te_next; /* reset 'te' from last saved te_next */
if (!te) { /* another indicator of end of readdir */
- dp->dl_entries = 0;
+ dp->dl_entries = NULL;
return 0;
}
/*
@@ -365,29 +361,14 @@ amfs_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *
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)
+static int
+amfs_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) {
/*
@@ -398,7 +379,7 @@ amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep
* to be returned in a single packet. If it isn't (which would be
* fairly unbelievable) then tough.
*/
- dlog("amfs_generic_readdir: default search");
+ dlog("%s: default search", __func__);
/*
* Check for enough room. This is extremely approximate but is more
* than enough space. Really need 2 times:
@@ -407,8 +388,11 @@ amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep
* 4byte name length
* 4byte name
* plus the dirlist structure */
- if (count < (2 * (2 * (sizeof(*ep) + sizeof("..") + 4) + sizeof(*dp))))
+#define NEEDROOM (2 * (2 * (sizeof(*ep) + sizeof("..") + 4) + sizeof(*dp)))
+ if (count < NEEDROOM) {
+ dlog("%s: not enough room %u < %zu", __func__, count, NEEDROOM);
return EINVAL;
+ }
xp = next_nonerror_node(mp->am_child);
dp->dl_entries = ep;
@@ -425,8 +409,9 @@ amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep
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);
+ ep[1].ne_nextentry = NULL;
+ (void)memcpy(ep[1].ne_cookie, (xp ? &xp->am_gen : &dotdotcookie),
+ sizeof(dotdotcookie));
if (!xp)
dp->dl_eof = TRUE; /* by default assume readdir done */
@@ -443,12 +428,12 @@ amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep
}
return 0;
}
- dlog("amfs_generic_readdir: real child");
+ dlog("%s: real child", __func__);
if (gen == DOT_DOT_COOKIE) {
- dlog("amfs_generic_readdir: End of readdir in %s", mp->am_path);
+ dlog("%s: End of readdir in %s", __func__, mp->am_path);
dp->dl_eof = TRUE;
- dp->dl_entries = 0;
+ dp->dl_entries = NULL;
if (amuDebug(D_READDIR))
plog(XLOG_DEBUG, "end of readdir eof=TRUE, dl_entries=0\n");
return 0;
@@ -491,7 +476,7 @@ amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep
}
} while (todo > 0);
- ep->ne_nextentry = 0;
+ ep->ne_nextentry = NULL;
if (amuDebug(D_READDIR)) {
nfsentry *ne;
@@ -507,3 +492,460 @@ amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep
}
return ESTALE;
}
+
+/*
+ * Search a chain for an entry with some name.
+ */
+static int
+key_already_in_chain3(char *keyname, const am_entry3 *chain)
+{
+ const am_entry3 *tmpchain = chain;
+
+ while (tmpchain) {
+ if (keyname && tmpchain->name && STREQ(keyname, tmpchain->name))
+ return 1;
+ tmpchain = tmpchain->nextentry;
+ }
+
+ return 0;
+}
+
+/*
+ * Create a chain of entries which are not linked.
+ */
+static am_entry3 *
+make_entry_chain3(am_node *mp, const am_entry3 *current_chain, int fully_browsable)
+{
+ static uint64 last_cookie = (uint64) 2; /* monotonically increasing */
+ static am_entry3 chain[MAX_CHAIN];
+ static int max_entries = MAX_CHAIN;
+ char *key;
+ int num_entries = 0, i;
+ u_int preflen = 0;
+ am_entry3 *retval = (am_entry3 *) NULL;
+ mntfs *mf;
+ mnt_map *mmp;
+
+ if (!mp) {
+ plog(XLOG_DEBUG, "make_entry_chain3: mp is (NULL)");
+ return retval;
+ }
+ mf = mp->am_al->al_mnt;
+ if (!mf) {
+ plog(XLOG_DEBUG, "make_entry_chain3: mp->am_al->al_mnt is (NULL)");
+ return retval;
+ }
+ mmp = (mnt_map *) mf->mf_private;
+ if (!mmp) {
+ plog(XLOG_DEBUG, "make_entry_chain3: mp->am_al->al_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_chain3(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_chain3: no more space in chain");
+ if (num_entries > 0) {
+ chain[num_entries - 1].nextentry = NULL;
+ retval = &chain[0];
+ }
+ return retval;
+ }
+
+ /* we have space. put entry in next cell */
+ ++last_cookie;
+ chain[num_entries].fileid = last_cookie;
+ chain[num_entries].cookie = last_cookie;
+ chain[num_entries].name = key;
+ if (num_entries < max_entries - 1) { /* link to next one */
+ chain[num_entries].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].nextentry = NULL;
+ retval = &chain[0];
+ }
+
+ return retval;
+}
+
+static size_t needroom3(void)
+{
+ /*
+ * Check for enough room. This is extremely approximate but should
+ * be enough space. Really need 2 times:
+ * (8byte fileid
+ * 8byte cookie
+ * 8byte name pointer
+ * 8byte next entry addres) = sizeof(am_entry3)
+ * 2byte name + 1byte terminator
+ * plus the size of the am_dirlist3 structure */
+ return ((2 * ((sizeof(am_entry3) + sizeof("..") + 1))) + sizeof(am_dirlist3));
+}
+
+/* This one is called only if map is browsable */
+static int
+amfs_readdir3_browsable(am_node *mp, am_cookie3 cookie,
+ am_dirlist3 *dp, am_entry3 *ep, u_int count,
+ int fully_browsable)
+{
+ uint64 gen = *(uint64 *) cookie;
+ int chain_length, i;
+ static am_entry3 *te, *te_next;
+ static int j;
+
+ dp->eof = FALSE; /* assume readdir not done */
+
+ if (amuDebug(D_READDIR))
+ plog(XLOG_DEBUG, "amfs_readdir3_browsable gen=%lu, count=%d", gen, count);
+
+ if (gen == 0) {
+ size_t needed = needroom3();
+ /*
+ * 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("%s: default search", __func__);
+
+ if (count < needed) {
+ dlog("%s: not enough room %u < %zu", __func__, count, needed);
+ 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->entries = ep;
+
+ /* construct "." */
+ ep[0].fileid = mp->am_gen;
+ ep[0].name = ".";
+ ep[0].nextentry = &ep[1];
+ ep[0].cookie = 0;
+
+ /* construct ".." */
+ if (mp->am_parent)
+ ep[1].fileid = mp->am_parent->am_gen;
+ else
+ ep[1].fileid = mp->am_gen;
+
+ ep[1].name = "..";
+ ep[1].nextentry = NULL;
+ ep[1].cookie = dotdotcookie;
+
+ /*
+ * 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_chain3(mp, dp->entries, fully_browsable);
+ if (!te)
+ return 0;
+ if (amuDebug(D_READDIR)) {
+ am_entry3 *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->nextentry;
+ if (!te_next)
+ break;
+ }
+ if (te_next) {
+ am_entry3 *te_saved = te_next->nextentry;
+ te_next->nextentry = NULL; /* terminate "te" chain */
+ te_next = te_saved; /* save rest of "te" for next iteration */
+ dp->eof = FALSE; /* tell readdir there's more */
+ } else {
+ dp->eof = TRUE; /* tell readdir that's it */
+ }
+ ep[1].nextentry = te; /* append this chunk of "te" chain */
+ if (amuDebug(D_READDIR)) {
+ am_entry3 *ne;
+ for (j = 0, ne = te; ne; ne = ne->ne_nextentry)
+ plog(XLOG_DEBUG, "gen2 key %4d \"%s\"", j++, ne->name);
+ for (j = 0, ne = ep; ne; ne = ne->ne_nextentry) {
+ plog(XLOG_DEBUG, "gen2+ key %4d \"%s\" fi=%lu ck=%lu",
+ j++, ne->name, ne->fileid, ne->cookie);
+ }
+ plog(XLOG_DEBUG, "EOF is %d", dp->eof);
+ }
+ return 0;
+ } /* end of "if (gen == 0)" statement */
+
+ dlog("%s: real child", __func__);
+
+ if (gen == DOT_DOT_COOKIE) {
+ dlog("%s: End of readdir in %s", __func__, mp->am_path);
+ dp->eof = TRUE;
+ dp->entries = NULL;
+ 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->eof = TRUE;
+ dp->entries = ep;
+
+ te = te_next; /* reset 'te' from last saved te_next */
+ if (!te) { /* another indicator of end of readdir */
+ dp->entries = NULL;
+ 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->nextentry;
+ if (!te_next)
+ break;
+ }
+ if (te_next) {
+ am_entry3 *te_saved = te_next->nextentry;
+ te_next->nextentry = NULL; /* terminate "te" chain */
+ te_next = te_saved; /* save rest of "te" for next iteration */
+ dp->eof = FALSE; /* tell readdir there's more */
+ }
+ ep = te; /* send next chunk of "te" chain */
+ dp->entries = ep;
+ if (amuDebug(D_READDIR)) {
+ am_entry3 *ne;
+ plog(XLOG_DEBUG,
+ "entries=%p, te_next=%p, eof=%d", dp->entries, te_next, dp->eof);
+ for (ne = te; ne; ne = ne->nextentry)
+ plog(XLOG_DEBUG, "gen3 key %4d \"%s\"", j++, ne->name);
+ }
+ return 0;
+}
+
+static int
+amfs_readdir3(am_node *mp, am_cookie3 cookie,
+ am_dirlist3 *dp, am_entry3 *ep, u_int count)
+{
+ uint64 gen = *(uint64 *) cookie;
+ am_node *xp;
+
+ if (amuDebug(D_READDIR))
+ plog(XLOG_DEBUG, "amfs_readdir3 gen=%lu, count=%d", gen, count);
+
+ dp->eof = FALSE; /* assume readdir not done */
+
+ /* when gen is 0, we start reading from the beginning of the directory */
+ if (gen == 0) {
+ size_t needed = needroom3();
+ /*
+ * 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("%s: default search", __func__);
+
+ if (count < needed) {
+ dlog("%s: not enough room %u < %zu", __func__, count, needed);
+ return EINVAL;
+ }
+
+ xp = next_nonerror_node(mp->am_child);
+ dp->entries = ep;
+
+ /* construct "." */
+ ep[0].fileid = mp->am_gen;
+ ep[0].name = ".";
+ ep[0].cookie = 0;
+ ep[0].nextentry = &ep[1];
+
+ /* construct ".." */
+ if (mp->am_parent)
+ ep[1].fileid = mp->am_parent->am_gen;
+ else
+ ep[1].fileid = mp->am_gen;
+ ep[1].name = "..";
+ ep[1].nextentry = NULL;
+ ep[1].cookie = (xp ? xp->am_gen : dotdotcookie);
+
+ if (!xp)
+ dp->eof = TRUE; /* by default assume readdir done */
+
+ if (amuDebug(D_READDIR)) {
+ am_entry3 *ne;
+ int j;
+ for (j = 0, ne = ep; ne; ne = ne->nextentry) {
+ plog(XLOG_DEBUG, "gen1 key %4d \"%s\" fi=%lu ck=%lu",
+ j++, ne->name, ne->fileid, ne->cookie);
+ }
+ }
+ return 0;
+ }
+ dlog("%s: real child", __func__);
+
+ if (gen == (uint64) DOT_DOT_COOKIE) {
+ dlog("%s: End of readdir in %s", __func__, mp->am_path);
+ dp->eof = TRUE;
+ dp->entries = NULL;
+ 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->entries = ep;
+ do {
+ am_node *xp_next = next_nonerror_node(xp->am_osib);
+
+ if (xp_next) {
+ ep->cookie = xp_next->am_gen;
+ } else {
+ ep->cookie = (uint64) dotdotcookie;
+ dp->eof = TRUE;
+ }
+
+ ep->fileid = xp->am_gen;
+ ep->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->nextentry = ep + 1;
+ ep++;
+ --todo;
+ } else {
+ todo = 0;
+ }
+ } while (todo > 0);
+
+ ep->nextentry = NULL;
+
+ if (amuDebug(D_READDIR)) {
+ am_entry3 *ne;
+ int j;
+ for (j = 0, ne = ep; ne; ne = ne->nextentry) {
+ plog(XLOG_DEBUG, "gen2 key %4d \"%s\" fi=%lu ck=%lu",
+ j++, ne->name, ne->fileid, ne->cookie);
+ }
+ }
+ return 0;
+ }
+ return ESTALE;
+}
+
+/*
+ * 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, voidp cookie, voidp dp, voidp ep, u_int count)
+{
+ int browsable, full;
+
+ /* check if map is browsable */
+ browsable = 0;
+ if (mp->am_al->al_mnt && mp->am_al->al_mnt->mf_mopts) {
+ mntent_t mnt;
+ mnt.mnt_opts = mp->am_al->al_mnt->mf_mopts;
+ if (amu_hasmntopt(&mnt, "fullybrowsable"))
+ browsable = 2;
+ else if (amu_hasmntopt(&mnt, "browsable"))
+ browsable = 1;
+ }
+ full = (browsable == 2);
+
+ if (nfs_dispatcher == nfs_program_2) {
+ if (browsable)
+ return amfs_readdir_browsable(mp, cookie, dp, ep, count, full);
+ else
+ return amfs_readdir(mp, cookie, dp, ep, count);
+ } else {
+ if (browsable)
+ return amfs_readdir3_browsable(mp, (am_cookie3) cookie, dp, ep, count, full);
+ else
+ return amfs_readdir3(mp, (am_cookie3) cookie, dp, ep, count);
+ }
+}
diff --git a/amd/restart.c b/amd/restart.c
index 4f71e381e25a..de38bcfb2741 100644
--- a/amd/restart.c
+++ b/amd/restart.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -59,21 +55,21 @@ restart_fake_mntfs(mntent_t *me, am_ops *fs_ops)
* Partially fake up an opts structure
*/
memset(&mo, 0, sizeof(mo));
- mo.opt_rhost = 0;
- mo.opt_rfs = 0;
+ mo.opt_rhost = NULL;
+ mo.opt_rfs = NULL;
cp = strchr(me->mnt_fsname, ':');
if (cp) {
*cp = '\0';
- mo.opt_rhost = strdup(me->mnt_fsname);
- mo.opt_rfs = strdup(cp + 1);
+ mo.opt_rhost = xstrdup(me->mnt_fsname);
+ mo.opt_rfs = xstrdup(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("/");
+ mo.opt_rhost = xstrdup(me->mnt_fsname);
+ mo.opt_rfs = xstrdup("/");
me->mnt_fsname = str3cat(me->mnt_fsname, mo.opt_rhost, ":", "/");
}
mo.opt_fs = me->mnt_dir;
@@ -87,7 +83,6 @@ restart_fake_mntfs(mntent_t *me, am_ops *fs_ops)
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
*/
@@ -110,10 +105,8 @@ restart_fake_mntfs(mntent_t *me, am_ops *fs_ops)
/*
* Clean up mo
*/
- if (mo.opt_rhost)
- XFREE(mo.opt_rhost);
- if (mo.opt_rfs)
- XFREE(mo.opt_rfs);
+ XFREE(mo.opt_rhost);
+ XFREE(mo.opt_rfs);
}
@@ -140,7 +133,7 @@ restart(void)
mlp;
mlp = mlp->mnext) {
mntent_t *me = mlp->mnt;
- am_ops *fs_ops = 0;
+ am_ops *fs_ops = NULL;
if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) {
/*
@@ -203,7 +196,7 @@ restart_automounter_nodes(void)
mlp;
mlp = mlp->mnext) {
mntent_t *me = mlp->mnt;
- am_ops *fs_ops = 0;
+ am_ops *fs_ops = NULL;
char *colon;
long pid;
u_short port;
@@ -263,7 +256,8 @@ restart_automounter_nodes(void)
if (old_ports[i] == 0) {
int soNFS;
SVCXPRT *nfsxprt;
- if (create_nfs_service(&soNFS, &port, &nfsxprt, nfs_program_2) != 0) {
+ if (create_nfs_service(&soNFS, &port, &nfsxprt, nfs_dispatcher,
+ get_nfs_dispatcher_version(nfs_dispatcher)) != 0) {
plog(XLOG_WARNING, "Can't bind to port %u", port);
goto give_up;
}
diff --git a/amd/rpc_fwd.c b/amd/rpc_fwd.c
index b3c8be4fa3b7..757b4371024a 100644
--- a/amd/rpc_fwd.c
+++ b/amd/rpc_fwd.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -94,7 +90,7 @@ static rpc_forward *
fwd_alloc(void)
{
time_t now = clocktime(NULL);
- rpc_forward *p = 0, *p2;
+ rpc_forward *p = NULL, *p2;
/*
* First search for an existing expired one.
@@ -183,7 +179,7 @@ fwd_init(void)
/*
* Some things we talk to require a priv port - so make one here
*/
- if (bind_resv_port(fwd_sock, (u_short *) 0) < 0)
+ if (bind_resv_port(fwd_sock, (u_short *) NULL) < 0)
plog(XLOG_ERROR, "can't bind privileged port (rpc_fwd)");
if (fcntl(fwd_sock, F_SETFL, FNDELAY) < 0
diff --git a/amd/sched.c b/amd/sched.c
index 8efe57a3ab81..5c816b4c2058 100644
--- a/amd/sched.c
+++ b/amd/sched.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -262,7 +258,7 @@ sigchld(int sig)
#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) {
+ while ((pid = wait3( &w, WNOHANG, (struct rusage *) NULL)) > 0) {
#endif /* not HAVE_WAITPID */
pjob *p, *p2;
diff --git a/amd/srvr_amfs_auto.c b/amd/srvr_amfs_auto.c
index 4742cf6f750d..44b130254d30 100644
--- a/amd/srvr_amfs_auto.c
+++ b/amd/srvr_amfs_auto.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -69,14 +65,14 @@ amfs_generic_find_srvr(mntfs *mf)
if (!fs) {
fs = ALLOC(struct fserver);
fs->fs_refc = 0;
- fs->fs_host = strdup("localhost");
- fs->fs_ip = 0;
+ fs->fs_host = xstrdup("localhost");
+ fs->fs_ip = NULL;
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;
+ fs->fs_private = NULL;
+ fs->fs_prfree = NULL;
ins_que(&fs->fs_q, &amfs_auto_srvr_list);
@@ -135,8 +131,7 @@ timeout_srvr(voidp v)
/*
* Free the net address
*/
- if (fs->fs_ip)
- XFREE(fs->fs_ip);
+ XFREE(fs->fs_ip);
/*
* Free the host name.
diff --git a/amd/srvr_nfs.c b/amd/srvr_nfs.c
index 0c74a658e5ee..b7c852c9e1de 100644
--- a/amd/srvr_nfs.c
+++ b/amd/srvr_nfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
* 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
+ * 3. 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.
*
@@ -75,6 +71,7 @@
typedef struct nfs_private {
u_short np_mountd; /* Mount daemon port number */
char np_mountd_inval; /* Port *may* be invalid */
+ /* 'Y' invalid, 'N' valid, 'P' permanent */
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 */
@@ -88,7 +85,9 @@ qelem nfs_srvr_list = {&nfs_srvr_list, &nfs_srvr_list};
static int global_xid; /* For NFS pings */
#define XID_ALLOC() (++global_xid)
-#ifdef HAVE_FS_NFS3
+#if defined(HAVE_FS_NFS4)
+# define NUM_NFS_VERS 3
+#elif defined(HAVE_FS_NFS3)
# define NUM_NFS_VERS 2
#else /* not HAVE_FS_NFS3 */
# define NUM_NFS_VERS 1
@@ -124,8 +123,8 @@ flush_srvr_nfs_cache(fserver *fs)
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;
+ if (np && np->np_mountd_inval != 'P') {
+ np->np_mountd_inval = 'Y';
np->np_error = -1;
}
}
@@ -147,9 +146,9 @@ create_ping_payload(u_long nfs_version)
*/
if (nfs_version == 0) {
nfs_version = NFS_VERSION;
- plog(XLOG_WARNING, "create_ping_payload: nfs_version = 0, changed to 2");
+ plog(XLOG_WARNING, "%s: nfs_version = 0, changed to 2", __func__);
} else
- plog(XLOG_INFO, "create_ping_payload: nfs_version: %d", (int) nfs_version);
+ plog(XLOG_INFO, "%s: nfs_version: %d", __func__, (int) nfs_version);
rpc_msg_init(&ping_msg, NFS_PROGRAM, nfs_version, NFSPROC_NULL);
@@ -164,6 +163,7 @@ create_ping_payload(u_long nfs_version)
if (!xdr_callmsg(&ping_xdr, &ping_msg)) {
plog(XLOG_ERROR, "Couldn't create ping RPC message");
going_down(3);
+ return;
}
/*
* Find out how long it is
@@ -184,7 +184,7 @@ 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;
+ fserver *fs = NULL;
/*
* Find which fileserver we are talking about
@@ -207,7 +207,7 @@ got_portmap(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia,
* network ordering.
*/
np->np_mountd = htons((u_short) port);
- np->np_mountd_inval = FALSE;
+ np->np_mountd_inval = 'N';
np->np_error = 0;
} else {
dlog("Error fetching port for mountd on %s", fs->fs_host);
@@ -291,9 +291,9 @@ recompute_portmap(fserver *fs)
}
if (fs->fs_version == 0)
- plog(XLOG_WARNING, "recompute_portmap: nfs_version = 0 fixed");
+ plog(XLOG_WARNING, "%s: nfs_version = 0 fixed", __func__);
- plog(XLOG_INFO, "recompute_portmap: NFS version %d on %s",
+ plog(XLOG_INFO, "%s: NFS version %d on %s", __func__,
(int) fs->fs_version, fs->fs_host);
#ifdef HAVE_FS_NFS3
if (fs->fs_version == NFS_VERSION3)
@@ -311,6 +311,7 @@ int
get_mountd_port(fserver *fs, u_short *port, wchan_t wchan)
{
int error = -1;
+
if (FSRV_ISDOWN(fs))
return EWOULDBLOCK;
@@ -329,10 +330,18 @@ get_mountd_port(fserver *fs, u_short *port, wchan_t wchan)
* indication that the mountd may be invalid, not
* that it is known to be invalid.
*/
- if (np->np_mountd_inval)
+ switch (np->np_mountd_inval) {
+ case 'Y':
recompute_portmap(fs);
- else
- np->np_mountd_inval = TRUE;
+ break;
+ case 'N':
+ np->np_mountd_inval = 'Y';
+ break;
+ case 'P':
+ break;
+ default:
+ abort();
+ }
}
if (error < 0 && wchan && !(fs->fs_flags & FSF_WANT)) {
/*
@@ -425,7 +434,7 @@ nfs_keepalive_callback(voidp pkt, int len, struct sockaddr_in *sp, struct sockad
/*
* Recompute portmap information if not known
*/
- if (np->np_mountd_inval)
+ if (np->np_mountd_inval == 'Y')
recompute_portmap(fs);
found_map++;
@@ -454,7 +463,7 @@ check_fs_addr_change(fserver *fs)
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));
+ old_ipaddr = xstrdup(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",
@@ -474,7 +483,7 @@ check_fs_addr_change(fserver *fs)
#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
+#endif /* 0 */
}
@@ -562,22 +571,24 @@ nfs_keepalive(voidp v)
int error;
nfs_private *np = (nfs_private *) fs->fs_private;
int fstimeo = -1;
+ int fs_version = nfs_valid_version(gopt.nfs_vers_ping) &&
+ gopt.nfs_vers_ping < fs->fs_version ? gopt.nfs_vers_ping : fs->fs_version;
/*
* Send an NFS ping to this node
*/
- if (ping_len[fs->fs_version - NFS_VERSION] == 0)
- create_ping_payload(fs->fs_version);
+ if (ping_len[fs_version - NFS_VERSION] == 0)
+ create_ping_payload(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],
+ ping_buf[fs_version - NFS_VERSION],
+ ping_len[fs_version - NFS_VERSION],
fs->fs_ip,
- (struct sockaddr_in *) 0,
+ (struct sockaddr_in *) NULL,
(voidp) ((long) np->np_xid), /* cast needed for 64-bit archs */
nfs_keepalive_callback);
@@ -673,7 +684,7 @@ start_nfs_pings(fserver *fs, int pingval)
fserver *
find_nfs_srvr(mntfs *mf)
{
- char *host = mf->mf_fo->opt_rhost;
+ char *host;
fserver *fs;
int pingval;
mntent_t mnt;
@@ -687,6 +698,11 @@ find_nfs_srvr(mntfs *mf)
int nfs_port_opt = 0;
int fserver_is_down = 0;
+ if (mf->mf_fo == NULL) {
+ plog(XLOG_ERROR, "%s: NULL mf_fo", __func__);
+ return NULL;
+ }
+ host = mf->mf_fo->opt_rhost;
/*
* Get ping interval from mount options.
* Current only used to decide whether pings
@@ -702,7 +718,8 @@ find_nfs_srvr(mntfs *mf)
*/
nfs_version = NFS_VERSION;
nfs_proto = "udp";
- plog(XLOG_WARNING, "find_nfs_srvr: NFS mount failed, trying again with NFSv2/UDP");
+ plog(XLOG_WARNING, "%s: NFS mount failed, trying again with NFSv2/UDP",
+ __func__);
mf->mf_flags &= ~MFF_NFS_SCALEDOWN;
} else {
/*
@@ -742,12 +759,13 @@ find_nfs_srvr(mntfs *mf)
/* 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",
+ plog(XLOG_INFO, "%s: force NFS version to %d", __func__,
(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);
+ plog(XLOG_INFO, "%s: force NFS protocol transport to %s", __func__,
+ nfs_proto);
}
}
@@ -769,7 +787,7 @@ find_nfs_srvr(mntfs *mf)
if (hp) {
switch (hp->h_addrtype) {
case AF_INET:
- ip = ALLOC(struct sockaddr_in);
+ ip = CALLOC(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;
@@ -795,8 +813,7 @@ find_nfs_srvr(mntfs *mf)
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);
+ XFREE(ip);
return fs;
}
}
@@ -821,10 +838,12 @@ find_nfs_srvr(mntfs *mf)
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).
+ * Prefer NFSv4/tcp if the client supports it (cf. RFC 2054, 7).
*/
if (!nfs_version) {
-#ifdef HAVE_FS_NFS3
+#if defined(HAVE_FS_NFS4)
+ nfs_version = NFS_VERSION4;
+#elif defined(HAVE_FS_NFS3)
nfs_version = NFS_VERSION3;
#else /* not HAVE_FS_NFS3 */
nfs_version = NFS_VERSION;
@@ -833,11 +852,11 @@ find_nfs_srvr(mntfs *mf)
(int) nfs_version);
}
if (!nfs_proto) {
-#if defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3)
+#if defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) || defined(HAVE_FS_NFS4)
nfs_proto = "tcp";
-#else /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */
+#else /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) || defined(HAVE_FS_NFS4) */
nfs_proto = "udp";
-#endif /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */
+#endif /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) || defined(HAVE_FS_NFS4) */
plog(XLOG_INFO, "No NFS protocol transport specified, will use %s",
nfs_proto);
}
@@ -849,7 +868,8 @@ find_nfs_srvr(mntfs *mf)
*/
if (check_pmap_up(host, ip)) {
if (nfs_proto) {
- best_nfs_version = get_nfs_version(host, ip, nfs_version, nfs_proto);
+ best_nfs_version = get_nfs_version(host, ip, nfs_version, nfs_proto,
+ gopt.nfs_vers);
nfs_port = ip->sin_port;
}
#ifdef MNTTAB_OPT_PROTO
@@ -858,8 +878,8 @@ find_nfs_srvr(mntfs *mf)
char **p;
for (p = protocols; *p; p++) {
- proto_nfs_version = get_nfs_version(host, ip, nfs_version, *p);
-
+ proto_nfs_version = get_nfs_version(host, ip, nfs_version, *p,
+ gopt.nfs_vers);
if (proto_nfs_version > best_nfs_version) {
best_nfs_version = proto_nfs_version;
nfs_proto = *p;
@@ -908,8 +928,8 @@ find_nfs_srvr(mntfs *mf)
if (!nfs_port)
nfs_port = htons(NFS_PORT);
- dlog("find_nfs_srvr: using port %d for nfs on %s",
- (int) ntohs(nfs_port), host);
+ dlog("%s: using port %d for nfs on %s", __func__,
+ (int) ntohs(nfs_port), host);
ip->sin_port = nfs_port;
no_dns:
@@ -935,7 +955,7 @@ no_dns:
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));
+ old_ipaddr = xstrdup(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",
@@ -962,24 +982,28 @@ no_dns:
*/
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;
+ if (np->np_mountd_inval != 'P') {
+ 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;
+ } else {
+ fs->fs_flags = FSF_VALID;
+ }
+
}
fs->fs_refc++;
- if (ip)
- XFREE(ip);
+ XFREE(ip);
return fs;
}
}
@@ -993,7 +1017,7 @@ no_dns:
*/
fs = ALLOC(struct fserver);
fs->fs_refc = 1;
- fs->fs_host = strdup(hp ? hp->h_name : "unknown_hostname");
+ fs->fs_host = xstrdup(hp ? hp->h_name : "unknown_hostname");
if (gopt.flags & CFM_NORMALIZE_HOSTNAMES)
host_normalize(&fs->fs_host);
fs->fs_ip = ip;
@@ -1014,9 +1038,18 @@ no_dns:
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;
+ np->np_mountd = htons(hasmntval(&mnt, "mountport"));
+ if (np->np_mountd == 0) {
+ np->np_mountd_inval = 'Y';
+ np->np_xid = XID_ALLOC();
+ np->np_error = -1;
+ } else {
+ plog(XLOG_INFO, "%s: using mountport: %d", __func__,
+ (int) ntohs(np->np_mountd));
+ np->np_mountd_inval = 'P';
+ np->np_xid = 0;
+ np->np_error = 0;
+ }
/*
* Initially the server will be deemed dead after
diff --git a/amd/sun2amd.8 b/amd/sun2amd.8
new file mode 100644
index 000000000000..67d241f32cdb
--- /dev/null
+++ b/amd/sun2amd.8
@@ -0,0 +1,92 @@
+.\"
+.\" Copyright (c) 1997-2014 Erez Zadok
+.\" Copyright (c) 2005 Daniel P. Ottavio
+.\" 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. 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/sun2amd.8
+.\"
+.TH SUN2AMD 8L "14 August 2005"
+
+.SH NAME
+sun2amd \- converts Sun automount maps to Amd maps
+
+.SH SYNOPSIS
+.B sun2amd
+[-hH] [-i infile] [-o outfile]
+
+.SH DESCRIPTION
+.B sun2amd
+is used to convert Sun style automount maps to Amd style automount
+maps. By default
+.B sun2amd
+reads from stdin and writes to stdout.
+
+.SH OPTIONS
+.TP
+.B -h
+Help
+.TP
+.B -i
+Read Sun map information from specified file.
+.TP
+.B -o
+Write Amd map information to specified file.
+
+.SH EXAMPLE
+To convert a Sun automount file called auto_foo to an Amd file called
+auto.amd type:
+
+.B sun2amd
+-i auto_foo -o auto.amd
+
+.SH BUGS
+* Can not convert master maps yet.
+
+* NFS is the only automount type currently supported.
+
+total_bug_count = number_found + 1;
+
+.SH "SEE ALSO"
+.BR automount(8),
+.BR amd(8)
+
+.I "Linux NFS and Automounter Administration"
+by Erez Zadok, ISBN 0-7821-2739-8, (Sybex, 2001).
+.LP
+.I http://www.am-utils.org
+.LP
+
+.SH AUTHOR
+Daniel P. Ottavio
+.I <dottavio@ic.sunysb.edu>
diff --git a/amd/sun2amd.c b/amd/sun2amd.c
new file mode 100644
index 000000000000..ee6fbb59626f
--- /dev/null
+++ b/amd/sun2amd.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 1997-2014 Erez Zadok
+ * Copyright (c) 2005 Daniel P. Ottavio
+ * 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. 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/sun2amd.c
+ *
+ */
+
+/*
+ * Translate Sun-syntax maps to Amd maps
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amd.h>
+#include <sun_map.h>
+
+
+/* dummies to make the program compile and link */
+struct amu_global_options gopt;
+#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, rfc931_timeout=0;
+# endif /* NEED_LIBWRAP_SEVERITY_VARIABLES */
+#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
+
+
+/*
+ * Parse the stream sun_in, convert the map information to amd, write
+ * the results to amd_out.
+ */
+static int
+sun2amd_convert(FILE *sun_in, FILE *amd_out)
+{
+ char line_buff[INFO_MAX_LINE_LEN], *tmp, *key, *entry;
+ int pos, line = 0, retval = 1;
+
+ /* just to be safe */
+ memset(line_buff, 0, sizeof(line_buff));
+
+ /* Read the input line by line and do the conversion. */
+ while ((pos = file_read_line(line_buff, sizeof(line_buff), sun_in))) {
+ line++;
+ line_buff[pos - 1] = '\0';
+
+ /* remove comments */
+ if ((tmp = strchr(line_buff, '#')) != NULL) {
+ *tmp = '\0';
+ }
+
+ /* find start of key */
+ key = line_buff;
+ while (*key != '\0' && isspace((unsigned char)*key)) {
+ key++;
+ }
+
+ /* ignore blank lines */
+ if (*key == '\0') {
+ continue;
+ }
+
+ /* find the end of the key and NULL terminate */
+ tmp = key;
+ while (*tmp != '\0' && isspace((unsigned char)*tmp) == 0) {
+ tmp++;
+ }
+ if (*tmp == '\0') {
+ plog(XLOG_ERROR, "map line %d has no entry", line);
+ goto err;
+ }
+ *tmp++ = '\0';
+ if (*tmp == '\0') {
+ plog(XLOG_ERROR, "map line %d has no entry", line);
+ goto err;
+ }
+ entry = tmp;
+
+ /* convert the sun entry to an amd entry */
+ if ((tmp = sun_entry2amd(key, entry)) == NULL) {
+ plog(XLOG_ERROR, "parse error on line %d", line);
+ goto err;
+ }
+
+ if (fprintf(amd_out, "%s %s\n", key, tmp) < 0) {
+ plog(XLOG_ERROR, "can't write to output stream: %s", strerror(errno));
+ goto err;
+ }
+
+ /* just to be safe */
+ memset(line_buff, 0, sizeof(line_buff));
+ }
+
+ /* success */
+ retval = 0;
+
+ err:
+ return retval;
+}
+
+
+/*
+ * wrapper open function
+ */
+static FILE *
+sun2amd_open(const char *path, const char *mode)
+{
+ FILE *retval = NULL;
+
+ if ((retval = fopen(path,mode)) == NULL) {
+ plog(XLOG_ERROR,"could not open file %s",path);
+ }
+
+ return retval;
+}
+
+
+/*
+ * echo the usage and exit
+ */
+static void
+sun2amd_usage(void)
+{
+ fprintf(stderr,
+ "usage : sun2amd [-hH] [-i infile] [-o outfile]\n"
+ "-h\thelp\n"
+ "-i\tspecify an infile (defaults to stdin)\n"
+ "-o\tspecify an outfile (defaults to stdout)\n");
+}
+
+
+int
+main(int argc, char **argv)
+{
+ /* default in/out to stdin/stdout */
+ FILE *sun_in = stdin, *amd_out = stdout;
+ int opt, retval = 1;
+
+ while ((opt = getopt(argc, argv , "i:o:hH")) != -1) {
+ switch (opt) {
+
+ case 'i':
+ if ((sun_in = sun2amd_open(optarg,"r")) == NULL) {
+ goto err;
+ }
+ break;
+
+ case 'o':
+ if ((amd_out = sun2amd_open(optarg,"w")) == NULL) {
+ goto err;
+ }
+ break;
+
+ case 'h':
+ case 'H':
+ sun2amd_usage();
+ goto err;
+ }
+ }
+
+ retval = sun2amd_convert(sun_in,amd_out);
+
+ err:
+ exit(retval);
+}
diff --git a/amd/sun_map.c b/amd/sun_map.c
new file mode 100644
index 000000000000..8e3559960cd3
--- /dev/null
+++ b/amd/sun_map.c
@@ -0,0 +1,595 @@
+/*
+ * Copyright (c) 1997-2014 Erez Zadok
+ * Copyright (c) 2005 Daniel P. Ottavio
+ * 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. 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/sun_map.c
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amd.h>
+#include <sun_map.h>
+
+
+
+/*
+ * Add a data pointer to the end of the list.
+ */
+void
+sun_list_add(struct sun_list *list, qelem *item)
+{
+ if (list->last == NULL) {
+ list->last = item;
+ list->first = item;
+ item->q_back = NULL;
+ }
+ else {
+ list->last->q_forw = item;
+ item->q_back = list->last;
+ list->last = item;
+ }
+
+ item->q_forw = NULL;
+}
+
+
+/*
+ * Sun2Amd conversion routines
+ */
+
+/*
+ * AMD entry keywords
+ */
+#define AMD_OPTS_KW "addopts:=" /* add entry options */
+#define AMD_RHOST_KW "rhost:=" /* remote host */
+#define AMD_RFS_KW "rfs:=" /* remote file system */
+#define AMD_FS_KW "fs:=" /* local file system */
+#define AMD_DEV_KW "dev:=" /* device */
+#define AMD_TYPE_NFS_KW "type:=nfs;" /* fs type nfs */
+#define AMD_TYPE_AUTO_KW "type:=auto;" /* fs type auto */
+#define AMD_TYPE_CDFS_KW "type:=cdfs;" /* fs type cd */
+#define AMD_MAP_FS_KW "fs:=${map};" /* set the mount map as current map */
+#define AMD_MAP_PREF_KW "pref:=${key}/" /* set the mount map as current map */
+
+/*
+ * A set of string Sun fstypes.
+ */
+#define SUN_NFS_TYPE "nfs"
+#define SUN_HSFS_TYPE "hsfs" /* CD fs */
+#define SUN_AUTOFS_TYPE "autofs"
+#define SUN_CACHEFS_TYPE "cachefs"
+
+#define SUN_KEY_SUB "&" /* Sun key substitution */
+
+/* a set a Sun variable substitutions for map entries */
+#define SUN_ARCH "$ARCH" /* host architecture */
+#define SUN_CPU "$CPU" /* processor type */
+#define SUN_HOST "$HOST" /* host name */
+#define SUN_OSNAME "$OSNAME" /* OS name */
+#define SUN_OSREL "$OSREL" /* OS release */
+#define SUN_OSVERS "$OSVERS" /* OS version */
+#define SUN_NATISA "$NATISA" /* native instruction set */
+
+/* a set of Amd variable substitutions */
+#define AMD_ARCH "${arch}" /* host architecture */
+#define AMD_HOST "${host}" /* host name */
+#define AMD_OSNAME "${os}" /* OS name */
+#define AMD_OSVER "${osver}" /* OS version */
+
+
+/*
+ * Return a copy of src that has all occurrences of 'str' replaced
+ * with sub.
+ *
+ * param src - the original string
+ * param str - string that is the replaced with str
+ * param sub - string that replaces an occurrences of 'delim'
+ *
+ * return - new string with str substitutions, NULL on error
+ */
+static char *
+sun_strsub(const char *src, const char *str, const char *sub)
+{
+
+ char *retval = NULL, *str_start, *str_end, *src_end;
+ size_t total_size, first_half, second_half, sub_size;
+
+ /* assign pointers to the start and end of str */
+ if ((str_start = strstr(src, str)) == NULL) {
+ return retval;
+ }
+ str_end = (strlen(str) - 1) + str_start;
+
+ /* assign to the end of the src. */
+ src_end = (strlen(src) - 1) + (char*)src;
+
+ /* size from the beginning of src to the start of str */
+ first_half = (size_t)(str_start - src);
+
+ /* size from the end of str to the end of src */
+ second_half = (size_t)(src_end - str_end);
+
+ sub_size = strlen(sub);
+
+ total_size = (first_half + sub_size + second_half + 1);
+
+ retval = (char*)xmalloc(total_size);
+ memset(retval, 0, total_size);
+
+ /*
+ * Put together the string such that the first half is copied
+ * followed the sub and second half.
+ *
+ * We use strncpy instead of xstrlcpy because we are intentionally
+ * causing truncation and we don't want this to cause errors in the
+ * log.
+ */
+ (void)strncpy(retval, src, first_half);
+ (void)strncat(retval, sub, sub_size);
+ (void)strncat(retval, str_end + 1, second_half);
+
+ if (strstr(retval, str) != NULL) {
+ /*
+ * If there is another occurrences of str call this function
+ * recursively.
+ */
+ char* tmp;
+ if ((tmp = sun_strsub(retval, str, sub)) != NULL) {
+ XFREE(retval);
+ retval = tmp;
+ }
+ }
+ return retval;
+}
+
+
+/*
+ * Return a new string that is a copy of str, all occurrences of a Sun
+ * variable substitutions are replaced by there equivalent Amd
+ * substitutions.
+ *
+ * param str - source string
+ *
+ * return - A new string with the expansions, NULL if str does not
+ * exist in src or error.
+ */
+static char *
+sun_expand2amd(const char *str)
+{
+
+ char *retval = NULL, *tmp = NULL, *tmp2 = NULL;
+ const char *pos;
+
+ /*
+ * Iterator through the string looking for '$' chars. For each '$'
+ * found try to replace it with Sun variable substitutions. If we
+ * find a '$' that is not a substation each of the i.e $blah than
+ * each of the replace attempt will fail and we'll move on to the
+ * next char.
+ */
+ tmp = xstrdup(str);
+ for (pos = str; *pos != '\0'; pos++) {
+ if (*pos != '$') {
+ continue;
+ }
+ if (tmp2 != NULL) {
+ XFREE(tmp);
+ tmp = tmp2;
+ }
+
+ /*
+ * If a 'replace' does not return NULL than a variable was
+ * successfully substituted.
+ */
+
+ /* architecture */
+ if ((tmp2 = sun_strsub(tmp, SUN_ARCH, AMD_ARCH)) != NULL) {
+ continue;
+ }
+ /* cpu - there is not POSIX uname for cpu so just use machine */
+ if ((tmp2 = sun_strsub(tmp, SUN_CPU, AMD_ARCH)) != NULL) {
+ continue;
+ }
+ /* hostname */
+ if ((tmp2 = sun_strsub(tmp, SUN_HOST, AMD_HOST)) != NULL) {
+ continue;
+ }
+ /* os name */
+ if ((tmp2 = sun_strsub(tmp, SUN_OSNAME, AMD_OSNAME)) != NULL) {
+ continue;
+ }
+ /*
+ * os release - Amd doesn't hava a OS release var just usr os
+ * version or now.
+ */
+ if ((tmp2 = sun_strsub(tmp, SUN_OSREL, AMD_OSVER)) != NULL) {
+ continue;
+ }
+ /* os version */
+ if ((tmp2 = sun_strsub(tmp, SUN_OSVERS, AMD_OSVER)) != NULL) {
+ continue;
+ }
+ /* native instruction set - there is no POSIX natisa so just use system */
+ if ((tmp2 = sun_strsub(tmp, SUN_NATISA, AMD_ARCH)) != NULL) {
+ continue;
+ }
+ }
+ if (tmp2 == NULL) {
+ retval = tmp;
+ }
+ else {
+ retval = tmp2;
+ XFREE(tmp);
+ }
+
+ return retval;
+}
+
+
+/*
+ * This is a wrapper function for appending Amd entry information to a
+ * buffer. Any Sun variable substitutions will be converted into Amd
+ * equivalents.
+ *
+ * param dest - destination buffer
+ * param deslen - destination buffer length
+ * param key - entry key, this might be needed for key substitutions
+ * param str - string to append
+ */
+static void
+sun_append_str(char *dest,
+ size_t destlen,
+ const char *key,
+ const char *str)
+{
+ char *sub = NULL, *sub2 = NULL, *out = NULL;
+
+ /* By default we are going to just write the original string. */
+ out = (char*)str;
+
+ /*
+ * Resolve variable substitutions in two steps; 1) replace any key
+ * map substitutions with the entry key 2) expand any variable
+ * substitutions i.e $HOST.
+ *
+ * Try to replace the key substitution '&'. If this function returns
+ * with a new string, one or more key subs. where replaced with the
+ * entry key.
+ */
+ if ((sub = sun_strsub(str, SUN_KEY_SUB, "${key}")) != NULL) {
+ out = sub;
+ /*
+ * Try to convert any variable substitutions. If this function
+ * returns a new string one or more var subs where expanded.
+ */
+ if ((sub2 = sun_expand2amd(sub)) != NULL) {
+ out = sub2;
+ }
+ }
+ /*
+ * Try to convert any variable substitutions. If this function
+ * returns a new string one or more var subs where expanded.
+ */
+ else if (out != NULL && (sub = sun_expand2amd(out)) != NULL) {
+ out = sub;
+ }
+
+ if (out != NULL) {
+ xstrlcat(dest, out, destlen);
+ }
+ XFREE(sub);
+ XFREE(sub2);
+}
+
+
+/*
+ * Convert the list of Sun mount options to Amd mount options. The
+ * result is concatenated to dest.
+ *
+ * param dest - destination buffer
+ * param destlen - destination buffer length
+ * param key - automount key
+ * param opt_list - list of Sun mount options
+ */
+static void
+sun_opts2amd(char *dest,
+ size_t destlen,
+ const char *key,
+ const struct sun_opt *opt_list)
+{
+ const struct sun_opt *opt;
+
+ xstrlcat(dest, AMD_OPTS_KW, destlen);
+
+ /* Iterate through each option and append it to the buffer. */
+ for(opt = opt_list; opt != NULL; opt = NEXT(struct sun_opt, opt)) {
+ sun_append_str(dest, destlen, key, opt->str);
+ /* If there are more options add some commas. */
+ if (NEXT(struct sun_opt, opt) != NULL) {
+ xstrlcat(dest, ",", destlen);
+ }
+ }
+ xstrlcat(dest, ";", destlen);
+}
+
+
+/*
+ * Convert the list of Sun mount locations to a list of Amd mount
+ * locations. The result is concatenated to dest.
+ *
+ * param dest - destination buffer
+ * param destlen - destination buffer length
+ * param key - automount key
+ * param local_list - list of Sun mount locations
+ */
+static void
+sun_locations2amd(char *dest,
+ size_t destlen,
+ const char *key,
+ const struct sun_location *local_list)
+{
+ const struct sun_location *local;
+ const struct sun_host *host;
+
+ for (local = local_list;
+ local != NULL;
+ local = NEXT(struct sun_location,local)) {
+ /*
+ * Check to see if the list of hosts is empty. Some mount types
+ * i.e cd-rom may have mount location with no host.
+ */
+ if (local->host_list != NULL) {
+ /* Write each host that belongs to this location. */
+ for (host = local->host_list;
+ host != NULL;
+ host = NEXT(struct sun_host, host)) {
+ /* set fstype NFS */
+ xstrlcat(dest, AMD_TYPE_NFS_KW, destlen);
+ /* add rhost key word */
+ xstrlcat(dest, AMD_RHOST_KW, destlen);
+ /* add host name */
+ sun_append_str(dest, destlen, key, host->name);
+ xstrlcat(dest, ";", destlen);
+ /* add remote fs key word */
+ xstrlcat(dest, AMD_RFS_KW, destlen);
+ /* add local path */
+ sun_append_str(dest, destlen, key, local->path);
+ if (NEXT(struct sun_host, host) != NULL) {
+ xstrlcat(dest, ";", destlen);
+ xstrlcat(dest, " ", destlen);
+ }
+ }
+ }
+ else {
+ /* no host location */
+ xstrlcat(dest, AMD_FS_KW, destlen);
+ sun_append_str(dest, destlen, key, local->path);
+ }
+ if (NEXT(struct sun_location, local) != NULL) {
+ /* add a space to separate each location */
+ xstrlcat(dest, " ", destlen);
+ }
+ }
+}
+
+
+/*
+ * Convert a Sun HSFS mount point to an Amd. The result is
+ * concatenated intp dest.
+ *
+ * param dest - destination buffer
+ * param destlen - destination buffer length
+ * param key - automount key
+ * param s_entry - Sun entry
+ */
+static void
+sun_hsfs2amd(char *dest,
+ size_t destlen,
+ const char *key,
+ const struct sun_entry *s_entry)
+{
+ /* set fstype CDFS */
+ xstrlcat(dest, AMD_TYPE_CDFS_KW, destlen);
+ /* set the cdrom device */
+ xstrlcat(dest, AMD_DEV_KW, destlen);
+ /* XXX: For now just assume that there is only one device. */
+ xstrlcat(dest, s_entry->location_list->path, destlen);
+}
+
+
+/*
+ * Convert a Sun NFS automount entry to an Amd. The result is concatenated
+ * into dest.
+ *
+ * param dest - destination buffer
+ * param destlen - destination buffer length
+ * param key - automount key
+ * param s_entry - Sun entry
+ */
+static void
+sun_nfs2amd(char *dest,
+ size_t destlen,
+ const char *key,
+ const struct sun_entry *s_entry)
+{
+ if (s_entry->location_list != NULL) {
+ /* write out the list of mountpoint locations */
+ sun_locations2amd(dest, destlen, key, s_entry->location_list);
+ }
+}
+
+
+/*
+ * Convert a Sun multi-mount point entry to an Amd. This is done
+ * using the Amd type auto. Each auto entry is separated with a \n.
+ *
+ * param dest - destination buffer
+ * param destlen - destination buffer length
+ * param key - automount key
+ * param s_entry - Sun entry
+ */
+static void
+sun_multi2amd(char *dest,
+ size_t destlen,
+ const char *key,
+ const struct sun_entry *s_entry)
+{
+ const struct sun_mountpt *mountpt;
+
+ /* We need to setup a auto fs Amd automount point. */
+ xstrlcat(dest, AMD_TYPE_AUTO_KW, destlen);
+ xstrlcat(dest, AMD_MAP_FS_KW, destlen);
+ xstrlcat(dest, AMD_MAP_PREF_KW, destlen);
+
+ /* write the mountpts to dest */
+ for (mountpt = s_entry->mountpt_list;
+ mountpt != NULL;
+ mountpt = NEXT(struct sun_mountpt, mountpt)) {
+ xstrlcat(dest, "\n", destlen);
+ /* write the key */
+ xstrlcat(dest, key, destlen);
+ /* write the mount path */
+ sun_append_str(dest, destlen, key, mountpt->path);
+ /* space */
+ xstrlcat(dest, " ", destlen);
+ /* Write all the host locations for this mount point. */
+ sun_locations2amd(dest, destlen, key, mountpt->location_list);
+ }
+}
+
+
+/*
+ * Convert the sun_entry into an Amd equivalent string.
+ *
+ * param key - automount key
+ * param s_entry - Sun style automap entry
+ *
+ * return - Amd entry on succes, NULL on error
+ */
+char *
+sun_entry2amd(const char *key, const char *s_entry_str)
+{
+ char *retval = NULL;
+ char line_buff[INFO_MAX_LINE_LEN];
+ int ws;
+ struct sun_entry *s_entry = NULL;
+
+ /* The key should not be NULL. */
+ if (key == NULL) {
+ plog(XLOG_ERROR,"Sun key value was null");
+ goto err;
+ }
+ /* The Sun entry string should never be NULL. */
+ if (s_entry_str == NULL) {
+ plog(XLOG_ERROR,"Sun entry value was null");
+ goto err;
+ }
+
+ /* Make sure there are no trailing white spaces or '\n'. */
+ xstrlcpy(line_buff, s_entry_str, sizeof(line_buff));
+ ws = strlen(line_buff) - 1;
+ while (ws >= 0 && (isspace((unsigned char)line_buff[ws]) || line_buff[ws] == '\n')) {
+ line_buff[ws--] = '\0';
+ }
+
+ /* Parse the sun entry line. */
+ s_entry = sun_map_parse_read(line_buff);
+ if (s_entry == NULL) {
+ plog(XLOG_ERROR,"could not parse Sun style map");
+ goto err;
+ }
+
+ memset(line_buff, 0, sizeof(line_buff));
+
+ if (s_entry->opt_list != NULL) {
+ /* write the mount options to the buffer */
+ sun_opts2amd(line_buff, sizeof(line_buff), key, s_entry->opt_list);
+ }
+
+ /* Check if this is a multi-mount entry. */
+ if (s_entry->mountpt_list != NULL) {
+ /* multi-mount point */
+ sun_multi2amd(line_buff, sizeof(line_buff), key, s_entry);
+ retval = xstrdup(line_buff);
+ }
+ else {
+ /* single mount point */
+ if (s_entry->fstype != NULL) {
+ if (NSTREQ(s_entry->fstype, SUN_NFS_TYPE, strlen(SUN_NFS_TYPE))) {
+ /* NFS Type */
+ sun_nfs2amd(line_buff, sizeof(line_buff), key, s_entry);
+ retval = xstrdup(line_buff);
+ }
+ else if (NSTREQ(s_entry->fstype, SUN_HSFS_TYPE, strlen(SUN_HSFS_TYPE))) {
+ /* HSFS Type (CD fs) */
+ sun_hsfs2amd(line_buff, sizeof(line_buff), key, s_entry);
+ retval = xstrdup(line_buff);
+ }
+ /*
+ * XXX: The following fstypes are not yet supported.
+ */
+ else if (NSTREQ(s_entry->fstype, SUN_AUTOFS_TYPE, strlen(SUN_AUTOFS_TYPE))) {
+ /* AutoFS Type */
+ plog(XLOG_ERROR, "Sun fstype %s is currently not supported by Amd.",
+ s_entry->fstype);
+ goto err;
+
+ }
+ else if (NSTREQ(s_entry->fstype, SUN_CACHEFS_TYPE, strlen(SUN_CACHEFS_TYPE))) {
+ /* CacheFS Type */
+ plog(XLOG_ERROR, "Sun fstype %s is currently not supported by Amd.",
+ s_entry->fstype);
+ goto err;
+ }
+ else {
+ plog(XLOG_ERROR, "Sun fstype %s is currently not supported by Amd.",
+ s_entry->fstype);
+ goto err;
+ }
+ }
+ else {
+ plog(XLOG_INFO, "No SUN fstype specified defaulting to NFS.");
+ sun_nfs2amd(line_buff, sizeof(line_buff), key, s_entry);
+ retval = xstrdup(line_buff);
+ }
+ }
+
+ err:
+ XFREE(s_entry);
+ return retval;
+}
diff --git a/amd/sun_map.h b/amd/sun_map.h
new file mode 100644
index 000000000000..75e707ae7003
--- /dev/null
+++ b/amd/sun_map.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 1997-2014 Erez Zadok
+ * Copyright (c) 2005 Daniel P. Ottavio
+ * 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. 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/sun_map.h
+ *
+ */
+
+#ifndef _SUN_MAP_H
+#define _SUN_MAP_H
+
+/* host */
+struct sun_host {
+ qelem head; /* link-list header */
+ char *name; /* hostname */
+ int weight; /* weight given to the host */
+};
+
+/* location */
+struct sun_location {
+ qelem head; /* link-list header */
+ char *path; /* server path */
+ struct sun_host *host_list; /* list of hosts */
+};
+
+/* sun mount option */
+struct sun_opt {
+ qelem head; /* link-list header */
+ char *str; /* option string */
+};
+
+/* mount point */
+struct sun_mountpt {
+ qelem head; /* link-list header */
+ char *path; /* optional mount point path */
+ char *fstype; /* filesystem type */
+ struct sun_opt *opt_list; /* list of option strings */
+ struct sun_location *location_list; /* list of 'struct s2a_location' */
+};
+
+/* automount entry */
+struct sun_entry {
+ qelem head; /* link-list header */
+ char *key; /* auto map key */
+ char *fstype; /* filesystem type */
+ struct sun_opt *opt_list; /* list of mount options */
+ struct sun_location *location_list; /* list of mount locations */
+ struct sun_mountpt *mountpt_list; /* list of mount points */
+};
+
+/*
+ * automount map file
+ *
+ * XXX: Only a place holder structure, not implemented yet.
+ */
+struct sun_map {
+ qelem head; /* link-list header */
+ char *path; /* directory path of the map file */
+ char *mount_dir; /* top level mount point for this map */
+ int lookup; /* lookup type i.e file, yp, program, etc. */
+ int direct_bool; /* set true if this map is a direct map */
+ struct sun_opt *opt_list; /* list of global map options */
+ struct sun_opt *include_list; /* list of included map files */
+ struct sun_entry *entry_list; /* list of 'struct s2a_entry' */
+};
+
+/*
+ * master map file
+ *
+ * XXX: Only a place holder structure, not implemented yet.
+ */
+struct sun_mmap {
+ qelem head; /* link-list header */
+ struct sun_opt *include_list; /* list of included master maps */
+ struct sun_map *amap_list; /* list of 'struct s2a_amap' */
+};
+
+struct sun_list {
+ qelem *first;
+ qelem *last;
+};
+
+
+/*
+ * EXTERNS
+ */
+extern char *sun_entry2amd(const char *, const char *);
+extern struct sun_entry *sun_map_parse_read(const char *);
+extern void sun_list_add(struct sun_list *, qelem *);
+
+#endif /* not _SUN_MAP_H */
diff --git a/amd/sun_map_parse.y b/amd/sun_map_parse.y
new file mode 100644
index 000000000000..ccf258e2dcc8
--- /dev/null
+++ b/amd/sun_map_parse.y
@@ -0,0 +1,492 @@
+%{
+/*
+ * Copyright (c) 1997-2014 Erez Zadok
+ * Copyright (c) 2005 Daniel P. Ottavio
+ * 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. 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/sun_map_parse.y
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amd.h>
+#include <sun_map.h>
+
+
+#define SUN_FSTYPE_STR "fstype="
+
+
+extern int sun_map_lex(void);
+extern int sun_map_error(const char *);
+extern void sun_map_tok_setbuff(const char *);
+extern int sun_map_parse(void);
+
+struct sun_entry *sun_map_parse_read(const char *);
+
+static struct sun_list *sun_entry_list = NULL;
+static struct sun_list *sun_opt_list = NULL;
+static struct sun_list *sun_host_list = NULL;
+static struct sun_list *sun_location_list = NULL;
+static struct sun_list *mountpt_list = NULL;
+static char *tmpFsType = NULL;
+
+
+/*
+ * Each get* function returns a pointer to the corresponding global
+ * list structure. If the structure is NULL than a new instance is
+ * returned.
+ */
+static struct sun_list *get_sun_opt_list(void);
+static struct sun_list *get_sun_host_list(void);
+static struct sun_list *get_sun_location_list(void);
+static struct sun_list *get_mountpt_list(void);
+static struct sun_list *get_sun_entry_list(void);
+
+%}
+
+%union {
+ char strval[2048];
+}
+
+%token NEWLINE COMMENT WSPACE
+%token <strval> WORD
+
+%%
+
+amap : file
+ ;
+
+file : new_lines entries
+ | entries
+ ;
+
+entries : entry
+ | entry new_lines
+ | entry new_lines entries
+ ;
+
+new_lines : NEWLINE
+ | NEWLINE new_lines
+ ;
+
+entry : locations {
+
+ struct sun_list *list;
+ struct sun_entry *entry;
+
+ /* allocate an entry */
+ entry = CALLOC(struct sun_entry);
+
+ /*
+ * Assign the global location list to this entry and reset the
+ * global pointer. Reseting the global pointer will create a new
+ * list instance next time get_sun_location_list() is called.
+ */
+ list = get_sun_location_list();
+ entry->location_list = (struct sun_location *)list->first;
+ sun_location_list = NULL;
+
+ /* Add this entry to the entry list. */
+ sun_list_add(get_sun_entry_list(), (qelem *)entry);
+}
+
+| '-' options WSPACE locations {
+
+ struct sun_list *list;
+ struct sun_entry *entry;
+
+ entry = CALLOC(struct sun_entry);
+
+ /* An fstype may have been defined in the 'options'. */
+ if (tmpFsType != NULL) {
+ entry->fstype = tmpFsType;
+ tmpFsType = NULL;
+ }
+
+ /*
+ * Assign the global location list to this entry and reset the
+ * global pointer. Reseting the global pointer will create a new
+ * list instance next time get_sun_location_list() is called.
+ */
+ list = get_sun_location_list();
+ entry->location_list = (struct sun_location *)list->first;
+ sun_location_list = NULL;
+
+ /*
+ * Assign the global opt list to this entry and reset the global
+ * pointer. Reseting the global pointer will create a new list
+ * instance next time get_sun_opt_list() is called.
+ */
+ list = get_sun_opt_list();
+ entry->opt_list = (struct sun_opt *)list->first;
+ sun_opt_list = NULL;
+
+ /* Add this entry to the entry list. */
+ sun_list_add(get_sun_entry_list(), (qelem *)entry);
+}
+
+| mountpoints {
+
+ struct sun_list *list;
+ struct sun_entry *entry;
+
+ /* allocate an entry */
+ entry = CALLOC(struct sun_entry);
+
+ /*
+ * Assign the global mountpt list to this entry and reset the global
+ * pointer. Reseting the global pointer will create a new list
+ * instance next time get_mountpt_list() is called.
+ */
+ list = get_mountpt_list();
+ entry->mountpt_list = (struct sun_mountpt *)list->first;
+ mountpt_list = NULL;
+
+ /* Add this entry to the entry list. */
+ sun_list_add(get_sun_entry_list(), (qelem *)entry);
+}
+
+| '-' options WSPACE mountpoints {
+
+ struct sun_list *list;
+ struct sun_entry *entry;
+
+ /* allocate an entry */
+ entry = CALLOC(struct sun_entry);
+
+ /* An fstype may have been defined in the 'options'. */
+ if (tmpFsType != NULL) {
+ entry->fstype = tmpFsType;
+ tmpFsType = NULL;
+ }
+
+ /*
+ * Assign the global mountpt list to this entry and reset the global
+ * pointer. Reseting the global pointer will create a new list
+ * instance next time get_mountpt_list() is called.
+ */
+ list = get_mountpt_list();
+ entry->mountpt_list = (struct sun_mountpt *)list->first;
+ mountpt_list = NULL;
+
+ /*
+ * Assign the global opt list to this entry and reset the global
+ * pointer. Reseting the global pointer will create a new list
+ * instance next time get_sun_opt_list() is called.
+ */
+ list = get_sun_opt_list();
+ entry->opt_list = (struct sun_opt *)list->first;
+ sun_opt_list = NULL;
+
+ /* Add this entry to the entry list. */
+ sun_list_add(get_sun_entry_list(), (qelem *)entry);
+}
+;
+
+mountpoints : mountpoint
+ | mountpoint WSPACE mountpoints
+ ;
+
+mountpoint : WORD WSPACE location {
+
+ struct sun_list *list;
+ struct sun_mountpt *mountpt;
+
+ /* allocate a mountpt */
+ mountpt = CALLOC(struct sun_mountpt);
+
+ /*
+ * Assign the global loaction list to this entry and reset the
+ * global pointer. Reseting the global pointer will create a new
+ * list instance next time get_sun_location_list() is called.
+ */
+ list = get_sun_location_list();
+ mountpt->location_list = (struct sun_location *)list->first;
+ sun_location_list = NULL;
+
+ mountpt->path = xstrdup($1);
+
+ /* Add this mountpt to the mountpt list. */
+ sun_list_add(get_mountpt_list(), (qelem *)mountpt);
+}
+
+| WORD WSPACE '-' options WSPACE location {
+
+ struct sun_list *list;
+ struct sun_mountpt *mountpt;
+
+ /* allocate a mountpt */
+ mountpt = CALLOC(struct sun_mountpt);
+
+ /* An fstype may have been defined in the 'options'. */
+ if (tmpFsType != NULL) {
+ mountpt->fstype = tmpFsType;
+ tmpFsType = NULL;
+ }
+
+ /*
+ * Assign the global location list to this entry and reset the
+ * global pointer. Reseting the global pointer will create a new
+ * list instance next time get_sun_location_list() is called.
+ */
+ list = get_sun_location_list();
+ mountpt->location_list = (struct sun_location *)list->first;
+ sun_location_list = NULL;
+
+ /*
+ * Assign the global opt list to this entry and reset the global
+ * pointer. Reseting the global pointer will create a new list
+ * instance next time get_sun_opt_list() is called.
+ */
+ list = get_sun_opt_list();
+ mountpt->opt_list = (struct sun_opt *)list->first;
+ sun_opt_list = NULL;
+
+ mountpt->path = xstrdup($1);
+
+ /* Add this mountpt to the mountpt list. */
+ sun_list_add(get_mountpt_list(), (qelem *)mountpt);
+}
+;
+
+locations : location
+ | location WSPACE locations
+ ;
+
+location : hosts ':' WORD {
+
+ struct sun_list *list;
+ struct sun_location *location;
+
+ /* allocate a new location */
+ location = CALLOC(struct sun_location);
+
+ /*
+ * Assign the global opt list to this entry and reset the global
+ * pointer. Reseting the global pointer will create a new list
+ * instance next time get_sun_opt_list() is called.
+ */
+ list = get_sun_host_list();
+ location->host_list = (struct sun_host *)list->first;
+ sun_host_list = NULL;
+
+ location->path = xstrdup($3);
+
+ /* Add this location to the location list. */
+ sun_list_add(get_sun_location_list(), (qelem *)location);
+}
+
+| ':' WORD {
+
+ struct sun_location *location;
+
+ /* allocate a new location */
+ location = CALLOC(struct sun_location);
+
+ location->path = xstrdup($2);
+
+ /* Add this location to the location list. */
+ sun_list_add(get_sun_location_list(), (qelem *)location);
+}
+;
+
+hosts : host
+ | host ',' hosts
+ ;
+
+host : WORD {
+
+ /* allocate a new host */
+ struct sun_host *host = CALLOC(struct sun_host);
+
+ host->name = xstrdup($1);
+
+ /* Add this host to the host list. */
+ sun_list_add(get_sun_host_list(),(qelem *)host);
+}
+
+| WORD weight {
+
+ /*
+ * It is assumed that the host for this rule was allocated by the
+ * 'weight' rule and assigned to be the last host item on the host
+ * list.
+ */
+ struct sun_host *host = (struct sun_host *)sun_host_list->last;
+
+ host->name = xstrdup($1);
+}
+;
+
+weight : '(' WORD ')' {
+
+ int val;
+ /* allocate a new host */
+ struct sun_host *host = CALLOC(struct sun_host);
+
+ val = atoi($2);
+
+ host->weight = val;
+
+ /* Add this host to the host list. */
+ sun_list_add(get_sun_host_list(), (qelem *)host);
+}
+;
+
+options : option
+ | option ',' options
+ ;
+
+option : WORD {
+
+ char *type;
+
+ /* check if this is an fstype option */
+ if ((type = strstr($1,SUN_FSTYPE_STR)) != NULL) {
+ /* parse out the fs type from the Sun fstype keyword */
+ if ((type = type + strlen(SUN_FSTYPE_STR)) != NULL) {
+ /*
+ * This global fstype str will be assigned to the current being
+ * parsed later in the parsing.
+ */
+ tmpFsType = xstrdup(type);
+ }
+ }
+ else {
+ /*
+ * If it is not an fstype option allocate an opt struct and assign
+ * the value.
+ */
+ struct sun_opt *opt = CALLOC(struct sun_opt);
+ opt->str = xstrdup($1);
+ /* Add this opt to the opt list. */
+ sun_list_add(get_sun_opt_list(), (qelem *)opt);
+ }
+}
+
+;
+
+%%
+
+/*
+ * Parse 'map_data' which is assumed to be a Sun-syle map. If
+ * successful a sun_entry is returned.
+ *
+ * The parser is designed to parse map entries with out the keys. For
+ * example the entry:
+ *
+ * usr -ro pluto:/usr/local
+ *
+ * should be passed to the parser as:
+ *
+ * -ro pluto:/usr/local
+ *
+ * The reason for this is that the Amd info services already strip off
+ * the key when they read map info.
+ */
+struct sun_entry *
+sun_map_parse_read(const char *map_data)
+{
+ struct sun_entry *retval = NULL;
+
+ /* pass map_data to lex */
+ sun_map_tok_setbuff(map_data);
+
+ /* call yacc */
+ sun_map_parse();
+
+ if (sun_entry_list != NULL) {
+ /* return the first Sun entry in the list */
+ retval = (struct sun_entry*)sun_entry_list->first;
+ sun_entry_list = NULL;
+ }
+ else {
+ plog(XLOG_ERROR, "Sun map parser did not produce data structs.");
+ }
+
+ return retval;
+}
+
+
+static struct sun_list *
+get_sun_entry_list(void)
+{
+ if (sun_entry_list == NULL) {
+ sun_entry_list = CALLOC(struct sun_list);
+ }
+ return sun_entry_list;
+}
+
+
+static struct sun_list *
+get_mountpt_list(void)
+{
+ if (mountpt_list == NULL) {
+ mountpt_list = CALLOC(struct sun_list);
+ }
+ return mountpt_list;
+}
+
+
+static struct sun_list *
+get_sun_location_list(void)
+{
+ if (sun_location_list == NULL) {
+ sun_location_list = CALLOC(struct sun_list);
+ }
+ return sun_location_list;
+}
+
+
+static struct sun_list *
+get_sun_host_list(void)
+{
+ if (sun_host_list == NULL) {
+ sun_host_list = CALLOC(struct sun_list);
+ }
+ return sun_host_list;
+}
+
+
+static struct sun_list *
+get_sun_opt_list(void)
+{
+ if (sun_opt_list == NULL) {
+ sun_opt_list = CALLOC(struct sun_list);
+ }
+ return sun_opt_list;
+}
diff --git a/amd/sun_map_tok.l b/amd/sun_map_tok.l
new file mode 100644
index 000000000000..f979bea4cf1f
--- /dev/null
+++ b/amd/sun_map_tok.l
@@ -0,0 +1,233 @@
+%{
+/*
+ * Copyright (c) 1997-2014 Erez Zadok
+ * Copyright (c) 2005 Daniel P. Ottavio
+ * 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. 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/sun_map_tok.l
+ *
+ */
+
+#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 <sun_map_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 __IGNORE(fwrite( yytext, yyleng, 1, yyout ))
+# endif /* not ECHO */
+#endif /* FLEX_SCANNER */
+
+int yylex(void);
+int sun_map_error(const char *);
+
+/*
+ * We need to configure lex to parse from a string
+ * instead of a file. Each version of lex has it's
+ * own way of doing this (sigh).
+ */
+
+/* assign the buffer to parse */
+void sun_map_tok_setbuff(const char* buff);
+
+/* buffer that contains the string to parse */
+const char *sun_map_tok_buff = NULL;
+
+#ifdef FLEX_SCANNER
+/*
+ * The flex scanner uses the YY_INPUT to parse the input.
+ * We need to redefine it so that it can parse strings.
+ * In addition to the above string buffer we need to have
+ * a position pointer and a end pointer.
+ */
+
+/* current position of the buffer */
+const char *sun_map_tok_pos = NULL;
+
+/* size of the buffer */
+const char *sun_map_tok_end = NULL;
+
+/* copies the current position + maxsize into buff */
+int sun_map_input(char *buff, int maxsize);
+
+# undef YY_INPUT
+# define YY_INPUT(buff,result,maxsize) (result = sun_map_input(buff,maxsize))
+
+#else
+/*
+ * If this is not Flex than fall back to an AT&T style lex.
+ * We can parse strings by redefining input and unput.
+ */
+#undef input
+#undef unput
+#define input() (*(char *)sun_map_tok_buff++)
+#define unput(c) (*(char *)--sun_map_tok_buff = c)
+
+#endif /* FLEX_SCANNER */
+
+/*
+ * some systems such as DU-4.x have a different GNU flex in /usr/bin
+ * which automatically generates yywrap macros and symbols. So I must
+ * distinguish between them and when yywrap is actually needed.
+ */
+#if !defined(yywrap) || defined(yylex)
+int yywrap(void);
+#endif /* not yywrap or yylex */
+
+/* no need to use yywrap() */
+#define YY_SKIP_YYWRAP
+
+int sun_map_line = 1;
+int sun_map_tokpos = 1;
+
+%}
+
+/* This option causes Solaris lex to fail. Use flex. See BUGS file */
+/* no need to use yyunput() */
+%option nounput
+%option noinput
+
+/* allocate more output slots so lex scanners don't run out of mem */
+%o 1024
+
+WORD_REX [A-Za-z0-9_/&\.$=]+[A-Za-z0-9_/&\.$=-]*
+COMMENT_REX ^#.*\n
+WSPACE_REX [ \t]*
+NEWLINE_REX [ \t]*\n
+CONTINUE_REX "\\"\n
+
+%%
+
+{WORD_REX} {
+ sun_map_tokpos += yyleng;
+ xstrlcpy((char *)sun_map_lval.strval,(const char *)yytext,sizeof(sun_map_lval.strval));
+ return WORD;
+ }
+
+{WSPACE_REX} {
+ sun_map_tokpos += yyleng;
+ return WSPACE;
+ }
+
+{NEWLINE_REX} {
+ sun_map_tokpos = 0;
+ sun_map_line++;
+ return NEWLINE;
+ }
+
+{CONTINUE_REX} {
+ sun_map_tokpos = 0;
+ sun_map_line++;
+ }
+
+{COMMENT_REX} {
+ sun_map_line++;
+ }
+
+. {
+ return yytext[0];
+ }
+
+%%
+
+
+int
+sun_map_error(const char* s)
+{
+ return 1;
+}
+
+#ifdef FLEX_SCANNER
+void
+sun_map_tok_setbuff(const char* buff)
+{
+ sun_map_tok_end = buff + strlen(buff);
+ sun_map_tok_pos = buff;
+ sun_map_tok_buff = buff;
+}
+
+
+int
+sun_map_input(char *buff, int maxsize)
+{
+ int size = MIN(maxsize, (sun_map_tok_end - sun_map_tok_pos));
+ if (size > 0) {
+ memcpy(buff,sun_map_tok_pos,size);
+ sun_map_tok_pos += size;
+ }
+
+ return size;
+}
+#else
+void
+sun_map_tok_setbuff(const char* buff)
+{
+ sun_map_tok_buff = buff;
+}
+
+#endif /* FLEX_SCANNER */
+
+/*
+ * some systems such as DU-4.x have a different GNU flex in /usr/bin
+ * which automatically generates yywrap macros and symbols. So I must
+ * distinguish between them and when yywrap is actually needed.
+ */
+#if !defined(yywrap) || defined(yylex)
+int yywrap(void)
+{
+ return 1;
+}
+#endif /* not yywrap or yylex */
diff --git a/amd/test1.sh b/amd/test1.sh
new file mode 100755
index 000000000000..44cafbcbc71e
--- /dev/null
+++ b/amd/test1.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+./amd -v 2> /dev/null