Properly check for readdir/closedir() failures
authorBruce Momjian <bruce@momjian.us>
Fri, 21 Mar 2014 17:45:11 +0000 (13:45 -0400)
committerBruce Momjian <bruce@momjian.us>
Fri, 21 Mar 2014 17:45:11 +0000 (13:45 -0400)
Clear errno before calling readdir() and handle old MinGW errno bug
while adding full test coverage for readdir/closedir failures.

Backpatch through 8.4.

contrib/pg_standby/pg_standby.c
src/backend/storage/file/fd.c
src/bin/initdb/initdb.c
src/bin/pg_resetxlog/pg_resetxlog.c
src/port/dirent.c
src/port/dirmod.c

index d889c5cc64352ae3a6fe1b5a03d2afae8f621c7a..147445dfdd16375d98d1bfdaa27eb80b7d792a9c 100644 (file)
@@ -256,7 +256,7 @@ CustomizableCleanupPriorWALFiles(void)
         */
        if ((xldir = opendir(archiveLocation)) != NULL)
        {
-           while ((xlde = readdir(xldir)) != NULL)
+           while (errno = 0, (xlde = readdir(xldir)) != NULL)
            {
                /*
                 * We ignore the timeline part of the XLOG segment identifiers
@@ -294,13 +294,26 @@ CustomizableCleanupPriorWALFiles(void)
                    }
                }
            }
+
+#ifdef WIN32
+           /* Bug in old Mingw dirent.c;  fixed in mingw-runtime-3.2, 2003-10-10 */
+           if (GetLastError() == ERROR_NO_MORE_FILES)
+               errno = 0;
+#endif
+
+           if (errno)
+               fprintf(stderr, "%s: could not read archive location \"%s\": %s\n",
+                       progname, archiveLocation, strerror(errno));
            if (debug)
                fprintf(stderr, "\n");
        }
        else
            fprintf(stderr, "%s: archiveLocation \"%s\" open error\n", progname, archiveLocation);
 
-       closedir(xldir);
+       if (closedir(xldir))
+           fprintf(stderr, "%s: could not close archive location \"%s\": %s\n",
+                   progname, archiveLocation, strerror(errno));
+
        fflush(stderr);
    }
 }
index 05e159bac2f1c6bdc515701257e95b9b9e9d44ee..8bc266641ae70bd531a8d712c35219b8cd62bac5 100644 (file)
@@ -1582,11 +1582,7 @@ ReadDir(DIR *dir, const char *dirname)
        return dent;
 
 #ifdef WIN32
-
-   /*
-    * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
-    * released version
-    */
+   /* Bug in old Mingw dirent.c;  fixed in mingw-runtime-3.2, 2003-10-10 */
    if (GetLastError() == ERROR_NO_MORE_FILES)
        errno = 0;
 #endif
index d5a2902a1a1a240eca30df2c5db012c299ed750f..3b34baf083d691187e353aacacf653c34e848ff8 100644 (file)
@@ -861,7 +861,7 @@ check_data_dir(char *dir)
    if (!chkdir)
        return (errno == ENOENT) ? 0 : -1;
 
-   while ((file = readdir(chkdir)) != NULL)
+   while (errno = 0, (file = readdir(chkdir)) != NULL)
    {
        if (strcmp(".", file->d_name) == 0 ||
            strcmp("..", file->d_name) == 0)
@@ -877,18 +877,12 @@ check_data_dir(char *dir)
    }
 
 #ifdef WIN32
-
-   /*
-    * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
-    * released version
-    */
+   /* Bug in old Mingw dirent.c;  fixed in mingw-runtime-3.2, 2003-10-10 */
    if (GetLastError() == ERROR_NO_MORE_FILES)
        errno = 0;
 #endif
 
-   closedir(chkdir);
-
-   if (errno != 0)
+   if (errno || closedir(chkdir))
        result = -1;            /* some kind of I/O error? */
 
    return result;
index 8368c2165dc983533649df7b6ab5506a9cb15b8a..5f3de38d0785981e61a171739211a9fa4721fa97 100644 (file)
@@ -700,8 +700,7 @@ FindEndOfXLOG(void)
        exit(1);
    }
 
-   errno = 0;
-   while ((xlde = readdir(xldir)) != NULL)
+   while (errno = 0, (xlde = readdir(xldir)) != NULL)
    {
        if (strlen(xlde->d_name) == 24 &&
            strspn(xlde->d_name, "0123456789ABCDEF") == 24)
@@ -725,25 +724,27 @@ FindEndOfXLOG(void)
                newXlogSeg = seg;
            }
        }
-       errno = 0;
    }
-#ifdef WIN32
 
-   /*
-    * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
-    * released version
-    */
+#ifdef WIN32
+   /* Bug in old Mingw dirent.c;  fixed in mingw-runtime-3.2, 2003-10-10 */
    if (GetLastError() == ERROR_NO_MORE_FILES)
        errno = 0;
 #endif
 
    if (errno)
    {
-       fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
+       fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
+               progname, XLOGDIR, strerror(errno));
+       exit(1);
+   }
+
+   if (closedir(xldir))
+   {
+       fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
                progname, XLOGDIR, strerror(errno));
        exit(1);
    }
