xref: /netbsd-src/external/bsd/am-utils/dist/amd/amfs_nfsl.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
1 /*	$NetBSD: amfs_nfsl.c,v 1.1.1.2 2009/03/20 20:26:49 christos Exp $	*/
2 
3 /*
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.
8  * All rights reserved.
9  *
10  * This code is derived from software contributed to Berkeley by
11  * Jan-Simon Pendry at Imperial College, London.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
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.
28  *
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
39  * SUCH DAMAGE.
40  *
41  *
42  * File: am-utils/amd/amfs_nfsl.c
43  *
44  */
45 
46 /*
47  * NFSL: Network file system with local existence check.  If the local
48  * path denoted by $rfs exists, it behaves as type:=link.
49  *
50  * Example:
51  *	pkg	type:=nfsl;rhost:=jonny;rfs:=/n/johnny/src/pkg;fs:=${rfs}
52  */
53 
54 #ifdef HAVE_CONFIG_H
55 # include <config.h>
56 #endif /* HAVE_CONFIG_H */
57 #include <am_defs.h>
58 #include <amd.h>
59 
60 
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);
68 
69 /*
70  * NFS-Link operations
71  */
72 am_ops amfs_nfsl_ops =
73 {
74   "nfsl",
75   amfs_nfsl_match,
76   amfs_nfsl_init,
77   amfs_nfsl_mount,
78   amfs_nfsl_umount,
79   amfs_error_lookup_child,
80   amfs_error_mount_child,
81   amfs_error_readdir,
82   0,				/* amfs_nfsl_readlink */
83   0,				/* amfs_nfsl_mounted */
84   amfs_nfsl_umounted,
85   amfs_nfsl_ffserver,
86   0,				/* amfs_nfsl_get_wchan */
87   FS_MKMNT | FS_BACKGROUND | FS_AMQINFO,	/* nfs_fs_flags */
88 #ifdef HAVE_FS_AUTOFS
89   AUTOFS_NFSL_FS_FLAGS,
90 #endif /* HAVE_FS_AUTOFS */
91 };
92 
93 
94 /*
95  * Check that f/s has all needed fields.
96  * Returns: matched string if found, NULL otherwise.
97  */
98 static char *
99 amfs_nfsl_match(am_opts *fo)
100 {
101   char *cp;
102   char *ho = fo->opt_rhost;
103   char *retval;
104   struct stat stb;
105 
106   if (fo->opt_sublink && fo->opt_sublink[0])
107     cp = fo->opt_sublink;
108   else
109     cp = fo->opt_fs;
110 
111   if (!cp || !ho) {
112     plog(XLOG_USER, "amfs_nfsl: host $fs and $rhost must be specified");
113     return NULL;
114   }
115 
116   /*
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().
120    */
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);
127   } else {
128     plog(XLOG_INFO, "amfs_nfsl: \"%s\" exists, using type:=link", cp);
129     retval = amfs_link_ops.fs_match(fo);
130   }
131   return retval;
132 }
133 
134 
135 /*
136  * Initialize.
137  * Returns: 0 if OK, non-zero (errno) if failed.
138  */
139 static int
140 amfs_nfsl_init(mntfs *mf)
141 {
142   int ret = 0;
143   if (mf->mf_flags & MFF_NFSLINK) {
144     if (amfs_link_ops.fs_init)
145       ret = amfs_link_ops.fs_init(mf);
146   } else {
147     if (nfs_ops.fs_init)
148       ret = nfs_ops.fs_init(mf);
149   }
150   return ret;
151 }
152 
153 
154 /*
155  * Mount vfs.
156  * Returns: 0 if OK, non-zero (errno) if failed.
157  */
158 static int
159 amfs_nfsl_mount(am_node *mp, mntfs *mf)
160 {
161   int ret = 0;
162   if (mf->mf_flags & MFF_NFSLINK) {
163     if (amfs_link_ops.mount_fs)
164       ret = amfs_link_ops.mount_fs(mp, mf);
165   } else {
166     if (nfs_ops.mount_fs)
167       ret = nfs_ops.mount_fs(mp, mf);
168   }
169   return ret;
170 }
171 
172 
173 /*
174  * Unmount VFS.
175  * Returns: 0 if OK, non-zero (errno) if failed.
176  */
177 static int
178 amfs_nfsl_umount(am_node *mp, mntfs *mf)
179 {
180   int ret = 0;
181   if (mf->mf_flags & MFF_NFSLINK) {
182     if (amfs_link_ops.umount_fs)
183       ret = amfs_link_ops.umount_fs(mp, mf);
184   } else {
185     if (nfs_ops.umount_fs)
186       ret = nfs_ops.umount_fs(mp, mf);
187   }
188   return ret;
189 }
190 
191 
192 /*
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().
197  */
198 static void
199 amfs_nfsl_umounted(mntfs *mf)
200 {
201   if (mf->mf_flags & MFF_NFSLINK) {
202     if (amfs_link_ops.umounted)
203       amfs_link_ops.umounted(mf);
204   } else {
205     if (nfs_ops.umounted)
206       nfs_ops.umounted(mf);
207   }
208 }
209 
210 
211 /*
212  * Find a file server.
213  * Returns: fserver of found server, or NULL if not found.
214  */
215 static fserver *
216 amfs_nfsl_ffserver(mntfs *mf)
217 {
218   char *cp;
219   char *ho = mf->mf_fo->opt_rhost;
220   struct stat stb;
221 
222   if (mf->mf_fo->opt_sublink && mf->mf_fo->opt_sublink[0])
223     cp = mf->mf_fo->opt_sublink;
224   else
225     cp = mf->mf_fo->opt_fs;
226 
227   /*
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().
231    */
232   if (!STRCEQ(ho, am_get_hostname()) || lstat(cp, &stb) < 0) {
233     return nfs_ops.ffserver(mf);
234   } else {
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);
239   }
240 }
241