1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15   
 16   
 17   
 18   
 19  import stat 
 20  import time 
 21  from paramiko.common import * 
 22  from paramiko.sftp import * 
 23   
 24   
 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   
 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   
 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   
 87          return '<SFTPAttributes: %s>' % self._debug_str() 
  88   
 89   
 90       
 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   
119   
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               
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   
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   
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           
203          if (self.st_mtime is None) or (self.st_mtime == 0xffffffff): 
204               
205              datestr = '(unknown date)' 
206          else: 
207              if abs(time.time() - self.st_mtime) > 15552000: 
208                   
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           
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