Re: pg11+: pg_ls_*dir LIMIT 1: temporary files .. not closed at end-of-transaction - Mailing list pgsql-hackers

From Tom Lane
Subject Re: pg11+: pg_ls_*dir LIMIT 1: temporary files .. not closed at end-of-transaction
Date
Msg-id 27064.1585499825@sss.pgh.pa.us
Whole thread Raw
In response to Re: pg11+: pg_ls_*dir LIMIT 1: temporary files .. not closed at end-of-transaction  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: pg11+: pg_ls_*dir LIMIT 1: temporary files .. not closed atend-of-transaction  (Justin Pryzby <pryzby@telsasoft.com>)
List pgsql-hackers
I wrote:
> Justin Pryzby <pryzby@telsasoft.com> writes:
>> Maybe we should lstat() the file to determine if it's a dangling link; if
>> lstat() fails, then skip it.  Currently, we use stat(), which shows metdata of
>> a link's *target*.  Maybe we'd change that.

> Hm, good point that ENOENT could refer to a symlink's target.  Still,
> I'm not sure it's worth going out of our way to disambiguate that,
> given that these directories aren't really supposed to contain symlinks.
> (And on the third hand, if they aren't supposed to, then maybe these
> functions needn't look through any symlinks?  In which case just
> substituting lstat for stat would resolve the ambiguity.)

After looking at the callers of pg_ls_dir_files, and noticing that
it's already defined to ignore anything that's not a regular file,
I think switching to lstat makes sense.

I also grepped the other uses of ReadDir[Extended], and didn't see
any other ones that seemed desperately in need of changing.

So the attached seems like a sufficient fix.

            regards, tom lane

diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c
index 01185f2..8429a12 100644
--- a/src/backend/utils/adt/genfile.c
+++ b/src/backend/utils/adt/genfile.c
@@ -596,10 +596,15 @@ pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir, bool missing_ok)

         /* Get the file info */
         snprintf(path, sizeof(path), "%s/%s", dir, de->d_name);
-        if (stat(path, &attrib) < 0)
+        if (lstat(path, &attrib) < 0)
+        {
+            /* Ignore concurrently-deleted files, else complain */
+            if (errno == ENOENT)
+                continue;
             ereport(ERROR,
                     (errcode_for_file_access(),
                      errmsg("could not stat file \"%s\": %m", path)));
+        }

         /* Ignore anything but regular files */
         if (!S_ISREG(attrib.st_mode))

pgsql-hackers by date:

Previous
From: Tomas Vondra
Date:
Subject: Re: PATCH: logical_work_mem and logical streaming of largein-progress transactions
Next
From: Tom Lane
Date:
Subject: Re: Can we get rid of GetLocaleInfoEx() yet?