LEFT | RIGHT |
1 # -*- coding: utf-8 -*- | 1 # -*- coding: utf-8 -*- |
2 """The TAR file entry implementation.""" | 2 """The TAR file entry implementation.""" |
| 3 |
| 4 from __future__ import unicode_literals |
3 | 5 |
4 from dfdatetime import posix_time as dfdatetime_posix_time | 6 from dfdatetime import posix_time as dfdatetime_posix_time |
5 | 7 |
6 from dfvfs.lib import definitions | 8 from dfvfs.lib import definitions |
7 from dfvfs.lib import errors | 9 from dfvfs.lib import errors |
8 from dfvfs.lib import py2to3 | 10 from dfvfs.lib import py2to3 |
9 from dfvfs.path import tar_path_spec | 11 from dfvfs.path import tar_path_spec |
10 from dfvfs.vfs import file_entry | 12 from dfvfs.vfs import file_entry |
11 | 13 |
12 | 14 |
13 class TARDirectory(file_entry.Directory): | 15 class TARDirectory(file_entry.Directory): |
14 """File system directory that uses tarfile.""" | 16 """File system directory that uses tarfile.""" |
15 | 17 |
16 def _EntriesGenerator(self): | 18 def _EntriesGenerator(self): |
17 """Retrieves directory entries. | 19 """Retrieves directory entries. |
18 | 20 |
19 Since a directory can contain a vast number of entries using | 21 Since a directory can contain a vast number of entries using |
20 a generator is more memory efficient. | 22 a generator is more memory efficient. |
21 | 23 |
22 Yields: | 24 Yields: |
23 TARPathSpec: TAR path specification. | 25 TARPathSpec: TAR path specification. |
24 """ | 26 """ |
25 location = getattr(self.path_spec, u'location', None) | 27 location = getattr(self.path_spec, 'location', None) |
26 | 28 |
27 if (location is None or | 29 if (location is None or |
28 not location.startswith(self._file_system.PATH_SEPARATOR)): | 30 not location.startswith(self._file_system.PATH_SEPARATOR)): |
29 return | 31 return |
30 | 32 |
31 # The TAR info name does not have the leading path separator as | 33 # The TAR info name does not have the leading path separator as |
32 # the location string does. | 34 # the location string does. |
33 tar_path = location[1:] | 35 tar_path = location[1:] |
34 | 36 |
35 # Set of top level sub directories that have been yielded. | 37 # Set of top level sub directories that have been yielded. |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 is_virtual (Optional[bool]): True if the file entry is a virtual file | 95 is_virtual (Optional[bool]): True if the file entry is a virtual file |
94 entry emulated by the corresponding file system. | 96 entry emulated by the corresponding file system. |
95 tar_info (Optional[tarfile.TARInfo]): TAR info. | 97 tar_info (Optional[tarfile.TARInfo]): TAR info. |
96 | 98 |
97 Raises: | 99 Raises: |
98 BackEndError: when the TAR info is missing in a non-virtual file entry. | 100 BackEndError: when the TAR info is missing in a non-virtual file entry. |
99 """ | 101 """ |
100 if not is_virtual and tar_info is None: | 102 if not is_virtual and tar_info is None: |
101 tar_info = file_system.GetTARInfoByPathSpec(path_spec) | 103 tar_info = file_system.GetTARInfoByPathSpec(path_spec) |
102 if not is_virtual and tar_info is None: | 104 if not is_virtual and tar_info is None: |
103 raise errors.BackEndError(u'Missing TAR info in non-virtual file entry.') | 105 raise errors.BackEndError('Missing TAR info in non-virtual file entry.') |
104 | 106 |
105 super(TARFileEntry, self).__init__( | 107 super(TARFileEntry, self).__init__( |
106 resolver_context, file_system, path_spec, is_root=is_root, | 108 resolver_context, file_system, path_spec, is_root=is_root, |
107 is_virtual=is_virtual) | 109 is_virtual=is_virtual) |
108 self._tar_info = tar_info | 110 self._tar_info = tar_info |
109 | 111 |
110 if self._is_virtual or self._tar_info.isdir(): | 112 if self._is_virtual or self._tar_info.isdir(): |
111 self._type = definitions.FILE_ENTRY_TYPE_DIRECTORY | 113 self._type = definitions.FILE_ENTRY_TYPE_DIRECTORY |
112 elif self._tar_info.isfile(): | 114 elif self._tar_info.isfile(): |
113 self._type = definitions.FILE_ENTRY_TYPE_FILE | 115 self._type = definitions.FILE_ENTRY_TYPE_FILE |
(...skipping 27 matching lines...) Expand all Loading... |
141 | 143 |
142 def _GetStat(self): | 144 def _GetStat(self): |
143 """Retrieves the stat object. | 145 """Retrieves the stat object. |
144 | 146 |
145 Returns: | 147 Returns: |
146 VFSStat: stat object. | 148 VFSStat: stat object. |
147 """ | 149 """ |
148 stat_object = super(TARFileEntry, self)._GetStat() | 150 stat_object = super(TARFileEntry, self)._GetStat() |
149 | 151 |
150 # File data stat information. | 152 # File data stat information. |
151 stat_object.size = getattr(self._tar_info, u'size', None) | 153 stat_object.size = getattr(self._tar_info, 'size', None) |
152 | 154 |
153 # Ownership and permissions stat information. | 155 # Ownership and permissions stat information. |
154 stat_object.mode = getattr(self._tar_info, u'mode', None) | 156 stat_object.mode = getattr(self._tar_info, 'mode', None) |
155 stat_object.uid = getattr(self._tar_info, u'uid', None) | 157 stat_object.uid = getattr(self._tar_info, 'uid', None) |
156 stat_object.gid = getattr(self._tar_info, u'gid', None) | 158 stat_object.gid = getattr(self._tar_info, 'gid', None) |
157 | 159 |
158 # TODO: implement support for: | 160 # TODO: implement support for: |
159 # stat_object.uname = getattr(self._tar_info, u'uname', None) | 161 # stat_object.uname = getattr(self._tar_info, 'uname', None) |
160 # stat_object.gname = getattr(self._tar_info, u'gname', None) | 162 # stat_object.gname = getattr(self._tar_info, 'gname', None) |
161 | 163 |
162 # File entry type stat information. | 164 # File entry type stat information. |
163 | 165 |
164 # The root file entry is virtual and should have type directory. | 166 # The root file entry is virtual and should have type directory. |
165 | 167 |
166 # TODO: determine if this covers all the types: | 168 # TODO: determine if this covers all the types: |
167 # REGTYPE, AREGTYPE, LNKTYPE, SYMTYPE, DIRTYPE, FIFOTYPE, CONTTYPE, | 169 # REGTYPE, AREGTYPE, LNKTYPE, SYMTYPE, DIRTYPE, FIFOTYPE, CONTTYPE, |
168 # CHRTYPE, BLKTYPE, GNUTYPE_SPARSE | 170 # CHRTYPE, BLKTYPE, GNUTYPE_SPARSE |
169 | 171 |
170 # Other stat information. | 172 # Other stat information. |
171 # tar_info.pax_headers | 173 # tar_info.pax_headers |
172 | 174 |
173 return stat_object | 175 return stat_object |
174 | 176 |
175 @property | 177 @property |
176 def name(self): | 178 def name(self): |
177 """str: name of the file entry, which does not include the full path.""" | 179 """str: name of the file entry, which does not include the full path.""" |
178 path = getattr(self.path_spec, u'location', None) | 180 path = getattr(self.path_spec, 'location', None) |
179 if path is not None and not isinstance(path, py2to3.UNICODE_TYPE): | 181 if path is not None and not isinstance(path, py2to3.UNICODE_TYPE): |
180 try: | 182 try: |
181 path = path.decode(self._file_system.encoding) | 183 path = path.decode(self._file_system.encoding) |
182 except UnicodeDecodeError: | 184 except UnicodeDecodeError: |
183 path = None | 185 path = None |
184 return self._file_system.BasenamePath(path) | 186 return self._file_system.BasenamePath(path) |
185 | 187 |
186 @property | 188 @property |
187 def modification_time(self): | 189 def modification_time(self): |
188 """dfdatetime.DateTimeValues: modification time or None if not available.""" | 190 """dfdatetime.DateTimeValues: modification time or None if not available.""" |
189 timestamp = getattr(self._tar_info, u'mtime', None) | 191 timestamp = getattr(self._tar_info, 'mtime', None) |
190 if timestamp is not None: | 192 if timestamp is not None: |
191 return dfdatetime_posix_time.PosixTime(timestamp=timestamp) | 193 return dfdatetime_posix_time.PosixTime(timestamp=timestamp) |
192 | 194 |
193 @property | 195 @property |
194 def sub_file_entries(self): | 196 def sub_file_entries(self): |
195 """generator(TARFileEntry): sub file entries.""" | 197 """generator(TARFileEntry): sub file entries.""" |
196 tar_file = self._file_system.GetTARFile() | 198 tar_file = self._file_system.GetTARFile() |
197 | 199 |
198 if self._directory is None: | 200 if self._directory is None: |
199 self._directory = self._GetDirectory() | 201 self._directory = self._GetDirectory() |
200 | 202 |
201 if self._directory and tar_file: | 203 if self._directory and tar_file: |
202 for path_spec in self._directory.entries: | 204 for path_spec in self._directory.entries: |
203 location = getattr(path_spec, u'location', None) | 205 location = getattr(path_spec, 'location', None) |
204 if location is None: | 206 if location is None: |
205 continue | 207 continue |
206 | 208 |
207 kwargs = {} | 209 kwargs = {} |
208 try: | 210 try: |
209 kwargs[u'tar_info'] = tar_file.getmember(location[1:]) | 211 kwargs['tar_info'] = tar_file.getmember(location[1:]) |
210 except KeyError: | 212 except KeyError: |
211 kwargs[u'is_virtual'] = True | 213 kwargs['is_virtual'] = True |
212 | 214 |
213 yield TARFileEntry( | 215 yield TARFileEntry( |
214 self._resolver_context, self._file_system, path_spec, **kwargs) | 216 self._resolver_context, self._file_system, path_spec, **kwargs) |
215 | 217 |
216 def GetParentFileEntry(self): | 218 def GetParentFileEntry(self): |
217 """Retrieves the parent file entry. | 219 """Retrieves the parent file entry. |
218 | 220 |
219 Returns: | 221 Returns: |
220 TARFileEntry: parent file entry or None. | 222 TARFileEntry: parent file entry or None. |
221 """ | 223 """ |
222 location = getattr(self.path_spec, u'location', None) | 224 location = getattr(self.path_spec, 'location', None) |
223 if location is None: | 225 if location is None: |
224 return | 226 return |
225 | 227 |
226 parent_location = self._file_system.DirnamePath(location) | 228 parent_location = self._file_system.DirnamePath(location) |
227 if parent_location is None: | 229 if parent_location is None: |
228 return | 230 return |
229 | 231 |
230 if parent_location == u'': | 232 if parent_location == '': |
231 parent_location = self._file_system.PATH_SEPARATOR | 233 parent_location = self._file_system.PATH_SEPARATOR |
232 is_root = True | 234 is_root = True |
233 is_virtual = True | 235 is_virtual = True |
234 else: | 236 else: |
235 is_root = False | 237 is_root = False |
236 is_virtual = False | 238 is_virtual = False |
237 | 239 |
238 parent_path_spec = getattr(self.path_spec, u'parent', None) | 240 parent_path_spec = getattr(self.path_spec, 'parent', None) |
239 path_spec = tar_path_spec.TARPathSpec( | 241 path_spec = tar_path_spec.TARPathSpec( |
240 location=parent_location, parent=parent_path_spec) | 242 location=parent_location, parent=parent_path_spec) |
241 return TARFileEntry( | 243 return TARFileEntry( |
242 self._resolver_context, self._file_system, path_spec, is_root=is_root, | 244 self._resolver_context, self._file_system, path_spec, is_root=is_root, |
243 is_virtual=is_virtual) | 245 is_virtual=is_virtual) |
244 | 246 |
245 def GetTARInfo(self): | 247 def GetTARInfo(self): |
246 """Retrieves the TAR info. | 248 """Retrieves the TAR info. |
247 | 249 |
248 Returns: | 250 Returns: |
249 tarfile.TARInfo: TAR info or None if it does not exist. | 251 tarfile.TARInfo: TAR info or None if it does not exist. |
250 | 252 |
251 Raises: | 253 Raises: |
252 PathSpecError: if the path specification is incorrect. | 254 PathSpecError: if the path specification is incorrect. |
253 """ | 255 """ |
254 if not self._tar_info: | 256 if not self._tar_info: |
255 location = getattr(self.path_spec, u'location', None) | 257 location = getattr(self.path_spec, 'location', None) |
256 if location is None: | 258 if location is None: |
257 raise errors.PathSpecError(u'Path specification missing location.') | 259 raise errors.PathSpecError('Path specification missing location.') |
258 | 260 |
259 if not location.startswith(self._file_system.LOCATION_ROOT): | 261 if not location.startswith(self._file_system.LOCATION_ROOT): |
260 raise errors.PathSpecError(u'Invalid location in path specification.') | 262 raise errors.PathSpecError('Invalid location in path specification.') |
261 | 263 |
262 if len(location) == 1: | 264 if len(location) == 1: |
263 return | 265 return |
264 | 266 |
265 tar_file = self._file_system.GetTARFile() | 267 tar_file = self._file_system.GetTARFile() |
266 try: | 268 try: |
267 self._tar_info = tar_file.getmember(location[1:]) | 269 self._tar_info = tar_file.getmember(location[1:]) |
268 except KeyError: | 270 except KeyError: |
269 pass | 271 pass |
270 | 272 |
271 return self._tar_info | 273 return self._tar_info |
LEFT | RIGHT |