-   closedir(xldir);
 
    /*
     * Finally, convert to new xlog seg size, and advance by one to ensure we
@@ -775,8 +776,7 @@ KillExistingXLOG(void)
        exit(1);
    }
 
-   errno = 0;
-   while ((xlde = readdir(xldir)) != NULL)
+   while (errno = 0, (xlde = readdir(xldir)) != NULL)
    {
        if (strlen(xlde->d_name) == 24 &&
            strspn(xlde->d_name, "0123456789ABCDEF") == 24)
@@ -789,25 +789,27 @@ KillExistingXLOG(void)
                exit(1);
            }
        }
-       errno = 0;
    }
-#ifdef WIN32
 
-   /*
-    * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
-    * released version
-    */
+#ifdef WIN32
+   /* Bug in old Mingw dirent.c;  fixed in mingw-runtime-3.2, 2003-10-10 */
    if (GetLastError() == ERROR_NO_MORE_FILES)
        errno = 0;
 #endif
 
    if (errno)
    {
-       fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
+       fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
+               progname, XLOGDIR, strerror(errno));
+       exit(1);
+   }
+
+   if (closedir(xldir))
+   {
+       fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
                progname, XLOGDIR, strerror(errno));
        exit(1);
    }
-   closedir(xldir);
 }
 
 
@@ -831,8 +833,7 @@ KillExistingArchiveStatus(void)
        exit(1);
    }
 
-   errno = 0;
-   while ((xlde = readdir(xldir)) != NULL)
+   while (errno = 0, (xlde = readdir(xldir)) != NULL)
    {
        if (strspn(xlde->d_name, "0123456789ABCDEF") == 24 &&
            (strcmp(xlde->d_name + 24, ".ready") == 0 ||
@@ -846,25 +847,27 @@ KillExistingArchiveStatus(void)
                exit(1);
            }
        }
-       errno = 0;
    }
-#ifdef WIN32
 
-   /*
-    * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
-    * released version
-    */
+#ifdef WIN32
+   /* Bug in old Mingw dirent.c;  fixed in mingw-runtime-3.2, 2003-10-10 */
    if (GetLastError() == ERROR_NO_MORE_FILES)
        errno = 0;
 #endif
 
    if (errno)
    {
-       fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
+       fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
+               progname, ARCHSTATDIR, strerror(errno));
+       exit(1);
+   }
+
+   if (closedir(xldir))
+   {
+       fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
                progname, ARCHSTATDIR, strerror(errno));
        exit(1);
    }
-   closedir(xldir);
 }
 
 
index fd994a87aa5395a808d6fadd0716b800d2dd90b3..3485b8776727179212236f39c2cbb03dac352b98 100644 (file)
@@ -100,15 +100,19 @@ readdir(DIR *d)
    strcpy(d->ret.d_name, fd.cFileName);        /* Both strings are MAX_PATH
                                                 * long */
    d->ret.d_namlen = strlen(d->ret.d_name);
+
    return &d->ret;
 }
 
 int
 closedir(DIR *d)
 {
+   int ret = 0;
+
    if (d->handle != INVALID_HANDLE_VALUE)
-       FindClose(d->handle);
+       ret = !FindClose(d->handle);
    free(d->dirname);
    free(d);
-   return 0;
+
+   return ret;
 }
index 32364be852e59c5af5f7d7f522615e0ffefc25a8..258a8c4d54dfd16c16e05a1a112bfa884174b644 100644 (file)
@@ -330,8 +330,7 @@ pgfnames(const char *path)
 
    filenames = (char **) palloc(fnsize * sizeof(char *));
 
-   errno = 0;
-   while ((file = readdir(dir)) != NULL)
+   while (errno = 0, (file = readdir(dir)) != NULL)
    {
        if (strcmp(file->d_name, ".") != 0 && strcmp(file->d_name, "..") != 0)
        {
@@ -343,17 +342,14 @@ pgfnames(const char *path)
            }
            filenames[numnames++] = pstrdup(file->d_name);
        }
-       errno = 0;
    }
-#ifdef WIN32
 
-   /*
-    * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
-    * released version
-    */
+#ifdef WIN32
+   /* Bug in old Mingw dirent.c;  fixed in mingw-runtime-3.2, 2003-10-10 */
    if (GetLastError() == ERROR_NO_MORE_FILES)
        errno = 0;
 #endif
+
    if (errno)
    {
 #ifndef FRONTEND
@@ -366,7 +362,15 @@ pgfnames(const char *path)
 
    filenames[numnames] = NULL;
 
-   closedir(dir);
+   if (closedir(dir))
+   {
+#ifndef FRONTEND
+       elog(WARNING, "could not close directory \"%s\": %m", path);
+#else
+       fprintf(stderr, _("could not close directory \"%s\": %s\n"),
+               path, strerror(errno));
+#endif
+   }
 
    return filenames;
 }