1## @file 2# Install distribution package. 3# 4# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR> 5# 6# SPDX-License-Identifier: BSD-2-Clause-Patent 7# 8""" 9Install a distribution package 10""" 11## 12# Import Modules 13# 14from Core.FileHook import __FileHookOpen__ 15import os.path 16from os import chmod 17from os import SEEK_SET 18from os import SEEK_END 19import stat 20from hashlib import md5 21import copy 22from sys import stdin 23from sys import platform 24from shutil import rmtree 25from shutil import copyfile 26from traceback import format_exc 27from platform import python_version 28 29from Logger import StringTable as ST 30from Logger.ToolError import UNKNOWN_ERROR 31from Logger.ToolError import FILE_UNKNOWN_ERROR 32from Logger.ToolError import OPTION_MISSING 33from Logger.ToolError import UPT_ALREADY_INSTALLED_ERROR 34from Logger.ToolError import FatalError 35from Logger.ToolError import ABORT_ERROR 36from Logger.ToolError import CODE_ERROR 37from Logger.ToolError import FORMAT_INVALID 38from Logger.ToolError import FILE_TYPE_MISMATCH 39import Logger.Log as Logger 40 41from Library.Misc import Sdict 42from Library.Misc import ConvertPath 43from Library.ParserValidate import IsValidInstallPath 44from Xml.XmlParser import DistributionPackageXml 45from GenMetaFile.GenDecFile import PackageToDec 46from GenMetaFile.GenInfFile import ModuleToInf 47from Core.PackageFile import PackageFile 48from Core.PackageFile import FILE_NOT_FOUND 49from Core.PackageFile import FILE_CHECKSUM_FAILURE 50from Core.PackageFile import CreateDirectory 51from Core.DependencyRules import DependencyRules 52from Library import GlobalData 53 54## InstallNewPackage 55# 56# @param WorkspaceDir: Workspace Directory 57# @param Path: Package Path 58# @param CustomPath: whether need to customize path at first 59# 60def InstallNewPackage(WorkspaceDir, Path, CustomPath = False): 61 if os.path.isabs(Path): 62 Logger.Info(ST.MSG_RELATIVE_PATH_ONLY%Path) 63 elif CustomPath: 64 Logger.Info(ST.MSG_NEW_PKG_PATH) 65 else: 66 Path = ConvertPath(Path) 67 Path = os.path.normpath(Path) 68 FullPath = os.path.normpath(os.path.join(WorkspaceDir, Path)) 69 if os.path.exists(FullPath): 70 Logger.Info(ST.ERR_DIR_ALREADY_EXIST%FullPath) 71 else: 72 return Path 73 74 Input = stdin.readline() 75 Input = Input.replace('\r', '').replace('\n', '') 76 if Input == '': 77 Logger.Error("InstallPkg", UNKNOWN_ERROR, ST.ERR_USER_INTERRUPT) 78 Input = Input.replace('\r', '').replace('\n', '') 79 return InstallNewPackage(WorkspaceDir, Input, False) 80 81## InstallNewModule 82# 83# @param WorkspaceDir: Workspace Directory 84# @param Path: Standalone Module Path 85# @param PathList: The already installed standalone module Path list 86# 87def InstallNewModule(WorkspaceDir, Path, PathList = None): 88 if PathList is None: 89 PathList = [] 90 Path = ConvertPath(Path) 91 Path = os.path.normpath(Path) 92 FullPath = os.path.normpath(os.path.join(WorkspaceDir, Path)) 93 if os.path.exists(FullPath) and FullPath not in PathList: 94 Logger.Info(ST.ERR_DIR_ALREADY_EXIST%Path) 95 elif Path == FullPath: 96 Logger.Info(ST.MSG_RELATIVE_PATH_ONLY%FullPath) 97 else: 98 return Path 99 100 Input = stdin.readline() 101 Input = Input.replace('\r', '').replace('\n', '') 102 if Input == '': 103 Logger.Error("InstallPkg", UNKNOWN_ERROR, ST.ERR_USER_INTERRUPT) 104 Input = Input.replace('\r', '').replace('\n', '') 105 return InstallNewModule(WorkspaceDir, Input, PathList) 106 107 108## InstallNewFile 109# 110# @param WorkspaceDir: Workspace Direction 111# @param File: File 112# 113def InstallNewFile(WorkspaceDir, File): 114 FullPath = os.path.normpath(os.path.join(WorkspaceDir, File)) 115 if os.path.exists(FullPath): 116 Logger.Info(ST.ERR_FILE_ALREADY_EXIST %File) 117 Input = stdin.readline() 118 Input = Input.replace('\r', '').replace('\n', '') 119 if Input == '': 120 Logger.Error("InstallPkg", UNKNOWN_ERROR, ST.ERR_USER_INTERRUPT) 121 Input = Input.replace('\r', '').replace('\n', '') 122 return InstallNewFile(WorkspaceDir, Input) 123 else: 124 return File 125 126## UnZipDp 127# 128# UnZipDp 129# 130def UnZipDp(WorkspaceDir, DpPkgFileName, Index=1): 131 ContentZipFile = None 132 Logger.Quiet(ST.MSG_UZIP_PARSE_XML) 133 DistFile = PackageFile(DpPkgFileName) 134 135 DpDescFileName, ContentFileName = GetDPFile(DistFile.GetZipFile()) 136 137 TempDir = os.path.normpath(os.path.join(WorkspaceDir, "Conf/.tmp%s" % str(Index))) 138 GlobalData.gUNPACK_DIR.append(TempDir) 139 DistPkgFile = DistFile.UnpackFile(DpDescFileName, os.path.normpath(os.path.join(TempDir, DpDescFileName))) 140 if not DistPkgFile: 141 Logger.Error("InstallPkg", FILE_NOT_FOUND, ST.ERR_FILE_BROKEN %DpDescFileName) 142 143 # 144 # Generate distpkg 145 # 146 DistPkgObj = DistributionPackageXml() 147 DistPkg = DistPkgObj.FromXml(DistPkgFile) 148 if DistPkg.Header.RePackage == '': 149 DistPkg.Header.RePackage = False 150 if DistPkg.Header.ReadOnly == '': 151 DistPkg.Header.ReadOnly = False 152 153 # 154 # unzip contents.zip file 155 # 156 ContentFile = DistFile.UnpackFile(ContentFileName, os.path.normpath(os.path.join(TempDir, ContentFileName))) 157 if not ContentFile: 158 Logger.Error("InstallPkg", FILE_NOT_FOUND, 159 ST.ERR_FILE_BROKEN % ContentFileName) 160 161 # 162 # Get file size 163 # 164 FileSize = os.path.getsize(ContentFile) 165 166 if FileSize != 0: 167 ContentZipFile = PackageFile(ContentFile) 168 169 # 170 # verify MD5 signature when existed 171 # 172 if DistPkg.Header.Signature != '': 173 Md5Signature = md5(__FileHookOpen__(ContentFile, 'rb').read()) 174 if DistPkg.Header.Signature != Md5Signature.hexdigest(): 175 ContentZipFile.Close() 176 Logger.Error("InstallPkg", FILE_CHECKSUM_FAILURE, 177 ExtraData=ContentFile) 178 179 return DistPkg, ContentZipFile, DpPkgFileName, DistFile 180 181## GetPackageList 182# 183# GetPackageList 184# 185def GetPackageList(DistPkg, Dep, WorkspaceDir, Options, ContentZipFile, ModuleList, PackageList): 186 NewDict = Sdict() 187 for Guid, Version, Path in DistPkg.PackageSurfaceArea: 188 PackagePath = Path 189 Package = DistPkg.PackageSurfaceArea[Guid, Version, Path] 190 Logger.Info(ST.MSG_INSTALL_PACKAGE % Package.GetName()) 191# if Dep.CheckPackageExists(Guid, Version): 192# Logger.Info(ST.WRN_PACKAGE_EXISTED %(Guid, Version)) 193 if Options.UseGuidedPkgPath: 194 GuidedPkgPath = "%s_%s_%s" % (Package.GetName(), Guid, Version) 195 NewPackagePath = InstallNewPackage(WorkspaceDir, GuidedPkgPath, Options.CustomPath) 196 else: 197 NewPackagePath = InstallNewPackage(WorkspaceDir, PackagePath, Options.CustomPath) 198 InstallPackageContent(PackagePath, NewPackagePath, Package, ContentZipFile, Dep, WorkspaceDir, ModuleList, 199 DistPkg.Header.ReadOnly) 200 PackageList.append(Package) 201 202 NewDict[Guid, Version, Package.GetPackagePath()] = Package 203 204 # 205 # Now generate meta-data files, first generate all dec for package 206 # dec should be generated before inf, and inf should be generated after 207 # all packages installed, else hard to resolve modules' package 208 # dependency (Hard to get the location of the newly installed package) 209 # 210 for Package in PackageList: 211 FilePath = PackageToDec(Package, DistPkg.Header) 212 Md5Signature = md5(__FileHookOpen__(str(FilePath), 'rb').read()) 213 Md5Sum = Md5Signature.hexdigest() 214 if (FilePath, Md5Sum) not in Package.FileList: 215 Package.FileList.append((FilePath, Md5Sum)) 216 217 return NewDict 218 219## GetModuleList 220# 221# GetModuleList 222# 223def GetModuleList(DistPkg, Dep, WorkspaceDir, ContentZipFile, ModuleList): 224 # 225 # ModulePathList will keep track of the standalone module path that 226 # we just installed. If a new module's path in that list 227 # (only multiple INF in one directory will be so), we will 228 # install them directly. If not, we will try to create a new directory 229 # for it. 230 # 231 ModulePathList = [] 232 233 # 234 # Check module exist and install 235 # 236 Module = None 237 NewDict = Sdict() 238 for Guid, Version, Name, Path in DistPkg.ModuleSurfaceArea: 239 ModulePath = Path 240 Module = DistPkg.ModuleSurfaceArea[Guid, Version, Name, Path] 241 Logger.Info(ST.MSG_INSTALL_MODULE % Module.GetName()) 242 if Dep.CheckModuleExists(Guid, Version, Name, Path): 243 Logger.Quiet(ST.WRN_MODULE_EXISTED %Path) 244 # 245 # here check for the multiple inf share the same module path cases: 246 # they should be installed into the same directory 247 # 248 ModuleFullPath = \ 249 os.path.normpath(os.path.join(WorkspaceDir, ModulePath)) 250 if ModuleFullPath not in ModulePathList: 251 NewModulePath = InstallNewModule(WorkspaceDir, ModulePath, ModulePathList) 252 NewModuleFullPath = os.path.normpath(os.path.join(WorkspaceDir, NewModulePath)) 253 ModulePathList.append(NewModuleFullPath) 254 else: 255 NewModulePath = ModulePath 256 257 InstallModuleContent(ModulePath, NewModulePath, '', Module, ContentZipFile, WorkspaceDir, ModuleList, None, 258 DistPkg.Header.ReadOnly) 259 # 260 # Update module 261 # 262 Module.SetModulePath(Module.GetModulePath().replace(Path, NewModulePath, 1)) 263 264 NewDict[Guid, Version, Name, Module.GetModulePath()] = Module 265 266 # 267 # generate all inf for modules 268 # 269 for (Module, Package) in ModuleList: 270 CheckCNameInModuleRedefined(Module, DistPkg) 271 FilePath = ModuleToInf(Module, Package, DistPkg.Header) 272 Md5Signature = md5(__FileHookOpen__(str(FilePath), 'rb').read()) 273 Md5Sum = Md5Signature.hexdigest() 274 if Package: 275 if (FilePath, Md5Sum) not in Package.FileList: 276 Package.FileList.append((FilePath, Md5Sum)) 277 else: 278 if (FilePath, Md5Sum) not in Module.FileList: 279 Module.FileList.append((FilePath, Md5Sum)) 280 # 281 # append the module unicode files to Package FileList 282 # 283 for (FilePath, Md5Sum) in Module.FileList: 284 if str(FilePath).endswith('.uni') and Package and (FilePath, Md5Sum) not in Package.FileList: 285 Package.FileList.append((FilePath, Md5Sum)) 286 287 return NewDict 288 289## 290# Get all protocol/ppi/guid CNames and pcd name from all dependent DEC file 291# 292def GetDepProtocolPpiGuidPcdNames(DePackageObjList): 293 # 294 # [[Dec1Protocol1, Dec1Protocol2...], [Dec2Protocols...],...] 295 # 296 DependentProtocolCNames = [] 297 DependentPpiCNames = [] 298 DependentGuidCNames = [] 299 DependentPcdNames = [] 300 301 for PackageObj in DePackageObjList: 302 # 303 # Get protocol CName list from all dependent DEC file 304 # 305 ProtocolCNames = [] 306 for Protocol in PackageObj.GetProtocolList(): 307 if Protocol.GetCName() not in ProtocolCNames: 308 ProtocolCNames.append(Protocol.GetCName()) 309 310 DependentProtocolCNames.append(ProtocolCNames) 311 312 # 313 # Get Ppi CName list from all dependent DEC file 314 # 315 PpiCNames = [] 316 for Ppi in PackageObj.GetPpiList(): 317 if Ppi.GetCName() not in PpiCNames: 318 PpiCNames.append(Ppi.GetCName()) 319 320 DependentPpiCNames.append(PpiCNames) 321 322 # 323 # Get Guid CName list from all dependent DEC file 324 # 325 GuidCNames = [] 326 for Guid in PackageObj.GetGuidList(): 327 if Guid.GetCName() not in GuidCNames: 328 GuidCNames.append(Guid.GetCName()) 329 330 DependentGuidCNames.append(GuidCNames) 331 332 # 333 # Get PcdName list from all dependent DEC file 334 # 335 PcdNames = [] 336 for Pcd in PackageObj.GetPcdList(): 337 PcdName = '.'.join([Pcd.GetTokenSpaceGuidCName(), Pcd.GetCName()]) 338 if PcdName not in PcdNames: 339 PcdNames.append(PcdName) 340 341 DependentPcdNames.append(PcdNames) 342 343 344 return DependentProtocolCNames, DependentPpiCNames, DependentGuidCNames, DependentPcdNames 345 346## 347# Check if protocol CName is redefined 348# 349def CheckProtoclCNameRedefined(Module, DependentProtocolCNames): 350 for ProtocolInModule in Module.GetProtocolList(): 351 IsCNameDefined = False 352 for PackageProtocolCNames in DependentProtocolCNames: 353 if ProtocolInModule.GetCName() in PackageProtocolCNames: 354 if IsCNameDefined: 355 Logger.Error("\nUPT", FORMAT_INVALID, 356 File = Module.GetFullPath(), 357 ExtraData = \ 358 ST.ERR_INF_PARSER_ITEM_DUPLICATE_IN_DEC % ProtocolInModule.GetCName()) 359 else: 360 IsCNameDefined = True 361 362## 363# Check if Ppi CName is redefined 364# 365def CheckPpiCNameRedefined(Module, DependentPpiCNames): 366 for PpiInModule in Module.GetPpiList(): 367 IsCNameDefined = False 368 for PackagePpiCNames in DependentPpiCNames: 369 if PpiInModule.GetCName() in PackagePpiCNames: 370 if IsCNameDefined: 371 Logger.Error("\nUPT", FORMAT_INVALID, 372 File = Module.GetFullPath(), 373 ExtraData = ST.ERR_INF_PARSER_ITEM_DUPLICATE_IN_DEC % PpiInModule.GetCName()) 374 else: 375 IsCNameDefined = True 376 377## 378# Check if Guid CName is redefined 379# 380def CheckGuidCNameRedefined(Module, DependentGuidCNames): 381 for GuidInModule in Module.GetGuidList(): 382 IsCNameDefined = False 383 for PackageGuidCNames in DependentGuidCNames: 384 if GuidInModule.GetCName() in PackageGuidCNames: 385 if IsCNameDefined: 386 Logger.Error("\nUPT", FORMAT_INVALID, 387 File = Module.GetFullPath(), 388 ExtraData = \ 389 ST.ERR_INF_PARSER_ITEM_DUPLICATE_IN_DEC % GuidInModule.GetCName()) 390 else: 391 IsCNameDefined = True 392 393## 394# Check if PcdName is redefined 395# 396def CheckPcdNameRedefined(Module, DependentPcdNames): 397 PcdObjs = [] 398 if not Module.GetBinaryFileList(): 399 PcdObjs += Module.GetPcdList() 400 else: 401 Binary = Module.GetBinaryFileList()[0] 402 for AsBuild in Binary.GetAsBuiltList(): 403 PcdObjs += AsBuild.GetPatchPcdList() + AsBuild.GetPcdExList() 404 405 for PcdObj in PcdObjs: 406 PcdName = '.'.join([PcdObj.GetTokenSpaceGuidCName(), PcdObj.GetCName()]) 407 IsPcdNameDefined = False 408 for PcdNames in DependentPcdNames: 409 if PcdName in PcdNames: 410 if IsPcdNameDefined: 411 Logger.Error("\nUPT", FORMAT_INVALID, 412 File = Module.GetFullPath(), 413 ExtraData = ST.ERR_INF_PARSER_ITEM_DUPLICATE_IN_DEC % PcdName) 414 else: 415 IsPcdNameDefined = True 416 417## 418# Check if any Protocol/Ppi/Guid and Pcd name is redefined in its dependent DEC files 419# 420def CheckCNameInModuleRedefined(Module, DistPkg): 421 DePackageObjList = [] 422 # 423 # Get all dependent package objects 424 # 425 for Obj in Module.GetPackageDependencyList(): 426 Guid = Obj.GetGuid() 427 Version = Obj.GetVersion() 428 for Key in DistPkg.PackageSurfaceArea: 429 if Key[0] == Guid and Key[1] == Version: 430 if DistPkg.PackageSurfaceArea[Key] not in DePackageObjList: 431 DePackageObjList.append(DistPkg.PackageSurfaceArea[Key]) 432 433 DependentProtocolCNames, DependentPpiCNames, DependentGuidCNames, DependentPcdNames = \ 434 GetDepProtocolPpiGuidPcdNames(DePackageObjList) 435 436 CheckProtoclCNameRedefined(Module, DependentProtocolCNames) 437 CheckPpiCNameRedefined(Module, DependentPpiCNames) 438 CheckGuidCNameRedefined(Module, DependentGuidCNames) 439 CheckPcdNameRedefined(Module, DependentPcdNames) 440 441## GenToolMisc 442# 443# GenToolMisc 444# 445# 446def GenToolMisc(DistPkg, WorkspaceDir, ContentZipFile): 447 ToolObject = DistPkg.Tools 448 MiscObject = DistPkg.MiscellaneousFiles 449 DistPkg.FileList = [] 450 FileList = [] 451 ToolFileNum = 0 452 FileNum = 0 453 RootDir = WorkspaceDir 454 455 # 456 # FileList stores both tools files and misc files 457 # Misc file list must be appended to FileList *AFTER* Tools file list 458 # 459 if ToolObject: 460 FileList += ToolObject.GetFileList() 461 ToolFileNum = len(ToolObject.GetFileList()) 462 if 'EDK_TOOLS_PATH' in os.environ: 463 RootDir = os.environ['EDK_TOOLS_PATH'] 464 if MiscObject: 465 FileList += MiscObject.GetFileList() 466 for FileObject in FileList: 467 FileNum += 1 468 if FileNum > ToolFileNum: 469 # 470 # Misc files, root should be changed to WORKSPACE 471 # 472 RootDir = WorkspaceDir 473 File = ConvertPath(FileObject.GetURI()) 474 ToFile = os.path.normpath(os.path.join(RootDir, File)) 475 if os.path.exists(ToFile): 476 Logger.Info( ST.WRN_FILE_EXISTED % ToFile ) 477 # 478 # ask for user input the new file name 479 # 480 Logger.Info( ST.MSG_NEW_FILE_NAME) 481 Input = stdin.readline() 482 Input = Input.replace('\r', '').replace('\n', '') 483 OrigPath = os.path.split(ToFile)[0] 484 ToFile = os.path.normpath(os.path.join(OrigPath, Input)) 485 FromFile = os.path.join(FileObject.GetURI()) 486 Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, DistPkg.Header.ReadOnly, FileObject.GetExecutable()) 487 DistPkg.FileList.append((ToFile, Md5Sum)) 488 489## Tool entrance method 490# 491# This method mainly dispatch specific methods per the command line options. 492# If no error found, return zero value so the caller of this tool can know 493# if it's executed successfully or not. 494# 495# @param Options: command Options 496# 497def Main(Options = None): 498 try: 499 DataBase = GlobalData.gDB 500 WorkspaceDir = GlobalData.gWORKSPACE 501 if not Options.PackageFile: 502 Logger.Error("InstallPkg", OPTION_MISSING, ExtraData=ST.ERR_SPECIFY_PACKAGE) 503 504 # Get all Dist Info 505 DistInfoList = [] 506 DistPkgList = [] 507 Index = 1 508 for ToBeInstalledDist in Options.PackageFile: 509 # 510 # unzip dist.pkg file 511 # 512 DistInfoList.append(UnZipDp(WorkspaceDir, ToBeInstalledDist, Index)) 513 DistPkgList.append(DistInfoList[-1][0]) 514 Index += 1 515 516 # 517 # Add dist 518 # 519 GlobalData.gTO_BE_INSTALLED_DIST_LIST.append(DistInfoList[-1][0]) 520 521 # Check for dependency 522 Dep = DependencyRules(DataBase, DistPkgList) 523 524 for ToBeInstalledDist in DistInfoList: 525 CheckInstallDpx(Dep, ToBeInstalledDist[0], ToBeInstalledDist[2]) 526 527 # 528 # Install distribution 529 # 530 InstallDp(ToBeInstalledDist[0], ToBeInstalledDist[2], ToBeInstalledDist[1], 531 Options, Dep, WorkspaceDir, DataBase) 532 ReturnCode = 0 533 534 except FatalError as XExcept: 535 ReturnCode = XExcept.args[0] 536 if Logger.GetLevel() <= Logger.DEBUG_9: 537 Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + format_exc()) 538 539 except KeyboardInterrupt: 540 ReturnCode = ABORT_ERROR 541 if Logger.GetLevel() <= Logger.DEBUG_9: 542 Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + format_exc()) 543 544 except: 545 ReturnCode = CODE_ERROR 546 Logger.Error( 547 "\nInstallPkg", 548 CODE_ERROR, 549 ST.ERR_UNKNOWN_FATAL_INSTALL_ERR % Options.PackageFile, 550 ExtraData=ST.MSG_SEARCH_FOR_HELP % ST.MSG_EDKII_MAIL_ADDR, 551 RaiseError=False 552 ) 553 Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), 554 platform) + format_exc()) 555 finally: 556 Logger.Quiet(ST.MSG_REMOVE_TEMP_FILE_STARTED) 557 for ToBeInstalledDist in DistInfoList: 558 if ToBeInstalledDist[3]: 559 ToBeInstalledDist[3].Close() 560 if ToBeInstalledDist[1]: 561 ToBeInstalledDist[1].Close() 562 for TempDir in GlobalData.gUNPACK_DIR: 563 rmtree(TempDir) 564 GlobalData.gUNPACK_DIR = [] 565 Logger.Quiet(ST.MSG_REMOVE_TEMP_FILE_DONE) 566 if ReturnCode == 0: 567 Logger.Quiet(ST.MSG_FINISH) 568 return ReturnCode 569 570# BackupDist method 571# 572# This method will backup the Distribution file into the $(WORKSPACE)/conf/upt, and rename it 573# if there is already a same-named distribution existed. 574# 575# @param DpPkgFileName: The distribution path 576# @param Guid: The distribution Guid 577# @param Version: The distribution Version 578# @param WorkspaceDir: The workspace directory 579# @retval NewDpPkgFileName: The exact backup file name 580# 581def BackupDist(DpPkgFileName, Guid, Version, WorkspaceDir): 582 DistFileName = os.path.split(DpPkgFileName)[1] 583 DestDir = os.path.normpath(os.path.join(WorkspaceDir, GlobalData.gUPT_DIR)) 584 CreateDirectory(DestDir) 585 DestFile = os.path.normpath(os.path.join(DestDir, DistFileName)) 586 if os.path.exists(DestFile): 587 FileName, Ext = os.path.splitext(DistFileName) 588 NewFileName = FileName + '_' + Guid + '_' + Version + Ext 589 DestFile = os.path.normpath(os.path.join(DestDir, NewFileName)) 590 if os.path.exists(DestFile): 591 # 592 # ask for user input the new file name 593 # 594 Logger.Info( ST.MSG_NEW_FILE_NAME_FOR_DIST) 595 Input = stdin.readline() 596 Input = Input.replace('\r', '').replace('\n', '') 597 DestFile = os.path.normpath(os.path.join(DestDir, Input)) 598 copyfile(DpPkgFileName, DestFile) 599 NewDpPkgFileName = DestFile[DestFile.find(DestDir) + len(DestDir) + 1:] 600 return NewDpPkgFileName 601 602## CheckInstallDpx method 603# 604# check whether distribution could be installed 605# 606# @param Dep: the DependencyRules instance that used to check dependency 607# @param DistPkg: the distribution object 608# 609def CheckInstallDpx(Dep, DistPkg, DistPkgFileName): 610 # 611 # Check distribution package installed or not 612 # 613 if Dep.CheckDpExists(DistPkg.Header.GetGuid(), 614 DistPkg.Header.GetVersion()): 615 Logger.Error("InstallPkg", 616 UPT_ALREADY_INSTALLED_ERROR, 617 ST.WRN_DIST_PKG_INSTALLED % os.path.basename(DistPkgFileName)) 618 # 619 # Check distribution dependency (all module dependency should be 620 # satisfied) 621 # 622 if not Dep.CheckInstallDpDepexSatisfied(DistPkg): 623 Logger.Error("InstallPkg", UNKNOWN_ERROR, 624 ST.ERR_PACKAGE_NOT_MATCH_DEPENDENCY, 625 ExtraData=DistPkg.Header.Name) 626 627## InstallModuleContent method 628# 629# If this is standalone module, then Package should be none, 630# ModulePath should be '' 631# @param FromPath: FromPath 632# @param NewPath: NewPath 633# @param ModulePath: ModulePath 634# @param Module: Module 635# @param ContentZipFile: ContentZipFile 636# @param WorkspaceDir: WorkspaceDir 637# @param ModuleList: ModuleList 638# @param Package: Package 639# 640def InstallModuleContent(FromPath, NewPath, ModulePath, Module, ContentZipFile, 641 WorkspaceDir, ModuleList, Package = None, ReadOnly = False): 642 643 if NewPath.startswith("\\") or NewPath.startswith("/"): 644 NewPath = NewPath[1:] 645 646 if not IsValidInstallPath(NewPath): 647 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%NewPath) 648 649 NewModuleFullPath = os.path.normpath(os.path.join(WorkspaceDir, NewPath, 650 ConvertPath(ModulePath))) 651 Module.SetFullPath(os.path.normpath(os.path.join(NewModuleFullPath, 652 ConvertPath(Module.GetName()) + '.inf'))) 653 Module.FileList = [] 654 655 for MiscFile in Module.GetMiscFileList(): 656 if not MiscFile: 657 continue 658 for Item in MiscFile.GetFileList(): 659 File = Item.GetURI() 660 if File.startswith("\\") or File.startswith("/"): 661 File = File[1:] 662 663 if not IsValidInstallPath(File): 664 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%File) 665 666 FromFile = os.path.join(FromPath, ModulePath, File) 667 Executable = Item.GetExecutable() 668 ToFile = os.path.normpath(os.path.join(NewModuleFullPath, ConvertPath(File))) 669 Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly, Executable) 670 if Package and ((ToFile, Md5Sum) not in Package.FileList): 671 Package.FileList.append((ToFile, Md5Sum)) 672 elif Package: 673 continue 674 elif (ToFile, Md5Sum) not in Module.FileList: 675 Module.FileList.append((ToFile, Md5Sum)) 676 for Item in Module.GetSourceFileList(): 677 File = Item.GetSourceFile() 678 if File.startswith("\\") or File.startswith("/"): 679 File = File[1:] 680 681 if not IsValidInstallPath(File): 682 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%File) 683 684 FromFile = os.path.join(FromPath, ModulePath, File) 685 ToFile = os.path.normpath(os.path.join(NewModuleFullPath, ConvertPath(File))) 686 Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly) 687 if Package and ((ToFile, Md5Sum) not in Package.FileList): 688 Package.FileList.append((ToFile, Md5Sum)) 689 elif Package: 690 continue 691 elif (ToFile, Md5Sum) not in Module.FileList: 692 Module.FileList.append((ToFile, Md5Sum)) 693 for Item in Module.GetBinaryFileList(): 694 FileNameList = Item.GetFileNameList() 695 for FileName in FileNameList: 696 File = FileName.GetFilename() 697 if File.startswith("\\") or File.startswith("/"): 698 File = File[1:] 699 700 if not IsValidInstallPath(File): 701 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%File) 702 703 FromFile = os.path.join(FromPath, ModulePath, File) 704 ToFile = os.path.normpath(os.path.join(NewModuleFullPath, ConvertPath(File))) 705 Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly) 706 if Package and ((ToFile, Md5Sum) not in Package.FileList): 707 Package.FileList.append((ToFile, Md5Sum)) 708 elif Package: 709 continue 710 elif (ToFile, Md5Sum) not in Module.FileList: 711 Module.FileList.append((ToFile, Md5Sum)) 712 713 InstallModuleContentZipFile(ContentZipFile, FromPath, ModulePath, WorkspaceDir, NewPath, Module, Package, ReadOnly, 714 ModuleList) 715 716## InstallModuleContentZipFile 717# 718# InstallModuleContentZipFile 719# 720def InstallModuleContentZipFile(ContentZipFile, FromPath, ModulePath, WorkspaceDir, NewPath, Module, Package, ReadOnly, 721 ModuleList): 722 # 723 # Extract other files under current module path in content Zip file but not listed in the description 724 # 725 if ContentZipFile: 726 for FileName in ContentZipFile.GetZipFile().namelist(): 727 FileName = os.path.normpath(FileName) 728 CheckPath = os.path.normpath(os.path.join(FromPath, ModulePath)) 729 if FileUnderPath(FileName, CheckPath): 730 if FileName.startswith("\\") or FileName.startswith("/"): 731 FileName = FileName[1:] 732 733 if not IsValidInstallPath(FileName): 734 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName) 735 736 FromFile = FileName 737 ToFile = os.path.normpath(os.path.join(WorkspaceDir, 738 ConvertPath(FileName.replace(FromPath, NewPath, 1)))) 739 CheckList = copy.copy(Module.FileList) 740 if Package: 741 CheckList += Package.FileList 742 for Item in CheckList: 743 if Item[0] == ToFile: 744 break 745 else: 746 Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly) 747 if Package and ((ToFile, Md5Sum) not in Package.FileList): 748 Package.FileList.append((ToFile, Md5Sum)) 749 elif Package: 750 continue 751 elif (ToFile, Md5Sum) not in Module.FileList: 752 Module.FileList.append((ToFile, Md5Sum)) 753 754 ModuleList.append((Module, Package)) 755 756## FileUnderPath 757# Check whether FileName started with directory specified by CheckPath 758# 759# @param FileName: the FileName need to be checked 760# @param CheckPath: the path need to be checked against 761# @return: True or False 762# 763def FileUnderPath(FileName, CheckPath): 764 FileName = FileName.replace('\\', '/') 765 FileName = os.path.normpath(FileName) 766 CheckPath = CheckPath.replace('\\', '/') 767 CheckPath = os.path.normpath(CheckPath) 768 if FileName.startswith(CheckPath): 769 RemainingPath = os.path.normpath(FileName.replace(CheckPath, '', 1)) 770 while RemainingPath.startswith('\\') or RemainingPath.startswith('/'): 771 RemainingPath = RemainingPath[1:] 772 if FileName == os.path.normpath(os.path.join(CheckPath, RemainingPath)): 773 return True 774 775 return False 776 777## InstallFile 778# Extract File from Zipfile, set file attribute, and return the Md5Sum 779# 780# @return: True or False 781# 782def InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly, Executable=False): 783 if os.path.exists(os.path.normpath(ToFile)): 784 pass 785 else: 786 if not ContentZipFile or not ContentZipFile.UnpackFile(FromFile, ToFile): 787 Logger.Error("UPT", FILE_NOT_FOUND, ST.ERR_INSTALL_FILE_FROM_EMPTY_CONTENT % FromFile) 788 789 if ReadOnly: 790 if not Executable: 791 chmod(ToFile, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH) 792 else: 793 chmod(ToFile, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH) 794 elif Executable: 795 chmod(ToFile, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IWUSR | stat.S_IWGRP | 796 stat.S_IWOTH | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH) 797 else: 798 chmod(ToFile, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH) 799 800 Md5Signature = md5(__FileHookOpen__(str(ToFile), 'rb').read()) 801 Md5Sum = Md5Signature.hexdigest() 802 803 return Md5Sum 804 805## InstallPackageContent method 806# 807# @param FromPath: FromPath 808# @param ToPath: ToPath 809# @param Package: Package 810# @param ContentZipFile: ContentZipFile 811# @param Dep: Dep 812# @param WorkspaceDir: WorkspaceDir 813# @param ModuleList: ModuleList 814# 815def InstallPackageContent(FromPath, ToPath, Package, ContentZipFile, Dep, 816 WorkspaceDir, ModuleList, ReadOnly = False): 817 if Dep: 818 pass 819 Package.FileList = [] 820 821 if ToPath.startswith("\\") or ToPath.startswith("/"): 822 ToPath = ToPath[1:] 823 824 if not IsValidInstallPath(ToPath): 825 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%ToPath) 826 827 if FromPath.startswith("\\") or FromPath.startswith("/"): 828 FromPath = FromPath[1:] 829 830 if not IsValidInstallPath(FromPath): 831 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FromPath) 832 833 PackageFullPath = os.path.normpath(os.path.join(WorkspaceDir, ToPath)) 834 for MiscFile in Package.GetMiscFileList(): 835 for Item in MiscFile.GetFileList(): 836 FileName = Item.GetURI() 837 if FileName.startswith("\\") or FileName.startswith("/"): 838 FileName = FileName[1:] 839 840 if not IsValidInstallPath(FileName): 841 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName) 842 843 FromFile = os.path.join(FromPath, FileName) 844 Executable = Item.GetExecutable() 845 ToFile = (os.path.join(PackageFullPath, ConvertPath(FileName))) 846 Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly, Executable) 847 if (ToFile, Md5Sum) not in Package.FileList: 848 Package.FileList.append((ToFile, Md5Sum)) 849 PackageIncludeArchList = [] 850 for Item in Package.GetPackageIncludeFileList(): 851 FileName = Item.GetFilePath() 852 if FileName.startswith("\\") or FileName.startswith("/"): 853 FileName = FileName[1:] 854 855 if not IsValidInstallPath(FileName): 856 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName) 857 858 FromFile = os.path.join(FromPath, FileName) 859 ToFile = os.path.normpath(os.path.join(PackageFullPath, ConvertPath(FileName))) 860 RetFile = ContentZipFile.UnpackFile(FromFile, ToFile) 861 if RetFile == '': 862 # 863 # a non-exist path in Zipfile will return '', which means an include directory in our case 864 # save the information for later DEC creation usage and also create the directory 865 # 866 PackageIncludeArchList.append([Item.GetFilePath(), Item.GetSupArchList()]) 867 CreateDirectory(ToFile) 868 continue 869 if ReadOnly: 870 chmod(ToFile, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH) 871 else: 872 chmod(ToFile, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH|stat.S_IWUSR|stat.S_IWGRP|stat.S_IWOTH) 873 Md5Signature = md5(__FileHookOpen__(str(ToFile), 'rb').read()) 874 Md5Sum = Md5Signature.hexdigest() 875 if (ToFile, Md5Sum) not in Package.FileList: 876 Package.FileList.append((ToFile, Md5Sum)) 877 Package.SetIncludeArchList(PackageIncludeArchList) 878 879 for Item in Package.GetStandardIncludeFileList(): 880 FileName = Item.GetFilePath() 881 if FileName.startswith("\\") or FileName.startswith("/"): 882 FileName = FileName[1:] 883 884 if not IsValidInstallPath(FileName): 885 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName) 886 887 FromFile = os.path.join(FromPath, FileName) 888 ToFile = os.path.normpath(os.path.join(PackageFullPath, ConvertPath(FileName))) 889 Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly) 890 if (ToFile, Md5Sum) not in Package.FileList: 891 Package.FileList.append((ToFile, Md5Sum)) 892 893 # 894 # Update package 895 # 896 Package.SetPackagePath(Package.GetPackagePath().replace(FromPath, 897 ToPath, 1)) 898 Package.SetFullPath(os.path.normpath(os.path.join(PackageFullPath, 899 ConvertPath(Package.GetName()) + '.dec'))) 900 901 # 902 # Install files in module 903 # 904 Module = None 905 ModuleDict = Package.GetModuleDict() 906 for ModuleGuid, ModuleVersion, ModuleName, ModulePath in ModuleDict: 907 Module = ModuleDict[ModuleGuid, ModuleVersion, ModuleName, ModulePath] 908 InstallModuleContent(FromPath, ToPath, ModulePath, Module, 909 ContentZipFile, WorkspaceDir, ModuleList, Package, ReadOnly) 910 911## GetDPFile method 912# 913# @param ZipFile: A ZipFile 914# 915def GetDPFile(ZipFile): 916 ContentFile = '' 917 DescFile = '' 918 for FileName in ZipFile.namelist(): 919 if FileName.endswith('.content'): 920 if not ContentFile: 921 ContentFile = FileName 922 continue 923 elif FileName.endswith('.pkg'): 924 if not DescFile: 925 DescFile = FileName 926 continue 927 else: 928 continue 929 930 Logger.Error("PackagingTool", FILE_TYPE_MISMATCH, 931 ExtraData=ST.ERR_DIST_FILE_TOOMANY) 932 if not DescFile or not ContentFile: 933 Logger.Error("PackagingTool", FILE_UNKNOWN_ERROR, 934 ExtraData=ST.ERR_DIST_FILE_TOOFEW) 935 return DescFile, ContentFile 936 937## InstallDp method 938# 939# Install the distribution to current workspace 940# 941def InstallDp(DistPkg, DpPkgFileName, ContentZipFile, Options, Dep, WorkspaceDir, DataBase): 942 # 943 # PackageList, ModuleList record the information for the meta-data 944 # files that need to be generated later 945 # 946 PackageList = [] 947 ModuleList = [] 948 DistPkg.PackageSurfaceArea = GetPackageList(DistPkg, Dep, WorkspaceDir, Options, 949 ContentZipFile, ModuleList, PackageList) 950 951 DistPkg.ModuleSurfaceArea = GetModuleList(DistPkg, Dep, WorkspaceDir, ContentZipFile, ModuleList) 952 953 GenToolMisc(DistPkg, WorkspaceDir, ContentZipFile) 954 955 # 956 # copy "Distribution File" to directory $(WORKSPACE)/conf/upt 957 # 958 DistFileName = os.path.split(DpPkgFileName)[1] 959 NewDpPkgFileName = BackupDist(DpPkgFileName, DistPkg.Header.GetGuid(), DistPkg.Header.GetVersion(), WorkspaceDir) 960 961 # 962 # update database 963 # 964 Logger.Quiet(ST.MSG_UPDATE_PACKAGE_DATABASE) 965 DataBase.AddDPObject(DistPkg, NewDpPkgFileName, DistFileName, 966 DistPkg.Header.RePackage) 967 968