]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
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_archivecleanup/pg_archivecleanup.c
contrib/pg_standby/pg_standby.c
contrib/pg_upgrade/file.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 b2963decd72386124f516adda6ad2782f825f3fd..5589d59ce6a7f9b80ab2649ef5e45c2c18a9af65 100644 (file)
@@ -98,7 +98,7 @@ CleanupPriorWALFiles(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 in
@@ -132,7 +132,19 @@ CleanupPriorWALFiles(void)
                                }
                        }
                }
-               closedir(xldir);
+
+#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 (closedir(xldir))
+                       fprintf(stderr, "%s: could not close archive location \"%s\": %s\n",
+                                       progname, archiveLocation, strerror(errno));
        }
        else
                fprintf(stderr, "%s: could not open archiveLocation \"%s\": %s\n",
index adfbad5f388701b3c74cbd20152ac19652f6c777..af4bb37e2b61416eadfe6e75914c7387d89e2ee9 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 29e3c06a9e090d170b9dff4e71c245e21d9eee78..4def03e343407e1c9763643fb272a316ee364d8b 100644 (file)
@@ -291,7 +291,7 @@ pg_scandir_internal(migratorContext *ctx, const char *dirname,
 
        *namelist = NULL;
 
-       while ((direntry = readdir(dirdesc)) != NULL)
+       while (errno = 0, (direntry = readdir(dirdesc)) != NULL)
        {
                /* Invoke the selector function to see if the direntry matches */
                if ((*selector) (direntry))
@@ -318,7 +318,17 @@ pg_scandir_internal(migratorContext *ctx, const char *dirname,
                }
        }
 
-       closedir(dirdesc);
+#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)
+               pg_log(ctx, PG_FATAL, "Could not read directory \"%s\": %s\n", dirname, getErrorText(errno));
+
+       if (closedir(dirdesc))
+               pg_log(ctx, PG_FATAL, "Could not close directory \"%s\": %s\n", dirname, getErrorText(errno));
 
        return count;
 }
@@ -415,7 +425,7 @@ copy_dir(const char *src, const char *dst, bool force)
                        return -1;
        }
 
-       while ((de = readdir(srcdir)) != NULL)
+       while (errno = 0, (de = readdir(srcdir)) != NULL)
        {
                char            src_file[MAXPGPATH];
                char            dest_file[MAXPGPATH];
@@ -460,9 +470,19 @@ copy_dir(const char *src, const char *dst, bool force)
                }
        }
 
+#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)
+               return -1;
+
        if (srcdir != NULL)
        {
-               closedir(srcdir);
+               if (closedir(srcdir))
+                       return -1;
                srcdir = NULL;
        }
        return 1;
index 09a47086a517edfc0100301ab8cb06d34a9bc045..3d6b6a46eec5d49337ebdef5459bab99b12fc33e 100644 (file)
@@ -1614,11 +1614,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 901aed967877ed32e05463c63f5f7f2c58f5832f..9442444d9638622e1e2ce0be4a03f5e09dc190d2 100644 (file)
@@ -822,7 +822,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)
@@ -838,18 +838,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 ee403c286c2fba0b2cade22dc8979d273f3a6c82..c445f3c2bbf827a72bb6cc391bb2669e73e578ed 100644 (file)
@@ -742,8 +742,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)
@@ -767,25 +766,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
@@ -817,8 +818,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)
@@ -831,25 +831,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);
 }
 
 
@@ -873,8 +875,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 ||
@@ -888,25 +889,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 4034ef42f3fa566101e2b5eb2154996e7f8494c4..ee1c0c509a80abcc3f21dc96bd3e28f44c79d13f 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 d47c03e4450306d285bd9b2dddbd6155a95f3ba8..d7754418a88a5c169a9ca0e5ab83114accfeb237 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;
 }