Subject: Re: bug#79433: 9.7: cp(1): lchownat(2/3) fallback bogus?

From: Steffen Nurpmeso <[email-masked]>
Date: Sat, 13 Sep 2025 16:56:05 +0200

Paul Eggert wrote in
 <[email-masked]>:
 |On 2025-09-11 04:49, Steffen Nurpmeso wrote:
 |>              if (lchownat (dst_dirfd, relname, p->st.st_uid, p->st.st_gid\
 |>              )
 |>                  != 0)
 |>    ...
 |>                      error (0, errno, _("failed to preserve ownership \
 |>                      for %s"),
 |>                             quoteaf (dst_name));
 |> 
 |>    Here there is no lchownat(3/2),
 |
 |No kernel or C library has lchownat; that's a convenience function 
 |defined in coreutils/lib/openat.h (taken from Gnulib), equivalent to 
 |fchownat (..., AT_SYMLINK_NOFOLLOW).
 |
 |What does "strace cp -a xb xc" say? I see this:

  geteuid()                               = 1000
  openat(AT_FDCWD, "c", O_RDONLY|O_PATH|O_DIRECTORY) = -1 ENOENT (No such file or directory)
  newfstatat(AT_FDCWD, "b", {st_mode=S_IFLNK|0777, st_size=1, ...}, AT_SYMLINK_NOFOLLOW) = 0
  newfstatat(AT_FDCWD, "c", 0x7ffdf869dea0, AT_SYMLINK_NOFOLLOW) = -1 ENOENT (No such file or directory)
  readlink("b", "a", 2)                   = 1
  symlinkat("a", AT_FDCWD, "c")           = 0
  newfstatat(AT_FDCWD, "c", {st_mode=S_IFLNK|0777, st_size=1, ...}, AT_SYMLINK_NOFOLLOW) = 0
  lchown("c", 1000, 1000)                 = 0
  fchmodat2(AT_FDCWD, "c", 0777, AT_SYMLINK_NOFOLLOW) = -1 ENOSYS (Function not implemented)
^^
  openat(AT_FDCWD, "c", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH) = 3
  newfstatat(3, "", {st_mode=S_IFLNK|0777, st_size=1, ...}, AT_EMPTY_PATH) = 0
  close(3)                                = 0
  fcntl(1, F_GETFL)                       = 0x2 (flags O_RDWR)
  write(2, "cp: ", 4cp: )                     = 4
  write(2, "failed to preserve ownership for"..., 34failed to preserve ownership for c) = 34
  write(2, ": Operation not supported", 25: Operation not supported) = 25
  write(2, "\n", 1
  )                       = 1
  lseek(0, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
...

 |What happens if you use fchownat directly? Something like the following:

That just works.

I do not know how

  $ grep -r fchmodat2 /usr/include/
  /usr/include/bits/syscall.h:#ifdef __NR_fchmodat2
  /usr/include/bits/syscall.h:# define SYS_fchmodat2 __NR_fchmodat2

gets into there, the kernel definitely does not have that as via
grep.  Generated at glibc build time via

    # install kernel headers
    make -C /usr/src/linux mrproper
    make -C /usr/src/linux INSTALL_HDR_PATH=$PKG/usr headers_install

 --End of <[email-masked]>

--steffen
|
|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)