123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 |
- // SPDX-License-Identifier: GPL-2.0-only
- /* Manage a cache of file names' existence */
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <linux/list.h>
- #include "fncache.h"
- struct fncache {
- struct hlist_node nd;
- bool res;
- char name[];
- };
- #define FNHSIZE 61
- static struct hlist_head fncache_hash[FNHSIZE];
- unsigned shash(const unsigned char *s)
- {
- unsigned h = 0;
- while (*s)
- h = 65599 * h + *s++;
- return h ^ (h >> 16);
- }
- static bool lookup_fncache(const char *name, bool *res)
- {
- int h = shash((const unsigned char *)name) % FNHSIZE;
- struct fncache *n;
- hlist_for_each_entry(n, &fncache_hash[h], nd) {
- if (!strcmp(n->name, name)) {
- *res = n->res;
- return true;
- }
- }
- return false;
- }
- static void update_fncache(const char *name, bool res)
- {
- struct fncache *n = malloc(sizeof(struct fncache) + strlen(name) + 1);
- int h = shash((const unsigned char *)name) % FNHSIZE;
- if (!n)
- return;
- strcpy(n->name, name);
- n->res = res;
- hlist_add_head(&n->nd, &fncache_hash[h]);
- }
- /* 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;
- }
|