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