diff --git a/contrib/dbsize/dbsize.c b/contrib/dbsize/dbsize.c
index afa1937145c52af55114d08186aac01c3ee81bb2..903de97b3740f850c8ac3bd3af693040e57dfd30 100644
--- a/contrib/dbsize/dbsize.c
+++ b/contrib/dbsize/dbsize.c
@@ -5,7 +5,7 @@
  * Copyright (c) 2002-2005, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/contrib/dbsize/dbsize.c,v 1.17 2005/05/27 00:57:48 neilc Exp $
+ *	  $PostgreSQL: pgsql/contrib/dbsize/dbsize.c,v 1.18 2005/06/19 21:34:00 tgl Exp $
  *
  */
 
@@ -58,7 +58,7 @@ db_dir_size(const char *path)
 	if (!dirdesc)
 	    return 0;
 
-	while ((direntry = readdir(dirdesc)) != NULL)
+	while ((direntry = ReadDir(dirdesc, path)) != NULL)
 	{
 	    struct stat fst;
 
@@ -97,13 +97,8 @@ calculate_database_size(Oid dbOid)
 	/* Scan the non-default tablespaces */
 	snprintf(pathname, MAXPGPATH, "%s/pg_tblspc", DataDir);
 	dirdesc = AllocateDir(pathname);
-	if (!dirdesc)
-	    ereport(ERROR,
-				(errcode_for_file_access(),
-				 errmsg("could not open tablespace directory \"%s\": %m",
-						pathname)));
 
-	while ((direntry = readdir(dirdesc)) != NULL)
+	while ((direntry = ReadDir(dirdesc, pathname)) != NULL)
 	{
 	    if (strcmp(direntry->d_name, ".") == 0 ||
 			strcmp(direntry->d_name, "..") == 0)
@@ -147,13 +142,7 @@ pg_tablespace_size(PG_FUNCTION_ARGS)
 
 	dirdesc = AllocateDir(tblspcPath);
 
-	if (!dirdesc)
-		ereport(ERROR,
-				(errcode_for_file_access(),
-				 errmsg("could not open tablespace directory \"%s\": %m",
-						tblspcPath)));
-
-	while ((direntry = readdir(dirdesc)) != NULL)
+	while ((direntry = ReadDir(dirdesc, tblspcPath)) != NULL)
 	{
 	    struct stat fst;
 
diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c
index cfc4fd67ea9c1e2850e9eba0e3ab78485005bf4c..24f9a947792110d691b0806e74a265397593ffa5 100644
--- a/src/backend/access/transam/slru.c
+++ b/src/backend/access/transam/slru.c
@@ -48,7 +48,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.24 2005/02/12 23:53:37 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.25 2005/06/19 21:34:01 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -924,14 +924,7 @@ SlruScanDirectory(SlruCtl ctl, int cutoffPage, bool doDeletions)
 	cutoffPage -= cutoffPage % SLRU_PAGES_PER_SEGMENT;
 
 	cldir = AllocateDir(ctl->Dir);
-	if (cldir == NULL)
-		ereport(ERROR,
-				(errcode_for_file_access(),
-				 errmsg("could not open directory \"%s\": %m",
-						ctl->Dir)));
-
-	errno = 0;
-	while ((clde = readdir(cldir)) != NULL)
+	while ((clde = ReadDir(cldir, ctl->Dir)) != NULL)
 	{
 		if (strlen(clde->d_name) == 4 &&
 			strspn(clde->d_name, "0123456789ABCDEF") == 4)
@@ -950,21 +943,7 @@ SlruScanDirectory(SlruCtl ctl, int cutoffPage, bool doDeletions)
 				}
 			}
 		}
-		errno = 0;
 	}
