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