Skip to content

Commit fb91874

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 7f857a5 commit fb91874

File tree

10 files changed

+127
-72
lines changed

10 files changed

+127
-72
lines changed

contrib/pg_archivecleanup/pg_archivecleanup.c

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

118118
if ((xldir = opendir(archiveLocation)) != NULL)
119119
{
120-
while ((xlde = readdir(xldir)) != NULL)
120+
while (errno = 0, (xlde = readdir(xldir)) != NULL)
121121
{
122122
strncpy(walfile, xlde->d_name, MAXPGPATH);
123123
TrimExtension(walfile, additional_ext);
@@ -175,7 +175,19 @@ CleanupPriorWALFiles(void)
175175
}
176176
}
177177
}
178-
closedir(xldir);
178+
179+
#ifdef WIN32
180+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
181+
if (GetLastError() == ERROR_NO_MORE_FILES)
182+
errno = 0;
183+
#endif
184+
185+
if (errno)
186+
fprintf(stderr, "%s: could not read archive location \"%s\": %s\n",
187+
progname, archiveLocation, strerror(errno));
188+
if (closedir(xldir))
189+
fprintf(stderr, "%s: could not close archive location \"%s\": %s\n",
190+
progname, archiveLocation, strerror(errno));
179191
}
180192
else
181193
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
}

src/backend/storage/file/fd.c

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

19031903
#ifdef WIN32
1904-
1905-
/*
1906-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
1907-
* released version
1908-
*/
1904+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
19091905
if (GetLastError() == ERROR_NO_MORE_FILES)
19101906
errno = 0;
19111907
#endif

src/bin/initdb/initdb.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -557,11 +557,7 @@ walkdir(char *path, void (*action) (char *fname, bool isdir))
557557
}
558558

559559
#ifdef WIN32
560-
561-
/*
562-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
563-
* released version
564-
*/
560+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
565561
if (GetLastError() == ERROR_NO_MORE_FILES)
566562
errno = 0;
567563
#endif
@@ -573,7 +569,12 @@ walkdir(char *path, void (*action) (char *fname, bool isdir))
573569
exit_nicely();
574570
}
575571

576-
closedir(dir);
572+
if (closedir(dir))
573+
{
574+
fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
575+
progname, path, strerror(errno));
576+
exit_nicely();
577+
}
577578

578579
/*
579580
* 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
@@ -138,7 +138,7 @@ FindStreamingStart(uint32 *tli)
138138
disconnect_and_exit(1);
139139
}
140140

141-
while ((dirent = readdir(dir)) != NULL)
141+
while (errno = 0, (dirent = readdir(dir)) != NULL)
142142
{
143143
uint32 tli;
144144
XLogSegNo segno;
@@ -208,7 +208,25 @@ FindStreamingStart(uint32 *tli)
208208
}
209209
}
210210

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

213231
if (high_segno > 0)
214232
{

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: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -765,8 +765,7 @@ FindEndOfXLOG(void)
765765
exit(1);
766766
}
767767

768-
errno = 0;
769-
while ((xlde = readdir(xldir)) != NULL)
768+
while (errno = 0, (xlde = readdir(xldir)) != NULL)
770769
{
771770
if (strlen(xlde->d_name) == 24 &&
772771
strspn(xlde->d_name, "0123456789ABCDEF") == 24)
@@ -788,25 +787,27 @@ FindEndOfXLOG(void)
788787
if (segno > newXlogSegNo)
789788
newXlogSegNo = segno;
790789
}
791-
errno = 0;
792790
}
793-
#ifdef WIN32
794791

795-
/*
796-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
797-
* released version
798-
*/
792+
#ifdef WIN32
793+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
799794
if (GetLastError() == ERROR_NO_MORE_FILES)
800795
errno = 0;
801796
#endif
802797

803798
if (errno)
804799
{
805-
fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
800+
fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
801+
progname, XLOGDIR, strerror(errno));
802+
exit(1);
803+
}
804+
805+
if (closedir(xldir))
806+
{
807+
fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
806808
progname, XLOGDIR, strerror(errno));
807809
exit(1);
808810
}
809-
closedir(xldir);
810811

