Skip to content

Commit de13cea

Browse files
committed
Properly check for readdir/closedir() failures
Clear errno before calling readdir() and handle old MinGW errno bug while adding full test coverage for readdir/closedir failures. Backpatch through 8.4.
1 parent e1fa2d4 commit de13cea

File tree

6 files changed

+71
-57
lines changed

6 files changed

+71
-57
lines changed

contrib/pg_standby/pg_standby.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ CustomizableCleanupPriorWALFiles(void)
256256
*/
257257
if ((xldir = opendir(archiveLocation)) != NULL)
258258
{
259-
while ((xlde = readdir(xldir)) != NULL)
259+
while (errno = 0, (xlde = readdir(xldir)) != NULL)
260260
{
261261
/*
262262
* We ignore the timeline part of the XLOG segment identifiers
@@ -294,13 +294,26 @@ CustomizableCleanupPriorWALFiles(void)
294294
}
295295
}
296296
}
297+
298+
#ifdef WIN32
299+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
300+
if (GetLastError() == ERROR_NO_MORE_FILES)
301+
errno = 0;
302+
#endif
303+
304+
if (errno)
305+
fprintf(stderr, "%s: could not read archive location \"%s\": %s\n",
306+
progname, archiveLocation, strerror(errno));
297307
if (debug)
298308
fprintf(stderr, "\n");
299309
}
300310
else
301311
fprintf(stderr, "%s: archiveLocation \"%s\" open error\n", progname, archiveLocation);
302312

303-
closedir(xldir);
313+
if (closedir(xldir))
314+
fprintf(stderr, "%s: could not close archive location \"%s\": %s\n",
315+
progname, archiveLocation, strerror(errno));
316+
304317
fflush(stderr);
305318
}
306319
}

src/backend/storage/file/fd.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1582,11 +1582,7 @@ ReadDir(DIR *dir, const char *dirname)
15821582
return dent;
15831583

15841584
#ifdef WIN32
1585-
1586-
/*
1587-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
1588-
* released version
1589-
*/
1585+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
15901586
if (GetLastError() == ERROR_NO_MORE_FILES)
15911587
errno = 0;
15921588
#endif

src/bin/initdb/initdb.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -861,7 +861,7 @@ check_data_dir(char *dir)
861861
if (!chkdir)
862862
return (errno == ENOENT) ? 0 : -1;
863863

864-
while ((file = readdir(chkdir)) != NULL)
864+
while (errno = 0, (file = readdir(chkdir)) != NULL)
865865
{
866866
if (strcmp(".", file->d_name) == 0 ||
867867
strcmp("..", file->d_name) == 0)
@@ -877,18 +877,12 @@ check_data_dir(char *dir)
877877
}
878878

879879
#ifdef WIN32
880-
881-
/*
882-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
883-
* released version
884-
*/
880+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
885881
if (GetLastError() == ERROR_NO_MORE_FILES)
886882
errno = 0;
887883
#endif
888884

889-
closedir(chkdir);
890-
891-
if (errno != 0)
885+
if (errno || closedir(chkdir))
892886
result = -1; /* some kind of I/O error? */
893887

894888
return result;

src/bin/pg_resetxlog/pg_resetxlog.c

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -700,8 +700,7 @@ FindEndOfXLOG(void)
700700
exit(1);
701701
}
702702

703-
errno = 0;
704-
while ((xlde = readdir(xldir)) != NULL)
703+
while (errno = 0, (xlde = readdir(xldir)) != NULL)
705704
{
706705
if (strlen(xlde->d_name) == 24 &&
707706
strspn(xlde->d_name, "0123456789ABCDEF") == 24)
@@ -725,25 +724,27 @@ FindEndOfXLOG(void)
725724
newXlogSeg = seg;
726725
}
727726
}
728-
errno = 0;
729727
}
730-
#ifdef WIN32
731728

732-
/*
733-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
734-
* released version
735-
*/
729+
#ifdef WIN32
730+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
736731
if (GetLastError() == ERROR_NO_MORE_FILES)
737732
errno = 0;
738733
#endif
739734

740735
if (errno)
741736
{
742-
fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
737+
fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
738+
progname, XLOGDIR, strerror(errno));
739+
exit(1);
740+
}
741+
742+
if (closedir(xldir))
743+
{
744+
fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
743745
progname, XLOGDIR, strerror(errno));
744746
exit(1);
745747
}
746-
closedir(xldir);
747748

