Skip to content

Commit 6f03927

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 68a2e52 commit 6f03927

File tree

10 files changed

+122
-65
lines changed

10 files changed

+122
-65
lines changed

contrib/pg_archivecleanup/pg_archivecleanup.c

+14-2
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ CleanupPriorWALFiles(void)
106106

107107
if ((xldir = opendir(archiveLocation)) != NULL)
108108
{
109-
while ((xlde = readdir(xldir)) != NULL)
109+
while (errno = 0, (xlde = readdir(xldir)) != NULL)
110110
{
111111
strncpy(walfile, xlde->d_name, MAXPGPATH);
112112
TrimExtension(walfile, additional_ext);
@@ -164,7 +164,19 @@ CleanupPriorWALFiles(void)
164164
}
165165
}
166166
}
167-
closedir(xldir);
167+
168+
#ifdef WIN32
169+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
170+
if (GetLastError() == ERROR_NO_MORE_FILES)
171+
errno = 0;
172+
#endif
173+
174+
if (errno)
175+
fprintf(stderr, "%s: could not read archive location \"%s\": %s\n",
176+
progname, archiveLocation, strerror(errno));
177+
if (closedir(xldir))
178+
fprintf(stderr, "%s: could not close archive location \"%s\": %s\n",
179+
progname, archiveLocation, strerror(errno));
168180
}
169181
else
170182
fprintf(stderr, "%s: could not open archive location \"%s\": %s\n",

contrib/pg_standby/pg_standby.c

+15-2
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ CustomizableCleanupPriorWALFiles(void)
245245
*/
246246
if ((xldir = opendir(archiveLocation)) != NULL)
247247
{
248-
while ((xlde = readdir(xldir)) != NULL)
248+
while (errno = 0, (xlde = readdir(xldir)) != NULL)
249249
{
250250
/*
251251
* We ignore the timeline part of the XLOG segment identifiers
@@ -283,14 +283,27 @@ CustomizableCleanupPriorWALFiles(void)
283283
}
284284
}
285285
}
286+
287+
#ifdef WIN32
288+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
289+
if (GetLastError() == ERROR_NO_MORE_FILES)
290+
errno = 0;
291+
#endif
292+
293+
if (errno)
294+
fprintf(stderr, "%s: could not read archive location \"%s\": %s\n",
295+
progname, archiveLocation, strerror(errno));
286296
if (debug)
287297
fprintf(stderr, "\n");
288298
}
289299
else
290300
fprintf(stderr, "%s: could not open archive location \"%s\": %s\n",
291301
progname, archiveLocation, strerror(errno));
292302

293-
closedir(xldir);
303+
if (closedir(xldir))
304+
fprintf(stderr, "%s: could not close archive location \"%s\": %s\n",
305+
progname, archiveLocation, strerror(errno));
306+
294307
fflush(stderr);
295308
}
296309
}

src/backend/storage/file/fd.c

+1-4
Original file line numberDiff line numberDiff line change
@@ -1957,10 +1957,7 @@ ReadDir(DIR *dir, const char *dirname)
19571957
return dent;
19581958

19591959
#ifdef WIN32
1960-
/*
1961-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
1962-
* released version
1963-
*/
1960+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
19641961
if (GetLastError() == ERROR_NO_MORE_FILES)
19651962
errno = 0;
19661963
#endif

src/bin/initdb/initdb.c

+7-5
Original file line numberDiff line numberDiff line change
@@ -565,10 +565,7 @@ walkdir(char *path, void (*action) (char *fname, bool isdir))
565565
}
566566

567567
#ifdef WIN32
568-
/*
569-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
570-
* released version
571-
*/
568+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
572569
if (GetLastError() == ERROR_NO_MORE_FILES)
573570
errno = 0;
574571
#endif
@@ -580,7 +577,12 @@ walkdir(char *path, void (*action) (char *fname, bool isdir))
580577
exit_nicely();
581578
}
582579

583-
closedir(dir);
580+
if (closedir(dir))
581+
{
582+
fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
583+
progname, path, strerror(errno));
584+
exit_nicely();
585+
}
584586

