]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/UPT/Core/FileHook.py
BaseTools: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / BaseTools / Source / Python / UPT / Core / FileHook.py
CommitLineData
421ccda3
HC
1## @file\r
2# This file hooks file and directory creation and removal\r
3#\r
f7496d71 4# Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>\r
421ccda3 5#\r
2e351cbe 6# SPDX-License-Identifier: BSD-2-Clause-Patent\r
421ccda3
HC
7#\r
8\r
9'''\r
10File hook\r
11'''\r
12\r
13import os\r
14import stat\r
15import time\r
16import zipfile\r
17from time import sleep\r
18from Library import GlobalData\r
19\r
20__built_in_remove__ = os.remove\r
21__built_in_mkdir__ = os.mkdir\r
22__built_in_rmdir__ = os.rmdir\r
23__built_in_chmod__ = os.chmod\r
24__built_in_open__ = open\r
25\r
26_RMFILE = 0\r
27_MKFILE = 1\r
28_RMDIR = 2\r
29_MKDIR = 3\r
30_CHMOD = 4\r
31\r
32gBACKUPFILE = 'file.backup'\r
33gEXCEPTION_LIST = ['Conf'+os.sep+'DistributionPackageDatabase.db', '.tmp', gBACKUPFILE]\r
34\r
35class _PathInfo:\r
36 def __init__(self, action, path, mode=-1):\r
37 self.action = action\r
38 self.path = path\r
39 self.mode = mode\r
40\r
41class RecoverMgr:\r
42 def __init__(self, workspace):\r
43 self.rlist = []\r
44 self.zip = None\r
45 self.workspace = os.path.normpath(workspace)\r
46 self.backupfile = gBACKUPFILE\r
47 self.zipfile = os.path.join(self.workspace, gBACKUPFILE)\r
48\r
49 def _createzip(self):\r
50 if self.zip:\r
51 return\r
52 self.zip = zipfile.ZipFile(self.zipfile, 'w', zipfile.ZIP_DEFLATED)\r
53\r
54 def _save(self, tmp, path):\r
55 if not self._tryhook(path):\r
56 return\r
57 self.rlist.append(_PathInfo(tmp, path))\r
58\r
59 def bkrmfile(self, path):\r
60 arc = self._tryhook(path)\r
61 if arc and os.path.isfile(path):\r
62 self._createzip()\r
1ccc4d89 63 self.zip.write(path, arc.encode('utf_8'))\r
421ccda3
HC
64 sta = os.stat(path)\r
65 oldmode = stat.S_IMODE(sta.st_mode)\r
66 self.rlist.append(_PathInfo(_CHMOD, path, oldmode))\r
67 self.rlist.append(_PathInfo(_RMFILE, path))\r
68 __built_in_remove__(path)\r
69\r
70 def bkmkfile(self, path, mode, bufsize):\r
71 if not os.path.exists(path):\r
72 self._save(_MKFILE, path)\r
73 return __built_in_open__(path, mode, bufsize)\r
74\r
75 def bkrmdir(self, path):\r
76 if os.path.exists(path):\r
77 sta = os.stat(path)\r
78 oldmode = stat.S_IMODE(sta.st_mode)\r
79 self.rlist.append(_PathInfo(_CHMOD, path, oldmode))\r
80 self._save(_RMDIR, path)\r
81 __built_in_rmdir__(path)\r
82\r
83 def bkmkdir(self, path, mode):\r
84 if not os.path.exists(path):\r
85 self._save(_MKDIR, path)\r
86 __built_in_mkdir__(path, mode)\r
87\r
88 def bkchmod(self, path, mode):\r
89 if self._tryhook(path) and os.path.exists(path):\r
90 sta = os.stat(path)\r
91 oldmode = stat.S_IMODE(sta.st_mode)\r
92 self.rlist.append(_PathInfo(_CHMOD, path, oldmode))\r
93 __built_in_chmod__(path, mode)\r
94\r
95 def rollback(self):\r
96 if self.zip:\r
97 self.zip.close()\r
98 self.zip = None\r
99 index = len(self.rlist) - 1\r
100 while index >= 0:\r
101 item = self.rlist[index]\r
102 exist = os.path.exists(item.path)\r
103 if item.action == _MKFILE and exist:\r
104 #if not os.access(item.path, os.W_OK):\r
105 # os.chmod(item.path, S_IWUSR)\r
106 __built_in_remove__(item.path)\r
107 elif item.action == _RMFILE and not exist:\r
108 if not self.zip:\r
109 self.zip = zipfile.ZipFile(self.zipfile, 'r', zipfile.ZIP_DEFLATED)\r
110 arcname = os.path.normpath(item.path)\r
111 arcname = arcname[len(self.workspace)+1:].encode('utf_8')\r
112 if os.sep != "/" and os.sep in arcname:\r
113 arcname = arcname.replace(os.sep, '/')\r
114 mtime = self.zip.getinfo(arcname).date_time\r
115 content = self.zip.read(arcname)\r
116 filep = __built_in_open__(item.path, "wb")\r
117 filep.write(content)\r
118 filep.close()\r
119 intime = time.mktime(mtime + (0, 0, 0))\r
120 os.utime(item.path, (intime, intime))\r
121 elif item.action == _MKDIR and exist:\r
122 while True:\r
123 try:\r
124 __built_in_rmdir__(item.path)\r
125 break\r
126 except IOError:\r
127 # Sleep a short time and try again\r
128 # The anti-virus software may delay the file removal in this directory\r
129 sleep(0.1)\r
130 elif item.action == _RMDIR and not exist:\r
131 __built_in_mkdir__(item.path)\r
132 elif item.action == _CHMOD and exist:\r
133 try:\r
134 __built_in_chmod__(item.path, item.mode)\r
135 except EnvironmentError:\r
136 pass\r
137 index -= 1\r
138 self.commit()\r
139\r
140 def commit(self):\r
141 if self.zip:\r
142 self.zip.close()\r
143 __built_in_remove__(self.zipfile)\r
144\r
145 # Check if path needs to be hooked\r
146 def _tryhook(self, path):\r
147 path = os.path.normpath(path)\r
148 works = self.workspace if str(self.workspace).endswith(os.sep) else (self.workspace + os.sep)\r
149 if not path.startswith(works):\r
150 return ''\r
151 for exceptdir in gEXCEPTION_LIST:\r
152 full = os.path.join(self.workspace, exceptdir)\r
153 if full == path or path.startswith(full + os.sep) or os.path.split(full)[0] == path:\r
154 return ''\r
155 return path[len(self.workspace)+1:]\r
156\r
157def _hookrm(path):\r
158 if GlobalData.gRECOVERMGR:\r
159 GlobalData.gRECOVERMGR.bkrmfile(path)\r
160 else:\r
161 __built_in_remove__(path)\r
162\r
2617a73c 163def _hookmkdir(path, mode=0o777):\r
421ccda3
HC
164 if GlobalData.gRECOVERMGR:\r
165 GlobalData.gRECOVERMGR.bkmkdir(path, mode)\r
166 else:\r
167 __built_in_mkdir__(path, mode)\r
168\r
169def _hookrmdir(path):\r
170 if GlobalData.gRECOVERMGR:\r
171 GlobalData.gRECOVERMGR.bkrmdir(path)\r
172 else:\r
173 __built_in_rmdir__(path)\r
174\r
175def _hookmkfile(path, mode='r', bufsize=-1):\r
176 if GlobalData.gRECOVERMGR:\r
177 return GlobalData.gRECOVERMGR.bkmkfile(path, mode, bufsize)\r
178 return __built_in_open__(path, mode, bufsize)\r
179\r
180def _hookchmod(path, mode):\r
181 if GlobalData.gRECOVERMGR:\r
182 GlobalData.gRECOVERMGR.bkchmod(path, mode)\r
183 else:\r
184 __built_in_chmod__(path, mode)\r
185\r
186def SetRecoverMgr(mgr):\r
187 GlobalData.gRECOVERMGR = mgr\r
188\r
189os.remove = _hookrm\r
190os.mkdir = _hookmkdir\r
191os.rmdir = _hookrmdir\r
192os.chmod = _hookchmod\r
193__FileHookOpen__ = _hookmkfile\r