748749
/*
749750
* Finally, convert to new xlog seg size, and advance by one to ensure we
@@ -775,8 +776,7 @@ KillExistingXLOG(void)
775776
exit(1);
776777
}
777778

778-
errno = 0;
779-
while ((xlde = readdir(xldir)) != NULL)
779+
while (errno = 0, (xlde = readdir(xldir)) != NULL)
780780
{
781781
if (strlen(xlde->d_name) == 24 &&
782782
strspn(xlde->d_name, "0123456789ABCDEF") == 24)
@@ -789,25 +789,27 @@ KillExistingXLOG(void)
789789
exit(1);
790790
}
791791
}
792-
errno = 0;
793792
}
794-
#ifdef WIN32
795793

796-
/*
797-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
798-
* released version
799-
*/
794+
#ifdef WIN32
795+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
800796
if (GetLastError() == ERROR_NO_MORE_FILES)
801797
errno = 0;
802798
#endif
803799

804800
if (errno)
805801
{
806-
fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
802+
fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
803+
progname, XLOGDIR, strerror(errno));
804+
exit(1);
805+
}
806+
807+
if (closedir(xldir))
808+
{
809+
fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
807810
progname, XLOGDIR, strerror(errno));
808811
exit(1);
809812
}
810-
closedir(xldir);
811813
}
812814

813815

@@ -831,8 +833,7 @@ KillExistingArchiveStatus(void)
831833
exit(1);
832834
}
833835

834-
errno = 0;
835-
while ((xlde = readdir(xldir)) != NULL)
836+
while (errno = 0, (xlde = readdir(xldir)) != NULL)
836837
{
837838
if (strspn(xlde->d_name, "0123456789ABCDEF") == 24 &&
838839
(strcmp(xlde->d_name + 24, ".ready") == 0 ||
@@ -846,25 +847,27 @@ KillExistingArchiveStatus(void)
846847
exit(1);
847848
}
848849
}
849-
errno = 0;
850850
}
851-
#ifdef WIN32
852851

853-
/*
854-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
855-
* released version
856-
*/
852+
#ifdef WIN32
853+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
857854
if (GetLastError() == ERROR_NO_MORE_FILES)
858855
errno = 0;
859856
#endif
860857

861858
if (errno)
862859
{
863-
fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
860+
fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
861+
progname, ARCHSTATDIR, strerror(errno));
862+
exit(1);
863+
}
864+
865+
if (closedir(xldir))
866+
{
867+
fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
864868
progname, ARCHSTATDIR, strerror(errno));
865869
exit(1);
866870
}
867-
closedir(xldir);
868871
}
869872

870873

src/port/dirent.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,15 +100,19 @@ readdir(DIR *d)
100100
strcpy(d->ret.d_name, fd.cFileName); /* Both strings are MAX_PATH
101101
* long */
102102
d->ret.d_namlen = strlen(d->ret.d_name);
103+
103104
return &d->ret;
104105
}
105106

106107
int
107108
closedir(DIR *d)
108109
{
110+
int ret = 0;
111+
109112
if (d->handle != INVALID_HANDLE_VALUE)
110-
FindClose(d->handle);
113+
ret = !FindClose(d->handle);
111114
free(d->dirname);
112115
free(d);
113-
return 0;
116+
117+
return ret;
114118
}

src/port/dirmod.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -330,8 +330,7 @@ pgfnames(const char *path)
330330

331331
filenames = (char **) palloc(fnsize * sizeof(char *));
332332

333-
errno = 0;
334-
while ((file = readdir(dir)) != NULL)
333+
while (errno = 0, (file = readdir(dir)) != NULL)
335334
{
336335
if (strcmp(file->d_name, ".") != 0 && strcmp(file->d_name, "..") != 0)
337336
{
@@ -343,17 +342,14 @@ pgfnames(const char *path)
343342
}
344343
filenames[numnames++] = pstrdup(file->d_name);
345344
}
346-
errno = 0;
347345
}
348-
#ifdef WIN32
349346

350-
/*
351-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
352-
* released version
353-
*/
347+
#ifdef WIN32
348+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
354349
if (GetLastError() == ERROR_NO_MORE_FILES)
355350
errno = 0;
356351
#endif
352+
357353
if (errno)
358354
{
359355
#ifndef FRONTEND
@@ -366,7 +362,15 @@ pgfnames(const char *path)
366362

367363
filenames[numnames] = NULL;
368364

369-
closedir(dir);
365+
if (closedir(dir))
366+
{
367+
#ifndef FRONTEND
368+
elog(WARNING, "could not close directory \"%s\": %m", path);
369+
#else
370+
fprintf(stderr, _("could not close directory \"%s\": %s\n"),
371+
path, strerror(errno));
372+
#endif
373+
}
370374

371375
return filenames;
372376
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy