1 /*-------------------------------------------------------------------------
2 *
3 * controldata_utils.c
4 * Common code for control data file output.
5 *
6 *
7 * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
9 *
10 *
11 * IDENTIFICATION
12 * src/common/controldata_utils.c
13 *
14 *-------------------------------------------------------------------------
15 */
16
17 #ifndef FRONTEND
18 #include "postgres.h"
19 #else
20 #include "postgres_fe.h"
21 #endif
22
23 #include <unistd.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26
27 #include "catalog/pg_control.h"
28 #include "common/controldata_utils.h"
29 #include "port/pg_crc32c.h"
30
31 /*
32 * get_controlfile(char *DataDir, const char *progname)
33 *
34 * Get controlfile values. The caller is responsible
35 * for pfreeing the result.
36 */
37 ControlFileData *
get_controlfile(char * DataDir,const char * progname)38 get_controlfile(char *DataDir, const char *progname)
39 {
40 ControlFileData *ControlFile;
41 int fd;
42 char ControlFilePath[MAXPGPATH];
43 pg_crc32c crc;
44 int r;
45
46 ControlFile = palloc(sizeof(ControlFileData));
47 snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
48
49 if ((fd = open(ControlFilePath, O_RDONLY | PG_BINARY, 0)) == -1)
50 #ifndef FRONTEND
51 ereport(ERROR,
52 (errcode_for_file_access(),
53 errmsg("could not open file \"%s\" for reading: %m",
54 ControlFilePath)));
55 #else
56 {
57 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
58 progname, ControlFilePath, strerror(errno));
59 exit(EXIT_FAILURE);
60 }
61 #endif
62
63 r = read(fd, ControlFile, sizeof(ControlFileData));
64 if (r != sizeof(ControlFileData))
65 {
66 if (r < 0)
67 #ifndef FRONTEND
68 ereport(ERROR,
69 (errcode_for_file_access(),
70 errmsg("could not read file \"%s\": %m", ControlFilePath)));
71 #else
72 {
73 fprintf(stderr, _("%s: could not read file \"%s\": %s\n"),
74 progname, ControlFilePath, strerror(errno));
75 exit(EXIT_FAILURE);
76 }
77 #endif
78 else
79 #ifndef FRONTEND
80 ereport(ERROR,
81 (errmsg("could not read file \"%s\": read %d of %d",
82 ControlFilePath, r, (int) sizeof(ControlFileData))));
83 #else
84 {
85 fprintf(stderr, _("%s: could not read file \"%s\": read %d of %d\n"),
86 progname, ControlFilePath, r, (int) sizeof(ControlFileData));
87 exit(EXIT_FAILURE);
88 }
89 #endif
90 }
91
92 close(fd);
93
94 /* Check the CRC. */
95 INIT_CRC32C(crc);
96 COMP_CRC32C(crc,
97 (char *) ControlFile,
98 offsetof(ControlFileData, crc));
99 FIN_CRC32C(crc);
100
101 if (!EQ_CRC32C(crc, ControlFile->crc))
102 #ifndef FRONTEND
103 elog(ERROR, _("calculated CRC checksum does not match value stored in file"));
104 #else
105 printf(_("WARNING: Calculated CRC checksum does not match value stored in file.\n"
106 "Either the file is corrupt, or it has a different layout than this program\n"
107 "is expecting. The results below are untrustworthy.\n\n"));
108 #endif
109
110 /* Make sure the control file is valid byte order. */
111 if (ControlFile->pg_control_version % 65536 == 0 &&
112 ControlFile->pg_control_version / 65536 != 0)
113 #ifndef FRONTEND
114 elog(ERROR, _("byte ordering mismatch"));
115 #else
116 printf(_("WARNING: possible byte ordering mismatch\n"
117 "The byte ordering used to store the pg_control file might not match the one\n"
118 "used by this program. In that case the results below would be incorrect, and\n"
119 "the PostgreSQL installation would be incompatible with this data directory.\n"));
120 #endif
121
122 return ControlFile;
123 }
124