Skip to content

Commit d73cc58

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 697becf commit d73cc58

File tree

8 files changed

+97
-63
lines changed

8 files changed

+97
-63
lines changed

contrib/pg_archivecleanup/pg_archivecleanup.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ CleanupPriorWALFiles(void)
9898

9999
if ((xldir = opendir(archiveLocation)) != NULL)
100100
{
101-
while ((xlde = readdir(xldir)) != NULL)
101+
while (errno = 0, (xlde = readdir(xldir)) != NULL)
102102
{
103103
/*
104104
* We ignore the timeline part of the XLOG segment identifiers in
@@ -132,7 +132,19 @@ CleanupPriorWALFiles(void)
132132
}
133133
}
134134
}
135-
closedir(xldir);
135+
136+
#ifdef WIN32
137+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
138+
if (GetLastError() == ERROR_NO_MORE_FILES)
139+
errno = 0;
140+
#endif
141+
142+
if (errno)
143+
fprintf(stderr, "%s: could not read archive location \"%s\": %s\n",
144+
progname, archiveLocation, strerror(errno));
145+
if (closedir(xldir))
146+
fprintf(stderr, "%s: could not close archive location \"%s\": %s\n",
147+
progname, archiveLocation, strerror(errno));
136148
}
137149
else
138150
fprintf(stderr, "%s: could not open archive location \"%s\": %s\n",

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,14 +294,27 @@ 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: could not open archive location \"%s\": %s\n",
302312
progname, archiveLocation, strerror(errno));
303313

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

contrib/pg_upgrade/file.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ pg_scandir_internal(const char *dirname,
291291

292292
*namelist = NULL;
293293

294-
while ((direntry = readdir(dirdesc)) != NULL)
294+
while (errno = 0, (direntry = readdir(dirdesc)) != NULL)
295295
{
296296
/* Invoke the selector function to see if the direntry matches */
297297
if (!selector || (*selector) (direntry))
@@ -324,7 +324,17 @@ pg_scandir_internal(const char *dirname,
324324
}
325325
}
326326

327-
closedir(dirdesc);
327+
#ifdef WIN32
328+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
329+
if (GetLastError() == ERROR_NO_MORE_FILES)
330+
errno = 0;
331+
#endif
332+
333+
if (errno)
334+
pg_log(PG_FATAL, "could not read directory \"%s\": %s\n", dirname, getErrorText(errno));
335+
336+
if (closedir(dirdesc))
337+
pg_log(PG_FATAL, "could not close directory \"%s\": %s\n", dirname, getErrorText(errno));
328338

329339
return count;
330340
}

src/backend/storage/file/fd.c

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

16891689
#ifdef WIN32
1690-
1691-
/*
1692-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
1693-
* released version
1694-
*/
1690+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
16951691
if (GetLastError() == ERROR_NO_MORE_FILES)
16961692
errno = 0;
16971693
#endif

src/bin/pg_resetxlog/pg_resetxlog.c

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -742,8 +742,7 @@ FindEndOfXLOG(void)
742742
exit(1);
743743
}
744744

745-
errno = 0;
746-
while ((xlde = readdir(xldir)) != NULL)
745+
while (errno = 0, (xlde = readdir(xldir)) != NULL)
747746
{
748747
if (strlen(xlde->d_name) == 24 &&
749748
strspn(xlde->d_name, "0123456789ABCDEF") == 24)
@@ -767,25 +766,27 @@ FindEndOfXLOG(void)
767766
newXlogSeg = seg;
768767
}
769768
}
770-
errno = 0;
771769
}
772-
#ifdef WIN32
773770

774-
/*
775-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
776-
* released version
777-
*/
771+
#ifdef WIN32
772+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
778773
if (GetLastError() == ERROR_NO_MORE_FILES)
779774
errno = 0;
780775
#endif
781776

782777
if (errno)
783778
{
784-
fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
779+
fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
780+
progname, XLOGDIR, strerror(errno));
781+
exit(1);
782+
}
783+
784+
if (closedir(xldir))
785+
{
786+
fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
785787
progname, XLOGDIR, strerror(errno));
786788
exit(1);
787789
}
788-
closedir(xldir);
789790

790791
/*
791792
* Finally, convert to new xlog seg size, and advance by one to ensure we
@@ -817,8 +818,7 @@ KillExistingXLOG(void)
817818
exit(1);
818819
}
819820

820-
errno = 0;
821-
while ((xlde = readdir(xldir)) != NULL)
821+
while (errno = 0, (xlde = readdir(xldir)) != NULL)
822822
{
823823
if (strlen(xlde->d_name) == 24 &&
824824
strspn(xlde->d_name, "0123456789ABCDEF") == 24)
@@ -831,25 +831,27 @@ KillExistingXLOG(void)
831831
exit(1);
832832
}
833833
}
834-
errno = 0;
835834
}
836-
#ifdef WIN32
837835

838-
/*
839-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
840-
* released version
841-
*/
836+
#ifdef WIN32
837+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
842838
if (GetLastError() == ERROR_NO_MORE_FILES)
843839
errno = 0;
844840
#endif
845841

