xref: /illumos-gate/usr/src/cmd/fs.d/autofs/autod_lookup.c (revision 2983dda76a6d296fdb560c88114fe41caad1b84f)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  *	autod_lookup.c
23  *
24  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 #pragma ident	"%Z%%M%	%I%	%E% SMI"
29 
30 #include <stdio.h>
31 #include <ctype.h>
32 #include <string.h>
33 #include <syslog.h>
34 #include <errno.h>
35 #include <locale.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <assert.h>
39 #include "automount.h"
40 
41 int
42 do_lookup1(
43 	char *mapname,
44 	char *key,
45 	char *subdir,
46 	char *mapopts,
47 	char *path,
48 	uint_t isdirect,
49 	uid_t uid,
50 	autofs_action_t *action,
51 	struct linka *linkp)
52 {
53 	struct mapline ml;
54 	struct mapent *mapents = NULL;
55 	int err;
56 	struct autofs_rddir_cache *rdcp;
57 	int found = 0;
58 	bool_t iswildcard = FALSE;
59 	bool_t isrestricted = hasrestrictopt(mapopts);
60 	char *stack[STACKSIZ];
61 	char **stkptr = stack;
62 
63 	/*
64 	 * Default action is for no work to be done by kernel AUTOFS.
65 	 */
66 	*action = AUTOFS_NONE;
67 
68 	/*
69 	 * Is there a cache for this map?
70 	 */
71 	rw_rdlock(&autofs_rddir_cache_lock);
72 	err = autofs_rddir_cache_lookup(mapname, &rdcp);
73 	if (!err && rdcp->full) {
74 		rw_unlock(&autofs_rddir_cache_lock);
75 		/*
76 		 * Try to lock readdir cache entry for reading, if
77 		 * the entry can not be locked, then avoid blocking
78 		 * and go to the name service. I'm assuming it is
79 		 * faster to go to the name service than to wait for
80 		 * the cache to be populated.
81 		 */
82 		if (rw_tryrdlock(&rdcp->rwlock) == 0) {
83 			found = (rddir_entry_lookup(key, rdcp->entp) != NULL);
84 			rw_unlock(&rdcp->rwlock);
85 		}
86 	} else
87 		rw_unlock(&autofs_rddir_cache_lock);
88 
89 	if (!err) {
90 		/*
91 		 * release reference on cache entry
92 		 */
93 		mutex_lock(&rdcp->lock);
94 		rdcp->in_use--;
95 		assert(rdcp->in_use >= 0);
96 		mutex_unlock(&rdcp->lock);
97 	}
98 
99 	if (found)
100 		return (0);
101 
102 	/*
103 	 * entry not found in cache, try the name service now
104 	 */
105 	err = 0;
106 
107 	/* initialize the stack of open files for this thread */
108 	stack_op(INIT, NULL, stack, &stkptr);
109 
110 	err = getmapent(key, mapname, &ml, stack, &stkptr, &iswildcard,
111 		isrestricted);
112 	if (err == 0) /* call parser w default mount_access = TRUE */
113 		mapents = parse_entry(key, mapname, mapopts, &ml,
114 				    subdir, isdirect, TRUE);
115 
116 	/*
117 	 * Now we indulge in a bit of hanky-panky.
118 	 * If the entry isn't found in the map and the
119 	 * name begins with an "=" then we assume that
120 	 * the name is an undocumented control message
121 	 * for the daemon.  This is accessible only
122 	 * to superusers.
123 	 */
124 	if (mapents == NULL && *action == AUTOFS_NONE) {
125 		if (*key == '=' && uid == 0) {
126 			if (isdigit(*(key+1))) {
127 				/*
128 				 * If next character is a digit
129 				 * then set the trace level.
130 				 */
131 				trace = atoi(key+1);
132 				trace_prt(1, "Automountd: trace level = %d\n",
133 					trace);
134 			} else if (*(key+1) == 'v') {
135 				/*
136 				 * If it's a "v" then
137 				 * toggle verbose mode.
138 				 */
139 				verbose = !verbose;
140 				trace_prt(1, "Automountd: verbose %s\n",
141 						verbose ? "on" : "off");
142 			}
143 		}
144 
145 		err = ENOENT;
146 		goto done;
147 	}
148 
149 	/*
150 	 * Each mapent in the list describes a mount to be done.
151 	 * Since I'm only doing a lookup, I only care whether a mapentry
152 	 * was found or not. The mount will be done on a later RPC to
153 	 * do_mount1.
154 	 */
155 	if (mapents == NULL && *action == AUTOFS_NONE)
156 		err = ENOENT;
157 
158 done:	if (mapents)
159 		free_mapent(mapents);
160 
161 	if (*action == AUTOFS_NONE && (iswildcard == TRUE)) {
162 		*action = AUTOFS_MOUNT_RQ;
163 	}
164 	if (trace > 1) {
165 		trace_prt(1, "  do_lookup1: action=%d wildcard=%s error=%d\n",
166 			*action, iswildcard ? "TRUE" : "FALSE", err);
167 	}
168 	return (err);
169 }
170