예제 #1
0
 def _process_fsetstat(self, request_number, msg):
     handle = msg.get_binary()
     attr = SFTPAttributes._from_msg(msg)
     if handle not in self.file_table:
         self._response(request_number, SFTP_BAD_MESSAGE, 'Invalid handle')
         return
     self._send_status(request_number, self.file_table[handle].chattr(attr))
예제 #2
0
 def listdir_ex(self, path):
     path = self._adjust_cwd(path)
     basename = os.path.basename(path)
     dir = os.path.dirname(path)
     t, msg = self._request(CMD_OPENDIR, dir)
     if t != CMD_HANDLE:
         raise SFTPError('Expected handle')
     handle = msg.get_string()
     filelist = []
     while True:
         try:
             t, msg = self._request(CMD_READDIR, handle)
         except EOFError:
             # done with handle
             break
         if t != CMD_NAME:
             raise SFTPError('Expected name response')
         count = msg.get_int()
         for i in range(count):
             filename = _to_unicode(msg.get_string())
             longname = _to_unicode(msg.get_string())
             attr = SFTPAttributes._from_msg(msg, filename, longname)
             if (filename != '.') and (
                     filename != '..') and filename.startswith(basename):
                 filelist.append(filename)
     self._request(CMD_CLOSE, handle)
     return filelist
예제 #3
0
    def stat(self, path):
        """
        Retrieve information about a file on the remote system.  The return
        value is an object whose attributes correspond to the attributes of
        Python's ``stat`` structure as returned by ``os.stat``, except that it
        contains fewer fields.  An SFTP server may return as much or as little
        info as it wants, so the results may vary from server to server.

        Unlike a Python `python:stat` object, the result may not be accessed as
        a tuple.  This is mostly due to the author's slack factor.

        The fields supported are: ``st_mode``, ``st_size``, ``st_uid``,
        ``st_gid``, ``st_atime``, and ``st_mtime``.

        :param str path: the filename to stat
        :return:
            an `.SFTPAttributes` object containing attributes about the given
            file
        """
        path = self._adjust_cwd(path)
        self._log(DEBUG, 'stat({!r})'.format(path))
        t, msg = self._request(CMD_STAT, path)
        if t != CMD_ATTRS:
            raise SFTPError('Expected attributes')
        return SFTPAttributes._from_msg(msg)
예제 #4
0
    def stat(self, path):
        """
        Retrieve information about a file on the remote system.  The return
        value is an object whose attributes correspond to the attributes of
        python's C{stat} structure as returned by C{os.stat}, except that it
        contains fewer fields.  An SFTP server may return as much or as little
        info as it wants, so the results may vary from server to server.

        Unlike a python C{stat} object, the result may not be accessed as a
        tuple.  This is mostly due to the author's slack factor.

        The fields supported are: C{st_mode}, C{st_size}, C{st_uid}, C{st_gid},
        C{st_atime}, and C{st_mtime}.

        @param path: the filename to stat
        @type path: str
        @return: an object containing attributes about the given file
        @rtype: SFTPAttributes
        """
        path = self._adjust_cwd(path)
        self._log(DEBUG, 'stat(%r)' % path)
        t, msg = self._request(CMD_STAT, path)
        if t != CMD_ATTRS:
            raise SFTPError('Expected attributes')
        return SFTPAttributes._from_msg(msg)
예제 #5
0
    def stat(self, path):
        """
        Retrieve information about a file on the remote system.  The return
        value is an object whose attributes correspond to the attributes of
        Python's ``stat`` structure as returned by ``os.stat``, except that it
        contains fewer fields.  An SFTP server may return as much or as little
        info as it wants, so the results may vary from server to server.

        Unlike a Python `python:stat` object, the result may not be accessed as
        a tuple.  This is mostly due to the author's slack factor.

        The fields supported are: ``st_mode``, ``st_size``, ``st_uid``,
        ``st_gid``, ``st_atime``, and ``st_mtime``.

        :param str path: the filename to stat
        :return:
            an `.SFTPAttributes` object containing attributes about the given
            file
        """
        path = self._adjust_cwd(path)
        self._log(DEBUG, 'stat(%r)' % path)
        t, msg = self._request(CMD_STAT, path)
        if t != CMD_ATTRS:
            raise SFTPError('Expected attributes')
        return SFTPAttributes._from_msg(msg)