-#ifdef WIN32
-
-	/*
-	 * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but
-	 * not in released version
-	 */
-	if (GetLastError() == ERROR_NO_MORE_FILES)
-		errno = 0;
-#endif
-	if (errno)
-		ereport(ERROR,
-				(errcode_for_file_access(),
-			   errmsg("could not read directory \"%s\": %m", ctl->Dir)));
 	FreeDir(cldir);
 
 	return found;
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index 1aa9ce9b0258f3fa6c25902ea95d040dbc392e8d..6b78467ae1552bac22ee4c14b84c07b2b9ae69b1 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *		$PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.4 2005/06/19 20:00:38 tgl Exp $
+ *		$PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.5 2005/06/19 21:34:01 tgl Exp $
  *
  * NOTES
  *		Each global transaction is associated with a global transaction
@@ -1440,13 +1440,7 @@ PrescanPreparedTransactions(void)
 	snprintf(dir, MAXPGPATH, "%s/%s", DataDir, TWOPHASE_DIR);
 
 	cldir = AllocateDir(dir);
-	if (cldir == NULL)
-		ereport(ERROR,
-				(errcode_for_file_access(),
-				 errmsg("could not open directory \"%s\": %m", dir)));
-
-	errno = 0;
-	while ((clde = readdir(cldir)) != NULL)
+	while ((clde = ReadDir(cldir, dir)) != NULL)
 	{
 		if (strlen(clde->d_name) == 8 &&
 			strspn(clde->d_name, "0123456789ABCDEF") == 8)
@@ -1466,7 +1460,6 @@ PrescanPreparedTransactions(void)
 						(errmsg("removing future twophase state file \"%s\"",
 								clde->d_name)));
 				RemoveTwoPhaseFile(xid, true);
-				errno = 0;
 				continue;
 			}
 
@@ -1483,7 +1476,6 @@ PrescanPreparedTransactions(void)
 						(errmsg("removing corrupt twophase state file \"%s\"",
 								clde->d_name)));
 				RemoveTwoPhaseFile(xid, true);
-				errno = 0;
 				continue;
 			}
 
@@ -1496,7 +1488,6 @@ PrescanPreparedTransactions(void)
 								clde->d_name)));
 				RemoveTwoPhaseFile(xid, true);
 				pfree(buf);
-				errno = 0;
 				continue;
 			}
 
@@ -1528,22 +1519,7 @@ PrescanPreparedTransactions(void)
 
 			pfree(buf);
 		}
-		errno = 0;
 	}
-#ifdef WIN32
-
-	/*
-	 * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but
-	 * not in released version
-	 */
-	if (GetLastError() == ERROR_NO_MORE_FILES)
-		errno = 0;
-#endif
-	if (errno)
-		ereport(ERROR,
-				(errcode_for_file_access(),
-				 errmsg("could not read directory \"%s\": %m", dir)));
-
 	FreeDir(cldir);
 
 	return result;
@@ -1566,13 +1542,7 @@ RecoverPreparedTransactions(void)
 	snprintf(dir, MAXPGPATH, "%s/%s", DataDir, TWOPHASE_DIR);
 
 	cldir = AllocateDir(dir);
-	if (cldir == NULL)
-		ereport(ERROR,
-				(errcode_for_file_access(),
-				 errmsg("could not open directory \"%s\": %m", dir)));
-
-	errno = 0;
-	while ((clde = readdir(cldir)) != NULL)
+	while ((clde = ReadDir(cldir, dir)) != NULL)
 	{
 		if (strlen(clde->d_name) == 8 &&
 			strspn(clde->d_name, "0123456789ABCDEF") == 8)
@@ -1594,7 +1564,6 @@ RecoverPreparedTransactions(void)
 						(errmsg("removing stale twophase state file \"%s\"",
 								clde->d_name)));
 				RemoveTwoPhaseFile(xid, true);
-				errno = 0;
 				continue;
 			}
 
@@ -1606,7 +1575,6 @@ RecoverPreparedTransactions(void)
 						(errmsg("removing corrupt twophase state file \"%s\"",
 								clde->d_name)));
 				RemoveTwoPhaseFile(xid, true);
