[PATCH] Factor out common code for reloading database files

Simon Richter <[email protected]>
Newsgroups gmane.linux.debian.devel.dpkg.general
Message-ID <[email protected]>
---
 lib/dpkg/Makefile.am        |  1 +
 lib/dpkg/db-fsys-common.c   | 87 +++++++++++++++++++++++++++++++++++++
 lib/dpkg/db-fsys-divert.c   | 43 ++++--------------
 lib/dpkg/db-fsys-override.c | 50 +++++----------------
 lib/dpkg/dpkg-db.h          | 13 ++++++
 5 files changed, 120 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 9ef3a37f7..9ab402cf5 100644
--- a/lib/dpkg/Makefile.am
+++ b/lib/dpkg/Makefile.am
@@ -73,6 +73,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..be106aff6
--- /dev/null
+++ b/lib/dpkg/db-fsys-common.c
@@ -0,0 +1,87 @@
+/*
+ * libdpkg - Debian packaging suite library routines
+ * db-fsys-common.c - Common handling for admindb files
+ *
+ * Copyright © 2008-2012 Guillem Jover <[email protected]>
+ * Copyright © 2022 Simon Richter <[email protected]>
+ *
+ * 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 *out_unchanged)
+{
+	struct stat sb_next;
+	FILE *file_next;
+
+	assert(info);
+	assert(filename);
+
+	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);
+			if(out_unchanged)
+				*out_unchanged = true;
+			return NULL;
+		}
+		info->sb = sb_next;
+	}
+	if (info->file)
+		fclose(info->file);
+	info->file = file_next;
+
+	onerr_abort--;
+	if(out_unchanged)
+		*out_unchanged = false;
+	return file_next;
+}
diff --git a/lib/dpkg/db-fsys-divert.c b/lib/dpkg/db-fsys-divert.c
index e0054bb35..2198685ad 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 dbi;
+	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(&dbi, 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 b74f6cbc2..b3163ec78 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 dbi;
+	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(&dbi, 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 (!dbi.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(dbi.sb.st_size);
+	loaded_list_end = loaded_list + dbi.sb.st_size;
 
-	if (fd_read(fileno(file), loaded_list, sb_next.st_size) < 0)
+	if (fd_read(fileno(file), loaded_list, dbi.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 ***/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.