pg_verifybackup / pg_combinebackup: missing readdir() error check in directory scan
Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.
You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:
docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t253885psql -h localhost -U postgresBuilt from patchset v1 (message #1), October 22, 2026 at 07:20 AM.
Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:
git clone --branch t253885_1 https://github.com/hackorum-dev/postgres.gitIn a checkout you already have, add the fork once:
git remote add hackorum https://github.com/hackorum-dev/postgres.gitthen, for this patchset and every later one:
git fetch hackorum t253885_1 && git checkout t253885_1Patchset v1 (message #1) is on t253885_1
Hi,
While reading pg_verifybackup sources I noticed that the directory scan
never
checks errno after the readdir() loop, although similar loops elsewhere in
the tree does. And pg_combinebackup has the same problem:
while (errno = 0, (dirent = readdir(dir)) != NULL)
{
...
}
A failure partway through the scan is then indistinguishable from the end
of the directory. pg_verifybackup reports the entries it never reached as
"present in the manifest but not on disk"; pg_combinebackup writes out the
truncated directory and exits normally.
There are four such loops: verify_plain_backup_directory() and
verify_tar_backup() in pg_verifybackup.c, process_directory_recursively()
and scan_for_existing_tablespaces() in pg_combinebackup.c.
Commit 6f03927fce (Properly check for readdir/closedir() failures) added
the errno check to pg_archivecleanup.c, fd.c, initdb.c and other call
sites. pg_verifybackup and pg_combinebackup came later, which is probably
why the check never made it into their code.
The attached patch makes small changes to pg_verifybackup and
pg_combinebackup, adding the missing checks. pg_fatal() seems sufficient
for pg_combinebackup. For pg_verifybackup I don't think
report_backup_error() alone is enough: it keeps going, so the bogus
"missing file" reports remain and merely gain one more line. The patch
adds the directory to the ignore list as well, which is what the same
function already does when opendir() fails.
I simulated a readdir() failure on a plain backup of 21000 files.
pg_verifybackup reported 16732 of them as missing, though everyone was on
disk. With the patch it reports a single "could not read directory" error.
Unfortunately I couldn't come up with a portable test that would
demonstrate this; if someone can, I'd be grateful. The pattern seems clear
enough even without one.
--
Daria Lepikhova