Package libxyz :: Package vfs :: Module tar
[hide private]
[frames] | no frames]

Source Code for Module libxyz.vfs.tar

  1  #-*- coding: utf8 -* 
  2  # 
  3  # Max E. Kuznecov ~syhpoon <syhpoon@syhpoon.name> 2008-2009 
  4  # 
  5  # This file is part of XYZCommander. 
  6  # XYZCommander is free software: you can redistribute it and/or modify 
  7  # it under the terms of the GNU Lesser Public License as published by 
  8  # the Free Software Foundation, either version 3 of the License, or 
  9  # (at your option) any later version. 
 10  # XYZCommander is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 13  # GNU Lesser Public License for more details. 
 14  # You should have received a copy of the GNU Lesser Public License 
 15  # along with XYZCommander. If not, see <http://www.gnu.org/licenses/>. 
 16   
 17  import os 
 18  import stat 
 19  import tarfile 
 20  import time 
 21   
 22  from libxyz.core.utils import ustring, bstring 
 23  from libxyz.vfs import types as vfstypes 
 24  from libxyz.vfs import vfsobj 
 25  from libxyz.vfs import util 
 26  from libxyz.vfs import mode 
 27   
28 -class TarVFSObject(vfsobj.VFSObject):
29 """ 30 Tar archive interface 31 """ 32
33 - def either(self, a, b):
34 if self.root: 35 return a 36 else: 37 return b()
38 39 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 40 41 get_name = lambda self, x: os.path.basename(x.name) 42 get_path = lambda self, x: os.path.join(self.ext_path, x.lstrip(os.sep)) 43 44 file_type_map = { 45 lambda obj: obj.isfile(): vfstypes.VFSTypeFile(), 46 lambda obj: obj.isdir(): vfstypes.VFSTypeDir(), 47 lambda obj: obj.issym(): vfstypes.VFSTypeLink(), 48 lambda obj: obj.ischr(): vfstypes.VFSTypeChar(), 49 lambda obj: obj.isblk(): vfstypes.VFSTypeBlock(), 50 lambda obj: obj.isfifo(): vfstypes.VFSTypeFifo(), 51 } 52
53 - def __init__(self, *args, **kwargs):
54 self.tarobj = None 55 super(TarVFSObject, self).__init__(*args, **kwargs)
56 57 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 58
59 - def walk(self):
60 """ 61 Directory tree walker 62 @return: tuple (parent, dir, dirs, files) where: 63 parent - parent dir *VFSObject instance 64 dir - current dir TarVFSObject instance 65 dirs - list of TarVFSObject objects of directories 66 files - list of TarVFSObject objects of files 67 """ 68 69 tarobj = self._open_archive() 70 entries = tarobj.getmembers() 71 72 _dirs = [x for x in entries if x.isdir() and 73 self.in_dir(self.path, x.name)] 74 _files = [x for x in entries if not x.isdir() and 75 self.in_dir(self.path, x.name)] 76 77 _dirs.sort(cmp=lambda x, y: cmp(self.get_name(x), 78 self.get_name(y))) 79 _files.sort(cmp=lambda x, y: cmp(self.get_name(x), 80 self.get_name(y))) 81 82 if self.path == os.sep: 83 _parent = self.xyz.vfs.get_parent(self.parent.path, self.enc) 84 else: 85 _parent = self.xyz.vfs.dispatch( 86 self.get_path(os.path.dirname(self.path)), self.enc, 87 tarobj=self.tarobj) 88 _parent.name = ".." 89 90 return [ 91 _parent, 92 self, 93 [self.xyz.vfs.dispatch(self.get_path(x.name), 94 self.enc, tarobj=self.tarobj) 95 for x in _dirs], 96 [self.xyz.vfs.dispatch(self.get_path(x.name), 97 self.enc, tarobj=self.tarobj) 98 for x in _files], 99 ]
100 101 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 102 103 # def copy(self, path, existcb=None, errorcb=None, save_attrs=True, 104 # follow_links=False, cancel=None): 105 106 # env = { 107 # 'override': 'abort', 108 # 'error': 'abort' 109 # } 110 111 # tarobj = self._open_archive() 112 113 # return tarobj.extractall(path, [self._init_obj()]) 114 115 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 116
117 - def _prepare(self):
118 if self.path == os.sep: 119 self.root = True 120 else: 121 self.root = False 122 123 self.tarobj = self.kwargs.get("tarobj", None) 124 125 if self.root: 126 self.obj = None 127 else: 128 self.obj = self._init_obj() 129 130 self.ftype = self._find_type() 131 self.vtype = self.ftype.vtype 132 133 self._set_attributes() 134 135 self.attributes = ( 136 (_(u"Name"), ustring(self.name)), 137 (_(u"Type"), ustring(self.ftype)), 138 (_(u"Modification time"), ustring(time.ctime(self.mtime))), 139 (_(u"Size in bytes"), ustring(self.size)), 140 (_(u"Owner"), ustring(self.uid)), 141 (_(u"Group"), ustring(self.gid)), 142 (_(u"Access mode"), ustring(self.mode)), 143 (_(u"Type-specific data"), self.data), 144 )
145 146 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 147
148 - def __str__(self):
149 return "<TarVFSObject object: %s>" % self.path
150 151 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 152
153 - def in_dir(self, d, e):
154 """ 155 Filter only those archive entries which exist in the same 156 directory level 157 """ 158 159 if e.startswith(d.lstrip(os.sep)) and \ 160 len(util.split_path(e)) == (len(util.split_path(d)) + 1): 161 return True 162 else: 163 return False
164 165 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 166
167 - def _find_type(self):
168 """ 169 Find out file type 170 """ 171 172 if self.root: 173 return self.parent.ftype 174 175 for k, v in self.file_type_map.iteritems(): 176 if k(self.obj): 177 return v 178 179 return vfstypes.VFSTypeUnknown()
180 181 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 182
183 - def _set_attributes(self):
184 """ 185 Set file attibutes 186 """ 187 188 def set_link_attributes(): 189 """ 190 Set appropriate soft link attibutes 191 """ 192 193 self.info = "" 194 self.visual = "-> %s" % self.obj.linkname or ""
195 196 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 197 198 self.name = self.either(self.parent.name, lambda: self.name) 199 self.mtime = self.either(self.parent.mtime, lambda: self.obj.mtime) 200 self.size = self.either(self.parent.size, lambda: self.obj.size) 201 self.uid = self.either(self.parent.uid, lambda: self.obj.uid) 202 self.gid = self.either(self.parent.gid, lambda: self.obj.gid) 203 self.mode = mode.Mode(self.either(self.parent.mode.raw, 204 lambda: self.obj.mode), self.ftype) 205 self.visual = "%s%s" % (self.vtype, self.name) 206 207 self.info = "%s %s" % (util.format_size(self.size), self.mode) 208 209 if self.is_link(): 210 set_link_attributes() 211 elif self.is_file(): 212 _mode = stat.S_IMODE(self.mode.raw) 213 214 # Executable 215 if _mode & 0111: 216 self.vtype = "*" 217 self.visual = "*%s" % self.name
218 219 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 220
221 - def _init_obj(self):
222 tarobj = self._open_archive() 223 path = self.path.lstrip(os.sep) 224 225 try: 226 obj = tarobj.getmember(path) 227 except KeyError: 228 obj = tarobj.getmember(path + os.sep) 229 230 return obj
231 232 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 233
234 - def _open_archive(self):
235 if self.tarobj is None: 236 _mode = "r" 237 238 if self.driver == "gztar": 239 _mode = "r:gz" 240 elif self.driver == "bz2tar": 241 _mode = "r:bz2" 242 243 self.tarobj = tarfile.open(self.parent.path, mode=_mode) 244 245 return self.tarobj
246