]> git.ipfire.org Git - thirdparty/pciutils.git/blame - lib/names-cache.c
Domains: Legacy 16-bit domain numbers are maintained in generic code
[thirdparty/pciutils.git] / lib / names-cache.c
CommitLineData
752d4d9a
MM
1/*
2 * The PCI Library -- ID to Name Cache
3 *
fda7c18d 4 * Copyright (c) 2008--2009 Martin Mares <mj@ucw.cz>
752d4d9a
MM
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
fda7c18d
MM
9#include "internal.h"
10#include "names.h"
11
12#ifdef PCI_USE_DNS
13
752d4d9a
MM
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <errno.h>
18#include <sys/types.h>
19#include <pwd.h>
20#include <unistd.h>
21
752d4d9a
MM
22static const char cache_version[] = "#PCI-CACHE-1.0";
23
98ccf6d6
MM
24static char *get_cache_name(struct pci_access *a)
25{
26 char *name, *buf;
159b4709
MM
27
28 name = pci_get_param(a, "net.cache_name");
29 if (!name || !name[0])
98ccf6d6
MM
30 return NULL;
31 if (strncmp(name, "~/", 2))
32 return name;
33
34 uid_t uid = getuid();
35 struct passwd *pw = getpwuid(uid);
36 if (!pw)
37 return name;
38
39 buf = pci_malloc(a, strlen(pw->pw_dir) + strlen(name+1) + 1);
40 sprintf(buf, "%s%s", pw->pw_dir, name+1);
7220de95 41 pci_set_param_internal(a, "net.cache_name", buf, 1);
cd10d1d1
MM
42 pci_mfree(buf);
43 return pci_get_param(a, "net.cache_name");
98ccf6d6
MM
44}
45
752d4d9a
MM
46int
47pci_id_cache_load(struct pci_access *a, int flags)
48{
49 char *name;
50 char line[MAX_LINE];
752d4d9a
MM
51 FILE *f;
52 int lino;
53
54 a->id_cache_status = 1;
98ccf6d6
MM
55 name = get_cache_name(a);
56 if (!name)
57 return 0;
58 a->debug("Using cache %s\n", name);
752d4d9a
MM
59 if (flags & PCI_LOOKUP_REFRESH_CACHE)
60 {
61 a->debug("Not loading cache, will refresh everything\n");
62 a->id_cache_status = 2;
63 return 0;
64 }
65
98ccf6d6 66 f = fopen(name, "rb");
752d4d9a
MM
67 if (!f)
68 {
69 a->debug("Cache file does not exist\n");
70 return 0;
71 }
72 /* FIXME: Compare timestamp with the pci.ids file? */
73
74 lino = 0;
75 while (fgets(line, sizeof(line), f))
76 {
77 char *p = strchr(line, '\n');
78 lino++;
79 if (p)
80 {
81 *p = 0;
82 if (lino == 1)
83 {
84 if (strcmp(line, cache_version))
85 {
86 a->debug("Unrecognized cache version %s, ignoring\n", line);
87 break;
88 }
89 continue;
90 }
91 else
92 {
93 int cat, id1, id2, id3, id4, cnt;
94 if (sscanf(line, "%d%x%x%x%x%n", &cat, &id1, &id2, &id3, &id4, &cnt) >= 5)
95 {
96 p = line + cnt;
97 while (*p && *p == ' ')
98 p++;
99 pci_id_insert(a, cat, id1, id2, id3, id4, p, SRC_CACHE);
100 continue;
101 }
102 }
103 }
98ccf6d6 104 a->warning("Malformed cache file %s (line %d), ignoring", name, lino);
752d4d9a
MM
105 break;
106 }
107
108 if (ferror(f))
98ccf6d6 109 a->warning("Error while reading %s", name);
752d4d9a
MM
110 fclose(f);
111 return 1;
112}
113
752d4d9a
MM
114void
115pci_id_cache_flush(struct pci_access *a)
116{
117 int orig_status = a->id_cache_status;
118 FILE *f;
119 unsigned int h;
120 struct id_entry *e, *e2;
98ccf6d6 121 char hostname[256], *tmpname, *name;
61bc0b58 122 int this_pid;
752d4d9a
MM
123
124 a->id_cache_status = 0;
125 if (orig_status < 2)
126 return;
98ccf6d6
MM
127 name = get_cache_name(a);
128 if (!name)
752d4d9a 129 return;
61bc0b58
MM
130
131 this_pid = getpid();
132 if (gethostname(hostname, sizeof(hostname)) < 0)
133 hostname[0] = 0;
134 else
135 hostname[sizeof(hostname)-1] = 0;
98ccf6d6
MM
136 tmpname = pci_malloc(a, strlen(name) + strlen(hostname) + 64);
137 sprintf(tmpname, "%s.tmp-%s-%d", name, hostname, this_pid);
61bc0b58
MM
138
139 f = fopen(tmpname, "wb");
752d4d9a
MM
140 if (!f)
141 {
98ccf6d6 142 a->warning("Cannot write to %s: %s", name, strerror(errno));
61bc0b58 143 pci_mfree(tmpname);
752d4d9a
MM
144 return;
145 }
98ccf6d6 146 a->debug("Writing cache to %s\n", name);
752d4d9a
MM
147 fprintf(f, "%s\n", cache_version);
148
149 for (h=0; h<HASH_SIZE; h++)
150 for (e=a->id_hash[h]; e; e=e->next)
151 if (e->src == SRC_CACHE || e->src == SRC_NET)
152 {
61bc0b58
MM
153 /* Negative entries are not written */
154 if (!e->name[0])
155 continue;
156
752d4d9a
MM
157 /* Verify that every entry is written at most once */
158 for (e2=a->id_hash[h]; e2 != e; e2=e2->next)
159 if ((e2->src == SRC_CACHE || e2->src == SRC_NET) &&
160 e2->cat == e->cat &&
161 e2->id12 == e->id12 && e2->id34 == e->id34)
162 break;
163 if (e2 == e)
164 fprintf(f, "%d %x %x %x %x %s\n",
165 e->cat,
166 pair_first(e->id12), pair_second(e->id12),
167 pair_first(e->id34), pair_second(e->id34),
168 e->name);
169 }
170
171 fflush(f);
172 if (ferror(f))
98ccf6d6 173 a->warning("Error writing %s", name);
752d4d9a 174 fclose(f);
61bc0b58 175
98ccf6d6 176 if (rename(tmpname, name) < 0)
61bc0b58 177 {
98ccf6d6 178 a->warning("Cannot rename %s to %s: %s", tmpname, name, strerror(errno));
61bc0b58
MM
179 unlink(tmpname);
180 }
181 pci_mfree(tmpname);
752d4d9a
MM
182}
183
94d1b5e0
MM
184#else
185
186int pci_id_cache_load(struct pci_access *a UNUSED, int flags UNUSED)
187{
188 a->id_cache_status = 1;
189 return 0;
190}
191
192void pci_id_cache_flush(struct pci_access *a)
193{
194 a->id_cache_status = 0;
195}
196
197#endif
198
199void
200pci_id_cache_dirty(struct pci_access *a)
201{
202 if (a->id_cache_status >= 1)
203 a->id_cache_status = 2;
204}