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 x80000000, o700, o70, xffffffff
22 from paramiko.py3compat import long, b
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 `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
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
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
85 return '<SFTPAttributes: %s>' % self._debug_str()
86
87
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
115
146
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
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
199 if (self.st_mtime is None) or (self.st_mtime == xffffffff):
200
201 datestr = '(unknown date)'
202 else:
203 if abs(time.time() - self.st_mtime) > 15552000:
204
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
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
222