Your message dated Sun, 27 Jan 2008 23:32:02 +0000
with message-id <[EMAIL PROTECTED]>
and subject line Bug#456164: fixed in cvs 1:1.12.13-10
has caused the attached Bug report to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what I am
talking about this indicates a serious mail system misconfiguration
somewhere.  Please contact me immediately.)

Debian bug tracking system administrator
(administrator, Debian Bugs database)

--- Begin Message ---
Package: cvs
Version: 1.12.13-9
Severity: normal
Tags: patch

On this laptop, the root filesystem is Ubuntu, and I have a chroot for
my Debian development work. ~/src is bind-mounted into the chroot thus:

  /home/cjwatson/src on /chroot/sid/home/cjwatson/src type none (rw,bind)

Normally, this all works fine. However, after upgrading cvs from
1.12.13-8 to 1.12.13-9, cvs broke (I noticed due to autopoint),
complaining that it couldn't determine its current working directory:

  <[EMAIL PROTECTED] ~/src/debian/man-db/bzr/gnulib>$ mkdir x
  <[EMAIL PROTECTED] ~/src/debian/man-db/bzr/gnulib>$ cd x
  <[EMAIL PROTECTED] ~/src/debian/man-db/bzr/gnulib/x>$ cvs init
  cvs [init aborted]: cannot get working directory: No such file or directory

I narrowed things down with strace and gdb, and found that it's hitting
this case at line 309 of lib/getcwd.c:

      if (d == NULL)
        {
          if (errno == 0)
            /* EOF on dirstream, which means that the current directory
               has been removed.  */
            __set_errno (ENOENT);
          goto lose;
        }

Now, I confirmed that downgrading cvs back to 1.12.13-8 works, and
there's clearly no relevant change in the cvs source itself. Diffing the
amd64 build logs (I'm on i386, but I can't see those build logs so I'm
hoping that this is close enough):

@@ -517,7 +490,7 @@
 checking for canonicalize_file_name... yes
 checking whether this system has a definition of PATH_MAX... yes
 checking for mempcpy... (cached) yes
-checking for openat... no
+checking for openat... yes
 checking for memrchr... yes
 checking for dup2... yes
 checking for working POSIX fnmatch... yes
@@ -528,7 +501,7 @@
 checking for library containing getaddrinfo... (cached) none required
 checking for getaddrinfo... (cached) yes
 checking for gai_strerror... (cached) yes
-checking whether getcwd handles long file names properly... yes
+checking whether getcwd handles long file names properly... no, but it is 
partly working
 checking for struct tm.tm_zone... yes
 checking for getdelim... yes
 checking for gethostname... yes
@@ -557,7 +530,7 @@
 checking for mkstemp limitations... no
 checking for library containing nanosleep... none required
 checking whether nanosleep works... yes
-checking for openat... (cached) no
+checking for openat... (cached) yes
 checking for mbstate_t... (cached) yes
 checking whether mbrtowc and mbstate_t are properly declared... yes
 checking for readlink... yes

So the copy of Gnulib in the cvs source now detects openat and uses it
where it didn't previously, and then proceeds to break.

I noted that the copy of Gnulib in cvs dates from 2005-09-29, and
started looking at the subsequent changes from git:

  
http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=history;f=lib/getcwd.c;h=b8e9989b9056942f5b3869b0b669ff18406b5260;hb=HEAD

