25
25
#include "catalog/pg_control.h"
26
26
#include "common/controldata_utils.h"
27
27
#include "pg_getopt.h"
28
+ #include "catalog/catversion.h"
28
29
30
+ static void
31
+ WriteControlFile (ControlFileData ControlFile , const char * progname , const char * DataDir );
29
32
30
33
static void
31
34
usage (const char * progname )
@@ -35,6 +38,7 @@ usage(const char *progname)
35
38
printf (_ (" %s [OPTION] [DATADIR]\n" ), progname );
36
39
printf (_ ("\nOptions:\n" ));
37
40
printf (_ (" [-D] DATADIR data directory\n" ));
41
+ printf (_ (" [-c] update catversion in pg_control to the verision of the current binary\n" ));
38
42
printf (_ (" -V, --version output version information, then exit\n" ));
39
43
printf (_ (" -?, --help show this help, then exit\n" ));
40
44
printf (_ ("\nIf no data directory (DATADIR) is specified, "
@@ -96,6 +100,7 @@ main(int argc, char *argv[])
96
100
XLogSegNo segno ;
97
101
char xlogfilename [MAXFNAMELEN ];
98
102
int c ;
103
+ bool reset_catversion = false;
99
104
100
105
set_pglocale_pgservice (argv [0 ], PG_TEXTDOMAIN ("pg_controldata" ));
101
106
@@ -115,13 +120,16 @@ main(int argc, char *argv[])
115
120
}
116
121
}
117
122
118
- while ((c = getopt (argc , argv , "D:" )) != -1 )
123
+ while ((c = getopt (argc , argv , "D:c " )) != -1 )
119
124
{
120
125
switch (c )
121
126
{
122
127
case 'D' :
123
128
DataDir = optarg ;
124
129
break ;
130
+ case 'c' :
131
+ reset_catversion = true;
132
+ break ;
125
133
126
134
default :
127
135
fprintf (stderr , _ ("Try \"%s --help\" for more information.\n" ), progname );
@@ -157,6 +165,14 @@ main(int argc, char *argv[])
157
165
/* get a copy of the control file */
158
166
ControlFile = get_controlfile (DataDir , progname );
159
167
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
+
160
176
/*
161
177
* This slightly-chintzy coding will work as long as the control file
162
178
* timestamps are within the range of time_t; that should be the case in
@@ -298,3 +314,69 @@ main(int argc, char *argv[])
298
314
ControlFile -> data_checksum_version );
299
315
return 0 ;
300
316
}
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