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