As it turns out, I didn't have to look far. The third change after that
date fixes this bug, following a previous Debian bug report in coreutils
(#355810). It was also necessary to take the first change after that
date, otherwise the real fix didn't apply cleanly, and I felt it better
to upgrade than backport in this case.

I've attached a debdiff with dbs-ified versions of these patches. I
wasn't sure of your patch numbering system so I just shoved them in at a
convenient point; it's not important where they live since nothing else
in debian/patches/ touches lib/getcwd.c. I have confirmed that a cvs.deb
built using this patch is sufficient for me to be able to run autopoint.

Thanks,

-- 
Colin Watson                                       [EMAIL PROTECTED]
--- cvs-1.12.13.orig/debian/patches/20_readdir_errno
+++ cvs-1.12.13/debian/patches/20_readdir_errno
@@ -0,0 +1,121 @@
+# From Gnulib:
+#   
http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=commitdiff;h=0b78641d85af3b72e3b9d94cb7b94e45f3c08ee5
+# We don't need this directly, but it's required so that 21_getcwd_chroot
+# applies cleanly.
+#
+# 2005-10-29  Paul Eggert  <[EMAIL PROTECTED]>
+#
+#      * getcwd.c (__getcwd): Don't assume that system calls after readdir
+#      leave errno alone.  Problem reported by Dmitry V. Levin.
+
+--- cvs-1.12.13-old/lib/getcwd.c
++++ cvs-1.12.13/lib/getcwd.c
+@@ -201,6 +201,8 @@ __getcwd (char *buf, size_t size)
+       ino_t dotino;
+       bool mount_point;
+       int parent_status;
++      size_t dirroom;
++      size_t namlen;
+ 
+       /* Look at the parent directory.  */
+ #ifdef AT_FDCWD
+@@ -241,11 +243,20 @@ __getcwd (char *buf, size_t size)
+       goto lose;
+       dotlist[dotlen++] = '/';
+ #endif
+-      /* Clear errno to distinguish EOF from error if readdir returns
+-       NULL.  */
+-      __set_errno (0);
+-      while ((d = __readdir (dirstream)) != NULL)
++      for (;;)
+       {
++        /* Clear errno to distinguish EOF from error if readdir returns
++           NULL.  */
++        __set_errno (0);
++        d = __readdir (dirstream);
++        if (d == NULL)
++          {
++            if (errno == 0)
++              /* EOF on dirstream, which means that the current directory
++                 has been removed.  */
++              __set_errno (ENOENT);
++            goto lose;
++          }
+         if (d->d_name[0] == '.' &&
+             (d->d_name[1] == '\0' ||
+              (d->d_name[1] == '.' && d->d_name[2] == '\0')))
+@@ -303,48 +314,38 @@ __getcwd (char *buf, size_t size)
+               break;
+           }
+       }
+-      if (d == NULL)
+-      {
+-        if (errno == 0)
+-          /* EOF on dirstream, which means that the current directory
+-             has been removed.  */
+-          __set_errno (ENOENT);
+-        goto lose;
+-      }
+-      else
+-      {
+-        size_t dirroom = dirp - dir;
+-        size_t namlen = _D_EXACT_NAMLEN (d);
+ 
+-        if (dirroom <= namlen)
++      dirroom = dirp - dir;
++      namlen = _D_EXACT_NAMLEN (d);
++
++      if (dirroom <= namlen)
++      {
++        if (size != 0)
+           {
+-            if (size != 0)
+-              {
+-                __set_errno (ERANGE);
+-                goto lose;
+-              }
+-            else
+-              {
+-                char *tmp;
+-                size_t oldsize = allocated;
++            __set_errno (ERANGE);
++            goto lose;
++          }
++        else
++          {
++            char *tmp;
++            size_t oldsize = allocated;
+ 
+-                allocated += MAX (allocated, namlen);
+-                if (allocated < oldsize
+-                    || ! (tmp = realloc (dir, allocated)))
+-                  goto memory_exhausted;
++            allocated += MAX (allocated, namlen);
++            if (allocated < oldsize
++                || ! (tmp = realloc (dir, allocated)))
++              goto memory_exhausted;
+ 
+-                /* Move current contents up to the end of the buffer.
+-                   This is guaranteed to be non-overlapping.  */
+-                dirp = memcpy (tmp + allocated - (oldsize - dirroom),
+-                               tmp + dirroom,
+-                               oldsize - dirroom);
+-                dir = tmp;
+-              }
++            /* Move current contents up to the end of the buffer.
++               This is guaranteed to be non-overlapping.  */
++            dirp = memcpy (tmp + allocated - (oldsize - dirroom),
++                           tmp + dirroom,
++                           oldsize - dirroom);
++            dir = tmp;
+           }
+-        dirp -= namlen;
+-        memcpy (dirp, d->d_name, namlen);
+-        *--dirp = '/';
+       }
++      dirp -= namlen;
++      memcpy (dirp, d->d_name, namlen);
++      *--dirp = '/';
+ 
+       thisdev = dotdev;
+       thisino = dotino;
--- cvs-1.12.13.orig/debian/patches/21_getcwd_chroot
+++ cvs-1.12.13/debian/patches/21_getcwd_chroot
@@ -0,0 +1,172 @@
+# From Gnulib:
+#  
http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=commitdiff;h=79c0a43808d9ca85acd04600149fc1a9b75bd1b9
+#
+# 2006-07-03  Paul Eggert  <[EMAIL PROTECTED]>
+#
+#      Merge from coreutils.
+#
+#      2006-03-19  Jim Meyering  <[EMAIL PROTECTED]>
+#
+#      Work even in a chroot where d_ino values for entries in "/"
+#      don't match the stat.st_ino values for the same names.
+#      * getcwd.c (__getcwd): When no d_ino value matches the target inode
+#      number, iterate through all entries again, using lstat instead.
+#      Reported by Kenshi Muto in http://bugs.debian.org/355810, and by
+#      Zouhir Hafidi in https://bugzilla.redhat.com/bugzilla/190656.
+#
+#      * getcwd.c (__getcwd): Clarify a comment.
+#      Use memcpy in place of a call to strcpy.
+
+--- cvs-1.12.13-old/lib/getcwd.c
++++ cvs-1.12.13/lib/getcwd.c
+@@ -211,6 +211,7 @@ __getcwd (char *buf, size_t size)
+       int parent_status;
+       size_t dirroom;
+       size_t namlen;
++      bool use_d_ino = true;
+ 
+       /* Look at the parent directory.  */
+ #ifdef AT_FDCWD
+@@ -257,11 +258,26 @@ __getcwd (char *buf, size_t size)
+            NULL.  */
+         __set_errno (0);
+         d = __readdir (dirstream);
++
++        /* When we've iterated through all directory entries without finding
++           one with a matching d_ino, rewind the stream and consider each
++           name again, but this time, using lstat.  This is necessary in a
++           chroot on at least one system (glibc-2.3.6 + linux 2.6.12), where
++           .., ../.., ../../.., etc. all had the same device number, yet the
++           d_ino values for entries in / did not match those obtained
++           via lstat.  */
++        if (d == NULL && errno == 0 && use_d_ino)
++          {
++            use_d_ino = false;
++            rewinddir (dirstream);
++            d = __readdir (dirstream);
++          }
++
+         if (d == NULL)
+           {
+             if (errno == 0)
+-              /* EOF on dirstream, which means that the current directory
+-                 has been removed.  */
++              /* EOF on dirstream, which can mean e.g., that the current
++                 directory has been removed.  */
+               __set_errno (ENOENT);
+             goto lose;
+           }
+@@ -269,58 +285,65 @@ __getcwd (char *buf, size_t size)
+             (d->d_name[1] == '\0' ||
+              (d->d_name[1] == '.' && d->d_name[2] == '\0')))
+           continue;
+-        if (MATCHING_INO (d, thisino) || mount_point)
++
++        if (use_d_ino)
+           {
+-            int entry_status;
++            bool match = (MATCHING_INO (d, thisino) || mount_point);
++            if (! match)
++              continue;
++          }
++
++        {
++          int entry_status;
+ #ifdef AT_FDCWD
+-            entry_status = fstatat (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW);
++          entry_status = fstatat (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW);
+ #else
+-            /* Compute size needed for this file name, or for the file
+-               name ".." in the same directory, whichever is larger.
+-               Room for ".." might be needed the next time through
+-               the outer loop.  */
+-            size_t name_alloc = _D_ALLOC_NAMLEN (d);
+-            size_t filesize = dotlen + MAX (sizeof "..", name_alloc);
+-
+-            if (filesize < dotlen)
+-              goto memory_exhausted;
+-
+-            if (dotsize < filesize)
+-              {
+-                /* My, what a deep directory tree you have, Grandma.  */
+-                size_t newsize = MAX (filesize, dotsize * 2);
+-                size_t i;
+-                if (newsize < dotsize)
+-                  goto memory_exhausted;
+-                if (dotlist != dots)
+-                  free (dotlist);
+-                dotlist = malloc (newsize);
+-                if (dotlist == NULL)
+-                  goto lose;
+-                dotsize = newsize;
+-
+-                i = 0;
+-                do
+-                  {
+-                    dotlist[i++] = '.';
+-                    dotlist[i++] = '.';
+-                    dotlist[i++] = '/';
+-                  }
+-                while (i < dotlen);
+-              }
+-
+-            strcpy (dotlist + dotlen, d->d_name);
+-            entry_status = __lstat (dotlist, &st);
++          /* Compute size needed for this file name, or for the file
++             name ".." in the same directory, whichever is larger.
++             Room for ".." might be needed the next time through
++             the outer loop.  */
++          size_t name_alloc = _D_ALLOC_NAMLEN (d);
++          size_t filesize = dotlen + MAX (sizeof "..", name_alloc);
++
++          if (filesize < dotlen)
++            goto memory_exhausted;
++
++          if (dotsize < filesize)
++            {
++              /* My, what a deep directory tree you have, Grandma.  */
++              size_t newsize = MAX (filesize, dotsize * 2);
++              size_t i;
++              if (newsize < dotsize)
++                goto memory_exhausted;
++              if (dotlist != dots)
++                free (dotlist);
++              dotlist = malloc (newsize);
++              if (dotlist == NULL)
++                goto lose;
++              dotsize = newsize;
++
++              i = 0;
++              do
++                {
++                  dotlist[i++] = '.';
++                  dotlist[i++] = '.';
++                  dotlist[i++] = '/';
++                }
++              while (i < dotlen);
++            }
++
++          memcpy (dotlist + dotlen, d->d_name, _D_ALLOC_NAMLEN (d));
++          entry_status = __lstat (dotlist, &st);
+ #endif
+-            /* We don't fail here if we cannot stat() a directory entry.
+-               This can happen when (network) file systems fail.  If this
+-               entry is in fact the one we are looking for we will find
+-               out soon as we reach the end of the directory without
+-               having found anything.  */
+-            if (entry_status == 0 && S_ISDIR (st.st_mode)
+-                && st.st_dev == thisdev && st.st_ino == thisino)
+-              break;
+-          }
++          /* We don't fail here if we cannot stat() a directory entry.
++             This can happen when (network) file systems fail.  If this
++             entry is in fact the one we are looking for we will find
++             out soon as we reach the end of the directory without
++             having found anything.  */
++          if (entry_status == 0 && S_ISDIR (st.st_mode)
++              && st.st_dev == thisdev && st.st_ino == thisino)
++            break;
++        }
+       }
+ 
+       dirroom = dirp - dir;

