cp --parents F/G D

Version:

coreutils-6.7(fixed in 6.8)

How to reproduce?

Use the command

$ mkdir G

$ touch  F

$ coreutils-6.7/src/cp --parents F/G D

This command alone is meant to  copy F/G into D, resulting in D/F/G.

Symptom:

Early termination.

Create a directory ./D/F even though F isn’t a directory.

The error message is ./src/cp: cannot stat `F/G': Not a directory

The correct behavior should be that ‘cp’ rejects the input immediately since ‘F’ is not a directory!

Root cause:

The root cause is the buggy version did not bother to check whether the argument in ‘parents’ option is a directory.

In cp.c,

static bool make_dir_parents_private()

{

 .. .. ..

/* Here, ‘dir’ is ‘F’. */

if (XSTAT (x, dir, &stats))

{

          mode_t src_mode;

          mode_t omitted_permissions;

          mode_t mkdir_mode;

+     int src_errno;

          *new_dst = true;

-     if (XSTAT (x, src, &stats))

+         src_errno = (XSTAT (x, src, &stats) != 0

+                        ? errno

+                        : S_ISDIR (stats.st_mode)

+                          ? 0

+                          : ENOTDIR);

+        if (src_errno)

 {

        error (0, src_errno, _("failed to get attributes of %s"),

        quote (src));

        return false;

 }

}

in correct version src_errno == ENOTDIR.

The actual error message is printed here:

static bool copy_internal (... …) {

 if (XSTAT (x, src_name, &src_sb) != 0)

   {

     error (0, errno, _("cannot stat %s"), quote (src_name));

     return false;

   }

}

XSTAT is a macro for lstat system call.

Is there Error Message?

Yes.

Can Errlog automatically insert this error msg?

Yes. System call return value (lstat, checked).