8000 Properly check for readdir/closedir() failures · dirbacke/postgres@de13cea · GitHub
[go: up one dir, main page]

Skip to content {"props":{"docsUrl":"https://docs.github.com/get-started/accessibility/keyboard-shortcuts"}}

Commit de13cea

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 e1fa2d4 commit de13cea

File tree

6 files changed

+71
-57
lines changed

6 files changed

+71
-57
lines changed

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
}

src/backend/storage/file/fd.c

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

15841584
#ifdef WIN32
1585-
1586-
/*
1587-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
1588-
* released version
1589-
*/
1585+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
15901586
if (GetLastError() == ERROR_NO_MORE_FILES)
15911587
errno = 0;
15921588
#endif

src/bin/initdb/initdb.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -861,7 +861,7 @@ check_data_dir(char *dir)
861861
if (!chkdir)
862862
return (errno == ENOENT) ? 0 : -1;
863863

864-
while ((file = readdir(chkdir)) != NULL)
864+
while (errno = 0, (file = readdir(chkdir)) != NULL)
865865
{
866866
if (strcmp(".", file->d_name) == 0 ||
867867
strcmp("..", file->d_name) == 0)
@@ -877,18 +877,12 @@ check_data_dir(char *dir)
877877
}
878878

879879
#ifdef WIN32
880-
881-
/*
882-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
883-
* released version
884-
*/
880+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
885881
if (GetLastError() == ERROR_NO_MORE_FILES)
886882
errno = 0;
887883
#endif
888884

889-
closedir(chkdir);
890-
891-
if (errno != 0)
885+
if (errno || closedir(chkdir))
892886
result = -1; /* some kind of I/O error? */
893887

894888
return result;

src/bin/pg_resetxlog/pg_resetxlog.c

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -700,8 +700,7 @@ FindEndOfXLOG(void)
700700
exit(1);
701701
}
702702

703-
errno = 0;
704-
while ((xlde = readdir(xldir)) != NULL)
703+
while (errno = 0, (xlde = readdir(xldir)) != NULL)
705704
{
706705
if (strlen(xlde->d_name) == 24 &&
707706
strspn(xlde->d_name, "0123456789ABCDEF") == 24)
@@ -725,25 +724,27 @@ FindEndOfXLOG(void)
725724
newXlogSeg = seg;
726725
}
727726
}
728-
errno = 0;
729727
}
730-
#ifdef WIN32
731728

732-
/*
733-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
734-
* released version
735-
*/
729+
#ifdef WIN32
730+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
736731
if (GetLastError() == ERROR_NO_MORE_FILES)
737732
errno = 0;
738733
#endif
739734

740735
if (errno)
741736
{
742-
fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
737+
fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
738+
progname, XLOGDIR, strerror(errno));
739+
exit(1);
740+
}
741+
742+
if (closedir(xldir))
743+
{
744+
fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
743745
progname, XLOGDIR, strerror(errno));
744746
exit(1);
745747
}
746-
closedir(xldir);
747748

748749
/*
749750
* Finally, convert to new xlog seg size, and advance by one to ensure we
@@ -775,8 +776,7 @@ KillExistingXLOG(void)
775776
exit(1);
776777
}
777778

778-
errno = 0;
779-
while ((xlde = readdir(xldir)) != NULL)
779+
while (errno = 0, (xlde = readdir(xldir)) != NULL)
780780
{
781781
if (strlen(xlde->d_name) == 24 &&
782782
strspn(xlde->d_name, "0123456789ABCDEF") == 24)
@@ -789,25 +789,27 @@ KillExistingXLOG(void)
789789
exit(1);
790790
}
791791
}
792-
errno = 0;
793792
}
794-
#ifdef WIN32
795793

796-
/*
797-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
798-
* released version
799-
*/
794+
#ifdef WIN32
795+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
800796
if (GetLastError() == ERROR_NO_MORE_FILES)
801797
errno = 0;
802798
#endif
803799

804800
if (errno)
805801
{
806-
fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
802+
fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
803+
progname, XLOGDIR, strerror(errno));
804+
exit(1);
805+
}
806+
807+
if (closedir(xldir))
808+
{
809+
fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
807810
progname, XLOGDIR, strerror(errno));
808811
exit(1);
809812
}
810-
closedir(xldir);
811813
}
812814

813815

@@ -831,8 +833,7 @@ KillExistingArchiveStatus(void)
831833
exit(1);
832834
}
833835

834-
errno = 0;
835-
while ((xlde = readdir(xldir)) != NULL)
836+
while (errno = 0, (xlde = readdir(xldir)) != NULL)
836837
{
837838
if (strspn(xlde->d_name, "0123456789ABCDEF") == 24 &&
838839
(strcmp(xlde->d_name + 24, ".ready") == 0 ||
@@ -846,25 +847,27 @@ KillExistingArchiveStatus(void)
846847
exit(1);
847848
}
848849
}
849-
errno = 0;
850850
}
851-
#ifdef WIN32
852851

853-
/*
854-< F987 div class="diff-text-inner"> * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
855-
* released version
856-
*/
852+
#ifdef WIN32
853+
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
857854
if (GetLastError() == ERROR_NO_MORE_FILES)
858855
errno = 0;
859856
#endif
860857

861858
if (errno)
862859
{
863-
fprintf(stderr, _("%s: could not read from directory \"%s\": %s\n"),
860+
fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
861+
progname, ARCHSTATDIR, strerror(errno));
862+
exit(1);
863+
}
864+
865+
if (closedir(xldir))
866+
{
867+
fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
864868
progname, ARCHSTATDIR, strerror(errno));
865869
exit(1);
866870
}
867-
closedir(xldir);
868871
}
869872

870873

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