585587
/*
586588
* It's important to fsync the destination directory itself as individual

src/bin/pg_basebackup/pg_receivexlog.c

+20-2
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ FindStreamingStart(uint32 *tli)
139139
disconnect_and_exit(1);
140140
}
141141

142-
while ((dirent = readdir(dir)) != NULL)
142+
while (errno = 0, (dirent = readdir(dir)) != NULL)
143143
{
144144
uint32 tli;
145145
XLogSegNo segno;
@@ -209,7 +209,25 @@ FindStreamingStart(uint32 *tli)
209209
}
210210
}
211211

212-
closedir(dir);
212+
#ifdef WIN32
213+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
214+
if (GetLastError() == ERROR_NO_MORE_FILES)
215+
errno = 0;
216+
#endif
217+
218+
if (errno)
219+
{
220+
fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
221+
progname, basedir, strerror(errno));
222+
disconnect_and_exit(1);
223+
}
224+
225+
if (closedir(dir))
226+
{
227+
fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
228+
progname, basedir, strerror(errno));
229+
disconnect_and_exit(1);
230+
}
213231

214232
if (high_segno > 0)
215233
{

src/bin/pg_dump/pg_backup_directory.c

+15-2
Original file line numberDiff line numberDiff line change
@@ -177,15 +177,28 @@ InitArchiveFmt_Directory(ArchiveHandle *AH)
177177
struct dirent *d;
178178

179179
is_empty = true;
180-
while ((d = readdir(dir)))
180+
while (errno = 0, (d = readdir(dir)))
181181
{
182182
if (strcmp(d->d_name, ".") != 0 && strcmp(d->d_name, "..") != 0)
183183
{
184184
is_empty = false;
185185
break;
186186
}
187187
}
188-
closedir(dir);
188+
189+
#ifdef WIN32
190+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
191+
if (GetLastError() == ERROR_NO_MORE_FILES)
192+
errno = 0;
193+
#endif
194+
195+
if (errno)
196+
exit_horribly(modulename, "could not read directory \"%s\": %s\n",
197+
ctx->directory, strerror(errno));
198+
199+
if (closedir(dir))
200+
exit_horribly(modulename, "could not close directory \"%s\": %s\n",
201+
ctx->directory, strerror(errno));
189202
}
190203
}
191204

src/bin/pg_resetxlog/pg_resetxlog.c

+30-27
Original file line numberDiff line numberDiff line change
@@ -821,8 +821,7 @@ FindEndOfXLOG(void)
821821
exit(1);
822822
}
823823

824-
errno = 0;
825-
while ((xlde = readdir(xldir)) != NULL)
824+
while (errno = 0, (xlde = readdir(xldir)) != NULL)
826825
{
827826
if (strlen(xlde->d_name) == 24 &&
828827
strspn(xlde->d_name, "0123456789ABCDEF") == 24)
@@ -844,25 +843,27 @@ FindEndOfXLOG(void)
844843
if (segno > newXlogSegNo)
845844
newXlogSegNo = segno;
846845
}
847-
errno = 0;
848846
}
849847

850848
#ifdef WIN32
851-
/*
852-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
853-
* released version
854-
*/
849+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
855850
if (GetLastError() == ERROR_NO_MORE_FILES)
856851
errno = 0;
857852
#endif
858853

859854
if (errno)
860855
{
861-
fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
856+
fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
857+
progname, XLOGDIR, strerror(errno));
858+
exit(1);
859+
}
860+
861+
if (closedir(xldir))
862+
{
863+
fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
862864
progname, XLOGDIR, strerror(errno));
863865
exit(1);
864866
}
865-
closedir(xldir);
866867

