[RFC] Call lstat() before setting flags to FTW_SLN

Message ID 1487981243-16382-1-git-send-email-tuliom@linux.vnet.ibm.com
State Dropped
Headers

Commit Message

Tulio Magno Quites Machado Filho Feb. 25, 2017, 12:07 a.m. UTC
  POSIX.1-2008 doesn't describe this behavior explicitly in this case.
However, passing a stat buffer returned by a failed fstatat() doesn't
seem the correct behavior either.

Any comments?

---8<---

POSIX.1-2008 states the following for ftw():

    If the object is a symbolic link and stat() failed, it is unspecified
    whether ftw() passes FTW_SL or FTW_NS to the user-supplied function.

However, nftw() defines FTW_SLN, which is returned if "the object is a
symbolic link that does not name an existing file".

It also states:

    At each file it encounters, nftw() shall call the user-supplied function
    fn with four arguments:
    ...
    - The second argument is a pointer to the stat buffer containing
      information on the object, filled in as if fstatat(), stat(), or
      lstat() had been called to retrieve the information.

In the current implementation, when FTW_PHYS is not included and the object
is a symlink that doesn't name an existing file, the call to fstatat()
returns -1, flags is set to FTW_SLN and fn is called with a stat buffer
from a failed fstatat() call.

2017-02-24  Tulio Magno Quites Machado Filho  <tuliom@linux.vnet.ibm.com>

	* io/ftw.c (process_entry): Call LXSTAT() if FXSTATAT() failed
	and the object is a symbolic link.
---
 io/ftw.c | 2 --
 1 file changed, 2 deletions(-)
  

Comments

DJ Delorie Feb. 25, 2017, 3:26 a.m. UTC | #1
"Tulio Magno Quites Machado Filho" <tuliom@linux.vnet.ibm.com> writes:
> POSIX.1-2008 doesn't describe this behavior explicitly in this case.

See also https://bugzilla.redhat.com/show_bug.cgi?id=1422736
and http://austingroupbugs.net/view.php?id=1121

The spec also says "If FTW_PHYS is clear ... nftw() shall follow links
instead of reporting them" but calling lstat() *is* reporting them,
which the spec specifically forbids, if you read it that way.

Hence, the clarification I requested from the Austin Group.  If the spec
says we're not allowed to call lstat(), your patch is inappropriate.  If
we are allowed to call lstat(), I think your patch is wrong - it may
return FTW_NS for cases where lstat() might fail, where FTW_SLN should
have been returned.  I can't think of any such cases, but I've been
surprised before.  Also, cases where FTW_NS should be returned due to
errors reading *non*dangling links should be preserved.

(I suspect calling LXSTAT() when we set the flag where your patch
 deleted lines, should result in the desired behavior, though, possibly
 with a test for !FTW_PHYS)
  
Tulio Magno Quites Machado Filho Feb. 27, 2017, 1:12 p.m. UTC | #2
DJ Delorie <dj@redhat.com> writes:

> "Tulio Magno Quites Machado Filho" <tuliom@linux.vnet.ibm.com> writes:
>> POSIX.1-2008 doesn't describe this behavior explicitly in this case.
>
> See also https://bugzilla.redhat.com/show_bug.cgi?id=1422736
> and http://austingroupbugs.net/view.php?id=1121
>
> The spec also says "If FTW_PHYS is clear ... nftw() shall follow links
> instead of reporting them" but calling lstat() *is* reporting them,
> which the spec specifically forbids, if you read it that way.

Agreed.

> Hence, the clarification I requested from the Austin Group.  If the spec
> says we're not allowed to call lstat(), your patch is inappropriate.  If
> we are allowed to call lstat(), I think your patch is wrong - it may
> return FTW_NS for cases where lstat() might fail, where FTW_SLN should
> have been returned.  I can't think of any such cases, but I've been
> surprised before.  Also, cases where FTW_NS should be returned due to
> errors reading *non*dangling links should be preserved.

I think that's yet another interpretation of the spec.
So, we have to wait for their position.

> (I suspect calling LXSTAT() when we set the flag where your patch
>  deleted lines, should result in the desired behavior, though, possibly
>  with a test for !FTW_PHYS)

Ack.

Thanks for the references!
  

Patch

diff --git a/io/ftw.c b/io/ftw.c
index 140a237..21ea8a7 100644
--- a/io/ftw.c
+++ b/io/ftw.c
@@ -426,8 +426,6 @@  process_entry (struct ftw_data *data, struct dir_data *dir, const char *name,
 	result = -1;
       else if (data->flags & FTW_PHYS)
 	flag = FTW_NS;
-      else if (d_type == DT_LNK)
-	flag = FTW_SLN;
       else
 	{
 	  if (dir->streamfd != -1)