[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#751688: apt-utils: xz support is gone.



Control: tag -1 patch

On Sun, Jun 15, 2014 at 06:10:39PM +0200, Christian Marillat wrote:
> Packages::Compress seems to not work anymore with xz compression.
> 
> Only . (uncompressed), gzip and bzip2 seems to work, xz now return errors
> (see at the bottom).
> 
> Same error with Sources::Compress
> 
> Christian
> 
> 
> $ apt-ftparchive generate apt.conf
>  dists/unstable/main/binary-amd64/:E: write, still have 32768 to write but
> couldn't
> E: IO to subprocess/file failed - write (0: Success)
> E: write, still have 32768 to write but couldn't

The same bug hit the Ubuntu archive when we tried to add xz support
recently.  I finally got round to tracking this down.  The problem is
that the liblzma-based write code needs the same tweaks that the read
code already has to cope with the situation where lzma_code returns zero
the first time through because avail_out is zero, but will do more work
if called again.

The following patch ports the read tweaks to the write code as closely
as possible (including matching comments etc.), and it's working fine
for me now.

diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc
index eae4d23..b7c7b23 100644
--- a/apt-pkg/contrib/fileutl.cc
+++ b/apt-pkg/contrib/fileutl.cc
@@ -1816,6 +1816,7 @@ public:
    }
    virtual ssize_t InternalWrite(void const * const From, unsigned long long const Size) override
    {
+      ssize_t Res;
       lzma->stream.next_in = (uint8_t *)From;
       lzma->stream.avail_in = Size;
       lzma->stream.next_out = lzma->buffer;
@@ -1826,9 +1827,21 @@ public:
       size_t const n = sizeof(lzma->buffer)/sizeof(lzma->buffer[0]) - lzma->stream.avail_out;
       size_t const m = (n == 0) ? 0 : fwrite(lzma->buffer, 1, n, lzma->file);
       if (m != n)
-	 return -1;
+      {
+	 Res = -1;
+	 errno = 0;
+      }
       else
-	 return Size - lzma->stream.avail_in;
+      {
+	 Res = Size - lzma->stream.avail_in;
+	 if (Res == 0)
+	 {
+	    // lzma run was okay, but produced no output…
+	    Res = -1;
+	    errno = EINTR;
+	 }
+      }
+      return Res;
    }
    virtual bool InternalWriteError() override
    {
@@ -2425,10 +2438,18 @@ bool FileFd::Write(const void *From,unsigned long long Size)
    while (Res > 0 && Size > 0)
    {
       Res = d->InternalWrite(From, Size);
-      if (Res < 0 && errno == EINTR)
-	 continue;
+
       if (Res < 0)
+      {
+	 if (errno == EINTR)
+	 {
+	    // trick the while-loop into running again
+	    Res = 1;
+	    errno = 0;
+	    continue;
+	 }
 	 return d->InternalWriteError();
+      }
 
       From = (char const *)From + Res;
       Size -= Res;

Thanks,

-- 
Colin Watson                                       [cjwatson@ubuntu.com]


Reply to: