diff options
Diffstat (limited to 'src/pulsecore/database.c')
-rw-r--r-- | src/pulsecore/database.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/src/pulsecore/database.c b/src/pulsecore/database.c new file mode 100644 index 0000000..8b3b89c --- /dev/null +++ b/src/pulsecore/database.c @@ -0,0 +1,107 @@ +/*** + This file is part of PulseAudio. + + Copyright 2020 Igor V. Kovalenko <igor.v.kovalenko@gmail.com> + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <errno.h> +#include <dirent.h> + +#include <pulse/xmalloc.h> +#include <pulsecore/core-util.h> +#include <pulsecore/log.h> + +#include "database.h" +#include "core-error.h" + +pa_database* pa_database_open(const char *path, const char *fn, bool prependmid, bool for_write) { + + const char *filename_suffix = pa_database_get_filename_suffix(); + + char *machine_id = NULL, *filename_prefix, *full_path; + + DIR *database_dir = NULL; + struct dirent *de; + + pa_database *f; + + pa_assert(filename_suffix && filename_suffix[0]); + + if (prependmid && !(machine_id = pa_machine_id())) { + return NULL; + } + + /* Database file name starts with ${machine_id}-${fn} */ + if (machine_id) + filename_prefix = pa_sprintf_malloc("%s-%s", machine_id, fn); + else + filename_prefix = pa_xstrdup(fn); + + /* 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 existing 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) + && de->d_name[strlen(filename_prefix)] == '.' + && pa_endswith(de->d_name + strlen(filename_prefix) + 1, filename_suffix)) { + + /* candidate filename found, replace filename_prefix with this one */ + + pa_log_debug("Found existing 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 existing 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); + + if (f) + pa_log_info("Successfully opened '%s' database file '%s'.", fn, full_path); + else + pa_log("Failed to open '%s' database file '%s': %s", fn, full_path, pa_cstrerror(errno)); + + pa_xfree(full_path); + pa_xfree(filename_prefix); + + /* deallocate machine_id if it was used to construct file name */ + pa_xfree(machine_id); + + return f; +} |