Subject: 'install' fails to copy regular file to autofs/cifs, due to ACL or xattr handling

From: Bruno Haible <[email-masked]>
Date: Fri, 05 Apr 2024 11:48:14 +0200

Hi,

The 'install' program from coreutils-9.5 fails to copy a regular file
from an ext4 mount to an autofs/cifs mount.

The same operation, with 'cp -a', works fine.

Also, it works fine when coreutils was built with the configure options
"--disable-acl --disable-xattr".

How to reproduce
================

1) On the machine sparcdev.matoro.tk (Linux 6.8.2), I built coreutils-9.5
from source,
  - once with default options, in build-sparc64/,
  - once with "--disable-acl --disable-xattr", in build-sparc64-no-acl/.

2) Create a regular file on an ext4 mount:

$ echo hi > /var/tmp/foo3941
$ ls -lZ /var/tmp/foo3941
-rw-r----- 1 g-haible g-haible ? 3 Apr  4 13:29 /var/tmp/foo3941
$ getfacl /var/tmp/foo3941
getfacl: Removing leading '/' from absolute path names
# file: var/tmp/foo3941
# owner: g-haible
# group: g-haible
user::rw-
group::r--
other::---
$ df -m /var/tmp/
Filesystem     1M-blocks   Used Available Use% Mounted on
/dev/root         560245 123140    408574  24% /
$ mount | grep ' / '
/dev/sda2 on / type ext4 (rw,noatime)

3) Details about the destination directory:

$ echo $HOME
/media/guest-homedirs/haible
$ mount | grep /media/guest-homedirs/haible
/etc/autofs/auto.guest-homedirs on /media/guest-homedirs/haible type autofs (rw,relatime,fd=7,pgrp=2325,timeout=60,minproto=5,maxproto=5,direct,pipe_ino=46092)
//syslog.matoro.tk/guest-haible on /media/guest-homedirs/haible type cifs (rw,nosuid,relatime,vers=1.0,cache=strict,username=nobody,uid=30014,forceuid,gid=30014,forcegid,addr=fd05:0000:0000:0000:0000:0000:0000:0001,soft,unix,posixpaths,serverino,mapposix,acl,rsize=1048576,wsize=65536,bsize=1048576,retrans=1,echo_interval=60,actimeo=1,closetimeo=1)

4) The operation that fails:

$ build-sparc64/src/ginstall -c /var/tmp/foo3941 $HOME/foo3941; echo $?
build-sparc64/src/ginstall: setting permissions for '/media/guest-homedirs/haible/foo3941': Permission denied
1
$ build-sparc64-no-acl/src/ginstall -c /var/tmp/foo3941 $HOME/foo3941; echo $?
0

5) The same thing with 'cp -a' succeeds:

$ build-sparc64/src/cp -a /var/tmp/foo3941 $HOME/foo3941; echo $?
0
$ build-sparc64-no-acl/src/cp -a /var/tmp/foo3941 $HOME/foo3941; echo $?
0

6) 'strace' shows a failing call to fsetxattr:

$ strace build-sparc64/src/ginstall -c /var/tmp/foo3941 $HOME/foo3941
execve("build-sparc64/src/ginstall", ["build-sparc64/src/ginstall", "-c", "/var/tmp/foo3941", "/media/guest-homedirs/haible/foo"...], 0x7feffffce28 /* 43 vars */) = 0
brk(NULL)                               = 0x10000204000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=41866, ...}) = 0
mmap(NULL, 41866, PROT_READ, MAP_PRIVATE, 3, 0) = 0xfff8000100028000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib64/libacl.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\2\1\0\0\0\0\0\0\0\0\0\0\3\0+\0\0\0\1\0\0\0\0\0\0\0\0"..., 832) = 832
fstat64(3, {st_mode=S_IFREG|0755, st_size=1052312, ...}) = 0
mmap(NULL, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xfff8000100034000
mmap(NULL, 3147696, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_DENYWRITE, -1, 0) = 0xfff8000100206000
mmap(0xfff8000100300000, 2099120, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0xfff8000100300000
munmap(0xfff8000100206000, 1024000)     = 0
munmap(0xfff8000100502000, 18352)       = 0
mprotect(0xfff8000100308000, 2056192, PROT_NONE) = 0
mmap(0xfff80001004fe000, 16384, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xfe000) = 0xfff80001004fe000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib64/libattr.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\2\1\0\0\0\0\0\0\0\0\0\0\3\0+\0\0\0\1\0\0\0\0\0\0\0\0"..., 832) = 832
fstat64(3, {st_mode=S_IFREG|0755, st_size=1051928, ...}) = 0
mmap(NULL, 3147288, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_DENYWRITE, -1, 0) = 0xfff8000100502000
mmap(0xfff8000100600000, 2098712, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0xfff8000100600000
munmap(0xfff8000100502000, 1040384)     = 0
munmap(0xfff8000100802000, 1560)        = 0
mprotect(0xfff8000100604000, 2072576, PROT_NONE) = 0
mmap(0xfff80001007fe000, 16384, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xfe000) = 0xfff80001007fe000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\2\1\3\0\0\0\0\0\0\0\0\0\3\0+\0\0\0\1\0\0\0\0\0\2\305\240"..., 832) = 832
fstat64(3, {st_mode=S_IFREG|0755, st_size=2110256, ...}) = 0
mmap(NULL, 4233760, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_DENYWRITE, -1, 0) = 0xfff8000100802000
mmap(0xfff8000100900000, 3185184, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0xfff8000100900000
munmap(0xfff8000100802000, 1040384)     = 0
munmap(0xfff8000100c0a000, 6688)        = 0
mprotect(0xfff8000100a8e000, 1499136, PROT_NONE) = 0
mmap(0xfff8000100bfc000, 24576, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1fc000) = 0xfff8000100bfc000
mmap(0xfff8000100c02000, 31264, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xfff8000100c02000
close(3)                                = 0
set_tid_address(0xfff80001000365f0)     = 28674
set_robust_list(0xfff8000100036600, 24) = 0
mprotect(0xfff8000100bfc000, 16384, PROT_READ) = 0
mprotect(0xfff80001007fe000, 8192, PROT_READ) = 0
mprotect(0xfff80001004fe000, 8192, PROT_READ) = 0
mprotect(0x100001fe000, 8192, PROT_READ) = 0
mprotect(0xfff80001001fe000, 8192, PROT_READ) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
munmap(0xfff8000100028000, 41866)       = 0
getrandom("\x78\x3e\xea\xde\x42\xab\xf0\x1b", 8, GRND_NONBLOCK) = 8
brk(NULL)                               = 0x10000204000
brk(0x10000226000)                      = 0x10000226000
openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=3061520, ...}) = 0
mmap(NULL, 3061520, PROT_READ, MAP_PRIVATE, 3, 0) = 0xfff8000100c0c000
close(3)                                = 0
openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=2998, ...}) = 0
read(3, "# Locale name alias data base.\n#"..., 4096) = 2998
read(3, "", 4096)                       = 0
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/locale/de_DE.UTF-8/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/de_DE.utf8/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/de_DE/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/de.UTF-8/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/de.utf8/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/de/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
geteuid()                               = 30014
umask(000)                              = 027
openat(AT_FDCWD, "/media/guest-homedirs/haible/foo3941", O_RDONLY|O_PATH|O_DIRECTORY) = -1 ENOTDIR (Not a directory)
fstatat64(AT_FDCWD, "/var/tmp/foo3941", {st_mode=S_IFREG|0640, st_size=3, ...}, 0) = 0
fstatat64(AT_FDCWD, "/media/guest-homedirs/haible/foo3941", {st_mode=S_IFREG|0640, st_size=3, ...}, AT_SYMLINK_NOFOLLOW) = 0
unlinkat(AT_FDCWD, "/media/guest-homedirs/haible/foo3941", 0) = 0
openat(AT_FDCWD, "/var/tmp/foo3941", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0640, st_size=3, ...}) = 0
openat(AT_FDCWD, "/media/guest-homedirs/haible/foo3941", O_WRONLY|O_CREAT|O_EXCL, 0600) = 4
ioctl(4, BTRFS_IOC_CLONE or FICLONE, 3) = -1 EXDEV (Invalid cross-device link)
fstat64(4, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
fadvise64_64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
uname({sysname="Linux", nodename="matoro-sparcdev", ...}) = 0
copy_file_range(3, NULL, 4, NULL, 9223372035781033984, 0) = -1 EXDEV (Invalid cross-device link)
mmap(NULL, 1064960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xfff8000100038000
read(3, "hi\n", 1048576)                = 3
write(4, "hi\n", 3)                     = 3
read(3, "", 1048576)                    = 0
fsetxattr(4, "system.posix_acl_access", "\2\0\0\0\1\0\6\0\377\377\377\377\4\0\0\0\377\377\377\377 \0\0\0\377\377\377\377", 28, 0) = -1 EACCES (Permission denied)
fchmod(4, 0600)                         = 0
write(2, "build-sparc64/src/ginstall: ", 28build-sparc64/src/ginstall: ) = 28
write(2, "setting permissions for '/media/"..., 62setting permissions for '/media/guest-homedirs/haible/foo3941') = 62
write(2, ": Permission denied", 19: Permission denied)     = 19
write(2, "\n", 1
)                       = 1
close(4)                                = 0
close(3)                                = 0
munmap(0xfff8000100038000, 1064960)     = 0
_llseek(0, 0, 0x7feffbca600, SEEK_CUR)  = -1 ESPIPE (Illegal seek)
close(0)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(1)                           = ?
+++ exited with 1 +++

7) Symbol differences between the two builds:

$ nm build-sparc64/src/ginstall | grep acl
000000000001725c T acl_access_nontrivial
000000000001732c T acl_default_nontrivial
                 U [email-masked]
                 U [email-masked]
0000000000018b24 T acl_errno_valid
                 U [email-masked]
                 U [email-masked]
                 U [email-masked]
                 U [email-masked]
                 U [email-masked]
                 U [email-masked]
000000000000b5f4 T copy_acl
000000000000fbb8 T qcopy_acl
000000000000fc3c T qset_acl
000000000000b6d4 T set_acl
0000000000017394 t set_acls.isra.0

$ nm build-sparc64-no-acl/src/ginstall | grep acl
000000000000ade8 T copy_acl
000000000000f37c T qcopy_acl
000000000000f40c T qset_acl
000000000000aec8 T set_acl

Notes
=====

The 'cp' program does *not* use fsetxattr() calls on the destination file
descriptor and therefore does not fail:

$ strace build-sparc64/src/cp -a /var/tmp/foo3941 $HOME/foo3941
execve("build-sparc64/src/cp", ["build-sparc64/src/cp", "-a", "/var/tmp/foo3941", "/media/guest-homedirs/haible/foo"...], 0x7feffc96e38 /* 43 vars */) = 0
brk(NULL)                               = 0x10000202000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=41866, ...}) = 0
mmap(NULL, 41866, PROT_READ, MAP_PRIVATE, 3, 0) = 0xfff8000100028000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib64/libacl.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\2\1\0\0\0\0\0\0\0\0\0\0\3\0+\0\0\0\1\0\0\0\0\0\0\0\0"..., 832) = 832
fstat64(3, {st_mode=S_IFREG|0755, st_size=1052312, ...}) = 0
mmap(NULL, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xfff8000100034000
mmap(NULL, 3147696, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_DENYWRITE, -1, 0) = 0xfff8000100494000
mmap(0xfff8000100500000, 2099120, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0xfff8000100500000
munmap(0xfff8000100494000, 442368)      = 0
munmap(0xfff8000100702000, 599984)      = 0
mprotect(0xfff8000100508000, 2056192, PROT_NONE) = 0
mmap(0xfff80001006fe000, 16384, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xfe000) = 0xfff80001006fe000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib64/libattr.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\2\1\0\0\0\0\0\0\0\0\0\0\3\0+\0\0\0\1\0\0\0\0\0\0\0\0"..., 832) = 832
fstat64(3, {st_mode=S_IFREG|0755, st_size=1051928, ...}) = 0
mmap(NULL, 3147288, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_DENYWRITE, -1, 0) = 0xfff8000100702000
mmap(0xfff8000100800000, 2098712, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0xfff8000100800000
munmap(0xfff8000100702000, 1040384)     = 0
munmap(0xfff8000100a02000, 1560)        = 0
mprotect(0xfff8000100804000, 2072576, PROT_NONE) = 0
mmap(0xfff80001009fe000, 16384, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xfe000) = 0xfff80001009fe000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\2\1\3\0\0\0\0\0\0\0\0\0\3\0+\0\0\0\1\0\0\0\0\0\2\305\240"..., 832) = 832
fstat64(3, {st_mode=S_IFREG|0755, st_size=2110256, ...}) = 0
mmap(NULL, 4233760, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_DENYWRITE, -1, 0) = 0xfff8000100a02000
mmap(0xfff8000100b00000, 3185184, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0xfff8000100b00000
munmap(0xfff8000100a02000, 1040384)     = 0
munmap(0xfff8000100e0a000, 6688)        = 0
mprotect(0xfff8000100c8e000, 1499136, PROT_NONE) = 0
mmap(0xfff8000100dfc000, 24576, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1fc000) = 0xfff8000100dfc000
mmap(0xfff8000100e02000, 31264, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xfff8000100e02000
close(3)                                = 0
set_tid_address(0xfff80001000365d0)     = 29091
set_robust_list(0xfff80001000365e0, 24) = 0
mprotect(0xfff8000100dfc000, 16384, PROT_READ) = 0
mprotect(0xfff80001009fe000, 8192, PROT_READ) = 0
mprotect(0xfff80001006fe000, 8192, PROT_READ) = 0
mprotect(0x100001fe000, 8192, PROT_READ) = 0
mprotect(0xfff80001001fe000, 8192, PROT_READ) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
munmap(0xfff8000100028000, 41866)       = 0
getrandom("\x26\xa7\x29\x29\xf6\x69\x36\x3e", 8, GRND_NONBLOCK) = 8
brk(NULL)                               = 0x10000202000
brk(0x10000224000)                      = 0x10000224000
openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=3061520, ...}) = 0
mmap(NULL, 3061520, PROT_READ, MAP_PRIVATE, 3, 0) = 0xfff8000100e0c000
close(3)                                = 0
openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=2998, ...}) = 0
read(3, "# Locale name alias data base.\n#"..., 4096) = 2998
read(3, "", 4096)                       = 0
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/locale/de_DE.UTF-8/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/de_DE.utf8/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/de_DE/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/de.UTF-8/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/de.utf8/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/de/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
geteuid()                               = 30014
openat(AT_FDCWD, "/media/guest-homedirs/haible/foo3941", O_RDONLY|O_PATH|O_DIRECTORY) = -1 ENOTDIR (Not a directory)
fstatat64(AT_FDCWD, "/var/tmp/foo3941", {st_mode=S_IFREG|0640, st_size=3, ...}, AT_SYMLINK_NOFOLLOW) = 0
fstatat64(AT_FDCWD, "/media/guest-homedirs/haible/foo3941", {st_mode=S_IFREG|0600, st_size=3, ...}, 0) = 0
openat(AT_FDCWD, "/var/tmp/foo3941", O_RDONLY|O_NOFOLLOW) = 3
fstat64(3, {st_mode=S_IFREG|0640, st_size=3, ...}) = 0
openat(AT_FDCWD, "/media/guest-homedirs/haible/foo3941", O_WRONLY|O_TRUNC) = 4
ioctl(4, BTRFS_IOC_CLONE or FICLONE, 3) = -1 EXDEV (Invalid cross-device link)
fstat64(4, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
fadvise64_64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
uname({sysname="Linux", nodename="matoro-sparcdev", ...}) = 0
copy_file_range(3, NULL, 4, NULL, 9223372035781033984, 0) = -1 EXDEV (Invalid cross-device link)
mmap(NULL, 1064960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xfff8000100038000
read(3, "hi\n", 1048576)                = 3
write(4, "hi\n", 3)                     = 3
read(3, "", 1048576)                    = 0
utimensat(4, NULL, [{tv_sec=1712251745, tv_nsec=269582795} /* 2024-04-04T13:29:05.269582795-0400 */, {tv_sec=1712251745, tv_nsec=270582848} /* 2024-04-04T13:29:05.270582848-0400 */], 0) = 0
flistxattr(3, NULL, 0)                  = 0
flistxattr(3, 0x7feff9860a0, 0)         = 0
fchmod(4, 0100640)                      = 0
flistxattr(3, NULL, 0)                  = 0
flistxattr(3, 0x7feff9860c0, 0)         = 0
close(4)                                = 0
close(3)                                = 0
munmap(0xfff8000100038000, 1064960)     = 0
_llseek(0, 0, 0x7feff986600, SEEK_CUR)  = -1 ESPIPE (Illegal seek)
close(0)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

As you can see, it uses 4 flistxattr() calls on the source file descriptor,
apparently detecting that it's a regular file without ACLs, and proceeds to
do a simple fchmod() call on the destination file descriptor.

Probably the same logic is needed in the 'install' program.

Bruno