예제 #6
0
    def listdir_attr(self, path='.'):
        """
        Return a list containing L{SFTPAttributes} objects corresponding to
        files in the given C{path}.  The list is in arbitrary order.  It does
        not include the special entries C{'.'} and C{'..'} even if they are
        present in the folder.

        @param path: path to list (defaults to C{'.'})
        @type path: str
        @return: list of attributes
        @rtype: list of L{SFTPAttributes}
        
        @since: 1.2
        """
        path = self._adjust_cwd(path)
        t, msg = self._request(CMD_OPENDIR, path)
        if t != CMD_HANDLE:
            raise SFTPError('Expected handle')
        handle = msg.get_string()
        filelist = []
        while True:
            try:
                t, msg = self._request(CMD_READDIR, handle)
            except EOFError, e:
                # done with handle
                break
            if t != CMD_NAME:
                raise SFTPError('Expected name response')
            count = msg.get_int()
            for i in range(count):
                filename = _to_unicode(msg.get_string())
                longname = _to_unicode(msg.get_string())
                attr = SFTPAttributes._from_msg(msg, filename)
                if (filename != '.') and (filename != '..'):
                    filelist.append(attr)
예제 #7
0
    def listdir_attr(self, path='.'):
        """
        Return a list containing L{SFTPAttributes} objects corresponding to
        files in the given C{path}.  The list is in arbitrary order.  It does
        not include the special entries C{'.'} and C{'..'} even if they are
        present in the folder.

        @param path: path to list (defaults to C{'.'})
        @type path: str
        @return: list of attributes
        @rtype: list of L{SFTPAttributes}
        
        @since: 1.2
        """
        path = self._adjust_cwd(path)
        t, msg = self._request(CMD_OPENDIR, path)
        if t != CMD_HANDLE:
            raise SFTPError('Expected handle')
        handle = msg.get_string()
        filelist = []
        while True:
            try:
                t, msg = self._request(CMD_READDIR, handle)
            except EOFError, e:
                # done with handle
                break
            if t != CMD_NAME:
                raise SFTPError('Expected name response')
            count = msg.get_int()
            for i in range(count):
                filename = _to_unicode(msg.get_string())
                longname = _to_unicode(msg.get_string())
                attr = SFTPAttributes._from_msg(msg, filename)
                if (filename != '.') and (filename != '..'):
                    filelist.append(attr)
예제 #8
0
    def fstat(self, handle):
        """
        Get stats about a file on the remote server via it's handle

        """
        log.debug(f"stat request: [{handle}]")
        resp_type, msg = self._blocking_request(CMD_FSTAT, handle)
        if resp_type != CMD_ATTRS:
            raise SFTPError("Expected back attributes")
        return SFTPAttributes._from_msg(msg)
예제 #9
0
    def listdir_iter(self, path='.', read_aheads=10):
        """
        Generator version of `.listdir_attr`.

        See the API docs for `.listdir_attr` for overall details.

        This function adds one more kwarg on top of `.listdir_attr`:
        ``read_aheads``, an integer controlling how many
        ``SSH_FXP_READDIR`` requests are made to the server. The default
        should suffice for most file listings as each request/response cycle
        may contain multiple files (dependent on server implementation.)

        .. versionadded:: 1.15
        """
        path = self._adjust_cwd(path)
        self._log(DEBUG, "listdir(%r)", path)
        t, msg = self._request(CMD_OPENDIR, path)

        if t != CMD_HANDLE:
            raise SFTPError('Expected handle')

        handle = msg.get_string()

        while True:
            nums = list()
            results = list()
            try:
                # Send out a bunch of readdir requests so that we can read the responses later
                # Section 6.7 of the SSH file transfer RFC explains this
                # http://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt
                for i in range(read_aheads):
                    num = self._async_request(type(None), CMD_READDIR, handle)
                    nums.append(num)

                # need to read whole batch before yielding any
                for num in nums:
                    t, msg = self._read_response(num)
                    count = msg.get_int()
                    for i in range(count):
                        filename = msg.get_text()
                        longname = msg.get_text()
                        attr = SFTPAttributes._from_msg(
                            msg, filename, longname)
                        if (filename != '.') and (filename != '..'):
                            results.append(attr)

                for a in results:
                    yield a

            except EOFError:
                self._request(CMD_CLOSE, handle)
                for a in results:
                    yield a
                return
예제 #10
0
    def stat(self):
        """
        Retrieve information about this file from the remote system.  This is
        exactly like `.SFTPClient.stat`, except that it operates on an
        already-open file.

        :return: an `.SFTPAttributes` object containing attributes about this file.
        """
        t, msg = self.sftp._request(CMD_FSTAT, self.handle)
        if t != CMD_ATTRS:
            raise SFTPError('Expected attributes')
        return SFTPAttributes._from_msg(msg)
예제 #11
0
    def stat(self):
        """
        Retrieve information about this file from the remote system.  This is
        exactly like `.SFTPClient.stat`, except that it operates on an
        already-open file.

        :return: an `.SFTPAttributes` object containing attributes about this file.
        """
        t, msg = self.sftp._request(CMD_FSTAT, self.handle)
        if t != CMD_ATTRS:
            raise SFTPError('Expected attributes')
        return SFTPAttributes._from_msg(msg)
