On Jan 27 13:53, Ken Brown via Cygwin-patches wrote:
> Allow fchmodat with the AT_SYMLINK_NOFOLLOW flag to succeed on
> non-symlinks.  Previously it always failed, as it does on Linux.  But
> POSIX permits it to succeed on non-symlinks even if it fails on
> symlinks.
> 
> The reason for following POSIX rather than Linux is to make gnulib
> report that fchmodat works on Cygwin.  This improves the efficiency of
> packages like GNU tar that use gnulib's fchmodat module.  Previously
> such packages would use a gnulib replacement for fchmodat on Cygwin.
> ---
>  winsup/cygwin/syscalls.cc | 20 +++++++++++++++-----
>  1 file changed, 15 insertions(+), 5 deletions(-)
> 
> diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
> index 4cc8d07f5..5da05b18a 100644
> --- a/winsup/cygwin/syscalls.cc
> +++ b/winsup/cygwin/syscalls.cc
> @@ -4787,17 +4787,27 @@ fchmodat (int dirfd, const char *pathname, mode_t 
> mode, int flags)
>    tmp_pathbuf tp;
>    __try
>      {
> -      if (flags)
> +      if (flags & ~AT_SYMLINK_NOFOLLOW)
>       {
> -       /* BSD has lchmod, but Linux does not.  POSIX says
> -          AT_SYMLINK_NOFOLLOW is allowed to fail on symlinks; but Linux
> -          blindly fails even for non-symlinks.  */
> -       set_errno ((flags & ~AT_SYMLINK_NOFOLLOW) ? EINVAL : EOPNOTSUPP);
> +       set_errno (EINVAL);
>         __leave;
>       }
>        char *path = tp.c_get ();
>        if (gen_full_path_at (path, dirfd, pathname))
>       __leave;
> +      if (flags)

For clarity, and on the off-chance that new flags are added to fchmodat,
it might be better to check for (flags & AT_SYMLINK_NOFOLLOW) here
explicitely.  Your choice.

> +     {
> +          /* BSD has lchmod, but Linux does not.  POSIX says
> +          AT_SYMLINK_NOFOLLOW is allowed to fail on symlinks.
> +          Linux blindly fails even for non-symlinks, but we allow
> +          it to succeed. */
> +       path_conv pc (path, PC_SYM_NOFOLLOW, stat_suffixes);
> +       if (pc.issymlink ())
> +         {
> +           set_errno (EOPNOTSUPP);
> +           __leave;
> +         }
> +     }
>        return chmod (path, mode);
>      }
>    __except (EFAULT) {}
> -- 
> 2.30.0

Looks good.


Thanks,
Corinna

Reply via email to