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