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 */ 51static int 52write_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 */ 248static int 249write_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 */ 317int 318write_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} 331