867868
/*
868869
* Finally, convert to new xlog seg size, and advance by one to ensure we
@@ -892,8 +893,7 @@ KillExistingXLOG(void)
892893
exit(1);
893894
}
894895

895-
errno = 0;
896-
while ((xlde = readdir(xldir)) != NULL)
896+
while (errno = 0, (xlde = readdir(xldir)) != NULL)
897897
{
898898
if (strlen(xlde->d_name) == 24 &&
899899
strspn(xlde->d_name, "0123456789ABCDEF") == 24)
@@ -906,25 +906,27 @@ KillExistingXLOG(void)
906906
exit(1);
907907
}
908908
}
909-
errno = 0;
910909
}
911910

912911
#ifdef WIN32
913-
/*
914-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
915-
* released version
916-
*/
912+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
917913
if (GetLastError() == ERROR_NO_MORE_FILES)
918914
errno = 0;
919915
#endif
920916

921917
if (errno)
922918
{
923-
fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
919+
fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
920+
progname, XLOGDIR, strerror(errno));
921+
exit(1);
922+
}
923+
924+
if (closedir(xldir))
925+
{
926+
fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
924927
progname, XLOGDIR, strerror(errno));
925928
exit(1);
926929
}
927-
closedir(xldir);
928930
}
929931

930932

@@ -948,8 +950,7 @@ KillExistingArchiveStatus(void)
948950
exit(1);
949951
}
950952

951-
errno = 0;
952-
while ((xlde = readdir(xldir)) != NULL)
953+
while (errno = 0, (xlde = readdir(xldir)) != NULL)
953954
{
954955
if (strspn(xlde->d_name, "0123456789ABCDEF") == 24 &&
955956
(strcmp(xlde->d_name + 24, ".ready") == 0 ||
@@ -963,25 +964,27 @@ KillExistingArchiveStatus(void)
963964
exit(1);
964965
}
965966
}
966-
errno = 0;
967967
}
968968

969969
#ifdef WIN32
970-
/*
971-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
972-
* released version
973-
*/
970+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
974971
if (GetLastError() == ERROR_NO_MORE_FILES)
975972
errno = 0;
976973
#endif
977974

978975
if (errno)
979976
{
980-
fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
977+
fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
978+
progname, ARCHSTATDIR, strerror(errno));
979+
exit(1);
980+
}
981+
982+
if (closedir(xldir))
983+
{
984+
fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
981985
progname, ARCHSTATDIR, strerror(errno));
982986
exit(1);
983987
}
984-
closedir(xldir);
985988
}
986989

987990

src/common/pgfnames.c

+11-8
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@ pgfnames(const char *path)
5050

5151
filenames = (char **) palloc(fnsize * sizeof(char *));
5252

53-
errno = 0;
54-
while ((file = readdir(dir)) != NULL)
53+
while (errno = 0, (file = readdir(dir)) != NULL)
5554
{
5655
if (strcmp(file->d_name, ".") != 0 && strcmp(file->d_name, "..") != 0)
5756
{
@@ -63,14 +62,10 @@ pgfnames(const char *path)
6362
}
6463
filenames[numnames++] = pstrdup(file->d_name);
6564
}
66-
errno = 0;
6765
}
6866

6967
#ifdef WIN32
70-
/*
71-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
72-
* released version
73-
*/
68+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
7469
if (GetLastError() == ERROR_NO_MORE_FILES)
7570
errno = 0;
7671
#endif
@@ -87,7 +82,15 @@ pgfnames(const char *path)
8782

8883
filenames[numnames] = NULL;
8984

90-
closedir(dir);
85+
if (closedir(dir))
86+
{
87+
#ifndef FRONTEND
88+
elog(WARNING, "could not close directory \"%s\": %m", path);
89+
#else
90+
fprintf(stderr, _("could not close directory \"%s\": %s\n"),
91+
path, strerror(errno));
92+
#endif
93+
}
9194

9295
return filenames;
9396
}

src/port/dirent.c

+6-2
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
}

0 commit comments

Comments
 (0)