예제 #12
0
    def lstat(self, path):
        """
        Retrieve information about a file on the remote system, without
        following symbolic links (shortcuts).  This otherwise behaves exactly
        the same as L{stat}.

        @param path: the filename to stat.
        @type path: string
        @return: an object containing attributes about the given file.
        @rtype: SFTPAttributes
        """
        path = self._adjust_cwd(path)
        t, msg = self._request(CMD_LSTAT, path)
        if t != CMD_ATTRS:
            raise SFTPError('Expected attributes')
        return SFTPAttributes._from_msg(msg)
예제 #13
0
    def lstat(self, path):
        """
        Retrieve information about a file on the remote system, without
        following symbolic links (shortcuts).  This otherwise behaves exactly
        the same as L{stat}.

        @param path: the filename to stat.
        @type path: string
        @return: an object containing attributes about the given file.
        @rtype: SFTPAttributes
        """
        path = self._adjust_cwd(path)
        t, msg = self._request(CMD_LSTAT, path)
        if t != CMD_ATTRS:
            raise SFTPError('Expected attributes')
        return SFTPAttributes._from_msg(msg)
예제 #14
0
    def listdir_attr(self, path=".", encoding="utf-8", path_encoding='utf-8'):
        """
        Return a list containing `.SFTPAttributes` objects corresponding to
        files in the given ``path``.  The list is in arbitrary order.  It does
        not include the special entries ``'.'`` and ``'..'`` even if they are
        present in the folder.

        The returned `.SFTPAttributes` objects will each have an additional
        field: ``longname``, which may contain a formatted string of the file's
        attributes, in unix format.  The content of this string will probably
        depend on the SFTP server implementation.
        
        :param str encoding: the byte decode format (defauls to ```'utf-8'```),used to decode filename(under the path) byte ,eg: ```'中文目录'```
        :param str encoding: 设置服务器中返回byte的解码格式,当服务器返回内容中有使用其他格式编码的内容时(如目录下包含有中文)需要设置此参数,参数值建议为服务器使用的编码格式,如: 'GB180303'编码的中文,此时建议使用方式: listdir_attr(path='/test', encoding='GB18030')
        :param str path: path to list (defaults to ``'.'``)
        :param str path_encoding: the path parameter encode format (defauls to ```'utf-8'```),eg: listdir_attr(path='中文目录'.encode('GB18030'), path_encoding='GB18030')
        :param str path_encoding: 当需要查看的路径path在服务器上的编码格式不是utf-8时需要设置此参数,参数值为服务器所使用的编码格式,如需要查看的路径是'/test/中文路径',而服务器使用的编码格式是GB18030, 此时就建议如下使用方式: listdir_attr(path="/test/中文路径".encode("GB18030"), path_encoding='GB18030')
        :return: list of `.SFTPAttributes` objects

        .. versionadded:: 1.2
        """
        if path == '.' and self.getcwd() is not None:
            path = self.getcwd().encode(path_encoding)
        path = self._adjust_cwd(path)
        self._log(DEBUG, "listdir({!r})".format(path))
        t, msg = self._request(CMD_OPENDIR, path)
        if t != CMD_HANDLE:
            raise SFTPError("Expected handle")
        handle = msg.get_binary()
        filelist = []
        while True:
            try:
                t, msg = self._request(CMD_READDIR, handle)
            except EOFError:
                # done with handle
                break
            if t != CMD_NAME:
                raise SFTPError("Expected name response")
            count = msg.get_int()
            for i in range(count):
                filename = msg.get_text(encoding)
                longname = msg.get_text(encoding)
                attr = SFTPAttributes._from_msg(msg, filename, longname)
                if (filename != ".") and (filename != ".."):
                    filelist.append(attr)
        self._request(CMD_CLOSE, handle)
        return filelist
예제 #15
0
    def lstat(self, path):
        """
        Retrieve information about a file on the remote system, without
        following symbolic links (shortcuts).  This otherwise behaves exactly
        the same as `stat`.

        :param str path: the filename to stat
        :return:
            an `.SFTPAttributes` object containing attributes about the given
            file
        """
        path = self._adjust_cwd(path)
        self._log(DEBUG, 'lstat(%r)' % path)
        t, msg = self._request(CMD_LSTAT, path)
        if t != CMD_ATTRS:
            raise SFTPError('Expected attributes')
        return SFTPAttributes._from_msg(msg)
예제 #16
0
    def lstat(self, path):
        """
        Retrieve information about a file on the remote system, without
        following symbolic links (shortcuts).  This otherwise behaves exactly
        the same as `stat`.

        :param str path: the filename to stat
        :return:
            an `.SFTPAttributes` object containing attributes about the given
            file
        """
        path = self._adjust_cwd(path)
        self._log(DEBUG, 'lstat(%r)' % path)
        t, msg = self._request(CMD_LSTAT, path)
        if t != CMD_ATTRS:
            raise SFTPError('Expected attributes')
        return SFTPAttributes._from_msg(msg)
