00001
00002
00003
00004
00005
00006
00007
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
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
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
00072
00073
00074
00075
00076
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
00097
00098
00099 fclose(log);
00100
00101 result = system(cmd);
00102
00103 umask(old_umask);
00104
00105 if (result != 0)
00106 {
00107
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
00127
00128
00129
00130
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
00144
00145
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
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
00172
00173
00174
00175
00176
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
00200
00201
00202
00203
00204
00205 static int
00206 win32_check_directory_write_permissions(void)
00207 {
00208 int fd;
00209
00210
00211
00212
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
00225
00226
00227
00228
00229
00230
00231
00232 static void
00233 check_data_dir(const char *pg_data)
00234 {
00235 char subDirName[MAXPGPATH];
00236 int subdirnum;
00237
00238
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
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
00266
00267
00268
00269
00270
00271
00272 static void
00273 check_bin_dir(ClusterInfo *cluster)
00274 {
00275 struct stat statBuf;
00276
00277
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
00291 validate_exec(cluster->bindir, "psql");
00292 validate_exec(cluster->bindir, "pg_dumpall");
00293 }
00294 }
00295
00296
00297
00298
00299
00300
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
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
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
00329
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 }