Subject: Re: bug#70411: [bug] install(1) fails to read /dev/stdin on Darwin

From: Pádraig Brady <[email-masked]>
Date: Tue, 16 Apr 2024 15:25:22 +0100

On 16/04/2024 12:33, Pádraig Brady wrote:
> On 16/04/2024 01:19, Alejandro Colomar wrote:
>> Hi!
>>
>> I don't own a Darwin system, so I can't help much reproduce.  However,
>> I've received a bug report to the Linux man-pages, that our build
>> system (GNUmakefile-based), which ends up calling
>>
>> 	... | install /dev/stdin $@
>>
>> doesn't work on Darwin.  Here's the original bug report:
>> <https://github.com/NixOS/nixpkgs/pull/300797>.
>>
>> Here are the reported error messages:
>>
>> ...
>> INSTALL         /nix/store/3s28l9ijlkmsq8256zdxjvl173gkn37c-man-pages-6.7/share/man/man3/addseverity.3
>> INSTALL         /nix/store/3s28l9ijlkmsq8256zdxjvl173gkn37c-man-pages-6.7/share/man/man3/adjtime.3
>> install: skipping file '/dev/stdin', as it was replaced while being copied
>> make: *** [share/mk/install/man.mk:54: /nix/store/3s28l9ijlkmsq8256zdxjvl173gkn37c-man-pages-6.7/share/man/man3/addmntent.3] Error 1
>> make: *** Waiting for unfinished jobs....
>> install: skipping file '/dev/stdin', as it was replaced while being copied
>> make: *** [share/mk/install/man.mk:54: /nix/store/3s28l9ijlkmsq8256zdxjvl173gkn37c-man-pages-6.7/share/man/man3/acosh.3] Error 1
>> install: skipping file '/dev/stdin', as it was replaced while being copied
>> install: skipping file '/dev/stdin', as it was replaced while being copied
>> install: skipping file '/dev/stdin', as it was replaced while being copied
>> ...
>>
>> I don't see why install(1) should fail to read /dev/stdin under any
>> POSIX system
> 
> What version of darwin is this? I can't repro on Darwin 21.6.0 (MacOSX 12.6).
> The issue seems to be that /dev/stdin returns a varying inode which install(1) doesn't like currently

Note that check originally came from:
https://github.com/coreutils/coreutils/commit/dea4262fa

I suppose we could relax the check as follows, for files of apparent size 0
which would cater for this, and others that may also have unstable inodes.

cheers,
Pádraig.

diff --git a/src/copy.c b/src/copy.c
index 2145d89d5..fb5f0a1a0 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -1263,8 +1263,11 @@ copy_reg (char const *src_name, char const *dst_name,
      }

    /* Compare the source dev/ino from the open file to the incoming,
-     saved ones obtained via a previous call to stat.  */
-  if (! psame_inode (src_sb, &src_open_sb))
+     saved ones obtained via a previous call to stat.  Restrict
+     the check to files with an apparent size, to support "files"
+     with unstable inodes, like /dev/stdin on macOS.  */
+  if (! psame_inode (src_sb, &src_open_sb)
+      && (src_sb->st_size || src_open_sb.st_size))
      {
        error (0, 0,
               _("skipping file %s, as it was replaced while being copied"),