2

I am trying to write a simple program (toy example) that copies a file from a remote host to the local machine.

It works when I try to copy a txt file, but not for files like mp4.

Here is my code, which is basically parts stitched together from the tutorial: https://pastebin.com/0FPrmeDx

This is where the error happens:

int scp_receive(ssh_session session, ssh_scp scp)
{
  int rc;
  int size, mode;
  char *filename, *buffer;

  rc = ssh_scp_pull_request(scp);
  if (rc != SSH_SCP_REQUEST_NEWFILE)
  {
    fprintf(stderr, "Error receiving information about file: %s\n",
            ssh_get_error(session));
    return SSH_ERROR;
  }

  size = ssh_scp_request_get_size(scp);
  filename = strdup(ssh_scp_request_get_filename(scp));
  mode = ssh_scp_request_get_permissions(scp);
  printf("Receiving file %s, size %d, permisssions 0%o\n",
          filename, size, mode);
  free(filename);

  buffer = malloc(size);
  if (buffer == NULL)
  {
    fprintf(stderr, "Memory allocation error\n");
    return SSH_ERROR;
  }

  ssh_scp_accept_request(scp);
  rc = ssh_scp_read(scp, buffer, size);
  if (rc == SSH_ERROR)
  {
    fprintf(stderr, "Error receiving file data: %s\n",
            ssh_get_error(session));
    free(buffer);
    return rc;
  }
  printf("Done!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");

  int filedesc = open("/home/user/video.mp4", O_WRONLY | O_CREAT);

  if (filedesc < 0) {
    return -1;
  }

  write(filedesc, buffer, size);
  free(buffer);

  close(filedesc);

  rc = ssh_scp_pull_request(scp);
  if (rc != SSH_SCP_REQUEST_EOF)
  {
    fprintf(stderr, "Unexpected request: %s\n",
            ssh_get_error(session));
    return SSH_ERROR;
  }

  return SSH_OK;
}

Error is fired with the code:

rc = ssh_scp_pull_request(scp);
if (rc != SSH_SCP_REQUEST_EOF)
{
   fprintf(stderr, "Unexpected request: %s\n",
           ssh_get_error(session));
   return SSH_ERROR;
}

This is the error that I get:

Unexpected request: ssh_scp_pull_request called under invalid state

I tried to figure it out, but I couldn't make any progress on it.

Update 1:

The size of the copied file is exactly the same as of the source file both for txt and mp4 files. However, the copied file seems to be largely empty... When copied, the permissions are changed from -rwxr-xr-x to --wxr-----.

Update 2:

It seems that the file size plays a major role here. Very small files (10-15kb) are copied without problems. Bigger files are not copied and produce the above mentioned error...

Leta
  • 331
  • 1
  • 4
  • 16
  • Probably not the main error, but `size` needs to be of type `size_t`, not `int` (otherwise you won't be able to copy files > 2 GB on most platforms). – Paul R Jan 14 '19 at 12:05
  • Thanks a lot for the comment! I have changed the code. I will also update the problem description in a second... – Leta Jan 14 '19 at 12:11

1 Answers1

2

You cannot expect, that ssh_scp_read() reads the whole data in a single call to it. You have to iterate, until no more data is left to read:

int r = 0;
while (r < size) {
    int st = ssh_scp_read(scp, buffer+r, size-r);
    r += st;
}

Now, a subsequent call to ssh_scp_pull_request(scp) should succeed.

Ctx
  • 18,090
  • 24
  • 36
  • 51