PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
exec.c
Go to the documentation of this file.
1 /*
2  * exec.c
3  *
4  * execution functions
5  *
6  * Copyright (c) 2010-2017, 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 versions of binaries for cluster.
30  */
31 static void
33 {
34  char cmd[MAXPGPATH],
35  cmd_output[MAX_STRING];
36  FILE *output;
37  int pre_dot = 0,
38  post_dot = 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  /* Remove trailing newline */
50  if (strchr(cmd_output, '\n') != NULL)
51  *strchr(cmd_output, '\n') = '\0';
52 
53  if (sscanf(cmd_output, "%*s %*s %d.%d", &pre_dot, &post_dot) < 1)
54  pg_fatal("could not get version from %s\n", cmd);
55 
56  cluster->bin_version = (pre_dot * 100 + post_dot) * 100;
57 }
58 
59 
60 /*
61  * exec_prog()
62  * Execute an external program with stdout/stderr redirected, and report
63  * errors
64  *
65  * Formats a command from the given argument list, logs it to the log file,
66  * and attempts to execute that command. If the command executes
67  * successfully, exec_prog() returns true.
68  *
69  * If the command fails, an error message is saved to the specified log_file.
70  * If throw_error is true, this raises a PG_FATAL error and pg_upgrade
71  * terminates; otherwise it is just reported as PG_REPORT and exec_prog()
72  * returns false.
73  *
74  * The code requires it be called first from the primary thread on Windows.
75  */
76 bool
77 exec_prog(const char *log_file, const char *opt_log_file,
78  bool throw_error, const char *fmt,...)
79 {
80  int result = 0;
81  int written;
82 
83 #define MAXCMDLEN (2 * MAXPGPATH)
84  char cmd[MAXCMDLEN];
85  FILE *log;
86  va_list ap;
87 
88 #ifdef WIN32
89  static DWORD mainThreadId = 0;
90 
91  /* We assume we are called from the primary thread first */
92  if (mainThreadId == 0)
93  mainThreadId = GetCurrentThreadId();
94 #endif
95 
96  written = 0;
97  va_start(ap, fmt);
98  written += vsnprintf(cmd + written, MAXCMDLEN - written, fmt, ap);
99  va_end(ap);
100  if (written >= MAXCMDLEN)
101  pg_fatal("command too long\n");
102  written += snprintf(cmd + written, MAXCMDLEN - written,
103  " >> \"%s\" 2>&1", log_file);
104  if (written >= MAXCMDLEN)
105  pg_fatal("command too long\n");
106 
107  pg_log(PG_VERBOSE, "%s\n", cmd);
108 
109 #ifdef WIN32
110 
111  /*
112  * For some reason, Windows issues a file-in-use error if we write data to
113  * the log file from a non-primary thread just before we create a
114  * subprocess that also writes to the same log file. One fix is to sleep
115  * for 100ms. A cleaner fix is to write to the log file _after_ the
116  * subprocess has completed, so we do this only when writing from a
117  * non-primary thread. fflush(), running system() twice, and pre-creating
118  * the file do not see to help.
119  */
120  if (mainThreadId != GetCurrentThreadId())
121  result = system(cmd);
122 #endif
123 
124  log = fopen(log_file, "a");
125 
126 #ifdef WIN32
127  {
128  /*
129  * "pg_ctl -w stop" might have reported that the server has stopped
130  * because the postmaster.pid file has been removed, but "pg_ctl -w
131  * start" might still be in the process of closing and might still be
132  * holding its stdout and -l log file descriptors open. Therefore,
133  * try to open the log file a few more times.
134  */
135  int iter;
136 
137  for (iter = 0; iter < 4 && log == NULL; iter++)
138  {
139  pg_usleep(1000000); /* 1 sec */
140  log = fopen(log_file, "a");
141  }
142  }
143 #endif
144 
145  if (log == NULL)
146  pg_fatal("cannot write to log file %s\n", log_file);
147 
148 #ifdef WIN32
149  /* Are we printing "command:" before its output? */
150  if (mainThreadId == GetCurrentThreadId())
151  fprintf(log, "\n\n");
152 #endif
153  fprintf(log, "command: %s\n", cmd);
154 #ifdef WIN32
155  /* Are we printing "command:" after its output? */
156  if (mainThreadId != GetCurrentThreadId())
157  fprintf(log, "\n\n");
158 #endif
159 
160  /*
161  * In Windows, we must close the log file at this point so the file is not
162  * open while the command is running, or we get a share violation.
163  */
164  fclose(log);
165 
166 #ifdef WIN32
167  /* see comment above */
168  if (mainThreadId == GetCurrentThreadId())
169 #endif
170  result = system(cmd);
171 
172  if (result != 0)
173  {
174  /* we might be in on a progress status line, so go to the next line */
175  report_status(PG_REPORT, "\n*failure*");
176  fflush(stdout);
177 
178  pg_log(PG_VERBOSE, "There were problems executing \"%s\"\n", cmd);
179  if (opt_log_file)
180  pg_log(throw_error ? PG_FATAL : PG_REPORT,
181  "Consult the last few lines of \"%s\" or \"%s\" for\n"
182  "the probable cause of the failure.\n",
183  log_file, opt_log_file);
184  else
185  pg_log(throw_error ? PG_FATAL : PG_REPORT,
186  "Consult the last few lines of \"%s\" for\n"
187  "the probable cause of the failure.\n",
188  log_file);
189  }
190 
191 #ifndef WIN32
192 
193  /*
194  * We can't do this on Windows because it will keep the "pg_ctl start"
195  * output filename open until the server stops, so we do the \n\n above on
196  * that platform. We use a unique filename for "pg_ctl start" that is
197  * never reused while the server is running, so it works fine. We could
198  * log these commands to a third file, but that just adds complexity.
199  */
200  if ((log = fopen(log_file, "a")) == NULL)
201  pg_fatal("cannot write to log file %s\n", log_file);
202  fprintf(log, "\n\n");
203  fclose(log);
204 #endif
205 
206  return result == 0;
207 }
208 
209 
210 /*
211  * pid_lock_file_exists()
212  *
213  * Checks whether the postmaster.pid file exists.
214  */
215 bool
217 {
218  char path[MAXPGPATH];
219  int fd;
220 
221  snprintf(path, sizeof(path), "%s/postmaster.pid", datadir);
222 
223  if ((fd = open(path, O_RDONLY, 0)) < 0)
224  {
225  /* ENOTDIR means we will throw a more useful error later */
226  if (errno != ENOENT && errno != ENOTDIR)
227  pg_fatal("could not open file \"%s\" for reading: %s\n",
228  path, strerror(errno));
229 
230  return false;
231  }
232 
233  close(fd);
234  return true;
235 }
236 
237 
238 /*
239  * verify_directories()
240  *
241  * does all the hectic work of verifying directories and executables
242  * of old and new server.
243  *
244  * NOTE: May update the values of all parameters
245  */
246 void
248 {
249 #ifndef WIN32
250  if (access(".", R_OK | W_OK | X_OK) != 0)
251 #else
252  if (win32_check_directory_write_permissions() != 0)
253 #endif
254  pg_fatal("You must have read and write access in the current directory.\n");
255 
260 }
261 
262 
263 #ifdef WIN32
264 /*
265  * win32_check_directory_write_permissions()
266  *
267  * access() on WIN32 can't check directory permissions, so we have to
268  * optionally create, then delete a file to check.
269  * http://msdn.microsoft.com/en-us/library/1w06ktdy%28v=vs.80%29.aspx
270  */
271 static int
272 win32_check_directory_write_permissions(void)
273 {
274  int fd;
275 
276  /*
277  * We open a file we would normally create anyway. We do this even in
278  * 'check' mode, which isn't ideal, but this is the best we can do.
279  */
280  if ((fd = open(GLOBALS_DUMP_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0)
281  return -1;
282  close(fd);
283 
284  return unlink(GLOBALS_DUMP_FILE);
285 }
286 #endif
287 
288 
289 /*
290  * check_single_dir()
291  *
292  * Check for the presence of a single directory in PGDATA, and fail if
293  * is it missing or not accessible.
294  */
295 static void
296 check_single_dir(const char *pg_data, const char *subdir)
297 {
298  struct stat statBuf;
299  char subDirName[MAXPGPATH];
300 
301  snprintf(subDirName, sizeof(subDirName), "%s%s%s", pg_data,
302  /* Win32 can't stat() a directory with a trailing slash. */
303  *subdir ? "/" : "",
304  subdir);
305 
306  if (stat(subDirName, &statBuf) != 0)
307  report_status(PG_FATAL, "check for \"%s\" failed: %s\n",
308  subDirName, strerror(errno));
309  else if (!S_ISDIR(statBuf.st_mode))
310  report_status(PG_FATAL, "%s is not a directory\n",
311  subDirName);
312 }
313 
314 
315 /*
316  * check_data_dir()
317  *
318  * This function validates the given cluster directory - we search for a
319  * small set of subdirectories that we expect to find in a valid $PGDATA
320  * directory. If any of the subdirectories are missing (or secured against
321  * us) we display an error message and exit()
322  *
323  */
324 static void
326 {
327  const char *pg_data = cluster->pgdata;
328 
329  /* get old and new cluster versions */
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 versions after checking for the existence of pg_ctl,
381  * this gives a correct error if the binary used itself for the version
382  * fetching is broken.
383  */
386 
387  /* pg_resetxlog has been renamed to pg_resetwal in version 10 */
388  if (GET_MAJOR_VERSION(cluster->bin_version) < 1000)
389  validate_exec(cluster->bindir, "pg_resetxlog");
390  else
391  validate_exec(cluster->bindir, "pg_resetwal");
392  if (cluster == &new_cluster)
393  {
394  /* these are only needed in the new cluster */
395  validate_exec(cluster->bindir, "psql");
396  validate_exec(cluster->bindir, "pg_dump");
397  validate_exec(cluster->bindir, "pg_dumpall");
398  }
399 }
400 
401 
402 /*
403  * validate_exec()
404  *
405  * validate "path" as an executable file
406  */
407 static void
408 validate_exec(const char *dir, const char *cmdName)
409 {
410  char path[MAXPGPATH];
411  struct stat buf;
412 
413  snprintf(path, sizeof(path), "%s/%s", dir, cmdName);
414 
415 #ifdef WIN32
416  /* Windows requires a .exe suffix for stat() */
417  if (strlen(path) <= strlen(EXE_EXT) ||
418  pg_strcasecmp(path + strlen(path) - strlen(EXE_EXT), EXE_EXT) != 0)
419  strlcat(path, EXE_EXT, sizeof(path));
420 #endif
421 
422  /*
423  * Ensure that the file exists and is a regular file.
424  */
425  if (stat(path, &buf) < 0)
426  pg_fatal("check for \"%s\" failed: %s\n",
427  path, strerror(errno));
428  else if (!S_ISREG(buf.st_mode))
429  pg_fatal("check for \"%s\" failed: not an executable file\n",
430  path);
431 
432  /*
433  * Ensure that the file is both executable and readable (required for
434  * dynamic loading).
435  */
436 #ifndef WIN32
437  if (access(path, R_OK) != 0)
438 #else
439  if ((buf.st_mode & S_IRUSR) == 0)
440 #endif
441  pg_fatal("check for \"%s\" failed: cannot read file (permission denied)\n",
442  path);
443 
444 #ifndef WIN32
445  if (access(path, X_OK) != 0)
446 #else
447  if ((buf.st_mode & S_IXUSR) == 0)
448 #endif
449  pg_fatal("check for \"%s\" failed: cannot execute (permission denied)\n",
450  path);
451 }
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:272
static void output(uint64 loop_count)
bool pid_lock_file_exists(const char *datadir)
Definition: exec.c:216
static char * log_file
Definition: pg_ctl.c:83
#define GET_MAJOR_VERSION(v)
Definition: pg_upgrade.h:29
return result
Definition: formatting.c:1618
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
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 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:121
int unlink(const char *filename)
static void check_single_dir(const char *pg_data, const char *subdir)
Definition: exec.c:296
char * bindir
Definition: pg_upgrade.h:267
#define MAX_STRING
Definition: pg_upgrade.h:21
uint32 bin_version
Definition: pg_upgrade.h:274
#define NULL
Definition: c.h:229
static void validate_exec(const char *dir, const char *cmdName)
Definition: exec.c:408
void verify_directories(void)
Definition: exec.c:247
bool exec_prog(const char *log_file, const char *opt_log_file, bool throw_error, const char *fmt,...)
Definition: exec.c:77
static void check_data_dir(ClusterInfo *cluster)
Definition: exec.c:325
char * pgdata
Definition: pg_upgrade.h:264
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
#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