2 * Copyright (c) 1997-2014 Erez Zadok
3 * Copyright (c) 1990 Jan-Simon Pendry
4 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
5 * Copyright (c) 1990 The Regents of the University of California.
8 * This code is derived from software contributed to Berkeley by
9 * Jan-Simon Pendry at Imperial College, London.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * File: am-utils/amd/amfs_nfsl.c
41 * NFSL: Network file system with local existence check. If the local
42 * path denoted by $rfs exists, it behaves as type:=link.
45 * pkg type:=nfsl;rhost:=jonny;rfs:=/n/johnny/src/pkg;fs:=${rfs}
50 #endif /* HAVE_CONFIG_H */
55 /* forward declarations */
56 static char *amfs_nfsl_match(am_opts *fo);
57 static int amfs_nfsl_init(mntfs *mf);
58 static int amfs_nfsl_mount(am_node *mp, mntfs *mf);
59 static int amfs_nfsl_umount(am_node *mp, mntfs *mf);
60 static void amfs_nfsl_umounted(mntfs *mf);
61 static fserver *amfs_nfsl_ffserver(mntfs *mf);
66 am_ops amfs_nfsl_ops =
73 amfs_error_lookup_child,
74 amfs_error_mount_child,
76 0, /* amfs_nfsl_readlink */
77 0, /* amfs_nfsl_mounted */
80 0, /* amfs_nfsl_get_wchan */
81 FS_MKMNT | FS_BACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
84 #endif /* HAVE_FS_AUTOFS */
89 * Check that f/s has all needed fields.
90 * Returns: matched string if found, NULL otherwise.
93 amfs_nfsl_match(am_opts *fo)
96 char *ho = fo->opt_rhost;
100 if (fo->opt_sublink && fo->opt_sublink[0])
101 cp = fo->opt_sublink;
106 plog(XLOG_USER, "amfs_nfsl: host $fs and $rhost must be specified");
111 * If this host is not the same as $rhost, or if link does not exist,
112 * call nfs_ops.fs_match().
113 * If link value exists (or same host), call amfs_link_ops.fs_match().
115 if (!STRCEQ(ho, am_get_hostname()) && !STRCEQ(ho, hostd)) {
116 plog(XLOG_INFO, "amfs_nfsl: \"%s\" is not the local host \"%s\", "
117 "or \"%s\" using type:=nfs", ho, am_get_hostname(), hostd);
118 retval = nfs_ops.fs_match(fo);
119 } else if (lstat(cp, &stb) < 0) {
120 plog(XLOG_INFO, "amfs_nfsl: \"%s\" does not exist, using type:=nfs", cp);
121 retval = nfs_ops.fs_match(fo);
123 plog(XLOG_INFO, "amfs_nfsl: \"%s\" exists, using type:=link", cp);
124 retval = amfs_link_ops.fs_match(fo);
132 * Returns: 0 if OK, non-zero (errno) if failed.
135 amfs_nfsl_init(mntfs *mf)
138 if (mf->mf_flags & MFF_NFSLINK) {
139 if (amfs_link_ops.fs_init)
140 ret = amfs_link_ops.fs_init(mf);
143 ret = nfs_ops.fs_init(mf);
151 * Returns: 0 if OK, non-zero (errno) if failed.
154 amfs_nfsl_mount(am_node *mp, mntfs *mf)
157 if (mf->mf_flags & MFF_NFSLINK) {
158 if (amfs_link_ops.mount_fs)
159 ret = amfs_link_ops.mount_fs(mp, mf);
161 if (nfs_ops.mount_fs)
162 ret = nfs_ops.mount_fs(mp, mf);
170 * Returns: 0 if OK, non-zero (errno) if failed.
173 amfs_nfsl_umount(am_node *mp, mntfs *mf)
176 if (mf->mf_flags & MFF_NFSLINK) {
177 if (amfs_link_ops.umount_fs)
178 ret = amfs_link_ops.umount_fs(mp, mf);
180 if (nfs_ops.umount_fs)
181 ret = nfs_ops.umount_fs(mp, mf);
188 * Async unmount callback function.
189 * After the base umount() succeeds, we may want to take extra actions,
190 * such as informing remote mount daemons that we've unmounted them.
191 * See amfs_auto_umounted(), host_umounted(), nfs_umounted().
194 amfs_nfsl_umounted(mntfs *mf)
196 if (mf->mf_flags & MFF_NFSLINK) {
197 if (amfs_link_ops.umounted)
198 amfs_link_ops.umounted(mf);
200 if (nfs_ops.umounted)
201 nfs_ops.umounted(mf);
207 * Find a file server.
208 * Returns: fserver of found server, or NULL if not found.
211 amfs_nfsl_ffserver(mntfs *mf)
216 if (mf->mf_fo == NULL) {
217 plog(XLOG_ERROR, "%s: NULL mf_fo", __func__);
220 ho = mf->mf_fo->opt_rhost;
222 if (mf->mf_fo->opt_sublink && mf->mf_fo->opt_sublink[0])
223 cp = mf->mf_fo->opt_sublink;
225 cp = mf->mf_fo->opt_fs;
228 * If this host is not the same as $rhost, or if link does not exist,
229 * call amfs_link_ops.ffserver().
230 * If link value exists (or same host), then call ops_nfs.ffserver().
232 if ((!STRCEQ(ho, am_get_hostname()) &&
233 !STRCEQ(ho, hostd)) || lstat(cp, &stb) < 0) {
234 return nfs_ops.ffserver(mf);
236 mf->mf_flags |= MFF_NFSLINK;
237 /* remove the FS_MKMNT flag, we don't want amd touching the mountpoint */
238 mf->mf_fsflags &= ~FS_MKMNT;
239 return amfs_link_ops.ffserver(mf);