On 1/11/2021 6:50 PM, Ken Brown via Cygwin wrote:
On 1/11/2021 2:57 PM, Morgan King via Cygwin wrote:
Hello,

I am experiencing the same issue with tar and I am able to reproduce it following the steps at:
https://lists.gnu.org/archive/html/bug-tar/2011-08/msg00006.html

This issue only appears to occur when using 32-bit Cygwin, I am unable to reproduce it using 64-bit Cygwin.

I can confirm this.  Running the tar command under gdb shows a problem at gnu/fchmodat.c:94:

94            if (S_ISLNK (st.st_mode))

Here st is a stat structure for directory/1, so S_ISLNK() should be true.  It is indeed true on 64-bit Cygwin but not on 32-bit Cygwin.  Someone needs to look more closely and find out why this happened.  I'll try to do it tomorrow if no one beats me to it.

This appears to be a bug in fstat in 32-bit Cygwin. Here's what I'm seeing in gdb, using an unoptimized build of cygwin1.dll. There is a call to fstatat in the tar source file gnu/fchmodat.c:87. This ultimately leads to a call to fstat, whose definition in syscalls.cc is the following in the 32-bit case:

extern "C" int
fstat (int fd, struct stat *buf)
{
  struct stat buf64;
  int ret = fstat64 (fd, &buf64);
  if (!ret)
    stat64_to_stat32 (&buf64, (struct __stat32 *) buf);
  return ret;
}

After the call to fstat64, buf64 looks like this:

(gdb) p/o buf64
$20 = {st_dev = 016465473173, st_ino = 01240000000006533716,
  st_mode = 0120777, st_nlink = 01, st_uid = 0601751, st_gid = 0601001,
  st_rdev = 0, st_size = 01, st_atim = {tv_sec = 013777346014,
    tv_nsec = 03415154434}, st_mtim = {tv_sec = 013777334323, tv_nsec = 0},
  st_ctim = {tv_sec = 013777346014, tv_nsec = 03421004710},
  st_blksize = 0200000, st_blocks = 0, st_birthtim = {tv_sec = 013777346014,
    tv_nsec = 03415154434}}

After the call to stat64_to_stat32, buf looks like this:

(gdb) p/o *buf
$22 = {st_dev = 026106753173, st_ino = 017510000040000120777, st_mode = 01001,
  st_nlink = 01, st_uid = 013777346014, st_gid = 03415154434,
  st_rdev = 013777334323, st_size = 0161040234413777346014, st_atim = {
    tv_sec = 0200000, tv_nsec = 0}, st_mtim = {tv_sec = 01, tv_nsec = 0},
  st_ctim = {tv_sec = 06533716, tv_nsec = 025000000}, st_blksize = 0,
  st_blocks = 0, st_birthtim = {tv_sec = 0, tv_nsec = 03}}

Note that many of the values have been corrupted or shifted. (A few are expected to change.) I think the problem is the cast in the call

  stat64_to_stat32 (&buf64, (struct __stat32 *) buf);

I don't see how that could be expected to work, since several members of struct __stat32 have different sizes than the corresponding members of struct stat. I wonder if it worked by accident in the past, but the problem is just showing up with newer gcc because of changes in how it pads the two structs?

Corinna, can you shed some light on this?

Ken
--
Problem reports:      https://cygwin.com/problems.html
FAQ:                  https://cygwin.com/faq/
Documentation:        https://cygwin.com/docs.html
Unsubscribe info:     https://cygwin.com/ml/#unsubscribe-simple

Reply via email to