811812
/*
812813
* Finally, convert to new xlog seg size, and advance by one to ensure we
@@ -836,8 +837,7 @@ KillExistingXLOG(void)
836837
exit(1);
837838
}
838839

839-
errno = 0;
840-
while ((xlde = readdir(xldir)) != NULL)
840+
while (errno = 0, (xlde = readdir(xldir)) != NULL)
841841
{
842842
if (strlen(xlde->d_name) == 24 &&
843843
strspn(xlde->d_name, "0123456789ABCDEF") == 24)
@@ -850,25 +850,27 @@ KillExistingXLOG(void)
850850
exit(1);
851851
}
852852
}
853-
errno = 0;
854853
}
855-
#ifdef WIN32
856854

857-
/*
858-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
859-
* released version
860-
*/
855+
#ifdef WIN32
856+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
861857
if (GetLastError() == ERROR_NO_MORE_FILES)
862858
errno = 0;
863859
#endif
864860

865861
if (errno)
866862
{
867-
fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
863+
fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
864+
progname, XLOGDIR, strerror(errno));
865+
exit(1);
866+
}
867+
868+
if (closedir(xldir))
869+
{
870+
fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
868871
progname, XLOGDIR, strerror(errno));
869872
exit(1);
870873
}
871-
closedir(xldir);
872874
}
873875

874876

@@ -892,8 +894,7 @@ KillExistingArchiveStatus(void)
892894
exit(1);
893895
}
894896

895-
errno = 0;
896-
while ((xlde = readdir(xldir)) != NULL)
897+
while (errno = 0, (xlde = readdir(xldir)) != NULL)
897898
{
898899
if (strspn(xlde->d_name, "0123456789ABCDEF") == 24 &&
899900
(strcmp(xlde->d_name + 24, ".ready") == 0 ||
@@ -907,25 +908,27 @@ KillExistingArchiveStatus(void)
907908
exit(1);
908909
}
909910
}
910-
errno = 0;
911911
}
912-
#ifdef WIN32
913912

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

922919
if (errno)
923920
{
924-
fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
921+
fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
922+
progname, ARCHSTATDIR, strerror(errno));
923+
exit(1);
924+
}
925+
926+
if (closedir(xldir))
927+
{
928+
fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
925929
progname, ARCHSTATDIR, strerror(errno));
926930
exit(1);
927931
}
928-
closedir(xldir);
929932
}
930933

931934

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
@@ -382,8 +382,7 @@ pgfnames(const char *path)
382382

383383
filenames = (char **) palloc(fnsize * sizeof(char *));
384384

385-
errno = 0;
386-
while ((file = readdir(dir)) != NULL)
385+
while (errno = 0, (file = readdir(dir)) != NULL)
387386
{
388387
if (strcmp(file->d_name, ".") != 0 && strcmp(file->d_name, "..") != 0)
389388
{
@@ -395,17 +394,14 @@ pgfnames(const char *path)
395394
}
396395
filenames[numnames++] = pstrdup(file->d_name);
397396
}
398-
errno = 0;
399397
}
400-
#ifdef WIN32
401398

402-
/*
403-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
404-
* released version
405-
*/
399+
#ifdef WIN32
400+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
406401
if (GetLastError() == ERROR_NO_MORE_FILES)
407402
errno = 0;
408403
#endif
404+
409405
if (errno)
410406
{
411407
#ifndef FRONTEND
@@ -418,7 +414,15 @@ pgfnames(const char *path)
418414

419415
filenames[numnames] = NULL;
420416

421-
closedir(dir);
417+
if (closedir(dir))
418+
{
419+
#ifndef FRONTEND
420+
elog(WARNING, "could not close directory \"%s\": %m", path);
421+
#else
422+
fprintf(stderr, _("could not close directory \"%s\": %s\n"),
423+
path, strerror(errno));
424+
#endif
425+
}
422426

423427
return filenames;
424428
}

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