dnsp: Parse TXT records
[Samba/gebeck_regimport.git] / source3 / smbd / statcache.c
blobecadbdcdd40104742a94661fd83d2d793c730419
1 /*
2 Unix SMB/CIFS implementation.
3 stat cache code
4 Copyright (C) Andrew Tridgell 1992-2000
5 Copyright (C) Jeremy Allison 1999-2007
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "librpc/gen_ndr/messaging.h"
25 #include "memcache.h"
27 /****************************************************************************
28 Stat cache code used in unix_convert.
29 *****************************************************************************/
31 /**
32 * Add an entry into the stat cache.
34 * @param full_orig_name The original name as specified by the client
35 * @param orig_translated_path The name on our filesystem.
37 * @note Only the first strlen(orig_translated_path) characters are stored
38 * into the cache. This means that full_orig_name will be internally
39 * truncated.
43 void stat_cache_add( const char *full_orig_name,
44 char *translated_path,
45 bool case_sensitive)
47 size_t translated_path_length;
48 char *original_path;
49 size_t original_path_length;
50 char saved_char;
51 TALLOC_CTX *ctx = talloc_tos();
53 if (!lp_stat_cache()) {
54 return;
58 * Don't cache trivial valid directory entries such as . and ..
61 if ((*full_orig_name == '\0')
62 || ISDOT(full_orig_name) || ISDOTDOT(full_orig_name)) {
63 return;
67 * If we are in case insentive mode, we don't need to
68 * store names that need no translation - else, it
69 * would be a waste.
72 if (case_sensitive && (strcmp(full_orig_name, translated_path) == 0)) {
73 return;
77 * Remove any trailing '/' characters from the
78 * translated path.
81 translated_path_length = strlen(translated_path);
83 if(translated_path[translated_path_length-1] == '/') {
84 translated_path_length--;
87 if(case_sensitive) {
88 original_path = talloc_strdup(ctx,full_orig_name);
89 } else {
90 original_path = talloc_strdup_upper(ctx,full_orig_name);
93 if (!original_path) {
94 return;
97 original_path_length = strlen(original_path);
99 if(original_path[original_path_length-1] == '/') {
100 original_path[original_path_length-1] = '\0';
101 original_path_length--;
104 if (original_path_length != translated_path_length) {
105 if (original_path_length < translated_path_length) {
106 DEBUG(0, ("OOPS - tried to store stat cache entry "
107 "for weird length paths [%s] %lu and [%s] %lu)!\n",
108 original_path,
109 (unsigned long)original_path_length,
110 translated_path,
111 (unsigned long)translated_path_length));
112 TALLOC_FREE(original_path);
113 return;
116 /* we only want to index by the first part of original_path,
117 up to the length of translated_path */
119 original_path[translated_path_length] = '\0';
120 original_path_length = translated_path_length;
123 /* Ensure we're null terminated. */
124 saved_char = translated_path[translated_path_length];
125 translated_path[translated_path_length] = '\0';
128 * New entry or replace old entry.
131 memcache_add(
132 smbd_memcache(), STAT_CACHE,
133 data_blob_const(original_path, original_path_length),
134 data_blob_const(translated_path, translated_path_length + 1));
136 DEBUG(5,("stat_cache_add: Added entry (%lx:size %x) %s -> %s\n",
137 (unsigned long)translated_path,
138 (unsigned int)translated_path_length,
139 original_path,
140 translated_path));
142 translated_path[translated_path_length] = saved_char;
143 TALLOC_FREE(original_path);
147 * Look through the stat cache for an entry
149 * @param conn A connection struct to do the stat() with.
150 * @param name The path we are attempting to cache, modified by this routine
151 * to be correct as far as the cache can tell us. We assume that
152 * it is a talloc'ed string from top of stack, we free it if
153 * necessary.
154 * @param dirpath The path as far as the stat cache told us. Also talloced
155 * from top of stack.
156 * @param start A pointer into name, for where to 'start' in fixing the rest
157 * of the name up.
158 * @param psd A stat buffer, NOT from the cache, but just a side-effect.
160 * @return True if we translated (and did a scuccessful stat on) the entire
161 * name.
165 bool stat_cache_lookup(connection_struct *conn,
166 char **pp_name,
167 char **pp_dirpath,
168 char **pp_start,
169 SMB_STRUCT_STAT *pst)
171 char *chk_name;
172 size_t namelen;
173 bool sizechanged = False;
174 unsigned int num_components = 0;
175 char *translated_path;
176 size_t translated_path_length;
177 DATA_BLOB data_val;
178 char *name;
179 TALLOC_CTX *ctx = talloc_tos();
180 struct smb_filename smb_fname;
182 *pp_dirpath = NULL;
183 *pp_start = *pp_name;
185 if (!lp_stat_cache()) {
186 return False;
189 name = *pp_name;
190 namelen = strlen(name);
192 DO_PROFILE_INC(statcache_lookups);
195 * Don't lookup trivial valid directory entries.
197 if ((*name == '\0') || ISDOT(name) || ISDOTDOT(name)) {
198 return False;
201 if (conn->case_sensitive) {
202 chk_name = talloc_strdup(ctx,name);
203 if (!chk_name) {
204 DEBUG(0, ("stat_cache_lookup: strdup failed!\n"));
205 return False;
208 } else {
209 chk_name = talloc_strdup_upper(ctx,name);
210 if (!chk_name) {
211 DEBUG(0, ("stat_cache_lookup: talloc_strdup_upper failed!\n"));
212 return False;
216 * In some language encodings the length changes
217 * if we uppercase. We need to treat this differently
218 * below.
220 if (strlen(chk_name) != namelen) {
221 sizechanged = True;
225 while (1) {
226 char *sp;
228 data_val = data_blob_null;
230 if (memcache_lookup(
231 smbd_memcache(), STAT_CACHE,
232 data_blob_const(chk_name, strlen(chk_name)),
233 &data_val)) {
234 break;
237 DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n",
238 chk_name ));
240 * Didn't find it - remove last component for next try.
242 if (!(sp = strrchr_m(chk_name, '/'))) {
244 * We reached the end of the name - no match.
246 DO_PROFILE_INC(statcache_misses);
247 TALLOC_FREE(chk_name);
248 return False;
251 *sp = '\0';
254 * Count the number of times we have done this, we'll
255 * need it when reconstructing the string.
258 if (sizechanged) {
259 num_components++;
262 if ((*chk_name == '\0')
263 || ISDOT(chk_name) || ISDOTDOT(chk_name)) {
264 DO_PROFILE_INC(statcache_misses);
265 TALLOC_FREE(chk_name);
266 return False;
270 translated_path = talloc_strdup(ctx,(char *)data_val.data);
271 if (!translated_path) {
272 smb_panic("talloc failed");
274 translated_path_length = data_val.length - 1;
276 DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] "
277 "-> [%s]\n", chk_name, translated_path ));
278 DO_PROFILE_INC(statcache_hits);
280 ZERO_STRUCT(smb_fname);
281 smb_fname.base_name = translated_path;
283 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
284 /* Discard this entry - it doesn't exist in the filesystem. */
285 memcache_delete(smbd_memcache(), STAT_CACHE,
286 data_blob_const(chk_name, strlen(chk_name)));
287 TALLOC_FREE(chk_name);
288 TALLOC_FREE(translated_path);
289 return False;
291 *pst = smb_fname.st;
293 if (!sizechanged) {
294 memcpy(*pp_name, translated_path,
295 MIN(namelen, translated_path_length));
296 } else {
297 if (num_components == 0) {
298 name = talloc_strndup(ctx, translated_path,
299 translated_path_length);
300 } else {
301 char *sp;
303 sp = strnrchr_m(name, '/', num_components);
304 if (sp) {
305 name = talloc_asprintf(ctx,"%.*s%s",
306 (int)translated_path_length,
307 translated_path, sp);
308 } else {
309 name = talloc_strndup(ctx,
310 translated_path,
311 translated_path_length);
314 if (name == NULL) {
316 * TODO: Get us out of here with a real error message
318 smb_panic("talloc failed");
320 TALLOC_FREE(*pp_name);
321 *pp_name = name;
325 /* set pointer for 'where to start' on fixing the rest of the name */
326 *pp_start = &name[translated_path_length];
327 if (**pp_start == '/') {
328 ++*pp_start;
331 *pp_dirpath = translated_path;
332 TALLOC_FREE(chk_name);
333 return (namelen == translated_path_length);
336 /***************************************************************************
337 Tell all smbd's to delete an entry.
338 **************************************************************************/
340 void send_stat_cache_delete_message(struct messaging_context *msg_ctx,
341 const char *name)
343 #ifdef DEVELOPER
344 message_send_all(msg_ctx,
345 MSG_SMB_STAT_CACHE_DELETE,
346 name,
347 strlen(name)+1,
348 NULL);
349 #endif
352 /***************************************************************************
353 Delete an entry.
354 **************************************************************************/
356 void stat_cache_delete(const char *name)
358 char *lname = talloc_strdup_upper(talloc_tos(), name);
360 if (!lname) {
361 return;
363 DEBUG(10,("stat_cache_delete: deleting name [%s] -> %s\n",
364 lname, name ));
366 memcache_delete(smbd_memcache(), STAT_CACHE,
367 data_blob_const(lname, talloc_get_size(lname)-1));
368 TALLOC_FREE(lname);
371 /***************************************************************
372 Compute a hash value based on a string key value.
373 The function returns the bucket index number for the hashed key.
374 JRA. Use a djb-algorithm hash for speed.
375 ***************************************************************/
377 unsigned int fast_string_hash(TDB_DATA *key)
379 unsigned int n = 0;
380 const char *p;
381 for (p = (const char *)key->dptr; *p != '\0'; p++) {
382 n = ((n << 5) + n) ^ (unsigned int)(*p);
384 return n;
387 /***************************************************************************
388 Initializes or clears the stat cache.
389 **************************************************************************/
391 bool reset_stat_cache( void )
393 if (!lp_stat_cache())
394 return True;
396 memcache_flush(smbd_memcache(), STAT_CACHE);
398 return True;