From 54098217b07bb49f724f57aa29f5da36e85ee0af Mon Sep 17 00:00:00 2001 From: Shlok Kyal Date: Wed, 14 Feb 2024 16:27:15 +0530 Subject: [PATCH v20 10/12] Add version check for executables and standby server Add version check for executables and standby server --- doc/src/sgml/ref/pg_createsubscriber.sgml | 6 ++ src/bin/pg_basebackup/pg_createsubscriber.c | 67 +++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/doc/src/sgml/ref/pg_createsubscriber.sgml b/doc/src/sgml/ref/pg_createsubscriber.sgml index 63086a8e98..579e50a0a0 100644 --- a/doc/src/sgml/ref/pg_createsubscriber.sgml +++ b/doc/src/sgml/ref/pg_createsubscriber.sgml @@ -120,6 +120,12 @@ PostgreSQL documentation databases and walsenders. + + + Both the target and source instances must have same major versions with + pg_createsubscriber. + + diff --git a/src/bin/pg_basebackup/pg_createsubscriber.c b/src/bin/pg_basebackup/pg_createsubscriber.c index 0a70f00252..db088024d3 100644 --- a/src/bin/pg_basebackup/pg_createsubscriber.c +++ b/src/bin/pg_basebackup/pg_createsubscriber.c @@ -23,6 +23,7 @@ #include "common/file_perm.h" #include "common/logging.h" #include "common/restricted_token.h" +#include "common/string.h" #include "fe_utils/recovery_gen.h" #include "fe_utils/simple_list.h" #include "getopt_long.h" @@ -63,6 +64,7 @@ static char *get_pub_base_conninfo(char *conninfo, char **dbname); static char *construct_sub_conninfo(char *username, unsigned short subport, char *socketdir); static char *get_bin_directory(const char *path); +static void check_exec(const char *dir, const char *program); static bool check_data_directory(const char *datadir); static char *concat_conninfo_dbname(const char *conninfo, const char *dbname); static LogicalRepInfo *store_pub_sub_info(SimpleStringList dbnames, @@ -277,6 +279,11 @@ get_bin_directory(const char *path) pg_log_debug("pg_ctl path is: %s/%s", dirname, "pg_ctl"); pg_log_debug("pg_resetwal path is: %s/%s", dirname, "pg_resetwal"); + /* Check version of binaries */ + check_exec(dirname, "postgres"); + check_exec(dirname, "pg_ctl"); + check_exec(dirname, "pg_resetwal"); + return dirname; } @@ -290,6 +297,8 @@ check_data_directory(const char *datadir) { struct stat statbuf; char versionfile[MAXPGPATH]; + FILE *ver_fd; + char rawline[64]; pg_log_info("checking if directory \"%s\" is a cluster data directory", datadir); @@ -313,6 +322,31 @@ check_data_directory(const char *datadir) return false; } + /* Check standby server version */ + if ((ver_fd = fopen(versionfile, "r")) == NULL) + pg_fatal("could not open file \"%s\" for reading: %m", versionfile); + + /* Version number has to be the first line read */ + if (!fgets(rawline, sizeof(rawline), ver_fd)) + { + if (!ferror(ver_fd)) + pg_fatal("unexpected empty file \"%s\"", versionfile); + else + pg_fatal("could not read file \"%s\": %m", versionfile); + } + + /* Strip trailing newline and carriage return */ + (void) pg_strip_crlf(rawline); + + if (strcmp(rawline, PG_MAJORVERSION) != 0) + { + pg_log_error("standby server is of wrong version"); + pg_log_error_detail("File \"%s\" contains \"%s\", which is not compatible with this program's version \"%s\".", + versionfile, rawline, PG_MAJORVERSION); + exit(1); + } + + fclose(ver_fd); return true; } @@ -1581,6 +1615,39 @@ construct_sub_conninfo(char *username, unsigned short subport, char *sockdir) return ret; } +/* + * Make sure the given program has the same version with pg_createsubscriber. + */ +static void +check_exec(const char *dir, const char *program) +{ + char path[MAXPGPATH]; + char *line; + char cmd[MAXPGPATH]; + char versionstr[128]; + + snprintf(path, sizeof(path), "%s/%s", dir, program); + + if (validate_exec(path) != 0) + pg_fatal("check for \"%s\" failed: %m", path); + + snprintf(cmd, sizeof(cmd), "\"%s\" -V", path); + + if ((line = pipe_read_line(cmd)) == NULL) + pg_fatal("check for \"%s\" failed: cannot execute", path); + + pg_strip_crlf(line); + + snprintf(versionstr, sizeof(versionstr), "%s (PostgreSQL) " PG_VERSION, + program); + + if (strcmp(line, versionstr) != 0) + pg_fatal("check for \"%s\" failed: incorrect version: found \"%s\", expected \"%s\"", + path, line, versionstr); + + pg_free(line); +} + int main(int argc, char **argv) { -- 2.43.0