1*8bae5d40Schristos /* $NetBSD: am_ops.c,v 1.1.1.3 2015/01/17 16:34:15 christos Exp $ */
2a53f50b9Schristos
3a53f50b9Schristos /*
4*8bae5d40Schristos * Copyright (c) 1997-2014 Erez Zadok
5a53f50b9Schristos * Copyright (c) 1989 Jan-Simon Pendry
6a53f50b9Schristos * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
7a53f50b9Schristos * Copyright (c) 1989 The Regents of the University of California.
8a53f50b9Schristos * All rights reserved.
9a53f50b9Schristos *
10a53f50b9Schristos * This code is derived from software contributed to Berkeley by
11a53f50b9Schristos * Jan-Simon Pendry at Imperial College, London.
12a53f50b9Schristos *
13a53f50b9Schristos * Redistribution and use in source and binary forms, with or without
14a53f50b9Schristos * modification, are permitted provided that the following conditions
15a53f50b9Schristos * are met:
16a53f50b9Schristos * 1. Redistributions of source code must retain the above copyright
17a53f50b9Schristos * notice, this list of conditions and the following disclaimer.
18a53f50b9Schristos * 2. Redistributions in binary form must reproduce the above copyright
19a53f50b9Schristos * notice, this list of conditions and the following disclaimer in the
20a53f50b9Schristos * documentation and/or other materials provided with the distribution.
21*8bae5d40Schristos * 3. Neither the name of the University nor the names of its contributors
22a53f50b9Schristos * may be used to endorse or promote products derived from this software
23a53f50b9Schristos * without specific prior written permission.
24a53f50b9Schristos *
25a53f50b9Schristos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26a53f50b9Schristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27a53f50b9Schristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28a53f50b9Schristos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29a53f50b9Schristos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30a53f50b9Schristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31a53f50b9Schristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32a53f50b9Schristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33a53f50b9Schristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34a53f50b9Schristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35a53f50b9Schristos * SUCH DAMAGE.
36a53f50b9Schristos *
37a53f50b9Schristos *
38a53f50b9Schristos * File: am-utils/amd/am_ops.c
39a53f50b9Schristos *
40a53f50b9Schristos */
41a53f50b9Schristos
42a53f50b9Schristos #ifdef HAVE_CONFIG_H
43a53f50b9Schristos # include <config.h>
44a53f50b9Schristos #endif /* HAVE_CONFIG_H */
45a53f50b9Schristos #include <am_defs.h>
46a53f50b9Schristos #include <amd.h>
47a53f50b9Schristos
48a53f50b9Schristos
49a53f50b9Schristos /*
50a53f50b9Schristos * The order of these entries matters, since lookups in this table are done
51a53f50b9Schristos * on a first-match basis. The entries below are a mixture of native
52a53f50b9Schristos * filesystems supported by the OS (HAVE_FS_FOO), and some meta-filesystems
53a53f50b9Schristos * supported by amd (HAVE_AMU_FS_FOO). The order is set here in expected
54a53f50b9Schristos * match-hit such that more popular filesystems are listed first (nfs is the
55a53f50b9Schristos * most popular, followed by a symlink F/S)
56a53f50b9Schristos */
57a53f50b9Schristos static am_ops *vops[] =
58a53f50b9Schristos {
59a53f50b9Schristos #ifdef HAVE_FS_NFS
60a53f50b9Schristos &nfs_ops, /* network F/S (version 2) */
61a53f50b9Schristos #endif /* HAVE_FS_NFS */
62a53f50b9Schristos #ifdef HAVE_AMU_FS_LINK
63a53f50b9Schristos &amfs_link_ops, /* symlink F/S */
64a53f50b9Schristos #endif /* HAVE_AMU_FS_LINK */
65a53f50b9Schristos
66a53f50b9Schristos /*
67a53f50b9Schristos * Other amd-supported meta-filesystems.
68a53f50b9Schristos */
69a53f50b9Schristos #ifdef HAVE_AMU_FS_NFSX
70a53f50b9Schristos &amfs_nfsx_ops, /* multiple-nfs F/S */
71a53f50b9Schristos #endif /* HAVE_AMU_FS_NFSX */
72a53f50b9Schristos #ifdef HAVE_AMU_FS_NFSL
73a53f50b9Schristos &amfs_nfsl_ops, /* NFS with local link existence check */
74a53f50b9Schristos #endif /* HAVE_AMU_FS_NFSL */
75a53f50b9Schristos #ifdef HAVE_AMU_FS_HOST
76a53f50b9Schristos &amfs_host_ops, /* multiple exported nfs F/S */
77a53f50b9Schristos #endif /* HAVE_AMU_FS_HOST */
78a53f50b9Schristos #ifdef HAVE_AMU_FS_LINKX
79a53f50b9Schristos &amfs_linkx_ops, /* symlink F/S with link target verify */
80a53f50b9Schristos #endif /* HAVE_AMU_FS_LINKX */
81a53f50b9Schristos #ifdef HAVE_AMU_FS_PROGRAM
82a53f50b9Schristos &amfs_program_ops, /* program F/S */
83a53f50b9Schristos #endif /* HAVE_AMU_FS_PROGRAM */
84a53f50b9Schristos #ifdef HAVE_AMU_FS_UNION
85a53f50b9Schristos &amfs_union_ops, /* union F/S */
86a53f50b9Schristos #endif /* HAVE_AMU_FS_UNION */
87a53f50b9Schristos
88a53f50b9Schristos /*
89a53f50b9Schristos * A few more native filesystems.
90a53f50b9Schristos */
91a53f50b9Schristos #ifdef HAVE_FS_UFS
92a53f50b9Schristos &ufs_ops, /* Unix F/S */
93a53f50b9Schristos #endif /* HAVE_FS_UFS */
94a53f50b9Schristos #ifdef HAVE_FS_XFS
95a53f50b9Schristos &xfs_ops, /* Unix (irix) F/S */
96a53f50b9Schristos #endif /* HAVE_FS_XFS */
97*8bae5d40Schristos #ifdef HAVE_FS_EXT
98*8bae5d40Schristos &ext2_ops, /* Unix (linux) F/S */
99*8bae5d40Schristos &ext3_ops, /* Unix (linux) F/S */
100*8bae5d40Schristos &ext4_ops, /* Unix (linux) F/S */
101*8bae5d40Schristos #endif /* HAVE_FS_EXT */
102a53f50b9Schristos #ifdef HAVE_FS_EFS
103a53f50b9Schristos &efs_ops, /* Unix (irix) F/S */
104a53f50b9Schristos #endif /* HAVE_FS_EFS */
105a53f50b9Schristos #ifdef HAVE_FS_LOFS
106a53f50b9Schristos &lofs_ops, /* loopback F/S */
107a53f50b9Schristos #endif /* HAVE_FS_LOFS */
108a53f50b9Schristos #ifdef HAVE_FS_CDFS
109a53f50b9Schristos &cdfs_ops, /* CDROM/HSFS/ISO9960 F/S */
110a53f50b9Schristos #endif /* HAVE_FS_CDFS */
111a53f50b9Schristos #ifdef HAVE_FS_PCFS
112a53f50b9Schristos &pcfs_ops, /* Floppy/MSDOS F/S */
113a53f50b9Schristos #endif /* HAVE_FS_PCFS */
114a53f50b9Schristos #ifdef HAVE_FS_CACHEFS
115a53f50b9Schristos &cachefs_ops, /* caching F/S */
116a53f50b9Schristos #endif /* HAVE_FS_CACHEFS */
117a53f50b9Schristos #ifdef HAVE_FS_TMPFS
118a53f50b9Schristos &tmpfs_ops, /* /tmp (in memory) F/S */
119a53f50b9Schristos #endif /* HAVE_FS_TMPFS */
120a53f50b9Schristos #ifdef HAVE_FS_NULLFS
121a53f50b9Schristos /* FILL IN */ /* null (loopback) F/S */
122a53f50b9Schristos #endif /* HAVE_FS_NULLFS */
123a53f50b9Schristos #ifdef HAVE_FS_UNIONFS
124a53f50b9Schristos /* FILL IN */ /* union (bsd44) F/S */
125a53f50b9Schristos #endif /* HAVE_FS_UNIONFS */
126a53f50b9Schristos #ifdef HAVE_FS_UMAPFS
127a53f50b9Schristos /* FILL IN */ /* uid/gid mapping F/S */
128a53f50b9Schristos #endif /* HAVE_FS_UMAPFS */
1294bcd344eSchristos #ifdef HAVE_FS_UDF
1304bcd344eSchristos &udf_ops, /* UDF F/S */
1314bcd344eSchristos #endif /* HAVE_FS_UDF */
132*8bae5d40Schristos #ifdef HAVE_FS_LUSTRE
133*8bae5d40Schristos &lustre_ops, /* Lustre */
134*8bae5d40Schristos #endif /* HAVE_FS_LUSTRE */
135a53f50b9Schristos
136a53f50b9Schristos /*
137a53f50b9Schristos * These 4 should be last, in the order:
138a53f50b9Schristos * (1) amfs_auto
139a53f50b9Schristos * (2) amfs_direct
140a53f50b9Schristos * (3) amfs_toplvl
141a53f50b9Schristos * (4) amfs_error
142a53f50b9Schristos */
143a53f50b9Schristos #ifdef HAVE_AMU_FS_AUTO
144a53f50b9Schristos &amfs_auto_ops, /* Automounter F/S */
145a53f50b9Schristos #endif /* HAVE_AMU_FS_AUTO */
146a53f50b9Schristos #ifdef HAVE_AMU_FS_DIRECT
147a53f50b9Schristos &amfs_direct_ops, /* direct-mount F/S */
148a53f50b9Schristos #endif /* HAVE_AMU_FS_DIRECT */
149a53f50b9Schristos #ifdef HAVE_AMU_FS_TOPLVL
150a53f50b9Schristos &amfs_toplvl_ops, /* top-level mount F/S */
151a53f50b9Schristos #endif /* HAVE_AMU_FS_TOPLVL */
152a53f50b9Schristos #ifdef HAVE_AMU_FS_ERROR
153a53f50b9Schristos &amfs_error_ops, /* error F/S */
154a53f50b9Schristos #endif /* HAVE_AMU_FS_ERROR */
155a53f50b9Schristos 0
156a53f50b9Schristos };
157a53f50b9Schristos
158a53f50b9Schristos
159a53f50b9Schristos void
ops_showamfstypes(char * buf,size_t l)160a53f50b9Schristos ops_showamfstypes(char *buf, size_t l)
161a53f50b9Schristos {
162a53f50b9Schristos struct am_ops **ap;
163a53f50b9Schristos int linesize = 0;
164a53f50b9Schristos
165a53f50b9Schristos buf[0] = '\0';
166a53f50b9Schristos for (ap = vops; *ap; ap++) {
167a53f50b9Schristos xstrlcat(buf, (*ap)->fs_type, l);
168a53f50b9Schristos if (ap[1])
169a53f50b9Schristos xstrlcat(buf, ", ", l);
170a53f50b9Schristos linesize += strlen((*ap)->fs_type) + 2;
171a53f50b9Schristos if (linesize > 62) {
172a53f50b9Schristos linesize = 0;
173a53f50b9Schristos xstrlcat(buf, "\n ", l);
174a53f50b9Schristos }
175a53f50b9Schristos }
176a53f50b9Schristos }
177a53f50b9Schristos
178a53f50b9Schristos
179a53f50b9Schristos static void
ops_show1(char * buf,size_t l,int * linesizep,const char * name)180a53f50b9Schristos ops_show1(char *buf, size_t l, int *linesizep, const char *name)
181a53f50b9Schristos {
182a53f50b9Schristos xstrlcat(buf, name, l);
183a53f50b9Schristos xstrlcat(buf, ", ", l);
184a53f50b9Schristos *linesizep += strlen(name) + 2;
185a53f50b9Schristos if (*linesizep > 60) {
186a53f50b9Schristos xstrlcat(buf, "\t\n", l);
187a53f50b9Schristos *linesizep = 0;
188a53f50b9Schristos }
189a53f50b9Schristos }
190a53f50b9Schristos
191a53f50b9Schristos
192a53f50b9Schristos void
ops_showfstypes(char * buf,size_t l)193a53f50b9Schristos ops_showfstypes(char *buf, size_t l)
194a53f50b9Schristos {
195a53f50b9Schristos int linesize = 0;
196a53f50b9Schristos
197a53f50b9Schristos buf[0] = '\0';
198a53f50b9Schristos
199a53f50b9Schristos #ifdef MNTTAB_TYPE_AUTOFS
200a53f50b9Schristos ops_show1(buf, l, &linesize, MNTTAB_TYPE_AUTOFS);
201a53f50b9Schristos #endif /* MNTTAB_TYPE_AUTOFS */
202a53f50b9Schristos
203a53f50b9Schristos #ifdef MNTTAB_TYPE_CACHEFS
204a53f50b9Schristos ops_show1(buf, l, &linesize, MNTTAB_TYPE_CACHEFS);
205a53f50b9Schristos #endif /* MNTTAB_TYPE_CACHEFS */
206a53f50b9Schristos
207a53f50b9Schristos #ifdef MNTTAB_TYPE_CDFS
208a53f50b9Schristos ops_show1(buf, l, &linesize, MNTTAB_TYPE_CDFS);
209a53f50b9Schristos #endif /* MNTTAB_TYPE_CDFS */
210a53f50b9Schristos
211a53f50b9Schristos #ifdef MNTTAB_TYPE_CFS
212a53f50b9Schristos ops_show1(buf, l, &linesize, MNTTAB_TYPE_CFS);
213a53f50b9Schristos #endif /* MNTTAB_TYPE_CFS */
214a53f50b9Schristos
215a53f50b9Schristos #ifdef MNTTAB_TYPE_LOFS
216a53f50b9Schristos ops_show1(buf, l, &linesize, MNTTAB_TYPE_LOFS);
217a53f50b9Schristos #endif /* MNTTAB_TYPE_LOFS */
218a53f50b9Schristos
219a53f50b9Schristos #ifdef MNTTAB_TYPE_EFS
220a53f50b9Schristos ops_show1(buf, l, &linesize, MNTTAB_TYPE_EFS);
221a53f50b9Schristos #endif /* MNTTAB_TYPE_EFS */
222a53f50b9Schristos
223a53f50b9Schristos #ifdef MNTTAB_TYPE_MFS
224a53f50b9Schristos ops_show1(buf, l, &linesize, MNTTAB_TYPE_MFS);
225a53f50b9Schristos #endif /* MNTTAB_TYPE_MFS */
226a53f50b9Schristos
227a53f50b9Schristos #ifdef MNTTAB_TYPE_NFS
228a53f50b9Schristos ops_show1(buf, l, &linesize, MNTTAB_TYPE_NFS);
229a53f50b9Schristos #endif /* MNTTAB_TYPE_NFS */
230a53f50b9Schristos
231a53f50b9Schristos #ifdef MNTTAB_TYPE_NFS3
232a53f50b9Schristos ops_show1(buf, l, &linesize, "nfs3"); /* always hard-code as nfs3 */
233a53f50b9Schristos #endif /* MNTTAB_TYPE_NFS3 */
234a53f50b9Schristos
235a53f50b9Schristos #ifdef MNTTAB_TYPE_NULLFS
236a53f50b9Schristos ops_show1(buf, l, &linesize, MNTTAB_TYPE_NULLFS);
237a53f50b9Schristos #endif /* MNTTAB_TYPE_NULLFS */
238a53f50b9Schristos
239a53f50b9Schristos #ifdef MNTTAB_TYPE_PCFS
240a53f50b9Schristos ops_show1(buf, l, &linesize, MNTTAB_TYPE_PCFS);
241a53f50b9Schristos #endif /* MNTTAB_TYPE_PCFS */
242a53f50b9Schristos
243a53f50b9Schristos #ifdef MNTTAB_TYPE_TFS
244a53f50b9Schristos ops_show1(buf, l, &linesize, MNTTAB_TYPE_TFS);
245a53f50b9Schristos #endif /* MNTTAB_TYPE_TFS */
246a53f50b9Schristos
247a53f50b9Schristos #ifdef MNTTAB_TYPE_TMPFS
248a53f50b9Schristos ops_show1(buf, l, &linesize, MNTTAB_TYPE_TMPFS);
249a53f50b9Schristos #endif /* MNTTAB_TYPE_TMPFS */
250a53f50b9Schristos
251a53f50b9Schristos #ifdef MNTTAB_TYPE_UFS
252a53f50b9Schristos ops_show1(buf, l, &linesize, MNTTAB_TYPE_UFS);
253a53f50b9Schristos #endif /* MNTTAB_TYPE_UFS */
254a53f50b9Schristos
255a53f50b9Schristos #ifdef MNTTAB_TYPE_UMAPFS
256a53f50b9Schristos ops_show1(buf, l, &linesize, MNTTAB_TYPE_UMAPFS);
257a53f50b9Schristos #endif /* MNTTAB_TYPE_UMAPFS */
258a53f50b9Schristos
259a53f50b9Schristos #ifdef MNTTAB_TYPE_UNIONFS
260a53f50b9Schristos ops_show1(buf, l, &linesize, MNTTAB_TYPE_UNIONFS);
261a53f50b9Schristos #endif /* MNTTAB_TYPE_UNIONFS */
262a53f50b9Schristos
263a53f50b9Schristos #ifdef MNTTAB_TYPE_XFS
264a53f50b9Schristos ops_show1(buf, l, &linesize, MNTTAB_TYPE_XFS);
265a53f50b9Schristos #endif /* MNTTAB_TYPE_XFS */
266a53f50b9Schristos
267a53f50b9Schristos /* terminate with a period, newline, and NULL */
268a53f50b9Schristos if (buf[strlen(buf)-1] == '\n')
269a53f50b9Schristos buf[strlen(buf) - 4] = '\0';
270a53f50b9Schristos else
271a53f50b9Schristos buf[strlen(buf) - 2] = '\0';
272a53f50b9Schristos xstrlcat(buf, ".\n", l);
273a53f50b9Schristos }
274a53f50b9Schristos
275a53f50b9Schristos
276a53f50b9Schristos /*
277a53f50b9Schristos * return string option which is the reverse of opt.
278a53f50b9Schristos * nosuid -> suid
279a53f50b9Schristos * quota -> noquota
280a53f50b9Schristos * ro -> rw
281a53f50b9Schristos * etc.
282a53f50b9Schristos * may return pointer to static buffer or subpointer within opt.
283a53f50b9Schristos */
284a53f50b9Schristos static char *
reverse_option(const char * opt)285a53f50b9Schristos reverse_option(const char *opt)
286a53f50b9Schristos {
287a53f50b9Schristos static char buf[80];
288a53f50b9Schristos
289a53f50b9Schristos /* sanity check */
290a53f50b9Schristos if (!opt)
291a53f50b9Schristos return NULL;
292a53f50b9Schristos
293a53f50b9Schristos /* check special cases */
294a53f50b9Schristos /* XXX: if this gets too long, rewrite the code more flexibly */
295a53f50b9Schristos if (STREQ(opt, "ro")) return "rw";
296a53f50b9Schristos if (STREQ(opt, "rw")) return "ro";
297a53f50b9Schristos if (STREQ(opt, "bg")) return "fg";
298a53f50b9Schristos if (STREQ(opt, "fg")) return "bg";
299a53f50b9Schristos if (STREQ(opt, "soft")) return "hard";
300a53f50b9Schristos if (STREQ(opt, "hard")) return "soft";
301a53f50b9Schristos
302a53f50b9Schristos /* check if string starts with 'no' and chop it */
303a53f50b9Schristos if (NSTREQ(opt, "no", 2)) {
304a53f50b9Schristos xstrlcpy(buf, &opt[2], sizeof(buf));
305a53f50b9Schristos } else {
306a53f50b9Schristos /* finally return a string prepended with 'no' */
307a53f50b9Schristos xstrlcpy(buf, "no", sizeof(buf));
308a53f50b9Schristos xstrlcat(buf, opt, sizeof(buf));
309a53f50b9Schristos }
310a53f50b9Schristos return buf;
311a53f50b9Schristos }
312a53f50b9Schristos
313a53f50b9Schristos
314a53f50b9Schristos /*
315a53f50b9Schristos * start with an empty string. for each opts1 option that is not
316a53f50b9Schristos * in opts2, add it to the string (make sure the reverse of it
317a53f50b9Schristos * isn't in either). finally add opts2. return new string.
318a53f50b9Schristos * Both opts1 and opts2 must not be null!
319a53f50b9Schristos * Caller must eventually free the string being returned.
320a53f50b9Schristos */
321a53f50b9Schristos static char *
merge_opts(const char * opts1,const char * opts2)322a53f50b9Schristos merge_opts(const char *opts1, const char *opts2)
323a53f50b9Schristos {
324a53f50b9Schristos mntent_t mnt2; /* place holder for opts2 */
325a53f50b9Schristos char *newstr; /* new string to return (malloc'ed) */
326a53f50b9Schristos char *tmpstr; /* temp */
327a53f50b9Schristos char *eq; /* pointer to whatever follows '=' within temp */
328a53f50b9Schristos char oneopt[80]; /* one option w/o value if any */
329a53f50b9Schristos char *revoneopt; /* reverse of oneopt */
330a53f50b9Schristos size_t len = strlen(opts1) + strlen(opts2) + 2; /* space for "," and NULL */
331*8bae5d40Schristos char *s1 = xstrdup(opts1); /* copy of opts1 to munge */
332a53f50b9Schristos
333a53f50b9Schristos /* initialization */
334a53f50b9Schristos mnt2.mnt_opts = (char *) opts2;
335a53f50b9Schristos newstr = xmalloc(len);
336a53f50b9Schristos newstr[0] = '\0';
337a53f50b9Schristos
338a53f50b9Schristos for (tmpstr = strtok(s1, ",");
339a53f50b9Schristos tmpstr;
340a53f50b9Schristos tmpstr = strtok(NULL, ",")) {
341a53f50b9Schristos /* copy option to temp buffer */
342a53f50b9Schristos xstrlcpy(oneopt, tmpstr, sizeof(oneopt));
343a53f50b9Schristos /* if option has a value such as rsize=1024, chop the value part */
344*8bae5d40Schristos if ((eq = strchr(oneopt, '=')))
345a53f50b9Schristos *eq = '\0';
346a53f50b9Schristos /* find reverse option of oneopt */
347a53f50b9Schristos revoneopt = reverse_option(oneopt);
348a53f50b9Schristos /* if option or its reverse exist in opts2, ignore it */
349a53f50b9Schristos if (amu_hasmntopt(&mnt2, oneopt) || amu_hasmntopt(&mnt2, revoneopt))
350a53f50b9Schristos continue;
351a53f50b9Schristos /* add option to returned string */
352a53f50b9Schristos if (newstr[0]) {
353a53f50b9Schristos xstrlcat(newstr, ",", len);
354a53f50b9Schristos xstrlcat(newstr, tmpstr, len);
355a53f50b9Schristos } else {
356a53f50b9Schristos xstrlcpy(newstr, tmpstr, len);
357a53f50b9Schristos }
358a53f50b9Schristos }
359a53f50b9Schristos
360a53f50b9Schristos /* finally, append opts2 itself */
361a53f50b9Schristos if (newstr[0]) {
362a53f50b9Schristos xstrlcat(newstr, ",", len);
363a53f50b9Schristos xstrlcat(newstr, opts2, len);
364a53f50b9Schristos } else {
365a53f50b9Schristos xstrlcpy(newstr, opts2, len);
366a53f50b9Schristos }
367a53f50b9Schristos
368a53f50b9Schristos XFREE(s1);
369a53f50b9Schristos return newstr;
370a53f50b9Schristos }
371a53f50b9Schristos
372a53f50b9Schristos
373a53f50b9Schristos am_ops *
ops_search(char * type)374a53f50b9Schristos ops_search(char *type)
375a53f50b9Schristos {
376a53f50b9Schristos am_ops **vp;
377a53f50b9Schristos am_ops *rop = NULL;
378a53f50b9Schristos for (vp = vops; (rop = *vp); vp++)
379a53f50b9Schristos if (STREQ(rop->fs_type, type))
380a53f50b9Schristos break;
381a53f50b9Schristos return rop;
382a53f50b9Schristos }
383a53f50b9Schristos
384a53f50b9Schristos
385a53f50b9Schristos am_ops *
ops_match(am_opts * fo,char * key,char * g_key,char * path,char * keym,char * map)386a53f50b9Schristos ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map)
387a53f50b9Schristos {
388a53f50b9Schristos am_ops *rop = NULL;
389a53f50b9Schristos char *link_dir;
390a53f50b9Schristos
391a53f50b9Schristos /*
392a53f50b9Schristos * First crack the global opts and the local opts
393a53f50b9Schristos */
394a53f50b9Schristos if (!eval_fs_opts(fo, key, g_key, path, keym, map)) {
395a53f50b9Schristos rop = &amfs_error_ops;
396a53f50b9Schristos } else if (fo->opt_type == 0) {
397a53f50b9Schristos plog(XLOG_USER, "No fs type specified (key = \"%s\", map = \"%s\")", keym, map);
398a53f50b9Schristos rop = &amfs_error_ops;
399a53f50b9Schristos } else {
400a53f50b9Schristos /*
401a53f50b9Schristos * Next find the correct filesystem type
402a53f50b9Schristos */
403a53f50b9Schristos rop = ops_search(fo->opt_type);
404a53f50b9Schristos if (!rop) {
405a53f50b9Schristos plog(XLOG_USER, "fs type \"%s\" not recognized", fo->opt_type);
406a53f50b9Schristos rop = &amfs_error_ops;
407a53f50b9Schristos }
408a53f50b9Schristos }
409a53f50b9Schristos
410a53f50b9Schristos /*
411a53f50b9Schristos * Make sure we have a default mount option.
412a53f50b9Schristos * Otherwise skip past any leading '-'.
413a53f50b9Schristos */
414a53f50b9Schristos if (fo->opt_opts == 0)
415*8bae5d40Schristos fo->opt_opts = xstrdup("rw,defaults");
416a53f50b9Schristos else if (*fo->opt_opts == '-') {
417a53f50b9Schristos /*
418a53f50b9Schristos * We cannot simply do fo->opt_opts++ here since the opts
419a53f50b9Schristos * module will try to free the pointer fo->opt_opts later.
420a53f50b9Schristos * So just reallocate the thing -- stolcke 11/11/94
421a53f50b9Schristos */
422a53f50b9Schristos char *old = fo->opt_opts;
423*8bae5d40Schristos fo->opt_opts = xstrdup(old + 1);
424a53f50b9Schristos XFREE(old);
425a53f50b9Schristos }
426a53f50b9Schristos
427a53f50b9Schristos /*
428a53f50b9Schristos * If addopts option was used, then append it to the
429a53f50b9Schristos * current options and remote mount options.
430a53f50b9Schristos */
431a53f50b9Schristos if (fo->opt_addopts) {
432a53f50b9Schristos if (STREQ(fo->opt_opts, fo->opt_remopts)) {
433a53f50b9Schristos /* optimize things for the common case where opts==remopts */
434a53f50b9Schristos char *mergedstr;
435a53f50b9Schristos mergedstr = merge_opts(fo->opt_opts, fo->opt_addopts);
436a53f50b9Schristos plog(XLOG_INFO, "merge rem/opts \"%s\" add \"%s\" => \"%s\"",
437a53f50b9Schristos fo->opt_opts, fo->opt_addopts, mergedstr);
438a53f50b9Schristos XFREE(fo->opt_opts);
439a53f50b9Schristos XFREE(fo->opt_remopts);
440a53f50b9Schristos fo->opt_opts = mergedstr;
441*8bae5d40Schristos fo->opt_remopts = xstrdup(mergedstr);
442a53f50b9Schristos } else {
443a53f50b9Schristos char *mergedstr, *remmergedstr;
444a53f50b9Schristos mergedstr = merge_opts(fo->opt_opts, fo->opt_addopts);
445a53f50b9Schristos plog(XLOG_INFO, "merge opts \"%s\" add \"%s\" => \"%s\"",
446a53f50b9Schristos fo->opt_opts, fo->opt_addopts, mergedstr);
447a53f50b9Schristos XFREE(fo->opt_opts);
448a53f50b9Schristos fo->opt_opts = mergedstr;
449a53f50b9Schristos remmergedstr = merge_opts(fo->opt_remopts, fo->opt_addopts);
450a53f50b9Schristos plog(XLOG_INFO, "merge remopts \"%s\" add \"%s\" => \"%s\"",
451a53f50b9Schristos fo->opt_remopts, fo->opt_addopts, remmergedstr);
452a53f50b9Schristos XFREE(fo->opt_remopts);
453a53f50b9Schristos fo->opt_remopts = remmergedstr;
454a53f50b9Schristos }
455a53f50b9Schristos }
456a53f50b9Schristos
457a53f50b9Schristos /*
458a53f50b9Schristos * Initialize opt_mount_type to "nfs", if it's not initialized already
459a53f50b9Schristos */
460a53f50b9Schristos if (!fo->opt_mount_type)
461a53f50b9Schristos fo->opt_mount_type = "nfs";
462a53f50b9Schristos
463a53f50b9Schristos /* Normalize the sublink and make it absolute */
464a53f50b9Schristos link_dir = fo->opt_sublink;
465a53f50b9Schristos if (link_dir && link_dir[0] && link_dir[0] != '/') {
466a53f50b9Schristos link_dir = str3cat((char *) NULL, fo->opt_fs, "/", link_dir);
467a53f50b9Schristos normalize_slash(link_dir);
468a53f50b9Schristos XFREE(fo->opt_sublink);
469a53f50b9Schristos fo->opt_sublink = link_dir;
470a53f50b9Schristos }
471a53f50b9Schristos
472a53f50b9Schristos /*
473a53f50b9Schristos * Check the filesystem is happy
474a53f50b9Schristos */
475a53f50b9Schristos XFREE(fo->fs_mtab);
476a53f50b9Schristos
477a53f50b9Schristos fo->fs_mtab = rop->fs_match(fo);
478a53f50b9Schristos if (fo->fs_mtab)
479a53f50b9Schristos return rop;
480a53f50b9Schristos
481a53f50b9Schristos /*
482a53f50b9Schristos * Return error file system
483a53f50b9Schristos */
484a53f50b9Schristos fo->fs_mtab = amfs_error_ops.fs_match(fo);
485a53f50b9Schristos return &amfs_error_ops;
486a53f50b9Schristos }
487