Subject: Re: bug#22584: cp could be more precise than "Not a directory"

From: Assaf Gordon <[email-masked]>
Date: Mon, 8 Feb 2016 09:42:06 -0500

Hello Dan,

A bit more technical information (though not a resolution):

On 02/07/2016 11:19 AM, 積丹尼 Dan Jacobson wrote:
> $ cp .profile /tmp/My_DocVments/
> cp: cannot create regular file '/tmp/My_DocVments/': Not a directory
>
> Well can't it be more precise:
> No such directory nor file.

This is in fact done on purpose, explicitly in the code.

To illustrate:

     $ rm -rf /tmp/foobar
     $ strace -e stat cp .profile /tmp/foobar/
     stat("/tmp/foobar/", 0x7ffe77e60ed0)    = -1 ENOENT (No such file or directory)
     cp: cannot create regular file ‘/tmp/foobar/’: Not a directory

Despite stat(2) return error of 'ENOENT', the code in src/copy.c:1150
sets the error code to ENOTDIR (The comment refers only to 'EISDIR',
perhaps others can expand on why):

         /* Improve quality of diagnostic when a nonexistent dst_name
            ends in a slash and open fails with errno == EISDIR.  */
         if (dest_desc < 0 && dest_errno == EISDIR
                && *dst_name && dst_name[strlen (dst_name) - 1] == '/')
             dest_errno = ENOTDIR;

Then at src/copy.c:1150, the error is reported:

           error (0, dest_errno, _("cannot create regular file %s"),
                  quoteaf (dst_name));

===

Perhaps this is done to simulate the real ENOTDIR which is returned
if the file exist but is not a directory:

     $ rm -rf /tmp/foobar
     $ touch /tmp/foobar
     $ strace -e stat cp ~/.profile /tmp/foobar/
     stat("/tmp/foobar/", 0x7ffd40edf6c0)    = -1 ENOTDIR (Not a directory)
     cp: failed to access ‘/tmp/foobar/’: Not a directory

===

regards,
  - assaf