Merge branch 'vendor/OPENSSL'
[dragonfly.git] / contrib / amd / fsinfo / wr_atab.c
1 /*
2  * Copyright (c) 1997-1999 Erez Zadok
3  * Copyright (c) 1989 Jan-Simon Pendry
4  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
5  * Copyright (c) 1989 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: wr_atab.c,v 1.2 1999/01/10 21:54:29 ezk Exp $
42  *
43  */
44
45 #ifdef HAVE_CONFIG_H
46 # include <config.h>
47 #endif /* HAVE_CONFIG_H */
48 #include <am_defs.h>
49 #include <fsi_data.h>
50 #include <fsinfo.h>
51
52
53 /*
54  * Write a sequence of automount mount map entries
55  */
56 static int
57 write_amount_info(FILE *af, automount *ap,  int sk)
58 {
59   int errors = 0;
60
61   if (ap->a_mount) {
62     /*
63      * A pseudo-directory.
64      * This can also be a top-level directory, in which
65      * case the type:=auto is not wanted...
66      *
67      * type:=auto;fs:=${map};pref:=whatever/
68      */
69     automount *ap2;
70     if (strlen(ap->a_name) > sk) {
71       fprintf(af, "%s type:=auto;fs:=${map};pref:=%s/\n",
72               ap->a_name + sk, ap->a_name + sk);
73     }
74     ITER(ap2, automount, ap->a_mount)
75       errors += write_amount_info(af, ap2, sk);
76   } else if (ap->a_hardwiredfs) {
77
78     /*
79      * A hardwired filesystem "hostname:path"
80      * rhost:=hostname;rfs:=path
81      */
82     char *key = ap->a_name + sk;
83     char *hostname = ap->a_hardwiredfs;
84     char *path = strrchr(hostname, (int) ':');
85
86     if (path == NULL) {
87       fprintf(stderr, "%s: %s not an NFS filesystem\n", ap->a_name, ap->a_hardwiredfs);
88       errors++;
89     } else {
90       *path = '\0';
91       path++;
92
93       /*
94        * Output the map key
95        */
96       fputs(key, af);
97       fprintf(af, " rhost:=%s", hostname);
98       fprintf(af, ";rfs:=%s", path);
99       if (ap->a_opts && !STREQ(ap->a_opts, "")) {
100         fprintf(af, ";%s", ap->a_opts);
101       }
102       fputc('\n', af);
103       path--;
104       *path = ':';
105     }
106   } else if (ap->a_mounted) {
107
108     /*
109      * A mounted partition
110      * type:=link [ link entries ] type:=nfs [ nfs entries ]
111      */
112     dict_data *dd;
113     dict_ent *de = ap->a_mounted;
114     int done_type_link = 0;
115     char *key = ap->a_name + sk;
116
117     /*
118      * Output the map key
119      */
120     fputs(key, af);
121
122     /*
123      * First output any Link locations that would not
124      * otherwise be correctly mounted.  These refer
125      * to filesystem which are not mounted in the same
126      * place which the automounter would use.
127      */
128     ITER(dd, dict_data, &de->de_q) {
129       fsi_mount *mp = (fsi_mount *) dd->dd_data;
130       /*
131        * If the mount point and the exported volname are the
132        * same then this filesystem will be recognized by
133        * the restart code - so we don't need to put out a
134        * special rule for it.
135        */
136       if (mp->m_dk->d_host->h_lochost) {
137         char amountpt[1024];
138         compute_automount_point(amountpt, mp->m_dk->d_host, mp->m_exported->m_volname);
139         if (!STREQ(mp->m_dk->d_mountpt, amountpt)) {
140           /*
141            * ap->a_volname is the name of the aliased volume
142            * mp->m_name is the mount point of the filesystem
143            * mp->m_volname is the volume name of the filesystems
144            */
145
146           /*
147            * Find length of key and volume names
148            */
149           int avlen = strlen(ap->a_volname);
150           int mnlen = strlen(mp->m_volname);
151
152           /*
153            * Make sure a -type:=link is output once
154            */
155           if (!done_type_link) {
156             done_type_link = 1;
157             fputs(" -type:=link", af);
158           }
159
160           /*
161            * Output a selector for the hostname,
162            * the device from which to mount and
163            * where to mount.  This will correspond
164            * to the values output for the fstab.
165            */
166           if (mp->m_dk->d_host->h_lochost)
167             fprintf(af, " host==%s", mp->m_dk->d_host->h_lochost);
168           else
169             fprintf(af, " hostd==%s", mp->m_dk->d_host->h_hostname);
170           fprintf(af, ";fs:=%s", mp->m_name);
171
172           /*
173            * ... and a sublink if needed
174            */
175           if (mnlen < avlen) {
176             char *sublink = ap->a_volname + mnlen + 1;
177             fprintf(af, "/%s", sublink);
178           }
179           fputs(" ||", af);
180         }
181       }
182     }
183
184     /*
185      * Next do the NFS locations
186      */
187     if (done_type_link)
188       fputs(" -", af);
189
190     ITER(dd, dict_data, &de->de_q) {
191       fsi_mount *mp = (fsi_mount *) dd->dd_data;
192       int namelen = mp->m_name_len;
193       int exp_namelen = mp->m_exported->m_name_len;
194       int volnlen = strlen(ap->a_volname);
195       int mvolnlen = strlen(mp->m_volname);
196
197       fputc(' ', af);
198
199       /*
200        * Output any selectors
201        */
202       if (mp->m_sel)
203         fprintf(af, "%s;", mp->m_sel);
204
205       /*
206        * Print host and volname of exported filesystem
207        */
208       fprintf(af, "rhost:=%s",
209               mp->m_dk->d_host->h_lochost ?
210               mp->m_dk->d_host->h_lochost :
211               mp->m_dk->d_host->h_hostname);
212       fprintf(af, ";rfs:=%s", mp->m_exported->m_volname);
213       if (ap->a_opts && !STREQ(ap->a_opts, "")) {
214         fprintf(af, ";%s", ap->a_opts);
215       }
216
217       /*
218        * Now determine whether a sublink is required.
219        */
220       if (exp_namelen < namelen || mvolnlen < volnlen) {
221         char sublink[1024];
222         sublink[0] = '\0';
223         if (exp_namelen < namelen) {
224           strcat(sublink, mp->m_name + exp_namelen + 1);
225           if (mvolnlen < volnlen)
226             strcat(sublink, "/");
227         }
228         if (mvolnlen < volnlen)
229           strcat(sublink, ap->a_volname + mvolnlen + 1);
230
231         fprintf(af, ";sublink:=%s", sublink);
232       }
233     }
234     fputc('\n', af);
235   } else if (ap->a_symlink) {
236
237     /*
238      * A specific link.
239      *
240      * type:=link;fs:=whatever
241      */
242     fprintf(af, "%s type:=link;fs:=%s\n", ap->a_name + sk, ap->a_symlink);
243   }
244
245   return errors;
246 }
247
248
249 /*
250  * Write a single automount configuration file
251  */
252 static int
253 write_amount( qelem *q, char *def)
254 {
255   automount *ap;
256   int errors = 0;
257   int direct = 0;
258
259   /*
260    * Output all indirect maps
261    */
262   ITER(ap, automount, q) {
263     FILE *af;
264     char *p;
265
266     /*
267      * If there is no a_mount node then this is really
268      * a direct mount, so just keep a count and continue.
269      * Direct mounts are output into a special file during
270      * the second pass below.
271      */
272     if (!ap->a_mount) {
273       direct++;
274       continue;
275     }
276
277     p = strrchr(ap->a_name, '/');
278     if (!p)
279       p = ap->a_name;
280     else
281       p++;
282
283     af = pref_open(mount_pref, p, gen_hdr, ap->a_name);
284     if (af) {
285       show_new(ap->a_name);
286       fputs("/defaults ", af);
287       if (*def)
288         fprintf(af, "%s;", def);
289       fputs("type:=nfs\n", af);
290       errors += write_amount_info(af, ap, strlen(ap->a_name) + 1);
291       errors += pref_close(af);
292     }
293   }
294
295   /*
296    * Output any direct map entries which were found during the
297    * previous pass over the data.
298    */
299   if (direct) {
300     FILE *af = pref_open(mount_pref, "direct.map", info_hdr, "direct mount");
301
302     if (af) {
303       show_new("direct mounts");
304       fputs("/defaults ", af);
305       if (*def)
306         fprintf(af, "%s;", def);
307       fputs("type:=nfs\n", af);
308       ITER(ap, automount, q)
309       if (!ap->a_mount)
310           errors += write_amount_info(af, ap, 1);
311       errors += pref_close(af);
312     }
313   }
314   return errors;
315 }
316
317
318 /*
319  * Write all the needed automount configuration files
320  */
321 int
322 write_atab(qelem *q)
323 {
324   int errors = 0;
325
326   if (mount_pref) {
327     auto_tree *tp;
328     show_area_being_processed("write automount", 5);
329     ITER(tp, auto_tree, q)
330       errors += write_amount(tp->t_mount, tp->t_defaults);
331   }
332
333   return errors;
334 }