database: use existing database matching same architecture prefix
authorIgor V. Kovalenko <igor.v.kovalenko@gmail.com>
Sun, 29 Nov 2020 12:16:26 +0000 (15:16 +0300)
committerPulseAudio Marge Bot <pulseaudio-maintainers@lists.freedesktop.org>
Thu, 7 Jan 2021 23:27:16 +0000 (23:27 +0000)
State database binary file format may depend on system architecture,
for instance gdbm binary format depends on architecture word size,
making x86 and x64 gdbm files incompatible.

If this is the case, it is handled by adding system architecture name to
database file name using automatically configured CANONICAL_HOST string.
Meson build define CANONICAL_HOST to be system architecture name, while
autotools build extends this with vendor and and operating system components.

Switch autotools build to use host_cpu for CANONICAL_HOST to match Meson
configuration. For backwards compatibility always use existing database file
matching CANONICAL_HOST prefix if it exists.

Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/425>

configure.ac
src/pulsecore/database.c
src/pulsecore/database.h

index bd3a533..2bc4b90 100644 (file)
@@ -57,7 +57,7 @@ AC_SUBST(LIBPULSE_SIMPLE_VERSION_INFO, [1:1:1])
 AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:6:0])
 
 AC_CANONICAL_HOST
-AC_DEFINE_UNQUOTED([CANONICAL_HOST], "$host", [Canonical host string.])
+AC_DEFINE_UNQUOTED([CANONICAL_HOST], "$host_cpu", [Canonical host system architecture string.])
 
 AC_CHECK_PROG([STOW], [stow], [yes], [no])
 
index 11f3d03..43af6fc 100644 (file)
@@ -22,6 +22,7 @@
 #endif
 
 #include <errno.h>
+#include <dirent.h>
 
 #include <pulse/xmalloc.h>
 #include <pulsecore/core-util.h>
@@ -37,6 +38,9 @@ pa_database* pa_database_open(const char *path, const char *fn, bool prependmid,
 
     char *machine_id = NULL, *filename_prefix, *full_path;
 
+    DIR *database_dir = NULL;
+    struct dirent *de;
+
     pa_database *f;
 
     pa_assert(!arch_suffix || arch_suffix[0]);
@@ -53,6 +57,40 @@ pa_database* pa_database_open(const char *path, const char *fn, bool prependmid,
             fn,
             arch_suffix?".":"", arch_suffix?:"");
 
+    /* Search for existing database directory entry name matching architecture suffix and filename suffix. */
+    database_dir = opendir(path);
+
+    if (database_dir) {
+        for (;;) {
+            errno = 0;
+            de = readdir(database_dir);
+            if (!de) {
+                if (errno) {
+                    pa_log_warn("Unable to search for compatible database file, readdir() failed: %s", pa_cstrerror(errno));
+                    /* can continue as if there is no matching database file candidate */
+                }
+
+                break;
+            }
+
+            if (pa_startswith(de->d_name, filename_prefix) && pa_endswith(de->d_name + strlen(filename_prefix), filename_suffix)) {
+                /* candidate filename found, replace filename_prefix with this one if match is not exact */
+
+                if (strlen(de->d_name) != strlen(filename_prefix) + strlen(filename_suffix)) {
+                    pa_log_debug("Found compatible database file '%s/%s', using it", path, de->d_name);
+                    pa_xfree(filename_prefix);
+                    filename_prefix = pa_xstrndup(de->d_name, strlen(de->d_name) - strlen(filename_suffix));
+                }
+
+                break;
+            }
+        }
+
+        closedir(database_dir);
+    } else {
+        pa_log_warn("Unable to search for compatible database file, failed to open directory %s: %s", path, pa_cstrerror(errno));
+    }
+
     full_path = pa_sprintf_malloc("%s" PA_PATH_SEP "%s%s", path, filename_prefix, filename_suffix);
 
     f = pa_database_open_internal(full_path, for_write);
index fe28905..cc16e53 100644 (file)
@@ -43,7 +43,8 @@ const char* pa_database_get_arch_suffix(void);
 /* Database implementation; returns non-empty database filename extension string */
 const char* pa_database_get_filename_suffix(void);
 
-/* This will attempt opening database file matching compiled CANONICAL_HOST identifier.
+/* This will attempt opening database file matching compiled CANONICAL_HOST implementation architecture name prefix,
+ * or new database file will be created and opened with implementation architecture name suffix if required.
  * If prependmid is true, file name is augmented with machine id prefix. */
 pa_database* pa_database_open(const char *path, const char *fn, bool prependmid, bool for_write);