[PATCH] Add bzip2, lzma support to rpm2cpio()

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

 



Hello,

The attached patch adds support for bzip2 and lzma payloads to rpm2cpio().  
lzma support was done using pyliblzma from https://launchpad.net/pyliblzma

We discussed this patch previously in private mail with James, he wasn't quite 
satisfied with the patch, continuing discussion here per his request:

> On Friday 23 January 2009, James Antill wrote:
>> Ville Skyttä <ville.skytta@xxxxxx> writes:

>> Regarding the "too ugly" part, I'm afraid there's not much that can be done
>> to radically change it, the python gzip API is different from bz2 and lzma.
>> First, there's no similar decompressor object for gzip that exists for bz2
>> and lzma.  There's one in zlib but that one doesn't handle the gzip header
>> so that would have to be done manually which sure would be even uglier and
>> possibly fragile code duplication IMO.  Second unlike GzipFile, BZ2File and
>> LZMAFile don't have an option to pass an existing open file object (or file
>> descriptor) to them, they operate on filenames.
>
> Well it looked like at least the bz2 and lzma ones could share a code
> path, and maybe some of the control flow.

Hmm, but they do share the main decompression loop.  The only real differences 
are construction (obviously a necessity), and that lzma requires flush() to 
be called at the end but the bz2 decompressor doesn't have that method.  I'm 
sure the EOFError was needed for one (or perhaps both) of these, but the 
patch has been floating around in my local workspace so long that I've 
forgotten details about that.

> Seth also mentioned that 
> he'd prefer if that moved to a "cpio" property on YumLocalPackage
> anyway,

Ok, maybe there's some code in this patch that can be reused for that.

> and just deprecate the old rpmUtils interface. 

I see uses for rpm2cpio like functionality for external programs, such as for 
example rpmlint, so for those cases not depracating it would be useful.  But 
then again, I can't make rpmUtils a rpmlint dependency because it's part of 
yum and I'm sure distros that don't use yum otherwise wouldn't welcome a 
whole new depsolver dragged in for this purpose only.  Has splitting rpmUtils 
to a separate package been considered?
From b45171d74e94e051efe1637a2f17fdc0127c9f8b Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Ville=20Skytt=C3=A4?= <ville.skytta@xxxxxx>
Date: Thu, 22 Jan 2009 22:54:51 +0200
Subject: [PATCH] Add bzip2 and lzma support to rpm2cpio().

---
 rpmUtils/miscutils.py |   60 ++++++++++++++++++++++++++++++++++++------------
 1 files changed, 45 insertions(+), 15 deletions(-)

diff --git a/rpmUtils/miscutils.py b/rpmUtils/miscutils.py
index ee8cd79..a339193 100644
--- a/rpmUtils/miscutils.py
+++ b/rpmUtils/miscutils.py
@@ -18,11 +18,18 @@
 import rpm
 import types
 import gzip
+import bz2
 import os
 import sys
 import locale
 import signal
 
+try:
+    import lzma
+    have_lzma = True
+except:
+    have_lzma = False
+
 import rpmUtils.transaction
 
 def rpmOutToStr(arg):
@@ -317,22 +324,45 @@ def rpm2cpio(fdno, out=sys.stdout, bufsize=2048):
     ts = rpmUtils.transaction.initReadOnlyTransaction()
     hdr = ts.hdrFromFdno(fdno)
     del ts
-    
+
     compr = hdr[rpm.RPMTAG_PAYLOADCOMPRESSOR] or 'gzip'
-    #XXX FIXME
-    #if compr == 'bzip2':
-        # TODO: someone implement me!
-    #el
-    if compr != 'gzip':
-        raise rpmUtils.RpmUtilsError, \
-              'Unsupported payload compressor: "%s"' % compr
-    f = gzip.GzipFile(None, 'rb', None, os.fdopen(fdno, 'rb', bufsize))
-    while 1:
-        tmp = f.read(bufsize)
-        if tmp == "": break
-        out.write(tmp)
-    f.close()
-                                                                                
+
+    fo = os.fdopen(fdno, 'rb', bufsize)
+    try:
+        if compr == 'gzip':
+            fo = gzip.GzipFile(None, 'rb', None, fo)
+            data = fo.read(bufsize)
+            while data != '':
+                out.write(data)
+                data = fo.read(bufsize)
+        elif compr == 'bzip2' or compr == 'lzma':
+            if compr == 'lzma':
+                if have_lzma:
+                    decomp = lzma.LZMADecompressor()
+                else:
+                    raise rpmUtils.RpmUtilsError, \
+                          'lzma payload decompression requires the lzma module'
+            else:
+                decomp = bz2.BZ2Decompressor()
+            try:
+                raw = fo.read(bufsize)
+                while raw != '':
+                    data = decomp.decompress(raw)
+                    if data is not None:
+                        out.write(data)
+                    raw = fo.read(bufsize)
+            except EOFError:
+                pass
+            if hasattr(decomp, 'flush'):
+                data = decomp.flush()
+                if data is not None:
+                    out.write(data)
+        else:
+            raise rpmUtils.RpmUtilsError, \
+                  'Unsupported payload compressor: "%s"' % compr
+    finally:
+        fo.close()
+
 def formatRequire (name, version, flags):
     s = name
     
-- 
1.5.6.6

_______________________________________________
Yum mailing list
Yum@xxxxxxxxxxxxxxxxx
http://lists.baseurl.org/mailman/listinfo/yum

[Index of Archives]     [Fedora Users]     [Fedora Legacy List]     [Fedora Maintainers]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]

  Powered by Linux