How to copy a file in C/C++ with libssh and SFTP

Raphael Teubner picture Raphael Teubner · Dec 3, 2012 · Viewed 17.3k times · Source

I want to copy a file from a client to a remote server, but I don't understand how to do it with the libssh library SFTP API.

The situation is that: The SSH session is open and the SFTP session is open too, I can create a file and write in it from the client to the server with the integrated function of libssh.

I did not find an easy way to copy a file from the client to the server with a simple function like sftp_transfer(sourceFile(like c:\my document\hello world.txt),RemoteFile(/home/user/hello world.txt),right(read and write)) ?

With what I have understood from the tutorial it is first creating a file in the remote location (server) then it is opening this file with this line of code:

file = sftp_open(sftp, "/home/helloworld.txt",access_type,1);

After that the file is created on the server, and then it is writing into this created file with a buffer:

const char *helloworld = "Hello, World!\n";
int length = strlen(helloworld);
nwritten = sftp_write(file, helloworld, length);

My question is now if I have a file for example a .doc file and I want to transfer/upload that file from c:\mydocument\document.doc to remote the remote server /home/user/document.doc, how can I do it with this method ?

How can I put this file into the sftp_write() function to send it like the helloworld in the sample function?

I may be not good enough in programming to understand, but I really tried to understand it and I'm stuck with it.

Thanks in advance for your help

See below a sample of the code I used to test:

// Set variable for the communication
char buffer[256];
unsigned int nbytes;

//create a file to send by SFTP
int access_type = O_WRONLY | O_CREAT | O_TRUNC;
const char *helloworld = "Hello, World!\n";
int length = strlen(helloworld);

//Open a SFTP session
sftp = sftp_new(my_ssh_session);
if (sftp == NULL)
{
    fprintf(stderr, "Error allocating SFTP session: %s\n",
    ssh_get_error(my_ssh_session));
    return SSH_ERROR;
}
// Initialize the SFTP session
rc = sftp_init(sftp);
if (rc != SSH_OK)
{
    fprintf(stderr, "Error initializing SFTP session: %s.\n",
    sftp_get_error(sftp));
    sftp_free(sftp);
    return rc;
}

//Open the file into the remote side
file = sftp_open(sftp, "/home/helloworld.txt",access_type,1);
if (file == NULL)
{
    fprintf(stderr, "Can't open file for writing: %s\n",ssh_get_error(my_ssh_session));
    return SSH_ERROR;
}

//Write the file created with what's into the buffer
nwritten = sftp_write(file, helloworld, length);
if (nwritten != length)
{
    fprintf(stderr, "Can't write data to file: %s\n",
    ssh_get_error(my_ssh_session));
    sftp_close(file);
    return SSH_ERROR;
}

Answer

Reuben Morais picture Reuben Morais · Dec 3, 2012

Open the file in the usual way (using C++'s fstream or C's stdio.h), read its contents to a buffer, and pass the buffer to sftp_write.

Something like this:

ifstream fin("file.doc", ios::binary);
if (fin) {
  fin.seekg(0, ios::end);
  ios::pos_type bufsize = fin.tellg();   // get file size in bytes
  fin.seekg(0);                          // rewind to beginning of file

  std::vector<char> buf(bufsize);        // allocate buffer
  fin.read(buf.data(), bufsize);         // read file contents into buffer

  sftp_write(file, buf.data(), bufsize); // write buffer to remote file
}

Note that this is a very simple implementation. You should probably open the remote file in append mode, then write the data in chunks instead of sending single huge blob of data.