PostgreSQL Source Code  git master
exec.c
Go to the documentation of this file.
1 /*
2  * exec.c
3  *
4  * execution functions
5  *
6  * Copyright (c) 2010-2018, PostgreSQL Global Development Group
7  * src/bin/pg_upgrade/exec.c
8  */
9 
10 #include "postgres_fe.h"
11 
12 #include <fcntl.h>
13 
14 #include "pg_upgrade.h"
15 
16 static void check_data_dir(ClusterInfo *cluster);
17 static void check_bin_dir(ClusterInfo *cluster);
18 static void get_bin_version(ClusterInfo *cluster);
19 static void validate_exec(const char *dir, const char *cmdName);
20 
21 #ifdef WIN32
22 static int win32_check_directory_write_permissions(void);
23 #endif
24 
25 
26 /*
27  * get_bin_version
28  *
29  * Fetch major version of binaries for cluster.
30  */
31 static void
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 }
63 
64 
65 /*
66  * exec_prog()
67  * Execute an external program with stdout/stderr redirected, and report
68  * errors
69  *
70  * Formats a command from the given argument list, logs it to the log file,
71  * and attempts to execute that command. If the command executes
72  * successfully, exec_prog() returns true.
73  *
74  * If the command fails, an error message is optionally written to the specified
75  * log_file, and the program optionally exits.
76  *
77  * The code requires it be called first from the primary thread on Windows.
78  */
79 bool
80 exec_prog(const char *log_file, const char *opt_log_file,
81  bool report_error, bool exit_on_error, const char *fmt,...)
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 }
209 
210 
211 /*
212  * pid_lock_file_exists()
213  *
214  * Checks whether the postmaster.pid file exists.
215  */
216 bool
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 }
237 
238 
239 /*
240  * verify_directories()
241  *
242  * does all the hectic work of verifying directories and executables
243  * of old and new server.
244  *
245  * NOTE: May update the values of all parameters
246  */
247 void
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 }
262 
263 
264 #ifdef WIN32
265 /*
266  * win32_check_directory_write_permissions()
267  *
268  * access() on WIN32 can't check directory permissions, so we have to
269  * optionally create, then delete a file to check.
270  * http://msdn.microsoft.com/en-us/library/1w06ktdy%28v=vs.80%29.aspx
271  */
272 static int
273 win32_check_directory_write_permissions(void)
274 {
275  int fd;
276 
277  /*
278  * We open a file we would normally create anyway. We do this even in
279  * 'check' mode, which isn't ideal, but this is the best we can do.
280  */
281  if ((fd = open(GLOBALS_DUMP_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0)
282  return -1;
283  close(fd);
284 
285  return unlink(GLOBALS_DUMP_FILE);
286 }
287 #endif
288 
289 
290 /*
291  * check_single_dir()
292  *
293  * Check for the presence of a single directory in PGDATA, and fail if
294  * is it missing or not accessible.
295  */
296 static void
297 check_single_dir(const char *pg_data, const char *subdir)
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 }
314 
315 
316 /*
317  * check_data_dir()
318  *
319  * This function validates the given cluster directory - we search for a
320  * small set of subdirectories that we expect to find in a valid $PGDATA
321  * directory. If any of the subdirectories are missing (or secured against
322  * us) we display an error message and exit()
323  *
324  */
325 static void
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 }
353 
354 
355 /*
356  * check_bin_dir()
357  *
358  * This function searches for the executables that we expect to find
359  * in the binaries directory. If we find that a required executable
360  * is missing (or secured against us), we display an error message and
361  * exit().
362  */
363 static void
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 }
399 
400 
401 /*
402  * validate_exec()
403  *
404  * validate "path" as an executable file
405  */
406 static void
407 validate_exec(const char *dir, const char *cmdName)
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 }
uint32 get_major_server_version(ClusterInfo *cluster)
Definition: server.c:155
static void check_bin_dir(ClusterInfo *cluster)
Definition: exec.c:364
uint32 major_version
Definition: pg_upgrade.h:274
static void output(uint64 loop_count)
bool pid_lock_file_exists(const char *datadir)
Definition: exec.c:217
static char * log_file
Definition: pg_ctl.c:87
#define GET_MAJOR_VERSION(v)
Definition: pg_upgrade.h:29
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
static int fd(const char *x, int i)
Definition: preproc-init.c:105
ClusterInfo new_cluster
Definition: pg_upgrade.c:56
int int vsnprintf(char *str, size_t count, const char *fmt, va_list args)
void pg_usleep(long microsec)
Definition: signal.c:53
#define S_IWUSR
Definition: win32_port.h:274
#define MAXPGPATH
#define MAXCMDLEN
ClusterInfo old_cluster
Definition: pg_upgrade.c:56
char * datadir
void cluster(ClusterStmt *stmt, bool isTopLevel)
Definition: cluster.c:106
void pg_log(eLogType type, const char *fmt,...)
Definition: logging.c:69
static char * pg_data
Definition: initdb.c:122
static void check_single_dir(const char *pg_data, const char *subdir)
Definition: exec.c:297
#define S_ISREG(m)
Definition: win32_port.h:310
#define stat(a, b)
Definition: win32_port.h:266
char * bindir
Definition: pg_upgrade.h:269
#define MAX_STRING
Definition: pg_upgrade.h:21
uint32 bin_version
Definition: pg_upgrade.h:276
static void validate_exec(const char *dir, const char *cmdName)
Definition: exec.c:407
void verify_directories(void)
Definition: exec.c:248
#define S_IRUSR
Definition: win32_port.h:271
#define S_ISDIR(m)
Definition: win32_port.h:307
static void check_data_dir(ClusterInfo *cluster)
Definition: exec.c:326
char * pgdata
Definition: pg_upgrade.h:266
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
bool exec_prog(const char *log_file, const char *opt_log_file, bool report_error, bool exit_on_error, const char *fmt,...)
Definition: exec.c:80
#define GLOBALS_DUMP_FILE
Definition: pg_upgrade.h:32
#define close(a)
Definition: win32.h:12
size_t strlcat(char *dst, const char *src, size_t siz)
Definition: strlcat.c:33