138 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			138 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
#!/usr/bin/env python
 | 
						|
# -*- coding: utf-8 -*-
 | 
						|
#
 | 
						|
# Lightweight RPM to CPIO converter.
 | 
						|
# Copyright © 2008-2017 Rudá Moura. All rights reserved.
 | 
						|
#
 | 
						|
 | 
						|
'''Extract cpio archive from RPM package.
 | 
						|
 | 
						|
rpm2cpio converts the RPM on standard input or first parameter to a CPIO archive on standard output.
 | 
						|
 | 
						|
Usage:
 | 
						|
rpm2cpio < adjtimex-1.20-2.1.i386.rpm  | cpio -it
 | 
						|
./sbin/adjtimex
 | 
						|
./usr/share/doc/adjtimex-1.20
 | 
						|
./usr/share/doc/adjtimex-1.20/COPYING
 | 
						|
./usr/share/doc/adjtimex-1.20/COPYRIGHT
 | 
						|
./usr/share/doc/adjtimex-1.20/README
 | 
						|
./usr/share/man/man8/adjtimex.8.gz
 | 
						|
133 blocks
 | 
						|
'''
 | 
						|
 | 
						|
from __future__ import print_function
 | 
						|
 | 
						|
import sys
 | 
						|
import gzip
 | 
						|
import subprocess
 | 
						|
 | 
						|
try:
 | 
						|
    from StringIO import StringIO
 | 
						|
except ImportError:
 | 
						|
    from io import StringIO
 | 
						|
 | 
						|
HAS_LZMA_MODULE = True
 | 
						|
try:
 | 
						|
    import lzma
 | 
						|
except ImportError:
 | 
						|
    try:
 | 
						|
        import backports.lzma as lzma
 | 
						|
    except ImportError:
 | 
						|
        HAS_LZMA_MODULE = False
 | 
						|
 | 
						|
 | 
						|
RPM_MAGIC = b'\xed\xab\xee\xdb'
 | 
						|
GZIP_MAGIC = b'\x1f\x8b'
 | 
						|
XZ_MAGIC = b'\xfd7zXZ\x00'
 | 
						|
 | 
						|
 | 
						|
def gzip_decompress(data):
 | 
						|
    gzstream = StringIO(data)
 | 
						|
    gzipper = gzip.GzipFile(fileobj=gzstream)
 | 
						|
    data = gzipper.read()
 | 
						|
    return data
 | 
						|
 | 
						|
 | 
						|
def xz_decompress(data):
 | 
						|
    if HAS_LZMA_MODULE:
 | 
						|
        return lzma.decompress(data)
 | 
						|
    unxz = subprocess.Popen(['unxz'],
 | 
						|
                            stdin=subprocess.PIPE,
 | 
						|
                            stdout=subprocess.PIPE)
 | 
						|
    data = unxz.communicate(input=data)[0]
 | 
						|
    return data
 | 
						|
 | 
						|
 | 
						|
def is_rpm(reader):
 | 
						|
    lead = reader.read(96)
 | 
						|
    return lead[0:4] == RPM_MAGIC
 | 
						|
 | 
						|
 | 
						|
def extract_cpio(reader):
 | 
						|
    data = reader.read()
 | 
						|
    decompress = None
 | 
						|
    idx = data.find(XZ_MAGIC)
 | 
						|
    if idx != -1:
 | 
						|
        decompress = xz_decompress
 | 
						|
        pos = idx
 | 
						|
    idx = data.find(GZIP_MAGIC)
 | 
						|
    if idx != -1 and decompress is None:
 | 
						|
        decompress = gzip_decompress
 | 
						|
        pos = idx
 | 
						|
    if decompress is None:
 | 
						|
        return None
 | 
						|
    data = decompress(data[pos:])
 | 
						|
    return data
 | 
						|
 | 
						|
 | 
						|
def rpm2cpio(stream_in=None, stream_out=None):
 | 
						|
    if stream_in is None:
 | 
						|
        stream_in = sys.stdin
 | 
						|
    if stream_out is None:
 | 
						|
        stream_out = sys.stdout
 | 
						|
    try:
 | 
						|
        reader = stream_in.buffer
 | 
						|
        writer = stream_out.buffer
 | 
						|
    except AttributeError:
 | 
						|
        reader = stream_in
 | 
						|
        writer = stream_out
 | 
						|
    if not is_rpm(reader):
 | 
						|
        raise IOError('the input is not a RPM package')
 | 
						|
    cpio = extract_cpio(reader)
 | 
						|
    if cpio is None:
 | 
						|
        raise IOError('could not find compressed cpio archive')
 | 
						|
    writer.write(cpio)
 | 
						|
 | 
						|
 | 
						|
def main(args=None):
 | 
						|
    if args is None:
 | 
						|
        args = sys.argv
 | 
						|
    if args[1:]:
 | 
						|
        try:
 | 
						|
            fin = open(args[1])
 | 
						|
            rpm2cpio(fin)
 | 
						|
            fin.close()
 | 
						|
        except IOError as e:
 | 
						|
            print('Error:', args[1], e)
 | 
						|
            sys.exit(1)
 | 
						|
        except OSError as e:
 | 
						|
            print('Error: could not find lzma extractor')
 | 
						|
            print("Please, install Python's lzma module or the xz utility")
 | 
						|
            sys.exit(1)
 | 
						|
    else:
 | 
						|
        try:
 | 
						|
            rpm2cpio()
 | 
						|
        except IOError as e:
 | 
						|
            print('Error:', e)
 | 
						|
            sys.exit(1)
 | 
						|
        except OSError as e:
 | 
						|
            print('Error: could not find lzma extractor')
 | 
						|
            print("Please install Python's lzma module or the xz utility")
 | 
						|
            sys.exit(1)
 | 
						|
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    try:
 | 
						|
        main()
 | 
						|
    except KeyboardInterrupt:
 | 
						|
        print('Interrupted!')
 |