Package paramiko :: Module sftp_attr
[frames] | no frames]

Source Code for Module paramiko.sftp_attr

  1  # Copyright (C) 2003-2006 Robey Pointer <robeypointer@gmail.com> 
  2  # 
  3  # This file is part of paramiko. 
  4  # 
  5  # Paramiko is free software; you can redistribute it and/or modify it under the 
  6  # terms of the GNU Lesser General Public License as published by the Free 
  7  # Software Foundation; either version 2.1 of the License, or (at your option) 
  8  # any later version. 
  9  # 
 10  # Paramiko is distributed in the hope that it will be useful, but WITHOUT ANY 
 11  # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 
 12  # A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more 
 13  # details. 
 14  # 
 15  # You should have received a copy of the GNU Lesser General Public License 
 16  # along with Paramiko; if not, write to the Free Software Foundation, Inc., 
 17  # 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. 
 18   
 19  import stat 
 20  import time 
 21  from paramiko.common import x80000000, o700, o70, xffffffff 
 22  from paramiko.py3compat import long, b 
 23   
 24   
25 -class SFTPAttributes (object):
26 """ 27 Representation of the attributes of a file (or proxied file) for SFTP in 28 client or server mode. It attemps to mirror the object returned by 29 `os.stat` as closely as possible, so it may have the following fields, 30 with the same meanings as those returned by an `os.stat` object: 31 32 - ``st_size`` 33 - ``st_uid`` 34 - ``st_gid`` 35 - ``st_mode`` 36 - ``st_atime`` 37 - ``st_mtime`` 38 39 Because SFTP allows flags to have other arbitrary named attributes, these 40 are stored in a dict named ``attr``. Occasionally, the filename is also 41 stored, in ``filename``. 42 """ 43 44 FLAG_SIZE = 1 45 FLAG_UIDGID = 2 46 FLAG_PERMISSIONS = 4 47 FLAG_AMTIME = 8 48 FLAG_EXTENDED = x80000000 49
50 - def __init__(self):
51 """ 52 Create a new (empty) SFTPAttributes object. All fields will be empty. 53 """ 54 self._flags = 0 55 self.st_size = None 56 self.st_uid = None 57 self.st_gid = None 58 self.st_mode = None 59 self.st_atime = None 60 self.st_mtime = None 61 self.attr = {}
62
63 - def from_stat(cls, obj, filename=None):
64 """ 65 Create an `.SFTPAttributes` object from an existing ``stat`` object (an 66 object returned by `os.stat`). 67 68 :param object obj: an object returned by `os.stat` (or equivalent). 69 :param str filename: the filename associated with this file. 70 :return: new `.SFTPAttributes` object with the same attribute fields. 71 """ 72 attr = cls() 73 attr.st_size = obj.st_size 74 attr.st_uid = obj.st_uid 75 attr.st_gid = obj.st_gid 76 attr.st_mode = obj.st_mode 77 attr.st_atime = obj.st_atime 78 attr.st_mtime = obj.st_mtime 79 if filename is not None: 80 attr.filename = filename 81 return attr
82 from_stat = classmethod(from_stat) 83
84 - def __repr__(self):
85 return '<SFTPAttributes: %s>' % self._debug_str()
86 87 ### internals... 88
89 - def _from_msg(cls, msg, filename=None, longname=None):
90 attr = cls() 91 attr._unpack(msg) 92 if filename is not None: 93 attr.filename = filename 94 if longname is not None: 95 attr.longname = longname 96 return attr
97 _from_msg = classmethod(_from_msg) 98
99 - def _unpack(self, msg):
100 self._flags = msg.get_int() 101 if self._flags & self.FLAG_SIZE: 102 self.st_size = msg.get_int64() 103 if self._flags & self.FLAG_UIDGID: 104 self.st_uid = msg.get_int() 105 self.st_gid = msg.get_int() 106 if self._flags & self.FLAG_PERMISSIONS: 107 self.st_mode = msg.get_int() 108 if self._flags & self.FLAG_AMTIME: 109 self.st_atime = msg.get_int() 110 self.st_mtime = msg.get_int() 111 if self._flags & self.FLAG_EXTENDED: 112 count = msg.get_int() 113 for i in range(count): 114 self.attr[msg.get_string()] = msg.get_string()
115
116 - def _pack(self, msg):
117 self._flags = 0 118 if self.st_size is not None: 119 self._flags |= self.FLAG_SIZE 120 if (self.st_uid is not None) and (self.st_gid is not None): 121 self._flags |= self.FLAG_UIDGID 122 if self.st_mode is not None: 123 self._flags |= self.FLAG_PERMISSIONS 124 if (self.st_atime is not None) and (self.st_mtime is not None): 125 self._flags |= self.FLAG_AMTIME 126 if len(self.attr) > 0: 127 self._flags |= self.FLAG_EXTENDED 128 msg.add_int(self._flags) 129 if self._flags & self.FLAG_SIZE: 130 msg.add_int64(self.st_size) 131 if self._flags & self.FLAG_UIDGID: 132 msg.add_int(self.st_uid) 133 msg.add_int(self.st_gid) 134 if self._flags & self.FLAG_PERMISSIONS: 135 msg.add_int(self.st_mode) 136 if self._flags & self.FLAG_AMTIME: 137 # throw away any fractional seconds 138 msg.add_int(long(self.st_atime)) 139 msg.add_int(long(self.st_mtime)) 140 if self._flags & self.FLAG_EXTENDED: 141 msg.add_int(len(self.attr)) 142 for key, val in self.attr.items(): 143 msg.add_string(key) 144 msg.add_string(val) 145 return
146
147 - def _debug_str(self):
148 out = '[ ' 149 if self.st_size is not None: 150 out += 'size=%d ' % self.st_size 151 if (self.st_uid is not None) and (self.st_gid is not None): 152 out += 'uid=%d gid=%d ' % (self.st_uid, self.st_gid) 153 if self.st_mode is not None: 154 out += 'mode=' + oct(self.st_mode) + ' ' 155 if (self.st_atime is not None) and (self.st_mtime is not None): 156 out += 'atime=%d mtime=%d ' % (self.st_atime, self.st_mtime) 157 for k, v in self.attr.items(): 158 out += '"%s"=%r ' % (str(k), v) 159 out += ']' 160 return out
161
162 - def _rwx(n, suid, sticky=False):
163 if suid: 164 suid = 2 165 out = '-r'[n >> 2] + '-w'[(n >> 1) & 1] 166 if sticky: 167 out += '-xTt'[suid + (n & 1)] 168 else: 169 out += '-xSs'[suid + (n & 1)] 170 return out
171 _rwx = staticmethod(_rwx) 172
173 - def __str__(self):
174 """create a unix-style long description of the file (like ls -l)""" 175 if self.st_mode is not None: 176 kind = stat.S_IFMT(self.st_mode) 177 if kind == stat.S_IFIFO: 178 ks = 'p' 179 elif kind == stat.S_IFCHR: 180 ks = 'c' 181 elif kind == stat.S_IFDIR: 182 ks = 'd' 183 elif kind == stat.S_IFBLK: 184 ks = 'b' 185 elif kind == stat.S_IFREG: 186 ks = '-' 187 elif kind == stat.S_IFLNK: 188 ks = 'l' 189 elif kind == stat.S_IFSOCK: 190 ks = 's' 191 else: 192 ks = '?' 193 ks += self._rwx((self.st_mode & o700) >> 6, self.st_mode & stat.S_ISUID) 194 ks += self._rwx((self.st_mode & o70) >> 3, self.st_mode & stat.S_ISGID) 195 ks += self._rwx(self.st_mode & 7, self.st_mode & stat.S_ISVTX, True) 196 else: 197 ks = '?---------' 198 # compute display date 199 if (self.st_mtime is None) or (self.st_mtime == xffffffff): 200 # shouldn't really happen 201 datestr = '(unknown date)' 202 else: 203 if abs(time.time() - self.st_mtime) > 15552000: 204 # (15552000 = 6 months) 205 datestr = time.strftime('%d %b %Y', time.localtime(self.st_mtime)) 206 else: 207 datestr = time.strftime('%d %b %H:%M', time.localtime(self.st_mtime)) 208 filename = getattr(self, 'filename', '?') 209 210 # not all servers support uid/gid 211 uid = self.st_uid 212 gid = self.st_gid 213 if uid is None: 214 uid = 0 215 if gid is None: 216 gid = 0 217 218 return '%s 1 %-8d %-8d %8d %-12s %s' % (ks, uid, gid, self.st_size, datestr, filename)
219
220 - def asbytes(self):
221 return b(str(self))
222