2 * The PCI Library -- ID to Name Cache
4 * Copyright (c) 2008--2009 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL v2+.
8 * SPDX-License-Identifier: GPL-2.0-or-later
20 #include <sys/types.h>
24 static const char cache_version[] = "#PCI-CACHE-1.0";
26 static char *get_cache_name(struct pci_access *a)
30 name = pci_get_param(a, "net.cache_name");
31 if (!name || !name[0])
33 if (strncmp(name, "~/", 2))
37 struct passwd *pw = getpwuid(uid);
41 buf = pci_malloc(a, strlen(pw->pw_dir) + strlen(name+1) + 1);
42 sprintf(buf, "%s%s", pw->pw_dir, name+1);
43 pci_set_param_internal(a, "net.cache_name", buf, 1);
45 return pci_get_param(a, "net.cache_name");
49 pci_id_cache_load(struct pci_access *a, int flags)
56 a->id_cache_status = 1;
57 name = get_cache_name(a);
60 a->debug("Using cache %s\n", name);
61 if (flags & PCI_LOOKUP_REFRESH_CACHE)
63 a->debug("Not loading cache, will refresh everything\n");
64 a->id_cache_status = 2;
68 f = fopen(name, "rb");
71 a->debug("Cache file does not exist\n");
74 /* FIXME: Compare timestamp with the pci.ids file? */
77 while (fgets(line, sizeof(line), f))
79 char *p = strchr(line, '\n');
86 if (strcmp(line, cache_version))
88 a->debug("Unrecognized cache version %s, ignoring\n", line);
95 int cat, id1, id2, id3, id4, cnt;
96 if (sscanf(line, "%d%x%x%x%x%n", &cat, &id1, &id2, &id3, &id4, &cnt) >= 5)
99 while (*p && *p == ' ')
101 pci_id_insert(a, cat, id1, id2, id3, id4, p, SRC_CACHE);
106 a->warning("Malformed cache file %s (line %d), ignoring", name, lino);
111 a->warning("Error while reading %s", name);
117 pci_id_cache_flush(struct pci_access *a)
119 int orig_status = a->id_cache_status;
122 struct id_entry *e, *e2;
123 char hostname[256], *tmpname, *name;
126 a->id_cache_status = 0;
129 name = get_cache_name(a);
134 if (gethostname(hostname, sizeof(hostname)) < 0)
137 hostname[sizeof(hostname)-1] = 0;
138 tmpname = pci_malloc(a, strlen(name) + strlen(hostname) + 64);
139 sprintf(tmpname, "%s.tmp-%s-%d", name, hostname, this_pid);
141 f = fopen(tmpname, "wb");
144 a->warning("Cannot write to %s: %s", name, strerror(errno));
148 a->debug("Writing cache to %s\n", name);
149 fprintf(f, "%s\n", cache_version);
151 for (h=0; h<HASH_SIZE; h++)
152 for (e=a->id_hash[h]; e; e=e->next)
153 if (e->src == SRC_CACHE || e->src == SRC_NET)
155 /* Negative entries are not written */
159 /* Verify that every entry is written at most once */
160 for (e2=a->id_hash[h]; e2 != e; e2=e2->next)
161 if ((e2->src == SRC_CACHE || e2->src == SRC_NET) &&
163 e2->id12 == e->id12 && e2->id34 == e->id34)
166 fprintf(f, "%d %x %x %x %x %s\n",
168 pair_first(e->id12), pair_second(e->id12),
169 pair_first(e->id34), pair_second(e->id34),
175 a->warning("Error writing %s", name);
178 if (rename(tmpname, name) < 0)
180 a->warning("Cannot rename %s to %s: %s", tmpname, name, strerror(errno));
188 int pci_id_cache_load(struct pci_access *a UNUSED, int flags UNUSED)
190 a->id_cache_status = 1;
194 void pci_id_cache_flush(struct pci_access *a)
196 a->id_cache_status = 0;
202 pci_id_cache_dirty(struct pci_access *a)
204 if (a->id_cache_status >= 1)
205 a->id_cache_status = 2;