Skip to content

Commit d9c366f

Browse files
committed
Code review for pg_verify_checksums.c.
Use postgres_fe.h, since this is frontend code. Pretend that we've heard of project style guidelines for, eg, #include order. Use BlockNumber not int arithmetic for block numbers, to avoid misbehavior with relations exceeding 2^31 blocks. Avoid an unnecessary strict-aliasing warning (per report from Michael Banck). Const-ify assorted stuff. Avoid scribbling on the output of readdir() -- perhaps that's safe in practice, but POSIX forbids it, and this code has so far earned exactly zero credibility portability-wise. Editorialize on an ambiguously-worded message. I did not touch the problem of the "buf" local variable being possibly insufficiently aligned; that's not specific to this code, and seems like it should be fixed as part of a different, larger patch. Discussion: https://postgr.es/m/1535618100.1286.3.camel@credativ.de
1 parent f919c16 commit d9c366f

File tree

1 file changed

+23
-24
lines changed

1 file changed

+23
-24
lines changed

src/bin/pg_verify_checksums/pg_verify_checksums.c

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,20 @@
77
*
88
* src/bin/pg_verify_checksums/pg_verify_checksums.c
99
*/
10+
#include "postgres_fe.h"
1011

11-
#define FRONTEND 1
12+
#include <dirent.h>
13+
#include <sys/stat.h>
14+
#include <unistd.h>
1215

13-
#include "postgres.h"
1416
#include "catalog/pg_control.h"
1517
#include "common/controldata_utils.h"
1618
#include "getopt_long.h"
19+
#include "pg_getopt.h"
1720
#include "storage/bufpage.h"
1821
#include "storage/checksum.h"
1922
#include "storage/checksum_impl.h"
2023

21-
#include <sys/stat.h>
22-
#include <dirent.h>
23-
#include <unistd.h>
24-
25-
#include "pg_getopt.h"
26-
2724

2825
static int64 files = 0;
2926
static int64 blocks = 0;
@@ -36,7 +33,7 @@ static bool verbose = false;
3633
static const char *progname;
3734

3835
static void
39-
usage()
36+
usage(void)
4037
{
4138
printf(_("%s verifies data checksums in a PostgreSQL database cluster.\n\n"), progname);
4239
printf(_("Usage:\n"));
@@ -52,7 +49,7 @@ usage()
5249
printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
5350
}
5451

55-
static const char *skip[] = {
52+
static const char *const skip[] = {
5653
"pg_control",
5754
"pg_filenode.map",
5855
"pg_internal.init",
@@ -61,9 +58,9 @@ static const char *skip[] = {
6158
};
6259

6360
static bool
64-
skipfile(char *fn)
61+
skipfile(const char *fn)
6562
{
66-
const char **f;
63+
const char *const *f;
6764

6865
if (strcmp(fn, ".") == 0 ||
6966
strcmp(fn, "..") == 0)
@@ -76,12 +73,12 @@ skipfile(char *fn)
7673
}
7774

7875
static void
79-
scan_file(char *fn, int segmentno)
76+
scan_file(const char *fn, BlockNumber segmentno)
8077
{
8178
char buf[BLCKSZ];
8279
PageHeader header = (PageHeader) buf;
8380
int f;
84-
int blockno;
81+
BlockNumber blockno;
8582

8683
f = open(fn, O_RDONLY | PG_BINARY);
8784
if (f < 0)
@@ -102,21 +99,21 @@ scan_file(char *fn, int segmentno)
10299
break;
103100
if (r != BLCKSZ)
104101
{
105-
fprintf(stderr, _("%s: short read of block %d in file \"%s\", got only %d bytes\n"),
102+
fprintf(stderr, _("%s: short read of block %u in file \"%s\", got only %d bytes\n"),
106103
progname, blockno, fn, r);
107104
exit(1);
108105
}
109106
blocks++;
110107

111108
/* New pages have no checksum yet */
112-
if (PageIsNew(buf))
109+
if (PageIsNew(header))
113110
continue;
114111

115112
csum = pg_checksum_page(buf, blockno + segmentno * RELSEG_SIZE);
116113
if (csum != header->pd_checksum)
117114
{
118115
if (ControlFile->data_checksum_version == PG_DATA_CHECKSUM_VERSION)
119-
fprintf(stderr, _("%s: checksum verification failed in file \"%s\", block %d: calculated checksum %X but expected %X\n"),
116+
fprintf(stderr, _("%s: checksum verification failed in file \"%s\", block %u: calculated checksum %X but block contains %X\n"),
120117
progname, fn, blockno, csum, header->pd_checksum);
121118
badblocks++;
122119
}
@@ -130,7 +127,7 @@ scan_file(char *fn, int segmentno)
130127
}
131128

132129
static void
133-
scan_directory(char *basedir, char *subdir)
130+
scan_directory(const char *basedir, const char *subdir)
134131
{
135132
char path[MAXPGPATH];
136133
DIR *dir;
@@ -146,7 +143,7 @@ scan_directory(char *basedir, char *subdir)
146143
}
147144
while ((de = readdir(dir)) != NULL)
148145
{
149-
char fn[MAXPGPATH + 1];
146+
char fn[MAXPGPATH];
150147
struct stat st;
151148

152149
if (skipfile(de->d_name))
@@ -161,17 +158,19 @@ scan_directory(char *basedir, char *subdir)
161158
}
162159
if (S_ISREG(st.st_mode))
163160
{
161+
char fnonly[MAXPGPATH];
164162
char *forkpath,
165163
*segmentpath;
166-
int segmentno = 0;
164+
BlockNumber segmentno = 0;
167165

168166
/*
169167
* Cut off at the segment boundary (".") to get the segment number
170168
* in order to mix it into the checksum. Then also cut off at the
171169
* fork boundary, to get the relfilenode the file belongs to for
172170
* filtering.
173171
*/
174-
segmentpath = strchr(de->d_name, '.');
172+
strlcpy(fnonly, de->d_name, sizeof(fnonly));
173+
segmentpath = strchr(fnonly, '.');
175174
if (segmentpath != NULL)
176175
{
177176
*segmentpath++ = '\0';
@@ -184,11 +183,11 @@ scan_directory(char *basedir, char *subdir)
184183
}
185184
}
186185

187-
forkpath = strchr(de->d_name, '_');
186+
forkpath = strchr(fnonly, '_');
188187
if (forkpath != NULL)
189188
*forkpath++ = '\0';
190189

191-
if (only_relfilenode && strcmp(only_relfilenode, de->d_name) != 0)
190+
if (only_relfilenode && strcmp(only_relfilenode, fnonly) != 0)
192191
/* Relfilenode not to be included */
193192
continue;
194193

@@ -247,7 +246,7 @@ main(int argc, char *argv[])
247246
DataDir = optarg;
248247
break;
249248
case 'r':
250-
if (atoi(optarg) <= 0)
249+
if (atoi(optarg) == 0)
251250
{
252251
fprintf(stderr, _("%s: invalid relfilenode specification, must be numeric: %s\n"), progname, optarg);
253252
exit(1);

0 commit comments

Comments
 (0)