138494Sobrien/* 2174294Sobrien * Copyright (c) 1997-2006 Erez Zadok 338494Sobrien * Copyright (c) 1990 Jan-Simon Pendry 438494Sobrien * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 538494Sobrien * Copyright (c) 1990 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. 1938494Sobrien * 3. All advertising materials mentioning features or use of this software 2042629Sobrien * must display the following acknowledgment: 2138494Sobrien * This product includes software developed by the University of 2238494Sobrien * California, Berkeley and its contributors. 2338494Sobrien * 4. Neither the name of the University nor the names of its contributors 2438494Sobrien * may be used to endorse or promote products derived from this software 2538494Sobrien * without specific prior written permission. 2638494Sobrien * 2738494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2838494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2938494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3038494Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3138494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3238494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3338494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3438494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3538494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3638494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3738494Sobrien * SUCH DAMAGE. 3838494Sobrien * 3938494Sobrien * 40174294Sobrien * File: am-utils/amd/amfs_nfsl.c 4138494Sobrien * 4238494Sobrien */ 4338494Sobrien 4438494Sobrien/* 4538494Sobrien * NFSL: Network file system with local existence check. If the local 4638494Sobrien * path denoted by $rfs exists, it behaves as type:=link. 4738494Sobrien * 4838494Sobrien * Example: 4938494Sobrien * pkg type:=nfsl;rhost:=jonny;rfs:=/n/johnny/src/pkg;fs:=${rfs} 5038494Sobrien */ 5138494Sobrien 5238494Sobrien#ifdef HAVE_CONFIG_H 5338494Sobrien# include <config.h> 5438494Sobrien#endif /* HAVE_CONFIG_H */ 5538494Sobrien#include <am_defs.h> 5638494Sobrien#include <amd.h> 5738494Sobrien 5838494Sobrien 5938494Sobrien/* forward declarations */ 6038494Sobrienstatic char *amfs_nfsl_match(am_opts *fo); 6138494Sobrienstatic int amfs_nfsl_init(mntfs *mf); 62174294Sobrienstatic int amfs_nfsl_mount(am_node *mp, mntfs *mf); 63174294Sobrienstatic int amfs_nfsl_umount(am_node *mp, mntfs *mf); 64174294Sobrienstatic void amfs_nfsl_umounted(mntfs *mf); 6538494Sobrienstatic fserver *amfs_nfsl_ffserver(mntfs *mf); 6638494Sobrien 6738494Sobrien/* 6838494Sobrien * NFS-Link operations 6938494Sobrien */ 7038494Sobrienam_ops amfs_nfsl_ops = 7138494Sobrien{ 72174294Sobrien "nfsl", 73174294Sobrien amfs_nfsl_match, 74174294Sobrien amfs_nfsl_init, 75174294Sobrien amfs_nfsl_mount, 76174294Sobrien amfs_nfsl_umount, 77174294Sobrien amfs_error_lookup_child, 78174294Sobrien amfs_error_mount_child, 79174294Sobrien amfs_error_readdir, 80174294Sobrien 0, /* amfs_nfsl_readlink */ 81174294Sobrien 0, /* amfs_nfsl_mounted */ 82174294Sobrien amfs_nfsl_umounted, 83174294Sobrien amfs_nfsl_ffserver, 84174294Sobrien 0, /* amfs_nfsl_get_wchan */ 85174294Sobrien FS_MKMNT | FS_BACKGROUND | FS_AMQINFO, /* nfs_fs_flags */ 86174294Sobrien#ifdef HAVE_FS_AUTOFS 87174294Sobrien AUTOFS_NFSL_FS_FLAGS, 88174294Sobrien#endif /* HAVE_FS_AUTOFS */ 8938494Sobrien}; 9038494Sobrien 9138494Sobrien 9238494Sobrien/* 9338494Sobrien * Check that f/s has all needed fields. 9438494Sobrien * Returns: matched string if found, NULL otherwise. 9538494Sobrien */ 9638494Sobrienstatic char * 9738494Sobrienamfs_nfsl_match(am_opts *fo) 9838494Sobrien{ 99174294Sobrien char *cp; 10038494Sobrien char *ho = fo->opt_rhost; 101174294Sobrien char *retval; 10238494Sobrien struct stat stb; 10338494Sobrien 104174294Sobrien if (fo->opt_sublink) 105174294Sobrien cp = fo->opt_sublink; 106174294Sobrien else 107174294Sobrien cp = fo->opt_fs; 108174294Sobrien 10938494Sobrien if (!cp || !ho) { 11042629Sobrien plog(XLOG_USER, "amfs_nfsl: host $fs and $rhost must be specified"); 11138494Sobrien return NULL; 11238494Sobrien } 11338494Sobrien 11438494Sobrien /* 11538494Sobrien * If this host is not the same as $rhost, or if link does not exist, 116174294Sobrien * call nfs_ops.fs_match(). 117174294Sobrien * If link value exists (or same host), call amfs_link_ops.fs_match(). 11838494Sobrien */ 11942629Sobrien if (!STRCEQ(ho, am_get_hostname())) { 12038494Sobrien plog(XLOG_INFO, "amfs_nfsl: \"%s\" is not local host, using type:=nfs", ho); 121174294Sobrien retval = nfs_ops.fs_match(fo); 12238494Sobrien } else if (lstat(cp, &stb) < 0) { 12338494Sobrien plog(XLOG_INFO, "amfs_nfsl: \"%s\" does not exist, using type:=nfs", cp); 124174294Sobrien retval = nfs_ops.fs_match(fo); 12538494Sobrien } else { 12638494Sobrien plog(XLOG_INFO, "amfs_nfsl: \"%s\" exists, using type:=link", cp); 127174294Sobrien retval = amfs_link_ops.fs_match(fo); 12838494Sobrien } 129174294Sobrien return retval; 13038494Sobrien} 13138494Sobrien 13238494Sobrien 13338494Sobrien/* 13438494Sobrien * Initialize. 13538494Sobrien * Returns: 0 if OK, non-zero (errno) if failed. 13638494Sobrien */ 13738494Sobrienstatic int 13838494Sobrienamfs_nfsl_init(mntfs *mf) 13938494Sobrien{ 140174294Sobrien int ret = 0; 14138494Sobrien if (mf->mf_flags & MFF_NFSLINK) { 142174294Sobrien if (amfs_link_ops.fs_init) 143174294Sobrien ret = amfs_link_ops.fs_init(mf); 14438494Sobrien } else { 145174294Sobrien if (nfs_ops.fs_init) 146174294Sobrien ret = nfs_ops.fs_init(mf); 14738494Sobrien } 148174294Sobrien return ret; 14938494Sobrien} 15038494Sobrien 15138494Sobrien 15238494Sobrien/* 15338494Sobrien * Mount vfs. 15438494Sobrien * Returns: 0 if OK, non-zero (errno) if failed. 15538494Sobrien */ 15638494Sobrienstatic int 157174294Sobrienamfs_nfsl_mount(am_node *mp, mntfs *mf) 15838494Sobrien{ 159174294Sobrien int ret = 0; 16038494Sobrien if (mf->mf_flags & MFF_NFSLINK) { 161174294Sobrien if (amfs_link_ops.mount_fs) 162174294Sobrien ret = amfs_link_ops.mount_fs(mp, mf); 16338494Sobrien } else { 164174294Sobrien if (nfs_ops.mount_fs) 165174294Sobrien ret = nfs_ops.mount_fs(mp, mf); 16638494Sobrien } 167174294Sobrien return ret; 16838494Sobrien} 16938494Sobrien 17038494Sobrien 17138494Sobrien/* 17238494Sobrien * Unmount VFS. 17338494Sobrien * Returns: 0 if OK, non-zero (errno) if failed. 17438494Sobrien */ 17538494Sobrienstatic int 176174294Sobrienamfs_nfsl_umount(am_node *mp, mntfs *mf) 17738494Sobrien{ 178174294Sobrien int ret = 0; 17938494Sobrien if (mf->mf_flags & MFF_NFSLINK) { 180174294Sobrien if (amfs_link_ops.umount_fs) 181174294Sobrien ret = amfs_link_ops.umount_fs(mp, mf); 18238494Sobrien } else { 183174294Sobrien if (nfs_ops.umount_fs) 184174294Sobrien ret = nfs_ops.umount_fs(mp, mf); 18538494Sobrien } 186174294Sobrien return ret; 18738494Sobrien} 18838494Sobrien 18938494Sobrien 19038494Sobrien/* 19138494Sobrien * Async unmount callback function. 19238494Sobrien * After the base umount() succeeds, we may want to take extra actions, 19338494Sobrien * such as informing remote mount daemons that we've unmounted them. 19438494Sobrien * See amfs_auto_umounted(), host_umounted(), nfs_umounted(). 19538494Sobrien */ 19638494Sobrienstatic void 197174294Sobrienamfs_nfsl_umounted(mntfs *mf) 19838494Sobrien{ 19938494Sobrien if (mf->mf_flags & MFF_NFSLINK) { 200174294Sobrien if (amfs_link_ops.umounted) 201174294Sobrien amfs_link_ops.umounted(mf); 20238494Sobrien } else { 203174294Sobrien if (nfs_ops.umounted) 204174294Sobrien nfs_ops.umounted(mf); 20538494Sobrien } 20638494Sobrien} 20738494Sobrien 20838494Sobrien 20938494Sobrien/* 21038494Sobrien * Find a file server. 21138494Sobrien * Returns: fserver of found server, or NULL if not found. 21238494Sobrien */ 21338494Sobrienstatic fserver * 21438494Sobrienamfs_nfsl_ffserver(mntfs *mf) 21538494Sobrien{ 216174294Sobrien char *cp; 21738494Sobrien char *ho = mf->mf_fo->opt_rhost; 21838494Sobrien struct stat stb; 21938494Sobrien 220174294Sobrien if (mf->mf_fo->opt_sublink) 221174294Sobrien cp = mf->mf_fo->opt_sublink; 222174294Sobrien else 223174294Sobrien cp = mf->mf_fo->opt_fs; 224174294Sobrien 22538494Sobrien /* 22638494Sobrien * If this host is not the same as $rhost, or if link does not exist, 227174294Sobrien * call amfs_link_ops.ffserver(). 228174294Sobrien * If link value exists (or same host), then call ops_nfs.ffserver(). 22938494Sobrien */ 23042629Sobrien if (!STRCEQ(ho, am_get_hostname()) || lstat(cp, &stb) < 0) { 231174294Sobrien return nfs_ops.ffserver(mf); 23238494Sobrien } else { 23338494Sobrien mf->mf_flags |= MFF_NFSLINK; 234174294Sobrien /* remove the FS_MKMNT flag, we don't want amd touching the mountpoint */ 235174294Sobrien mf->mf_fsflags &= ~FS_MKMNT; 236174294Sobrien return amfs_link_ops.ffserver(mf); 23738494Sobrien } 23838494Sobrien} 239