コード例 #1
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
コード例 #2
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)
コード例 #3
0
ファイル: mockserver.py プロジェクト: sraman1407/atomic-hpc
def patch_chdir(self, path=None):
    """
    STANDARD IMPLEMENTATION DOESN'T WORK WITH RELATIVE PATHS

    Change the "current directory" of this SFTP session.  Since SFTP
    doesn't really have the concept of a current working directory, this is
    emulated by Paramiko.  Once you use this method to set a working
    directory, all operations on this `.SFTPClient` object will be relative
    to that path. You can pass in ``None`` to stop using a current working
    directory.

    :param str path: new current working directory

    :raises IOError: if the requested path doesn't exist on the server

    .. versionadded:: 1.4
    """
    if path is None:
        self._cwd = None
        return
    if not stat.S_ISDIR(self.stat(path).st_mode):
        raise SFTPError(errno.ENOTDIR,
                        "%s: %s" % (os.strerror(errno.ENOTDIR), path))
    # self._cwd = b(self.normalize(path))
    if self._cwd is None or os.path.isabs(path):
        self._cwd = b(self.normalize(os.path.abspath(path)))
    else:
        cwd = self._cwd.decode()
        self._cwd = b(self.normalize(os.path.join(cwd, path)))
コード例 #4
0
    def chdir(self, path=None, path_encoding='utf-8'):
        """
        Change the "current directory" of this SFTP session.  Since SFTP
        doesn't really have the concept of a current working directory, this is
        emulated by Paramiko.  Once you use this method to set a working
        directory, all operations on this `.SFTPClient` object will be relative
        to that path. You can pass in ``None`` to stop using a current working
        directory.

        :param str path: new current working directory
        :param str path_encoding: the param ```'path'``` encode format, eg: chdir(path='001中文目录'.encode('GB18030'),path_encoding='GB18030')
        :param str path_encoding: 当需要跳转的目录路径中包含有中文,而服务器未使用utf-8的编码格式时需要设置此参数,参数值为服务器使用的编码格式,如当服务器使用GB18030的编码格式时,使用实例:chdir(path="/test/中文目录".encode('GB18030'), path_encoding='GB18030')

        :raises:
            ``IOError`` -- if the requested path doesn't exist on the server

        .. versionadded:: 1.4
        """
        if path is None:
            self._cwd = None
            return
        if not stat.S_ISDIR(self.stat(path).st_mode):
            code = errno.ENOTDIR
            raise SFTPError(code, "{}: {}".format(os.strerror(code), path))
        self._cwd = b(self.normalize(path_encoding=path_encoding, path=path))
コード例 #5
0
ファイル: sftp_client.py プロジェクト: intgr/paramiko
    def chdir(self, path=None):
        """
        Change the "current directory" of this SFTP session.  Since SFTP
        doesn't really have the concept of a current working directory, this is
        emulated by Paramiko.  Once you use this method to set a working
        directory, all operations on this `.SFTPClient` object will be relative
        to that path. You can pass in ``None`` to stop using a current working
        directory.

        :param str path: new current working directory

        :raises:
            ``IOError`` -- if the requested path doesn't exist on the server

        .. versionadded:: 1.4
        """
        if path is None:
            self._cwd = None
            return
        if not stat.S_ISDIR(self.stat(path).st_mode):
            code = errno.ENOTDIR
            raise SFTPError(
                code, "{}: {}".format(os.strerror(code), path)
            )
        self._cwd = b(self.normalize(path))
