PostgreSQL Source Code  git master
exec.c File Reference
#include "postgres_fe.h"
#include <fcntl.h>
#include "pg_upgrade.h"
Include dependency graph for exec.c:

Go to the source code of this file.

Macros

#define MAXCMDLEN   (2 * MAXPGPATH)
 

Functions

static void check_data_dir (ClusterInfo *cluster)
 
static void check_bin_dir (ClusterInfo *cluster)
 
static void get_bin_version (ClusterInfo *cluster)
 
static void validate_exec (const char *dir, const char *cmdName)
 
bool exec_prog (const char *log_file, const char *opt_log_file, bool report_error, bool exit_on_error, const char *fmt,...)
 
bool pid_lock_file_exists (const char *datadir)
 
void verify_directories (void)
 
static void check_single_dir (const char *pg_data, const char *subdir)
 

Macro Definition Documentation

◆ MAXCMDLEN

#define MAXCMDLEN   (2 * MAXPGPATH)

Referenced by exec_prog().

Function Documentation

◆ check_bin_dir()

static void check_bin_dir ( ClusterInfo cluster)
static

Definition at line 364 of file exec.c.

References ClusterInfo::bin_version, ClusterInfo::bindir, get_bin_version(), GET_MAJOR_VERSION, new_cluster, PG_FATAL, report_status(), S_ISDIR, stat, strerror(), and validate_exec().

Referenced by verify_directories().

