summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/fe_utils/Makefile3
-rw-r--r--src/fe_utils/meson.build1
-rw-r--r--src/fe_utils/version.c86
-rw-r--r--src/include/fe_utils/version.h23
4 files changed, 112 insertions, 1 deletions
diff --git a/src/fe_utils/Makefile b/src/fe_utils/Makefile
index 28196ce0f6a..b9fd566ff87 100644
--- a/src/fe_utils/Makefile
+++ b/src/fe_utils/Makefile
@@ -37,7 +37,8 @@ OBJS = \
query_utils.o \
recovery_gen.o \
simple_list.o \
- string_utils.o
+ string_utils.o \
+ version.o
ifeq ($(PORTNAME), win32)
override CPPFLAGS += -DFD_SETSIZE=1024
diff --git a/src/fe_utils/meson.build b/src/fe_utils/meson.build
index 5a9ddb73463..ddac3c3a658 100644
--- a/src/fe_utils/meson.build
+++ b/src/fe_utils/meson.build
@@ -18,6 +18,7 @@ fe_utils_sources = files(
'recovery_gen.c',
'simple_list.c',
'string_utils.c',
+ 'version.c',
)
psqlscan = custom_target('psqlscan',
diff --git a/src/fe_utils/version.c b/src/fe_utils/version.c
new file mode 100644
index 00000000000..94f09233c01
--- /dev/null
+++ b/src/fe_utils/version.c
@@ -0,0 +1,86 @@
+/*-------------------------------------------------------------------------
+ *
+ * version.c
+ * Routine to retrieve information of PG_VERSION
+ *
+ * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/fe_utils/version.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+
+#include <sys/stat.h>
+
+#include "common/logging.h"
+#include "fe_utils/version.h"
+
+/*
+ * Assumed maximum size of PG_VERSION. This should be more than enough for
+ * any version numbers that need to be handled.
+ */
+#define PG_VERSION_MAX_SIZE 64
+
+/*
+ * get_pg_version
+ *
+ * Retrieve the major version number of the given data folder, from
+ * PG_VERSION. The result returned is a version number, that can be used
+ * for comparisons based on PG_VERSION_NUM. For example, if PG_VERSION
+ * contains "18\n", this function returns 180000.
+ *
+ * This supports both the pre-v10 and the post-v10 version numbering.
+ *
+ * Optionally, "version_str" can be specified to store the contents
+ * retrieved from PG_VERSION. It is allocated by this routine; the
+ * caller is responsible for pg_free()-ing it.
+ */
+uint32
+get_pg_version(const char *datadir, char **version_str)
+{
+ FILE *version_fd;
+ char ver_filename[MAXPGPATH];
+ char buf[PG_VERSION_MAX_SIZE];
+ int v1 = 0,
+ v2 = 0;
+ struct stat st;
+
+ snprintf(ver_filename, sizeof(ver_filename), "%s/PG_VERSION",
+ datadir);
+
+ if ((version_fd = fopen(ver_filename, "r")) == NULL)
+ pg_fatal("could not open version file \"%s\": %m", ver_filename);
+
+ if (fstat(fileno(version_fd), &st) != 0)
+ pg_fatal("could not stat file \"%s\": %m", ver_filename);
+ if (st.st_size > PG_VERSION_MAX_SIZE)
+ pg_fatal("file \"%s\" is too large", ver_filename);
+
+ if (fscanf(version_fd, "%63s", buf) == 0 ||
+ sscanf(buf, "%d.%d", &v1, &v2) < 1)
+ pg_fatal("could not parse version file \"%s\"", ver_filename);
+
+ fclose(version_fd);
+
+ if (version_str)
+ {
+ *version_str = pg_malloc(PG_VERSION_MAX_SIZE);
+ memcpy(*version_str, buf, st.st_size);
+ }
+
+ if (v1 < 10)
+ {
+ /* pre-v10 style, e.g. 9.6.1 */
+ return v1 * 10000 + v2 * 100;
+ }
+ else
+ {
+ /* post-v10 style, e.g. 10.1 */
+ return v1 * 10000;
+ }
+}
diff --git a/src/include/fe_utils/version.h b/src/include/fe_utils/version.h
new file mode 100644
index 00000000000..cea9d8020bc
--- /dev/null
+++ b/src/include/fe_utils/version.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * Routines to retrieve information of PG_VERSION
+ *
+ * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/fe_utils/version.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_VERSION_H
+#define PG_VERSION_H
+
+/*
+ * Retrieve the version major number, useful for major version checks
+ * based on PG_MAJORVERSION_NUM.
+ */
+#define GET_PG_MAJORVERSION_NUM(v) ((v) / 10000)
+
+extern uint32 get_pg_version(const char *datadir, char **version_str);
+
+#endif /* PG_VERSION_H */