Subject: Re: bug#78509: Coreutils' mv and cp 9.5 do not work properly on old PPC Mac OS X 10.4.11, Tiger

From: Paul Eggert <[email-masked]>
Date: Sat, 24 May 2025 12:33:48 -0700

On 2025-05-24 11:45, Peter Dyballa wrote:
> This function in lib/targetdir.c, target_directory_operand(), seems to work OK:
> 
>      63   if (must_be_working_directory (file))
> 
> evaluates to false
> 
>      72   if (!O_DIRECTORY)
> 
> evaluates to false – and we come to:
> 
>      88   if (try_to_open)
>      89     {
>      90       fd = open (file, O_PATHSEARCH | O_DIRECTORY);
>      91
>      92       /* On platforms lacking O_PATH, using O_SEARCH | O_DIRECTORY to
>      93          open an overly-protected non-directory can fail with either
>      94          EACCES or ENOTDIR.  Prefer ENOTDIR as it makes for better
>      95          diagnostics.  */
>      96       if (O_PATHSEARCH == O_SEARCH && fd < 0 && errno == EACCES)
>      97         errno = (((O_DIRECTORY ? stat (file, st) : stat_result) == 0
>      98                   && !S_ISDIR (st->st_mode))
>      99                  ? ENOTDIR : EACCES);
>     100     }
> 
> open() on line #90 returns 7

That's wrong. O_DIRECTORY means that open should fail when FILE is not a 
directory". In this case the file is "out" which is a regular file not a 
directory. Perhaps macOS is ignoring the O_DIRECTORY flag?

Can you verify that a simple program like the following triggers this 
macOS bug? If so, we might be able to work around it. You may need to 
munge this program a bit to get it to compile and illustrate the bug on 
macOS.

   #include <errno.h>
   #include <fcntl.h>
   #include <stdio.h>
   #include <unistd.h>

   #ifndef O_SEARCH
   # define O_SEARCH O_RDONLY
   #endif

   int
   main ()
   {
     int fd = open ("out", O_WRONLY | O_CREAT, 0666);
     if (fd < 0)
       return perror ("create"), 1;
     close (fd);
     fd = open ("out", O_SEARCH | O_DIRECTORY);
     if (fd < 0 && errno == ENOTDIR)
       return 0;
     if (fd < 0)
       return perror ("open"), 1;
     fprintf (stderr, "O_DIRECTORY incorrectly succeeded!\n");
     return 1;
   }