Red-M / RedSSH

Use SSH in python easily with C speed!
Other
20 stars 3 forks source link

listdir() only returns empty ssh2.sftp_handle.SFTPAttributes #1

Closed piperun closed 4 years ago

piperun commented 4 years ago

Bug reports

Steps to reproduce:

    usr = "username"
    passw = "pass"
    rs = redssh.RedSSH()
    rs.connect(hostname="hostname", username=usr, password=passw)
    rs.start_sftp()
    sftp = redssh.sftp.RedSFTP(rs)
    # You can set it to any other directory, afaik it'll return b'' no matter what.
    for folder in sftp.list_dir("/"):
        print(folder)

Expected behavior: [What was expected to happen.] Return a populated generator with tuples Actual behavior: [What actually happened.] Returns b' ' when only using list_dir() When using:

dirlist = sftp.list_dir()
print(dirlist.readdir()

I get a lot of: (-37, b'', <ssh2.sftp_handle.SFTPAttributes object at 0x00000296986B1F18>) In the middle of valid entries.

Red-M commented 4 years ago

I've been able to reproduce this.

What I've found is that this is actually a bug in ssh2-python to do with EAGAIN errors from being in non-blocking mode. I've provided a patch in 2.2.0 for RedSSH that allows the public ssh2-python to be used while removing these (since a return code of -37 is the number for the symbol redssh.libssh2.LIBSSH2_ERROR_EAGAIN).

As part of this fix, I've updated the documentation for redssh.sftp.RedSFTP.list_dir() about the new option and I've corrected the underlying issue in ssh2-python in my own fork of ssh2-python.

As a side note, I've updated the documentation on how to use the SFTP functions from RedSSH as what your code should look like is this:

import redssh
usr = "username"
passw = "pass"
rs = redssh.RedSSH()
rs.connect(hostname="hostname", username=usr, password=passw)
rs.start_sftp()

for folder in rs.sftp.list_dir("/"):
    print(folder)

I know this wasn't very clear and hopefully this documentation adjustment fixes this kind of issue.

In addition, the fix for this particular issue in my own fork of ssh2-python is available to install as long as you have gcc and make available on your system.

Edit: I should also mention that the old redssh.sftp.RedSFTP.list_dir() was actually redssh.sftp.RedSFTP.open_dir() and thus not really representative of the function name. Let me know if the new version of RedSSH fixes your issue (you'll need to use rs.sftp.list_dir("/",True) or install my fork of ssh2-python).

piperun commented 4 years ago

Indeed it worked as intended, so I take it making a SFTPClient object isn't needed?

Red-M commented 4 years ago

Making an SFTPClient object is not required at all as redssh.RedSSH().start_sftp() does this for you and stores it at redssh.RedSSH().sftp.