Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* Manage a cache of file names' existence */
0003 #include <stdlib.h>
0004 #include <unistd.h>
0005 #include <string.h>
0006 #include <linux/list.h>
0007 #include "fncache.h"
0008 
0009 struct fncache {
0010     struct hlist_node nd;
0011     bool res;
0012     char name[];
0013 };
0014 
0015 #define FNHSIZE 61
0016 
0017 static struct hlist_head fncache_hash[FNHSIZE];
0018 
0019 unsigned shash(const unsigned char *s)
0020 {
0021     unsigned h = 0;
0022     while (*s)
0023         h = 65599 * h + *s++;
0024     return h ^ (h >> 16);
0025 }
0026 
0027 static bool lookup_fncache(const char *name, bool *res)
0028 {
0029     int h = shash((const unsigned char *)name) % FNHSIZE;
0030     struct fncache *n;
0031 
0032     hlist_for_each_entry(n, &fncache_hash[h], nd) {
0033         if (!strcmp(n->name, name)) {
0034             *res = n->res;
0035             return true;
0036         }
0037     }
0038     return false;
0039 }
0040 
0041 static void update_fncache(const char *name, bool res)
0042 {
0043     struct fncache *n = malloc(sizeof(struct fncache) + strlen(name) + 1);
0044     int h = shash((const unsigned char *)name) % FNHSIZE;
0045 
0046     if (!n)
0047         return;
0048     strcpy(n->name, name);
0049     n->res = res;
0050     hlist_add_head(&n->nd, &fncache_hash[h]);
0051 }
0052 
0053 /* No LRU, only use when bounded in some other way. */
0054 bool file_available(const char *name)
0055 {
0056     bool res;
0057 
0058     if (lookup_fncache(name, &res))
0059         return res;
0060     res = access(name, R_OK) == 0;
0061     update_fncache(name, res);
0062     return res;
0063 }