コード例 #6
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
コード例 #7
0
    def open(self, filename, mode="r", bufsize=-1):
        """
        Open a file on the remote server.  The arguments are the same as for
        Python's built-in `python:file` (aka `python:open`).  A file-like
        object is returned, which closely mimics the behavior of a normal
        Python file object, including the ability to be used as a context
        manager.

        The mode indicates how the file is to be opened: ``'r'`` for reading,
        ``'w'`` for writing (truncating an existing file), ``'a'`` for
        appending, ``'r+'`` for reading/writing, ``'w+'`` for reading/writing
        (truncating an existing file), ``'a+'`` for reading/appending.  The
        Python ``'b'`` flag is ignored, since SSH treats all files as binary.
        The ``'U'`` flag is supported in a compatible way.

        Since 1.5.2, an ``'x'`` flag indicates that the operation should only
        succeed if the file was created and did not previously exist.  This has
        no direct mapping to Python's file flags, but is commonly known as the
        ``O_EXCL`` flag in posix.

        The file will be buffered in standard Python style by default, but
        can be altered with the ``bufsize`` parameter.  ``0`` turns off
        buffering, ``1`` uses line buffering, and any number greater than 1
        (``>1``) uses that specific buffer size.

        :param str filename: name of the file to open
        :param str mode: mode (Python-style) to open in
        :param int bufsize: desired buffering (-1 = default buffer size)
        :return: an `.SFTPFile` object representing the open file

        :raises: ``IOError`` -- if the file could not be opened.
        """
        filename = self._adjust_cwd(filename)
        self._log(DEBUG, "open({!r}, {!r})".format(filename, mode))
        imode = 0
        if ("r" in mode) or ("+" in mode):
            imode |= SFTP_FLAG_READ
        if ("w" in mode) or ("+" in mode) or ("a" in mode):
            imode |= SFTP_FLAG_WRITE
        if "w" in mode:
            imode |= SFTP_FLAG_CREATE | SFTP_FLAG_TRUNC
        if "a" in mode:
            imode |= SFTP_FLAG_CREATE | SFTP_FLAG_APPEND
        if "x" in mode:
            imode |= SFTP_FLAG_CREATE | SFTP_FLAG_EXCL
        attrblock = SFTPAttributes()
        t, msg = self._request(CMD_OPEN, filename, imode, attrblock)
        if t != CMD_HANDLE:
            raise SFTPError("Expected handle")
        handle = msg.get_binary()
        self._log(
            DEBUG,
            "open({!r}, {!r}) -> {}".format(
                filename, mode, u(hexlify(handle))
            ),
        )
        return SFTPFile(self, handle, mode, bufsize)
コード例 #8
0
 def _read(self, size):
     size = min(size, self.MAX_REQUEST_SIZE)
     if self._prefetching:
         data = self._read_prefetch(size)
         if data is not None:
             return data
     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()
コード例 #9
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)
コード例 #10
0
    def readlink(self, path):
        """
        Return the target of a symbolic link (shortcut).  You can use
        `symlink` to create these.  The result may be either an absolute or
        relative pathname.

        :param str path: path of the symbolic link file
        :return: target path, as a `str`
        """
        path = self._adjust_cwd(path)
        self._log(DEBUG, 'readlink(%r)' % path)
        t, msg = self._request(CMD_READLINK, path)
        if t != CMD_NAME:
            raise SFTPError('Expected name response')
        count = msg.get_int()
        if count == 0:
            return None
        if count != 1:
            raise SFTPError('Readlink returned %d results' % count)
        return _to_unicode(msg.get_string())
コード例 #11
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
コード例 #12
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)' % 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
コード例 #13
0
    def normalize(self, path):
        """
        Return the normalized path (on the server) of a given path.  This
        can be used to quickly resolve symbolic links or determine what the
        server is considering to be the "current folder" (by passing ``'.'``
        as ``path``).

        :param str path: path to be normalized
        :return: normalized form of the given path (as a `str`)

        :raises IOError: if the path can't be resolved on the server
        """
        path = self._adjust_cwd(path)
        self._log(DEBUG, 'normalize(%r)' % path)
        t, msg = self._request(CMD_REALPATH, path)
        if t != CMD_NAME:
            raise SFTPError('Expected name response')
        count = msg.get_int()
        if count != 1:
            raise SFTPError('Realpath returned %d results' % count)
        return msg.get_text()
