Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

scp examples update #21

Open
Jhoanor opened this issue Jul 9, 2013 · 0 comments
Open

scp examples update #21

Jhoanor opened this issue Jul 9, 2013 · 0 comments

Comments

@Jhoanor
Copy link

Jhoanor commented Jul 9, 2013

Since I had some trouble getting scp working, I'd thought I'd better share my examples.
In the regular examples there is only a scp_update, which doesn't work, not on OpenBSD at least, and getting a scp_download working was even a bit more awkward. (it now looks so simple though, but I didn't want to use sftp at first...)
Because no EOF is set when downloading, I had to keep an eye on filesize. In the C examples of the libssh2 package, that is the way it is done anyhow.
One would expect that after reading the last block of a file the next read would return "", which could be used to detect the eof. But it doesn't. It just hangs somewhere in a waiting loop, and I couldn't determine how to prevent that.

channel.close() will close the channel, but might generate an error. This is caused by a bug in channel.c line 46, which schould be: if (rc && rc != LIBSSH2_ERROR_EAGAIN)
To upload a file I've rewritten the send routine in the scp_upload.py example as follows. Reading and writing blocks instead of lines.

import os
...
def send(self, remote_path, mode=0644):
    file_size = os.path.getsize(remote_path)
    channel = self.session.scp_send(remote_path, mode, file_size)
    f=open(remote_path, "rb")
    send = 0
    while True:
        data = f.read(1024)
        channel.write(data)
        send = send + len(data)
        if  send >= file_size: 
            break
    f.close()
    channel.close()

To download a file I used the same scp_upload.py example with putting in a receive routine, reading blocks over the channel.
The last block get an extra 0 - eof byte, increasing the filesize, so I strip that (checking if it really is a 0, which can probably be omitted)
The only problem now is to determine the filesize. In C, it comes with the scp_recv call, but pylibssh2 puts a NULL in the fileinfo field :-(. So it has to be done with sftp:

import os
def _prepare_sock(self):
...
    self.sftp = self.session._session.sftp_init()
    ...
def receive(self, remote_path, mode=0644):
    file_size = self.sftp.get_stat(remote_path)[0]
    channel = self.session.scp_recv(remote_path)
    f=open(remote_path, "wb")
    got = 0
    while True:
        data = channel.read(1024)
        got = got + len(data)
        if got > file_size:
            if (data[-1:]=="\0"): # probably not needed
                f.write(data[:-1])
            break
        else:
            f.write(data)
    f.close()
    channel.close()
    os.chmod(remote_path,mode)
...
...
myscp.receive(sys.argv[4])

It would be nice if the regular examples can be updated with these.
Regards

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant