139 lines
3.3 KiB
Python
139 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!')
|