Trees | Indices | Help |
---|
|
1 # 2 # Copyright (c) 2008--2016 Red Hat, Inc. 3 # 4 # This software is licensed to you under the GNU General Public License, 5 # version 2 (GPLv2). There is NO WARRANTY for this software, express or 6 # implied, including the implied warranties of MERCHANTABILITY or FITNESS 7 # FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 8 # along with this software; if not, see 9 # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 10 # 11 # Red Hat trademarks are not licensed under GPLv2. No permission is 12 # granted to use or replicate Red Hat trademarks that are incorporated 13 # in this software or its documentation. 14 # 15 16 import os 17 import gzip 18 try: 19 # python 2 20 import cStringIO 21 except ImportError: 22 # python3 23 import io as cStringIO 24 import tempfile 25 try: 26 # python 2 27 import xmlrpclib 28 except ImportError: 29 # python3 30 import xmlrpc.client as xmlrpclib # pylint: disable=F0401 31 import struct 32 import sys 33 from spacewalk.common import fileutils 34 35 from spacewalk.common.usix import ListType, TupleType 36 37 from spacewalk.common.usix import raise_with_tb 38 from spacewalk.common import checksum 39 from spacewalk.common.rhn_pkg import A_Package, InvalidPackageError 40 41 # bare-except and broad-except 42 # pylint: disable=W0702,W0703 43 44 MPM_CHECKSUM_TYPE = 'md5' # FIXME: this should be a configuration option48 try: 49 from spacewalk.common import rhn_rpm 50 except ImportError: 51 # rhn_rpm not avalable; return a dummy comparison function 52 return -1 53 return rhn_rpm.labelCompare(l1, l2)54 5861 """ Loads an MPM and returns its header and its payload """ 62 if (filename is None and file_obj is None and fd is None): 63 raise ValueError("No parameters passed") 64 65 if filename is not None: 66 f = open(filename) 67 elif file_obj is not None: 68 f = file_obj 69 else: # fd is not None 70 f = os.fdopen(os.dup(fd), "r") 71 72 f.seek(0, 0) 73 74 p = MPM_Package() 75 try: 76 p.load(f) 77 except InvalidPackageError: 78 e = sys.exc_info()[1] 79 try: 80 return load_rpm(f) 81 except InvalidPackageError: 82 raise_with_tb(e, sys.exc_info()[2]) 83 except: 84 raise_with_tb(e, sys.exc_info()[2]) 85 86 return p.header, p.payload_stream8790 # Hmm, maybe an rpm 91 92 try: 93 from spacewalk.common import rhn_rpm 94 except ImportError: 95 raise_with_tb(InvalidPackageError, sys.exc_info()[2]) 96 97 # Dup the file descriptor, we don't want it to get closed before we read 98 # the payload 99 newfd = os.dup(stream.fileno()) 100 stream = os.fdopen(newfd, "r") 101 102 stream.flush() 103 stream.seek(0, 0) 104 105 try: 106 header = rhn_rpm.get_package_header(file_obj=stream) 107 except InvalidPackageError: 108 e = sys.exc_info()[1] 109 raise_with_tb(InvalidPackageError(*e.args), sys.exc_info()[2]) 110 except rhn_rpm.error: 111 e = sys.exc_info()[1] 112 raise_with_tb(InvalidPackageError(e), sys.exc_info()[2]) 113 except: 114 raise_with_tb(InvalidPackageError, sys.exc_info()[2]) 115 stream.seek(0, 0) 116 117 return header, stream118121 122 "Wrapper class for an mpm header - we need to store a flag is_source" 123156 157 MPM_HEADER_COMPRESSED_GZIP = 1 158 MPM_PAYLOAD_COMPRESSED_GZIP = 1125 self.hdr = hdr 126 self.is_source = hdr.get('is_source') 127 self.packaging = 'mpm' 128 self.signatures = []129 132134 self.hdr[name] = item135137 del self.hdr[name]138140 return getattr(self.hdr, name)141 144 145 @staticmethod 148 149 @staticmethod151 return MPM_CHECKSUM_TYPE152 153 @staticmethod162 # pylint: disable=R0902 163 _lead_format = '!16sB3s4L92s' 164 _magic = 'mpmpackage012345' 165296167 A_Package.__init__(self, input_stream) 168 self.header_flags = MPM_HEADER_COMPRESSED_GZIP 169 self.header_size = 0 170 self.payload_flags = 0 171 assert(len(self._magic) == 16) 172 self._buffer_size = 16384 173 self.file_size = 0174176 arr = self._read_lead(self.input_stream) 177 magic = arr[0] 178 if magic != self._magic: 179 raise InvalidPackageError() 180 header_len, payload_len = int(arr[5]), int(arr[6]) 181 self.header_flags, self.payload_flags = arr[3], arr[4] 182 self.file_size = 128 + header_len + payload_len 183 header_data = self._read_bytes(self.input_stream, header_len) 184 self._read_header(header_data, self.header_flags) 185 self.checksum_type = self.header.checksum_type()186188 # Lead has the following format: 189 # 16 bytes magic 190 # 1 bytes version 191 # 3 bytes unused 192 # 4 bytes header flags 193 # 4 bytes payload flags 194 # 4 bytes header length 195 # 4 bytes payload length 196 # 92 bytes padding to 128 bytes 197 lead = self._read_bytes(stream, 128) 198 if len(lead) != 128: 199 raise InvalidPackageError() 200 201 arr = struct.unpack(self._lead_format, lead) 202 return arr203205 # Clean up 206 self.__init__() 207 self.input_stream = input_stream 208 # Read the header 209 self.read_header() 210 211 payload_stream = fileutils.payload(input_stream.name, input_stream.tell()) 212 input_stream.seek(self.file_size) 213 if self.file_size != input_stream.tell(): 214 raise InvalidPackageError() 215 216 self._read_payload(payload_stream, self.payload_flags)217219 if header_flags & MPM_HEADER_COMPRESSED_GZIP: 220 t = cStringIO.StringIO(header_data) 221 g = gzip.GzipFile(None, "r", 0, t) 222 header_data = g.read() 223 g.close() 224 t.close() 225 226 try: 227 params, _x = xmlrpclib.loads(header_data) 228 except: 229 # XXX 230 raise 231 232 self.header = MPM_Header(params[0])233235 payload_stream.seek(0, 0) 236 if payload_flags & MPM_PAYLOAD_COMPRESSED_GZIP: 237 g = gzip.GzipFile(None, "r", 0, payload_stream) 238 t = tempfile.TemporaryFile() 239 self._stream_copy(g, t) 240 g.close() 241 payload_stream = t 242 243 self.payload_stream = payload_stream244246 if self.header is None: 247 raise Exception() 248 249 output_stream.seek(128, 0) 250 self._encode_header(output_stream) 251 self._encode_payload(output_stream) 252 253 # pylint: disable=E0012,W1401 254 # now we know header and payload size so rewind back and write lead 255 lead_arr = (self._magic, 1, "\0" * 3, self.header_flags, 256 self.payload_flags, self.header_size, self.payload_size, '\0' * 92) 257 # lead 258 lead = struct.pack(self._lead_format, *lead_arr) 259 output_stream.seek(0, 0) 260 output_stream.write(lead) 261 output_stream.seek(0, 2)262264 assert(self.header is not None) 265 data = xmlrpclib.dumps((_replace_null(self.header), )) 266 start = stream.tell() 267 if self.header_flags & MPM_HEADER_COMPRESSED_GZIP: 268 f = gzip.GzipFile(None, "wb", 9, stream) 269 f.write(data) 270 f.close() 271 else: 272 stream.write(data) 273 stream.flush() 274 self.header_size = stream.tell() - start275277 assert(self.payload_stream is not None) 278 if stream: 279 start = stream.tell() 280 if stream and self.payload_flags & MPM_PAYLOAD_COMPRESSED_GZIP: 281 f = gzip.GzipFile(None, "wb", 9, stream) 282 self._stream_copy(self.payload_stream, f, c_hash) 283 f.close() 284 else: 285 self._stream_copy(self.payload_stream, stream, c_hash) 286 if stream: 287 self.payload_size = stream.tell() - start288290 self.payload_stream = self.input_stream 291 c_hash = checksum.getHashlibInstance(self.header.checksum_type(), False) 292 self._encode_payload(output_stream, c_hash) 293 self.checksum = c_hash.hexdigest() 294 if output_stream: 295 self.payload_stream = output_stream299 if obj is None: 300 return '' 301 if isinstance(obj, ListType): 302 return list(map(_replace_null, obj)) 303 if isinstance(obj, TupleType): 304 return tuple(_replace_null(list(obj))) 305 if hasattr(obj, 'items'): 306 obj_dict = {} 307 for k, v in obj.items(): 308 obj_dict[_replace_null(k)] = _replace_null(v) 309 return obj_dict 310 return obj311
Trees | Indices | Help |
---|
Generated by Epydoc 3.0.1 on Wed Mar 4 07:37:44 2020 | http://epydoc.sourceforge.net |