예제 #17
0
    def listdir_attr(self, path='.'):
        """
        Return a list containing L{SFTPAttributes} objects corresponding to
        files in the given C{path}.  The list is in arbitrary order.  It does
        not include the special entries C{'.'} and C{'..'} even if they are
        present in the folder.

        The returned L{SFTPAttributes} objects will each have an additional
        field: C{longname}, which may contain a formatted string of the file's
        attributes, in unix format.  The content of this string will probably
        depend on the SFTP server implementation.

        @param path: path to list (defaults to C{'.'})
        @type path: str
        @return: list of attributes
        @rtype: list of L{SFTPAttributes}

        @since: 1.2
        """
        path = self._adjust_cwd(path)
        self._log(DEBUG, 'listdir(%r)' % path)
        t, msg = self._request(CMD_OPENDIR, path)
        if t != CMD_HANDLE:
            raise SFTPError('Expected handle')
        handle = msg.get_binary()
        filelist = []
        while True:
            try:
                t, msg = self._request(CMD_READDIR, handle)
            except EOFError:
                # done with handle
                break
            if t != CMD_NAME:
                raise SFTPError('Expected name response')
            count = msg.get_int()
            for i in range(count):
                filename = msg.get_text()
                longname = msg.get_text()
                attr = SFTPAttributes._from_msg(msg, filename, longname)
                if (filename != '.') and (filename != '..'):
                    filelist.append(attr)
        self._request(CMD_CLOSE, handle)
        return filelist
예제 #18
0
    def listdir_attr(self, path='.'):
        """
        Return a list containing L{SFTPAttributes} objects corresponding to
        files in the given C{path}.  The list is in arbitrary order.  It does
        not include the special entries C{'.'} and C{'..'} even if they are
        present in the folder.

        The returned L{SFTPAttributes} objects will each have an additional
        field: C{longname}, which may contain a formatted string of the file's
        attributes, in unix format.  The content of this string will probably
        depend on the SFTP server implementation.

        @param path: path to list (defaults to C{'.'})
        @type path: str
        @return: list of attributes
        @rtype: list of L{SFTPAttributes}

        @since: 1.2
        """
        path = self._adjust_cwd(path)
        self._log(DEBUG, 'listdir(%r)' % path)
        t, msg = self._request(CMD_OPENDIR, path)
        if t != CMD_HANDLE:
            raise SFTPError('Expected handle')
        handle = msg.get_binary()
        filelist = []
        while True:
            try:
                t, msg = self._request(CMD_READDIR, handle)
            except EOFError:
                # done with handle
                break
            if t != CMD_NAME:
                raise SFTPError('Expected name response')
            count = msg.get_int()
            for i in range(count):
                filename = msg.get_text()
                longname = msg.get_text()
                attr = SFTPAttributes._from_msg(msg, filename, longname)
                if (filename != '.') and (filename != '..'):
                    filelist.append(attr)
        self._request(CMD_CLOSE, handle)
        return filelist
예제 #19
0
    def listdir_attr(self, path="."):
        """
        Return a list containing `.SFTPAttributes` objects corresponding to
        files in the given ``path``.  The list is in arbitrary order.  It does
        not include the special entries ``'.'`` and ``'..'`` even if they are
        present in the folder.

        The returned `.SFTPAttributes` objects will each have an additional
        field: ``longname``, which may contain a formatted string of the file's
        attributes, in unix format.  The content of this string will probably
        depend on the SFTP server implementation.

        :param str path: path to list (defaults to ``'.'``)
        :return: list of `.SFTPAttributes` objects

        .. versionadded:: 1.2
        """
        path = self._adjust_cwd(path)
        self._log(DEBUG, "listdir({!r})".format(path))
        t, msg = self._request(CMD_OPENDIR, path)
        if t != CMD_HANDLE:
            raise SFTPError("Expected handle")
        handle = msg.get_binary()
        filelist = []
        while True:
            try:
                t, msg = self._request(CMD_READDIR, handle)
            except EOFError:
                # done with handle
                break
            if t != CMD_NAME:
                raise SFTPError("Expected name response")
            count = msg.get_int()
            for i in range(count):
                filename = msg.get_text()
                longname = msg.get_text()
                attr = SFTPAttributes._from_msg(msg, filename, longname)
                if (filename != ".") and (filename != ".."):
                    filelist.append(attr)
        self._request(CMD_CLOSE, handle)
        return filelist