846842
if (errno)
847843
{
848-
fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
844+
fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
845+
progname, XLOGDIR, strerror(errno));
846+
exit(1);
847+
}
848+
849+
if (closedir(xldir))
850+
{
851+
fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
849852
progname, XLOGDIR, strerror(errno));
850853
exit(1);
851854
}
852-
closedir(xldir);
853855
}
854856

855857

@@ -873,8 +875,7 @@ KillExistingArchiveStatus(void)
873875
exit(1);
874876
}
875877

876-
errno = 0;
877-
while ((xlde = readdir(xldir)) != NULL)
878+
while (errno = 0, (xlde = readdir(xldir)) != NULL)
878879
{
879880
if (strspn(xlde->d_name, "0123456789ABCDEF") == 24 &&
880881
(strcmp(xlde->d_name + 24, ".ready") == 0 ||
@@ -888,25 +889,27 @@ KillExistingArchiveStatus(void)
888889
exit(1);
889890
}
890891
}
891-
errno = 0;
892892
}
893-
#ifdef WIN32
894893

895-
/*
896-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
897-
* released version
898-
*/
894+
#ifdef WIN32
895+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
899896
if (GetLastError() == ERROR_NO_MORE_FILES)
900897
errno = 0;
901898
#endif
902899

903900
if (errno)
904901
{
905-
fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
902+
fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
903+
progname, ARCHSTATDIR, strerror(errno));
904+
exit(1);
905+
}
906+
907+
if (closedir(xldir))
908+
{
909+
fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
906910
progname, ARCHSTATDIR, strerror(errno));
907911
exit(1);
908912
}
909-
closedir(xldir);
910913
}
911914

912915

src/port/dirent.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,15 +105,19 @@ readdir(DIR *d)
105105
strcpy(d->ret.d_name, fd.cFileName); /* Both strings are MAX_PATH
106106
* long */
107107
d->ret.d_namlen = strlen(d->ret.d_name);
108+
108109
return &d->ret;
109110
}
110111

111112
int
112113
closedir(DIR *d)
113114
{
115+
int ret = 0;
116+
114117
if (d->handle != INVALID_HANDLE_VALUE)
115-
FindClose(d->handle);
118+
ret = !FindClose(d->handle);
116119
free(d->dirname);
117120
free(d);
118-
return 0;
121+
122+
return ret;
119123
}

src/port/dirmod.c

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

449449
filenames = (char **) palloc(fnsize * sizeof(char *));
450450

451-
errno = 0;
452-
while ((file = readdir(dir)) != NULL)
451+
while (errno = 0, (file = readdir(dir)) != NULL)
453452
{
454453
if (strcmp(file->d_name, ".") != 0 && strcmp(file->d_name, "..") != 0)
455454
{
@@ -461,17 +460,14 @@ pgfnames(const char *path)
461460
}
462461
filenames[numnames++] = pstrdup(file->d_name);
463462
}
464-
errno = 0;
465463
}
466-
#ifdef WIN32
467464

468-
/*
469-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
470-
* released version
471-
*/
465+
#ifdef WIN32
466+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
472467
if (GetLastError() == ERROR_NO_MORE_FILES)
473468
errno = 0;
474469
#endif
470+
475471
if (errno)
476472
{
477473
#ifndef FRONTEND
@@ -484,7 +480,15 @@ pgfnames(const char *path)
484480

485481
filenames[numnames] = NULL;
486482

487-
closedir(dir);
483+
if (closedir(dir))
484+
{
485+
#ifndef FRONTEND
486+
elog(WARNING, "could not close directory \"%s\": %m", path);
487+
#else
488+
fprintf(stderr, _("could not close directory \"%s\": %s\n"),
489+
path, strerror(errno));
490+
#endif
491+
}
488492

489493
return filenames;
490494
}

src/port/pgcheckdir.c

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,12 @@ pg_check_dir(const char *dir)
3232
DIR *chkdir;
3333
struct dirent *file;
3434

35-
errno = 0;
36-
3735
chkdir = opendir(dir);
3836

3937
if (chkdir == NULL)
4038
return (errno == ENOENT) ? 0 : -1;
4139

42-
while ((file = readdir(chkdir)) != NULL)
40+
while (errno = 0, (file = readdir(chkdir)) != NULL)
4341
{
4442
if (strcmp(".", file->d_name) == 0 ||
4543
strcmp("..", file->d_name) == 0)
@@ -55,18 +53,12 @@ pg_check_dir(const char *dir)
5553
}
5654

5755
#ifdef WIN32
58-
59-
/*
60-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
61-
* released version
62-
*/
56+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
6357
if (GetLastError() == ERROR_NO_MORE_FILES)
6458
errno = 0;
6559
#endif
6660

67-
closedir(chkdir);
68-
69-
if (errno != 0)
61+
if (errno || closedir(chkdir))
7062
result = -1; /* some kind of I/O error? */
7163

7264
return result;

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