diff options
Diffstat (limited to 'paramiko/sftp_file.py')
-rw-r--r-- | paramiko/sftp_file.py | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/paramiko/sftp_file.py b/paramiko/sftp_file.py new file mode 100644 index 00000000..f01d384d --- /dev/null +++ b/paramiko/sftp_file.py @@ -0,0 +1,137 @@ +#!/usr/bin/python + +# Copyright (C) 2003-2004 Robey Pointer <robey@lag.net> +# +# This file is part of paramiko. +# +# Paramiko is free software; you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation; either version 2.1 of the License, or (at your option) +# any later version. +# +# Paramiko is distrubuted in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Paramiko; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + +""" +L{SFTPFile} +""" + +from common import * +from sftp import * +from file import BufferedFile +from sftp_attr import SFTPAttributes + + +class SFTPFile (BufferedFile): + """ + Proxy object for a file on the remote server, in client mode SFTP. + """ + + # Some sftp servers will choke if you send read/write requests larger than + # this size. + MAX_REQUEST_SIZE = 32768 + + def __init__(self, sftp, handle, mode='r', bufsize=-1): + BufferedFile.__init__(self) + self.sftp = sftp + self.handle = handle + BufferedFile._set_mode(self, mode, bufsize) + + def close(self): + BufferedFile.close(self) + self.sftp._request(CMD_CLOSE, self.handle) + + def _read(self, size): + size = min(size, self.MAX_REQUEST_SIZE) + t, msg = self.sftp._request(CMD_READ, self.handle, long(self._realpos), int(size)) + if t != CMD_DATA: + raise SFTPError('Expected data') + return msg.get_string() + + def _write(self, data): + offset = 0 + while offset < len(data): + chunk = min(len(data) - offset, self.MAX_REQUEST_SIZE) + t, msg = self.sftp._request(CMD_WRITE, self.handle, long(self._realpos + offset), + str(data[offset : offset + chunk])) + offset += chunk + return len(data) + + def settimeout(self, timeout): + """ + Set a timeout on read/write operations on the underlying socket or + ssh L{Channel}. + + @see: L{Channel.settimeout} + @param timeout: seconds to wait for a pending read/write operation + before raising C{socket.timeout}, or C{None} for no timeout + @type timeout: float + """ + self.sock.settimeout(timeout) + + def gettimeout(self): + """ + Returns the timeout in seconds (as a float) associated with the socket + or ssh L{Channel} used for this file. + + @see: L{Channel.gettimeout} + @rtype: float + """ + return self.sock.gettimeout() + + def setblocking(self, blocking): + """ + Set blocking or non-blocking mode on the underiying socket or ssh + L{Channel}. + + @see: L{Channel.setblocking} + @param blocking: 0 to set non-blocking mode; non-0 to set blocking + mode. + @type blocking: int + """ + self.sock.setblocking(blocking) + + def seek(self, offset, whence=0): + self.flush() + if whence == self.SEEK_SET: + self._realpos = self._pos = offset + elif whence == self.SEEK_CUR: + self._realpos += offset + self._pos += offset + else: + self._realpos = self._pos = self._get_size() + offset + self._rbuffer = '' + + def stat(self): + """ + Retrieve information about this file from the remote system. This is + exactly like L{SFTP.stat}, except that it operates on an already-open + file. + + @return: an object containing attributes about this file. + @rtype: SFTPAttributes + """ + t, msg = self.sftp._request(CMD_FSTAT, self.handle) + if t != CMD_ATTRS: + raise SFTPError('Expected attributes') + return SFTPAttributes._from_msg(msg) + + + ### internals... + + + def _get_size(self): + t, msg = self.sftp._request(CMD_FSTAT, self.handle) + if t != CMD_ATTRS: + raise SFTPError('Expected attrs') + attr = SFTPAttributes._from_msg(msg) + try: + return attr.st_size + except: + return 0 |