예제 #20
0
    def listdir_attr(self, path='.'):
        """
        Return a list containing `.SFTPAttributes` objects corresponding to
        files in the given ``path``.  The list is in arbitrary order.  It does
        not include the special entries ``'.'`` and ``'..'`` even if they are
        present in the folder.

        The returned `.SFTPAttributes` objects will each have an additional
        field: ``longname``, which may contain a formatted string of the file's
        attributes, in unix format.  The content of this string will probably
        depend on the SFTP server implementation.

        :param str path: path to list (defaults to ``'.'``)
        :return: list of `.SFTPAttributes` objects

        .. versionadded:: 1.2
        """
        path = self._adjust_cwd(path)
        self._log(DEBUG, 'listdir({!r})'.format(path))
        t, msg = self._request(CMD_OPENDIR, path)
        if t != CMD_HANDLE:
            raise SFTPError('Expected handle')
        handle = msg.get_binary()
        filelist = []
        while True:
            try:
                t, msg = self._request(CMD_READDIR, handle)
            except EOFError:
                # done with handle
                break
            if t != CMD_NAME:
                raise SFTPError('Expected name response')
            count = msg.get_int()
            for i in range(count):
                filename = msg.get_text()
                longname = msg.get_text()
                attr = SFTPAttributes._from_msg(msg, filename, longname)
                if (filename != '.') and (filename != '..'):
                    filelist.append(attr)
        self._request(CMD_CLOSE, handle)
        return filelist
예제 #21
0
    def stat(self, path):
        """
        Retrieve information about a file on the remote system.  The return
        value is an object whose attributes correspond to the attributes of
        python's C{stat} structure as returned by C{os.stat}, except that it
        contains fewer fields.  An SFTP server may return as much or as little
        info as it wants, so the results may vary from server to server.

        Unlike a python C{stat} object, the result may not be accessed as a
        tuple.  This is mostly due to the author's slack factor.

        The fields supported are: C{st_mode}, C{st_size}, C{st_uid}, C{st_gid},
        C{st_atime}, and C{st_mtime}.

        @param path: the filename to stat.
        @type path: string
        @return: an object containing attributes about the given file.
        @rtype: SFTPAttributes
        """
        path = self._adjust_cwd(path)
        t, msg = self._request(CMD_STAT, path)
        if t != CMD_ATTRS:
            raise SFTPError('Expected attributes')
        return SFTPAttributes._from_msg(msg)