-				errno = 0;
 				continue;
 			}
 
@@ -1655,22 +1623,7 @@ RecoverPreparedTransactions(void)
 
 			pfree(buf);
 		}
-		errno = 0;
 	}
-#ifdef WIN32
-
-	/*
-	 * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but
-	 * not in released version
-	 */
-	if (GetLastError() == ERROR_NO_MORE_FILES)
-		errno = 0;
-#endif
-	if (errno)
-		ereport(ERROR,
-				(errcode_for_file_access(),
-				 errmsg("could not read directory \"%s\": %m", dir)));
-
 	FreeDir(cldir);
 }
 
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index b15949b285498920402321aee0f94fed0b2a9081..3a55a521c17b68027d511cd9d3ff94649cc5eadd 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.202 2005/06/19 20:00:38 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.203 2005/06/19 21:34:01 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2265,8 +2265,7 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr,
 
 	XLogFileName(lastoff, ThisTimeLineID, log, seg);
 
-	errno = 0;
-	while ((xlde = readdir(xldir)) != NULL)
+	while ((xlde = ReadDir(xldir, XLogDir)) != NULL)
 	{
 		/*
 		 * We ignore the timeline part of the XLOG segment identifiers in
@@ -2326,22 +2325,8 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr,
 				XLogArchiveCleanup(xlde->d_name);
 			}
 		}
-		errno = 0;
 	}
-#ifdef WIN32
 
-	/*
-	 * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but
-	 * not in released version
-	 */
-	if (GetLastError() == ERROR_NO_MORE_FILES)
-		errno = 0;
-#endif
-	if (errno)
-		ereport(ERROR,
-				(errcode_for_file_access(),
-			errmsg("could not read transaction log directory \"%s\": %m",
-				   XLogDir)));
 	FreeDir(xldir);
 }
 
@@ -2362,8 +2347,7 @@ RemoveOldBackupHistory(void)
 			errmsg("could not open transaction log directory \"%s\": %m",
 				   XLogDir)));
 
-	errno = 0;
-	while ((xlde = readdir(xldir)) != NULL)
+	while ((xlde = ReadDir(xldir, XLogDir)) != NULL)
 	{
 		if (strlen(xlde->d_name) > 24 &&
 			strspn(xlde->d_name, "0123456789ABCDEF") == 24 &&
@@ -2381,22 +2365,8 @@ RemoveOldBackupHistory(void)
 				XLogArchiveCleanup(xlde->d_name);
 			}
 		}
-		errno = 0;
 	}
-#ifdef WIN32
 
-	/*
-	 * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but
-	 * not in released version
-	 */
-	if (GetLastError() == ERROR_NO_MORE_FILES)
-		errno = 0;
-#endif
-	if (errno)
-		ereport(ERROR,
-				(errcode_for_file_access(),
-			errmsg("could not read transaction log directory \"%s\": %m",
-				   XLogDir)));
 	FreeDir(xldir);
 }
 
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index fac20708c0d36149c36a56f4f0aeaf0b40869ddf..a469a8fa349ff43bb726eb19625b22aa7964bb9d 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.21 2005/06/06 20:22:57 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.22 2005/06/19 21:34:01 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -519,23 +519,16 @@ remove_tablespace_directories(Oid tablespaceoid, bool redo)
 			pfree(location);
 			return true;
 		}
-		ereport(ERROR,
-				(errcode_for_file_access(),
-				 errmsg("could not open directory \"%s\": %m",
-						location)));
+		/* else let ReadDir report the error */
 	}
 