--- End Message ---
--- Begin Message ---
Source: cvs
Source-Version: 1:1.12.13-10

We believe that the bug you reported is fixed in the latest version of
cvs, which is due to be installed in the Debian FTP archive:

cvs_1.12.13-10.diff.gz
  to pool/main/c/cvs/cvs_1.12.13-10.diff.gz
cvs_1.12.13-10.dsc
  to pool/main/c/cvs/cvs_1.12.13-10.dsc
cvs_1.12.13-10_i386.deb
  to pool/main/c/cvs/cvs_1.12.13-10_i386.deb



A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to [EMAIL PROTECTED],
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Steve McIntyre <[EMAIL PROTECTED]> (supplier of updated cvs package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing [EMAIL PROTECTED])


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Format: 1.7
Date: Sun, 27 Jan 2008 19:08:02 +0000
Source: cvs
Binary: cvs
Architecture: source i386
Version: 1:1.12.13-10
Distribution: unstable
Urgency: low
Maintainer: Steve McIntyre <[EMAIL PROTECTED]>
Changed-By: Steve McIntyre <[EMAIL PROTECTED]>
Description: 
 cvs        - Concurrent Versions System
Closes: 197473 284710 351690 365078 422128 430415 455257 455496 456164 461154 
495641
Changes: 
 cvs (1:1.12.13-10) unstable; urgency=low
 .
   * Fix the internal getcwd() function to cope with working inside a
     bindmount/chroot. Thanks to Colin Watson for the patch.
     Closes: #456164,#461154,#495641
   * Add a fix from Petr Salinger so that cvs will work on
     GNU/kFreeBSD. Closes: #455496 . Looks related to the getcwd()
     changes above, but belt and braces won't hurt.
   * Add a Finnish Debconf translation, hanks to Esko Arajärvi.
     Closes: #455257
   * Updated the download URL in debian/copyright. Closes: #351690
   * Check for /etc/cvs-cron.conf before using it. Closes: #197473
   * Move the default repository location from /var/lib/cvs to /srv/cvs for
     better FHS compliance. Closes: #284710, thanks to Pierre THIERRY for
     the patch.
   * LOTS of fixes for silly mistakes in the auto-generated CVS man page.
     Closes: #365078 (and then some)
   * Break "tag" and "rtag" in the cvs.5 man page. Closes: #422128
   * Added IPV6 support, thanks to a patch from KIMURA Yasuhiro.
     Closes: #430415
   * Minor rules file cleanup (old commented lines removed)
Files: 
 9b0c6aec8f89b63aea389b3eb042e69c 748 devel optional cvs_1.12.13-10.dsc
 6a16f72ceb7a0c265cb82548021df269 102156 devel optional cvs_1.12.13-10.diff.gz
 19fcfb8cc72abcc9d98ad7b5ee7aede9 1681442 devel optional cvs_1.12.13-10_i386.deb

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)

iD8DBQFHnRNGfDt5cIjHwfcRAvk/AJ9nRIPVx4OjB25p5kdcjBoOrnKpKwCeLZcg
96GzDIE9Tdse/C4LHouK0Y8=
=0TK8
-----END PGP SIGNATURE-----



--- End Message ---

Reply via email to