コード例 #14
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)
コード例 #15
0
 def close(self, handle):
     """
     Close the remote file
     
     :param str handle: remote file handle to close
     """
     resp_type, msg = self._blocking_request(CMD_CLOSE, handle)
     if resp_type != CMD_STATUS:
         raise SFTPError("Error closing file")
     status = msg.get_int()
     log.debug(f'closed [{handle}] on server: {status}')
     return status
コード例 #16
0
 def _write(self, data):
     # may write less than requested if it would exceed max packet size
     chunk = min(len(data), self.MAX_REQUEST_SIZE)
     self._reqs.append(self.sftp._async_request(type(None), CMD_WRITE, self.handle, long(self._realpos), data[:chunk]))
     if not self.pipelined or (len(self._reqs) > 100 and self.sftp.sock.recv_ready()):
         while len(self._reqs):
             req = self._reqs.popleft()
             t, msg = self.sftp._read_response(req)
             if t != CMD_STATUS:
                 raise SFTPError('Expected status')
             # convert_status already called
     return chunk
コード例 #17
0
    def normalize(self, path, path_encoding='utf-8'):
        """
        Return the normalized path (on the server) of a given path.  This
        can be used to quickly resolve symbolic links or determine what the
        server is considering to be the "current folder" (by passing ``'.'``
        as ``path``).

        :param str path: path to be normalized
        :param str path_encoding: 编码/解码格式,默认: utf-8
        :return: normalized form of the given path (as a `str`)

        :raises: ``IOError`` -- if the path can't be resolved on the server
        """
        path = self._adjust_cwd(path)
        self._log(DEBUG, "normalize({!r})".format(path))
        t, msg = self._request(CMD_REALPATH, path)
        if t != CMD_NAME:
            raise SFTPError("Expected name response")
        count = msg.get_int()
        if count != 1:
            raise SFTPError("Realpath returned {} results".format(count))
        return msg.get_text(path_encoding)
コード例 #18
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)
コード例 #19
0
 def _async_response(self, t, msg, num):
     if t == CMD_STATUS:
         # save exception and re-raise it on next file operation
         try:
             self.sftp._convert_status(msg)
         except Exception as e:
             self._saved_exception = e
         return
     if t != CMD_DATA:
         raise SFTPError('Expected data')
     data = msg.get_string()
     with self._prefetch_lock:
         offset, length = self._prefetch_extents[num]
         self._prefetch_data[offset] = data
         del self._prefetch_extents[num]
         if len(self._prefetch_extents) == 0:
             self._prefetch_done = True
コード例 #20
0
    def open(self, filename, mode="r"):
        """
        Open a remote file, ``filename``, on the server for reading
        or writing.

        Args:
            filename (str): name of remote file to open
            mode (str): mode to open file in
        """
        filename = self.encode_path(filename)
        pflags = 0
        if "r" in mode:
            pflags |= SFTP_FLAG_READ
        if "w" in mode:
            pflags |= SFTP_FLAG_WRITE | SFTP_FLAG_CREATE | SFTP_FLAG_TRUNC
        attrs = SFTPAttributes()
        resp_type, msg = self._blocking_request(CMD_OPEN, filename, pflags, attrs)
        if resp_type != CMD_HANDLE:
            raise SFTPError("Expected remote file handle")
        return msg.get_binary()
コード例 #21
0
 def _threaded_reader(self, handle, writer, size):
     futures = []
     with self._lock:
         lo["expected_responses"] = math.ceil(size / MAX_PAYLOAD_SIZE)
     with ThreadPoolExecutor() as executor:
         n = 0
         while n < size:
             chunk = min(MAX_PAYLOAD_SIZE, size - n)
             futures.append(executor.submit(self.read, handle, chunk, n, thread=True))
             n += chunk
         requests = [f.result() for f in futures]
     for r in requests:
         resp_type, data = self._sftp._read_packet()
         if resp_type != CMD_DATA:
             raise SFTPError("Expected data")
         msg = Message(data)
         resp_num = msg.get_int()
         if resp_num in _request_stack:
             writer.seek(_request_stack[resp_num][0])
             log.debug(f'write local at byte {_request_stack[resp_num][0]}')
             writer.write(msg.get_string())
コード例 #22
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