X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lib%2Fnames-cache.c;h=ba5de6d678f71d18fbb2476dced4f237d3d9b28b;hb=4c2b4b1bfa348ea22a22f4ca271bc13096ab3e78;hp=2811fe46eb1391ea554f612fa14c92a2f45e0693;hpb=752d4d9ab7e567ea972a16f33d2a210ae90b7051;p=pciutils.git diff --git a/lib/names-cache.c b/lib/names-cache.c index 2811fe4..ba5de6d 100644 --- a/lib/names-cache.c +++ b/lib/names-cache.c @@ -1,11 +1,16 @@ /* * The PCI Library -- ID to Name Cache * - * Copyright (c) 2008 Martin Mares + * Copyright (c) 2008--2009 Martin Mares * * Can be freely distributed and used under the terms of the GNU GPL. */ +#include "internal.h" +#include "names.h" + +#ifdef PCI_USE_DNS + #include #include #include @@ -14,33 +19,43 @@ #include #include -#include "internal.h" -#include "names.h" - static const char cache_version[] = "#PCI-CACHE-1.0"; +static char *get_cache_name(struct pci_access *a) +{ + char *name, *buf; + + name = pci_get_param(a, "net.cache_name"); + if (!name || !name[0]) + return NULL; + if (strncmp(name, "~/", 2)) + return name; + + uid_t uid = getuid(); + struct passwd *pw = getpwuid(uid); + if (!pw) + return name; + + buf = pci_malloc(a, strlen(pw->pw_dir) + strlen(name+1) + 1); + sprintf(buf, "%s%s", pw->pw_dir, name+1); + pci_set_param_internal(a, "net.cache_name", buf, 1); + pci_mfree(buf); + return pci_get_param(a, "net.cache_name"); +} + int pci_id_cache_load(struct pci_access *a, int flags) { char *name; char line[MAX_LINE]; - const char default_name[] = "/.pciids-cache"; FILE *f; int lino; a->id_cache_status = 1; - if (!a->id_cache_file) - { - /* Construct the default ID cache name */ - uid_t uid = getuid(); - struct passwd *pw = getpwuid(uid); - if (!pw) - return 0; - name = pci_malloc(a, strlen(pw->pw_dir) + sizeof(default_name)); - sprintf(name, "%s%s", pw->pw_dir, default_name); - pci_set_id_cache(a, name, 1); - } - a->debug("Using cache %s\n", a->id_cache_file); + name = get_cache_name(a); + if (!name) + return 0; + a->debug("Using cache %s\n", name); if (flags & PCI_LOOKUP_REFRESH_CACHE) { a->debug("Not loading cache, will refresh everything\n"); @@ -48,7 +63,7 @@ pci_id_cache_load(struct pci_access *a, int flags) return 0; } - f = fopen(a->id_cache_file, "rb"); + f = fopen(name, "rb"); if (!f) { a->debug("Cache file does not exist\n"); @@ -86,23 +101,16 @@ pci_id_cache_load(struct pci_access *a, int flags) } } } - a->warning("Malformed cache file %s (line %d), ignoring", a->id_cache_file, lino); + a->warning("Malformed cache file %s (line %d), ignoring", name, lino); break; } if (ferror(f)) - a->warning("Error while reading %s", a->id_cache_file); + a->warning("Error while reading %s", name); fclose(f); return 1; } -void -pci_id_cache_dirty(struct pci_access *a) -{ - if (a->id_cache_status >= 1) - a->id_cache_status = 2; -} - void pci_id_cache_flush(struct pci_access *a) { @@ -110,25 +118,42 @@ pci_id_cache_flush(struct pci_access *a) FILE *f; unsigned int h; struct id_entry *e, *e2; + char hostname[256], *tmpname, *name; + int this_pid; a->id_cache_status = 0; if (orig_status < 2) return; - if (!a->id_cache_file) + name = get_cache_name(a); + if (!name) 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(name) + strlen(hostname) + 64); + sprintf(tmpname, "%s.tmp-%s-%d", name, 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", name, strerror(errno)); + pci_mfree(tmpname); return; } - a->debug("Writing cache to %s\n", a->id_cache_file); + a->debug("Writing cache to %s\n", name); fprintf(f, "%s\n", cache_version); for (h=0; hid_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) && @@ -145,15 +170,35 @@ pci_id_cache_flush(struct pci_access *a) fflush(f); if (ferror(f)) - a->warning("Error writing %s", a->id_cache_file); + a->warning("Error writing %s", name); fclose(f); + + if (rename(tmpname, name) < 0) + { + a->warning("Cannot rename %s to %s: %s", tmpname, name, strerror(errno)); + unlink(tmpname); + } + pci_mfree(tmpname); +} + +#else + +int pci_id_cache_load(struct pci_access *a UNUSED, int flags UNUSED) +{ + a->id_cache_status = 1; + return 0; +} + +void pci_id_cache_flush(struct pci_access *a) +{ + a->id_cache_status = 0; } +#endif + void -pci_set_id_cache(struct pci_access *a, char *name, int to_be_freed) +pci_id_cache_dirty(struct pci_access *a) { - if (a->free_id_cache_file) - free(a->id_cache_file); - a->id_cache_file = name; - a->free_id_cache_file = to_be_freed; + if (a->id_cache_status >= 1) + a->id_cache_status = 2; }