138494Sobrien/* 2310490Scy * Copyright (c) 1997-2014 Erez Zadok 338494Sobrien * Copyright (c) 1989 Jan-Simon Pendry 438494Sobrien * Copyright (c) 1989 Imperial College of Science, Technology & Medicine 538494Sobrien * Copyright (c) 1989 The Regents of the University of California. 638494Sobrien * All rights reserved. 738494Sobrien * 838494Sobrien * This code is derived from software contributed to Berkeley by 938494Sobrien * Jan-Simon Pendry at Imperial College, London. 1038494Sobrien * 1138494Sobrien * Redistribution and use in source and binary forms, with or without 1238494Sobrien * modification, are permitted provided that the following conditions 1338494Sobrien * are met: 1438494Sobrien * 1. Redistributions of source code must retain the above copyright 1538494Sobrien * notice, this list of conditions and the following disclaimer. 1638494Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1738494Sobrien * notice, this list of conditions and the following disclaimer in the 1838494Sobrien * documentation and/or other materials provided with the distribution. 19310490Scy * 3. Neither the name of the University nor the names of its contributors 2038494Sobrien * may be used to endorse or promote products derived from this software 2138494Sobrien * without specific prior written permission. 2238494Sobrien * 2338494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2438494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2538494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2638494Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2738494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2838494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2938494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3038494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3138494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3238494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3338494Sobrien * SUCH DAMAGE. 3438494Sobrien * 3538494Sobrien * 36174294Sobrien * File: am-utils/fsinfo/wr_atab.c 3738494Sobrien * 3838494Sobrien */ 3938494Sobrien 4038494Sobrien#ifdef HAVE_CONFIG_H 4138494Sobrien# include <config.h> 4238494Sobrien#endif /* HAVE_CONFIG_H */ 4338494Sobrien#include <am_defs.h> 4438494Sobrien#include <fsi_data.h> 4538494Sobrien#include <fsinfo.h> 4638494Sobrien 4738494Sobrien 4838494Sobrien/* 4938494Sobrien * Write a sequence of automount mount map entries 5038494Sobrien */ 5138494Sobrienstatic int 52174294Sobrienwrite_amount_info(FILE *af, automount *ap, u_int sk) 5338494Sobrien{ 5438494Sobrien int errors = 0; 5538494Sobrien 5638494Sobrien if (ap->a_mount) { 5738494Sobrien /* 5838494Sobrien * A pseudo-directory. 5938494Sobrien * This can also be a top-level directory, in which 6038494Sobrien * case the type:=auto is not wanted... 6138494Sobrien * 6238494Sobrien * type:=auto;fs:=${map};pref:=whatever/ 6338494Sobrien */ 6438494Sobrien automount *ap2; 6538494Sobrien if (strlen(ap->a_name) > sk) { 6638494Sobrien fprintf(af, "%s type:=auto;fs:=${map};pref:=%s/\n", 6738494Sobrien ap->a_name + sk, ap->a_name + sk); 6838494Sobrien } 6938494Sobrien ITER(ap2, automount, ap->a_mount) 7038494Sobrien errors += write_amount_info(af, ap2, sk); 7138494Sobrien } else if (ap->a_hardwiredfs) { 7238494Sobrien 7338494Sobrien /* 7438494Sobrien * A hardwired filesystem "hostname:path" 7538494Sobrien * rhost:=hostname;rfs:=path 7638494Sobrien */ 7738494Sobrien char *key = ap->a_name + sk; 7838494Sobrien char *hostname = ap->a_hardwiredfs; 7938494Sobrien char *path = strrchr(hostname, (int) ':'); 8038494Sobrien 8138494Sobrien if (path == NULL) { 8238494Sobrien fprintf(stderr, "%s: %s not an NFS filesystem\n", ap->a_name, ap->a_hardwiredfs); 8338494Sobrien errors++; 8438494Sobrien } else { 8538494Sobrien *path = '\0'; 8638494Sobrien path++; 8738494Sobrien 8838494Sobrien /* 8938494Sobrien * Output the map key 9038494Sobrien */ 9138494Sobrien fputs(key, af); 9238494Sobrien fprintf(af, " rhost:=%s", hostname); 9338494Sobrien fprintf(af, ";rfs:=%s", path); 9438494Sobrien if (ap->a_opts && !STREQ(ap->a_opts, "")) { 9538494Sobrien fprintf(af, ";%s", ap->a_opts); 9638494Sobrien } 9738494Sobrien fputc('\n', af); 9838494Sobrien path--; 9938494Sobrien *path = ':'; 10038494Sobrien } 10138494Sobrien } else if (ap->a_mounted) { 10238494Sobrien 10338494Sobrien /* 10438494Sobrien * A mounted partition 10538494Sobrien * type:=link [ link entries ] type:=nfs [ nfs entries ] 10638494Sobrien */ 10738494Sobrien dict_data *dd; 10838494Sobrien dict_ent *de = ap->a_mounted; 10938494Sobrien int done_type_link = 0; 11038494Sobrien char *key = ap->a_name + sk; 11138494Sobrien 11238494Sobrien /* 11338494Sobrien * Output the map key 11438494Sobrien */ 11538494Sobrien fputs(key, af); 11638494Sobrien 11738494Sobrien /* 11838494Sobrien * First output any Link locations that would not 11938494Sobrien * otherwise be correctly mounted. These refer 12038494Sobrien * to filesystem which are not mounted in the same 12138494Sobrien * place which the automounter would use. 12238494Sobrien */ 12338494Sobrien ITER(dd, dict_data, &de->de_q) { 12438494Sobrien fsi_mount *mp = (fsi_mount *) dd->dd_data; 12538494Sobrien /* 12638494Sobrien * If the mount point and the exported volname are the 12742629Sobrien * same then this filesystem will be recognized by 12838494Sobrien * the restart code - so we don't need to put out a 12938494Sobrien * special rule for it. 13038494Sobrien */ 13138494Sobrien if (mp->m_dk->d_host->h_lochost) { 13238494Sobrien char amountpt[1024]; 133174294Sobrien compute_automount_point(amountpt, sizeof(amountpt), 134174294Sobrien mp->m_dk->d_host, mp->m_exported->m_volname); 13538494Sobrien if (!STREQ(mp->m_dk->d_mountpt, amountpt)) { 13638494Sobrien /* 13738494Sobrien * ap->a_volname is the name of the aliased volume 13838494Sobrien * mp->m_name is the mount point of the filesystem 13938494Sobrien * mp->m_volname is the volume name of the filesystems 14038494Sobrien */ 14138494Sobrien 14238494Sobrien /* 14338494Sobrien * Find length of key and volume names 14438494Sobrien */ 14538494Sobrien int avlen = strlen(ap->a_volname); 14638494Sobrien int mnlen = strlen(mp->m_volname); 14738494Sobrien 14838494Sobrien /* 14938494Sobrien * Make sure a -type:=link is output once 15038494Sobrien */ 15138494Sobrien if (!done_type_link) { 15238494Sobrien done_type_link = 1; 15338494Sobrien fputs(" -type:=link", af); 15438494Sobrien } 15538494Sobrien 15638494Sobrien /* 15738494Sobrien * Output a selector for the hostname, 15838494Sobrien * the device from which to mount and 15938494Sobrien * where to mount. This will correspond 16038494Sobrien * to the values output for the fstab. 16138494Sobrien */ 16238494Sobrien if (mp->m_dk->d_host->h_lochost) 16338494Sobrien fprintf(af, " host==%s", mp->m_dk->d_host->h_lochost); 16438494Sobrien else 16538494Sobrien fprintf(af, " hostd==%s", mp->m_dk->d_host->h_hostname); 16638494Sobrien fprintf(af, ";fs:=%s", mp->m_name); 16738494Sobrien 16838494Sobrien /* 16938494Sobrien * ... and a sublink if needed 17038494Sobrien */ 17138494Sobrien if (mnlen < avlen) { 17238494Sobrien char *sublink = ap->a_volname + mnlen + 1; 17338494Sobrien fprintf(af, "/%s", sublink); 17438494Sobrien } 17538494Sobrien fputs(" ||", af); 17638494Sobrien } 17738494Sobrien } 17838494Sobrien } 17938494Sobrien 18038494Sobrien /* 18138494Sobrien * Next do the NFS locations 18238494Sobrien */ 18338494Sobrien if (done_type_link) 18438494Sobrien fputs(" -", af); 18538494Sobrien 18638494Sobrien ITER(dd, dict_data, &de->de_q) { 18738494Sobrien fsi_mount *mp = (fsi_mount *) dd->dd_data; 18838494Sobrien int namelen = mp->m_name_len; 18938494Sobrien int exp_namelen = mp->m_exported->m_name_len; 19038494Sobrien int volnlen = strlen(ap->a_volname); 19138494Sobrien int mvolnlen = strlen(mp->m_volname); 19238494Sobrien 19338494Sobrien fputc(' ', af); 19438494Sobrien 19538494Sobrien /* 19638494Sobrien * Output any selectors 19738494Sobrien */ 19838494Sobrien if (mp->m_sel) 19938494Sobrien fprintf(af, "%s;", mp->m_sel); 20038494Sobrien 20138494Sobrien /* 20238494Sobrien * Print host and volname of exported filesystem 20338494Sobrien */ 20438494Sobrien fprintf(af, "rhost:=%s", 20538494Sobrien mp->m_dk->d_host->h_lochost ? 20638494Sobrien mp->m_dk->d_host->h_lochost : 20738494Sobrien mp->m_dk->d_host->h_hostname); 20838494Sobrien fprintf(af, ";rfs:=%s", mp->m_exported->m_volname); 20938494Sobrien if (ap->a_opts && !STREQ(ap->a_opts, "")) { 21038494Sobrien fprintf(af, ";%s", ap->a_opts); 21138494Sobrien } 21238494Sobrien 21338494Sobrien /* 21438494Sobrien * Now determine whether a sublink is required. 21538494Sobrien */ 21638494Sobrien if (exp_namelen < namelen || mvolnlen < volnlen) { 21738494Sobrien char sublink[1024]; 21838494Sobrien sublink[0] = '\0'; 21938494Sobrien if (exp_namelen < namelen) { 220174294Sobrien xstrlcat(sublink, mp->m_name + exp_namelen + 1, sizeof(sublink)); 22138494Sobrien if (mvolnlen < volnlen) 222174294Sobrien xstrlcat(sublink, "/", sizeof(sublink)); 22338494Sobrien } 22438494Sobrien if (mvolnlen < volnlen) 225174294Sobrien xstrlcat(sublink, ap->a_volname + mvolnlen + 1, sizeof(sublink)); 22638494Sobrien 22738494Sobrien fprintf(af, ";sublink:=%s", sublink); 22838494Sobrien } 22938494Sobrien } 23038494Sobrien fputc('\n', af); 23138494Sobrien } else if (ap->a_symlink) { 23238494Sobrien 23338494Sobrien /* 23438494Sobrien * A specific link. 23538494Sobrien * 23638494Sobrien * type:=link;fs:=whatever 23738494Sobrien */ 23838494Sobrien fprintf(af, "%s type:=link;fs:=%s\n", ap->a_name + sk, ap->a_symlink); 23938494Sobrien } 24038494Sobrien 24138494Sobrien return errors; 24238494Sobrien} 24338494Sobrien 24438494Sobrien 24538494Sobrien/* 24638494Sobrien * Write a single automount configuration file 24738494Sobrien */ 24838494Sobrienstatic int 24938494Sobrienwrite_amount( qelem *q, char *def) 25038494Sobrien{ 25138494Sobrien automount *ap; 25238494Sobrien int errors = 0; 25338494Sobrien int direct = 0; 25438494Sobrien 25538494Sobrien /* 25638494Sobrien * Output all indirect maps 25738494Sobrien */ 25838494Sobrien ITER(ap, automount, q) { 25938494Sobrien FILE *af; 26038494Sobrien char *p; 26138494Sobrien 26238494Sobrien /* 26338494Sobrien * If there is no a_mount node then this is really 26438494Sobrien * a direct mount, so just keep a count and continue. 26538494Sobrien * Direct mounts are output into a special file during 26638494Sobrien * the second pass below. 26738494Sobrien */ 26838494Sobrien if (!ap->a_mount) { 26938494Sobrien direct++; 27038494Sobrien continue; 27138494Sobrien } 27238494Sobrien 27338494Sobrien p = strrchr(ap->a_name, '/'); 27438494Sobrien if (!p) 27538494Sobrien p = ap->a_name; 27638494Sobrien else 27738494Sobrien p++; 27838494Sobrien 27938494Sobrien af = pref_open(mount_pref, p, gen_hdr, ap->a_name); 28038494Sobrien if (af) { 28138494Sobrien show_new(ap->a_name); 28238494Sobrien fputs("/defaults ", af); 28338494Sobrien if (*def) 28438494Sobrien fprintf(af, "%s;", def); 28538494Sobrien fputs("type:=nfs\n", af); 28638494Sobrien errors += write_amount_info(af, ap, strlen(ap->a_name) + 1); 28738494Sobrien errors += pref_close(af); 28838494Sobrien } 28938494Sobrien } 29038494Sobrien 29138494Sobrien /* 29238494Sobrien * Output any direct map entries which were found during the 29338494Sobrien * previous pass over the data. 29438494Sobrien */ 29538494Sobrien if (direct) { 29638494Sobrien FILE *af = pref_open(mount_pref, "direct.map", info_hdr, "direct mount"); 29738494Sobrien 29838494Sobrien if (af) { 29938494Sobrien show_new("direct mounts"); 30038494Sobrien fputs("/defaults ", af); 30138494Sobrien if (*def) 30238494Sobrien fprintf(af, "%s;", def); 30338494Sobrien fputs("type:=nfs\n", af); 30438494Sobrien ITER(ap, automount, q) 30538494Sobrien if (!ap->a_mount) 30638494Sobrien errors += write_amount_info(af, ap, 1); 30738494Sobrien errors += pref_close(af); 30838494Sobrien } 30938494Sobrien } 31038494Sobrien return errors; 31138494Sobrien} 31238494Sobrien 31338494Sobrien 31438494Sobrien/* 31538494Sobrien * Write all the needed automount configuration files 31638494Sobrien */ 31738494Sobrienint 31838494Sobrienwrite_atab(qelem *q) 31938494Sobrien{ 32038494Sobrien int errors = 0; 32138494Sobrien 32238494Sobrien if (mount_pref) { 32338494Sobrien auto_tree *tp; 32438494Sobrien show_area_being_processed("write automount", 5); 32538494Sobrien ITER(tp, auto_tree, q) 32638494Sobrien errors += write_amount(tp->t_mount, tp->t_defaults); 32738494Sobrien } 32838494Sobrien 32938494Sobrien return errors; 33038494Sobrien} 331