1## @file 2# 3# PackageFile class represents the zip file of a distribution package. 4# 5# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR> 6# 7# SPDX-License-Identifier: BSD-2-Clause-Patent 8# 9 10''' 11PackageFile 12''' 13 14## 15# Import Modules 16# 17import os.path 18import zipfile 19import tempfile 20import platform 21 22from Logger.ToolError import FILE_OPEN_FAILURE 23from Logger.ToolError import FILE_CHECKSUM_FAILURE 24from Logger.ToolError import FILE_NOT_FOUND 25from Logger.ToolError import FILE_DECOMPRESS_FAILURE 26from Logger.ToolError import FILE_UNKNOWN_ERROR 27from Logger.ToolError import FILE_WRITE_FAILURE 28from Logger.ToolError import FILE_COMPRESS_FAILURE 29import Logger.Log as Logger 30from Logger import StringTable as ST 31from Library.Misc import CreateDirectory 32from Library.Misc import RemoveDirectory 33from Core.FileHook import __FileHookOpen__ 34from Common.MultipleWorkspace import MultipleWorkspace as mws 35 36 37class PackageFile: 38 def __init__(self, FileName, Mode="r"): 39 self._FileName = FileName 40 if Mode not in ["r", "w", "a"]: 41 Mode = "r" 42 try: 43 self._ZipFile = zipfile.ZipFile(FileName, Mode, \ 44 zipfile.ZIP_DEFLATED) 45 self._Files = {} 46 for Filename in self._ZipFile.namelist(): 47 self._Files[os.path.normpath(Filename)] = Filename 48 except BaseException as Xstr: 49 Logger.Error("PackagingTool", FILE_OPEN_FAILURE, 50 ExtraData="%s (%s)" % (FileName, str(Xstr))) 51 52 BadFile = self._ZipFile.testzip() 53 if BadFile is not None: 54 Logger.Error("PackagingTool", FILE_CHECKSUM_FAILURE, 55 ExtraData="[%s] in %s" % (BadFile, FileName)) 56 57 def GetZipFile(self): 58 return self._ZipFile 59 60 ## Get file name 61 # 62 def __str__(self): 63 return self._FileName 64 65 ## Extract the file 66 # 67 # @param To: the destination file 68 # 69 def Unpack(self, ToDest): 70 for FileN in self._ZipFile.namelist(): 71 ToFile = os.path.normpath(os.path.join(ToDest, FileN)) 72 Msg = "%s -> %s" % (FileN, ToFile) 73 Logger.Info(Msg) 74 self.Extract(FileN, ToFile) 75 76 ## Extract the file 77 # 78 # @param File: the extracted file 79 # @param ToFile: the destination file 80 # 81 def UnpackFile(self, File, ToFile): 82 File = File.replace('\\', '/') 83 if File in self._ZipFile.namelist(): 84 Msg = "%s -> %s" % (File, ToFile) 85 Logger.Info(Msg) 86 self.Extract(File, ToFile) 87 return ToFile 88 89 return '' 90 91 ## Extract the file 92 # 93 # @param Which: the source path 94 # @param ToDest: the destination path 95 # 96 def Extract(self, Which, ToDest): 97 Which = os.path.normpath(Which) 98 if Which not in self._Files: 99 Logger.Error("PackagingTool", FILE_NOT_FOUND, 100 ExtraData="[%s] in %s" % (Which, self._FileName)) 101 try: 102 FileContent = self._ZipFile.read(self._Files[Which]) 103 except BaseException as Xstr: 104 Logger.Error("PackagingTool", FILE_DECOMPRESS_FAILURE, 105 ExtraData="[%s] in %s (%s)" % (Which, \ 106 self._FileName, \ 107 str(Xstr))) 108 try: 109 CreateDirectory(os.path.dirname(ToDest)) 110 if os.path.exists(ToDest) and not os.access(ToDest, os.W_OK): 111 Logger.Warn("PackagingTool", \ 112 ST.WRN_FILE_NOT_OVERWRITTEN % ToDest) 113 return 114 else: 115 ToFile = __FileHookOpen__(ToDest, 'wb') 116 except BaseException as Xstr: 117 Logger.Error("PackagingTool", FILE_OPEN_FAILURE, 118 ExtraData="%s (%s)" % (ToDest, str(Xstr))) 119 120 try: 121 ToFile.write(FileContent) 122 ToFile.close() 123 except BaseException as Xstr: 124 Logger.Error("PackagingTool", FILE_WRITE_FAILURE, 125 ExtraData="%s (%s)" % (ToDest, str(Xstr))) 126 127 ## Remove the file 128 # 129 # @param Files: the removed files 130 # 131 def Remove(self, Files): 132 TmpDir = os.path.join(tempfile.gettempdir(), ".packaging") 133 if os.path.exists(TmpDir): 134 RemoveDirectory(TmpDir, True) 135 136 os.mkdir(TmpDir) 137 self.Unpack(TmpDir) 138 for SinF in Files: 139 SinF = os.path.normpath(SinF) 140 if SinF not in self._Files: 141 Logger.Error("PackagingTool", FILE_NOT_FOUND, 142 ExtraData="%s is not in %s!" % \ 143 (SinF, self._FileName)) 144 self._Files.pop(SinF) 145 self._ZipFile.close() 146 147 self._ZipFile = zipfile.ZipFile(self._FileName, "w", \ 148 zipfile.ZIP_DEFLATED) 149 Cwd = os.getcwd() 150 os.chdir(TmpDir) 151 self.PackFiles(self._Files) 152 os.chdir(Cwd) 153 RemoveDirectory(TmpDir, True) 154 155 ## Pack the files under Top directory, the directory shown in the zipFile start from BaseDir, 156 # BaseDir should be the parent directory of the Top directory, for example, 157 # Pack(Workspace\Dir1, Workspace) will pack files under Dir1, and the path in the zipfile will 158 # start from Workspace 159 # 160 # @param Top: the top directory 161 # @param BaseDir: the base directory 162 # 163 def Pack(self, Top, BaseDir): 164 if not os.path.isdir(Top): 165 Logger.Error("PackagingTool", FILE_UNKNOWN_ERROR, \ 166 "%s is not a directory!" %Top) 167 168 FilesToPack = [] 169 Cwd = os.getcwd() 170 os.chdir(BaseDir) 171 RelaDir = Top[Top.upper().find(BaseDir.upper()).\ 172 join(len(BaseDir).join(1)):] 173 174 for Root, Dirs, Files in os.walk(RelaDir): 175 if 'CVS' in Dirs: 176 Dirs.remove('CVS') 177 if '.svn' in Dirs: 178 Dirs.remove('.svn') 179 180 for Dir in Dirs: 181 if Dir.startswith('.'): 182 Dirs.remove(Dir) 183 for File1 in Files: 184 if File1.startswith('.'): 185 continue 186 ExtName = os.path.splitext(File1)[1] 187 # 188 # skip '.dec', '.inf', '.dsc', '.fdf' files 189 # 190 if ExtName.lower() in ['.dec', '.inf', '.dsc', '.fdf']: 191 continue 192 FilesToPack.append(os.path.join(Root, File1)) 193 self.PackFiles(FilesToPack) 194 os.chdir(Cwd) 195 196 ## Pack the file 197 # 198 # @param Files: the files to pack 199 # 200 def PackFiles(self, Files): 201 for File in Files: 202 Cwd = os.getcwd() 203 os.chdir(mws.getWs(mws.WORKSPACE, File)) 204 self.PackFile(File) 205 os.chdir(Cwd) 206 207 ## Pack the file 208 # 209 # @param File: the files to pack 210 # @param ArcName: the Arc Name 211 # 212 def PackFile(self, File, ArcName=None): 213 try: 214 # 215 # avoid packing same file multiple times 216 # 217 if platform.system() != 'Windows': 218 File = File.replace('\\', '/') 219 ZipedFilesNameList = self._ZipFile.namelist() 220 for ZipedFile in ZipedFilesNameList: 221 if File == os.path.normpath(ZipedFile): 222 return 223 Logger.Info("packing ..." + File) 224 self._ZipFile.write(File, ArcName) 225 except BaseException as Xstr: 226 Logger.Error("PackagingTool", FILE_COMPRESS_FAILURE, 227 ExtraData="%s (%s)" % (File, str(Xstr))) 228 229 ## Write data to the packed file 230 # 231 # @param Data: data to write 232 # @param ArcName: the Arc Name 233 # 234 def PackData(self, Data, ArcName): 235 try: 236 if os.path.splitext(ArcName)[1].lower() == '.pkg': 237 Data = Data.encode('utf_8') 238 self._ZipFile.writestr(ArcName, Data) 239 except BaseException as Xstr: 240 Logger.Error("PackagingTool", FILE_COMPRESS_FAILURE, 241 ExtraData="%s (%s)" % (ArcName, str(Xstr))) 242 243 ## Close file 244 # 245 # 246 def Close(self): 247 self._ZipFile.close() 248 249 250 251