-	errno = 0;
-	while ((de = readdir(dirdesc)) != NULL)
+	while ((de = ReadDir(dirdesc, location)) != NULL)
 	{
 		/* Note we ignore PG_VERSION for the nonce */
 		if (strcmp(de->d_name, ".") == 0 ||
 			strcmp(de->d_name, "..") == 0 ||
 			strcmp(de->d_name, "PG_VERSION") == 0)
-		{
-			errno = 0;
 			continue;
-		}
 
 		subfile = palloc(strlen(location) + 1 + strlen(de->d_name) + 1);
 		sprintf(subfile, "%s/%s", location, de->d_name);
@@ -555,22 +548,8 @@ remove_tablespace_directories(Oid tablespaceoid, bool redo)
 							subfile)));
 
 		pfree(subfile);
-		errno = 0;
 	}
-#ifdef WIN32
 
-	/*
-	 * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but
-	 * not in released version
-	 */
-	if (GetLastError() == ERROR_NO_MORE_FILES)
-		errno = 0;
-#endif
-	if (errno)
-		ereport(ERROR,
-				(errcode_for_file_access(),
-				 errmsg("could not read directory \"%s\": %m",
-						location)));
 	FreeDir(dirdesc);
 
 	/*
@@ -685,38 +664,16 @@ directory_is_empty(const char *path)
 	struct dirent *de;
 
 	dirdesc = AllocateDir(path);
-	if (dirdesc == NULL)
-		ereport(ERROR,
-				(errcode_for_file_access(),
-				 errmsg("could not open directory \"%s\": %m",
-						path)));
 
-	errno = 0;
-	while ((de = readdir(dirdesc)) != NULL)
+	while ((de = ReadDir(dirdesc, path)) != NULL)
 	{
 		if (strcmp(de->d_name, ".") == 0 ||
 			strcmp(de->d_name, "..") == 0)
-		{
-			errno = 0;
 			continue;
-		}
 		FreeDir(dirdesc);
 		return false;
 	}
-#ifdef WIN32
 
-	/*
-	 * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but
-	 * not in released version
-	 */
-	if (GetLastError() == ERROR_NO_MORE_FILES)
-		errno = 0;
-#endif
-	if (errno)
-		ereport(ERROR,
-				(errcode_for_file_access(),
-				 errmsg("could not read directory \"%s\": %m",
-						path)));
 	FreeDir(dirdesc);
 	return true;
 }
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index fc2d9ce7299e9add1851a7e8c11411a895921939..e5eecb2dbc5d52c6f349c201dbdaedadda18f660 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -19,7 +19,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/postmaster/pgarch.c,v 1.15 2005/03/10 07:14:03 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/pgarch.c,v 1.16 2005/06/19 21:34:01 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -510,8 +510,7 @@ pgarch_readyXlog(char *xlog)
 			 errmsg("could not open archive status directory \"%s\": %m",
 					XLogArchiveStatusDir)));
 
-	errno = 0;
-	while ((rlde = readdir(rldir)) != NULL)
+	while ((rlde = ReadDir(rldir, XLogArchiveStatusDir)) != NULL)
 	{
 		int			basenamelen = (int) strlen(rlde->d_name) - 6;
 
@@ -531,23 +530,7 @@ pgarch_readyXlog(char *xlog)
 					strcpy(newxlog, rlde->d_name);
 			}
 		}
-
-		errno = 0;
 	}
-#ifdef WIN32
-
-	/*
-	 * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but
-	 * not in released version
-	 */
-	if (GetLastError() == ERROR_NO_MORE_FILES)
-		errno = 0;
-#endif
-	if (errno)
-		ereport(ERROR,
-				(errcode_for_file_access(),
-			 errmsg("could not read archive status directory \"%s\": %m",
-					XLogArchiveStatusDir)));
 	FreeDir(rldir);
 
 	if (found)
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 81ba3edbbeceaf0efe88351348d41c9f7c3f560b..b91e667d0b31466c0429700eae34e05f6c4a1fcc 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.116 2005/05/20 14:53:26 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.117 2005/06/19 21:34:02 tgl Exp $
  *
  * NOTES:
  *
@@ -1337,6 +1337,59 @@ TryAgain:
 	return NULL;
 }
 