예제 #22
0
 def _process(self, t, request_number, msg):
     self._log(DEBUG, 'Request: %s' % CMD_NAMES[t])
     if t == CMD_OPEN:
         path = msg.get_text()
         flags = self._convert_pflags(msg.get_int())
         attr = SFTPAttributes._from_msg(msg)
         self._send_handle_response(request_number,
                                    self.server.open(path, flags, attr))
     elif t == CMD_CLOSE:
         handle = msg.get_binary()
         if handle in self.folder_table:
             del self.folder_table[handle]
             self._send_status(request_number, SFTP_OK)
             return
         if handle in self.file_table:
             self.file_table[handle].close()
             del self.file_table[handle]
             self._send_status(request_number, SFTP_OK)
             return
         self._send_status(request_number, SFTP_BAD_MESSAGE,
                           'Invalid handle')
     elif t == CMD_READ:
         handle = msg.get_binary()
         offset = msg.get_int64()
         length = msg.get_int()
         if handle not in self.file_table:
             self._send_status(request_number, SFTP_BAD_MESSAGE,
                               'Invalid handle')
             return
         data = self.file_table[handle].read(offset, length)
         if isinstance(data, (bytes_types, string_types)):
             if len(data) == 0:
                 self._send_status(request_number, SFTP_EOF)
             else:
                 self._response(request_number, CMD_DATA, data)
         else:
             self._send_status(request_number, data)
     elif t == CMD_WRITE:
         handle = msg.get_binary()
         offset = msg.get_int64()
         data = msg.get_binary()
         if handle not in self.file_table:
             self._send_status(request_number, SFTP_BAD_MESSAGE,
                               'Invalid handle')
             return
         self._send_status(request_number,
                           self.file_table[handle].write(offset, data))
     elif t == CMD_REMOVE:
         path = msg.get_text()
         self._send_status(request_number, self.server.remove(path))
     elif t == CMD_RENAME:
         oldpath = msg.get_text()
         newpath = msg.get_text()
         self._send_status(request_number,
                           self.server.rename(oldpath, newpath))
     elif t == CMD_MKDIR:
         path = msg.get_text()
         attr = SFTPAttributes._from_msg(msg)
         self._send_status(request_number, self.server.mkdir(path, attr))
     elif t == CMD_RMDIR:
         path = msg.get_text()
         self._send_status(request_number, self.server.rmdir(path))
     elif t == CMD_OPENDIR:
         path = msg.get_text()
         self._open_folder(request_number, path)
         return
     elif t == CMD_READDIR:
         handle = msg.get_binary()
         if handle not in self.folder_table:
             self._send_status(request_number, SFTP_BAD_MESSAGE,
                               'Invalid handle')
             return
         folder = self.folder_table[handle]
         self._read_folder(request_number, folder)
     elif t == CMD_STAT:
         path = msg.get_text()
         resp = self.server.stat(path)
         if issubclass(type(resp), SFTPAttributes):
             self._response(request_number, CMD_ATTRS, resp)
         else:
             self._send_status(request_number, resp)
     elif t == CMD_LSTAT:
         path = msg.get_text()
         resp = self.server.lstat(path)
         if issubclass(type(resp), SFTPAttributes):
             self._response(request_number, CMD_ATTRS, resp)
         else:
             self._send_status(request_number, resp)
     elif t == CMD_FSTAT:
         handle = msg.get_binary()
         if handle not in self.file_table:
             self._send_status(request_number, SFTP_BAD_MESSAGE,
                               'Invalid handle')
             return
         resp = self.file_table[handle].stat()
         if issubclass(type(resp), SFTPAttributes):
             self._response(request_number, CMD_ATTRS, resp)
         else:
             self._send_status(request_number, resp)
     elif t == CMD_SETSTAT:
         path = msg.get_text()
         attr = SFTPAttributes._from_msg(msg)
         self._send_status(request_number, self.server.chattr(path, attr))
     elif t == CMD_FSETSTAT:
         handle = msg.get_binary()
         attr = SFTPAttributes._from_msg(msg)
         if handle not in self.file_table:
             self._response(request_number, SFTP_BAD_MESSAGE,
                            'Invalid handle')
             return
         self._send_status(request_number,
                           self.file_table[handle].chattr(attr))
     elif t == CMD_READLINK:
         path = msg.get_text()
         resp = self.server.readlink(path)
         if isinstance(resp, (bytes_types, string_types)):
             self._response(request_number, CMD_NAME, 1, resp, '',
                            SFTPAttributes())
         else:
             self._send_status(request_number, resp)
     elif t == CMD_SYMLINK:
         # the sftp 2 draft is incorrect here!  path always follows target_path
         target_path = msg.get_text()
         path = msg.get_text()
         self._send_status(request_number,
                           self.server.symlink(target_path, path))
     elif t == CMD_REALPATH:
         path = msg.get_text()
         rpath = self.server.canonicalize(path)
         self._response(request_number, CMD_NAME, 1, rpath, '',
                        SFTPAttributes())
     elif t == CMD_EXTENDED:
         tag = msg.get_text()
         if tag == 'check-file':
             self._check_file(request_number, msg)
         else:
             self._send_status(request_number, SFTP_OP_UNSUPPORTED)
     else:
         self._send_status(request_number, SFTP_OP_UNSUPPORTED)
예제 #23
0
 def _process_open(self, request_number, msg):
     path = msg.get_text()
     flags = self._convert_pflags(msg.get_int())
     attr = SFTPAttributes._from_msg(msg)
     self._send_handle_response(request_number,
                                self.server.open(path, flags, attr))
예제 #24
0
 def _process_setstat(self, request_number, msg):
     path = msg.get_text()
     attr = SFTPAttributes._from_msg(msg)
     self._send_status(request_number, self.server.chattr(path, attr))
예제 #25
0
    def listdir_iter(self, path='.', read_aheads=50):
        """
        Generator version of `.listdir_attr`.

        See the API docs for `.listdir_attr` for overall details.

        This function adds one more kwarg on top of `.listdir_attr`:
        ``read_aheads``, an integer controlling how many
        ``SSH_FXP_READDIR`` requests are made to the server. The default of 50
        should suffice for most file listings as each request/response cycle
        may contain multiple files (dependent on server implementation.)

        .. versionadded:: 1.15
        """
        path = self._adjust_cwd(path)
        self._log(DEBUG, 'listdir(%r)' % path)
        t, msg = self._request(CMD_OPENDIR, path)

        if t != CMD_HANDLE:
            raise SFTPError('Expected handle')

        handle = msg.get_string()

        nums = list()
        while True:
            try:
                # Send out a bunch of readdir requests so that we can read the
                # responses later on Section 6.7 of the SSH file transfer RFC
                # explains this
                # http://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt
                for i in range(read_aheads):
                    num = self._async_request(type(None), CMD_READDIR, handle)
                    nums.append(num)

                # For each of our sent requests
                # Read and parse the corresponding packets
                # If we're at the end of our queued requests, then fire off
                # some more requests
                # Exit the loop when we've reached the end of the directory
                # handle
                for num in nums:
                    t, pkt_data = self._read_packet()
                    msg = Message(pkt_data)
                    new_num = msg.get_int()
                    if num == new_num:
                        if t == CMD_STATUS:
                            self._convert_status(msg)
                    count = msg.get_int()
                    for i in range(count):
                        filename = msg.get_text()
                        longname = msg.get_text()
                        attr = SFTPAttributes._from_msg(
                            msg, filename, longname)
                        if (filename != '.') and (filename != '..'):
                            yield attr

                # If we've hit the end of our queued requests, reset nums.
                nums = list()

            except EOFError:
                self._request(CMD_CLOSE, handle)
                return
