From ed280d5ac360e2af796e9bd973d7b4df89f0c449 Mon Sep 17 00:00:00 2001 From: "Jeremy T. Bouse" Date: Fri, 27 Nov 2009 16:20:12 -0500 Subject: Imported Upstream version 1.7.4 --- docs/paramiko.sftp_client-pysrc.html | 1563 ++++++++++++++++++++++++++++++++++ 1 file changed, 1563 insertions(+) create mode 100644 docs/paramiko.sftp_client-pysrc.html (limited to 'docs/paramiko.sftp_client-pysrc.html') diff --git a/docs/paramiko.sftp_client-pysrc.html b/docs/paramiko.sftp_client-pysrc.html new file mode 100644 index 0000000..0b17480 --- /dev/null +++ b/docs/paramiko.sftp_client-pysrc.html @@ -0,0 +1,1563 @@ + + + + + paramiko.sftp_client + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + Package paramiko :: + Module sftp_client + + + + + +
[frames] | no frames]
+
+

Source Code for Module paramiko.sftp_client

+
+  1  # Copyright (C) 2003-2007  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  """ 
+ 20  Client-mode SFTP support. 
+ 21  """ 
+ 22   
+ 23  from binascii import hexlify 
+ 24  import errno 
+ 25  import os 
+ 26  import threading 
+ 27  import time 
+ 28  import weakref 
+ 29   
+ 30  from paramiko.sftp import * 
+ 31  from paramiko.sftp_attr import SFTPAttributes 
+ 32  from paramiko.ssh_exception import SSHException 
+ 33  from paramiko.sftp_file import SFTPFile 
+ 34   
+ 35   
+
36 -def _to_unicode(s): +
37 """ + 38 decode a string as ascii or utf8 if possible (as required by the sftp + 39 protocol). if neither works, just return a byte string because the server + 40 probably doesn't know the filename's encoding. + 41 """ + 42 try: + 43 return s.encode('ascii') + 44 except UnicodeError: + 45 try: + 46 return s.decode('utf-8') + 47 except UnicodeError: + 48 return s +
49 + 50 +
51 -class SFTPClient (BaseSFTP): +
52 """ + 53 SFTP client object. C{SFTPClient} is used to open an sftp session across + 54 an open ssh L{Transport} and do remote file operations. + 55 """ + 56 +
57 - def __init__(self, sock): +
58 """ + 59 Create an SFTP client from an existing L{Channel}. The channel + 60 should already have requested the C{"sftp"} subsystem. + 61 + 62 An alternate way to create an SFTP client context is by using + 63 L{from_transport}. + 64 + 65 @param sock: an open L{Channel} using the C{"sftp"} subsystem + 66 @type sock: L{Channel} + 67 + 68 @raise SSHException: if there's an exception while negotiating + 69 sftp + 70 """ + 71 BaseSFTP.__init__(self) + 72 self.sock = sock + 73 self.ultra_debug = False + 74 self.request_number = 1 + 75 # lock for request_number + 76 self._lock = threading.Lock() + 77 self._cwd = None + 78 # request # -> SFTPFile + 79 self._expecting = weakref.WeakValueDictionary() + 80 if type(sock) is Channel: + 81 # override default logger + 82 transport = self.sock.get_transport() + 83 self.logger = util.get_logger(transport.get_log_channel() + '.sftp') + 84 self.ultra_debug = transport.get_hexdump() + 85 try: + 86 server_version = self._send_version() + 87 except EOFError, x: + 88 raise SSHException('EOF during negotiation') + 89 self._log(INFO, 'Opened sftp connection (server version %d)' % server_version) +
90 +
91 - def from_transport(cls, t): +
92 """ + 93 Create an SFTP client channel from an open L{Transport}. + 94 + 95 @param t: an open L{Transport} which is already authenticated + 96 @type t: L{Transport} + 97 @return: a new L{SFTPClient} object, referring to an sftp session + 98 (channel) across the transport + 99 @rtype: L{SFTPClient} +100 """ +101 chan = t.open_session() +102 if chan is None: +103 return None +104 chan.invoke_subsystem('sftp') +105 return cls(chan) +
106 from_transport = classmethod(from_transport) +107 +
108 - def _log(self, level, msg, *args): +
109 super(SFTPClient, self)._log(level, "[chan %s] " + msg, *([ self.sock.get_name() ] + list(args))) +
110 +
111 - def close(self): +
112 """ +113 Close the SFTP session and its underlying channel. +114 +115 @since: 1.4 +116 """ +117 self._log(INFO, 'sftp session closed.') +118 self.sock.close() +
119 +
120 - def get_channel(self): +
121 """ +122 Return the underlying L{Channel} object for this SFTP session. This +123 might be useful for doing things like setting a timeout on the channel. +124 +125 @return: the SSH channel +126 @rtype: L{Channel} +127 +128 @since: 1.7.1 +129 """ +130 return self.sock +
131 +
132 - def listdir(self, path='.'): +
133 """ +134 Return a list containing the names of the entries in the given C{path}. +135 The list is in arbitrary order. It does not include the special +136 entries C{'.'} and C{'..'} even if they are present in the folder. +137 This method is meant to mirror C{os.listdir} as closely as possible. +138 For a list of full L{SFTPAttributes} objects, see L{listdir_attr}. +139 +140 @param path: path to list (defaults to C{'.'}) +141 @type path: str +142 @return: list of filenames +143 @rtype: list of str +144 """ +145 return [f.filename for f in self.listdir_attr(path)] +
146 +
147 - def listdir_attr(self, path='.'): +
148 """ +149 Return a list containing L{SFTPAttributes} objects corresponding to +150 files in the given C{path}. The list is in arbitrary order. It does +151 not include the special entries C{'.'} and C{'..'} even if they are +152 present in the folder. +153 +154 The returned L{SFTPAttributes} objects will each have an additional +155 field: C{longname}, which may contain a formatted string of the file's +156 attributes, in unix format. The content of this string will probably +157 depend on the SFTP server implementation. +158 +159 @param path: path to list (defaults to C{'.'}) +160 @type path: str +161 @return: list of attributes +162 @rtype: list of L{SFTPAttributes} +163 +164 @since: 1.2 +165 """ +166 path = self._adjust_cwd(path) +167 self._log(DEBUG, 'listdir(%r)' % path) +168 t, msg = self._request(CMD_OPENDIR, path) +169 if t != CMD_HANDLE: +170 raise SFTPError('Expected handle') +171 handle = msg.get_string() +172 filelist = [] +173 while True: +174 try: +175 t, msg = self._request(CMD_READDIR, handle) +176 except EOFError, e: +177 # done with handle +178 break +179 if t != CMD_NAME: +180 raise SFTPError('Expected name response') +181 count = msg.get_int() +182 for i in range(count): +183 filename = _to_unicode(msg.get_string()) +184 longname = _to_unicode(msg.get_string()) +185 attr = SFTPAttributes._from_msg(msg, filename, longname) +186 if (filename != '.') and (filename != '..'): +187 filelist.append(attr) +188 self._request(CMD_CLOSE, handle) +189 return filelist +
190 +
191 - def open(self, filename, mode='r', bufsize=-1): +
192 """ +193 Open a file on the remote server. The arguments are the same as for +194 python's built-in C{file} (aka C{open}). A file-like object is +195 returned, which closely mimics the behavior of a normal python file +196 object. +197 +198 The mode indicates how the file is to be opened: C{'r'} for reading, +199 C{'w'} for writing (truncating an existing file), C{'a'} for appending, +200 C{'r+'} for reading/writing, C{'w+'} for reading/writing (truncating an +201 existing file), C{'a+'} for reading/appending. The python C{'b'} flag +202 is ignored, since SSH treats all files as binary. The C{'U'} flag is +203 supported in a compatible way. +204 +205 Since 1.5.2, an C{'x'} flag indicates that the operation should only +206 succeed if the file was created and did not previously exist. This has +207 no direct mapping to python's file flags, but is commonly known as the +208 C{O_EXCL} flag in posix. +209 +210 The file will be buffered in standard python style by default, but +211 can be altered with the C{bufsize} parameter. C{0} turns off +212 buffering, C{1} uses line buffering, and any number greater than 1 +213 (C{>1}) uses that specific buffer size. +214 +215 @param filename: name of the file to open +216 @type filename: str +217 @param mode: mode (python-style) to open in +218 @type mode: str +219 @param bufsize: desired buffering (-1 = default buffer size) +220 @type bufsize: int +221 @return: a file object representing the open file +222 @rtype: SFTPFile +223 +224 @raise IOError: if the file could not be opened. +225 """ +226 filename = self._adjust_cwd(filename) +227 self._log(DEBUG, 'open(%r, %r)' % (filename, mode)) +228 imode = 0 +229 if ('r' in mode) or ('+' in mode): +230 imode |= SFTP_FLAG_READ +231 if ('w' in mode) or ('+' in mode) or ('a' in mode): +232 imode |= SFTP_FLAG_WRITE +233 if ('w' in mode): +234 imode |= SFTP_FLAG_CREATE | SFTP_FLAG_TRUNC +235 if ('a' in mode): +236 imode |= SFTP_FLAG_CREATE | SFTP_FLAG_APPEND +237 if ('x' in mode): +238 imode |= SFTP_FLAG_CREATE | SFTP_FLAG_EXCL +239 attrblock = SFTPAttributes() +240 t, msg = self._request(CMD_OPEN, filename, imode, attrblock) +241 if t != CMD_HANDLE: +242 raise SFTPError('Expected handle') +243 handle = msg.get_string() +244 self._log(DEBUG, 'open(%r, %r) -> %s' % (filename, mode, hexlify(handle))) +245 return SFTPFile(self, handle, mode, bufsize) +
246 +247 # python continues to vacillate about "open" vs "file"... +248 file = open +249 +
250 - def remove(self, path): +
251 """ +252 Remove the file at the given path. This only works on files; for +253 removing folders (directories), use L{rmdir}. +254 +255 @param path: path (absolute or relative) of the file to remove +256 @type path: str +257 +258 @raise IOError: if the path refers to a folder (directory) +259 """ +260 path = self._adjust_cwd(path) +261 self._log(DEBUG, 'remove(%r)' % path) +262 self._request(CMD_REMOVE, path) +
263 +264 unlink = remove +265 +
266 - def rename(self, oldpath, newpath): +
267 """ +268 Rename a file or folder from C{oldpath} to C{newpath}. +269 +270 @param oldpath: existing name of the file or folder +271 @type oldpath: str +272 @param newpath: new name for the file or folder +273 @type newpath: str +274 +275 @raise IOError: if C{newpath} is a folder, or something else goes +276 wrong +277 """ +278 oldpath = self._adjust_cwd(oldpath) +279 newpath = self._adjust_cwd(newpath) +280 self._log(DEBUG, 'rename(%r, %r)' % (oldpath, newpath)) +281 self._request(CMD_RENAME, oldpath, newpath) +
282 +
283 - def mkdir(self, path, mode=0777): +
284 """ +285 Create a folder (directory) named C{path} with numeric mode C{mode}. +286 The default mode is 0777 (octal). On some systems, mode is ignored. +287 Where it is used, the current umask value is first masked out. +288 +289 @param path: name of the folder to create +290 @type path: str +291 @param mode: permissions (posix-style) for the newly-created folder +292 @type mode: int +293 """ +294 path = self._adjust_cwd(path) +295 self._log(DEBUG, 'mkdir(%r, %r)' % (path, mode)) +296 attr = SFTPAttributes() +297 attr.st_mode = mode +298 self._request(CMD_MKDIR, path, attr) +
299 +
300 - def rmdir(self, path): +
301 """ +302 Remove the folder named C{path}. +303 +304 @param path: name of the folder to remove +305 @type path: str +306 """ +307 path = self._adjust_cwd(path) +308 self._log(DEBUG, 'rmdir(%r)' % path) +309 self._request(CMD_RMDIR, path) +
310 +
311 - def stat(self, path): +
312 """ +313 Retrieve information about a file on the remote system. The return +314 value is an object whose attributes correspond to the attributes of +315 python's C{stat} structure as returned by C{os.stat}, except that it +316 contains fewer fields. An SFTP server may return as much or as little +317 info as it wants, so the results may vary from server to server. +318 +319 Unlike a python C{stat} object, the result may not be accessed as a +320 tuple. This is mostly due to the author's slack factor. +321 +322 The fields supported are: C{st_mode}, C{st_size}, C{st_uid}, C{st_gid}, +323 C{st_atime}, and C{st_mtime}. +324 +325 @param path: the filename to stat +326 @type path: str +327 @return: an object containing attributes about the given file +328 @rtype: SFTPAttributes +329 """ +330 path = self._adjust_cwd(path) +331 self._log(DEBUG, 'stat(%r)' % path) +332 t, msg = self._request(CMD_STAT, path) +333 if t != CMD_ATTRS: +334 raise SFTPError('Expected attributes') +335 return SFTPAttributes._from_msg(msg) +
336 +
337 - def lstat(self, path): +
338 """ +339 Retrieve information about a file on the remote system, without +340 following symbolic links (shortcuts). This otherwise behaves exactly +341 the same as L{stat}. +342 +343 @param path: the filename to stat +344 @type path: str +345 @return: an object containing attributes about the given file +346 @rtype: SFTPAttributes +347 """ +348 path = self._adjust_cwd(path) +349 self._log(DEBUG, 'lstat(%r)' % path) +350 t, msg = self._request(CMD_LSTAT, path) +351 if t != CMD_ATTRS: +352 raise SFTPError('Expected attributes') +353 return SFTPAttributes._from_msg(msg) +
354 +370 +
371 - def chmod(self, path, mode): +
372 """ +373 Change the mode (permissions) of a file. The permissions are +374 unix-style and identical to those used by python's C{os.chmod} +375 function. +376 +377 @param path: path of the file to change the permissions of +378 @type path: str +379 @param mode: new permissions +380 @type mode: int +381 """ +382 path = self._adjust_cwd(path) +383 self._log(DEBUG, 'chmod(%r, %r)' % (path, mode)) +384 attr = SFTPAttributes() +385 attr.st_mode = mode +386 self._request(CMD_SETSTAT, path, attr) +
387 +
388 - def chown(self, path, uid, gid): +
389 """ +390 Change the owner (C{uid}) and group (C{gid}) of a file. As with +391 python's C{os.chown} function, you must pass both arguments, so if you +392 only want to change one, use L{stat} first to retrieve the current +393 owner and group. +394 +395 @param path: path of the file to change the owner and group of +396 @type path: str +397 @param uid: new owner's uid +398 @type uid: int +399 @param gid: new group id +400 @type gid: int +401 """ +402 path = self._adjust_cwd(path) +403 self._log(DEBUG, 'chown(%r, %r, %r)' % (path, uid, gid)) +404 attr = SFTPAttributes() +405 attr.st_uid, attr.st_gid = uid, gid +406 self._request(CMD_SETSTAT, path, attr) +
407 +
408 - def utime(self, path, times): +
409 """ +410 Set the access and modified times of the file specified by C{path}. If +411 C{times} is C{None}, then the file's access and modified times are set +412 to the current time. Otherwise, C{times} must be a 2-tuple of numbers, +413 of the form C{(atime, mtime)}, which is used to set the access and +414 modified times, respectively. This bizarre API is mimicked from python +415 for the sake of consistency -- I apologize. +416 +417 @param path: path of the file to modify +418 @type path: str +419 @param times: C{None} or a tuple of (access time, modified time) in +420 standard internet epoch time (seconds since 01 January 1970 GMT) +421 @type times: tuple(int) +422 """ +423 path = self._adjust_cwd(path) +424 if times is None: +425 times = (time.time(), time.time()) +426 self._log(DEBUG, 'utime(%r, %r)' % (path, times)) +427 attr = SFTPAttributes() +428 attr.st_atime, attr.st_mtime = times +429 self._request(CMD_SETSTAT, path, attr) +
430 +
431 - def truncate(self, path, size): +
432 """ +433 Change the size of the file specified by C{path}. This usually extends +434 or shrinks the size of the file, just like the C{truncate()} method on +435 python file objects. +436 +437 @param path: path of the file to modify +438 @type path: str +439 @param size: the new size of the file +440 @type size: int or long +441 """ +442 path = self._adjust_cwd(path) +443 self._log(DEBUG, 'truncate(%r, %r)' % (path, size)) +444 attr = SFTPAttributes() +445 attr.st_size = size +446 self._request(CMD_SETSTAT, path, attr) +
447 +470 +
471 - def normalize(self, path): +
472 """ +473 Return the normalized path (on the server) of a given path. This +474 can be used to quickly resolve symbolic links or determine what the +475 server is considering to be the "current folder" (by passing C{'.'} +476 as C{path}). +477 +478 @param path: path to be normalized +479 @type path: str +480 @return: normalized form of the given path +481 @rtype: str +482 +483 @raise IOError: if the path can't be resolved on the server +484 """ +485 path = self._adjust_cwd(path) +486 self._log(DEBUG, 'normalize(%r)' % path) +487 t, msg = self._request(CMD_REALPATH, path) +488 if t != CMD_NAME: +489 raise SFTPError('Expected name response') +490 count = msg.get_int() +491 if count != 1: +492 raise SFTPError('Realpath returned %d results' % count) +493 return _to_unicode(msg.get_string()) +
494 +
495 - def chdir(self, path): +
496 """ +497 Change the "current directory" of this SFTP session. Since SFTP +498 doesn't really have the concept of a current working directory, this +499 is emulated by paramiko. Once you use this method to set a working +500 directory, all operations on this SFTPClient object will be relative +501 to that path. +502 +503 @param path: new current working directory +504 @type path: str +505 +506 @raise IOError: if the requested path doesn't exist on the server +507 +508 @since: 1.4 +509 """ +510 self._cwd = self.normalize(path) +
511 +
512 - def getcwd(self): +
513 """ +514 Return the "current working directory" for this SFTP session, as +515 emulated by paramiko. If no directory has been set with L{chdir}, +516 this method will return C{None}. +517 +518 @return: the current working directory on the server, or C{None} +519 @rtype: str +520 +521 @since: 1.4 +522 """ +523 return self._cwd +
524 +
525 - def put(self, localpath, remotepath, callback=None): +
526 """ +527 Copy a local file (C{localpath}) to the SFTP server as C{remotepath}. +528 Any exception raised by operations will be passed through. This +529 method is primarily provided as a convenience. +530 +531 The SFTP operations use pipelining for speed. +532 +533 @param localpath: the local file to copy +534 @type localpath: str +535 @param remotepath: the destination path on the SFTP server +536 @type remotepath: str +537 @param callback: optional callback function that accepts the bytes +538 transferred so far and the total bytes to be transferred +539 (since 1.7.4) +540 @type callback: function(int, int) +541 @return: an object containing attributes about the given file +542 (since 1.7.4) +543 @rtype: SFTPAttributes +544 +545 @since: 1.4 +546 """ +547 file_size = os.stat(localpath).st_size +548 fl = file(localpath, 'rb') +549 fr = self.file(remotepath, 'wb') +550 fr.set_pipelined(True) +551 size = 0 +552 while True: +553 data = fl.read(32768) +554 if len(data) == 0: +555 break +556 fr.write(data) +557 size += len(data) +558 if callback is not None: +559 callback(size, file_size) +560 fl.close() +561 fr.close() +562 s = self.stat(remotepath) +563 if s.st_size != size: +564 raise IOError('size mismatch in put! %d != %d' % (s.st_size, size)) +565 return s +
566 +
567 - def get(self, remotepath, localpath, callback=None): +
568 """ +569 Copy a remote file (C{remotepath}) from the SFTP server to the local +570 host as C{localpath}. Any exception raised by operations will be +571 passed through. This method is primarily provided as a convenience. +572 +573 @param remotepath: the remote file to copy +574 @type remotepath: str +575 @param localpath: the destination path on the local host +576 @type localpath: str +577 @param callback: optional callback function that accepts the bytes +578 transferred so far and the total bytes to be transferred +579 (since 1.7.4) +580 @type callback: function(int, int) +581 +582 @since: 1.4 +583 """ +584 fr = self.file(remotepath, 'rb') +585 file_size = self.stat(remotepath).st_size +586 fr.prefetch() +587 fl = file(localpath, 'wb') +588 size = 0 +589 while True: +590 data = fr.read(32768) +591 if len(data) == 0: +592 break +593 fl.write(data) +594 size += len(data) +595 if callback is not None: +596 callback(size, file_size) +597 fl.close() +598 fr.close() +599 s = os.stat(localpath) +600 if s.st_size != size: +601 raise IOError('size mismatch in get! %d != %d' % (s.st_size, size)) +
602 +603 +604 ### internals... +605 +606 +
607 - def _request(self, t, *arg): +
608 num = self._async_request(type(None), t, *arg) +609 return self._read_response(num) +
610 +
611 - def _async_request(self, fileobj, t, *arg): +
612 # this method may be called from other threads (prefetch) +613 self._lock.acquire() +614 try: +615 msg = Message() +616 msg.add_int(self.request_number) +617 for item in arg: +618 if type(item) is int: +619 msg.add_int(item) +620 elif type(item) is long: +621 msg.add_int64(item) +622 elif type(item) is str: +623 msg.add_string(item) +624 elif type(item) is SFTPAttributes: +625 item._pack(msg) +626 else: +627 raise Exception('unknown type for %r type %r' % (item, type(item))) +628 num = self.request_number +629 self._expecting[num] = fileobj +630 self._send_packet(t, str(msg)) +631 self.request_number += 1 +632 finally: +633 self._lock.release() +634 return num +
635 +
636 - def _read_response(self, waitfor=None): +
637 while True: +638 try: +639 t, data = self._read_packet() +640 except EOFError, e: +641 raise SSHException('Server connection dropped: %s' % (str(e),)) +642 msg = Message(data) +643 num = msg.get_int() +644 if num not in self._expecting: +645 # might be response for a file that was closed before responses came back +646 self._log(DEBUG, 'Unexpected response #%d' % (num,)) +647 if waitfor is None: +648 # just doing a single check +649 break +650 continue +651 fileobj = self._expecting[num] +652 del self._expecting[num] +653 if num == waitfor: +654 # synchronous +655 if t == CMD_STATUS: +656 self._convert_status(msg) +657 return t, msg +658 if fileobj is not type(None): +659 fileobj._async_response(t, msg) +660 if waitfor is None: +661 # just doing a single check +662 break +663 return (None, None) +
664 +
665 - def _finish_responses(self, fileobj): +
666 while fileobj in self._expecting.values(): +667 self._read_response() +668 fileobj._check_exception() +
669 +
670 - def _convert_status(self, msg): +
671 """ +672 Raises EOFError or IOError on error status; otherwise does nothing. +673 """ +674 code = msg.get_int() +675 text = msg.get_string() +676 if code == SFTP_OK: +677 return +678 elif code == SFTP_EOF: +679 raise EOFError(text) +680 elif code == SFTP_NO_SUCH_FILE: +681 # clever idea from john a. meinel: map the error codes to errno +682 raise IOError(errno.ENOENT, text) +683 elif code == SFTP_PERMISSION_DENIED: +684 raise IOError(errno.EACCES, text) +685 else: +686 raise IOError(text) +
687 +
688 - def _adjust_cwd(self, path): +
689 """ +690 Return an adjusted path if we're emulating a "current working +691 directory" for the server. +692 """ +693 if type(path) is unicode: +694 path = path.encode('utf-8') +695 if self._cwd is None: +696 return path +697 if (len(path) > 0) and (path[0] == '/'): +698 # absolute path +699 return path +700 if self._cwd == '/': +701 return self._cwd + path +702 return self._cwd + '/' + path +
703 +704 +
705 -class SFTP (SFTPClient): +
706 "an alias for L{SFTPClient} for backwards compatability" +707 pass +
708 +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + -- cgit v1.2.3