138494Sobrien/*
2310490Scy * Copyright (c) 1997-2014 Erez Zadok
338494Sobrien * Copyright (c) 1990 Jan-Simon Pendry
438494Sobrien * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
538494Sobrien * Copyright (c) 1990 The Regents of the University of California.
638494Sobrien * All rights reserved.
738494Sobrien *
838494Sobrien * This code is derived from software contributed to Berkeley by
938494Sobrien * Jan-Simon Pendry at Imperial College, London.
1038494Sobrien *
1138494Sobrien * Redistribution and use in source and binary forms, with or without
1238494Sobrien * modification, are permitted provided that the following conditions
1338494Sobrien * are met:
1438494Sobrien * 1. Redistributions of source code must retain the above copyright
1538494Sobrien *    notice, this list of conditions and the following disclaimer.
1638494Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1738494Sobrien *    notice, this list of conditions and the following disclaimer in the
1838494Sobrien *    documentation and/or other materials provided with the distribution.
19310490Scy * 3. Neither the name of the University nor the names of its contributors
2038494Sobrien *    may be used to endorse or promote products derived from this software
2138494Sobrien *    without specific prior written permission.
2238494Sobrien *
2338494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2438494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2538494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2638494Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2738494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2838494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2938494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3038494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3138494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3238494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3338494Sobrien * SUCH DAMAGE.
3438494Sobrien *
3538494Sobrien *
36174294Sobrien * File: am-utils/amd/amfs_nfsl.c
3738494Sobrien *
3838494Sobrien */
3938494Sobrien
4038494Sobrien/*
4138494Sobrien * NFSL: Network file system with local existence check.  If the local
4238494Sobrien * path denoted by $rfs exists, it behaves as type:=link.
4338494Sobrien *
4438494Sobrien * Example:
4538494Sobrien *	pkg	type:=nfsl;rhost:=jonny;rfs:=/n/johnny/src/pkg;fs:=${rfs}
4638494Sobrien */
4738494Sobrien
4838494Sobrien#ifdef HAVE_CONFIG_H
4938494Sobrien# include <config.h>
5038494Sobrien#endif /* HAVE_CONFIG_H */
5138494Sobrien#include <am_defs.h>
5238494Sobrien#include <amd.h>
5338494Sobrien
5438494Sobrien
5538494Sobrien/* forward declarations */
5638494Sobrienstatic char *amfs_nfsl_match(am_opts *fo);
5738494Sobrienstatic int amfs_nfsl_init(mntfs *mf);
58174294Sobrienstatic int amfs_nfsl_mount(am_node *mp, mntfs *mf);
59174294Sobrienstatic int amfs_nfsl_umount(am_node *mp, mntfs *mf);
60174294Sobrienstatic void amfs_nfsl_umounted(mntfs *mf);
6138494Sobrienstatic fserver *amfs_nfsl_ffserver(mntfs *mf);
6238494Sobrien
6338494Sobrien/*
6438494Sobrien * NFS-Link operations
6538494Sobrien */
6638494Sobrienam_ops amfs_nfsl_ops =
6738494Sobrien{
68174294Sobrien  "nfsl",
69174294Sobrien  amfs_nfsl_match,
70174294Sobrien  amfs_nfsl_init,
71174294Sobrien  amfs_nfsl_mount,
72174294Sobrien  amfs_nfsl_umount,
73174294Sobrien  amfs_error_lookup_child,
74174294Sobrien  amfs_error_mount_child,
75174294Sobrien  amfs_error_readdir,
76174294Sobrien  0,				/* amfs_nfsl_readlink */
77174294Sobrien  0,				/* amfs_nfsl_mounted */
78174294Sobrien  amfs_nfsl_umounted,
79174294Sobrien  amfs_nfsl_ffserver,
80174294Sobrien  0,				/* amfs_nfsl_get_wchan */
81174294Sobrien  FS_MKMNT | FS_BACKGROUND | FS_AMQINFO,	/* nfs_fs_flags */
82174294Sobrien#ifdef HAVE_FS_AUTOFS
83174294Sobrien  AUTOFS_NFSL_FS_FLAGS,
84174294Sobrien#endif /* HAVE_FS_AUTOFS */
8538494Sobrien};
8638494Sobrien
8738494Sobrien
8838494Sobrien/*
8938494Sobrien * Check that f/s has all needed fields.
9038494Sobrien * Returns: matched string if found, NULL otherwise.
9138494Sobrien */
9238494Sobrienstatic char *
9338494Sobrienamfs_nfsl_match(am_opts *fo)
9438494Sobrien{
95174294Sobrien  char *cp;
9638494Sobrien  char *ho = fo->opt_rhost;
97174294Sobrien  char *retval;
9838494Sobrien  struct stat stb;
9938494Sobrien
100310490Scy  if (fo->opt_sublink && fo->opt_sublink[0])
101174294Sobrien    cp = fo->opt_sublink;
102174294Sobrien  else
103174294Sobrien    cp = fo->opt_fs;
104174294Sobrien
10538494Sobrien  if (!cp || !ho) {
10642629Sobrien    plog(XLOG_USER, "amfs_nfsl: host $fs and $rhost must be specified");
10738494Sobrien    return NULL;
10838494Sobrien  }
10938494Sobrien
11038494Sobrien  /*
11138494Sobrien   * If this host is not the same as $rhost, or if link does not exist,
112174294Sobrien   * call nfs_ops.fs_match().
113174294Sobrien   * If link value exists (or same host), call amfs_link_ops.fs_match().
11438494Sobrien   */
115310490Scy  if (!STRCEQ(ho, am_get_hostname()) && !STRCEQ(ho, hostd)) {
116310490Scy    plog(XLOG_INFO, "amfs_nfsl: \"%s\" is not the local host \"%s\", "
117310490Scy	"or \"%s\" using type:=nfs", ho, am_get_hostname(), hostd);
118174294Sobrien    retval = nfs_ops.fs_match(fo);
11938494Sobrien  } else if (lstat(cp, &stb) < 0) {
12038494Sobrien    plog(XLOG_INFO, "amfs_nfsl: \"%s\" does not exist, using type:=nfs", cp);
121174294Sobrien    retval = nfs_ops.fs_match(fo);
12238494Sobrien  } else {
12338494Sobrien    plog(XLOG_INFO, "amfs_nfsl: \"%s\" exists, using type:=link", cp);
124174294Sobrien    retval = amfs_link_ops.fs_match(fo);
12538494Sobrien  }
126174294Sobrien  return retval;
12738494Sobrien}
12838494Sobrien
12938494Sobrien
13038494Sobrien/*
13138494Sobrien * Initialize.
13238494Sobrien * Returns: 0 if OK, non-zero (errno) if failed.
13338494Sobrien */
13438494Sobrienstatic int
13538494Sobrienamfs_nfsl_init(mntfs *mf)
13638494Sobrien{
137174294Sobrien  int ret = 0;
13838494Sobrien  if (mf->mf_flags & MFF_NFSLINK) {
139174294Sobrien    if (amfs_link_ops.fs_init)
140174294Sobrien      ret = amfs_link_ops.fs_init(mf);
14138494Sobrien  } else {
142174294Sobrien    if (nfs_ops.fs_init)
143174294Sobrien      ret = nfs_ops.fs_init(mf);
14438494Sobrien  }
145174294Sobrien  return ret;
14638494Sobrien}
14738494Sobrien
14838494Sobrien
14938494Sobrien/*
15038494Sobrien * Mount vfs.
15138494Sobrien * Returns: 0 if OK, non-zero (errno) if failed.
15238494Sobrien */
15338494Sobrienstatic int
154174294Sobrienamfs_nfsl_mount(am_node *mp, mntfs *mf)
15538494Sobrien{
156174294Sobrien  int ret = 0;
15738494Sobrien  if (mf->mf_flags & MFF_NFSLINK) {
158174294Sobrien    if (amfs_link_ops.mount_fs)
159174294Sobrien      ret = amfs_link_ops.mount_fs(mp, mf);
16038494Sobrien  } else {
161174294Sobrien    if (nfs_ops.mount_fs)
162174294Sobrien      ret = nfs_ops.mount_fs(mp, mf);
16338494Sobrien  }
164174294Sobrien  return ret;
16538494Sobrien}
16638494Sobrien
16738494Sobrien
16838494Sobrien/*
16938494Sobrien * Unmount VFS.
17038494Sobrien * Returns: 0 if OK, non-zero (errno) if failed.
17138494Sobrien */
17238494Sobrienstatic int
173174294Sobrienamfs_nfsl_umount(am_node *mp, mntfs *mf)
17438494Sobrien{
175174294Sobrien  int ret = 0;
17638494Sobrien  if (mf->mf_flags & MFF_NFSLINK) {
177174294Sobrien    if (amfs_link_ops.umount_fs)
178174294Sobrien      ret = amfs_link_ops.umount_fs(mp, mf);
17938494Sobrien  } else {
180174294Sobrien    if (nfs_ops.umount_fs)
181174294Sobrien      ret = nfs_ops.umount_fs(mp, mf);
18238494Sobrien  }
183174294Sobrien  return ret;
18438494Sobrien}
18538494Sobrien
18638494Sobrien
18738494Sobrien/*
18838494Sobrien * Async unmount callback function.
18938494Sobrien * After the base umount() succeeds, we may want to take extra actions,
19038494Sobrien * such as informing remote mount daemons that we've unmounted them.
19138494Sobrien * See amfs_auto_umounted(), host_umounted(), nfs_umounted().
19238494Sobrien */
19338494Sobrienstatic void
194174294Sobrienamfs_nfsl_umounted(mntfs *mf)
19538494Sobrien{
19638494Sobrien  if (mf->mf_flags & MFF_NFSLINK) {
197174294Sobrien    if (amfs_link_ops.umounted)
198174294Sobrien      amfs_link_ops.umounted(mf);
19938494Sobrien  } else {
200174294Sobrien    if (nfs_ops.umounted)
201174294Sobrien      nfs_ops.umounted(mf);
20238494Sobrien  }
20338494Sobrien}
20438494Sobrien
20538494Sobrien
20638494Sobrien/*
20738494Sobrien * Find a file server.
20838494Sobrien * Returns: fserver of found server, or NULL if not found.
20938494Sobrien */
21038494Sobrienstatic fserver *
21138494Sobrienamfs_nfsl_ffserver(mntfs *mf)
21238494Sobrien{
213310490Scy  char *cp, *ho;
21438494Sobrien  struct stat stb;
21538494Sobrien
216310490Scy  if (mf->mf_fo == NULL) {
217310490Scy    plog(XLOG_ERROR, "%s: NULL mf_fo", __func__);
218310490Scy    return NULL;
219310490Scy  }
220310490Scy  ho = mf->mf_fo->opt_rhost;
221310490Scy
222310490Scy  if (mf->mf_fo->opt_sublink && mf->mf_fo->opt_sublink[0])
223174294Sobrien    cp = mf->mf_fo->opt_sublink;
224174294Sobrien  else
225174294Sobrien    cp = mf->mf_fo->opt_fs;
226174294Sobrien
22738494Sobrien  /*
22838494Sobrien   * If this host is not the same as $rhost, or if link does not exist,
229174294Sobrien   * call amfs_link_ops.ffserver().
230174294Sobrien   * If link value exists (or same host), then call ops_nfs.ffserver().
23138494Sobrien   */
232310490Scy  if ((!STRCEQ(ho, am_get_hostname()) &&
233310490Scy       !STRCEQ(ho, hostd)) || lstat(cp, &stb) < 0) {
234174294Sobrien    return nfs_ops.ffserver(mf);
23538494Sobrien  } else {
23638494Sobrien    mf->mf_flags |= MFF_NFSLINK;
237174294Sobrien    /* remove the FS_MKMNT flag, we don't want amd touching the mountpoint */
238174294Sobrien    mf->mf_fsflags &= ~FS_MKMNT;
239174294Sobrien    return amfs_link_ops.ffserver(mf);
24038494Sobrien  }
24138494Sobrien}
242