예제 #26
0
    def listdir_iter(self, path='.', read_ahead_requests=50):
        """
        Generator yielding L{SFTPAttributes} objects corresponding to
        files in the given C{path}.  Files are yielded in arbitrary order.  It does
        not include the special entries C{'.'} and C{'..'} even if they are
        present in the folder.

        The returned L{SFTPAttributes} objects will each have an additional
        field: C{longname}, which may contain a formatted string of the file's
        attributes, in unix format.  The content of this string will probably
        depend on the SFTP server implementation.

        @param path: path to list (defaults to C{'.'})
        @type path: str
        @return: Yields L{SFTPAttributes}
        @rtype: L{SFTPAttributes}

        @since: 1.9
        """
        path = self._adjust_cwd(path)
        self._log(DEBUG, 'listdir(%r)' % path)
        t, msg = self._request(CMD_OPENDIR, path)

        if t != CMD_HANDLE:
            raise SFTPError('Expected handle')

        handle = msg.get_string()

        nums = list()
        while True:
            try:
                # Send out a bunch of readdir requests so that we can read the responses later on
                # Section 6.7 of the SSH file transfer RFC explains this
                # http://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt
                for i in range(read_ahead_requests):
                    num = self._async_request(type(None), CMD_READDIR, handle)
                    nums.append(num)


                # For each of our sent requests
                # Read and parse the corresponding packets
                # If we're at the end of our queued requests, then fire off some more requests
                # Exit the loop when we've reached the end of the directory handle
                for num in nums:
                    t, pkt_data = self._read_packet()
                    msg = Message(pkt_data)
                    new_num = msg.get_int()
                    if num == new_num:
                        if t == CMD_STATUS:
                            self._convert_status(msg)
                    count = msg.get_int()
                    for i in range(count):
                        filename = msg.get_string()
                        longname = msg.get_string()
                        attr = SFTPAttributes._from_msg(msg, filename, longname)
                        if (filename != '.') and (filename != '..'):
                            yield attr

                # If we've hit the end of our queued requests, reset nums.
                nums = list()

            except EOFError:
                self._request(CMD_CLOSE, handle)
                return
