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