diff options
author | Robey Pointer <robey@lag.net> | 2004-11-22 07:27:21 +0000 |
---|---|---|
committer | Robey Pointer <robey@lag.net> | 2004-11-22 07:27:21 +0000 |
commit | a8a023a2432753bc6bdfdd0011b66869642845d0 (patch) | |
tree | 7c4b11ad93f31c821d09f29f2c1d510701850583 /paramiko/sftp_handle.py | |
parent | 611d66428ed7d1885c406e490dfe8bd7a3307fea (diff) | |
download | paramiko-a8a023a2432753bc6bdfdd0011b66869642845d0.tar.gz |
[project @ Arch-1:robey@lag.net--2003-public%secsh--dev--1.0--patch-113]
sftp server support!
finally check in sftp_handle (file handle abstraction), sftp_si (server
interface), and sftp_server (server implementation) -- all of which make
a roughly 90% implementation of server-side sftp.
Diffstat (limited to 'paramiko/sftp_handle.py')
-rw-r--r-- | paramiko/sftp_handle.py | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/paramiko/sftp_handle.py b/paramiko/sftp_handle.py new file mode 100644 index 00000000..5f202969 --- /dev/null +++ b/paramiko/sftp_handle.py @@ -0,0 +1,174 @@ +#!/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. + +""" +Abstraction of an SFTP file handle (for server mode). +""" + +import os +from common import * +from sftp import * + + +class SFTPHandle (object): + """ + Abstract object representing a handle to an open file (or folder) on + the server. Each handle has a string representation used by the client + to refer to the underlying file. + """ + def __init__(self): + self.__name = None + # only for handles to folders: + self.__files = { } + self.__tell = None + + def close(self): + """ + When a client closes a file, this method is called on the handle. + Normally you would use this method to close the underlying OS level + file object(s). + """ + pass + + def read(self, offset, length): + """ + Read up to C{length} bytes from this file, starting at position + C{offset}. The offset may be a python long, since SFTP allows it + to be 64 bits. + + If the end of the file has been reached, this method may return an + empty string to signify EOF, or it may also return L{SFTP_EOF}. + + The default implementation checks for an attribute on C{self} named + C{readfile}, and if present, performs the read operation on the python + file-like object found there. (This is meant as a time saver for the + common case where you are wrapping a python file object.) + + @param offset: position in the file to start reading from. + @type offset: int or long + @param length: number of bytes to attempt to read. + @type length: int + @return: data read from the file, or an SFTP error code. + @rtype: str + """ + if not hasattr(self, 'readfile') or (self.readfile is None): + return SFTP_OP_UNSUPPORTED + try: + if self.__tell is None: + self.__tell = self.readfile.tell() + if offset != self.__tell: + self.readfile.seek(offset) + self.__tell = offset + data = self.readfile.read(length) + except IOError, e: + self.__tell = None + return SFTPServer.convert_errno(e.errno) + self.__tell += len(data) + return data + + def write(self, offset, data): + """ + Write C{data} into this file at position C{offset}. Extending the + file past its original end is expected. Unlike python's normal + C{write()} methods, this method cannot do a partial write: it must + write all of C{data} or else return an error. + + The default implementation checks for an attribute on C{self} named + C{writefile}, and if present, performs the write operation on the + python file-like object found there. The attribute is named + differently from C{readfile} to make it easy to implement read-only + (or write-only) files, but if both attributes are present, they should + refer to the same file. + + @param offset: position in the file to start reading from. + @type offset: int or long + @param data: data to write into the file. + @type data: str + @return: an SFTP error code like L{SFTP_OK}. + """ + if not hasattr(self, 'writefile') or (self.writefile is None): + return SFTP_OP_UNSUPPORTED + try: + if self.__tell is None: + self.__tell = self.writefile.tell() + if offset != self.__tell: + self.writefile.seek(offset) + self.__tell = offset + self.writefile.write(data) + except IOError, e: + self.__tell = None + return SFTPServer.convert_errno(e.errno) + self.__tell += len(data) + return SFTP_OK + + def stat(self): + """ + Return an L{SFTPAttributes} object referring to this open file, or an + error code. This is equivalent to L{SFTPServerInterface.stat}, except + it's called on an open file instead of a path. + + @return: an attributes object for the given file, or an SFTP error + code (like L{SFTP_PERMISSION_DENIED}). + @rtype: L{SFTPAttributes} I{or error code} + """ + return SFTP_OP_UNSUPPORTED + + def chattr(self, attr): + """ + Change the attributes of this file. The C{attr} object will contain + only those fields provided by the client in its request, so you should + check for the presence of fields before using them. + + @param attr: the attributes to change on this file. + @type attr: L{SFTPAttributes} + @return: an error code like L{SFTP_OK}. + @rtype: int + """ + return SFTP_OP_UNSUPPORTED + + + ### internals... + + + def _set_files(self, files): + """ + Used by the SFTP server code to cache a directory listing. (In + the SFTP protocol, listing a directory is a multi-stage process + requiring a temporary handle.) + """ + self.__files = files + + def _get_next_files(self): + """ + Used by the SFTP server code to retreive a cached directory + listing. + """ + fnlist = self.__files[:16] + self.__files = self.__files[16:] + return fnlist + + def _get_name(self): + return self.__name + + def _set_name(self, name): + self.__name = name + + +from sftp_server import SFTPServer |