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
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)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