Merge branch 'vendor/ZLIB'
[dragonfly.git] / contrib / amd / amd / amfs_nfsl.c
1 /*
2  * Copyright (c) 1997-1999 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  *      %W% (Berkeley) %G%
40  *
41  * $Id: amfs_nfsl.c,v 1.3 1999/01/10 21:53:42 ezk Exp $
42  *
43  */
44
45 /*
46  * NFSL: Network file system with local existence check.  If the local
47  * path denoted by $rfs exists, it behaves as type:=link.
48  *
49  * Example:
50  *      pkg     type:=nfsl;rhost:=jonny;rfs:=/n/johnny/src/pkg;fs:=${rfs}
51  */
52
53 #ifdef HAVE_CONFIG_H
54 # include <config.h>
55 #endif /* HAVE_CONFIG_H */
56 #include <am_defs.h>
57 #include <amd.h>
58
59
60 /* forward declarations */
61 static char *amfs_nfsl_match(am_opts *fo);
62 static int amfs_nfsl_init(mntfs *mf);
63 static int amfs_nfsl_fmount(mntfs *mf);
64 static int amfs_nfsl_fumount(mntfs *mf);
65 static void amfs_nfsl_umounted(am_node *mp);
66 static fserver *amfs_nfsl_ffserver(mntfs *mf);
67
68 /*
69  * NFS-Link operations
70  */
71 am_ops amfs_nfsl_ops =
72 {
73   "nfsl",                       /* name of file system */
74   amfs_nfsl_match,              /* match */
75   amfs_nfsl_init,               /* initialize */
76   amfs_auto_fmount,             /* mount vnode */
77   amfs_nfsl_fmount,             /* mount vfs */
78   amfs_auto_fumount,            /* unmount vnode */
79   amfs_nfsl_fumount,            /* unmount VFS */
80   amfs_error_lookuppn,          /* lookup path-name */
81   amfs_error_readdir,           /* read directory */
82   0,                            /* read link */
83   0,                            /* after-mount extra actions */
84   amfs_nfsl_umounted,           /* after-umount extra actions */
85   amfs_nfsl_ffserver,           /* find a file server */
86   FS_MKMNT | FS_BACKGROUND | FS_AMQINFO /* flags */
87 };
88
89
90 /*
91  * Check that f/s has all needed fields.
92  * Returns: matched string if found, NULL otherwise.
93  */
94 static char *
95 amfs_nfsl_match(am_opts *fo)
96 {
97   char *cp = fo->opt_fs;
98   char *ho = fo->opt_rhost;
99   struct stat stb;
100
101   if (!cp || !ho) {
102     plog(XLOG_USER, "amfs_nfsl: host $fs and $rhost must be specified");
103     return NULL;
104   }
105
106   /*
107    * If this host is not the same as $rhost, or if link does not exist,
108    * perform nfs_match(), same as for type:=nfs.
109    * If link value exists (or same host), then perform amfs_link_match(),
110    * same as for linkx.
111    */
112   if (!STRCEQ(ho, am_get_hostname())) {
113     plog(XLOG_INFO, "amfs_nfsl: \"%s\" is not local host, using type:=nfs", ho);
114     return nfs_match(fo);
115   } else if (lstat(cp, &stb) < 0) {
116     plog(XLOG_INFO, "amfs_nfsl: \"%s\" does not exist, using type:=nfs", cp);
117     return nfs_match(fo);
118   } else {
119     plog(XLOG_INFO, "amfs_nfsl: \"%s\" exists, using type:=link", cp);
120     return amfs_link_match(fo);
121   }
122 }
123
124
125 /*
126  * Initialize.
127  * Returns: 0 if OK, non-zero (errno) if failed.
128  */
129 static int
130 amfs_nfsl_init(mntfs *mf)
131 {
132   /*
133    * If a link, do nothing (same as type:=link).
134    * If non-link, do nfs_init (same as type:=nfs).
135    */
136   if (mf->mf_flags & MFF_NFSLINK) {
137     return 0;
138   } else {
139     return nfs_init(mf);
140   }
141 }
142
143
144 /*
145  * Mount vfs.
146  * Returns: 0 if OK, non-zero (errno) if failed.
147  */
148 static int
149 amfs_nfsl_fmount(mntfs *mf)
150 {
151   /*
152    * If a link, do run amfs_link_fmount() (same as type:=link)
153    * If non-link, do nfs_fmount (same as type:=nfs).
154    */
155   if (mf->mf_flags & MFF_NFSLINK) {
156     return amfs_link_fmount(mf);
157   } else {
158     return nfs_fmount(mf);
159   }
160 }
161
162
163 /*
164  * Unmount VFS.
165  * Returns: 0 if OK, non-zero (errno) if failed.
166  */
167 static int
168 amfs_nfsl_fumount(mntfs *mf)
169 {
170   /*
171    * If a link, do run amfs_link_fumount() (same as type:=link)
172    * If non-link, do nfs_fumount (same as type:=nfs).
173    */
174   if (mf->mf_flags & MFF_NFSLINK) {
175     return amfs_link_fumount(mf);
176   } else {
177     return nfs_fumount(mf);
178   }
179 }
180
181
182 /*
183  * Async unmount callback function.
184  * After the base umount() succeeds, we may want to take extra actions,
185  * such as informing remote mount daemons that we've unmounted them.
186  * See amfs_auto_umounted(), host_umounted(), nfs_umounted().
187  */
188 static void
189 amfs_nfsl_umounted(am_node *mp)
190 {
191   mntfs *mf = mp->am_mnt;
192
193   /*
194    * If a link, do nothing (same as type:=link)
195    * If non-link, do nfs_fumount (same as type:=nfs).
196    */
197   if (mf->mf_flags & MFF_NFSLINK) {
198     return;
199   } else {
200     nfs_umounted(mp);
201     /*
202      * MUST remove mount point directories, because if they remain
203      * behind, the next nfsl access will think they are a link
204      * type file system, and not NFS! (when it performs link target
205      * existence test)
206      */
207     if (mf->mf_flags & MFF_MKMNT)
208       rmdirs(mf->mf_mount);
209     return;
210   }
211 }
212
213
214 /*
215  * Find a file server.
216  * Returns: fserver of found server, or NULL if not found.
217  */
218 static fserver *
219 amfs_nfsl_ffserver(mntfs *mf)
220 {
221   char *cp = mf->mf_fo->opt_fs;
222   char *ho = mf->mf_fo->opt_rhost;
223   struct stat stb;
224
225   /*
226    * If this host is not the same as $rhost, or if link does not exist,
227    * perform find_nfs_srvr(), same as for type:=nfs.
228    * If link value exists (or same host), then perform
229    * find_amfs_auto_srvr(), same as for linkx.
230    */
231   if (!STRCEQ(ho, am_get_hostname()) || lstat(cp, &stb) < 0) {
232     return find_nfs_srvr(mf);
233   } else {
234     mf->mf_flags |= MFF_NFSLINK;
235     return find_amfs_auto_srvr(mf);
236   }
237 }