I am trying to download few files stored on a remote machine. Those files can be either text files, image files (of jpeg,jpg form), video or audio files. Text files are downloaded successfully without issue and I am also able to open it as well in my local machine where I download them.
But image files and other video, audio files do not open after getting downloaded. When I checked, they were not of same size as original file. Like say the original file was of 30kb, but the downloaded file was only of 5kb. And this is the reason that maybe I am not able to open those files locally after downloading?
I am using scp
function of libssh
. Below is what I am trying:
#include <iostream>
#include <string>
#include <libssh.h>
#include <stdlib.h>
#include <fstream>
#include <stdio.h>
#include <Windows.h>
#include <fcntl.h>
#include <sstream>
#include <io.h>
using namespace std;
static int fetch_files(ssh_session session){
int size;
//char buffer[16384];
int mode;
int rc;
//creating scp session to read from remote host for this file
ssh_scp scp = ssh_scp_new(session, SSH_SCP_READ | SSH_SCP_RECURSIVE, "/home/snaps.jpg");
//executing the init
rc = ssh_scp_init(scp);
//pulling from request object
rc = ssh_scp_pull_request(scp);
if (rc != SSH_SCP_REQUEST_NEWFILE)
{
std::cout << "Error receiving information about file: rc != SSH_SCP_REQUEST_NEWFILE";
return -3;
}
else {
//trying to download the file from the created scp object
int t_filesize = ssh_scp_request_get_size(scp);
cout << "filesize is = " << t_filesize;
string t_filename = strdup(ssh_scp_request_get_filename(scp));
cout << "File name read is = " << t_filename;
int t_filemode = ssh_scp_request_get_permissions(scp);
cout << "File mode is = " << t_filemode;
//fprintf(stderr, "Receiving file %s, size %d, permisssions 0%o\n", t_filename, t_filesize, t_filemode);
FILE *fptr = fopen("file.jpg", "w");
if (NULL == fptr)
{
fprintf(stderr, "Error opening local file: %s, error %s\n", t_filename, strerror(errno));
ssh_scp_deny_request(scp, "Unable to open local file");
}
ssh_scp_accept_request(scp);
while (rc >= 0)
{ //reading and storing into buffer to write on local file system
rc = ssh_scp_read(scp, buffer, sizeof(buffer));
cout << "Buffer = " << buffer;
//cout << "RC = " << rc << " and SSH_ERROR is = " << SSH_ERROR;
if (rc == SSH_ERROR)
{
fprintf(stderr, "Error receiving file data: %s\n", ssh_get_error(session));
fclose(fptr);
ssh_scp_close(scp);
ssh_scp_free(scp);
return rc;
}
//fprintf(stderr, "Bytes received = %d\n", rc);
if (fwrite(buffer, rc, 1, fptr) != t_filesize)
{
fprintf(stderr, "Error writing file data: %s\n", strerror(errno));
fclose(fptr);
ssh_scp_close(scp);
ssh_scp_free(scp);
return rc;
}
}
cout << "Buffer is = " << buffer;
fclose(fptr);
}
How can I resolve it?
if (fwrite(buffer, rc, 1, fptr) != t_filesize)
Should have been
if (fwrite(buffer, 1, rc, fptr) != rc)
Or
if (fwrite(buffer, rc, 1, fptr) != 1)
rc
and 1
are swapped. You intended to write rc
bytes, second parameter is size of each unit with, third is number of units. Neither has anything to do with t_filesize
yet.
while (rc >= 0)
Insufficient, you also need a counter for the total bytes received yet. In the loop increment by rc
and break if total >= t_filesize
.
rc = ssh_scp_read(scp, buffer, sizeof(buffer));
Extend to
rc = ssh_scp_read(scp, buffer, min(sizeof(buffer), t_filesize - total));
So you don't request read of bytes which are not available.
As for why your files are too small, it's because you run into the faulty error handling mentioned first. You only get the first buffer full (respectively not even that, because the buffer isn't fully used), and the you already return from transfer.