Skip to content

Commit 5a1e948

Browse files
committed
add new option to pg_controldata '-c' which allows to update catversion in pg_control to the verision of the current binary
1 parent e139d38 commit 5a1e948

File tree

1 file changed

+83
-1
lines changed

1 file changed

+83
-1
lines changed

src/bin/pg_controldata/pg_controldata.c

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@
2525
#include "catalog/pg_control.h"
2626
#include "common/controldata_utils.h"
2727
#include "pg_getopt.h"
28+
#include "catalog/catversion.h"
2829

30+
static void
31+
WriteControlFile(ControlFileData ControlFile, const char *progname, const char *DataDir);
2932

3033
static void
3134
usage(const char *progname)
@@ -35,6 +38,7 @@ usage(const char *progname)
3538
printf(_(" %s [OPTION] [DATADIR]\n"), progname);
3639
printf(_("\nOptions:\n"));
3740
printf(_(" [-D] DATADIR data directory\n"));
41+
printf(_(" [-c] update catversion in pg_control to the verision of the current binary\n"));
3842
printf(_(" -V, --version output version information, then exit\n"));
3943
printf(_(" -?, --help show this help, then exit\n"));
4044
printf(_("\nIf no data directory (DATADIR) is specified, "
@@ -96,6 +100,7 @@ main(int argc, char *argv[])
96100
XLogSegNo segno;
97101
char xlogfilename[MAXFNAMELEN];
98102
int c;
103+
bool reset_catversion = false;
99104

100105
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_controldata"));
101106

@@ -115,13 +120,16 @@ main(int argc, char *argv[])
115120
}
116121
}
117122

118-
while ((c = getopt(argc, argv, "D:")) != -1)
123+
while ((c = getopt(argc, argv, "D:c")) != -1)
119124
{
120125
switch (c)
121126
{
122127
case 'D':
123128
DataDir = optarg;
124129
break;
130+
case 'c':
131+
reset_catversion = true;
132+
break;
125133

126134
default:
127135
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
@@ -157,6 +165,14 @@ main(int argc, char *argv[])
157165
/* get a copy of the control file */
158166
ControlFile = get_controlfile(DataDir, progname);
159167

168+
if (reset_catversion)
169+
{
170+
ControlFile->catalog_version_no = CATALOG_VERSION_NO;
171+
WriteControlFile(*ControlFile, progname, DataDir);
172+
printf(_("Catalog version updated\n"));
173+
return 0;
174+
}
175+
160176
/*
161177
* This slightly-chintzy coding will work as long as the control file
162178
* timestamps are within the range of time_t; that should be the case in
@@ -298,3 +314,69 @@ main(int argc, char *argv[])
298314
ControlFile->data_checksum_version);
299315
return 0;
300316
}
317+
318+
static void
319+
WriteControlFile(ControlFileData ControlFile, const char *progname, const char *DataDir)
320+
{
321+
int fd;
322+
char buffer[PG_CONTROL_SIZE]; /* need not be aligned */
323+
char ControlFilePath[MAXPGPATH];
324+
325+
snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
326+
327+
/* Contents are protected with a CRC */
328+
INIT_CRC32C(ControlFile.crc);
329+
COMP_CRC32C(ControlFile.crc,
330+
(char *) &ControlFile,
331+
offsetof(ControlFileData, crc));
332+
FIN_CRC32C(ControlFile.crc);
333+
334+
/*
335+
* We write out PG_CONTROL_SIZE bytes into pg_control, zero-padding the
336+
* excess over sizeof(ControlFileData). This reduces the odds of
337+
* premature-EOF errors when reading pg_control. We'll still fail when we
338+
* check the contents of the file, but hopefully with a more specific
339+
* error than "couldn't read pg_control".
340+
*/
341+
if (sizeof(ControlFileData) > PG_CONTROL_SIZE)
342+
{
343+
fprintf(stderr,
344+
_("%s: internal error -- sizeof(ControlFileData) is too large ... fix PG_CONTROL_SIZE\n"),
345+
progname);
346+
exit(1);
347+
}
348+
349+
memset(buffer, 0, PG_CONTROL_SIZE);
350+
memcpy(buffer, &ControlFile, sizeof(ControlFileData));
351+
352+
unlink(ControlFilePath);
353+
354+
fd = open(ControlFilePath,
355+
O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
356+
S_IRUSR | S_IWUSR);
357+
if (fd < 0)
358+
{
359+
fprintf(stderr, _("%s: could not create pg_control file: %s\n"),
360+
progname, strerror(errno));
361+
exit(1);
362+
}
363+
364+
errno = 0;
365+
if (write(fd, buffer, PG_CONTROL_SIZE) != PG_CONTROL_SIZE)
366+
{
367+
/* if write didn't set errno, assume problem is no disk space */
368+
if (errno == 0)
369+
errno = ENOSPC;
370+
fprintf(stderr, _("%s: could not write pg_control file: %s\n"),
371+
progname, strerror(errno));
372+
exit(1);
373+
}
374+
375+
if (fsync(fd) != 0)
376+
{
377+
fprintf(stderr, _("%s: fsync error: %s\n"), progname, strerror(errno));
378+
exit(1);
379+
}
380+
381+
close(fd);
382+
}

0 commit comments

Comments
 (0)