]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/amd/fsinfo/wr_atab.c
MFC r308493, r308619: Update amd from am-utils 6.1.5 to 6.2.
[FreeBSD/stable/10.git] / contrib / amd / fsinfo / wr_atab.c
1 /*
2  * Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  *
36  * File: am-utils/fsinfo/wr_atab.c
37  *
38  */
39
40 #ifdef HAVE_CONFIG_H
41 # include <config.h>
42 #endif /* HAVE_CONFIG_H */
43 #include <am_defs.h>
44 #include <fsi_data.h>
45 #include <fsinfo.h>
46
47
48 /*
49  * Write a sequence of automount mount map entries
50  */
51 static int
52 write_amount_info(FILE *af, automount *ap,  u_int sk)
53 {
54   int errors = 0;
55
56   if (ap->a_mount) {
57     /*
58      * A pseudo-directory.
59      * This can also be a top-level directory, in which
60      * case the type:=auto is not wanted...
61      *
62      * type:=auto;fs:=${map};pref:=whatever/
63      */
64     automount *ap2;
65     if (strlen(ap->a_name) > sk) {
66       fprintf(af, "%s type:=auto;fs:=${map};pref:=%s/\n",
67               ap->a_name + sk, ap->a_name + sk);
68     }
69     ITER(ap2, automount, ap->a_mount)
70       errors += write_amount_info(af, ap2, sk);
71   } else if (ap->a_hardwiredfs) {
72
73     /*
74      * A hardwired filesystem "hostname:path"
75      * rhost:=hostname;rfs:=path
76      */
77     char *key = ap->a_name + sk;
78     char *hostname = ap->a_hardwiredfs;
79     char *path = strrchr(hostname, (int) ':');
80
81     if (path == NULL) {
82       fprintf(stderr, "%s: %s not an NFS filesystem\n", ap->a_name, ap->a_hardwiredfs);
83       errors++;
84     } else {
85       *path = '\0';
86       path++;
87
88       /*
89        * Output the map key
90        */
91       fputs(key, af);
92       fprintf(af, " rhost:=%s", hostname);
93       fprintf(af, ";rfs:=%s", path);
94       if (ap->a_opts && !STREQ(ap->a_opts, "")) {
95         fprintf(af, ";%s", ap->a_opts);
96       }
97       fputc('\n', af);
98       path--;
99       *path = ':';
100     }
101   } else if (ap->a_mounted) {
102
103     /*
104      * A mounted partition
105      * type:=link [ link entries ] type:=nfs [ nfs entries ]
106      */
107     dict_data *dd;
108     dict_ent *de = ap->a_mounted;
109     int done_type_link = 0;
110     char *key = ap->a_name + sk;
111
112     /*
113      * Output the map key
114      */
115     fputs(key, af);
116
117     /*
118      * First output any Link locations that would not
119      * otherwise be correctly mounted.  These refer
120      * to filesystem which are not mounted in the same
121      * place which the automounter would use.
122      */
123     ITER(dd, dict_data, &de->de_q) {
124       fsi_mount *mp = (fsi_mount *) dd->dd_data;
125       /*
126        * If the mount point and the exported volname are the
127        * same then this filesystem will be recognized by
128        * the restart code - so we don't need to put out a
129        * special rule for it.
130        */
131       if (mp->m_dk->d_host->h_lochost) {
132         char amountpt[1024];
133         compute_automount_point(amountpt, sizeof(amountpt),
134                                 mp->m_dk->d_host, mp->m_exported->m_volname);
135         if (!STREQ(mp->m_dk->d_mountpt, amountpt)) {
136           /*
137            * ap->a_volname is the name of the aliased volume
138            * mp->m_name is the mount point of the filesystem
139            * mp->m_volname is the volume name of the filesystems
140            */
141
142           /*
143            * Find length of key and volume names
144            */
145           int avlen = strlen(ap->a_volname);
146           int mnlen = strlen(mp->m_volname);
147
148           /*
149            * Make sure a -type:=link is output once
150            */
151           if (!done_type_link) {
152             done_type_link = 1;
153             fputs(" -type:=link", af);
154           }
155
156           /*
157            * Output a selector for the hostname,
158            * the device from which to mount and
159            * where to mount.  This will correspond
160            * to the values output for the fstab.
161            */
162           if (mp->m_dk->d_host->h_lochost)
163             fprintf(af, " host==%s", mp->m_dk->d_host->h_lochost);
164           else
165             fprintf(af, " hostd==%s", mp->m_dk->d_host->h_hostname);
166           fprintf(af, ";fs:=%s", mp->m_name);
167
168           /*
169            * ... and a sublink if needed
170            */
171           if (mnlen < avlen) {
172             char *sublink = ap->a_volname + mnlen + 1;
173             fprintf(af, "/%s", sublink);
174           }
175           fputs(" ||", af);
176         }
177       }
178     }
179
180     /*
181      * Next do the NFS locations
182      */
183     if (done_type_link)
184       fputs(" -", af);
185
186     ITER(dd, dict_data, &de->de_q) {
187       fsi_mount *mp = (fsi_mount *) dd->dd_data;
188       int namelen = mp->m_name_len;
189       int exp_namelen = mp->m_exported->m_name_len;
190       int volnlen = strlen(ap->a_volname);
191       int mvolnlen = strlen(mp->m_volname);
192
193       fputc(' ', af);
194
195       /*
196        * Output any selectors
197        */
198       if (mp->m_sel)
199         fprintf(af, "%s;", mp->m_sel);
200
201       /*
202        * Print host and volname of exported filesystem
203        */
204       fprintf(af, "rhost:=%s",
205               mp->m_dk->d_host->h_lochost ?
206               mp->m_dk->d_host->h_lochost :
207               mp->m_dk->d_host->h_hostname);
208       fprintf(af, ";rfs:=%s", mp->m_exported->m_volname);
209       if (ap->a_opts && !STREQ(ap->a_opts, "")) {
210         fprintf(af, ";%s", ap->a_opts);
211       }
212
213       /*
214        * Now determine whether a sublink is required.
215        */
216       if (exp_namelen < namelen || mvolnlen < volnlen) {
217         char sublink[1024];
218         sublink[0] = '\0';
219         if (exp_namelen < namelen) {
220           xstrlcat(sublink, mp->m_name + exp_namelen + 1, sizeof(sublink));
221           if (mvolnlen < volnlen)
222             xstrlcat(sublink, "/", sizeof(sublink));
223         }
224         if (mvolnlen < volnlen)
225           xstrlcat(sublink, ap->a_volname + mvolnlen + 1, sizeof(sublink));
226
227         fprintf(af, ";sublink:=%s", sublink);
228       }
229     }
230     fputc('\n', af);
231   } else if (ap->a_symlink) {
232
233     /*
234      * A specific link.
235      *
236      * type:=link;fs:=whatever
237      */
238     fprintf(af, "%s type:=link;fs:=%s\n", ap->a_name + sk, ap->a_symlink);
239   }
240
241   return errors;
242 }
243
244
245 /*
246  * Write a single automount configuration file
247  */
248 static int
249 write_amount( qelem *q, char *def)
250 {
251   automount *ap;
252   int errors = 0;
253   int direct = 0;
254
255   /*
256    * Output all indirect maps
257    */
258   ITER(ap, automount, q) {
259     FILE *af;
260     char *p;
261
262     /*
263      * If there is no a_mount node then this is really
264      * a direct mount, so just keep a count and continue.
265      * Direct mounts are output into a special file during
266      * the second pass below.
267      */
268     if (!ap->a_mount) {
269       direct++;
270       continue;
271     }
272
273     p = strrchr(ap->a_name, '/');
274     if (!p)
275       p = ap->a_name;
276     else
277       p++;
278
279     af = pref_open(mount_pref, p, gen_hdr, ap->a_name);
280     if (af) {
281       show_new(ap->a_name);
282       fputs("/defaults ", af);
283       if (*def)
284         fprintf(af, "%s;", def);
285       fputs("type:=nfs\n", af);
286       errors += write_amount_info(af, ap, strlen(ap->a_name) + 1);
287       errors += pref_close(af);
288     }
289   }
290
291   /*
292    * Output any direct map entries which were found during the
293    * previous pass over the data.
294    */
295   if (direct) {
296     FILE *af = pref_open(mount_pref, "direct.map", info_hdr, "direct mount");
297
298     if (af) {
299       show_new("direct mounts");
300       fputs("/defaults ", af);
301       if (*def)
302         fprintf(af, "%s;", def);
303       fputs("type:=nfs\n", af);
304       ITER(ap, automount, q)
305       if (!ap->a_mount)
306           errors += write_amount_info(af, ap, 1);
307       errors += pref_close(af);
308     }
309   }
310   return errors;
311 }
312
313
314 /*
315  * Write all the needed automount configuration files
316  */
317 int
318 write_atab(qelem *q)
319 {
320   int errors = 0;
321
322   if (mount_pref) {
323     auto_tree *tp;
324     show_area_being_processed("write automount", 5);
325     ITER(tp, auto_tree, q)
326       errors += write_amount(tp->t_mount, tp->t_defaults);
327   }
328
329   return errors;
330 }