Skip to content

Commit 4859a71

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 192856b commit 4859a71

File tree

8 files changed

+109
-63
lines changed

8 files changed

+109
-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 archiveLocation \"%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,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
}

contrib/pg_upgrade/file.c

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ pg_scandir_internal(migratorContext *ctx, 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) (direntry))
@@ -318,7 +318,17 @@ pg_scandir_internal(migratorContext *ctx, const char *dirname,
318318
}
319319
}
320320

321-
closedir(dirdesc);
321+
#ifdef WIN32
322+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
323+
if (GetLastError() == ERROR_NO_MORE_FILES)
324+
errno = 0;
325+
#endif
326+
327+
if (errno)
328+
pg_log(ctx, PG_FATAL, "Could not read directory \"%s\": %s\n", dirname, getErrorText(errno));
329+
330+
if (closedir(dirdesc))
331+
pg_log(ctx, PG_FATAL, "Could not close directory \"%s\": %s\n", dirname, getErrorText(errno));
322332

323333
return count;
324334
}
@@ -415,7 +425,7 @@ copy_dir(const char *src, const char *dst, bool force)
415425
return -1;
416426
}
417427

418-
while ((de = readdir(srcdir)) != NULL)
428+
while (errno = 0, (de = readdir(srcdir)) != NULL)
419429
{
420430
char src_file[MAXPGPATH];
421431
char dest_file[MAXPGPATH];
@@ -460,9 +470,19 @@ copy_dir(const char *src, const char *dst, bool force)
460470
}
461471
}
462472

473+
#ifdef WIN32
474+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
475+
if (GetLastError() == ERROR_NO_MORE_FILES)
476+
errno = 0;
477+
#endif
478+
479+
if (errno)
480+
return -1;
481+
463482
if (srcdir != NULL)
464483
{
465-
closedir(srcdir);
484+
if (closedir(srcdir))
485+
return -1;
466486
srcdir = NULL;
467487
}
468488
return 1;

src/backend/storage/file/fd.c

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

16161616
#ifdef WIN32
1617-
1618-
/*
1619-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
1620-
* released version
1621-
*/
1617+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
16221618
if (GetLastError() == ERROR_NO_MORE_FILES)
16231619
errno = 0;
16241620
#endif

src/bin/initdb/initdb.c

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

825-
while ((file = readdir(chkdir)) != NULL)
825+
while (errno = 0, (file = readdir(chkdir)) != NULL)
826826
{
827827
if (strcmp(".", file->d_name) == 0 ||
828828
strcmp("..", file->d_name) == 0)
@@ -838,18 +838,12 @@ check_data_dir(char *dir)
838838
}
839839

840840
#ifdef WIN32
841-
842-
/*
843-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
844-
* released version
845-
*/
841+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
846842
if (GetLastError() == ERROR_NO_MORE_FILES)
847843
errno = 0;
848844
#endif
849845

850-
closedir(chkdir);
851-
852-
if (errno != 0)
846+
if (errno || closedir(chkdir))
853847
result = -1; /* some kind of I/O error? */
854848

855849
return result;

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
@@ -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)