Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)