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  /*
115  * For some reason, Windows issues a file-in-use error if we write data to
116  * the log file from a non-primary thread just before we create a
117  * subprocess that also writes to the same log file. One fix is to sleep
118  * for 100ms. A cleaner fix is to write to the log file _after_ the
119  * subprocess has completed, so we do this only when writing from a
120  * non-primary thread. fflush(), running system() twice, and pre-creating
121  * the file do not see to help.
122  */
123  if (mainThreadId != GetCurrentThreadId())
124  result = system(cmd);
125 #endif
126 
127  log = fopen(log_file, "a");
128 
129 #ifdef WIN32
130  {
131  /*
132  * "pg_ctl -w stop" might have reported that the server has stopped
133  * because the postmaster.pid file has been removed, but "pg_ctl -w
134  * start" might still be in the process of closing and might still be
135  * holding its stdout and -l log file descriptors open. Therefore,
136  * try to open the log file a few more times.
137  */
138  int iter;
139 
140  for (iter = 0; iter < 4 && log == NULL; iter++)
141  {
142  pg_usleep(1000000); /* 1 sec */
143  log = fopen(log_file, "a");
144  }
145  }
146 #endif
147 
148  if (log == NULL)
149  pg_fatal("could not write to log file \"%s\"\n", log_file);
150 
151 #ifdef WIN32
152  /* Are we printing "command:" before its output? */
153  if (mainThreadId == GetCurrentThreadId())
154  fprintf(log, "\n\n");
155 #endif
156  fprintf(log, "command: %s\n", cmd);
157 #ifdef WIN32
158  /* Are we printing "command:" after its output? */
159  if (mainThreadId != GetCurrentThreadId())
160  fprintf(log, "\n\n");
161 #endif
162 
163  /*
164  * In Windows, we must close the log file at this point so the file is not
165  * open while the command is running, or we get a share violation.
166  */
167  fclose(log);
168 
169 #ifdef WIN32
170  /* see comment above */
171  if (mainThreadId == GetCurrentThreadId())
172 #endif
173  result = system(cmd);
174 
175  if (result != 0 && report_error)
176  {
177  /* we might be in on a progress status line, so go to the next line */
178  report_status(PG_REPORT, "\n*failure*");
179  fflush(stdout);
180 
181  pg_log(PG_VERBOSE, "There were problems executing \"%s\"\n", cmd);
182  if (opt_log_file)
183  pg_log(exit_on_error ? PG_FATAL : PG_REPORT,
184  "Consult the last few lines of \"%s\" or \"%s\" for\n"
185  "the probable cause of the failure.\n",
186  log_file, opt_log_file);
187  else
188  pg_log(exit_on_error ? PG_FATAL : PG_REPORT,
189  "Consult the last few lines of \"%s\" for\n"
190  "the probable cause of the failure.\n",
191  log_file);
192  }
193 
194 #ifndef WIN32
195 
196  /*
197  * We can't do this on Windows because it will keep the "pg_ctl start"
198  * output filename open until the server stops, so we do the \n\n above on
199  * that platform. We use a unique filename for "pg_ctl start" that is
200  * never reused while the server is running, so it works fine. We could
201  * log these commands to a third file, but that just adds complexity.
202  */
203  if ((log = fopen(log_file, "a")) == NULL)
204  pg_fatal("could not write to log file \"%s\"\n", log_file);
205  fprintf(log, "\n\n");
206  fclose(log);
207 #endif
208 
209  return result == 0;
210 }
211 
212 
213 /*
214  * pid_lock_file_exists()
215  *
216  * Checks whether the postmaster.pid file exists.
217  */
218 bool
220 {
221  char path[MAXPGPATH];
222  int fd;
223 
224  snprintf(path, sizeof(path), "%s/postmaster.pid", datadir);
225 
226  if ((fd = open(path, O_RDONLY, 0)) < 0)
227  {
228  /* ENOTDIR means we will throw a more useful error later */
229  if (errno != ENOENT && errno != ENOTDIR)
230  pg_fatal("could not open file \"%s\" for reading: %s\n",
231  path, strerror(errno));
232 
233  return false;
234  }
235 
236  close(fd);
237  return true;
238 }
239 
240 
241 /*
242  * verify_directories()
243  *
244  * does all the hectic work of verifying directories and executables
245  * of old and new server.
246  *
247  * NOTE: May update the values of all parameters
248  */
249 void
251 {
252 #ifndef WIN32
253  if (access(".", R_OK | W_OK | X_OK) != 0)
254 #else
255  if (win32_check_directory_write_permissions() != 0)
256 #endif
257  pg_fatal("You must have read and write access in the current directory.\n");
258 
263 }
264 
265 
266 #ifdef WIN32
267 /*
268  * win32_check_directory_write_permissions()
269  *
270  * access() on WIN32 can't check directory permissions, so we have to
271  * optionally create, then delete a file to check.
272  * http://msdn.microsoft.com/en-us/library/1w06ktdy%28v=vs.80%29.aspx
273  */
274 static int
275 win32_check_directory_write_permissions(void)
276 {
277  int fd;
278 
279  /*
280  * We open a file we would normally create anyway. We do this even in
281  * 'check' mode, which isn't ideal, but this is the best we can do.
282  */
283  if ((fd = open(GLOBALS_DUMP_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0)
284  return -1;
285  close(fd);
286 
287  return unlink(GLOBALS_DUMP_FILE);
288 }
289 #endif
290 
291 
292 /*
293  * check_single_dir()
294  *
295  * Check for the presence of a single directory in PGDATA, and fail if
296  * is it missing or not accessible.
297  */
298 static void
299 check_single_dir(const char *pg_data, const char *subdir)
300 {
301  struct stat statBuf;
302  char subDirName[MAXPGPATH];
303 
304  snprintf(subDirName, sizeof(subDirName), "%s%s%s", pg_data,
305  /* Win32 can't stat() a directory with a trailing slash. */
306  *subdir ? "/" : "",
307  subdir);
308 
309  if (stat(subDirName, &statBuf) != 0)
310  report_status(PG_FATAL, "check for \"%s\" failed: %s\n",
311  subDirName, strerror(errno));
312  else if (!S_ISDIR(statBuf.st_mode))
313  report_status(PG_FATAL, "\"%s\" is not a directory\n",
314  subDirName);
315 }
316 
317 
318 /*
319  * check_data_dir()
320  *
321  * This function validates the given cluster directory - we search for a
322  * small set of subdirectories that we expect to find in a valid $PGDATA
323  * directory. If any of the subdirectories are missing (or secured against
324  * us) we display an error message and exit()
325  *
326  */
327 static void
329 {
330  const char *pg_data = cluster->pgdata;
331 
332  /* get the cluster version */
333  cluster->major_version = get_major_server_version(cluster);
334 
335  check_single_dir(pg_data, "");
336  check_single_dir(pg_data, "base");
337  check_single_dir(pg_data, "global");
338  check_single_dir(pg_data, "pg_multixact");
339  check_single_dir(pg_data, "pg_subtrans");
340  check_single_dir(pg_data, "pg_tblspc");
341  check_single_dir(pg_data, "pg_twophase");
342 
343  /* pg_xlog has been renamed to pg_wal in v10 */
344  if (GET_MAJOR_VERSION(cluster->major_version) < 1000)
345  check_single_dir(pg_data, "pg_xlog");
346  else
347  check_single_dir(pg_data, "pg_wal");
348 
349  /* pg_clog has been renamed to pg_xact in v10 */
350  if (GET_MAJOR_VERSION(cluster->major_version) < 1000)
351  check_single_dir(pg_data, "pg_clog");
352  else
353  check_single_dir(pg_data, "pg_xact");
354 }
355 
356 
357 /*
358  * check_bin_dir()
359  *
360  * This function searches for the executables that we expect to find
361  * in the binaries directory. If we find that a required executable
362  * is missing (or secured against us), we display an error message and
363  * exit().
364  */
365 static void
367 {
368  struct stat statBuf;
369 
370  /* check bindir */
371  if (stat(cluster->bindir, &statBuf) != 0)
372  report_status(PG_FATAL, "check for \"%s\" failed: %s\n",
373  cluster->bindir, strerror(errno));
374  else if (!S_ISDIR(statBuf.st_mode))
375  report_status(PG_FATAL, "\"%s\" is not a directory\n",
376  cluster->bindir);
377 
378  validate_exec(cluster->bindir, "postgres");
379  validate_exec(cluster->bindir, "pg_ctl");
380 
381  /*
382  * Fetch the binary version after checking for the existence of pg_ctl.
383  * This way we report a useful error if the pg_ctl binary used for version
384  * fetching is missing/broken.
385  */
386  get_bin_version(cluster);
387 
388  /* pg_resetxlog has been renamed to pg_resetwal in version 10 */
389  if (GET_MAJOR_VERSION(cluster->bin_version) < 1000)
390  validate_exec(cluster->bindir, "pg_resetxlog");
391  else
392  validate_exec(cluster->bindir, "pg_resetwal");
393  if (cluster == &new_cluster)
394  {
395  /* these are only needed in the new cluster */
396  validate_exec(cluster->bindir, "psql");
397  validate_exec(cluster->bindir, "pg_dump");
398  validate_exec(cluster->bindir, "pg_dumpall");
399  }
400 }
401 
402 
403 /*
404  * validate_exec()
405  *
406  * validate "path" as an executable file
407  */
408 static void
409 validate_exec(const char *dir, const char *cmdName)
410 {
411  char path[MAXPGPATH];
412  struct stat buf;
413 
414  snprintf(path, sizeof(path), "%s/%s", dir, cmdName);
415 
416 #ifdef WIN32
417  /* Windows requires a .exe suffix for stat() */
418  if (strlen(path) <= strlen(EXE_EXT) ||
419  pg_strcasecmp(path + strlen(path) - strlen(EXE_EXT), EXE_EXT) != 0)
420  strlcat(path, EXE_EXT, sizeof(path));
421 #endif
422 
423  /*
424  * Ensure that the file exists and is a regular file.
425  */
426  if (stat(path, &buf) < 0)
427  pg_fatal("check for \"%s\" failed: %s\n",
428  path, strerror(errno));
429  else if (!S_ISREG(buf.st_mode))
430  pg_fatal("check for \"%s\" failed: not a regular file\n",
431  path);
432 
433  /*
434  * Ensure that the file is both executable and readable (required for
435  * dynamic loading).
436  */
437 #ifndef WIN32
438  if (access(path, R_OK) != 0)
439 #else
440  if ((buf.st_mode & S_IRUSR) == 0)
441 #endif
442  pg_fatal("check for \"%s\" failed: cannot read file (permission denied)\n",
443  path);
444 
445 #ifndef WIN32
446  if (access(path, X_OK) != 0)
447 #else
448  if ((buf.st_mode & S_IXUSR) == 0)
449 #endif
450  pg_fatal("check for \"%s\" failed: cannot execute (permission denied)\n",
451  path);
452 }
uint32 get_major_server_version(ClusterInfo *cluster)
Definition: server.c:158
static void check_bin_dir(ClusterInfo *cluster)
Definition: exec.c:366
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:219
static char * log_file
Definition: pg_ctl.c:88
#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:57
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:57
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:299
#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:409
void verify_directories(void)
Definition: exec.c:250
#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:328
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