]> mj.ucw.cz Git - pciutils.git/blobdiff - lib/names-cache.c
Sylixos: Bits of Makefile and configure
[pciutils.git] / lib / names-cache.c
index 2811fe46eb1391ea554f612fa14c92a2f45e0693..ba5de6d678f71d18fbb2476dced4f237d3d9b28b 100644 (file)
@@ -1,11 +1,16 @@
 /*
  *     The PCI Library -- ID to Name Cache
  *
- *     Copyright (c) 2008 Martin Mares <mj@ucw.cz>
+ *     Copyright (c) 2008--2009 Martin Mares <mj@ucw.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
 
+#include "internal.h"
+#include "names.h"
+
+#ifdef PCI_USE_DNS
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <pwd.h>
 #include <unistd.h>
 
-#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; h<HASH_SIZE; h++)
     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) &&
@@ -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;
 }