1 /*
2 * exec.c
3 *
4 * execution functions
5 *
6 * Copyright (c) 2010-2016, 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(const char *pg_data);
18 static void check_bin_dir(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 * exec_prog()
28 * Execute an external program with stdout/stderr redirected, and report
29 * errors
30 *
31 * Formats a command from the given argument list, logs it to the log file,
32 * and attempts to execute that command. If the command executes
33 * successfully, exec_prog() returns true.
34 *
35 * If the command fails, an error message is saved to the specified log_file.
36 * If throw_error is true, this raises a PG_FATAL error and pg_upgrade
37 * terminates; otherwise it is just reported as PG_REPORT and exec_prog()
38 * returns false.
39 *
40 * The code requires it be called first from the primary thread on Windows.
41 */
42 bool
exec_prog(const char * log_file,const char * opt_log_file,bool throw_error,const char * fmt,...)43 exec_prog(const char *log_file, const char *opt_log_file,
44 bool throw_error, const char *fmt,...)
45 {
46 int result = 0;
47 int written;
48
49 #define MAXCMDLEN (2 * MAXPGPATH)
50 char cmd[MAXCMDLEN];
51 FILE *log;
52 va_list ap;
53
54 #ifdef WIN32
55 static DWORD mainThreadId = 0;
56
57 /* We assume we are called from the primary thread first */
58 if (mainThreadId == 0)
59 mainThreadId = GetCurrentThreadId();
60 #endif
61
62 written = 0;
63 va_start(ap, fmt);
64 written += vsnprintf(cmd + written, MAXCMDLEN - written, fmt, ap);
65 va_end(ap);
66 if (written >= MAXCMDLEN)
67 pg_fatal("command too long\n");
68 written += snprintf(cmd + written, MAXCMDLEN - written,
69 " >> \"%s\" 2>&1", log_file);
70 if (written >= MAXCMDLEN)
71 pg_fatal("command too long\n");
72
73 pg_log(PG_VERBOSE, "%s\n", cmd);
74
75 #ifdef WIN32
76 /*
77 * For some reason, Windows issues a file-in-use error if we write data to
78 * the log file from a non-primary thread just before we create a
79 * subprocess that also writes to the same log file. One fix is to sleep
80 * for 100ms. A cleaner fix is to write to the log file _after_ the
81 * subprocess has completed, so we do this only when writing from a
82 * non-primary thread. fflush(), running system() twice, and pre-creating
83 * the file do not see to help.
84 */
85 if (mainThreadId != GetCurrentThreadId())
86 result = system(cmd);
87 #endif
88
89 log = fopen(log_file, "a");
90
91 #ifdef WIN32
92 {
93 /*
94 * "pg_ctl -w stop" might have reported that the server has stopped
95 * because the postmaster.pid file has been removed, but "pg_ctl -w
96 * start" might still be in the process of closing and might still be
97 * holding its stdout and -l log file descriptors open. Therefore,
98 * try to open the log file a few more times.
99 */
100 int iter;
101
102 for (iter = 0; iter < 4 && log == NULL; iter++)
103 {
104 pg_usleep(1000000); /* 1 sec */
105 log = fopen(log_file, "a");
106 }
107 }
108 #endif
109
110 if (log == NULL)
111 pg_fatal("cannot write to log file %s\n", log_file);
112
113 #ifdef WIN32
114 /* Are we printing "command:" before its output? */
115 if (mainThreadId == GetCurrentThreadId())
116 fprintf(log, "\n\n");
117 #endif
118 fprintf(log, "command: %s\n", cmd);
119 #ifdef WIN32
120 /* Are we printing "command:" after its output? */
121 if (mainThreadId != GetCurrentThreadId())
122 fprintf(log, "\n\n");
123 #endif
124
125 /*
126 * In Windows, we must close the log file at this point so the file is not
127 * open while the command is running, or we get a share violation.
128 */
129 fclose(log);
130
131 #ifdef WIN32
132 /* see comment above */
133 if (mainThreadId == GetCurrentThreadId())
134 #endif
135 result = system(cmd);
136
137 if (result != 0)
138 {
139 /* we might be in on a progress status line, so go to the next line */
140 report_status(PG_REPORT, "\n*failure*");
141 fflush(stdout);
142
143 pg_log(PG_VERBOSE, "There were problems executing \"%s\"\n", cmd);
144 if (opt_log_file)
145 pg_log(throw_error ? PG_FATAL : PG_REPORT,
146 "Consult the last few lines of \"%s\" or \"%s\" for\n"
147 "the probable cause of the failure.\n",
148 log_file, opt_log_file);
149 else
150 pg_log(throw_error ? PG_FATAL : PG_REPORT,
151 "Consult the last few lines of \"%s\" for\n"
152 "the probable cause of the failure.\n",
153 log_file);
154 }
155
156 #ifndef WIN32
157 /*
158 * We can't do this on Windows because it will keep the "pg_ctl start"
159 * output filename open until the server stops, so we do the \n\n above on
160 * that platform. We use a unique filename for "pg_ctl start" that is
161 * never reused while the server is running, so it works fine. We could
162 * log these commands to a third file, but that just adds complexity.
163 */
164 if ((log = fopen(log_file, "a")) == NULL)
165 pg_fatal("cannot write to log file %s\n", log_file);
166 fprintf(log, "\n\n");
167 fclose(log);
168 #endif
169
170 return result == 0;
171 }
172
173
174 /*
175 * pid_lock_file_exists()
176 *
177 * Checks whether the postmaster.pid file exists.
178 */
179 bool
pid_lock_file_exists(const char * datadir)180 pid_lock_file_exists(const char *datadir)
181 {
182 char path[MAXPGPATH];
183 int fd;
184
185 snprintf(path, sizeof(path), "%s/postmaster.pid", datadir);
186
187 if ((fd = open(path, O_RDONLY, 0)) < 0)
188 {
189 /* ENOTDIR means we will throw a more useful error later */
190 if (errno != ENOENT && errno != ENOTDIR)
191 pg_fatal("could not open file \"%s\" for reading: %s\n",
192 path, strerror(errno));
193
194 return false;
195 }
196
197 close(fd);
198 return true;
199 }
200
201
202 /*
203 * verify_directories()
204 *
205 * does all the hectic work of verifying directories and executables
206 * of old and new server.
207 *
208 * NOTE: May update the values of all parameters
209 */
210 void
verify_directories(void)211 verify_directories(void)
212 {
213 #ifndef WIN32
214 if (access(".", R_OK | W_OK | X_OK) != 0)
215 #else
216 if (win32_check_directory_write_permissions() != 0)
217 #endif
218 pg_fatal("You must have read and write access in the current directory.\n");
219
220 check_bin_dir(&old_cluster);
221 check_data_dir(old_cluster.pgdata);
222 check_bin_dir(&new_cluster);
223 check_data_dir(new_cluster.pgdata);
224 }
225
226
227 #ifdef WIN32
228 /*
229 * win32_check_directory_write_permissions()
230 *
231 * access() on WIN32 can't check directory permissions, so we have to
232 * optionally create, then delete a file to check.
233 * http://msdn.microsoft.com/en-us/library/1w06ktdy%28v=vs.80%29.aspx
234 */
235 static int
win32_check_directory_write_permissions(void)236 win32_check_directory_write_permissions(void)
237 {
238 int fd;
239
240 /*
241 * We open a file we would normally create anyway. We do this even in
242 * 'check' mode, which isn't ideal, but this is the best we can do.
243 */
244 if ((fd = open(GLOBALS_DUMP_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0)
245 return -1;
246 close(fd);
247
248 return unlink(GLOBALS_DUMP_FILE);
249 }
250 #endif
251
252
253 /*
254 * check_data_dir()
255 *
256 * This function validates the given cluster directory - we search for a
257 * small set of subdirectories that we expect to find in a valid $PGDATA
258 * directory. If any of the subdirectories are missing (or secured against
259 * us) we display an error message and exit()
260 *
261 */
262 static void
check_data_dir(const char * pg_data)263 check_data_dir(const char *pg_data)
264 {
265 char subDirName[MAXPGPATH];
266 int subdirnum;
267
268 /* start check with top-most directory */
269 const char *requiredSubdirs[] = {"", "base", "global", "pg_clog",
270 "pg_multixact", "pg_subtrans", "pg_tblspc", "pg_twophase",
271 "pg_xlog"};
272
273 for (subdirnum = 0;
274 subdirnum < sizeof(requiredSubdirs) / sizeof(requiredSubdirs[0]);
275 ++subdirnum)
276 {
277 struct stat statBuf;
278
279 snprintf(subDirName, sizeof(subDirName), "%s%s%s", pg_data,
280 /* Win32 can't stat() a directory with a trailing slash. */
281 *requiredSubdirs[subdirnum] ? "/" : "",
282 requiredSubdirs[subdirnum]);
283
284 if (stat(subDirName, &statBuf) != 0)
285 report_status(PG_FATAL, "check for \"%s\" failed: %s\n",
286 subDirName, strerror(errno));
287 else if (!S_ISDIR(statBuf.st_mode))
288 report_status(PG_FATAL, "%s is not a directory\n",
289 subDirName);
290 }
291 }
292
293
294 /*
295 * check_bin_dir()
296 *
297 * This function searches for the executables that we expect to find
298 * in the binaries directory. If we find that a required executable
299 * is missing (or secured against us), we display an error message and
300 * exit().
301 */
302 static void
check_bin_dir(ClusterInfo * cluster)303 check_bin_dir(ClusterInfo *cluster)
304 {
305 struct stat statBuf;
306
307 /* check bindir */
308 if (stat(cluster->bindir, &statBuf) != 0)
309 report_status(PG_FATAL, "check for \"%s\" failed: %s\n",
310 cluster->bindir, strerror(errno));
311 else if (!S_ISDIR(statBuf.st_mode))
312 report_status(PG_FATAL, "%s is not a directory\n",
313 cluster->bindir);
314
315 validate_exec(cluster->bindir, "postgres");
316 validate_exec(cluster->bindir, "pg_ctl");
317 validate_exec(cluster->bindir, "pg_resetxlog");
318 if (cluster == &new_cluster)
319 {
320 /* these are only needed in the new cluster */
321 validate_exec(cluster->bindir, "psql");
322 validate_exec(cluster->bindir, "pg_dump");
323 validate_exec(cluster->bindir, "pg_dumpall");
324 }
325 }
326
327
328 /*
329 * validate_exec()
330 *
331 * validate "path" as an executable file
332 */
333 static void
validate_exec(const char * dir,const char * cmdName)334 validate_exec(const char *dir, const char *cmdName)
335 {
336 char path[MAXPGPATH];
337 struct stat buf;
338
339 snprintf(path, sizeof(path), "%s/%s", dir, cmdName);
340
341 #ifdef WIN32
342 /* Windows requires a .exe suffix for stat() */
343 if (strlen(path) <= strlen(EXE_EXT) ||
344 pg_strcasecmp(path + strlen(path) - strlen(EXE_EXT), EXE_EXT) != 0)
345 strlcat(path, EXE_EXT, sizeof(path));
346 #endif
347
348 /*
349 * Ensure that the file exists and is a regular file.
350 */
351 if (stat(path, &buf) < 0)
352 pg_fatal("check for \"%s\" failed: %s\n",
353 path, strerror(errno));
354 else if (!S_ISREG(buf.st_mode))
355 pg_fatal("check for \"%s\" failed: not an executable file\n",
356 path);
357
358 /*
359 * Ensure that the file is both executable and readable (required for
360 * dynamic loading).
361 */
362 #ifndef WIN32
363 if (access(path, R_OK) != 0)
364 #else
365 if ((buf.st_mode & S_IRUSR) == 0)
366 #endif
367 pg_fatal("check for \"%s\" failed: cannot read file (permission denied)\n",
368 path);
369
370 #ifndef WIN32
371 if (access(path, X_OK) != 0)
372 #else
373 if ((buf.st_mode & S_IXUSR) == 0)
374 #endif
375 pg_fatal("check for \"%s\" failed: cannot execute (permission denied)\n",
376 path);
377 }
378