ssh_scp_read返回垃圾

时间:2017-07-21 11:56:11

标签: c scp libssh

我正在尝试从我的服务器下载文件;客户端和服务器都是Linux,但ssh_scp_read()返回不正确的整数。根据文档,该函数最多写入65536个字节,但当文件为37980时仅读取16384,但这不是我主要考虑的问题;在这个16384字节的末尾附近,它开始用NULL垃圾填充缓冲区,然后将其写入文件。

递归目录的创建工作正常;问题是下载大于16384字节的文件。此时我将使用sftp而不是scp,但我想知道我做错了什么。

这是功能代码:

int get(ssh_session gno_ses,ssh_scp scp)
{
    int rc;
    int size, permissions;
    char *buff, *filename, path[PATH_MAX];

    while(1)
    {
        rc = ssh_scp_pull_request(scp);
        switch (rc)
        {
            // cases [...]
            case SSH_SCP_REQUEST_NEWFILE:
                size = ssh_scp_request_get_size(scp);
                printf("Size is %d\n",size);
                filename = strdup(ssh_scp_request_get_filename(scp));
                permissions = ssh_scp_request_get_permissions(scp);

                FILE *file;
                file = fopen(filename, "w+");
                if (!file)
                {
                    ssh_scp_deny_request(scp,"Unable to open");
                    fprintf(stderr, " %s: %s\n", filename, strerror(errno));
                    fclose(file);
                    break;
                }

                buff = malloc(size);
                printf("Size of buffer is %d\n", size);
                if (!buff)
                {
                    fprintf(stderr, "\nBuff memory allocation error.\n");
                    return SSH_ERROR;
                }

                if( ssh_scp_accept_request(scp) != SSH_OK)
                {
                    fprintf(stderr, "Error accepting request: %s\n", ssh_get_error(gno_ses));
                    break;
                }

                do
                {
                    rc = ssh_scp_read(scp, buff, size);
                    if (rc == SSH_ERROR)
                    {
                        fprintf(stderr, "Error receiving file data: %s\n", ssh_get_error(gno_ses));
                        break;
                    }
                    if (fwrite(buff, 1, size, file) != size)
                    {
                        perror("Error at writting to file: ");
                        break;
                    }
                    printf("ssh_scp_read got %d\n",rc);
                } while (rc != 0);

                fclose(file);
                free(filename);
                free(buff);
                break;
        }
    }
    return SSH_OK;
}

这是输出:

Size is 37980
Size of buffer is 37980
ssh_scp_read got 16384
ssh_scp_read got 16384
ssh_scp_read got 5212
Error receiving file data: ssh_scp_read called under invalid state

任何意见都会受到赞赏。

2 个答案:

答案 0 :(得分:1)

问题在于,当size报告其读数低于该值时,我正在编写scp_scp_read()个字节:

rc = ssh_scp_read(scp, buff, size);
fwrite(buff, 1, size, file)

修复方法是只写rc个字节:

            int len_loop = size;
            int len;
            do
            {
                rc = ssh_scp_read(scp, buff, size);
                if (rc == SSH_ERROR || rc < 0)
                {
                    fprintf(stderr, "Error receiving file data: %s\n", ssh_get_error(gno_ses));
                    break;
                }
                else if (!rc)
                {
                    break;
                }
                len = fwrite(buff, 1, rc, file);
                if (len != rc)
                {
                    perror("Error at writting to file: ");
                    break;
                }
                printf("ssh_scp_read got %d\n",rc);
                len_loop -= rc;
            } while(len_loop);

答案 1 :(得分:0)

将内循环更改为

int len = size;
do
   {
                    rc = ssh_scp_read(scp, buff, size);
                    if (rc == SSH_ERROR)
                    {
                        fprintf(stderr, "Error receiving file data: %s\n", 
                        ssh_get_error(gno_ses));
                        break;
                    }
                    if (fwrite(buff, 1, rc, file) != size)
                    {
                        perror("Error at writting to file: ");
                        break;
                    }
                    printf("ssh_scp_read got %d\n",rc);
                    len-=rc;
    } while (len);