| 1 | |
| 2 |
|
| 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, 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, NULL);
|
| 54 | free(old_key);
|
| 55 | }
|
| 56 | }
|
| 57 |
|
| 58 |
|
| 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 | }
|