]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/amd/amd/amfs_nfsl.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / amd / amd / amfs_nfsl.c
1 /*
2  * Copyright (c) 1997-2006 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.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Jan-Simon Pendry at Imperial College, London.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
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. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgment:
21  *      This product includes software developed by the University of
22  *      California, Berkeley and its contributors.
23  * 4. Neither the name of the University nor the names of its contributors
24  *    may be used to endorse or promote products derived from this software
25  *    without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  *
39  *
40  * File: am-utils/amd/amfs_nfsl.c
41  *
42  */
43
44 /*
45  * NFSL: Network file system with local existence check.  If the local
46  * path denoted by $rfs exists, it behaves as type:=link.
47  *
48  * Example:
49  *      pkg     type:=nfsl;rhost:=jonny;rfs:=/n/johnny/src/pkg;fs:=${rfs}
50  */
51
52 #ifdef HAVE_CONFIG_H
53 # include <config.h>
54 #endif /* HAVE_CONFIG_H */
55 #include <am_defs.h>
56 #include <amd.h>
57
58
59 /* forward declarations */
60 static char *amfs_nfsl_match(am_opts *fo);
61 static int amfs_nfsl_init(mntfs *mf);
62 static int amfs_nfsl_mount(am_node *mp, mntfs *mf);
63 static int amfs_nfsl_umount(am_node *mp, mntfs *mf);
64 static void amfs_nfsl_umounted(mntfs *mf);
65 static fserver *amfs_nfsl_ffserver(mntfs *mf);
66
67 /*
68  * NFS-Link operations
69  */
70 am_ops amfs_nfsl_ops =
71 {
72   "nfsl",
73   amfs_nfsl_match,
74   amfs_nfsl_init,
75   amfs_nfsl_mount,
76   amfs_nfsl_umount,
77   amfs_error_lookup_child,
78   amfs_error_mount_child,
79   amfs_error_readdir,
80   0,                            /* amfs_nfsl_readlink */
81   0,                            /* amfs_nfsl_mounted */
82   amfs_nfsl_umounted,
83   amfs_nfsl_ffserver,
84   0,                            /* amfs_nfsl_get_wchan */
85   FS_MKMNT | FS_BACKGROUND | FS_AMQINFO,        /* nfs_fs_flags */
86 #ifdef HAVE_FS_AUTOFS
87   AUTOFS_NFSL_FS_FLAGS,
88 #endif /* HAVE_FS_AUTOFS */
89 };
90
91
92 /*
93  * Check that f/s has all needed fields.
94  * Returns: matched string if found, NULL otherwise.
95  */
96 static char *
97 amfs_nfsl_match(am_opts *fo)
98 {
99   char *cp;
100   char *ho = fo->opt_rhost;
101   char *retval;
102   struct stat stb;
103
104   if (fo->opt_sublink)
105     cp = fo->opt_sublink;
106   else
107     cp = fo->opt_fs;
108
109   if (!cp || !ho) {
110     plog(XLOG_USER, "amfs_nfsl: host $fs and $rhost must be specified");
111     return NULL;
112   }
113
114   /*
115    * If this host is not the same as $rhost, or if link does not exist,
116    * call nfs_ops.fs_match().
117    * If link value exists (or same host), call amfs_link_ops.fs_match().
118    */
119   if (!STRCEQ(ho, am_get_hostname())) {
120     plog(XLOG_INFO, "amfs_nfsl: \"%s\" is not local host, using type:=nfs", ho);
121     retval = nfs_ops.fs_match(fo);
122   } else if (lstat(cp, &stb) < 0) {
123     plog(XLOG_INFO, "amfs_nfsl: \"%s\" does not exist, using type:=nfs", cp);
124     retval = nfs_ops.fs_match(fo);
125   } else {
126     plog(XLOG_INFO, "amfs_nfsl: \"%s\" exists, using type:=link", cp);
127     retval = amfs_link_ops.fs_match(fo);
128   }
129   return retval;
130 }
131
132
133 /*
134  * Initialize.
135  * Returns: 0 if OK, non-zero (errno) if failed.
136  */
137 static int
138 amfs_nfsl_init(mntfs *mf)
139 {
140   int ret = 0;
141   if (mf->mf_flags & MFF_NFSLINK) {
142     if (amfs_link_ops.fs_init)
143       ret = amfs_link_ops.fs_init(mf);
144   } else {
145     if (nfs_ops.fs_init)
146       ret = nfs_ops.fs_init(mf);
147   }
148   return ret;
149 }
150
151
152 /*
153  * Mount vfs.
154  * Returns: 0 if OK, non-zero (errno) if failed.
155  */
156 static int
157 amfs_nfsl_mount(am_node *mp, mntfs *mf)
158 {
159   int ret = 0;
160   if (mf->mf_flags & MFF_NFSLINK) {
161     if (amfs_link_ops.mount_fs)
162       ret = amfs_link_ops.mount_fs(mp, mf);
163   } else {
164     if (nfs_ops.mount_fs)
165       ret = nfs_ops.mount_fs(mp, mf);
166   }
167   return ret;
168 }
169
170
171 /*
172  * Unmount VFS.
173  * Returns: 0 if OK, non-zero (errno) if failed.
174  */
175 static int
176 amfs_nfsl_umount(am_node *mp, mntfs *mf)
177 {
178   int ret = 0;
179   if (mf->mf_flags & MFF_NFSLINK) {
180     if (amfs_link_ops.umount_fs)
181       ret = amfs_link_ops.umount_fs(mp, mf);
182   } else {
183     if (nfs_ops.umount_fs)
184       ret = nfs_ops.umount_fs(mp, mf);
185   }
186   return ret;
187 }
188
189
190 /*
191  * Async unmount callback function.
192  * After the base umount() succeeds, we may want to take extra actions,
193  * such as informing remote mount daemons that we've unmounted them.
194  * See amfs_auto_umounted(), host_umounted(), nfs_umounted().
195  */
196 static void
197 amfs_nfsl_umounted(mntfs *mf)
198 {
199   if (mf->mf_flags & MFF_NFSLINK) {
200     if (amfs_link_ops.umounted)
201       amfs_link_ops.umounted(mf);
202   } else {
203     if (nfs_ops.umounted)
204       nfs_ops.umounted(mf);
205   }
206 }
207
208
209 /*
210  * Find a file server.
211  * Returns: fserver of found server, or NULL if not found.
212  */
213 static fserver *
214 amfs_nfsl_ffserver(mntfs *mf)
215 {
216   char *cp;
217   char *ho = mf->mf_fo->opt_rhost;
218   struct stat stb;
219
220   if (mf->mf_fo->opt_sublink)
221     cp = mf->mf_fo->opt_sublink;
222   else
223     cp = mf->mf_fo->opt_fs;
224
225   /*
226    * If this host is not the same as $rhost, or if link does not exist,
227    * call amfs_link_ops.ffserver().
228    * If link value exists (or same host), then call ops_nfs.ffserver().
229    */
230   if (!STRCEQ(ho, am_get_hostname()) || lstat(cp, &stb) < 0) {
231     return nfs_ops.ffserver(mf);
232   } else {
233     mf->mf_flags |= MFF_NFSLINK;
234     /* remove the FS_MKMNT flag, we don't want amd touching the mountpoint */
235     mf->mf_fsflags &= ~FS_MKMNT;
236     return amfs_link_ops.ffserver(mf);
237   }
238 }