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 */ 55static int 56write_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 */ 252static int 253write_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 */ 321int 322write_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} 335