Package backend :: Package server :: Package importlib :: Module headerSource
[hide private]
[frames] | no frames]

Source Code for Module backend.server.importlib.headerSource

  1  # 
  2  # Copyright (c) 2008--2020 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  # Converts headers to the intermediate format 
 17  # 
 18   
 19  import time 
 20  import string 
 21  from importLib import File, Dependency, ChangeLog, Channel, \ 
 22      IncompletePackage, Package, SourcePackage 
 23  from backendLib import gmtime, localtime 
 24  from spacewalk.common.usix import ListType, TupleType, IntType, LongType, StringType, UnicodeType 
 25  from spacewalk.common.rhnLog import log_debug 
 26  from spacewalk.common.stringutils import to_string 
 27  from spacewalk.common.usix import LongType 
 28   
 29   
30 -class rpmPackage(IncompletePackage):
31 # Various mappings 32 tagMap = { 33 # Ignoring these tags 34 'last_modified': None, 35 # We set them differently 36 'checksum': None, 37 'checksum_type': None, 38 'checksum_list': None, 39 'sigchecksum': None, 40 'sigchecksum_type': None, 41 } 42
43 - def populate(self, header, size, checksum_type, checksum, path=None, org_id=None, 44 header_start=None, header_end=None, channels=[]):
45 46 # XXX is seems to me that this is the place that 'source_rpm' is getting 47 # set 48 for f in self.keys(): 49 field = f 50 if f in self.tagMap: 51 field = self.tagMap[f] 52 if not field: 53 # Unsupported 54 continue 55 56 # get the db field value from the header 57 val = header[field] 58 if f == 'build_time': 59 if type(val) in (IntType, LongType): 60 # A UNIX timestamp without timezone => UTC timezone 61 val = gmtime(val) 62 if f == 'payload_size': 63 if val is None: 64 # use longarchivesize header field for rpms with archive > 4GB 65 if ('longarchivesize' in header) and (header['longarchivesize'] > 0): 66 val = header['longarchivesize'] 67 elif val < 0: 68 # workaround for older rpms where signed 69 # attributes go negative for size > 2G 70 val = LongType(val) + 2 ** 32 71 elif val: 72 # Convert to strings 73 if isinstance(val, UnicodeType): 74 val = to_string(val) 75 else: 76 val = str(val) 77 elif val == []: 78 val = None 79 self[f] = val 80 81 self['package_size'] = size 82 self['checksum_type'] = checksum_type 83 self['checksum'] = checksum 84 self['checksums'] = {checksum_type: checksum} 85 self['path'] = path 86 self['org_id'] = org_id 87 self['header_start'] = header_start 88 self['header_end'] = header_end 89 self['last_modified'] = localtime(time.time()) 90 if 'sigmd5' in self: 91 if self['sigmd5']: 92 self['sigchecksum_type'] = 'md5' 93 self['sigchecksum'] = self['sigmd5'] 94 del(self['sigmd5']) 95 96 # Fix some of the information up 97 vendor = self['vendor'] 98 if vendor is None: 99 self['vendor'] = 'Red Hat, Inc.' 100 payloadFormat = self['payload_format'] 101 if payloadFormat is None: 102 self['payload_format'] = 'cpio' 103 if self['payload_size'] is None: 104 self['payload_size'] = 0 105 return self
106 107
108 -class rpmBinaryPackage(Package, rpmPackage):
109 # Various mappings 110 tagMap = rpmPackage.tagMap.copy() 111 tagMap.update({ 112 'package_group': 'group', 113 'rpm_version': 'rpmversion', 114 'payload_size': 'archivesize', 115 'installed_size': 'size', 116 'payload_format': 'payloadformat', 117 'build_host': 'buildhost', 118 'build_time': 'buildtime', 119 'source_rpm': 'sourcerpm', 120 # Arrays: require a different mapping 121 'requires': None, 122 'provides': None, 123 'conflicts': None, 124 'obsoletes': None, 125 'suggests': None, 126 'supplements': None, 127 'enhances': None, 128 'recommends': None, 129 'breaks': None, 130 'predepends': None, 131 'files': None, 132 'changelog': None, 133 'channels': None, 134 # We set them differently 135 'package_size': None, 136 'org_id': None, 137 'md5sum': None, 138 'path': None, 139 'header_start': None, 140 'header_end': None, 141 # Unsupported 142 'sigpgp': None, 143 'siggpg': None, 144 'package_id': None, 145 'multi_arch': None, 146 }) 147
148 - def populate(self, header, size, checksum_type, checksum, path=None, org_id=None, 149 header_start=None, header_end=None, channels=[]):
150 151 rpmPackage.populate(self, header, size, checksum_type, checksum, path, org_id, 152 header_start, header_end) 153 154 # bz 1218762: if package group is None 155 if self['package_group'] is None: 156 self['package_group'] = "Unspecified" 157 158 # workaround for bug in rpm-python <= 4.4.2.3-27.el5 (BZ# 783451) 159 self['package_group'] = self['package_group'].rstrip() 160 # Populate file information 161 self._populateFiles(header) 162 # Populate dependency information 163 self._populateDependencyInformation(header) 164 # Populate changelogs 165 self._populateChangeLog(header) 166 # Channels 167 self._populateChannels(channels)
168
169 - def _populateFiles(self, header):
170 self._populateTag(header, 'files', rpmFile)
171
172 - def _populateDependencyInformation(self, header):
173 mapping = { 174 'provides' : rpmProvides, 175 'requires' : rpmRequires, 176 'conflicts' : rpmConflicts, 177 'obsoletes' : rpmObsoletes, 178 'breaks' : rpmBreaks, 179 'predepends': rpmPredepends, 180 } 181 182 old_weak_deps_mapping = { 183 'supplements' : rpmOldSupplements, 184 'enhances' : rpmOldEnhances, 185 'suggests' : rpmOldSuggests, 186 'recommends' : rpmOldRecommends, 187 } 188 189 new_weak_deps_mapping = { 190 'supplements' : rpmSupplements, 191 'enhances' : rpmEnhances, 192 'suggests' : rpmSuggests, 193 'recommends': rpmRecommends, 194 } 195 196 for k, v in mapping.items(): 197 self._populateTag(header, k, v) 198 for k, v in old_weak_deps_mapping.items(): 199 self._populateTag(header, k, v) 200 for k, v in new_weak_deps_mapping.items(): 201 self._populateTag(header, k, v)
202
203 - def _populateChangeLog(self, header):
204 self._populateTag(header, 'changelog', rpmChangeLog)
205
206 - def _populateChannels(self, channels):
207 l = [] 208 for channel in channels: 209 dict = {'label': channel} 210 obj = Channel() 211 obj.populate(dict) 212 l.append(obj) 213 self['channels'] = l
214
215 - def _populateTag(self, header, tag, Class):
216 """ 217 Populates a tag with a list of Class instances, getting the 218 information from a header 219 """ 220 # First fix rpm's brokenness - sometimes singe-elements lists are 221 # actually single elements 222 fix = {} 223 itemcount = 0 224 225 for f, rf in Class.tagMap.items(): 226 v = sanitizeList(header[rf]) 227 ic = len(v) 228 if not itemcount or ic < itemcount: 229 itemcount = ic 230 fix[f] = v 231 232 # Now create the array of objects 233 if self[tag] is None: 234 self[tag] = [] 235 236 unique_deps = [] 237 for i in range(itemcount): 238 hash = {} 239 for k, v in fix.items(): 240 # bugzilla 426963: fix for rpm v3 obsoletes header with 241 # empty version and flags values 242 if not len(v) and k == 'version': 243 hash[k] = '' 244 elif not len(v) and k == 'flags': 245 hash[k] = 0 246 else: 247 hash[k] = v[i] 248 249 # for the old weak dependency tags 250 # RPMSENSE_STRONG(1<<27) indicate recommends; if not set it is suggests only 251 if Class in [rpmOldRecommends, rpmOldSupplements, rpmOldSuggests, rpmOldEnhances]: 252 if tag in ['recommends', 'supplements'] and not(hash['flags'] & (1 << 27)): 253 continue 254 if tag in ['suggests', 'enhances'] and (hash['flags'] & (1 << 27)): 255 continue 256 # Create a file 257 obj = Class() 258 # Fedora 10+ rpms have duplicate provides deps, 259 # Lets clean em up before db inserts. 260 if tag in ['requires', 'provides', 'obsoletes', 'conflicts', 'recommends', 'suggests', 'supplements', 'enhances', 'breaks', 'predepends']: 261 if not len(hash['name']): 262 continue 263 dep_nv = (hash['name'], hash['version'], hash['flags']) 264 265 if dep_nv not in unique_deps: 266 unique_deps.append(dep_nv) 267 obj.populate(hash) 268 self[tag].append(obj) 269 else: 270 # duplicate dep, ignore 271 continue 272 else: 273 if tag == 'files': 274 hash['checksum_type'] = self['checksum_type'] 275 obj.populate(hash) 276 self[tag].append(obj)
277 278
279 -class rpmSourcePackage(SourcePackage, rpmPackage):
280 tagMap = rpmPackage.tagMap.copy() 281 tagMap.update({ 282 'package_group': 'group', 283 'rpm_version': 'rpmversion', 284 'payload_size': 'archivesize', 285 'build_host': 'buildhost', 286 'build_time': 'buildtime', 287 'source_rpm': 'sourcerpm', 288 # Arrays: require a different mapping 289 # We set them differently 290 'package_size': None, 291 'org_id': None, 292 'md5sum': None, 293 'path': None, 294 # Unsupported 295 'payload_format': None, 296 'channels': None, 297 'package_id': None, 298 }) 299
300 - def populate(self, header, size, checksum_type, checksum, path=None, org_id=None, 301 header_start=None, header_end=None, channels=[]):
302 rpmPackage.populate(self, header, size, checksum_type, checksum, path, org_id, 303 header_start, header_end) 304 # bz 1218762: if package group is None 305 if self['package_group'] is None: 306 self['package_group'] = "Unspecified" 307 308 nvr = [] 309 # workaround for bug in rpm-python <= 4.4.2.3-27.el5 (BZ# 783451) 310 self['package_group'] = self['package_group'].rstrip() 311 # Fill in source_rpm 312 for tag in ['name', 'version', 'release']: 313 nvr.append(header[tag]) 314 315 # 5/13/05 wregglej - 154248 If 1051 is in the list of keys in the header, 316 # the package is a nosrc package and needs to be saved as such. 317 if 1051 in list(header.keys()): 318 self['source_rpm'] = "%s-%s-%s.nosrc.rpm" % tuple(nvr) 319 else: 320 self['source_rpm'] = "%s-%s-%s.src.rpm" % tuple(nvr) 321 322 # Convert sigchecksum to ASCII 323 self['sigchecksum_type'] = 'md5' 324 self['sigchecksum'] = string.join( 325 ["%02x" % ord(x) for x in self['sigchecksum']], '')
326 327
328 -class rpmFile(File, ChangeLog):
329 # Mapping from the attribute's names to rpm tags 330 tagMap = { 331 'name': 'filenames', 332 'device': 'filedevices', 333 'inode': 'fileinodes', 334 'file_mode': 'filemodes', 335 'username': 'fileusername', 336 'groupname': 'filegroupname', 337 'rdev': 'filerdevs', 338 'file_size': 'filesizes', 339 'mtime': 'filemtimes', 340 'filedigest': 'filemd5s', # FILEMD5S is a pre-rpm4.6 name for FILEDIGESTS 341 # we have to use it for compatibility reason 342 'linkto': 'filelinktos', 343 'flags': 'fileflags', 344 'verifyflags': 'fileverifyflags', 345 'lang': 'filelangs', 346 } 347
348 - def populate(self, hash):
349 ChangeLog.populate(self, hash) 350 # Fix the time 351 tm = self['mtime'] 352 if type(tm) in (IntType, LongType): 353 # A UNIX timestamp 354 self['mtime'] = localtime(tm) 355 if type(self['filedigest']) == StringType: 356 self['checksum'] = self['filedigest'] 357 del(self['filedigest'])
358 359
360 -class rpmProvides(Dependency):
361 # More mappings 362 tagMap = { 363 'name': 'provides', 364 'version': 'provideversion', 365 'flags': 'provideflags', 366 }
367 368
369 -class rpmRequires(Dependency):
370 # More mappings 371 tagMap = { 372 'name': 'requirename', 373 'version': 'requireversion', 374 'flags': 'requireflags', 375 }
376
377 -class rpmOldSuggests(Dependency):
378 # More mappings 379 tagMap = { 380 'name': 1156, # 'suggestsname', 381 'version': 1157, # 'suggestsversion', 382 'flags': 1158, # 'suggestsflags', 383 }
384
385 -class rpmSuggests(Dependency):
386 # More mappings 387 tagMap = { 388 'name' : 5049, #'suggestsname', 389 'version' : 5050, #'suggestsversion', 390 'flags' : 5051, #'suggestsflags', 391 }
392
393 -class rpmOldRecommends(Dependency):
394 # More mappings 395 tagMap = { 396 'name' : 1156, #'recommendsname', 397 'version' : 1157, #'recommendsversion', 398 'flags' : 1158, #'recommendsflags', 399 }
400
401 -class rpmRecommends(Dependency):
402 # More mappings 403 tagMap = { 404 'name' : 5046, #'recommendsname', 405 'version' : 5047, #'recommendsversion', 406 'flags' : 5048, #'recommendsflags', 407 }
408
409 -class rpmOldSupplements(Dependency):
410 # More mappings 411 tagMap = { 412 'name' : 1159, #'supplementsname', 413 'version' : 1160, #'supplementsversion', 414 'flags' : 1161, #'supplementsflags', 415 }
416
417 -class rpmSupplements(Dependency):
418 # More mappings 419 tagMap = { 420 'name' : 5052, #'supplementsname', 421 'version' : 5053, #'supplementsversion', 422 'flags' : 5054, #'supplementsflags', 423 }
424
425 -class rpmOldEnhances(Dependency):
426 # More mappings 427 tagMap = { 428 'name' : 1159, #'enhancesname', 429 'version' : 1160, #'enhancesversion', 430 'flags' : 1161, #'enhancesflags', 431 }
432
433 -class rpmEnhances(Dependency):
434 # More mappings 435 tagMap = { 436 'name' : 5055, #'enhancesname', 437 'version' : 5056, #'enhancesversion', 438 'flags' : 5057, #'enhancesflags', 439 }
440
441 -class rpmConflicts(Dependency):
442 # More mappings 443 tagMap = { 444 'name': 'conflictname', 445 'version': 'conflictversion', 446 'flags': 'conflictflags', 447 }
448 449
450 -class rpmObsoletes(Dependency):
451 # More mappings 452 tagMap = { 453 'name': 'obsoletename', 454 'version': 'obsoleteversion', 455 'flags': 'obsoleteflags', 456 }
457 458
459 -class rpmBreaks(Dependency):
460 # More mappings 461 tagMap = { 462 'name': 1159, # 'enhancesname' 463 'version': 1160, # 'enhancesversion' 464 'flags': 1161, # 'enhancesflags' 465 }
466 467
468 -class rpmPredepends(Dependency):
469 # More mappings 470 tagMap = { 471 'name': 1159, # 'enhancesname' 472 'version': 1160, # 'enhancesversion' 473 'flags': 1161, # 'enhancesflags' 474 }
475 476
477 -class rpmChangeLog(ChangeLog):
478 tagMap = { 479 'name': 'changelogname', 480 'text': 'changelogtext', 481 'time': 'changelogtime', 482 } 483
484 - def populate(self, hash):
485 ChangeLog.populate(self, hash) 486 # Fix the time 487 tm = self['time'] 488 if type(tm) in (IntType, LongType): 489 # A UNIX timestamp 490 self['time'] = localtime(tm) 491 # In changelog, data is either in UTF-8, or in any other 492 # undetermined encoding. Assume ISO-Latin-1 if not UTF-8. 493 for i in ('text', 'name'): 494 try: 495 self[i] = UnicodeType(self[i], "utf-8") 496 except UnicodeDecodeError: 497 self[i] = UnicodeType(self[i], "iso-8859-1")
498 499
500 -def sanitizeList(l):
501 if l is None: 502 return [] 503 if type(l) in (ListType, TupleType): 504 return l 505 return [l]
506 507
508 -def createPackage(header, size, checksum_type, checksum, relpath, org_id, header_start, 509 header_end, channels):
510 """ 511 Returns a populated instance of rpmBinaryPackage or rpmSourcePackage 512 """ 513 if header.is_source: 514 log_debug(4, "Creating source package") 515 p = rpmSourcePackage() 516 else: 517 log_debug(4, "Creating package") 518 p = rpmBinaryPackage() 519 520 # bug #524231 - we need to call fullFilelist() for RPM v3 file list 521 # to expand correctly 522 header.hdr.fullFilelist() 523 p.populate(header, size, checksum_type, checksum, relpath, org_id, header_start, header_end, 524 channels) 525 return p
526