*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.577 2009/04/05 04:19:58 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.578 2009/05/02 22:02:37 tgl Exp $
*
* NOTES
*
/*
* postmaster.c - function prototypes
*/
+static void getInstallationPaths(const char *argv0);
static void checkDataDir(void);
#ifdef USE_BONJOUR
ALLOCSET_DEFAULT_MAXSIZE);
MemoryContextSwitchTo(PostmasterContext);
- if (find_my_exec(argv[0], my_exec_path) < 0)
- elog(FATAL, "%s: could not locate my own executable path",
- argv[0]);
-
- get_pkglib_path(my_exec_path, pkglib_path);
+ /* Initialize paths to installation files */
+ getInstallationPaths(argv[0]);
/*
* Options setup
ExitPostmaster(1);
}
-#ifdef EXEC_BACKEND
- /* Locate executable backend before we change working directory */
- if (find_other_exec(argv[0], "postgres", PG_BACKEND_VERSIONSTR,
- postgres_exec_path) < 0)
- ereport(FATAL,
- (errmsg("%s: could not locate matching postgres executable",
- progname)));
-#endif
-
/*
* Locate the proper configuration files and data directory, and read
* postgresql.conf for the first time.
}
+/*
+ * Compute and check the directory paths to files that are part of the
+ * installation (as deduced from the postgres executable's own location)
+ */
+static void
+getInstallationPaths(const char *argv0)
+{
+ DIR *pdir;
+
+ /* Locate the postgres executable itself */
+ if (find_my_exec(argv0, my_exec_path) < 0)
+ elog(FATAL, "%s: could not locate my own executable path", argv0);
+
+#ifdef EXEC_BACKEND
+ /* Locate executable backend before we change working directory */
+ if (find_other_exec(argv0, "postgres", PG_BACKEND_VERSIONSTR,
+ postgres_exec_path) < 0)
+ ereport(FATAL,
+ (errmsg("%s: could not locate matching postgres executable",
+ argv0)));
+#endif
+
+ /*
+ * Locate the pkglib directory --- this has to be set early in case we try
+ * to load any modules from it in response to postgresql.conf entries.
+ */
+ get_pkglib_path(my_exec_path, pkglib_path);
+
+ /*
+ * Verify that there's a readable directory there; otherwise the
+ * Postgres installation is incomplete or corrupt. (A typical cause
+ * of this failure is that the postgres executable has been moved or
+ * hardlinked to some directory that's not a sibling of the installation
+ * lib/ directory.)
+ */
+ pdir = AllocateDir(pkglib_path);
+ if (pdir == NULL)
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not open directory \"%s\": %m",
+ pkglib_path),
+ errhint("This may indicate an incomplete PostgreSQL installation, or that the file \"%s\" has been moved away from its proper location.",
+ my_exec_path)));
+ FreeDir(pdir);
+
+ /*
+ * XXX is it worth similarly checking the share/ directory? If the
+ * lib/ directory is there, then share/ probably is too.
+ */
+}
+
+
/*
* Validate the proposed data directory
*/
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/misc/tzparser.c,v 1.7 2009/01/01 17:23:53 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/misc/tzparser.c,v 1.8 2009/05/02 22:02:37 tgl Exp $
*
*-------------------------------------------------------------------------
*/
tzFile = AllocateFile(file_path, "r");
if (!tzFile)
{
- /* at level 0, if file doesn't exist, guc.c's complaint is enough */
+ /*
+ * Check to see if the problem is not the filename but the directory.
+ * This is worth troubling over because if the installation share/
+ * directory is missing or unreadable, this is likely to be the first
+ * place we notice a problem during postmaster startup.
+ */
+ int save_errno = errno;
+ DIR *tzdir;
+
+ snprintf(file_path, sizeof(file_path), "%s/timezonesets",
+ share_path);
+ tzdir = AllocateDir(file_path);
+ if (tzdir == NULL)
+ {
+ ereport(tz_elevel,
+ (errcode_for_file_access(),
+ errmsg("could not open directory \"%s\": %m",
+ file_path),
+ errhint("This may indicate an incomplete PostgreSQL installation, or that the file \"%s\" has been moved away from its proper location.",
+ my_exec_path)));
+ return -1;
+ }
+ FreeDir(tzdir);
+ errno = save_errno;
+
+ /*
+ * otherwise, if file doesn't exist and it's level 0, guc.c's
+ * complaint is enough
+ */
if (errno != ENOENT || depth > 0)
ereport(tz_elevel,
(errcode_for_file_access(),
errmsg("could not read time zone file \"%s\": %m",
filename)));
+
return -1;
}