[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[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: