]> mj.ucw.cz Git - pciutils.git/commitdiff
Location of name cache now follows XDG base dir specification
authorMartin Mares <mj@ucw.cz>
Sun, 18 Feb 2024 00:40:36 +0000 (01:40 +0100)
committerMartin Mares <mj@ucw.cz>
Sun, 18 Feb 2024 00:40:36 +0000 (01:40 +0100)
We also create parent directories of net.cache_name automatically.

Tilde expansion is performed internally and it does not change
user-specified net.cache_name any longer.

lib/init.c
lib/names-cache.c
lib/pci.h

index 347668163f7a9f9a0b6d75227022b19f5a4ae3b8..943321b1571aab6dd774297beb602f65053d4bc6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     The PCI Library -- Initialization and related things
  *
- *     Copyright (c) 1997--2018 Martin Mares <mj@ucw.cz>
+ *     Copyright (c) 1997--2024 Martin Mares <mj@ucw.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL v2+.
  *
@@ -406,6 +406,27 @@ pci_init_name_list_path(struct pci_access *a)
 
 #endif
 
+#ifdef PCI_USE_DNS
+
+static void
+pci_init_dns(struct pci_access *a)
+{
+  pci_define_param(a, "net.domain", PCI_ID_DOMAIN, "DNS domain used for resolving of ID's");
+  a->id_lookup_mode = PCI_LOOKUP_CACHE;
+
+  char *cache_dir = getenv("XDG_CACHE_HOME");
+  if (!cache_dir)
+    cache_dir = "~/.cache";
+
+  int name_len = strlen(cache_dir) + 32;
+  char *cache_name = pci_malloc(NULL, name_len);
+  snprintf(cache_name, name_len, "%s/pci-ids", cache_dir);
+  struct pci_param *param = pci_define_param(a, "net.cache_name", cache_name, "Name of the ID cache file");
+  param->value_malloced = 1;
+}
+
+#endif
+
 struct pci_access *
 pci_alloc(void)
 {
@@ -415,9 +436,7 @@ pci_alloc(void)
   memset(a, 0, sizeof(*a));
   pci_init_name_list_path(a);
 #ifdef PCI_USE_DNS
-  pci_define_param(a, "net.domain", PCI_ID_DOMAIN, "DNS domain used for resolving of ID's");
-  pci_define_param(a, "net.cache_name", "~/.pciids-cache", "Name of the ID cache file");
-  a->id_lookup_mode = PCI_LOOKUP_CACHE;
+  pci_init_dns(a);
 #endif
 #ifdef PCI_HAVE_HWDB
   pci_define_param(a, "hwdb.disable", "0", "Do not look up names in UDEV's HWDB if non-zero");
index 65bfb85acbc5bf76e70bd5515b0fa08f9efc1b62..16e9e9af2faf0cfa10c447e458ff7c70cd0a3f74 100644 (file)
@@ -18,6 +18,7 @@
 #include <string.h>
 #include <errno.h>
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <pwd.h>
 #include <unistd.h>
 
@@ -25,24 +26,75 @@ 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");
+  if (!a->id_cache_name)
+    {
+      char *name = pci_get_param(a, "net.cache_name");
+      if (!name || !name[0])
+       return NULL;
+
+      if (strncmp(name, "~/", 2))
+       a->id_cache_name = pci_strdup(a, name);
+      else
+       {
+         uid_t uid = getuid();
+         struct passwd *pw = getpwuid(uid);
+         if (!pw)
+           return name;
+
+         a->id_cache_name = pci_malloc(a, strlen(pw->pw_dir) + strlen(name+1) + 1);
+         sprintf(a->id_cache_name, "%s%s", pw->pw_dir, name+1);
+       }
+    }
+
+  return a->id_cache_name;
+}
+
+static void create_parent_dirs(struct pci_access *a, char *name)
+{
+  // Assumes that we have a private copy of the name we can modify
+
+  char *p = name + strlen(name);
+  while (p > name && *p != '/')
+    p--;
+  if (p == name)
+    return;
+
+  while (p > name)
+    {
+      // We stand at a slash. Check if the current prefix exists.
+      *p = 0;
+      struct stat st;
+      int res = stat(name, &st);
+      *p = '/';
+      if (res >= 0)
+       break;
+
+      // Does not exist yet, move up one directory
+      p--;
+      while (p > name && *p != '/')
+       p--;
+    }
+
+  // We now stand at the end of the longest existing prefix.
+  // Create all directories to the right of it.
+  for (;;)
+    {
+      p++;
+      while (*p && *p != '/')
+       p++;
+      if (!*p)
+       break;
+
+      *p = 0;
+      int res = mkdir(name, 0777);
+      if (res < 0)
+       {
+         a->warning("Cannot create directory %s: %s", name, strerror(errno));
+         *p = '/';
+         break;
+       }
+      *p = '/';
+    }
 }
 
 int
@@ -53,11 +105,15 @@ pci_id_cache_load(struct pci_access *a, int flags)
   FILE *f;
   int lino;
 
+  if (a->id_cache_status > 0)
+    return 0;
   a->id_cache_status = 1;
+
   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");
@@ -130,6 +186,8 @@ pci_id_cache_flush(struct pci_access *a)
   if (!name)
     return;
 
+  create_parent_dirs(a, name);
+
   this_pid = getpid();
   if (gethostname(hostname, sizeof(hostname)) < 0)
     hostname[0] = 0;
@@ -194,6 +252,8 @@ int pci_id_cache_load(struct pci_access *a UNUSED, int flags UNUSED)
 void pci_id_cache_flush(struct pci_access *a)
 {
   a->id_cache_status = 0;
+  pci_mfree(a->id_cache_name);
+  a->id_cache_name = NULL;
 }
 
 #endif
index b3386d75c77f84ff7ec8cb483e231d9a0ec74b0b..dbdb02fcfd2d719a008596d43789a83cb75757cc 100644 (file)
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -83,6 +83,7 @@ struct pci_access {
   struct id_bucket *current_id_bucket;
   int id_load_attempted;
   int id_cache_status;                 /* 0=not read, 1=read, 2=dirty */
+  char *id_cache_name;
   struct udev *id_udev;                        /* names-hwdb.c */
   struct udev_hwdb *id_udev_hwdb;
   int fd;                              /* proc/sys: fd for config space */