summaryrefslogtreecommitdiff
path: root/paramiko/sftp_attr.py
diff options
context:
space:
mode:
Diffstat (limited to 'paramiko/sftp_attr.py')
-rw-r--r--paramiko/sftp_attr.py208
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)