예제 #27
0
 def _process(self, t, request_number, msg):
     self._log(DEBUG, 'Request: %s' % CMD_NAMES[t])
     if t == CMD_OPEN:
         path = msg.get_text()
         flags = self._convert_pflags(msg.get_int())
         attr = SFTPAttributes._from_msg(msg)
         self._send_handle_response(request_number, self.server.open(path, flags, attr))
     elif t == CMD_CLOSE:
         handle = msg.get_binary()
         if handle in self.folder_table:
             del self.folder_table[handle]
             self._send_status(request_number, SFTP_OK)
             return
         if handle in self.file_table:
             self.file_table[handle].close()
             del self.file_table[handle]
             self._send_status(request_number, SFTP_OK)
             return
         self._send_status(request_number, SFTP_BAD_MESSAGE, 'Invalid handle')
     elif t == CMD_READ:
         handle = msg.get_binary()
         offset = msg.get_int64()
         length = msg.get_int()
         if handle not in self.file_table:
             self._send_status(request_number, SFTP_BAD_MESSAGE, 'Invalid handle')
             return
         data = self.file_table[handle].read(offset, length)
         if isinstance(data, (bytes_types, string_types)):
             if len(data) == 0:
                 self._send_status(request_number, SFTP_EOF)
             else:
                 self._response(request_number, CMD_DATA, data)
         else:
             self._send_status(request_number, data)
     elif t == CMD_WRITE:
         handle = msg.get_binary()
         offset = msg.get_int64()
         data = msg.get_binary()
         if handle not in self.file_table:
             self._send_status(request_number, SFTP_BAD_MESSAGE, 'Invalid handle')
             return
         self._send_status(request_number, self.file_table[handle].write(offset, data))
     elif t == CMD_REMOVE:
         path = msg.get_text()
         self._send_status(request_number, self.server.remove(path))
     elif t == CMD_RENAME:
         oldpath = msg.get_text()
         newpath = msg.get_text()
         self._send_status(request_number, self.server.rename(oldpath, newpath))
     elif t == CMD_MKDIR:
         path = msg.get_text()
         attr = SFTPAttributes._from_msg(msg)
         self._send_status(request_number, self.server.mkdir(path, attr))
     elif t == CMD_RMDIR:
         path = msg.get_text()
         self._send_status(request_number, self.server.rmdir(path))
     elif t == CMD_OPENDIR:
         path = msg.get_text()
         self._open_folder(request_number, path)
         return
     elif t == CMD_READDIR:
         handle = msg.get_binary()
         if handle not in self.folder_table:
             self._send_status(request_number, SFTP_BAD_MESSAGE, 'Invalid handle')
             return
         folder = self.folder_table[handle]
         self._read_folder(request_number, folder)
     elif t == CMD_STAT:
         path = msg.get_text()
         resp = self.server.stat(path)
         if issubclass(type(resp), SFTPAttributes):
             self._response(request_number, CMD_ATTRS, resp)
         else:
             self._send_status(request_number, resp)
     elif t == CMD_LSTAT:
         path = msg.get_text()
         resp = self.server.lstat(path)
         if issubclass(type(resp), SFTPAttributes):
             self._response(request_number, CMD_ATTRS, resp)
         else:
             self._send_status(request_number, resp)
     elif t == CMD_FSTAT:
         handle = msg.get_binary()
         if handle not in self.file_table:
             self._send_status(request_number, SFTP_BAD_MESSAGE, 'Invalid handle')
             return
         resp = self.file_table[handle].stat()
         if issubclass(type(resp), SFTPAttributes):
             self._response(request_number, CMD_ATTRS, resp)
         else:
             self._send_status(request_number, resp)
     elif t == CMD_SETSTAT:
         path = msg.get_text()
         attr = SFTPAttributes._from_msg(msg)
         self._send_status(request_number, self.server.chattr(path, attr))
     elif t == CMD_FSETSTAT:
         handle = msg.get_binary()
         attr = SFTPAttributes._from_msg(msg)
         if handle not in self.file_table:
             self._response(request_number, SFTP_BAD_MESSAGE, 'Invalid handle')
             return
         self._send_status(request_number, self.file_table[handle].chattr(attr))
     elif t == CMD_READLINK:
         path = msg.get_text()
         resp = self.server.readlink(path)
         if isinstance(resp, (bytes_types, string_types)):
             self._response(request_number, CMD_NAME, 1, resp, '', SFTPAttributes())
         else:
             self._send_status(request_number, resp)
     elif t == CMD_SYMLINK:
         # the sftp 2 draft is incorrect here!  path always follows target_path
         target_path = msg.get_text()
         path = msg.get_text()
         self._send_status(request_number, self.server.symlink(target_path, path))
     elif t == CMD_REALPATH:
         path = msg.get_text()
         rpath = self.server.canonicalize(path)
         self._response(request_number, CMD_NAME, 1, rpath, '', SFTPAttributes())
     elif t == CMD_EXTENDED:
         tag = msg.get_text()
         if tag == 'check-file':
             self._check_file(request_number, msg)
         else:
             self._send_status(request_number, SFTP_OP_UNSUPPORTED)
     else:
         self._send_status(request_number, SFTP_OP_UNSUPPORTED)
예제 #28
0
    def listdir_iter(self, path='.', read_aheads=50):
        """
        Generator version of `.listdir_attr`.

        See the API docs for `.listdir_attr` for overall details.

        This function adds one more kwarg on top of `.listdir_attr`:
        ``read_aheads``, an integer controlling how many
        ``SSH_FXP_READDIR`` requests are made to the server. The default of 50
        should suffice for most file listings as each request/response cycle
        may contain multiple files (dependant on server implementation.)

        .. versionadded:: 1.15
        """
        path = self._adjust_cwd(path)
        self._log(DEBUG, 'listdir(%r)' % path)
        t, msg = self._request(CMD_OPENDIR, path)

        if t != CMD_HANDLE:
            raise SFTPError('Expected handle')

        handle = msg.get_string()

        nums = list()
        while True:
            try:
                # Send out a bunch of readdir requests so that we can read the
                # responses later on Section 6.7 of the SSH file transfer RFC
                # explains this
                # http://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt
                for i in range(read_aheads):
                    num = self._async_request(type(None), CMD_READDIR, handle)
                    nums.append(num)


                # For each of our sent requests
                # Read and parse the corresponding packets
                # If we're at the end of our queued requests, then fire off
                # some more requests
                # Exit the loop when we've reached the end of the directory
                # handle
                for num in nums:
                    t, pkt_data = self._read_packet()
                    msg = Message(pkt_data)
                    new_num = msg.get_int()
                    if num == new_num:
                        if t == CMD_STATUS:
                            self._convert_status(msg)
                    count = msg.get_int()
                    for i in range(count):
                        filename = msg.get_text()
                        longname = msg.get_text()
                        attr = SFTPAttributes._from_msg(
                            msg, filename, longname)
                        if (filename != '.') and (filename != '..'):
                            yield attr

                # If we've hit the end of our queued requests, reset nums.
                nums = list()

            except EOFError:
                self._request(CMD_CLOSE, handle)
                return