paramiko.sftp_attr

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

# Source Code for Module paramiko.sftp_attr

      1  # Copyright (C) 2003-2006 Robey Pointer <robey@lag.net>
      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 distrubuted 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 *
     22  from paramiko.sftp import *
     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      C{os.stat} as closely as possible, so it may have the following fields,
     30      with the same meanings as those returned by an C{os.stat} object:
     31          - st_size
     32          - st_uid
     33          - st_gid
     34          - st_mode
     35          - st_atime
     36          - st_mtime
     37
     38      Because SFTP allows flags to have other arbitrary named attributes, these
     39      are stored in a dict named C{attr}.  Occasionally, the filename is also
     40      stored, in C{filename}.
     41      """
     42
     43      FLAG_SIZE = 1
     44      FLAG_UIDGID = 2
     45      FLAG_PERMISSIONS = 4
     46      FLAG_AMTIME = 8
     47      FLAG_EXTENDED = 0x80000000L
     48
     49 -    def __init__(self):
     50          """
     51          Create a new (empty) SFTPAttributes object.  All fields will be empty.
     52          """
     53          self._flags = 0
     54          self.st_size = None
     55          self.st_uid = None
     56          self.st_gid = None
     57          self.st_mode = None
     58          self.st_atime = None
     59          self.st_mtime = None
     60          self.attr = {}
     61
     62 -    def from_stat(cls, obj, filename=None):
     63          """
     64          Create an SFTPAttributes object from an existing C{stat} object (an
     65          object returned by C{os.stat}).
     66
     67          @param obj: an object returned by C{os.stat} (or equivalent).
     68          @type obj: object
     69          @param filename: the filename associated with this file.
     70          @type filename: str
     71          @return: new L{SFTPAttributes} object with the same attribute fields.
     72          @rtype: L{SFTPAttributes}
     73          """
     74          attr = cls()
     75          attr.st_size = obj.st_size
     76          attr.st_uid = obj.st_uid
     77          attr.st_gid = obj.st_gid
     78          attr.st_mode = obj.st_mode
     79          attr.st_atime = obj.st_atime
     80          attr.st_mtime = obj.st_mtime
     81          if filename is not None:
     82              attr.filename = filename
     83          return attr
     84      from_stat = classmethod(from_stat)
     85
     86 -    def __repr__(self):
     87          return '<SFTPAttributes: %s>' % self._debug_str()
     88
     89
     90      ###  internals...
     91
     92
     93 -    def _from_msg(cls, msg, filename=None, longname=None):
     94          attr = cls()
     95          attr._unpack(msg)
     96          if filename is not None:
     97              attr.filename = filename
     98          if longname is not None:
     99              attr.longname = longname
    100          return attr
    101      _from_msg = classmethod(_from_msg)
    102
    103 -    def _unpack(self, msg):
    104          self._flags = msg.get_int()
    105          if self._flags & self.FLAG_SIZE:
    106              self.st_size = msg.get_int64()
    107          if self._flags & self.FLAG_UIDGID:
    108              self.st_uid = msg.get_int()
    109              self.st_gid = msg.get_int()
    110          if self._flags & self.FLAG_PERMISSIONS:
    111              self.st_mode = msg.get_int()
    112          if self._flags & self.FLAG_AMTIME:
    113              self.st_atime = msg.get_int()
    114              self.st_mtime = msg.get_int()
    115          if self._flags & self.FLAG_EXTENDED:
    116              count = msg.get_int()
    117              for i in range(count):
    118                  self.attr[msg.get_string()] = msg.get_string()
    119
    120 -    def _pack(self, msg):
    121          self._flags = 0
    122          if self.st_size is not None:
    123              self._flags |= self.FLAG_SIZE
    124          if (self.st_uid is not None) and (self.st_gid is not None):
    125              self._flags |= self.FLAG_UIDGID
    126          if self.st_mode is not None:
    127              self._flags |= self.FLAG_PERMISSIONS
    128          if (self.st_atime is not None) and (self.st_mtime is not None):
    129              self._flags |= self.FLAG_AMTIME
    130          if len(self.attr) > 0:
    131              self._flags |= self.FLAG_EXTENDED
    132          msg.add_int(self._flags)
    133          if self._flags & self.FLAG_SIZE:
    134              msg.add_int64(self.st_size)
    135          if self._flags & self.FLAG_UIDGID:
    136              msg.add_int(self.st_uid)
    137              msg.add_int(self.st_gid)
    138          if self._flags & self.FLAG_PERMISSIONS:
    139              msg.add_int(self.st_mode)
    140          if self._flags & self.FLAG_AMTIME:
    141              # throw away any fractional seconds
    142              msg.add_int(long(self.st_atime))
    143              msg.add_int(long(self.st_mtime))
    144          if self._flags & self.FLAG_EXTENDED:
    145              msg.add_int(len(self.attr))
    146              for key, val in self.attr.iteritems():
    147                  msg.add_string(key)
    148                  msg.add_string(val)
    149          return
    150
    151 -    def _debug_str(self):
    152          out = '[ '
    153          if self.st_size is not None:
    154              out += 'size=%d ' % self.st_size
    155          if (self.st_uid is not None) and (self.st_gid is not None):
    156              out += 'uid=%d gid=%d ' % (self.st_uid, self.st_gid)
    157          if self.st_mode is not None:
    158              out += 'mode=' + oct(self.st_mode) + ' '
    159          if (self.st_atime is not None) and (self.st_mtime is not None):
    160              out += 'atime=%d mtime=%d ' % (self.st_atime, self.st_mtime)
    161          for k, v in self.attr.iteritems():
    162              out += '"%s"=%r ' % (str(k), v)
    163          out += ']'
    164          return out
    165
    166 -    def _rwx(n, suid, sticky=False):
    167          if suid:
    168              suid = 2
    169          out = '-r'[n >> 2] + '-w'[(n >> 1) & 1]
    170          if sticky:
    171              out += '-xTt'[suid + (n & 1)]
    172          else:
    173              out += '-xSs'[suid + (n & 1)]
    174          return out
    175      _rwx = staticmethod(_rwx)
    176
    177 -    def __str__(self):
    178          "create a unix-style long description of the file (like ls -l)"
    179          if self.st_mode is not None:
    180              kind = stat.S_IFMT(self.st_mode)
    181              if kind == stat.S_IFIFO:
    182                  ks = 'p'
    183              elif kind == stat.S_IFCHR:
    184                  ks = 'c'
    185              elif kind == stat.S_IFDIR:
    186                  ks = 'd'
    187              elif kind == stat.S_IFBLK:
    188                  ks = 'b'
    189              elif kind == stat.S_IFREG:
    190                  ks = '-'
    191              elif kind == stat.S_IFLNK:
    192                  ks = 'l'
    193              elif kind == stat.S_IFSOCK:
    194                  ks = 's'
    195              else:
    196                  ks = '?'
    197              ks += self._rwx((self.st_mode & 0700) >> 6, self.st_mode & stat.S_ISUID)
    198              ks += self._rwx((self.st_mode & 070) >> 3, self.st_mode & stat.S_ISGID)
    199              ks += self._rwx(self.st_mode & 7, self.st_mode & stat.S_ISVTX, True)
    200          else:
    201              ks = '?---------'
    202          # compute display date
    203          if (self.st_mtime is None) or (self.st_mtime == 0xffffffff):
    204              # shouldn't really happen
    205              datestr = '(unknown date)'
    206          else:
    207              if abs(time.time() - self.st_mtime) > 15552000:
    208                  # (15552000 = 6 months)
    209                  datestr = time.strftime('%d %b %Y', time.localtime(self.st_mtime))
    210              else:
    211                  datestr = time.strftime('%d %b %H:%M', time.localtime(self.st_mtime))
    212          filename = getattr(self, 'filename', '?')
    213
    214          # not all servers support uid/gid
    215          uid = self.st_uid
    216          gid = self.st_gid
    217          if uid is None:
    218              uid = 0
    219          if gid is None:
    220              gid = 0
    221
    222          return '%s   1 %-8d %-8d %8d %-12s %s' % (ks, uid, gid, self.st_size, datestr, filename)
    223