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

Lines changed: 14 additions & 2 deletions
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

Lines changed: 15 additions & 2 deletions
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

Lines changed: 1 addition & 4 deletions
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

Lines changed: 7 additions & 5 deletions
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

Lines changed: 20 additions & 2 deletions
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

Lines changed: 15 additions & 2 deletions
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

Lines changed: 30 additions & 27 deletions
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

Lines changed: 11 additions & 8 deletions
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

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
}

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