+/*
+ * Read a directory opened with AllocateDir, ereport'ing any error.
+ *
+ * This is easier to use than raw readdir() since it takes care of some
+ * otherwise rather tedious and error-prone manipulation of errno.  Also,
+ * if you are happy with a generic error message for AllocateDir failure,
+ * you can just do
+ *
+ *		dir = AllocateDir(path);
+ *		while ((dirent = ReadDir(dir, path)) != NULL)
+ *			process dirent;
+ *		FreeDir(path);
+ *
+ * since a NULL dir parameter is taken as indicating AllocateDir failed.
+ * (Make sure errno hasn't been changed since AllocateDir if you use this
+ * shortcut.)
+ *
+ * The pathname passed to AllocateDir must be passed to this routine too,
+ * but it is only used for error reporting.
+ */
+struct dirent *
+ReadDir(DIR *dir, const char *dirname)
+{
+	struct dirent *dent;
+
+	/* Give a generic message for AllocateDir failure, if caller didn't */
+	if (dir == NULL)
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not open directory \"%s\": %m",
+						dirname)));
+
+	errno = 0;
+	if ((dent = readdir(dir)) != NULL)
+		return dent;
+
+#ifdef WIN32
+	/*
+	 * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but
+	 * not in released version
+	 */
+	if (GetLastError() == ERROR_NO_MORE_FILES)
+		errno = 0;
+#endif
+
+	if (errno)
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not read directory \"%s\": %m",
+						dirname)));
+	return NULL;
+}
+
 /*
  * Close a directory opened with AllocateDir.
  *
@@ -1526,14 +1579,8 @@ RemovePgTempFiles(void)
 	 */
 	snprintf(db_path, sizeof(db_path), "%s/base", DataDir);
 	db_dir = AllocateDir(db_path);
-	if (db_dir == NULL)
-	{
-		/* this really should not happen */
-		elog(LOG, "could not open directory \"%s\": %m", db_path);
-		return;
-	}
 
-	while ((db_de = readdir(db_dir)) != NULL)
+	while ((db_de = ReadDir(db_dir, db_path)) != NULL)
 	{
 		if (strcmp(db_de->d_name, ".") == 0 ||
 			strcmp(db_de->d_name, "..") == 0)
@@ -1576,7 +1623,7 @@ RemovePgTempFilesInDir(const char *tmpdirname)
 		return;
 	}
 
