mirror of
https://github.com/curl/curl.git
synced 2026-08-25 22:53:38 +03:00
libssh: simplify myssh_statemach_act()
Reduce complexity by splitting out sub functions. Made myssh_quote_error() to reduce code duplication. Closes #20252
This commit is contained in:
parent
1b24428d62
commit
bd3b2a626a
1 changed files with 138 additions and 176 deletions
|
|
@ -727,6 +727,19 @@ static int myssh_in_SFTP_READDIR_DONE(struct Curl_easy *data,
|
||||||
return SSH_NO_ERROR;
|
return SSH_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void myssh_quote_error(struct Curl_easy *data, struct ssh_conn *sshc,
|
||||||
|
const char *cmd)
|
||||||
|
{
|
||||||
|
if(cmd)
|
||||||
|
failf(data, "%s command failed: %s", cmd,
|
||||||
|
ssh_get_error(sshc->ssh_session));
|
||||||
|
Curl_safefree(sshc->quote_path1);
|
||||||
|
Curl_safefree(sshc->quote_path2);
|
||||||
|
myssh_to(data, sshc, SSH_SFTP_CLOSE);
|
||||||
|
sshc->nextstate = SSH_NO_STATE;
|
||||||
|
sshc->actualcode = CURLE_QUOTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
static int myssh_in_SFTP_QUOTE_STATVFS(struct Curl_easy *data,
|
static int myssh_in_SFTP_QUOTE_STATVFS(struct Curl_easy *data,
|
||||||
struct ssh_conn *sshc)
|
struct ssh_conn *sshc)
|
||||||
{
|
{
|
||||||
|
|
@ -734,12 +747,7 @@ static int myssh_in_SFTP_QUOTE_STATVFS(struct Curl_easy *data,
|
||||||
|
|
||||||
statvfs = sftp_statvfs(sshc->sftp_session, sshc->quote_path1);
|
statvfs = sftp_statvfs(sshc->sftp_session, sshc->quote_path1);
|
||||||
if(!statvfs && !sshc->acceptfail) {
|
if(!statvfs && !sshc->acceptfail) {
|
||||||
Curl_safefree(sshc->quote_path1);
|
myssh_quote_error(data, sshc, "statvfs");
|
||||||
failf(data, "statvfs command failed: %s",
|
|
||||||
ssh_get_error(sshc->ssh_session));
|
|
||||||
myssh_to(data, sshc, SSH_SFTP_CLOSE);
|
|
||||||
sshc->nextstate = SSH_NO_STATE;
|
|
||||||
sshc->actualcode = CURLE_QUOTE_ERROR;
|
|
||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
else if(statvfs) {
|
else if(statvfs) {
|
||||||
|
|
@ -1765,13 +1773,9 @@ static int myssh_in_SFTP_QUOTE_STAT(struct Curl_easy *data,
|
||||||
sftp_attributes_free(sshc->quote_attrs);
|
sftp_attributes_free(sshc->quote_attrs);
|
||||||
sshc->quote_attrs = sftp_stat(sshc->sftp_session, sshc->quote_path2);
|
sshc->quote_attrs = sftp_stat(sshc->sftp_session, sshc->quote_path2);
|
||||||
if(!sshc->quote_attrs) {
|
if(!sshc->quote_attrs) {
|
||||||
Curl_safefree(sshc->quote_path1);
|
|
||||||
Curl_safefree(sshc->quote_path2);
|
|
||||||
failf(data, "Attempt to get SFTP stats failed: %d",
|
failf(data, "Attempt to get SFTP stats failed: %d",
|
||||||
sftp_get_error(sshc->sftp_session));
|
sftp_get_error(sshc->sftp_session));
|
||||||
myssh_to(data, sshc, SSH_SFTP_CLOSE);
|
myssh_quote_error(data, sshc, NULL);
|
||||||
sshc->nextstate = SSH_NO_STATE;
|
|
||||||
sshc->actualcode = CURLE_QUOTE_ERROR;
|
|
||||||
return SSH_NO_ERROR;
|
return SSH_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1780,12 +1784,8 @@ static int myssh_in_SFTP_QUOTE_STAT(struct Curl_easy *data,
|
||||||
const char *p = sshc->quote_path1;
|
const char *p = sshc->quote_path1;
|
||||||
curl_off_t gid;
|
curl_off_t gid;
|
||||||
if(curlx_str_number(&p, &gid, UINT_MAX)) {
|
if(curlx_str_number(&p, &gid, UINT_MAX)) {
|
||||||
Curl_safefree(sshc->quote_path1);
|
|
||||||
Curl_safefree(sshc->quote_path2);
|
|
||||||
failf(data, "Syntax error: chgrp gid not a number");
|
failf(data, "Syntax error: chgrp gid not a number");
|
||||||
myssh_to(data, sshc, SSH_SFTP_CLOSE);
|
myssh_quote_error(data, sshc, NULL);
|
||||||
sshc->nextstate = SSH_NO_STATE;
|
|
||||||
sshc->actualcode = CURLE_QUOTE_ERROR;
|
|
||||||
return SSH_NO_ERROR;
|
return SSH_NO_ERROR;
|
||||||
}
|
}
|
||||||
sshc->quote_attrs->gid = (uint32_t)gid;
|
sshc->quote_attrs->gid = (uint32_t)gid;
|
||||||
|
|
@ -1795,12 +1795,8 @@ static int myssh_in_SFTP_QUOTE_STAT(struct Curl_easy *data,
|
||||||
curl_off_t perms;
|
curl_off_t perms;
|
||||||
const char *p = sshc->quote_path1;
|
const char *p = sshc->quote_path1;
|
||||||
if(curlx_str_octal(&p, &perms, 07777)) {
|
if(curlx_str_octal(&p, &perms, 07777)) {
|
||||||
Curl_safefree(sshc->quote_path1);
|
|
||||||
Curl_safefree(sshc->quote_path2);
|
|
||||||
failf(data, "Syntax error: chmod permissions not a number");
|
failf(data, "Syntax error: chmod permissions not a number");
|
||||||
myssh_to(data, sshc, SSH_SFTP_CLOSE);
|
myssh_quote_error(data, sshc, NULL);
|
||||||
sshc->nextstate = SSH_NO_STATE;
|
|
||||||
sshc->actualcode = CURLE_QUOTE_ERROR;
|
|
||||||
return SSH_NO_ERROR;
|
return SSH_NO_ERROR;
|
||||||
}
|
}
|
||||||
sshc->quote_attrs->permissions = (mode_t)perms;
|
sshc->quote_attrs->permissions = (mode_t)perms;
|
||||||
|
|
@ -1810,12 +1806,8 @@ static int myssh_in_SFTP_QUOTE_STAT(struct Curl_easy *data,
|
||||||
const char *p = sshc->quote_path1;
|
const char *p = sshc->quote_path1;
|
||||||
curl_off_t uid;
|
curl_off_t uid;
|
||||||
if(curlx_str_number(&p, &uid, UINT_MAX)) {
|
if(curlx_str_number(&p, &uid, UINT_MAX)) {
|
||||||
Curl_safefree(sshc->quote_path1);
|
|
||||||
Curl_safefree(sshc->quote_path2);
|
|
||||||
failf(data, "Syntax error: chown uid not a number");
|
failf(data, "Syntax error: chown uid not a number");
|
||||||
myssh_to(data, sshc, SSH_SFTP_CLOSE);
|
myssh_quote_error(data, sshc, NULL);
|
||||||
sshc->nextstate = SSH_NO_STATE;
|
|
||||||
sshc->actualcode = CURLE_QUOTE_ERROR;
|
|
||||||
return SSH_NO_ERROR;
|
return SSH_NO_ERROR;
|
||||||
}
|
}
|
||||||
sshc->quote_attrs->uid = (uint32_t)uid;
|
sshc->quote_attrs->uid = (uint32_t)uid;
|
||||||
|
|
@ -1836,11 +1828,7 @@ static int myssh_in_SFTP_QUOTE_STAT(struct Curl_easy *data,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if(fail) {
|
if(fail) {
|
||||||
Curl_safefree(sshc->quote_path1);
|
myssh_quote_error(data, sshc, NULL);
|
||||||
Curl_safefree(sshc->quote_path2);
|
|
||||||
myssh_to(data, sshc, SSH_SFTP_CLOSE);
|
|
||||||
sshc->nextstate = SSH_NO_STATE;
|
|
||||||
sshc->actualcode = CURLE_QUOTE_ERROR;
|
|
||||||
return SSH_NO_ERROR;
|
return SSH_NO_ERROR;
|
||||||
}
|
}
|
||||||
if(date > UINT_MAX)
|
if(date > UINT_MAX)
|
||||||
|
|
@ -1871,6 +1859,104 @@ static void conn_forget_socket(struct Curl_easy *data, int sockindex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void myssh_SESSION_DISCONNECT(struct Curl_easy *data,
|
||||||
|
struct ssh_conn *sshc)
|
||||||
|
{
|
||||||
|
/* during weird times when we have been prematurely aborted, the channel
|
||||||
|
is still alive when we reach this state and we MUST kill the channel
|
||||||
|
properly first */
|
||||||
|
if(sshc->scp_session) {
|
||||||
|
ssh_scp_free(sshc->scp_session);
|
||||||
|
sshc->scp_session = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sshc->sftp_file) {
|
||||||
|
sftp_close(sshc->sftp_file);
|
||||||
|
sshc->sftp_file = NULL;
|
||||||
|
}
|
||||||
|
if(sshc->sftp_session) {
|
||||||
|
sftp_free(sshc->sftp_session);
|
||||||
|
sshc->sftp_session = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_disconnect(sshc->ssh_session);
|
||||||
|
if(!ssh_version(SSH_VERSION_INT(0, 10, 0))) {
|
||||||
|
/* conn->sock[FIRSTSOCKET] is closed by ssh_disconnect behind our back,
|
||||||
|
tell the connection to forget about it. This libssh
|
||||||
|
bug is fixed in 0.10.0. */
|
||||||
|
conn_forget_socket(data, FIRSTSOCKET);
|
||||||
|
}
|
||||||
|
|
||||||
|
SSH_STRING_FREE_CHAR(sshc->homedir);
|
||||||
|
|
||||||
|
myssh_to(data, sshc, SSH_SESSION_FREE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int myssh_SSH_SCP_DOWNLOAD(struct Curl_easy *data,
|
||||||
|
struct ssh_conn *sshc)
|
||||||
|
{
|
||||||
|
curl_off_t bytecount;
|
||||||
|
int rc = ssh_scp_pull_request(sshc->scp_session);
|
||||||
|
if(rc != SSH_SCP_REQUEST_NEWFILE) {
|
||||||
|
const char *err_msg = ssh_get_error(sshc->ssh_session);
|
||||||
|
failf(data, "%s", err_msg);
|
||||||
|
return myssh_to_ERROR(data, sshc, CURLE_REMOTE_FILE_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* download data */
|
||||||
|
bytecount = ssh_scp_request_get_size(sshc->scp_session);
|
||||||
|
data->req.maxdownload = (curl_off_t)bytecount;
|
||||||
|
Curl_xfer_setup_recv(data, FIRSTSOCKET, bytecount);
|
||||||
|
|
||||||
|
/* not set by Curl_xfer_setup to preserve keepon bits */
|
||||||
|
data->conn->send_idx = 0;
|
||||||
|
|
||||||
|
myssh_to(data, sshc, SSH_STOP);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int myssh_in_TRANS_INIT(struct Curl_easy *data, struct ssh_conn *sshc,
|
||||||
|
struct SSHPROTO *sshp)
|
||||||
|
{
|
||||||
|
CURLcode result;
|
||||||
|
int rc = 0;
|
||||||
|
if(!sshp)
|
||||||
|
return myssh_to_ERROR(data, sshc, CURLE_FAILED_INIT);
|
||||||
|
|
||||||
|
result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
|
||||||
|
if(result) {
|
||||||
|
sshc->actualcode = result;
|
||||||
|
myssh_to(data, sshc, SSH_STOP);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Functions from the SCP subsystem cannot handle/return SSH_AGAIN */
|
||||||
|
ssh_set_blocking(sshc->ssh_session, 1);
|
||||||
|
|
||||||
|
if(data->state.upload) {
|
||||||
|
if(data->state.infilesize < 0) {
|
||||||
|
failf(data, "SCP requires a known file size for upload");
|
||||||
|
return myssh_to_ERROR(data, sshc, CURLE_UPLOAD_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
sshc->scp_session =
|
||||||
|
ssh_scp_new(sshc->ssh_session, SSH_SCP_WRITE, sshp->path);
|
||||||
|
myssh_to(data, sshc, SSH_SCP_UPLOAD_INIT);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sshc->scp_session =
|
||||||
|
ssh_scp_new(sshc->ssh_session, SSH_SCP_READ, sshp->path);
|
||||||
|
myssh_to(data, sshc, SSH_SCP_DOWNLOAD_INIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!sshc->scp_session) {
|
||||||
|
const char *err_msg = ssh_get_error(sshc->ssh_session);
|
||||||
|
failf(data, "%s", err_msg);
|
||||||
|
rc = myssh_to_ERROR(data, sshc, CURLE_UPLOAD_FAILED);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ssh_statemach_act() runs the SSH state machine as far as it can without
|
* ssh_statemach_act() runs the SSH state machine as far as it can without
|
||||||
* blocking and without reaching the end. The data the pointer 'block' points
|
* blocking and without reaching the end. The data the pointer 'block' points
|
||||||
|
|
@ -1883,9 +1969,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
||||||
bool *block)
|
bool *block)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
struct connectdata *conn = data->conn;
|
|
||||||
int rc = SSH_NO_ERROR, err;
|
int rc = SSH_NO_ERROR, err;
|
||||||
const char *err_msg;
|
|
||||||
|
|
||||||
*block = FALSE; /* we are not blocking by default */
|
*block = FALSE; /* we are not blocking by default */
|
||||||
do {
|
do {
|
||||||
|
|
@ -1942,14 +2026,13 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
||||||
break;
|
break;
|
||||||
case SSH_SFTP_QUOTE_INIT:
|
case SSH_SFTP_QUOTE_INIT:
|
||||||
rc = sshp ? myssh_in_SFTP_QUOTE_INIT(data, sshc, sshp) :
|
rc = sshp ? myssh_in_SFTP_QUOTE_INIT(data, sshc, sshp) :
|
||||||
CURLE_FAILED_INIT;
|
CURLE_FAILED_INIT;
|
||||||
break;
|
break;
|
||||||
case SSH_SFTP_POSTQUOTE_INIT:
|
case SSH_SFTP_POSTQUOTE_INIT:
|
||||||
rc = myssh_in_SFTP_POSTQUOTE_INIT(data, sshc);
|
rc = myssh_in_SFTP_POSTQUOTE_INIT(data, sshc);
|
||||||
break;
|
break;
|
||||||
case SSH_SFTP_QUOTE:
|
case SSH_SFTP_QUOTE:
|
||||||
rc = sshp ? myssh_in_SFTP_QUOTE(data, sshc, sshp) :
|
rc = sshp ? myssh_in_SFTP_QUOTE(data, sshc, sshp) : CURLE_FAILED_INIT;
|
||||||
CURLE_FAILED_INIT;
|
|
||||||
break;
|
break;
|
||||||
case SSH_SFTP_NEXT_QUOTE:
|
case SSH_SFTP_NEXT_QUOTE:
|
||||||
rc = myssh_in_SFTP_NEXT_QUOTE(data, sshc);
|
rc = myssh_in_SFTP_NEXT_QUOTE(data, sshc);
|
||||||
|
|
@ -1957,23 +2040,13 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
||||||
case SSH_SFTP_QUOTE_STAT:
|
case SSH_SFTP_QUOTE_STAT:
|
||||||
rc = myssh_in_SFTP_QUOTE_STAT(data, sshc);
|
rc = myssh_in_SFTP_QUOTE_STAT(data, sshc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SSH_SFTP_QUOTE_SETSTAT:
|
case SSH_SFTP_QUOTE_SETSTAT:
|
||||||
rc = sftp_setstat(sshc->sftp_session, sshc->quote_path2,
|
rc = sftp_setstat(sshc->sftp_session, sshc->quote_path2,
|
||||||
sshc->quote_attrs);
|
sshc->quote_attrs);
|
||||||
if(rc == SSH_AGAIN)
|
if(rc == SSH_AGAIN)
|
||||||
break;
|
break;
|
||||||
if(rc && !sshc->acceptfail) {
|
if(rc && !sshc->acceptfail) {
|
||||||
Curl_safefree(sshc->quote_path1);
|
myssh_quote_error(data, sshc, "setstat");
|
||||||
Curl_safefree(sshc->quote_path2);
|
|
||||||
failf(data, "Attempt to set SFTP stats failed: %s",
|
|
||||||
ssh_get_error(sshc->ssh_session));
|
|
||||||
myssh_to(data, sshc, SSH_SFTP_CLOSE);
|
|
||||||
sshc->nextstate = SSH_NO_STATE;
|
|
||||||
sshc->actualcode = CURLE_QUOTE_ERROR;
|
|
||||||
/* sshc->actualcode = sftp_error_to_CURLE(err);
|
|
||||||
* we do not send the actual error; we return
|
|
||||||
* the error the libssh2 backend is returning */
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
||||||
|
|
@ -1985,13 +2058,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
||||||
if(rc == SSH_AGAIN)
|
if(rc == SSH_AGAIN)
|
||||||
break;
|
break;
|
||||||
if(rc && !sshc->acceptfail) {
|
if(rc && !sshc->acceptfail) {
|
||||||
Curl_safefree(sshc->quote_path1);
|
myssh_quote_error(data, sshc, "symlink");
|
||||||
Curl_safefree(sshc->quote_path2);
|
|
||||||
failf(data, "symlink command failed: %s",
|
|
||||||
ssh_get_error(sshc->ssh_session));
|
|
||||||
myssh_to(data, sshc, SSH_SFTP_CLOSE);
|
|
||||||
sshc->nextstate = SSH_NO_STATE;
|
|
||||||
sshc->actualcode = CURLE_QUOTE_ERROR;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
||||||
|
|
@ -2003,12 +2070,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
||||||
if(rc == SSH_AGAIN)
|
if(rc == SSH_AGAIN)
|
||||||
break;
|
break;
|
||||||
if(rc && !sshc->acceptfail) {
|
if(rc && !sshc->acceptfail) {
|
||||||
Curl_safefree(sshc->quote_path1);
|
myssh_quote_error(data, sshc, "mkdir");
|
||||||
failf(data, "mkdir command failed: %s",
|
|
||||||
ssh_get_error(sshc->ssh_session));
|
|
||||||
myssh_to(data, sshc, SSH_SFTP_CLOSE);
|
|
||||||
sshc->nextstate = SSH_NO_STATE;
|
|
||||||
sshc->actualcode = CURLE_QUOTE_ERROR;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
||||||
|
|
@ -2020,13 +2082,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
||||||
if(rc == SSH_AGAIN)
|
if(rc == SSH_AGAIN)
|
||||||
break;
|
break;
|
||||||
if(rc && !sshc->acceptfail) {
|
if(rc && !sshc->acceptfail) {
|
||||||
Curl_safefree(sshc->quote_path1);
|
myssh_quote_error(data, sshc, "rename");
|
||||||
Curl_safefree(sshc->quote_path2);
|
|
||||||
failf(data, "rename command failed: %s",
|
|
||||||
ssh_get_error(sshc->ssh_session));
|
|
||||||
myssh_to(data, sshc, SSH_SFTP_CLOSE);
|
|
||||||
sshc->nextstate = SSH_NO_STATE;
|
|
||||||
sshc->actualcode = CURLE_QUOTE_ERROR;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
||||||
|
|
@ -2037,12 +2093,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
||||||
if(rc == SSH_AGAIN)
|
if(rc == SSH_AGAIN)
|
||||||
break;
|
break;
|
||||||
if(rc && !sshc->acceptfail) {
|
if(rc && !sshc->acceptfail) {
|
||||||
Curl_safefree(sshc->quote_path1);
|
myssh_quote_error(data, sshc, "rmdir");
|
||||||
failf(data, "rmdir command failed: %s",
|
|
||||||
ssh_get_error(sshc->ssh_session));
|
|
||||||
myssh_to(data, sshc, SSH_SFTP_CLOSE);
|
|
||||||
sshc->nextstate = SSH_NO_STATE;
|
|
||||||
sshc->actualcode = CURLE_QUOTE_ERROR;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
||||||
|
|
@ -2053,11 +2104,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
||||||
if(rc == SSH_AGAIN)
|
if(rc == SSH_AGAIN)
|
||||||
break;
|
break;
|
||||||
if(rc && !sshc->acceptfail) {
|
if(rc && !sshc->acceptfail) {
|
||||||
Curl_safefree(sshc->quote_path1);
|
myssh_quote_error(data, sshc, "rm");
|
||||||
failf(data, "rm command failed: %s", ssh_get_error(sshc->ssh_session));
|
|
||||||
myssh_to(data, sshc, SSH_SFTP_CLOSE);
|
|
||||||
sshc->nextstate = SSH_NO_STATE;
|
|
||||||
sshc->actualcode = CURLE_QUOTE_ERROR;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
||||||
|
|
@ -2170,11 +2217,10 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
||||||
|
|
||||||
case SSH_SFTP_READDIR_INIT:
|
case SSH_SFTP_READDIR_INIT:
|
||||||
rc = sshp ? myssh_in_SFTP_READDIR_INIT(data, sshc, sshp) :
|
rc = sshp ? myssh_in_SFTP_READDIR_INIT(data, sshc, sshp) :
|
||||||
CURLE_FAILED_INIT;
|
CURLE_FAILED_INIT;
|
||||||
break;
|
break;
|
||||||
case SSH_SFTP_READDIR:
|
case SSH_SFTP_READDIR:
|
||||||
rc = sshp ? myssh_in_SFTP_READDIR(data, sshc, sshp) :
|
rc = sshp ? myssh_in_SFTP_READDIR(data, sshc, sshp) : CURLE_FAILED_INIT;
|
||||||
CURLE_FAILED_INIT;
|
|
||||||
break;
|
break;
|
||||||
case SSH_SFTP_READDIR_LINK:
|
case SSH_SFTP_READDIR_LINK:
|
||||||
rc = myssh_in_SFTP_READDIR_LINK(data, sshc);
|
rc = myssh_in_SFTP_READDIR_LINK(data, sshc);
|
||||||
|
|
@ -2187,57 +2233,19 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
||||||
break;
|
break;
|
||||||
case SSH_SFTP_DOWNLOAD_INIT:
|
case SSH_SFTP_DOWNLOAD_INIT:
|
||||||
rc = sshp ? myssh_in_SFTP_DOWNLOAD_INIT(data, sshc, sshp) :
|
rc = sshp ? myssh_in_SFTP_DOWNLOAD_INIT(data, sshc, sshp) :
|
||||||
CURLE_FAILED_INIT;
|
CURLE_FAILED_INIT;
|
||||||
break;
|
break;
|
||||||
case SSH_SFTP_DOWNLOAD_STAT:
|
case SSH_SFTP_DOWNLOAD_STAT:
|
||||||
rc = myssh_in_SFTP_DOWNLOAD_STAT(data, sshc);
|
rc = myssh_in_SFTP_DOWNLOAD_STAT(data, sshc);
|
||||||
break;
|
break;
|
||||||
case SSH_SFTP_CLOSE:
|
case SSH_SFTP_CLOSE:
|
||||||
rc = sshp ? myssh_in_SFTP_CLOSE(data, sshc, sshp) :
|
rc = sshp ? myssh_in_SFTP_CLOSE(data, sshc, sshp) : CURLE_FAILED_INIT;
|
||||||
CURLE_FAILED_INIT;
|
|
||||||
break;
|
break;
|
||||||
case SSH_SFTP_SHUTDOWN:
|
case SSH_SFTP_SHUTDOWN:
|
||||||
rc = myssh_in_SFTP_SHUTDOWN(data, sshc);
|
rc = myssh_in_SFTP_SHUTDOWN(data, sshc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SSH_SCP_TRANS_INIT:
|
case SSH_SCP_TRANS_INIT:
|
||||||
if(!sshp) {
|
rc = myssh_in_TRANS_INIT(data, sshc, sshp);
|
||||||
result = CURLE_FAILED_INIT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
|
|
||||||
if(result) {
|
|
||||||
sshc->actualcode = result;
|
|
||||||
myssh_to(data, sshc, SSH_STOP);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Functions from the SCP subsystem cannot handle/return SSH_AGAIN */
|
|
||||||
ssh_set_blocking(sshc->ssh_session, 1);
|
|
||||||
|
|
||||||
if(data->state.upload) {
|
|
||||||
if(data->state.infilesize < 0) {
|
|
||||||
failf(data, "SCP requires a known file size for upload");
|
|
||||||
sshc->actualcode = CURLE_UPLOAD_FAILED;
|
|
||||||
rc = myssh_to_ERROR(data, sshc, CURLE_UPLOAD_FAILED);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
sshc->scp_session =
|
|
||||||
ssh_scp_new(sshc->ssh_session, SSH_SCP_WRITE, sshp->path);
|
|
||||||
myssh_to(data, sshc, SSH_SCP_UPLOAD_INIT);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sshc->scp_session =
|
|
||||||
ssh_scp_new(sshc->ssh_session, SSH_SCP_READ, sshp->path);
|
|
||||||
myssh_to(data, sshc, SSH_SCP_DOWNLOAD_INIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!sshc->scp_session) {
|
|
||||||
err_msg = ssh_get_error(sshc->ssh_session);
|
|
||||||
failf(data, "%s", err_msg);
|
|
||||||
rc = myssh_to_ERROR(data, sshc, CURLE_UPLOAD_FAILED);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SSH_SCP_UPLOAD_INIT:
|
case SSH_SCP_UPLOAD_INIT:
|
||||||
|
|
@ -2247,7 +2255,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
||||||
}
|
}
|
||||||
rc = ssh_scp_init(sshc->scp_session);
|
rc = ssh_scp_init(sshc->scp_session);
|
||||||
if(rc != SSH_OK) {
|
if(rc != SSH_OK) {
|
||||||
err_msg = ssh_get_error(sshc->ssh_session);
|
const char *err_msg = ssh_get_error(sshc->ssh_session);
|
||||||
failf(data, "%s", err_msg);
|
failf(data, "%s", err_msg);
|
||||||
rc = myssh_to_ERROR(data, sshc, CURLE_UPLOAD_FAILED);
|
rc = myssh_to_ERROR(data, sshc, CURLE_UPLOAD_FAILED);
|
||||||
break;
|
break;
|
||||||
|
|
@ -2258,7 +2266,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
||||||
(int)data->set.new_file_perms);
|
(int)data->set.new_file_perms);
|
||||||
|
|
||||||
if(rc != SSH_OK) {
|
if(rc != SSH_OK) {
|
||||||
err_msg = ssh_get_error(sshc->ssh_session);
|
const char *err_msg = ssh_get_error(sshc->ssh_session);
|
||||||
failf(data, "%s", err_msg);
|
failf(data, "%s", err_msg);
|
||||||
rc = myssh_to_ERROR(data, sshc, CURLE_UPLOAD_FAILED);
|
rc = myssh_to_ERROR(data, sshc, CURLE_UPLOAD_FAILED);
|
||||||
break;
|
break;
|
||||||
|
|
@ -2275,10 +2283,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SSH_SCP_DOWNLOAD_INIT:
|
case SSH_SCP_DOWNLOAD_INIT:
|
||||||
|
|
||||||
rc = ssh_scp_init(sshc->scp_session);
|
rc = ssh_scp_init(sshc->scp_session);
|
||||||
if(rc != SSH_OK) {
|
if(rc != SSH_OK) {
|
||||||
err_msg = ssh_get_error(sshc->ssh_session);
|
const char *err_msg = ssh_get_error(sshc->ssh_session);
|
||||||
failf(data, "%s", err_msg);
|
failf(data, "%s", err_msg);
|
||||||
rc = myssh_to_ERROR(data, sshc, CURLE_COULDNT_CONNECT);
|
rc = myssh_to_ERROR(data, sshc, CURLE_COULDNT_CONNECT);
|
||||||
break;
|
break;
|
||||||
|
|
@ -2286,28 +2293,10 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
||||||
myssh_to(data, sshc, SSH_SCP_DOWNLOAD);
|
myssh_to(data, sshc, SSH_SCP_DOWNLOAD);
|
||||||
FALLTHROUGH();
|
FALLTHROUGH();
|
||||||
|
|
||||||
case SSH_SCP_DOWNLOAD: {
|
case SSH_SCP_DOWNLOAD:
|
||||||
curl_off_t bytecount;
|
rc = myssh_SSH_SCP_DOWNLOAD(data, sshc);
|
||||||
|
|
||||||
rc = ssh_scp_pull_request(sshc->scp_session);
|
|
||||||
if(rc != SSH_SCP_REQUEST_NEWFILE) {
|
|
||||||
err_msg = ssh_get_error(sshc->ssh_session);
|
|
||||||
failf(data, "%s", err_msg);
|
|
||||||
rc = myssh_to_ERROR(data, sshc, CURLE_REMOTE_FILE_NOT_FOUND);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* download data */
|
|
||||||
bytecount = ssh_scp_request_get_size(sshc->scp_session);
|
|
||||||
data->req.maxdownload = (curl_off_t)bytecount;
|
|
||||||
Curl_xfer_setup_recv(data, FIRSTSOCKET, bytecount);
|
|
||||||
|
|
||||||
/* not set by Curl_xfer_setup to preserve keepon bits */
|
|
||||||
conn->send_idx = 0;
|
|
||||||
|
|
||||||
myssh_to(data, sshc, SSH_STOP);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case SSH_SCP_DONE:
|
case SSH_SCP_DONE:
|
||||||
if(data->state.upload)
|
if(data->state.upload)
|
||||||
myssh_to(data, sshc, SSH_SCP_SEND_EOF);
|
myssh_to(data, sshc, SSH_SCP_SEND_EOF);
|
||||||
|
|
@ -2346,41 +2335,14 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
||||||
FALLTHROUGH();
|
FALLTHROUGH();
|
||||||
|
|
||||||
case SSH_SESSION_DISCONNECT:
|
case SSH_SESSION_DISCONNECT:
|
||||||
/* during weird times when we have been prematurely aborted, the channel
|
myssh_SESSION_DISCONNECT(data, sshc);
|
||||||
is still alive when we reach this state and we MUST kill the channel
|
|
||||||
properly first */
|
|
||||||
if(sshc->scp_session) {
|
|
||||||
ssh_scp_free(sshc->scp_session);
|
|
||||||
sshc->scp_session = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(sshc->sftp_file) {
|
|
||||||
sftp_close(sshc->sftp_file);
|
|
||||||
sshc->sftp_file = NULL;
|
|
||||||
}
|
|
||||||
if(sshc->sftp_session) {
|
|
||||||
sftp_free(sshc->sftp_session);
|
|
||||||
sshc->sftp_session = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssh_disconnect(sshc->ssh_session);
|
|
||||||
if(!ssh_version(SSH_VERSION_INT(0, 10, 0))) {
|
|
||||||
/* conn->sock[FIRSTSOCKET] is closed by ssh_disconnect behind our back,
|
|
||||||
tell the connection to forget about it. This libssh
|
|
||||||
bug is fixed in 0.10.0. */
|
|
||||||
conn_forget_socket(data, FIRSTSOCKET);
|
|
||||||
}
|
|
||||||
|
|
||||||
SSH_STRING_FREE_CHAR(sshc->homedir);
|
|
||||||
|
|
||||||
myssh_to(data, sshc, SSH_SESSION_FREE);
|
|
||||||
FALLTHROUGH();
|
FALLTHROUGH();
|
||||||
case SSH_SESSION_FREE:
|
case SSH_SESSION_FREE:
|
||||||
sshc_cleanup(sshc);
|
sshc_cleanup(sshc);
|
||||||
/* the code we are about to return */
|
/* the code we are about to return */
|
||||||
result = sshc->actualcode;
|
result = sshc->actualcode;
|
||||||
memset(sshc, 0, sizeof(struct ssh_conn));
|
memset(sshc, 0, sizeof(struct ssh_conn));
|
||||||
connclose(conn, "SSH session free");
|
connclose(data->conn, "SSH session free");
|
||||||
sshc->state = SSH_SESSION_FREE; /* current */
|
sshc->state = SSH_SESSION_FREE; /* current */
|
||||||
sshc->nextstate = SSH_NO_STATE;
|
sshc->nextstate = SSH_NO_STATE;
|
||||||
myssh_to(data, sshc, SSH_STOP);
|
myssh_to(data, sshc, SSH_STOP);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue