diff options
Diffstat (limited to 'paramiko/sftp_attr.py')
-rw-r--r-- | paramiko/sftp_attr.py | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/paramiko/sftp_attr.py b/paramiko/sftp_attr.py new file mode 100644 index 0000000..eae7c99 --- /dev/null +++ b/paramiko/sftp_attr.py @@ -0,0 +1,208 @@ +# Copyright (C) 2003-2005 Robey Pointer <robey@lag.net> +# +# This file is part of paramiko. +# +# Paramiko is free software; you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation; either version 2.1 of the License, or (at your option) +# any later version. +# +# Paramiko is distrubuted in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Paramiko; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + +import stat +import time +from paramiko.common import * +from paramiko.sftp import * + + +class SFTPAttributes (object): + """ + Representation of the attributes of a file (or proxied file) for SFTP in + client or server mode. It attemps to mirror the object returned by + C{os.stat} as closely as possible, so it may have the following fields, + with the same meanings as those returned by an C{os.stat} object: + - st_size + - st_uid + - st_gid + - st_mode + - st_atime + - st_mtime + + Because SFTP allows flags to have other arbitrary named attributes, these + are stored in a dict named C{attr}. Occasionally, the filename is also + stored, in C{filename}. + """ + + FLAG_SIZE = 1 + FLAG_UIDGID = 2 + FLAG_PERMISSIONS = 4 + FLAG_AMTIME = 8 + FLAG_EXTENDED = 0x80000000L + + def __init__(self): + """ + Create a new (empty) SFTPAttributes object. All fields will be empty. + """ + self._flags = 0 + self.attr = {} + + def from_stat(cls, obj, filename=None): + """ + Create an SFTPAttributes object from an existing C{stat} object (an + object returned by C{os.stat}). + + @param obj: an object returned by C{os.stat} (or equivalent). + @type obj: object + @param filename: the filename associated with this file. + @type filename: str + @return: new L{SFTPAttributes} object with the same attribute fields. + @rtype: L{SFTPAttributes} + """ + attr = cls() + attr.st_size = obj.st_size + attr.st_uid = obj.st_uid + attr.st_gid = obj.st_gid + attr.st_mode = obj.st_mode + attr.st_atime = obj.st_atime + attr.st_mtime = obj.st_mtime + if filename is not None: + attr.filename = filename + return attr + from_stat = classmethod(from_stat) + + def __repr__(self): + return '<SFTPAttributes: %s>' % self._debug_str() + + def __str__(self): + return self._debug_str() + + + ### internals... + + + def _from_msg(cls, msg, filename=None): + attr = cls() + attr._unpack(msg) + if filename is not None: + attr.filename = filename + return attr + _from_msg = classmethod(_from_msg) + + def _unpack(self, msg): + self._flags = msg.get_int() + if self._flags & self.FLAG_SIZE: + self.st_size = msg.get_int64() + if self._flags & self.FLAG_UIDGID: + self.st_uid = msg.get_int() + self.st_gid = msg.get_int() + if self._flags & self.FLAG_PERMISSIONS: + self.st_mode = msg.get_int() + if self._flags & self.FLAG_AMTIME: + self.st_atime = msg.get_int() + self.st_mtime = msg.get_int() + if self._flags & self.FLAG_EXTENDED: + count = msg.get_int() + for i in range(count): + self.attr[msg.get_string()] = msg.get_string() + + def _pack(self, msg): + self._flags = 0 + if hasattr(self, 'st_size'): + self._flags |= self.FLAG_SIZE + if hasattr(self, 'st_uid') or hasattr(self, 'st_gid'): + self._flags |= self.FLAG_UIDGID + if hasattr(self, 'st_mode'): + self._flags |= self.FLAG_PERMISSIONS + if hasattr(self, 'st_atime') or hasattr(self, 'st_mtime'): + self._flags |= self.FLAG_AMTIME + if len(self.attr) > 0: + self._flags |= self.FLAG_EXTENDED + msg.add_int(self._flags) + if self._flags & self.FLAG_SIZE: + msg.add_int64(self.st_size) + if self._flags & self.FLAG_UIDGID: + msg.add_int(getattr(self, 'st_uid', 0)) + msg.add_int(getattr(self, 'st_gid', 0)) + if self._flags & self.FLAG_PERMISSIONS: + msg.add_int(self.st_mode) + if self._flags & self.FLAG_AMTIME: + msg.add_int(getattr(self, 'st_atime', 0)) + msg.add_int(getattr(self, 'st_mtime', 0)) + if self._flags & self.FLAG_EXTENDED: + msg.add_int(len(self.attr)) + for key, val in self.attr.iteritems(): + msg.add_string(key) + msg.add_string(val) + return + + def _debug_str(self): + out = '[ ' + if hasattr(self, 'st_size'): + out += 'size=%d ' % self.st_size + if hasattr(self, 'st_uid') or hasattr(self, 'st_gid'): + out += 'uid=%d gid=%d ' % (getattr(self, 'st_uid', 0), getattr(self, 'st_gid', 0)) + if hasattr(self, 'st_mode'): + out += 'mode=' + oct(self.st_mode) + ' ' + if hasattr(self, 'st_atime') or hasattr(self, 'st_mtime'): + out += 'atime=%d mtime=%d ' % (getattr(self, 'st_atime', 0), + getattr(self, 'st_mtime', 0)) + for k, v in self.attr.iteritems(): + out += '"%s"=%r ' % (str(k), v) + out += ']' + return out + + def _rwx(n, suid, sticky=False): + if suid: + suid = 2 + out = '-r'[n >> 2] + '-w'[(n >> 1) & 1] + if sticky: + out += '-xTt'[suid + (n & 1)] + else: + out += '-xSs'[suid + (n & 1)] + return out + _rwx = staticmethod(_rwx) + + def __str__(self): + "create a unix-style long description of the file (like ls -l)" + if hasattr(self, 'st_mode'): + kind = stat.S_IFMT(self.st_mode) + if kind == stat.S_IFIFO: + ks = 'p' + elif kind == stat.S_IFCHR: + ks = 'c' + elif kind == stat.S_IFDIR: + ks = 'd' + elif kind == stat.S_IFBLK: + ks = 'b' + elif kind == stat.S_IFREG: + ks = '-' + elif kind == stat.S_IFLNK: + ks = 'l' + elif kind == stat.S_IFSOCK: + ks = 's' + else: + ks = '?' + ks += self._rwx((self.st_mode & 0700) >> 6, self.st_mode & stat.S_ISUID) + ks += self._rwx((self.st_mode & 070) >> 3, self.st_mode & stat.S_ISGID) + ks += self._rwx(self.st_mode & 7, self.st_mode & stat.S_ISVTX, True) + else: + ks = '?---------' + uid = getattr(self, 'st_uid', -1) + gid = getattr(self, 'st_gid', -1) + size = getattr(self, 'st_size', -1) + mtime = getattr(self, 'st_mtime', 0) + # compute display date + if abs(time.time() - mtime) > 15552000: + # (15552000 = 6 months) + datestr = time.strftime('%d %b %Y', time.localtime(mtime)) + else: + datestr = time.strftime('%d %b %H:%M', time.localtime(mtime)) + filename = getattr(self, 'filename', '?') + return '%s 1 %-8d %-8d %8d %-12s %s' % (ks, uid, gid, size, datestr, filename) |