| // SPDX-License-Identifier: GPL-2.0-only | |
| /* Manage a cache of file names' existence */ | |
| #include <pthread.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <unistd.h> | |
| #include <linux/compiler.h> | |
| #include "fncache.h" | |
| #include "hashmap.h" | |
| static struct hashmap *fncache; | |
| static size_t fncache__hash(long key, void *ctx __maybe_unused) | |
| { | |
| return str_hash((const char *)key); | |
| } | |
| static bool fncache__equal(long key1, long key2, void *ctx __maybe_unused) | |
| { | |
| return strcmp((const char *)key1, (const char *)key2) == 0; | |
| } | |
| static void fncache__init(void) | |
| { | |
| fncache = hashmap__new(fncache__hash, fncache__equal, /*ctx=*/NULL); | |
| } | |
| static struct hashmap *fncache__get(void) | |
| { | |
| static pthread_once_t fncache_once = PTHREAD_ONCE_INIT; | |
| pthread_once(&fncache_once, fncache__init); | |
| return fncache; | |
| } | |
| static bool lookup_fncache(const char *name, bool *res) | |
| { | |
| long val; | |
| if (!hashmap__find(fncache__get(), name, &val)) | |
| return false; | |
| *res = (val != 0); | |
| return true; | |
| } | |
| static void update_fncache(const char *name, bool res) | |
| { | |
| char *old_key = NULL, *key = strdup(name); | |
| if (key) { | |
| hashmap__set(fncache__get(), key, res, &old_key, /*old_value*/NULL); | |
| free(old_key); | |
| } | |
| } | |
| /* No LRU, only use when bounded in some other way. */ | |
| bool file_available(const char *name) | |
| { | |
| bool res; | |
| if (lookup_fncache(name, &res)) | |
| return res; | |
| res = access(name, R_OK) == 0; | |
| update_fncache(name, res); | |
| return res; | |
| } |