]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/amd/fsinfo/wr_atab.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / amd / fsinfo / wr_atab.c
1 /*
2  * Copyright (c) 1997-2006 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  *
40  * File: am-utils/fsinfo/wr_atab.c
41  *
42  */
43
44 #ifdef HAVE_CONFIG_H
45 # include <config.h>
46 #endif /* HAVE_CONFIG_H */
47 #include <am_defs.h>
48 #include <fsi_data.h>
49 #include <fsinfo.h>
50
51
52 /*
53  * Write a sequence of automount mount map entries
54  */
55 static int
56 write_amount_info(FILE *af, automount *ap,  u_int sk)
57 {
58   int errors = 0;
59
60   if (ap->a_mount) {
61     /*
62      * A pseudo-directory.
63      * This can also be a top-level directory, in which
64      * case the type:=auto is not wanted...
65      *
66      * type:=auto;fs:=${map};pref:=whatever/
67      */
68     automount *ap2;
69     if (strlen(ap->a_name) > sk) {
70       fprintf(af, "%s type:=auto;fs:=${map};pref:=%s/\n",
71               ap->a_name + sk, ap->a_name + sk);
72     }
73     ITER(ap2, automount, ap->a_mount)
74       errors += write_amount_info(af, ap2, sk);
75   } else if (ap->a_hardwiredfs) {
76
77     /*
78      * A hardwired filesystem "hostname:path"
79      * rhost:=hostname;rfs:=path
80      */
81     char *key = ap->a_name + sk;
82     char *hostname = ap->a_hardwiredfs;
83     char *path = strrchr(hostname, (int) ':');
84
85     if (path == NULL) {
86       fprintf(stderr, "%s: %s not an NFS filesystem\n", ap->a_name, ap->a_hardwiredfs);
87       errors++;
88     } else {
89       *path = '\0';
90       path++;
91
92       /*
93        * Output the map key
94        */
95       fputs(key, af);
96       fprintf(af, " rhost:=%s", hostname);
97       fprintf(af, ";rfs:=%s", path);
98       if (ap->a_opts && !STREQ(ap->a_opts, "")) {
99         fprintf(af, ";%s", ap->a_opts);
100       }
101       fputc('\n', af);
102       path--;
103       *path = ':';
104     }
105   } else if (ap->a_mounted) {
106
107     /*
108      * A mounted partition
109      * type:=link [ link entries ] type:=nfs [ nfs entries ]
110      */
111     dict_data *dd;
112     dict_ent *de = ap->a_mounted;
113     int done_type_link = 0;
114     char *key = ap->a_name + sk;
115
116     /*
117      * Output the map key
118      */
119     fputs(key, af);
120
121     /*
122      * First output any Link locations that would not
123      * otherwise be correctly mounted.  These refer
124      * to filesystem which are not mounted in the same
125      * place which the automounter would use.
126      */
127     ITER(dd, dict_data, &de->de_q) {
128       fsi_mount *mp = (fsi_mount *) dd->dd_data;
129       /*
130        * If the mount point and the exported volname are the
131        * same then this filesystem will be recognized by
132        * the restart code - so we don't need to put out a
133        * special rule for it.
134        */
135       if (mp->m_dk->d_host->h_lochost) {
136         char amountpt[1024];
137         compute_automount_point(amountpt, sizeof(amountpt),
138                                 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           xstrlcat(sublink, mp->m_name + exp_namelen + 1, sizeof(sublink));
225           if (mvolnlen < volnlen)
226             xstrlcat(sublink, "/", sizeof(sublink));
227         }
228         if (mvolnlen < volnlen)
229           xstrlcat(sublink, ap->a_volname + mvolnlen + 1, sizeof(sublink));
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 }