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