Header And Logo

PostgreSQL
| The world's most advanced open source database.

exec.c

Go to the documentation of this file.
00001 /*
00002  *  exec.c
00003  *
00004  *  execution functions
00005  *
00006  *  Copyright (c) 2010-2013, PostgreSQL Global Development Group
00007  *  contrib/pg_upgrade/exec.c
00008  */
00009 
00010 #include "postgres_fe.h"
00011 
00012 #include "pg_upgrade.h"
00013 
00014 #include <fcntl.h>
00015 #include <unistd.h>
00016 #include <sys/types.h>
00017 
00018 static void check_data_dir(const char *pg_data);
00019 static void check_bin_dir(ClusterInfo *cluster);
00020 static void validate_exec(const char *dir, const char *cmdName);
00021 
00022 #ifdef WIN32
00023 static int  win32_check_directory_write_permissions(void);
00024 #endif
00025 
00026 
00027 /*
00028  * exec_prog()
00029  *      Execute an external program with stdout/stderr redirected, and report
00030  *      errors
00031  *
00032  * Formats a command from the given argument list, logs it to the log file,
00033  * and attempts to execute that command.  If the command executes
00034  * successfully, exec_prog() returns true.
00035  *
00036  * If the command fails, an error message is saved to the specified log_file.
00037  * If throw_error is true, this raises a PG_FATAL error and pg_upgrade
00038  * terminates; otherwise it is just reported as PG_REPORT and exec_prog()
00039  * returns false.
00040  */
00041 bool
00042 exec_prog(const char *log_file, const char *opt_log_file,
00043           bool throw_error, const char *fmt,...)
00044 {
00045     int         result;
00046     int         written;
00047 #define MAXCMDLEN (2 * MAXPGPATH)
00048     char        cmd[MAXCMDLEN];
00049     mode_t      old_umask = 0;
00050     FILE       *log;
00051     va_list     ap;
00052 
00053     old_umask = umask(S_IRWXG | S_IRWXO);
00054 
00055     written = strlcpy(cmd, SYSTEMQUOTE, sizeof(cmd));
00056     va_start(ap, fmt);
00057     written += vsnprintf(cmd + written, MAXCMDLEN - written, fmt, ap);
00058     va_end(ap);
00059     if (written >= MAXCMDLEN)
00060         pg_log(PG_FATAL, "command too long\n");
00061     written += snprintf(cmd + written, MAXCMDLEN - written,
00062                         " >> \"%s\" 2>&1" SYSTEMQUOTE, log_file);
00063     if (written >= MAXCMDLEN)
00064         pg_log(PG_FATAL, "command too long\n");
00065 
00066     log = fopen_priv(log_file, "a");
00067 
00068 #ifdef WIN32
00069     {
00070         /* 
00071          * "pg_ctl -w stop" might have reported that the server has
00072          * stopped because the postmaster.pid file has been removed,
00073          * but "pg_ctl -w start" might still be in the process of
00074          * closing and might still be holding its stdout and -l log
00075          * file descriptors open.  Therefore, try to open the log 
00076          * file a few more times.
00077          */
00078         int iter;
00079         for (iter = 0; iter < 4 && log == NULL; iter++)
00080         {
00081             sleep(1);
00082             log = fopen_priv(log_file, "a");
00083         }
00084     }
00085 #endif
00086 
00087     if (log == NULL)
00088         pg_log(PG_FATAL, "cannot write to log file %s\n", log_file);
00089 #ifdef WIN32
00090     fprintf(log, "\n\n");
00091 #endif
00092     pg_log(PG_VERBOSE, "%s\n", cmd);
00093     fprintf(log, "command: %s\n", cmd);
00094 
00095     /*
00096      * In Windows, we must close the log file at this point so the file is not
00097      * open while the command is running, or we get a share violation.
00098      */
00099     fclose(log);
00100 
00101     result = system(cmd);
00102 
00103     umask(old_umask);
00104 
00105     if (result != 0)
00106     {
00107         /* we might be in on a progress status line, so go to the next line */
00108         report_status(PG_REPORT, "\n*failure*");
00109         fflush(stdout);
00110 
00111         pg_log(PG_VERBOSE, "There were problems executing \"%s\"\n", cmd);
00112         if (opt_log_file)
00113             pg_log(throw_error ? PG_FATAL : PG_REPORT,
00114                    "Consult the last few lines of \"%s\" or \"%s\" for\n"
00115                    "the probable cause of the failure.\n",
00116                    log_file, opt_log_file);
00117         else
00118             pg_log(throw_error ? PG_FATAL : PG_REPORT,
00119                    "Consult the last few lines of \"%s\" for\n"
00120                    "the probable cause of the failure.\n",
00121                    log_file);
00122     }
00123 
00124 #ifndef WIN32
00125     /* 
00126      *  We can't do this on Windows because it will keep the "pg_ctl start"
00127      *  output filename open until the server stops, so we do the \n\n above
00128      *  on that platform.  We use a unique filename for "pg_ctl start" that is
00129      *  never reused while the server is running, so it works fine.  We could
00130      *  log these commands to a third file, but that just adds complexity.
00131      */
00132     if ((log = fopen_priv(log_file, "a")) == NULL)
00133         pg_log(PG_FATAL, "cannot write to log file %s\n", log_file);
00134     fprintf(log, "\n\n");
00135     fclose(log);
00136 #endif
00137 
00138     return result == 0;
00139 }
00140 
00141 
00142 /*
00143  * pid_lock_file_exists()
00144  *
00145  * Checks whether the postmaster.pid file exists.
00146  */
00147 bool
00148 pid_lock_file_exists(const char *datadir)
00149 {
00150     char        path[MAXPGPATH];
00151     int         fd;
00152 
00153     snprintf(path, sizeof(path), "%s/postmaster.pid", datadir);
00154 
00155     if ((fd = open(path, O_RDONLY, 0)) < 0)
00156     {
00157         /* ENOTDIR means we will throw a more useful error later */
00158         if (errno != ENOENT && errno != ENOTDIR)
00159             pg_log(PG_FATAL, "could not open file \"%s\" for reading: %s\n",
00160                    path, getErrorText(errno));
00161 
00162         return false;
00163     }
00164 
00165     close(fd);
00166     return true;
00167 }
00168 
00169 
00170 /*
00171  * verify_directories()
00172  *
00173  * does all the hectic work of verifying directories and executables
00174  * of old and new server.
00175  *
00176  * NOTE: May update the values of all parameters
00177  */
00178 void
00179 verify_directories(void)
00180 {
00181 
00182 #ifndef WIN32
00183     if (access(".", R_OK | W_OK | X_OK) != 0)
00184 #else
00185     if (win32_check_directory_write_permissions() != 0)
00186 #endif
00187         pg_log(PG_FATAL,
00188           "You must have read and write access in the current directory.\n");
00189 
00190     check_bin_dir(&old_cluster);
00191     check_data_dir(old_cluster.pgdata);
00192     check_bin_dir(&new_cluster);
00193     check_data_dir(new_cluster.pgdata);
00194 }
00195 
00196 
00197 #ifdef WIN32
00198 /*
00199  * win32_check_directory_write_permissions()
00200  *
00201  *  access() on WIN32 can't check directory permissions, so we have to
00202  *  optionally create, then delete a file to check.
00203  *      http://msdn.microsoft.com/en-us/library/1w06ktdy%28v=vs.80%29.aspx
00204  */
00205 static int
00206 win32_check_directory_write_permissions(void)
00207 {
00208     int         fd;
00209 
00210     /*
00211      * We open a file we would normally create anyway.  We do this even in
00212      * 'check' mode, which isn't ideal, but this is the best we can do.
00213      */
00214     if ((fd = open(GLOBALS_DUMP_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0)
00215         return -1;
00216     close(fd);
00217 
00218     return unlink(GLOBALS_DUMP_FILE);
00219 }
00220 #endif
00221 
00222 
00223 /*
00224  * check_data_dir()
00225  *
00226  *  This function validates the given cluster directory - we search for a
00227  *  small set of subdirectories that we expect to find in a valid $PGDATA
00228  *  directory.  If any of the subdirectories are missing (or secured against
00229  *  us) we display an error message and exit()
00230  *
00231  */
00232 static void
00233 check_data_dir(const char *pg_data)
00234 {
00235     char        subDirName[MAXPGPATH];
00236     int         subdirnum;
00237 
00238     /* start check with top-most directory */
00239     const char *requiredSubdirs[] = {"", "base", "global", "pg_clog",
00240         "pg_multixact", "pg_subtrans", "pg_tblspc", "pg_twophase",
00241     "pg_xlog"};
00242 
00243     for (subdirnum = 0;
00244          subdirnum < sizeof(requiredSubdirs) / sizeof(requiredSubdirs[0]);
00245          ++subdirnum)
00246     {
00247         struct stat statBuf;
00248 
00249         snprintf(subDirName, sizeof(subDirName), "%s%s%s", pg_data,
00250         /* Win32 can't stat() a directory with a trailing slash. */
00251                  *requiredSubdirs[subdirnum] ? "/" : "",
00252                  requiredSubdirs[subdirnum]);
00253 
00254         if (stat(subDirName, &statBuf) != 0)
00255             report_status(PG_FATAL, "check for \"%s\" failed: %s\n",
00256                           subDirName, getErrorText(errno));
00257         else if (!S_ISDIR(statBuf.st_mode))
00258             report_status(PG_FATAL, "%s is not a directory\n",
00259                           subDirName);
00260     }
00261 }
00262 
00263 
00264 /*
00265  * check_bin_dir()
00266  *
00267  *  This function searches for the executables that we expect to find
00268  *  in the binaries directory.  If we find that a required executable
00269  *  is missing (or secured against us), we display an error message and
00270  *  exit().
00271  */
00272 static void
00273 check_bin_dir(ClusterInfo *cluster)
00274 {
00275     struct stat statBuf;
00276 
00277     /* check bindir */
00278     if (stat(cluster->bindir, &statBuf) != 0)
00279         report_status(PG_FATAL, "check for \"%s\" failed: %s\n",
00280                       cluster->bindir, getErrorText(errno));
00281     else if (!S_ISDIR(statBuf.st_mode))
00282         report_status(PG_FATAL, "%s is not a directory\n",
00283                       cluster->bindir);
00284 
00285     validate_exec(cluster->bindir, "postgres");
00286     validate_exec(cluster->bindir, "pg_ctl");
00287     validate_exec(cluster->bindir, "pg_resetxlog");
00288     if (cluster == &new_cluster)
00289     {
00290         /* these are only needed in the new cluster */
00291         validate_exec(cluster->bindir, "psql");
00292         validate_exec(cluster->bindir, "pg_dumpall");
00293     }
00294 }
00295 
00296 
00297 /*
00298  * validate_exec()
00299  *
00300  * validate "path" as an executable file
00301  */
00302 static void
00303 validate_exec(const char *dir, const char *cmdName)
00304 {
00305     char        path[MAXPGPATH];
00306     struct stat buf;
00307 
00308     snprintf(path, sizeof(path), "%s/%s", dir, cmdName);
00309 
00310 #ifdef WIN32
00311     /* Windows requires a .exe suffix for stat() */
00312     if (strlen(path) <= strlen(EXE_EXT) ||
00313         pg_strcasecmp(path + strlen(path) - strlen(EXE_EXT), EXE_EXT) != 0)
00314         strlcat(path, EXE_EXT, sizeof(path));
00315 #endif
00316 
00317     /*
00318      * Ensure that the file exists and is a regular file.
00319      */
00320     if (stat(path, &buf) < 0)
00321         pg_log(PG_FATAL, "check for \"%s\" failed: %s\n",
00322                path, getErrorText(errno));
00323     else if (!S_ISREG(buf.st_mode))
00324         pg_log(PG_FATAL, "check for \"%s\" failed: not an executable file\n",
00325                path);
00326 
00327     /*
00328      * Ensure that the file is both executable and readable (required for
00329      * dynamic loading).
00330      */
00331 #ifndef WIN32
00332     if (access(path, R_OK) != 0)
00333 #else
00334     if ((buf.st_mode & S_IRUSR) == 0)
00335 #endif
00336         pg_log(PG_FATAL, "check for \"%s\" failed: cannot read file (permission denied)\n",
00337                path);
00338 
00339 #ifndef WIN32
00340     if (access(path, X_OK) != 0)
00341 #else
00342     if ((buf.st_mode & S_IXUSR) == 0)
00343 #endif
00344         pg_log(PG_FATAL, "check for \"%s\" failed: cannot execute (permission denied)\n",
00345                path);
00346 }