0

I need to download a directory from a remote location by using libssh and scp protocol. The directory contaains audio, video and some text files in it. Using the below code, I am trying to scp these files from a directory with the help of libssh scp function but it is downloading some garbage file . If i try to grab txt file it copies the data into some file with random name like ,oyøwithout extension at the given path of my windows machine. Can anyone guide what I am doing wrong and how to fix it to get files transferred? Or if there is any other way by which I can download these files using libssh?

  #include <iostream>
  #include <string>
  #include <libssh.h>
  #include <stdlib.h>
  #include <fstream> 
  #include <stdio.h>
  #include <fcntl.h>
  #include <sstream>
  #include <io.h>


static int fetch_files(ssh_session session)
{
    int size;
    int mode;
    int rc;
    int fd;
    ssh_scp scp = ssh_scp_new(session,
                              SSH_SCP_READ | SSH_SCP_RECURSIVE,
                              "/data/misc/qmmf/snapshot_01.jpg");

    if (scp == NULL)
    {
        std::cout << "Error allocating scp session: scp == NULL";
        return -1;
    }

    rc = ssh_scp_init(scp);
    if (rc != SSH_OK)
    {
        std::cout << "Error initializing scp session: rc != SSH_OK";
        ssh_scp_free(scp);
        return rc;
    }

    rc = ssh_scp_pull_request(scp);
    if (rc != SSH_SCP_REQUEST_NEWFILE)
    {
        cout << "Error receiving information about file: rc != SSH_SCP_REQUEST_NEWFILE";
        return -3;
    }

    int fileSize = ssh_scp_request_get_size(scp);
    string filename = _strdup(ssh_scp_request_get_filename(scp));
    int filePermission = ssh_scp_request_get_permissions(scp);
    cout << "fileSize" << fileSize << endl;
    cout << "filename" << filename << endl;
    cout << "filePermission" << filePermission << endl;

    char* buffer1 = (char *) malloc(sizeof(char) * fileSize);

    if (buffer1 == NULL)
    {
        cout << "Memory allocation error!";
        return SSH_ERROR;
    }

    ssh_scp_accept_request(scp);
    rc = ssh_scp_read(scp, buffer1, sizeof(char) * fileSize);
    if (rc == SSH_ERROR)
    {
        cout << "Error receiving file data: rc == SSH_ERROR!";
        free(buffer1);
        return rc;
    }

    char path[10000];
    sprintf_s(path, "C:\Documents/%s", filename);

    if (0 < (fd = open(path, O_RDWR | O_CREAT | O_TRUNC, filePermission)))
    {
        write(fd, buffer1, sizeof(char) * fileSize);
        close(fd);
    }
    else
    {
        cout << "Failed to open file!";
    }
    return 0;
}
CodeHunter
  • 2,017
  • 2
  • 21
  • 47
  • I recommend using `string path = "C:\\Documents\\" + filename;` and `std::fstream` instead. – user4581301 Feb 21 '19 at 03:03
  • ok. let me try it out. – CodeHunter Feb 21 '19 at 03:04
  • @user4581301 how it is a duplicate? I don't see it. This is related to contents in a file which I downloaded which mostly contains audio, images and video files. Can you please remove the duplicate part from it? – CodeHunter Feb 21 '19 at 03:27
  • You are getting garbage filenames because the `%s` in `sprintf_s(path, "C:\Documents/%s", filename);` instructs `sprintf_s` to format a null terminated array of characters. `filename` is a `std::string`, not a character array. `sprintf` did the best it could with the wrong input, tried to treat the `string` as a character array, and wound up spitting out nonsense characters based on binary data inside the `string`. `sprintf_s and `printf` behave exactly the same in this respect, hence the duplicate. – user4581301 Feb 21 '19 at 06:12
  • An MCVE for this looks like https://ideone.com/WU46zG . I had to use plain ol' `sprintf` for this because the particular variant of `sprintf_s` you used is pretty much Windows only. It's not part of Standard C++. – user4581301 Feb 21 '19 at 06:13

0 Answers0