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