[PATCH] Factor out common code for reloading database files
---
lib/dpkg/Makefile.am | 1 +
lib/dpkg/db-fsys-common.c | 84 +++++++++++++++++++++++++++++++++++++
lib/dpkg/db-fsys-divert.c | 43 ++++---------------
lib/dpkg/db-fsys-override.c | 50 +++++-----------------
lib/dpkg/dpkg-db.h | 13 ++++++
5 files changed, 117 insertions(+), 74 deletions(-)
create mode 100644 lib/dpkg/db-fsys-common.c
diff --git a/lib/dpkg/Makefile.am b/lib/dpkg/Makefile.am
index 3403338ce..45c3e01ff 100644
--- a/lib/dpkg/Makefile.am
+++ b/lib/dpkg/Makefile.am
@@ -79,6 +79,7 @@ libdpkg_la_SOURCES = \
db-ctrl-access.c \
db-ctrl-format.c \
db-ctrl-upgrade.c \
+ db-fsys-common.c \
db-fsys-digest.c \
db-fsys-divert.c \
db-fsys-files.c \
diff --git a/lib/dpkg/db-fsys-common.c b/lib/dpkg/db-fsys-common.c
new file mode 100644
index 000000000..fc52e9f8b
--- /dev/null
+++ b/lib/dpkg/db-fsys-common.c
@@ -0,0 +1,84 @@
+/*
+ * libdpkg - Debian packaging suite library routines
+ * db-fsys-common.c - Common handling for admindb files
+ *
+ * Copyright © 2008-2012 Guillem Jover <guillem@debian.org>
+ * Copyright © 2022 Simon Richter <sjr@debian.org>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <compat.h>
+
+#include "dpkg-db.h"
+#include "dpkg.h"
+#include "i18n.h"
+#include "debug.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <assert.h>
+
+FILE *dpkg_db_reopen(
+ struct dbinfo *info,
+ char const *filename,
+ bool *unchanged)
+{
+ struct stat sb_next;
+ FILE *file_next;
+
+ assert(info);
+
+ onerr_abort++;
+
+ file_next = fopen(filename, "r");
+ if (!file_next) {
+ if (errno != ENOENT)
+ ohshite(_("failed to open %s"), filename);
+ } else {
+ setcloexec(fileno(file_next), filename);
+
+ if (fstat(fileno(file_next), &sb_next))
+ ohshite(_("failed to fstat %s"), filename);
+
+ /*
+ * We need to keep the database file open so that the
+ * filesystem cannot reuse the inode number (f.ex. during
+ * multiple dpkg-divert invocations in a maintainer script),
+ * otherwise the following check might turn true, and we
+ * would skip reloading a modified database.
+ */
+ if (info->file &&
+ info->sb.st_dev == sb_next.st_dev &&
+ info->sb.st_ino == sb_next.st_ino) {
+ fclose(file_next);
+ onerr_abort--;
+ debug(dbg_general, "%s: %s is unchanged, skipping",
+ __func__, filename);
+ *unchanged = true;
+ return NULL;
+ }
+ info->sb = sb_next;
+ }
+ if (info->file)
+ fclose(info->file);
+ info->file = file_next;
+
+ onerr_abort--;
+ *unchanged = false;
+ return file_next;
+}
diff --git a/lib/dpkg/db-fsys-divert.c b/lib/dpkg/db-fsys-divert.c
index bf0b7ff5a..e3bdcadf4 100644
--- a/lib/dpkg/db-fsys-divert.c
+++ b/lib/dpkg/db-fsys-divert.c
@@ -23,7 +23,6 @@
#include <compat.h>
#include <sys/types.h>
-#include <sys/stat.h>
#include <errno.h>
#include <string.h>
@@ -45,54 +44,28 @@ static char *diversionsname;
void
ensure_diversions(void)
{
- static struct stat sb_prev;
- struct stat sb_next;
+ static struct dbinfo info;
+ bool unchanged;
char linebuf[MAXDIVERTFILENAME];
- static FILE *file_prev;
FILE *file;
struct fsys_diversion *ov, *oicontest, *oialtname;
if (diversionsname == NULL)
diversionsname = dpkg_db_get_path(DIVERSIONSFILE);
- onerr_abort++;
+ file = dpkg_db_reopen(&info, diversionsname, &unchanged);
- file = fopen(diversionsname, "r");
- if (!file) {
- if (errno != ENOENT)
- ohshite(_("failed to open diversions file"));
- } else {
- setcloexec(fileno(file), diversionsname);
-
- if (fstat(fileno(file), &sb_next))
- ohshite(_("failed to fstat diversions file"));
-
- /*
- * We need to keep the database file open so that the
- * filesystem cannot reuse the inode number (f.ex. during
- * multiple dpkg-divert invocations in a maintainer script),
- * otherwise the following check might turn true, and we
- * would skip reloading a modified database.
- */
- if (file_prev &&
- sb_prev.st_dev == sb_next.st_dev &&
- sb_prev.st_ino == sb_next.st_ino) {
- fclose(file);
- onerr_abort--;
- debug(dbg_general, "%s: same, skipping", __func__);
- return;
- }
- sb_prev = sb_next;
- }
- if (file_prev)
- fclose(file_prev);
- file_prev = file;
+ if (unchanged)
+ return;
+
+ onerr_abort++;
for (ov = diversions; ov; ov = ov->next) {
ov->useinstead->divert->camefrom->divert = NULL;
ov->useinstead->divert = NULL;
}
diversions = NULL;
+
if (!file) {
onerr_abort--;
debug(dbg_general, "%s: none, resetting", __func__);
diff --git a/lib/dpkg/db-fsys-override.c b/lib/dpkg/db-fsys-override.c
index e079c5ffb..10f1a27c9 100644
--- a/lib/dpkg/db-fsys-override.c
+++ b/lib/dpkg/db-fsys-override.c
@@ -24,7 +24,6 @@
#include <compat.h>
#include <sys/types.h>
-#include <sys/stat.h>
#include <errno.h>
#include <string.h>
@@ -111,9 +110,8 @@ statdb_parse_mode(const char *str)
void
ensure_statoverrides(enum statdb_parse_flags flags)
{
- static struct stat sb_prev;
- struct stat sb_next;
- static FILE *file_prev;
+ static struct dbinfo info;
+ bool unchanged;
FILE *file;
char *loaded_list, *loaded_list_end, *thisline, *nextline, *ptr;
struct file_stat *fso;
@@ -123,38 +121,12 @@ ensure_statoverrides(enum statdb_parse_flags flags)
if (statoverridename == NULL)
statoverridename = dpkg_db_get_path(STATOVERRIDEFILE);
- onerr_abort++;
+ file = dpkg_db_reopen(&info, statoverridename, &unchanged);
- file = fopen(statoverridename, "r");
- if (!file) {
- if (errno != ENOENT)
- ohshite(_("failed to open statoverride file"));
- } else {
- setcloexec(fileno(file), statoverridename);
-
- if (fstat(fileno(file), &sb_next))
- ohshite(_("failed to fstat statoverride file"));
-
- /*
- * We need to keep the database file open so that the
- * filesystem cannot reuse the inode number (f.ex. during
- * multiple dpkg-statoverride invocations in a maintainer
- * script), otherwise the following check might turn true,
- * and we would skip reloading a modified database.
- */
- if (file_prev &&
- sb_prev.st_dev == sb_next.st_dev &&
- sb_prev.st_ino == sb_next.st_ino) {
- fclose(file);
- onerr_abort--;
- debug(dbg_general, "%s: same, skipping", __func__);
- return;
- }
- sb_prev = sb_next;
- }
- if (file_prev)
- fclose(file_prev);
- file_prev = file;
+ if (unchanged)
+ return;
+
+ onerr_abort++;
/* Reset statoverride information. */
iter = fsys_hash_iter_new();
@@ -171,15 +143,15 @@ ensure_statoverrides(enum statdb_parse_flags flags)
/* If the statoverride list is empty we don't need to bother
* reading it. */
- if (!sb_next.st_size) {
+ if (!info.sb.st_size) {
onerr_abort--;
return;
}
- loaded_list = m_malloc(sb_next.st_size);
- loaded_list_end = loaded_list + sb_next.st_size;
+ loaded_list = m_malloc(info.sb.st_size);
+ loaded_list_end = loaded_list + info.sb.st_size;
- if (fd_read(fileno(file), loaded_list, sb_next.st_size) < 0)
+ if (fd_read(fileno(file), loaded_list, info.sb.st_size) < 0)
ohshite(_("reading statoverride file '%.250s'"), statoverridename);
thisline = loaded_list;
diff --git a/lib/dpkg/dpkg-db.h b/lib/dpkg/dpkg-db.h
index 61f220506..4d602cb00 100644
--- a/lib/dpkg/dpkg-db.h
+++ b/lib/dpkg/dpkg-db.h
@@ -24,6 +24,7 @@
#define LIBDPKG_DPKG_DB_H
#include <sys/types.h>
+#include <sys/stat.h>
#include <stdbool.h>
#include <stdio.h>
@@ -259,6 +260,18 @@ const char *dpkg_db_set_dir(const char *dir);
const char *dpkg_db_get_dir(void);
char *dpkg_db_get_path(const char *pathpart);
+/*** from db-fsys-common.c ***/
+
+struct dbinfo {
+ FILE *file;
+ struct stat sb;
+};
+
+FILE *dpkg_db_reopen(
+ struct dbinfo *info,
+ char const *filename,
+ bool *unchanged);
+
#include <dpkg/atomic-file.h>
/*** from dbmodify.c ***/
--
2.39.2
Reply to: