]> granicus.if.org Git - postgresql/blob - contrib/pg_upgrade/exec.c
In pg_upgrade, document why we can't issue \n\n in the command logfile
[postgresql] / contrib / pg_upgrade / exec.c
1 /*
2  *      exec.c
3  *
4  *      execution functions
5  *
6  *      Copyright (c) 2010-2012, PostgreSQL Global Development Group
7  *      contrib/pg_upgrade/exec.c
8  */
9
10 #include "postgres.h"
11
12 #include "pg_upgrade.h"
13
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <sys/types.h>
17
18 static void check_data_dir(const char *pg_data);
19 static void check_bin_dir(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  * exec_prog()
29  *              Execute an external program with stdout/stderr redirected, and report
30  *              errors
31  *
32  * Formats a command from the given argument list, logs it to the log file,
33  * and attempts to execute that command.  If the command executes
34  * successfully, exec_prog() returns true.
35  *
36  * If the command fails, an error message is saved to the specified log_file.
37  * If throw_error is true, this raises a PG_FATAL error and pg_upgrade
38  * terminates; otherwise it is just reported as PG_REPORT and exec_prog()
39  * returns false.
40  */
41 bool
42 exec_prog(const char *log_file, const char *opt_log_file,
43                   bool throw_error, const char *fmt,...)
44 {
45         int                     result;
46         int                     written;
47 #define MAXCMDLEN (2 * MAXPGPATH)
48         char            cmd[MAXCMDLEN];
49         mode_t          old_umask = 0;
50         FILE       *log;
51         va_list         ap;
52
53         old_umask = umask(S_IRWXG | S_IRWXO);
54
55         written = strlcpy(cmd, SYSTEMQUOTE, sizeof(cmd));
56         va_start(ap, fmt);
57         written += vsnprintf(cmd + written, MAXCMDLEN - written, fmt, ap);
58         va_end(ap);
59         if (written >= MAXCMDLEN)
60                 pg_log(PG_FATAL, "command too long\n");
61         written += snprintf(cmd + written, MAXCMDLEN - written,
62                                                 " >> \"%s\" 2>&1" SYSTEMQUOTE, log_file);
63         if (written >= MAXCMDLEN)
64                 pg_log(PG_FATAL, "command too long\n");
65
66         if ((log = fopen_priv(log_file, "a")) == NULL)
67                 pg_log(PG_FATAL, "cannot write to log file %s\n", log_file);
68 #ifdef WIN32
69         fprintf(log, "\n\n");
70 #endif
71         pg_log(PG_VERBOSE, "%s\n", cmd);
72         fprintf(log, "command: %s\n", cmd);
73
74         /*
75          * In Windows, we must close the log file at this point so the file is not
76          * open while the command is running, or we get a share violation.
77          */
78         fclose(log);
79
80         result = system(cmd);
81
82         umask(old_umask);
83
84         if (result != 0)
85         {
86                 report_status(PG_REPORT, "*failure*");
87                 fflush(stdout);
88                 pg_log(PG_VERBOSE, "There were problems executing \"%s\"\n", cmd);
89                 if (opt_log_file)
90                         pg_log(throw_error ? PG_FATAL : PG_REPORT,
91                                    "Consult the last few lines of \"%s\" or \"%s\" for\n"
92                                    "the probable cause of the failure.\n",
93                                    log_file, opt_log_file);
94                 else
95                         pg_log(throw_error ? PG_FATAL : PG_REPORT,
96                                    "Consult the last few lines of \"%s\" for\n"
97                                    "the probable cause of the failure.\n",
98                                    log_file);
99         }
100
101 #ifndef WIN32
102         /* 
103          *      We can't do this on Windows because it will keep the "pg_ctl start"
104          *      output filename open until the server stops, so we do the \n\n above
105          *      on that platform.  We use a unique filename for "pg_ctl start" that is
106          *      never reused while the server is running, so it works fine.  We could
107          *      log these commands to a third file, but that just adds complexity.
108          */
109         if ((log = fopen_priv(log_file, "a")) == NULL)
110                 pg_log(PG_FATAL, "cannot write to log file %s\n", log_file);
111         fprintf(log, "\n\n");
112         fclose(log);
113 #endif
114
115         return result == 0;
116 }
117
118
119 /*
120  * is_server_running()
121  *
122  * checks whether postmaster on the given data directory is running or not.
123  * The check is performed by looking for the existence of postmaster.pid file.
124  */
125 bool
126 is_server_running(const char *datadir)
127 {
128         char            path[MAXPGPATH];
129         int                     fd;
130
131         snprintf(path, sizeof(path), "%s/postmaster.pid", datadir);
132
133         if ((fd = open(path, O_RDONLY, 0)) < 0)
134         {
135                 /* ENOTDIR means we will throw a more useful error later */
136                 if (errno != ENOENT && errno != ENOTDIR)
137                         pg_log(PG_FATAL, "could not open file \"%s\" for reading: %s\n",
138                                    path, getErrorText(errno));
139
140                 return false;
141         }
142
143         close(fd);
144         return true;
145 }
146
147
148 /*
149  * verify_directories()
150  *
151  * does all the hectic work of verifying directories and executables
152  * of old and new server.
153  *
154  * NOTE: May update the values of all parameters
155  */
156 void
157 verify_directories(void)
158 {
159
160         prep_status("Checking current, bin, and data directories");
161
162 #ifndef WIN32
163         if (access(".", R_OK | W_OK | X_OK) != 0)
164 #else
165         if (win32_check_directory_write_permissions() != 0)
166 #endif
167                 pg_log(PG_FATAL,
168                   "You must have read and write access in the current directory.\n");
169
170         check_bin_dir(&old_cluster);
171         check_data_dir(old_cluster.pgdata);
172         check_bin_dir(&new_cluster);
173         check_data_dir(new_cluster.pgdata);
174         check_ok();
175 }
176
177
178 #ifdef WIN32
179 /*
180  * win32_check_directory_write_permissions()
181  *
182  *      access() on WIN32 can't check directory permissions, so we have to
183  *      optionally create, then delete a file to check.
184  *              http://msdn.microsoft.com/en-us/library/1w06ktdy%28v=vs.80%29.aspx
185  */
186 static int
187 win32_check_directory_write_permissions(void)
188 {
189         int                     fd;
190
191         /*
192          * We open a file we would normally create anyway.      We do this even in
193          * 'check' mode, which isn't ideal, but this is the best we can do.
194          */
195         if ((fd = open(GLOBALS_DUMP_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0)
196                 return -1;
197         close(fd);
198
199         return unlink(GLOBALS_DUMP_FILE);
200 }
201 #endif
202
203
204 /*
205  * check_data_dir()
206  *
207  *      This function validates the given cluster directory - we search for a
208  *      small set of subdirectories that we expect to find in a valid $PGDATA
209  *      directory.      If any of the subdirectories are missing (or secured against
210  *      us) we display an error message and exit()
211  *
212  */
213 static void
214 check_data_dir(const char *pg_data)
215 {
216         char            subDirName[MAXPGPATH];
217         int                     subdirnum;
218
219         /* start check with top-most directory */
220         const char *requiredSubdirs[] = {"", "base", "global", "pg_clog",
221                 "pg_multixact", "pg_subtrans", "pg_tblspc", "pg_twophase",
222         "pg_xlog"};
223
224         for (subdirnum = 0;
225                  subdirnum < sizeof(requiredSubdirs) / sizeof(requiredSubdirs[0]);
226                  ++subdirnum)
227         {
228                 struct stat statBuf;
229
230                 snprintf(subDirName, sizeof(subDirName), "%s%s%s", pg_data,
231                 /* Win32 can't stat() a directory with a trailing slash. */
232                                  *requiredSubdirs[subdirnum] ? "/" : "",
233                                  requiredSubdirs[subdirnum]);
234
235                 if (stat(subDirName, &statBuf) != 0)
236                         report_status(PG_FATAL, "check for \"%s\" failed: %s\n",
237                                                   subDirName, getErrorText(errno));
238                 else if (!S_ISDIR(statBuf.st_mode))
239                         report_status(PG_FATAL, "%s is not a directory\n",
240                                                   subDirName);
241         }
242 }
243
244
245 /*
246  * check_bin_dir()
247  *
248  *      This function searches for the executables that we expect to find
249  *      in the binaries directory.      If we find that a required executable
250  *      is missing (or secured against us), we display an error message and
251  *      exit().
252  */
253 static void
254 check_bin_dir(ClusterInfo *cluster)
255 {
256         struct stat statBuf;
257
258         /* check bindir */
259         if (stat(cluster->bindir, &statBuf) != 0)
260                 report_status(PG_FATAL, "check for \"%s\" failed: %s\n",
261                                           cluster->bindir, getErrorText(errno));
262         else if (!S_ISDIR(statBuf.st_mode))
263                 report_status(PG_FATAL, "%s is not a directory\n",
264                                           cluster->bindir);
265
266         validate_exec(cluster->bindir, "postgres");
267         validate_exec(cluster->bindir, "pg_ctl");
268         validate_exec(cluster->bindir, "pg_resetxlog");
269         if (cluster == &new_cluster)
270         {
271                 /* these are only needed in the new cluster */
272                 validate_exec(cluster->bindir, "pg_config");
273                 validate_exec(cluster->bindir, "psql");
274                 validate_exec(cluster->bindir, "pg_dumpall");
275         }
276 }
277
278
279 /*
280  * validate_exec()
281  *
282  * validate "path" as an executable file
283  */
284 static void
285 validate_exec(const char *dir, const char *cmdName)
286 {
287         char            path[MAXPGPATH];
288         struct stat buf;
289
290         snprintf(path, sizeof(path), "%s/%s", dir, cmdName);
291
292 #ifdef WIN32
293         /* Windows requires a .exe suffix for stat() */
294         if (strlen(path) <= strlen(EXE_EXT) ||
295                 pg_strcasecmp(path + strlen(path) - strlen(EXE_EXT), EXE_EXT) != 0)
296                 strlcat(path, EXE_EXT, sizeof(path));
297 #endif
298
299         /*
300          * Ensure that the file exists and is a regular file.
301          */
302         if (stat(path, &buf) < 0)
303                 pg_log(PG_FATAL, "check for \"%s\" failed: %s\n",
304                            path, getErrorText(errno));
305         else if (!S_ISREG(buf.st_mode))
306                 pg_log(PG_FATAL, "check for \"%s\" failed: not an executable file\n",
307                            path);
308
309         /*
310          * Ensure that the file is both executable and readable (required for
311          * dynamic loading).
312          */
313 #ifndef WIN32
314         if (access(path, R_OK) != 0)
315 #else
316         if ((buf.st_mode & S_IRUSR) == 0)
317 #endif
318                 pg_log(PG_FATAL, "check for \"%s\" failed: cannot read file (permission denied)\n",
319                            path);
320
321 #ifndef WIN32
322         if (access(path, X_OK) != 0)
323 #else
324         if ((buf.st_mode & S_IXUSR) == 0)
325 #endif
326                 pg_log(PG_FATAL, "check for \"%s\" failed: cannot execute (permission denied)\n",
327                            path);
328 }