summaryrefslogtreecommitdiff
path: root/lib/names-cache.c
diff options
context:
space:
mode:
authorMartin Mares <mj@ucw.cz>2008-02-11 21:47:25 +0100
committerMartin Mares <mj@ucw.cz>2008-02-11 21:47:25 +0100
commit61bc0b585ea4af022e35d57bad70ed815a3c2089 (patch)
tree40e3f4c58a381f19f57a8d57ee111e0c843da489 /lib/names-cache.c
parentc6b83ae3aece7a098858701c4ae3b36adc1c1378 (diff)
downloadpciutils-61bc0b585ea4af022e35d57bad70ed815a3c2089.tar.gz
Writes to the cache file are no longer racy.
Diffstat (limited to 'lib/names-cache.c')
-rw-r--r--lib/names-cache.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/lib/names-cache.c b/lib/names-cache.c
index 09f29b2..73d09a2 100644
--- a/lib/names-cache.c
+++ b/lib/names-cache.c
@@ -105,16 +105,28 @@ pci_id_cache_flush(struct pci_access *a)
FILE *f;
unsigned int h;
struct id_entry *e, *e2;
+ char hostname[256], *tmpname;
+ int this_pid;
a->id_cache_status = 0;
if (orig_status < 2)
return;
if (!a->id_cache_file)
return;
- f = fopen(a->id_cache_file, "wb");
+
+ this_pid = getpid();
+ if (gethostname(hostname, sizeof(hostname)) < 0)
+ hostname[0] = 0;
+ else
+ hostname[sizeof(hostname)-1] = 0;
+ tmpname = pci_malloc(a, strlen(a->id_cache_file) + strlen(hostname) + 64);
+ sprintf(tmpname, "%s.tmp-%s-%d", a->id_cache_file, hostname, this_pid);
+
+ f = fopen(tmpname, "wb");
if (!f)
{
- a->warning("Cannot write %s: %s", a->id_cache_file, strerror(errno));
+ a->warning("Cannot write to %s: %s", a->id_cache_file, strerror(errno));
+ pci_mfree(tmpname);
return;
}
a->debug("Writing cache to %s\n", a->id_cache_file);
@@ -124,6 +136,10 @@ pci_id_cache_flush(struct pci_access *a)
for (e=a->id_hash[h]; e; e=e->next)
if (e->src == SRC_CACHE || e->src == SRC_NET)
{
+ /* Negative entries are not written */
+ if (!e->name[0])
+ continue;
+
/* Verify that every entry is written at most once */
for (e2=a->id_hash[h]; e2 != e; e2=e2->next)
if ((e2->src == SRC_CACHE || e2->src == SRC_NET) &&
@@ -142,6 +158,13 @@ pci_id_cache_flush(struct pci_access *a)
if (ferror(f))
a->warning("Error writing %s", a->id_cache_file);
fclose(f);
+
+ if (rename(tmpname, a->id_cache_file) < 0)
+ {
+ a->warning("Cannot rename %s to %s: %s", tmpname, a->id_cache_status, strerror(errno));
+ unlink(tmpname);
+ }
+ pci_mfree(tmpname);
}
#else