diff options
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/RmPkg.py')
-rwxr-xr-x | src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/RmPkg.py | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/RmPkg.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/RmPkg.py new file mode 100755 index 00000000..98e0fcd6 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/RmPkg.py @@ -0,0 +1,270 @@ +## @file +# Install distribution package. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +RmPkg +''' + +## +# Import Modules +# +import os.path +from stat import S_IWUSR +from traceback import format_exc +from platform import python_version +from hashlib import md5 +from sys import stdin +from sys import platform + +from Core.DependencyRules import DependencyRules +from Library import GlobalData +from Logger import StringTable as ST +import Logger.Log as Logger +from Logger.ToolError import OPTION_MISSING +from Logger.ToolError import UNKNOWN_ERROR +from Logger.ToolError import ABORT_ERROR +from Logger.ToolError import CODE_ERROR +from Logger.ToolError import FatalError + + +## CheckDpDepex +# +# Check if the Depex is satisfied +# @param Dep: Dep +# @param Guid: Guid of Dp +# @param Version: Version of Dp +# @param WorkspaceDir: Workspace Dir +# +def CheckDpDepex(Dep, Guid, Version, WorkspaceDir): + (Removable, DependModuleList) = Dep.CheckDpDepexForRemove(Guid, Version) + if not Removable: + Logger.Info(ST.MSG_CONFIRM_REMOVE) + Logger.Info(ST.MSG_USER_DELETE_OP) + Input = stdin.readline() + Input = Input.replace('\r', '').replace('\n', '') + if Input.upper() != 'Y': + Logger.Error("RmPkg", UNKNOWN_ERROR, ST.ERR_USER_INTERRUPT) + return 1 + else: + # + # report list of modules that are not valid due to force + # remove, + # also generate a log file for reference + # + Logger.Info(ST.MSG_INVALID_MODULE_INTRODUCED) + LogFilePath = os.path.normpath(os.path.join(WorkspaceDir, GlobalData.gINVALID_MODULE_FILE)) + Logger.Info(ST.MSG_CHECK_LOG_FILE % LogFilePath) + try: + LogFile = open(LogFilePath, 'w') + try: + for ModulePath in DependModuleList: + LogFile.write("%s\n"%ModulePath) + Logger.Info(ModulePath) + except IOError: + Logger.Warn("\nRmPkg", ST.ERR_FILE_WRITE_FAILURE, + File=LogFilePath) + except IOError: + Logger.Warn("\nRmPkg", ST.ERR_FILE_OPEN_FAILURE, + File=LogFilePath) + finally: + LogFile.close() + +## Remove Path +# +# removing readonly file on windows will get "Access is denied" +# error, so before removing, change the mode to be writeable +# +# @param Path: The Path to be removed +# +def RemovePath(Path): + Logger.Info(ST.MSG_REMOVE_FILE % Path) + if not os.access(Path, os.W_OK): + os.chmod(Path, S_IWUSR) + os.remove(Path) + try: + os.removedirs(os.path.split(Path)[0]) + except OSError: + pass +## GetCurrentFileList +# +# @param DataBase: DataBase of UPT +# @param Guid: Guid of Dp +# @param Version: Version of Dp +# @param WorkspaceDir: Workspace Dir +# +def GetCurrentFileList(DataBase, Guid, Version, WorkspaceDir): + NewFileList = [] + for Dir in DataBase.GetDpInstallDirList(Guid, Version): + RootDir = os.path.normpath(os.path.join(WorkspaceDir, Dir)) + for Root, Dirs, Files in os.walk(RootDir): + Logger.Debug(0, Dirs) + for File in Files: + FilePath = os.path.join(Root, File) + if FilePath not in NewFileList: + NewFileList.append(FilePath) + return NewFileList + + +## Tool entrance method +# +# This method mainly dispatch specific methods per the command line options. +# If no error found, return zero value so the caller of this tool can know +# if it's executed successfully or not. +# +# @param Options: command option +# +def Main(Options = None): + + try: + DataBase = GlobalData.gDB + if not Options.DistributionFile: + Logger.Error("RmPkg", + OPTION_MISSING, + ExtraData=ST.ERR_SPECIFY_PACKAGE) + WorkspaceDir = GlobalData.gWORKSPACE + # + # Prepare check dependency + # + Dep = DependencyRules(DataBase) + + # + # Get the Dp information + # + StoredDistFile, Guid, Version = GetInstalledDpInfo(Options.DistributionFile, Dep, DataBase, WorkspaceDir) + + # + # Check Dp depex + # + CheckDpDepex(Dep, Guid, Version, WorkspaceDir) + + # + # remove distribution + # + RemoveDist(Guid, Version, StoredDistFile, DataBase, WorkspaceDir, Options.Yes) + + Logger.Quiet(ST.MSG_FINISH) + + ReturnCode = 0 + + except FatalError as XExcept: + ReturnCode = XExcept.args[0] + if Logger.GetLevel() <= Logger.DEBUG_9: + Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + \ + format_exc()) + except KeyboardInterrupt: + ReturnCode = ABORT_ERROR + if Logger.GetLevel() <= Logger.DEBUG_9: + Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + \ + format_exc()) + except: + Logger.Error( + "\nRmPkg", + CODE_ERROR, + ST.ERR_UNKNOWN_FATAL_REMOVING_ERR, + ExtraData=ST.MSG_SEARCH_FOR_HELP % ST.MSG_EDKII_MAIL_ADDR, + RaiseError=False + ) + Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + \ + format_exc()) + ReturnCode = CODE_ERROR + return ReturnCode + +## GetInstalledDpInfo method +# +# Get the installed distribution information +# +# @param DistributionFile: the name of the distribution +# @param Dep: the instance of DependencyRules +# @param DataBase: the internal database +# @param WorkspaceDir: work space directory +# @retval StoredDistFile: the distribution file that backed up +# @retval Guid: the Guid of the distribution +# @retval Version: the Version of distribution +# +def GetInstalledDpInfo(DistributionFile, Dep, DataBase, WorkspaceDir): + (Guid, Version, NewDpFileName) = DataBase.GetDpByName(os.path.split(DistributionFile)[1]) + if not Guid: + Logger.Error("RmPkg", UNKNOWN_ERROR, ST.ERR_PACKAGE_NOT_INSTALLED % DistributionFile) + + # + # Check Dp existing + # + if not Dep.CheckDpExists(Guid, Version): + Logger.Error("RmPkg", UNKNOWN_ERROR, ST.ERR_DISTRIBUTION_NOT_INSTALLED) + # + # Check for Distribution files existence in /conf/upt, if not exist, + # Warn user and go on. + # + StoredDistFile = os.path.normpath(os.path.join(WorkspaceDir, GlobalData.gUPT_DIR, NewDpFileName)) + if not os.path.isfile(StoredDistFile): + Logger.Warn("RmPkg", ST.WRN_DIST_NOT_FOUND%StoredDistFile) + StoredDistFile = None + + return StoredDistFile, Guid, Version + +## RemoveDist method +# +# remove a distribution +# +# @param Guid: the Guid of the distribution +# @param Version: the Version of distribution +# @param StoredDistFile: the distribution file that backed up +# @param DataBase: the internal database +# @param WorkspaceDir: work space directory +# @param ForceRemove: whether user want to remove file even it is modified +# +def RemoveDist(Guid, Version, StoredDistFile, DataBase, WorkspaceDir, ForceRemove): + # + # Get Current File List + # + NewFileList = GetCurrentFileList(DataBase, Guid, Version, WorkspaceDir) + + # + # Remove all files + # + MissingFileList = [] + for (Path, Md5Sum) in DataBase.GetDpFileList(Guid, Version): + if os.path.isfile(Path): + if Path in NewFileList: + NewFileList.remove(Path) + if not ForceRemove: + # + # check whether modified by users + # + Md5Signature = md5(open(str(Path), 'rb').read()) + if Md5Sum != Md5Signature.hexdigest(): + Logger.Info(ST.MSG_CONFIRM_REMOVE2 % Path) + Input = stdin.readline() + Input = Input.replace('\r', '').replace('\n', '') + if Input.upper() != 'Y': + continue + RemovePath(Path) + else: + MissingFileList.append(Path) + + for Path in NewFileList: + if os.path.isfile(Path): + if (not ForceRemove) and (not os.path.split(Path)[1].startswith('.')): + Logger.Info(ST.MSG_CONFIRM_REMOVE3 % Path) + Input = stdin.readline() + Input = Input.replace('\r', '').replace('\n', '') + if Input.upper() != 'Y': + continue + RemovePath(Path) + + # + # Remove distribution files in /Conf/.upt + # + if StoredDistFile is not None: + os.remove(StoredDistFile) + + # + # update database + # + Logger.Quiet(ST.MSG_UPDATE_PACKAGE_DATABASE) + DataBase.RemoveDpObj(Guid, Version) |