From f022f467771c1c4b3270462710923b94b29b3c81 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Sun, 18 Feb 2024 01:40:36 +0100 Subject: 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. --- lib/init.c | 27 +++++++++++++--- lib/names-cache.c | 96 ++++++++++++++++++++++++++++++++++++++++++++----------- lib/pci.h | 1 + 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 + * Copyright (c) 1997--2024 Martin Mares * * 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 #include #include +#include #include #include @@ -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 */ -- cgit 1.2.3-korg