123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- /*
- * Copyright (c) 2011-2012 Nokia Corporation and/or its subsidiary(-ies).
- * All rights reserved.
- * This component and the accompanying materials are made available
- * under the terms of the License "Eclipse Public License v1.0"
- * which accompanies this distribution, and is available
- * at the URL "http://www.eclipse.org/legal/epl-v10.html".
- *
- * Initial Contributors:
- * Nokia Corporation - initial contribution.
- *
- * Contributors:
- *
- * Description:
- *
- * pathcache.c - maps between the lowercase of a filename and the actual
- * name on the filesystem.
- */
- #include <alloca.h>
- #include <string.h>
- #include <errno.h>
- #include <dirent.h>
- #include <ctype.h>
- #include <assert.h>
- #include "pathcache.h"
- #include "debug.h"
- HashTable *caseless_ht = NULL;
- long caseless_cache_hits = 0;
- long caseless_cache_misses = 0;
- void caseless_cache_init(const char rootpath[])
- {
- assert(rootpath);
- caseless_ht = hashtable_new(MAX_FILENAME_CACHE);
- cache_subtree(rootpath, caseless_ht);
- }
- /*
- Record a file in the cach using the lowercased absolute path as a key
- */
- void caseless_cache_path(const char path[])
- {
- assert(path);
- char * lowercase_path = alloca(strlen(path)+1);
- int i;
- for (i = 0; path[i] != '\0'; i++)
- {
- lowercase_path[i] = tolower(path[i]);
- }
- lowercase_path[i] = '\0';
- hashtable_store(caseless_ht, lowercase_path, path);
- }
- /*
- Mark a file as not existing in the cache so it's quick to answer "stat" operaions
- that look for files which are not there - e.g. when make is running.
- */
- void caseless_cache_missing(const char path[])
- {
- assert(path);
- char * lowercase_path = alloca(strlen(path)+1);
- int i;
- for (i = 0; path[i] != '\0'; i++)
- {
- lowercase_path[i] = tolower(path[i]);
- }
- lowercase_path[i] = '\0';
- hashtable_store(caseless_ht, lowercase_path, "");
- }
- /*
- see if a file is in the cache without regarding the case of the filename
- - return the absolute "real" name of the file on disc (ie. with correct case)
- or NULL if the file doesn't exist.
- */
- char *caseless_cache_lookup(const char path[])
- {
- assert(path);
- char *lowercase_path = alloca(strlen(path)+1);
- int i;
- for (i = 0; path[i] != '\0'; i++)
- {
- lowercase_path[i] = tolower(path[i]);
- }
- lowercase_path[i] = '\0';
- return hashtable_lookup(caseless_ht, lowercase_path);
- }
- /*
- cache_subtree
- path - path to start from
- dircache - hashtable to add case insensitive mappings to.
- Recursive function to pre-fill the cache with all files and directories
- from the source subtree down. This would usually be done once when the
- filesystem is first mounted to populate the cache with existing files.
- The open, create, unlink etc function calls are then supposed to keep
- the cache uptodate.
- */
- int cache_subtree(const char path[], HashTable *dircache)
- {
- DIR *d = NULL;
- struct dirent entry;
- struct dirent *index;
- assert(path);
- int path_len = strlen(path) + NAME_MAX + 2;
- char * subpath = alloca(path_len);
- assert(dircache);
- d = opendir(path);
- debug(">>cache_subtree: opened %s, result=%d\n",path,(size_t)d);
- if (!d)
- return errno;
- readdir_r(d, &entry, &index);
- debug(">>cache_subtree: initial readdir %s\n",entry.d_name);
- while (index == &entry)
- {
- if (strcmp(entry.d_name,".") == 0 ||
- strcmp(entry.d_name,"..") == 0)
- {
- readdir_r(d, &entry, &index);
- continue;
- }
- strcpy(subpath, path);
- strcat(subpath, "/");
- strcat(subpath, entry.d_name);
- caseless_cache_path(subpath);
- if (entry.d_type == DT_DIR)
- {
- cache_subtree(subpath, dircache);
- }
-
- readdir_r(d, &entry, &index);
- }
- caseless_cache_path(path);
- closedir(d);
-
- return 0;
- }
- /*
- Locates files and caches the results for future use. Records
- as missing those files that are looked for but not found.
- The input parameter is modified to contain the actual filename
- so must be big enough to hold any possible absolute filename.
- returns 0 if the file is found, non-zero if it isn't.
- */
- int cached_findcaseless(char *path)
- {
- int fcr = 0;
- char *cached;
- assert(path);
- cached = caseless_cache_lookup(path);
- debug("caseless: cache_hit sought '%s', found '%s'\n", path, cached);
- if (cached)
- {
- if (cached[0] == '\0')
- {
- debug("caseless: file known to not exist '%s'\n", path);
- fcr = 1;
- } else {
- strcpy(path,cached); // dest should be big enough
- }
- caseless_cache_hits = (caseless_cache_hits+1) % 2000000000;
- } else {
- debug("caseless: cache_miss '%s'\n", path);
- caseless_cache_missing(path);
- fcr = 1;
- }
- return fcr;
- }
|