1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Manage a cache of file names' existence */ 3 #include <pthread.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include <unistd.h> 7 #include <linux/compiler.h> 8 #include "fncache.h" 9 #include "hashmap.h" 10 11 static struct hashmap *fncache; 12 13 static size_t fncache__hash(long key, void *ctx __maybe_unused) 14 { 15 return str_hash((const char *)key); 16 } 17 18 static bool fncache__equal(long key1, long key2, void *ctx __maybe_unused) 19 { 20 return strcmp((const char *)key1, (const char *)key2) == 0; 21 } 22 23 static void fncache__init(void) 24 { 25 fncache = hashmap__new(fncache__hash, fncache__equal, /*ctx=*/NULL); 26 } 27 28 static struct hashmap *fncache__get(void) 29 { 30 static pthread_once_t fncache_once = PTHREAD_ONCE_INIT; 31 32 pthread_once(&fncache_once, fncache__init); 33 34 return fncache; 35 } 36 37 static bool lookup_fncache(const char *name, bool *res) 38 { 39 long val; 40 41 if (!hashmap__find(fncache__get(), name, &val)) 42 return false; 43 44 *res = (val != 0); 45 return true; 46 } 47 48 static void update_fncache(const char *name, bool res) 49 { 50 char *old_key = NULL, *key = strdup(name); 51 52 if (key) { 53 hashmap__set(fncache__get(), key, res, &old_key, /*old_value*/NULL); 54 free(old_key); 55 } 56 } 57 58 /* No LRU, only use when bounded in some other way. */ 59 bool file_available(const char *name) 60 { 61 bool res; 62 63 if (lookup_fncache(name, &res)) 64 return res; 65 res = access(name, R_OK) == 0; 66 update_fncache(name, res); 67 return res; 68 } 69