365 {
366  struct stat statBuf;
367 
368  /* check bindir */
369  if (stat(cluster->bindir, &statBuf) != 0)
370  report_status(PG_FATAL, "check for \"%s\" failed: %s\n",
371  cluster->bindir, strerror(errno));
372  else if (!S_ISDIR(statBuf.st_mode))
373  report_status(PG_FATAL, "\"%s\" is not a directory\n",
374  cluster->bindir);
375 
376  validate_exec(cluster->bindir, "postgres");
377  validate_exec(cluster->bindir, "pg_ctl");
378 
379  /*
380  * Fetch the binary version after checking for the existence of pg_ctl.
381  * This way we report a useful error if the pg_ctl binary used for version
382  * fetching is missing/broken.
383  */
384  get_bin_version(cluster);
385 
386  /* pg_resetxlog has been renamed to pg_resetwal in version 10 */
387  if (GET_MAJOR_VERSION(cluster->bin_version) < 1000)
388  validate_exec(cluster->bindir, "pg_resetxlog");
389  else
390  validate_exec(cluster->bindir, "pg_resetwal");
391  if (cluster == &new_cluster)
392  {
393  /* these are only needed in the new cluster */
394  validate_exec(cluster->bindir, "psql");
395  validate_exec(cluster->bindir, "pg_dump");
396  validate_exec(cluster->bindir, "pg_dumpall");
397  }
398 }
#define GET_MAJOR_VERSION(v)
Definition: pg_upgrade.h:29
ClusterInfo new_cluster
Definition: pg_upgrade.c:56
#define stat(a, b)
Definition: win32_port.h:266
char * bindir
Definition: pg_upgrade.h:269
uint32 bin_version
Definition: pg_upgrade.h:276
static void validate_exec(const char *dir, const char *cmdName)
Definition: exec.c:407
#define S_ISDIR(m)
Definition: win32_port.h:307
static void get_bin_version(ClusterInfo *cluster)
Definition: exec.c:32
const char * strerror(int errnum)
Definition: strerror.c:19
void report_status(eLogType type, const char *fmt,...) pg_attribute_printf(2

◆ check_data_dir()

static void check_data_dir ( ClusterInfo cluster)
static

Definition at line 326 of file exec.c.

References check_single_dir(), get_major_server_version(), GET_MAJOR_VERSION, ClusterInfo::major_version, pg_data, and ClusterInfo::pgdata.

Referenced by verify_directories().

327 {
328  const char *pg_data = cluster->pgdata;
329 
330  /* get the cluster version */
331  cluster->major_version = get_major_server_version(cluster);
332 
333  check_single_dir(pg_data, "");
334  check_single_dir(pg_data, "base");
335  check_single_dir(pg_data, "global");
336  check_single_dir(pg_data, "pg_multixact");
337  check_single_dir(pg_data, "pg_subtrans");
338  check_single_dir(pg_data, "pg_tblspc");
339  check_single_dir(pg_data, "pg_twophase");
340 
341  /* pg_xlog has been renamed to pg_wal in v10 */
342  if (GET_MAJOR_VERSION(cluster->major_version) < 1000)
343  check_single_dir(pg_data, "pg_xlog");
344  else
345  check_single_dir(pg_data, "pg_wal");
346 
347  /* pg_clog has been renamed to pg_xact in v10 */
348  if (GET_MAJOR_VERSION(cluster->major_version) < 1000)
349  check_single_dir(pg_data, "pg_clog");
350  else
351  check_single_dir(pg_data, "pg_xact");
352 }
uint32 get_major_server_version(ClusterInfo *cluster)
Definition: server.c:155
uint32 major_version
Definition: pg_upgrade.h:274
#define GET_MAJOR_VERSION(v)
Definition: pg_upgrade.h:29
static char * pg_data
Definition: initdb.c:122
static void check_single_dir(const char *pg_data, const char *subdir)
Definition: exec.c:297
char * pgdata
Definition: pg_upgrade.h:266

◆ check_single_dir()

static void check_single_dir ( const char *  pg_data,
const char *  subdir 
)
static

Definition at line 297 of file exec.c.

References MAXPGPATH, PG_FATAL, report_status(), S_ISDIR, snprintf(), stat, and strerror().

Referenced by check_data_dir().

298 {
299  struct stat statBuf;
300  char subDirName[MAXPGPATH];
301 
302  snprintf(subDirName, sizeof(subDirName), "%s%s%s", pg_data,
303  /* Win32 can't stat() a directory with a trailing slash. */
304  *subdir ? "/" : "",
305  subdir);
306 
307  if (stat(subDirName, &statBuf) != 0)
308  report_status(PG_FATAL, "check for \"%s\" failed: %s\n",
309  subDirName, strerror(errno));
310  else if (!S_ISDIR(statBuf.st_mode))
311  report_status(PG_FATAL, "\"%s\" is not a directory\n",
312  subDirName);
313 }
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define MAXPGPATH
static char * pg_data
Definition: initdb.c:122
#define stat(a, b)
Definition: win32_port.h:266
#define S_ISDIR(m)
Definition: win32_port.h:307
const char * strerror(int errnum)
Definition: strerror.c:19
void report_status(eLogType type, const char *fmt,...) pg_attribute_printf(2

◆ exec_prog()

bool exec_prog ( const char *  log_file,
const char *  opt_log_file,
bool  report_error,
bool  exit_on_error,
const char *  fmt,
  ... 
)

Definition at line 80 of file exec.c.

References MAXCMDLEN, PG_FATAL, pg_fatal(), pg_log(), PG_REPORT, pg_usleep(), PG_VERBOSE, report_status(), snprintf(), and vsnprintf().

Referenced by copy_subdir_files(), copy_xact_xlog_xid(), generate_old_dump(), main(), parallel_exec_prog(), prepare_new_cluster(), prepare_new_databases(), start_postmaster(), and stop_postmaster().

82 {
83  int result = 0;
84  int written;
85 
86 #define MAXCMDLEN (2 * MAXPGPATH)
87  char cmd[MAXCMDLEN];
88  FILE *log;
89  va_list ap;
90 
91 #ifdef WIN32
92  static DWORD mainThreadId = 0;
93 
94  /* We assume we are called from the primary thread first */
95  if (mainThreadId == 0)
96  mainThreadId = GetCurrentThreadId();
97 #endif
98 
99  written = 0;
100  va_start(ap, fmt);
101  written += vsnprintf(cmd + written, MAXCMDLEN - written, fmt, ap);
102  va_end(ap);
103  if (written >= MAXCMDLEN)
104  pg_fatal("command too long\n");
105  written += snprintf(cmd + written, MAXCMDLEN - written,
106  " >> \"%s\" 2>&1", log_file);
107  if (written >= MAXCMDLEN)
108  pg_fatal("command too long\n");
109 
110  pg_log(PG_VERBOSE, "%s\n", cmd);
111 
112 #ifdef WIN32
113  /*
114  * For some reason, Windows issues a file-in-use error if we write data to
115  * the log file from a non-primary thread just before we create a
116  * subprocess that also writes to the same log file. One fix is to sleep
117  * for 100ms. A cleaner fix is to write to the log file _after_ the
118  * subprocess has completed, so we do this only when writing from a
119  * non-primary thread. fflush(), running system() twice, and pre-creating
120  * the file do not see to help.
121  */
122  if (mainThreadId != GetCurrentThreadId())
123  result = system(cmd);
124 #endif
125 
126  log = fopen(log_file, "a");
127 
128 #ifdef WIN32
129  {
130  /*
131  * "pg_ctl -w stop" might have reported that the server has stopped
132  * because the postmaster.pid file has been removed, but "pg_ctl -w
133  * start" might still be in the process of closing and might still be
134  * holding its stdout and -l log file descriptors open. Therefore,
135  * try to open the log file a few more times.
136  */
137  int iter;
138 
139  for (iter = 0; iter < 4 && log == NULL; iter++)
140  {
141  pg_usleep(1000000); /* 1 sec */
142  log = fopen(log_file, "a");
143  }
144  }
145 #endif
146 
147  if (log == NULL)
148  pg_fatal("could not write to log file \"%s\"\n", log_file);
149 
150 #ifdef WIN32
151  /* Are we printing "command:" before its output? */
152  if (mainThreadId == GetCurrentThreadId())
153  fprintf(log, "\n\n");
154 #endif
155  fprintf(log, "command: %s\n", cmd);
156 #ifdef WIN32
157  /* Are we printing "command:" after its output? */
158  if (mainThreadId != GetCurrentThreadId())
159  fprintf(log, "\n\n");
160 #endif
161 
162  /*
163  * In Windows, we must close the log file at this point so the file is not
164  * open while the command is running, or we get a share violation.
165  */
166  fclose(log);
167 
168 #ifdef WIN32
169  /* see comment above */
170  if (mainThreadId == GetCurrentThreadId())
171 #endif
172  result = system(cmd);
173 
174  if (result != 0 && report_error)
175  {
176  /* we might be in on a progress status line, so go to the next line */
177  report_status(PG_REPORT, "\n*failure*");
178  fflush(stdout);
179 
180  pg_log(PG_VERBOSE, "There were problems executing \"%s\"\n", cmd);
181  if (opt_log_file)
182  pg_log(exit_on_error ? PG_FATAL : PG_REPORT,
183  "Consult the last few lines of \"%s\" or \"%s\" for\n"
184  "the probable cause of the failure.\n",
185  log_file, opt_log_file);
186  else
187  pg_log(exit_on_error ? PG_FATAL : PG_REPORT,
188  "Consult the last few lines of \"%s\" for\n"
189  "the probable cause of the failure.\n",
190  log_file);
191  }
192 
193 #ifndef WIN32
194  /*
195  * We can't do this on Windows because it will keep the "pg_ctl start"
196  * output filename open until the server stops, so we do the \n\n above on
197  * that platform. We use a unique filename for "pg_ctl start" that is
198  * never reused while the server is running, so it works fine. We could
199  * log these commands to a third file, but that just adds complexity.
200  */
201  if ((log = fopen(log_file, "a")) == NULL)
202  pg_fatal("could not write to log file \"%s\"\n", log_file);
203  fprintf(log, "\n\n");
204  fclose(log);
205 #endif
206 
207  return result == 0;
208 }
static char * log_file
Definition: pg_ctl.c:87
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
int int vsnprintf(char *str, size_t count, const char *fmt, va_list args)
void pg_usleep(long microsec)
Definition: signal.c:53
#define MAXCMDLEN
void pg_log(eLogType type, const char *fmt,...)
Definition: logging.c:69
void report_status(eLogType type, const char *fmt,...) pg_attribute_printf(2

◆ get_bin_version()

static void get_bin_version ( ClusterInfo cluster)
static

Definition at line 32 of file exec.c.

References ClusterInfo::bin_version, ClusterInfo::bindir, MAX_STRING, MAXPGPATH, output(), pg_fatal(), snprintf(), and strerror().

Referenced by check_bin_dir().

33 {
34  char cmd[MAXPGPATH],
35  cmd_output[MAX_STRING];
36  FILE *output;
37  int v1 = 0,
38  v2 = 0;
39 
40  snprintf(cmd, sizeof(cmd), "\"%s/pg_ctl\" --version", cluster->bindir);
41 
42  if ((output = popen(cmd, "r")) == NULL ||
43  fgets(cmd_output, sizeof(cmd_output), output) == NULL)
44  pg_fatal("could not get pg_ctl version data using %s: %s\n",
45  cmd, strerror(errno));
46 
47  pclose(output);
48 
49  if (sscanf(cmd_output, "%*s %*s %d.%d", &v1, &v2) < 1)
50  pg_fatal("could not get pg_ctl version output from %s\n", cmd);
51 
52  if (v1 < 10)
53  {
54  /* old style, e.g. 9.6.1 */
55  cluster->bin_version = v1 * 10000 + v2 * 100;
56  }
57  else
58  {
59  /* new style, e.g. 10.1 */
60  cluster->bin_version = v1 * 10000;
61  }
62 }
static void output(uint64 loop_count)
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
#define MAXPGPATH
char * bindir
Definition: pg_upgrade.h:269
#define MAX_STRING
Definition: pg_upgrade.h:21
uint32 bin_version
Definition: pg_upgrade.h:276
const char * strerror(int errnum)
Definition: strerror.c:19

◆ pid_lock_file_exists()

bool pid_lock_file_exists ( const char *  datadir)

Definition at line 217 of file exec.c.

References close, fd(), MAXPGPATH, pg_fatal(), snprintf(), and strerror().

Referenced by setup().

218 {
219  char path[MAXPGPATH];
220  int fd;
221 
222  snprintf(path, sizeof(path), "%s/postmaster.pid", datadir);
223 
224  if ((fd = open(path, O_RDONLY, 0)) < 0)
225  {
226  /* ENOTDIR means we will throw a more useful error later */
227  if (errno != ENOENT && errno != ENOTDIR)
228  pg_fatal("could not open file \"%s\" for reading: %s\n",
229  path, strerror(errno));
230 
231  return false;
232  }
233 
234  close(fd);
235  return true;
236 }
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define MAXPGPATH
char * datadir
const char * strerror(int errnum)
Definition: strerror.c:19
#define close(a)
Definition: win32.h:12

◆ validate_exec()

static void validate_exec ( const char *  dir,
const char *  cmdName 
)
static

Definition at line 407 of file exec.c.

References MAXPGPATH, pg_fatal(), pg_strcasecmp(), S_IRUSR, S_ISREG, S_IXUSR, snprintf(), stat, strerror(), and strlcat().

Referenced by check_bin_dir().

408 {
409  char path[MAXPGPATH];
410  struct stat buf;
411 
412  snprintf(path, sizeof(path), "%s/%s", dir, cmdName);
413 
414 #ifdef WIN32
415  /* Windows requires a .exe suffix for stat() */
416  if (strlen(path) <= strlen(EXE_EXT) ||
417  pg_strcasecmp(path + strlen(path) - strlen(EXE_EXT), EXE_EXT) != 0)
418  strlcat(path, EXE_EXT, sizeof(path));
419 #endif
420 
421  /*
422  * Ensure that the file exists and is a regular file.
423  */
424  if (stat(path, &buf) < 0)
425  pg_fatal("check for \"%s\" failed: %s\n",
426  path, strerror(errno));
427  else if (!S_ISREG(buf.st_mode))
428  pg_fatal("check for \"%s\" failed: not a regular file\n",
429  path);
430 
431  /*
432  * Ensure that the file is both executable and readable (required for
433  * dynamic loading).
434  */
435 #ifndef WIN32
436  if (access(path, R_OK) != 0)
437 #else
438  if ((buf.st_mode & S_IRUSR) == 0)
439 #endif
440  pg_fatal("check for \"%s\" failed: cannot read file (permission denied)\n",
441  path);
442 
443 #ifndef WIN32
444  if (access(path, X_OK) != 0)
445 #else
446  if ((buf.st_mode & S_IXUSR) == 0)
447 #endif
448  pg_fatal("check for \"%s\" failed: cannot execute (permission denied)\n",
449  path);
450 }
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define S_IXUSR
Definition: win32_port.h:277
#define MAXPGPATH
static char * buf
Definition: pg_test_fsync.c:67
#define S_ISREG(m)
Definition: win32_port.h:310
#define stat(a, b)
Definition: win32_port.h:266
#define S_IRUSR
Definition: win32_port.h:271
const char * strerror(int errnum)
Definition: strerror.c:19
size_t strlcat(char *dst, const char *src, size_t siz)
Definition: strlcat.c:33

◆ verify_directories()

void verify_directories ( void  )

Definition at line 248 of file exec.c.

References check_bin_dir(), check_data_dir(), close, fd(), GLOBALS_DUMP_FILE, new_cluster, old_cluster, pg_fatal(), S_IRUSR, and S_IWUSR.

Referenced by setup().

249 {
250 #ifndef WIN32
251  if (access(".", R_OK | W_OK | X_OK) != 0)
252 #else
253  if (win32_check_directory_write_permissions() != 0)
254 #endif
255  pg_fatal("You must have read and write access in the current directory.\n");
256 
261 }
static void check_bin_dir(ClusterInfo *cluster)
Definition: exec.c:364
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
ClusterInfo new_cluster
Definition: pg_upgrade.c:56
ClusterInfo old_cluster
Definition: pg_upgrade.c:56
static void check_data_dir(ClusterInfo *cluster)
Definition: exec.c:326