1/*	$NetBSD$	*/
2
3/*
4 * Copyright (c) 1997-2014 Erez Zadok
5 * Copyright (c) 1990 Jan-Simon Pendry
6 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
7 * Copyright (c) 1990 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. Neither the name of the University nor the names of its contributors
22 *    may be used to endorse or promote products derived from this software
23 *    without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 *
38 * File: am-utils/amd/amfs_union.c
39 *
40 */
41
42/*
43 * Union automounter file system
44 */
45
46#ifdef HAVE_CONFIG_H
47# include <config.h>
48#endif /* HAVE_CONFIG_H */
49#include <am_defs.h>
50#include <amd.h>
51
52/****************************************************************************
53 *** FORWARD DEFINITIONS                                                  ***
54 ****************************************************************************/
55static int create_amfs_union_node(char *dir, opaque_t arg);
56static void amfs_union_mounted(mntfs *mf);
57
58
59/****************************************************************************
60 *** OPS STRUCTURES                                                       ***
61 ****************************************************************************/
62am_ops amfs_union_ops =
63{
64  "union",
65  amfs_generic_match,
66  0,				/* amfs_union_init */
67  amfs_toplvl_mount,
68  amfs_toplvl_umount,
69  amfs_generic_lookup_child,
70  amfs_generic_mount_child,
71  amfs_generic_readdir,
72  0,				/* amfs_union_readlink */
73  amfs_union_mounted,
74  0,				/* amfs_union_umounted */
75  amfs_generic_find_srvr,
76  0,				/* amfs_union_get_wchan */
77  FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO | FS_DIRECTORY,
78#ifdef HAVE_FS_AUTOFS
79  AUTOFS_UNION_FS_FLAGS,
80#endif /* HAVE_FS_AUTOFS */
81};
82
83
84/*
85 * Create a reference to a union'ed entry
86 * XXX: this function may not be used anywhere...
87 */
88static int
89create_amfs_union_node(char *dir, opaque_t arg)
90{
91  if (!STREQ(dir, "/defaults")) {
92    int error = 0;
93    am_node *am;
94    am = amfs_generic_lookup_child(arg, dir, &error, VLOOK_CREATE);
95    if (am && error < 0)
96      (void)amfs_generic_mount_child(am, &error);
97    if (error > 0) {
98      errno = error;		/* XXX */
99      plog(XLOG_ERROR, "unionfs: could not mount %s: %m", dir);
100    }
101    return error;
102  }
103  return 0;
104}
105
106
107static void
108amfs_union_mounted(mntfs *mf)
109{
110  int index;
111  am_node *mp;
112
113  amfs_mkcacheref(mf);
114
115  /*
116   * Having made the union mount point,
117   * populate all the entries...
118   */
119  for (mp = get_first_exported_ap(&index);
120       mp;
121       mp = get_next_exported_ap(&index)) {
122    if (mp->am_al->al_mnt == mf) {
123      /* return value from create_amfs_union_node is ignored by mapc_keyiter */
124      (void) mapc_keyiter((mnt_map *) mp->am_al->al_mnt->mf_private,
125			  create_amfs_union_node,
126			  mp);
127      break;
128    }
129  }
130}
131