]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/PackagingTool/RmPkg.py
Fixed memory leak and buffer overrun for string op-code.
[mirror_edk2.git] / BaseTools / Source / Python / PackagingTool / RmPkg.py
1 ## @file
2 # Install distribution package.
3 #
4 # Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
9 #
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 #
13
14 ##
15 # Import Modules
16 #
17 import os
18 import sys
19 import traceback
20 import platform
21 from optparse import OptionParser
22
23 import Common.EdkLogger as EdkLogger
24 from Common.BuildToolError import *
25 from Common.Misc import *
26 from Common.XmlParser import *
27
28 from IpiDb import *
29 from DependencyRules import *
30
31 # Version and Copyright
32 VersionNumber = "0.1"
33 __version__ = "%prog Version " + VersionNumber
34 __copyright__ = "Copyright (c) 2008, Intel Corporation All rights reserved."
35
36 ## Check environment variables
37 #
38 # Check environment variables that must be set for build. Currently they are
39 #
40 # WORKSPACE The directory all packages/platforms start from
41 # EDK_TOOLS_PATH The directory contains all tools needed by the build
42 # PATH $(EDK_TOOLS_PATH)/Bin/<sys> must be set in PATH
43 #
44 # If any of above environment variable is not set or has error, the build
45 # will be broken.
46 #
47 def CheckEnvVariable():
48 # check WORKSPACE
49 if "WORKSPACE" not in os.environ:
50 EdkLogger.error("RmPkg", ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found",
51 ExtraData="WORKSPACE")
52
53 WorkspaceDir = os.path.normpath(os.environ["WORKSPACE"])
54 if not os.path.exists(WorkspaceDir):
55 EdkLogger.error("RmPkg", FILE_NOT_FOUND, "WORKSPACE doesn't exist", ExtraData="%s" % WorkspaceDir)
56 elif ' ' in WorkspaceDir:
57 EdkLogger.error("RmPkg", FORMAT_NOT_SUPPORTED, "No space is allowed in WORKSPACE path",
58 ExtraData=WorkspaceDir)
59 os.environ["WORKSPACE"] = WorkspaceDir
60
61 ## Parse command line options
62 #
63 # Using standard Python module optparse to parse command line option of this tool.
64 #
65 # @retval Opt A optparse.Values object containing the parsed options
66 # @retval Args Target of build command
67 #
68 def MyOptionParser():
69 UsageString = "%prog -g <guid> -n <version> [-y] [-q | -v] [-h]"
70
71 Parser = OptionParser(description=__copyright__,version=__version__,prog="RmPkg",usage=UsageString)
72
73 Parser.add_option("-?", action="help", help="show this help message and exit")
74
75 # Parser.add_option("-f", "--force", action="store_true", type=None, dest="ForceRemove",
76 # help="Force creation - overwrite existing one.")
77
78 Parser.add_option("-y", "--yes", action="store_true", dest="Yes",
79 help="Not asking for confirmation when deleting files.")
80
81 Parser.add_option("-n", "--package-version", action="store", type="string", dest="PackageVersion",
82 help="The version of distribution package to be removed.")
83
84 Parser.add_option("-g", "--package-guid", action="store", type="string", dest="PackageGuid",
85 help="The GUID of distribution package to be removed.")
86
87 Parser.add_option("-q", "--quiet", action="store_const", dest="LogLevel", const=EdkLogger.QUIET,
88 help="Disable all messages except FATAL ERRORS.")
89
90 Parser.add_option("-v", "--verbose", action="store_const", dest="LogLevel", const=EdkLogger.VERBOSE,
91 help="Turn on verbose output")
92
93 Parser.add_option("-d", "--debug", action="store", type="int", dest="LogLevel",
94 help="Enable debug messages at specified level.")
95
96 Parser.set_defaults(LogLevel=EdkLogger.INFO)
97
98 (Opt, Args)=Parser.parse_args()
99
100 return Opt
101
102 ## Remove all empty dirs under the path
103 def RemoveEmptyDirs(Path):
104 # Remove all sub dirs
105 for Root, Dirs, Files in os.walk(Path):
106 for Dir in Dirs:
107 FullPath = os.path.normpath(os.path.join(Root, Dir))
108 if os.path.isdir(FullPath):
109 if os.listdir(FullPath) == []:
110 os.rmdir(FullPath)
111 else:
112 RemoveEmptyDirs(FullPath)
113 # Remove itself
114 if os.path.isdir(Path) and os.listdir(Path) == []:
115 os.rmdir(Path)
116
117
118 ## Tool entrance method
119 #
120 # This method mainly dispatch specific methods per the command line options.
121 # If no error found, return zero value so the caller of this tool can know
122 # if it's executed successfully or not.
123 #
124 # @retval 0 Tool was successful
125 # @retval 1 Tool failed
126 #
127 def Main():
128 EdkLogger.Initialize()
129 Options = MyOptionParser()
130 try:
131 if not Options.PackageGuid and not Options.PackageVersion:
132 EdkLogger.error("RmPkg", OPTION_MISSING, ExtraData="The GUID and Version of distribution package must be specified")
133
134 if Options.LogLevel < EdkLogger.DEBUG_9:
135 EdkLogger.SetLevel(Options.LogLevel + 1)
136 else:
137 EdkLogger.SetLevel(Options.LogLevel)
138
139 CheckEnvVariable()
140 WorkspaceDir = os.environ["WORKSPACE"]
141
142 # Prepare check dependency
143 Db = IpiDatabase(os.path.normpath(os.path.join(WorkspaceDir, "Conf/DistributionPackageDatabase.db")))
144 Db.InitDatabase()
145 Dep = DependencyRules(Db)
146
147 Guid = Options.PackageGuid
148 Version = Options.PackageVersion
149
150 # Check Dp existing
151 if not Dep.CheckDpExists(Guid, Version):
152 EdkLogger.error("RmPkg", UNKNOWN_ERROR, "This distribution package are not installed!")
153
154 # Check Dp depex
155 if not Dep.CheckDpDepexForRemove(Guid, Version):
156 print "Some packages/modules are depending on this distribution package, do you really want to remove it?"
157 print "Press Y to delete all files or press other keys to quit:"
158 Input = Input = sys.stdin.readline()
159 Input = Input.replace('\r', '').replace('\n', '')
160 if Input.upper() != 'Y':
161 EdkLogger.error("RmPkg", UNKNOWN_ERROR, "User interrupt")
162
163 # Remove all files
164 if not Options.Yes:
165 print "All files of the distribution package will be removed, do you want to continue?"
166 print "Press Y to remove all files or press other keys to quit:"
167 Input = Input = sys.stdin.readline()
168 Input = Input.replace('\r', '').replace('\n', '')
169 if Input.upper() != 'Y':
170 EdkLogger.error("RmPkg", UNKNOWN_ERROR, "User interrupt")
171
172 # Remove all files
173 MissingFileList = []
174 for Item in Db.GetDpFileList(Guid, Version):
175 if os.path.isfile(Item):
176 print "Removing file [%s] ..." % Item
177 os.remove(Item)
178 else:
179 MissingFileList.append(Item)
180
181 # Remove all empty dirs of package
182 for Item in Db.GetPackageListFromDp(Guid, Version):
183 Dir = os.path.dirname(Item[2])
184 RemoveEmptyDirs(Dir)
185
186 # Remove all empty dirs of module
187 for Item in Db.GetStandaloneModuleInstallPathListFromDp(Guid, Version):
188 Dir = os.path.dirname(Item)
189 RemoveEmptyDirs(Dir)
190
191 # update database
192 EdkLogger.quiet("Update Distribution Package Database ...")
193 Db.RemoveDpObj(Guid, Version)
194 EdkLogger.quiet("DONE")
195
196 except FatalError, X:
197 if Options and Options.LogLevel < EdkLogger.DEBUG_9:
198 EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())
199 ReturnCode = X.args[0]
200 except KeyboardInterrupt:
201 ReturnCode = ABORT_ERROR
202 if Options and Options.LogLevel < EdkLogger.DEBUG_9:
203 EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())
204 except:
205 EdkLogger.error(
206 "\nRmPkg",
207 CODE_ERROR,
208 "Unknown fatal error when removing package",
209 ExtraData="\n(Please send email to edk2-buildtools-devel@lists.sourceforge.net for help, attaching following call stack trace!)\n",
210 RaiseError=False
211 )
212 EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())
213 ReturnCode = CODE_ERROR
214 finally:
215 Progressor.Abort()
216
217 if __name__ == '__main__':
218 sys.exit(Main())