-	while ((temp_de = readdir(temp_dir)) != NULL)
+	while ((temp_de = ReadDir(temp_dir, tmpdirname)) != NULL)
 	{
 		if (strcmp(temp_de->d_name, ".") == 0 ||
 			strcmp(temp_de->d_name, "..") == 0)
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index 886ff011221ba6ae2783505ea297342893878ee5..45532539664f21f93d8f293bc21270b0b94436fb 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/misc.c,v 1.43 2005/05/19 21:35:47 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/misc.c,v 1.44 2005/06/19 21:34:02 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -187,11 +187,10 @@ pg_tablespace_databases(PG_FUNCTION_ARGS)
 	if (!fctx->dirdesc)			/* not a tablespace */
 		SRF_RETURN_DONE(funcctx);
 
-	while ((de = readdir(fctx->dirdesc)) != NULL)
+	while ((de = ReadDir(fctx->dirdesc, fctx->location)) != NULL)
 	{
 		char	   *subdir;
 		DIR		   *dirdesc;
-
 		Oid			datOid = atooid(de->d_name);
 
 		/* this test skips . and .., but is awfully weak */
@@ -204,16 +203,13 @@ pg_tablespace_databases(PG_FUNCTION_ARGS)
 		subdir = palloc(strlen(fctx->location) + 1 + strlen(de->d_name) + 1);
 		sprintf(subdir, "%s/%s", fctx->location, de->d_name);
 		dirdesc = AllocateDir(subdir);
-		pfree(subdir);
-		if (!dirdesc)
-			continue;			/* XXX more sloppiness */
-
-		while ((de = readdir(dirdesc)) != 0)
+		while ((de = ReadDir(dirdesc, subdir)) != NULL)
 		{
 			if (strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0)
 				break;
 		}
 		FreeDir(dirdesc);
+		pfree(subdir);
 
 		if (!de)
 			continue;			/* indeed, nothing in it */
diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h
index 20c2c64c8985c19c292635c6f0f24e20b5e93bcf..0cebfb85bb21de7b696ddd534a92146382090bd2 100644
--- a/src/include/storage/fd.h
+++ b/src/include/storage/fd.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/storage/fd.h,v 1.51 2005/05/20 14:53:26 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/storage/fd.h,v 1.52 2005/06/19 21:34:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -76,6 +76,7 @@ extern int	FreeFile(FILE *file);
 
 /* Operations to allow use of the <dirent.h> library routines */
 extern DIR *AllocateDir(const char *dirname);
+extern struct dirent *ReadDir(DIR *dir, const char *dirname);
 extern int	FreeDir(DIR *dir);
 
 /* If you've really really gotta have a plain kernel FD, use this */
diff --git a/src/timezone/pgtz.c b/src/timezone/pgtz.c
index b5b9107c758c3b34638c003778a546aac270a929..391c3e552c548011f7c54e93fd46ec7f6b83d072 100644
--- a/src/timezone/pgtz.c
+++ b/src/timezone/pgtz.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/timezone/pgtz.c,v 1.33 2005/06/15 00:09:26 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/timezone/pgtz.c,v 1.34 2005/06/19 21:34:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -409,11 +409,12 @@ identify_system_timezone(void)
  * score.  bestzonename must be a buffer of length TZ_STRLEN_MAX + 1.
  */
 static void
-scan_available_timezones(char *tzdir, char *tzdirsub, struct tztry * tt,
+scan_available_timezones(char *tzdir, char *tzdirsub, struct tztry *tt,
 						 int *bestscore, char *bestzonename)
 {
 	int			tzdir_orig_len = strlen(tzdir);
 	DIR		   *dirdesc;
+	struct dirent *direntry;
 
 	dirdesc = AllocateDir(tzdir);
 	if (!dirdesc)
@@ -424,22 +425,10 @@ scan_available_timezones(char *tzdir, char *tzdirsub, struct tztry * tt,
 		return;
 	}
 
-	for (;;)
+	while ((direntry = ReadDir(dirdesc, tzdir)) != NULL)
 	{
-		struct dirent *direntry;
 		struct stat statbuf;
 
-		errno = 0;
-		direntry = readdir(dirdesc);
-		if (!direntry)
-		{
-			if (errno)
-				ereport(LOG,
-						(errcode_for_file_access(),
-						 errmsg("error reading directory: %m")));
-			break;
-		}
-
 		/* Ignore . and .., plus any other "hidden" files */
 		if (direntry->d_name[0] == '.')
 			continue;
@@ -452,6 +441,7 @@ scan_available_timezones(char *tzdir, char *tzdirsub, struct tztry * tt,
 			ereport(LOG,
 					(errcode_for_file_access(),
 					 errmsg("could not stat \"%s\": %m", tzdir)));
+			tzdir[tzdir_orig_len] = '\0';
 			continue;
 		}
 
@@ -480,12 +470,12 @@ scan_available_timezones(char *tzdir, char *tzdirsub, struct tztry * tt,
 					StrNCpy(bestzonename, tzdirsub, TZ_STRLEN_MAX + 1);
 			}
 		}
+
+		/* Restore tzdir */
+		tzdir[tzdir_orig_len] = '\0';
 	}
 
 	FreeDir(dirdesc);
-
-	/* Restore tzdir */
-	tzdir[tzdir_orig_len] = '\0';
 }
 
 #else							/* WIN32 */