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 #include <stdio.h>
29 #include <ctype.h>
30 #include <string.h>
31 #include <syslog.h>
32 #include <errno.h>
33 #include <locale.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <assert.h>
37 #include "automount.h"
38
39 int
do_lookup1(char * mapname,char * key,char * subdir,char * mapopts,char * path,uint_t isdirect,uid_t uid,autofs_action_t * action,struct linka * linkp)40 do_lookup1(
41 char *mapname,
42 char *key,
43 char *subdir,
44 char *mapopts,
45 char *path,
46 uint_t isdirect,
47 uid_t uid,
48 autofs_action_t *action,
49 struct linka *linkp)
50 {
51 struct mapline ml;
52 struct mapent *mapents = NULL;
53 int err;
54 struct autofs_rddir_cache *rdcp;
55 int found = 0;
56 bool_t iswildcard = FALSE;
57 bool_t isrestricted = hasrestrictopt(mapopts);
58 char *stack[STACKSIZ];
59 char **stkptr = stack;
60
61 /*
62 * Default action is for no work to be done by kernel AUTOFS.
63 */
64 *action = AUTOFS_NONE;
65
66 /*
67 * Is there a cache for this map?
68 */
69 rw_rdlock(&autofs_rddir_cache_lock);
70 err = autofs_rddir_cache_lookup(mapname, &rdcp);
71 if (!err && rdcp->full) {
72 rw_unlock(&autofs_rddir_cache_lock);
73 /*
74 * Try to lock readdir cache entry for reading, if
75 * the entry can not be locked, then avoid blocking
76 * and go to the name service. I'm assuming it is
77 * faster to go to the name service than to wait for
78 * the cache to be populated.
79 */
80 if (rw_tryrdlock(&rdcp->rwlock) == 0) {
81 found = (rddir_entry_lookup(key, rdcp->entp) != NULL);
82 rw_unlock(&rdcp->rwlock);
83 }
84 } else
85 rw_unlock(&autofs_rddir_cache_lock);
86
87 if (!err) {
88 /*
89 * release reference on cache entry
90 */
91 mutex_lock(&rdcp->lock);
92 rdcp->in_use--;
93 assert(rdcp->in_use >= 0);
94 mutex_unlock(&rdcp->lock);
95 }
96
97 if (found)
98 return (0);
99
100 /*
101 * entry not found in cache, try the name service now
102 */
103 err = 0;
104
105 /* initialize the stack of open files for this thread */
106 stack_op(INIT, NULL, stack, &stkptr);
107
108 err = getmapent(key, mapname, &ml, stack, &stkptr, &iswildcard,
109 isrestricted);
110 if (err == 0) /* call parser w default mount_access = TRUE */
111 mapents = parse_entry(key, mapname, mapopts, &ml,
112 subdir, isdirect, TRUE);
113
114 /*
115 * Now we indulge in a bit of hanky-panky.
116 * If the entry isn't found in the map and the
117 * name begins with an "=" then we assume that
118 * the name is an undocumented control message
119 * for the daemon. This is accessible only
120 * to superusers.
121 */
122 if (mapents == NULL && *action == AUTOFS_NONE) {
123 if (*key == '=' && uid == 0) {
124 if (isdigit(*(key+1))) {
125 /*
126 * If next character is a digit
127 * then set the trace level.
128 */
129 trace = atoi(key+1);
130 trace_prt(1, "Automountd: trace level = %d\n",
131 trace);
132 } else if (*(key+1) == 'v') {
133 /*
134 * If it's a "v" then
135 * toggle verbose mode.
136 */
137 verbose = !verbose;
138 trace_prt(1, "Automountd: verbose %s\n",
139 verbose ? "on" : "off");
140 }
141 }
142
143 err = ENOENT;
144 goto done;
145 }
146
147 /*
148 * Each mapent in the list describes a mount to be done.
149 * Since I'm only doing a lookup, I only care whether a mapentry
150 * was found or not. The mount will be done on a later RPC to
151 * do_mount1.
152 */
153 if (mapents == NULL && *action == AUTOFS_NONE)
154 err = ENOENT;
155
156 done: if (mapents)
157 free_mapent(mapents);
158
159 if (*action == AUTOFS_NONE && (iswildcard == TRUE)) {
160 *action = AUTOFS_MOUNT_RQ;
161 }
162 if (trace > 1) {
163 trace_prt(1, " do_lookup1: action=%d wildcard=%s error=%d\n",
164 *action, iswildcard ? "TRUE" : "FALSE", err);
165 }
166 return (err);
167 }
168