4 * Copyright (c) 1997-2009 Erez Zadok
5 * Copyright (c) 1990 Jan-Simon Pendry
6 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
7 * Copyright (c) 1990 The Regents of the University of California.
10 * This code is derived from software contributed to Berkeley by
11 * Jan-Simon Pendry at Imperial College, London.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 * must display the following acknowledgment:
23 * This product includes software developed by the University of
24 * California, Berkeley and its contributors.
25 * 4. Neither the name of the University nor the names of its contributors
26 * may be used to endorse or promote products derived from this software
27 * without specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 * File: am-utils/amd/amfs_nfsl.c
47 * NFSL: Network file system with local existence check. If the local
48 * path denoted by $rfs exists, it behaves as type:=link.
51 * pkg type:=nfsl;rhost:=jonny;rfs:=/n/johnny/src/pkg;fs:=${rfs}
56 #endif /* HAVE_CONFIG_H */
61 /* forward declarations */
62 static char *amfs_nfsl_match(am_opts
*fo
);
63 static int amfs_nfsl_init(mntfs
*mf
);
64 static int amfs_nfsl_mount(am_node
*mp
, mntfs
*mf
);
65 static int amfs_nfsl_umount(am_node
*mp
, mntfs
*mf
);
66 static void amfs_nfsl_umounted(mntfs
*mf
);
67 static fserver
*amfs_nfsl_ffserver(mntfs
*mf
);
72 am_ops amfs_nfsl_ops
=
79 amfs_error_lookup_child
,
80 amfs_error_mount_child
,
82 0, /* amfs_nfsl_readlink */
83 0, /* amfs_nfsl_mounted */
86 0, /* amfs_nfsl_get_wchan */
87 FS_MKMNT
| FS_BACKGROUND
| FS_AMQINFO
, /* nfs_fs_flags */
90 #endif /* HAVE_FS_AUTOFS */
95 * Check that f/s has all needed fields.
96 * Returns: matched string if found, NULL otherwise.
99 amfs_nfsl_match(am_opts
*fo
)
102 char *ho
= fo
->opt_rhost
;
106 if (fo
->opt_sublink
&& fo
->opt_sublink
[0])
107 cp
= fo
->opt_sublink
;
112 plog(XLOG_USER
, "amfs_nfsl: host $fs and $rhost must be specified");
117 * If this host is not the same as $rhost, or if link does not exist,
118 * call nfs_ops.fs_match().
119 * If link value exists (or same host), call amfs_link_ops.fs_match().
121 if (!STRCEQ(ho
, am_get_hostname())) {
122 plog(XLOG_INFO
, "amfs_nfsl: \"%s\" is not local host, using type:=nfs", ho
);
123 retval
= nfs_ops
.fs_match(fo
);
124 } else if (lstat(cp
, &stb
) < 0) {
125 plog(XLOG_INFO
, "amfs_nfsl: \"%s\" does not exist, using type:=nfs", cp
);
126 retval
= nfs_ops
.fs_match(fo
);
128 plog(XLOG_INFO
, "amfs_nfsl: \"%s\" exists, using type:=link", cp
);
129 retval
= amfs_link_ops
.fs_match(fo
);
137 * Returns: 0 if OK, non-zero (errno) if failed.
140 amfs_nfsl_init(mntfs
*mf
)
143 if (mf
->mf_flags
& MFF_NFSLINK
) {
144 if (amfs_link_ops
.fs_init
)
145 ret
= amfs_link_ops
.fs_init(mf
);
148 ret
= nfs_ops
.fs_init(mf
);
156 * Returns: 0 if OK, non-zero (errno) if failed.
159 amfs_nfsl_mount(am_node
*mp
, mntfs
*mf
)
162 if (mf
->mf_flags
& MFF_NFSLINK
) {
163 if (amfs_link_ops
.mount_fs
)
164 ret
= amfs_link_ops
.mount_fs(mp
, mf
);
166 if (nfs_ops
.mount_fs
)
167 ret
= nfs_ops
.mount_fs(mp
, mf
);
175 * Returns: 0 if OK, non-zero (errno) if failed.
178 amfs_nfsl_umount(am_node
*mp
, mntfs
*mf
)
181 if (mf
->mf_flags
& MFF_NFSLINK
) {
182 if (amfs_link_ops
.umount_fs
)
183 ret
= amfs_link_ops
.umount_fs(mp
, mf
);
185 if (nfs_ops
.umount_fs
)
186 ret
= nfs_ops
.umount_fs(mp
, mf
);
193 * Async unmount callback function.
194 * After the base umount() succeeds, we may want to take extra actions,
195 * such as informing remote mount daemons that we've unmounted them.
196 * See amfs_auto_umounted(), host_umounted(), nfs_umounted().
199 amfs_nfsl_umounted(mntfs
*mf
)
201 if (mf
->mf_flags
& MFF_NFSLINK
) {
202 if (amfs_link_ops
.umounted
)
203 amfs_link_ops
.umounted(mf
);
205 if (nfs_ops
.umounted
)
206 nfs_ops
.umounted(mf
);
212 * Find a file server.
213 * Returns: fserver of found server, or NULL if not found.
216 amfs_nfsl_ffserver(mntfs
*mf
)
219 char *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()) || lstat(cp
, &stb
) < 0) {
233 return nfs_ops
.ffserver(mf
);
235 mf
->mf_flags
|= MFF_NFSLINK
;
236 /* remove the FS_MKMNT flag, we don't want amd touching the mountpoint */
237 mf
->mf_fsflags
&= ~FS_MKMNT
;
238 return amfs_link_ops
.ffserver(mf
);