aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Mares <mj@ucw.cz>2024-02-18 01:40:36 +0100
committerMartin Mares <mj@ucw.cz>2024-02-18 01:40:36 +0100
commitf022f467771c1c4b3270462710923b94b29b3c81 (patch)
tree0d5a1b6145efd40fba5721d316eb08c0fa3f8fd8
parent06f9ecf36e529695feea35038e15233dffe37bb7 (diff)
downloadpciutils-f022f467771c1c4b3270462710923b94b29b3c81.tar.gz
Location of name cache now follows XDG base dir specification
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.
-rw-r--r--lib/init.c27
-rw-r--r--lib/names-cache.c96
-rw-r--r--lib/pci.h1
3 files changed, 102 insertions, 22 deletions
diff --git a/lib/init.c b/lib/init.c
index 3476681..943321b 100644
--- a/lib/init.c
+++ b/lib/init.c
@@ -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");
diff --git a/lib/names-cache.c b/lib/names-cache.c
index 65bfb85..16e9e9a 100644
--- a/lib/names-cache.c
+++ b/lib/names-cache.c
@@ -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
diff --git a/lib/pci.h b/lib/pci.h
index b3386d7..dbdb02f 100644
--- 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 */