Simplify uses of readdir() by creating a function ReadDir() that
authorTom Lane
Sun, 19 Jun 2005 21:34:03 +0000 (21:34 +0000)
committerTom Lane
Sun, 19 Jun 2005 21:34:03 +0000 (21:34 +0000)
includes error checking and an appropriate ereport(ERROR) message.
This gets rid of rather tedious and error-prone manipulation of errno,
as well as a Windows-specific bug workaround, at more than a dozen
call sites.  After an idea in a recent patch by Heikki Linnakangas.

contrib/dbsize/dbsize.c
src/backend/access/transam/slru.c
src/backend/access/transam/twophase.c
src/backend/access/transam/xlog.c
src/backend/commands/tablespace.c
src/backend/postmaster/pgarch.c
src/backend/storage/file/fd.c
src/backend/utils/adt/misc.c
src/include/storage/fd.h
src/timezone/pgtz.c

index afa1937145c52af55114d08186aac01c3ee81bb2..903de97b3740f850c8ac3bd3af693040e57dfd30 100644 (file)
@@ -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;
 
index cfc4fd67ea9c1e2850e9eba0e3ab78485005bf4c..24f9a947792110d691b0806e74a265397593ffa5 100644 (file)
@@ -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;
index 1aa9ce9b0258f3fa6c25902ea95d040dbc392e8d..6b78467ae1552bac22ee4c14b84c07b2b9ae69b1 100644 (file)
@@ -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);
 }
 
index b15949b285498920402321aee0f94fed0b2a9081..3a55a521c17b68027d511cd9d3ff94649cc5eadd 100644 (file)
@@ -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);
 }
 
index fac20708c0d36149c36a56f4f0aeaf0b40869ddf..a469a8fa349ff43bb726eb19625b22aa7964bb9d 100644 (file)
@@ -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;
 }
index fc2d9ce7299e9add1851a7e8c11411a895921939..e5eecb2dbc5d52c6f349c201dbdaedadda18f660 100644 (file)
@@ -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)
index 81ba3edbbeceaf0efe88351348d41c9f7c3f560b..b91e667d0b31466c0429700eae34e05f6c4a1fcc 100644 (file)
@@ -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)
index 886ff011221ba6ae2783505ea297342893878ee5..45532539664f21f93d8f293bc21270b0b94436fb 100644 (file)
@@ -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 */
index 20c2c64c8985c19c292635c6f0f24e20b5e93bcf..0cebfb85bb21de7b696ddd534a92146382090bd2 100644 (file)
@@ -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  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 */
index b5b9107c758c3b34638c003778a546aac270a929..391c3e552c548011f7c54e93fd46ec7f6b83d072 100644 (file)
@@ -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 */