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 "pg_upgrade.h"
13 
14 #include <fcntl.h>
15 #include <sys/types.h>
16 
17 static void check_data_dir(ClusterInfo *cluster);
18 static void check_bin_dir(ClusterInfo *cluster);
19 static void get_bin_version(ClusterInfo *cluster);
20 static void validate_exec(const char *dir, const char *cmdName);
21 
22 #ifdef WIN32
23 static int win32_check_directory_write_permissions(void);
24 #endif
25 
26 
27 /*
28  * get_bin_version
29  *
30  * Fetch versions of binaries for cluster.
31  */
32 static void
34 {
35  char cmd[MAXPGPATH],
36  cmd_output[MAX_STRING];
37  FILE *output;
38  int pre_dot = 0,
39  post_dot = 0;
40 
41  snprintf(cmd, sizeof(cmd), "\"%s/pg_ctl\" --version", cluster->bindir);
42 
43  if ((output = popen(cmd, "r")) == NULL ||
44  fgets(cmd_output, sizeof(cmd_output), output) == NULL)
45  pg_fatal("could not get pg_ctl version data using %s: %s\n",
46  cmd, strerror(errno));
47 
48  pclose(output);
49 
50  /* Remove trailing newline */
51  if (strchr(cmd_output, '\n') != NULL)
52  *strchr(cmd_output, '\n') = '\0';
53 
54  if (sscanf(cmd_output, "%*s %*s %d.%d", &pre_dot, &post_dot) < 1)
55  pg_fatal("could not get version from %s\n", cmd);
56 
57  cluster->bin_version = (pre_dot * 100 + post_dot) * 100;
58 }
59 
60 
61 /*
62  * exec_prog()
63  * Execute an external program with stdout/stderr redirected, and report
64  * errors
65  *
66  * Formats a command from the given argument list, logs it to the log file,
67  * and attempts to execute that command. If the command executes
68  * successfully, exec_prog() returns true.
69  *
70  * If the command fails, an error message is saved to the specified log_file.
71  * If throw_error is true, this raises a PG_FATAL error and pg_upgrade
72  * terminates; otherwise it is just reported as PG_REPORT and exec_prog()
73  * returns false.
74  *
75  * The code requires it be called first from the primary thread on Windows.
76  */
77 bool
78 exec_prog(const char *log_file, const char *opt_log_file,
79  bool throw_error, const char *fmt,...)
80 {
81  int result = 0;
82  int written;
83 
84 #define MAXCMDLEN (2 * MAXPGPATH)
85  char cmd[MAXCMDLEN];
86  FILE *log;
87  va_list ap;
88 
89 #ifdef WIN32
90  static DWORD mainThreadId = 0;
91 
92  /* We assume we are called from the primary thread first */
93  if (mainThreadId == 0)
94  mainThreadId = GetCurrentThreadId();
95 #endif
96 
97  written = 0;
98  va_start(ap, fmt);
99  written += vsnprintf(cmd + written, MAXCMDLEN - written, fmt, ap);
100  va_end(ap);
101  if (written >= MAXCMDLEN)
102  pg_fatal("command too long\n");
103  written += snprintf(cmd + written, MAXCMDLEN - written,
104  " >> \"%s\" 2>&1", log_file);
105  if (written >= MAXCMDLEN)
106  pg_fatal("command too long\n");
107 
108  pg_log(PG_VERBOSE, "%s\n", cmd);
109 
110 #ifdef WIN32
111 
112  /*
113  * For some reason, Windows issues a file-in-use error if we write data to
114  * the log file from a non-primary thread just before we create a
115  * subprocess that also writes to the same log file. One fix is to sleep
116  * for 100ms. A cleaner fix is to write to the log file _after_ the
117  * subprocess has completed, so we do this only when writing from a
118  * non-primary thread. fflush(), running system() twice, and pre-creating
119  * the file do not see to help.
120  */
121  if (mainThreadId != GetCurrentThreadId())
122  result = system(cmd);
123 #endif
124 
125  log = fopen(log_file, "a");
126 
127 #ifdef WIN32
128  {
129  /*
130  * "pg_ctl -w stop" might have reported that the server has stopped
131  * because the postmaster.pid file has been removed, but "pg_ctl -w
132  * start" might still be in the process of closing and might still be
133  * holding its stdout and -l log file descriptors open. Therefore,
134  * try to open the log file a few more times.
135  */
136  int iter;
137 
138  for (iter = 0; iter < 4 && log == NULL; iter++)
139  {
140  pg_usleep(1000000); /* 1 sec */
141  log = fopen(log_file, "a");
142  }
143  }
144 #endif
145 
146  if (log == NULL)
147  pg_fatal("cannot write to log file %s\n", log_file);
148 
149 #ifdef WIN32
150  /* Are we printing "command:" before its output? */
151  if (mainThreadId == GetCurrentThreadId())
152  fprintf(log, "\n\n");
153 #endif
154  fprintf(log, "command: %s\n", cmd);
155 #ifdef WIN32
156  /* Are we printing "command:" after its output? */
157  if (mainThreadId != GetCurrentThreadId())
158  fprintf(log, "\n\n");
159 #endif
160 
161  /*
162  * In Windows, we must close the log file at this point so the file is not
163  * open while the command is running, or we get a share violation.
164  */
165  fclose(log);
166 
167 #ifdef WIN32
168  /* see comment above */
169  if (mainThreadId == GetCurrentThreadId())
170 #endif
171  result = system(cmd);
172 
173  if (result != 0)
174  {
175  /* we might be in on a progress status line, so go to the next line */
176  report_status(PG_REPORT, "\n*failure*");
177  fflush(stdout);
178 
179  pg_log(PG_VERBOSE, "There were problems executing \"%s\"\n", cmd);
180  if (opt_log_file)
181  pg_log(throw_error ? PG_FATAL : PG_REPORT,
182  "Consult the last few lines of \"%s\" or \"%s\" for\n"
183  "the probable cause of the failure.\n",
184  log_file, opt_log_file);
185  else
186  pg_log(throw_error ? PG_FATAL : PG_REPORT,
187  "Consult the last few lines of \"%s\" for\n"
188  "the probable cause of the failure.\n",
189  log_file);
190  }
191 
192 #ifndef WIN32
193 
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("cannot 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 old and new cluster versions */
333 
334  check_single_dir(pg_data, "");
335  check_single_dir(pg_data, "base");
336  check_single_dir(pg_data, "global");
337  check_single_dir(pg_data, "pg_multixact");
338  check_single_dir(pg_data, "pg_subtrans");
339  check_single_dir(pg_data, "pg_tblspc");
340  check_single_dir(pg_data, "pg_twophase");
341 
342  /* pg_xlog has been renamed to pg_wal in post-10 cluster */
343  if (GET_MAJOR_VERSION(cluster->major_version) < 1000)
344  check_single_dir(pg_data, "pg_xlog");
345  else
346  check_single_dir(pg_data, "pg_wal");
347 }
348 
349 
350 /*
351  * check_bin_dir()
352  *
353  * This function searches for the executables that we expect to find
354  * in the binaries directory. If we find that a required executable
355  * is missing (or secured against us), we display an error message and
356  * exit().
357  */
358 static void
360 {
361  struct stat statBuf;
362 
363  /* check bindir */
364  if (stat(cluster->bindir, &statBuf) != 0)
365  report_status(PG_FATAL, "check for \"%s\" failed: %s\n",
366  cluster->bindir, strerror(errno));
367  else if (!S_ISDIR(statBuf.st_mode))
368  report_status(PG_FATAL, "%s is not a directory\n",
369  cluster->bindir);
370 
371  validate_exec(cluster->bindir, "postgres");
372  validate_exec(cluster->bindir, "pg_ctl");
373 
374  /*
375  * Fetch the binary versions after checking for the existence of pg_ctl,
376  * this gives a correct error if the binary used itself for the version
377  * fetching is broken.
378  */
381 
382  /* pg_resetxlog has been renamed to pg_resetwal in version 10 */
383  if (GET_MAJOR_VERSION(cluster->bin_version) < 1000)
384  validate_exec(cluster->bindir, "pg_resetxlog");
385  else
386  validate_exec(cluster->bindir, "pg_resetwal");
387  if (cluster == &new_cluster)
388  {
389  /* these are only needed in the new cluster */
390  validate_exec(cluster->bindir, "psql");
391  validate_exec(cluster->bindir, "pg_dump");
392  validate_exec(cluster->bindir, "pg_dumpall");
393  }
394 }
395 
396 
397 /*
398  * validate_exec()
399  *
400  * validate "path" as an executable file
401  */
402 static void
403 validate_exec(const char *dir, const char *cmdName)
404 {
405  char path[MAXPGPATH];
406  struct stat buf;
407 
408  snprintf(path, sizeof(path), "%s/%s", dir, cmdName);
409 
410 #ifdef WIN32
411  /* Windows requires a .exe suffix for stat() */
412  if (strlen(path) <= strlen(EXE_EXT) ||
413  pg_strcasecmp(path + strlen(path) - strlen(EXE_EXT), EXE_EXT) != 0)
414  strlcat(path, EXE_EXT, sizeof(path));
415 #endif
416 
417  /*
418  * Ensure that the file exists and is a regular file.
419  */
420  if (stat(path, &buf) < 0)
421  pg_fatal("check for \"%s\" failed: %s\n",
422  path, strerror(errno));
423  else if (!S_ISREG(buf.st_mode))
424  pg_fatal("check for \"%s\" failed: not an executable file\n",
425  path);
426 
427  /*
428  * Ensure that the file is both executable and readable (required for
429  * dynamic loading).
430  */
431 #ifndef WIN32
432  if (access(path, R_OK) != 0)
433 #else
434  if ((buf.st_mode & S_IRUSR) == 0)
435 #endif
436  pg_fatal("check for \"%s\" failed: cannot read file (permission denied)\n",
437  path);
438 
439 #ifndef WIN32
440  if (access(path, X_OK) != 0)
441 #else
442  if ((buf.st_mode & S_IXUSR) == 0)
443 #endif
444  pg_fatal("check for \"%s\" failed: cannot execute (permission denied)\n",
445  path);
446 }
uint32 get_major_server_version(ClusterInfo *cluster)
Definition: server.c:155
static void check_bin_dir(ClusterInfo *cluster)
Definition: exec.c:359
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:86
#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
static int fd(const char *x, int i)
Definition: preproc-init.c:105
ClusterInfo new_cluster
Definition: pg_upgrade.c:55
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:55
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:120
int unlink(const char *filename)
static void check_single_dir(const char *pg_data, const char *subdir)
Definition: exec.c:297
char * bindir
Definition: pg_upgrade.h:269
#define MAX_STRING
Definition: pg_upgrade.h:21
uint32 bin_version
Definition: pg_upgrade.h:276
#define NULL
Definition: c.h:226
static void validate_exec(const char *dir, const char *cmdName)
Definition: exec.c:403
void verify_directories(void)
Definition: exec.c:248
bool exec_prog(const char *log_file, const char *opt_log_file, bool throw_error, const char *fmt,...)
Definition: exec.c:78
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:33
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:17
size_t strlcat(char *dst, const char *src, size_t siz)
Definition: strlcat.c:33