mirror of
https://github.com/curl/curl.git
synced 2026-04-11 12:01:42 +08:00
libssh: split myssh_statemach_act into sub functions and rename
Follow-up to bd3b2a626a
- rename it to myssh_statemachine
- remove the use of ternary operators in the switch
- fix the error handling for if 'sshp' actually ever is NULL
Closes #21250
This commit is contained in:
parent
a20989b82c
commit
b168fc79ff
@ -357,6 +357,8 @@ static int myssh_in_SFTP_READDIR_INIT(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc,
|
||||
struct SSHPROTO *sshp)
|
||||
{
|
||||
if(!sshp)
|
||||
return myssh_to_ERROR(data, sshc, CURLE_FAILED_INIT);
|
||||
Curl_pgrsSetDownloadSize(data, -1);
|
||||
if(data->req.no_body) {
|
||||
myssh_to(data, sshc, SSH_STOP);
|
||||
@ -384,6 +386,8 @@ static int myssh_in_SFTP_READDIR(struct Curl_easy *data,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
if(!sshp)
|
||||
return myssh_to_ERROR(data, sshc, CURLE_FAILED_INIT);
|
||||
curlx_dyn_reset(&sshc->readdir_buf);
|
||||
if(sshc->readdir_attrs)
|
||||
sftp_attributes_free(sshc->readdir_attrs);
|
||||
@ -959,6 +963,9 @@ static int myssh_in_UPLOAD_INIT(struct Curl_easy *data,
|
||||
int flags;
|
||||
int rc = 0;
|
||||
|
||||
if(!sshp)
|
||||
return myssh_to_ERROR(data, sshc, CURLE_FAILED_INIT);
|
||||
|
||||
if(data->state.resume_from) {
|
||||
sftp_attributes attrs;
|
||||
|
||||
@ -1105,6 +1112,8 @@ static int myssh_in_SFTP_DOWNLOAD_INIT(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc,
|
||||
struct SSHPROTO *sshp)
|
||||
{
|
||||
if(!sshp)
|
||||
return myssh_to_ERROR(data, sshc, CURLE_FAILED_INIT);
|
||||
/* Work on getting the specified file */
|
||||
if(sshc->sftp_file)
|
||||
sftp_close(sshc->sftp_file);
|
||||
@ -1222,6 +1231,8 @@ static int myssh_in_SFTP_CLOSE(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc,
|
||||
struct SSHPROTO *sshp)
|
||||
{
|
||||
if(!sshp)
|
||||
return myssh_to_ERROR(data, sshc, CURLE_FAILED_INIT);
|
||||
if(sshc->sftp_file) {
|
||||
sftp_close(sshc->sftp_file);
|
||||
sshc->sftp_file = NULL;
|
||||
@ -1321,7 +1332,12 @@ static int myssh_in_SFTP_QUOTE_INIT(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc,
|
||||
struct SSHPROTO *sshp)
|
||||
{
|
||||
CURLcode result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
|
||||
CURLcode result;
|
||||
|
||||
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);
|
||||
@ -1375,6 +1391,9 @@ static int myssh_in_SFTP_QUOTE(struct Curl_easy *data,
|
||||
const char *cmd = sshc->quote_item->data;
|
||||
sshc->acceptfail = FALSE;
|
||||
|
||||
if(!sshp)
|
||||
return myssh_to_ERROR(data, sshc, CURLE_FAILED_INIT);
|
||||
|
||||
/* if a command starts with an asterisk, which a legal SFTP command never
|
||||
can, the command is allowed to fail without it causing any
|
||||
aborts or cancels etc. It causes libcurl to act as if the command
|
||||
@ -1842,19 +1861,337 @@ static void sshc_cleanup(struct ssh_conn *sshc)
|
||||
}
|
||||
}
|
||||
|
||||
static int myssh_in_SFTP_QUOTE_SETSTAT(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc)
|
||||
{
|
||||
int rc = sftp_setstat(sshc->sftp_session, sshc->quote_path2,
|
||||
sshc->quote_attrs);
|
||||
if(rc == SSH_AGAIN)
|
||||
return rc;
|
||||
if(rc && !sshc->acceptfail) {
|
||||
myssh_quote_error(data, sshc, "setstat");
|
||||
return rc;
|
||||
}
|
||||
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
||||
return SSH_NO_ERROR;
|
||||
}
|
||||
|
||||
static int myssh_in_SFTP_QUOTE_SYMLINK(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc)
|
||||
{
|
||||
int rc = sftp_symlink(sshc->sftp_session, sshc->quote_path2,
|
||||
sshc->quote_path1);
|
||||
if(rc == SSH_AGAIN)
|
||||
return rc;
|
||||
if(rc && !sshc->acceptfail) {
|
||||
myssh_quote_error(data, sshc, "symlink");
|
||||
return rc;
|
||||
}
|
||||
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
||||
return SSH_NO_ERROR;
|
||||
}
|
||||
|
||||
static int myssh_in_SFTP_QUOTE_MKDIR(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc)
|
||||
{
|
||||
int rc = sftp_mkdir(sshc->sftp_session, sshc->quote_path1,
|
||||
(mode_t)data->set.new_directory_perms);
|
||||
if(rc == SSH_AGAIN)
|
||||
return rc;
|
||||
if(rc && !sshc->acceptfail) {
|
||||
myssh_quote_error(data, sshc, "mkdir");
|
||||
return rc;
|
||||
}
|
||||
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
||||
return SSH_NO_ERROR;
|
||||
}
|
||||
|
||||
static int myssh_in_SFTP_QUOTE_RENAME(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc)
|
||||
{
|
||||
int rc = sftp_rename(sshc->sftp_session, sshc->quote_path1,
|
||||
sshc->quote_path2);
|
||||
if(rc == SSH_AGAIN)
|
||||
return rc;
|
||||
if(rc && !sshc->acceptfail) {
|
||||
myssh_quote_error(data, sshc, "rename");
|
||||
return rc;
|
||||
}
|
||||
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
||||
return SSH_NO_ERROR;
|
||||
}
|
||||
|
||||
static int myssh_in_SFTP_QUOTE_RMDIR(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc)
|
||||
{
|
||||
int rc = sftp_rmdir(sshc->sftp_session, sshc->quote_path1);
|
||||
if(rc == SSH_AGAIN)
|
||||
return rc;
|
||||
if(rc && !sshc->acceptfail) {
|
||||
myssh_quote_error(data, sshc, "rmdir");
|
||||
return rc;
|
||||
}
|
||||
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
||||
return SSH_NO_ERROR;
|
||||
}
|
||||
|
||||
static int myssh_in_SFTP_QUOTE_UNLINK(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc)
|
||||
{
|
||||
int rc = sftp_unlink(sshc->sftp_session, sshc->quote_path1);
|
||||
if(rc == SSH_AGAIN)
|
||||
return rc;
|
||||
if(rc && !sshc->acceptfail) {
|
||||
myssh_quote_error(data, sshc, "rm");
|
||||
return rc;
|
||||
}
|
||||
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
||||
return SSH_NO_ERROR;
|
||||
}
|
||||
|
||||
static int myssh_in_SFTP_GETINFO(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc)
|
||||
{
|
||||
if(data->set.get_filetime)
|
||||
myssh_to(data, sshc, SSH_SFTP_FILETIME);
|
||||
else
|
||||
myssh_to(data, sshc, SSH_SFTP_TRANS_INIT);
|
||||
return SSH_NO_ERROR;
|
||||
}
|
||||
|
||||
static int myssh_in_SFTP_FILETIME(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc,
|
||||
struct SSHPROTO *sshp)
|
||||
{
|
||||
sftp_attributes attrs;
|
||||
if(!sshp)
|
||||
return myssh_to_ERROR(data, sshc, CURLE_FAILED_INIT);
|
||||
|
||||
attrs = sftp_stat(sshc->sftp_session, sshp->path);
|
||||
if(attrs) {
|
||||
data->info.filetime = attrs->mtime;
|
||||
sftp_attributes_free(attrs);
|
||||
}
|
||||
|
||||
myssh_to(data, sshc, SSH_SFTP_TRANS_INIT);
|
||||
return SSH_NO_ERROR;
|
||||
}
|
||||
|
||||
static int myssh_in_SFTP_TRANS_INIT(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc,
|
||||
struct SSHPROTO *sshp)
|
||||
{
|
||||
if(!sshp)
|
||||
return myssh_to_ERROR(data, sshc, CURLE_FAILED_INIT);
|
||||
if(data->state.upload)
|
||||
myssh_to(data, sshc, SSH_SFTP_UPLOAD_INIT);
|
||||
else {
|
||||
size_t path_len = strlen(sshp->path);
|
||||
|
||||
if(path_len && sshp->path[path_len - 1] == '/')
|
||||
myssh_to(data, sshc, SSH_SFTP_READDIR_INIT);
|
||||
else
|
||||
myssh_to(data, sshc, SSH_SFTP_DOWNLOAD_INIT);
|
||||
}
|
||||
|
||||
return SSH_NO_ERROR;
|
||||
}
|
||||
|
||||
static int myssh_in_SFTP_CREATE_DIRS_INIT(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc,
|
||||
struct SSHPROTO *sshp)
|
||||
{
|
||||
if(!sshp)
|
||||
return myssh_to_ERROR(data, sshc, CURLE_FAILED_INIT);
|
||||
|
||||
if(strlen(sshp->path) > 1) {
|
||||
sshc->slash_pos = sshp->path + 1; /* ignore the leading '/' */
|
||||
myssh_to(data, sshc, SSH_SFTP_CREATE_DIRS);
|
||||
}
|
||||
else {
|
||||
myssh_to(data, sshc, SSH_SFTP_UPLOAD_INIT);
|
||||
}
|
||||
return SSH_NO_ERROR;
|
||||
}
|
||||
|
||||
static int myssh_in_SFTP_CREATE_DIRS(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc,
|
||||
struct SSHPROTO *sshp)
|
||||
{
|
||||
if(!sshp)
|
||||
return myssh_to_ERROR(data, sshc, CURLE_FAILED_INIT);
|
||||
|
||||
sshc->slash_pos = strchr(sshc->slash_pos, '/');
|
||||
if(sshc->slash_pos) {
|
||||
*sshc->slash_pos = 0;
|
||||
|
||||
infof(data, "Creating directory '%s'", sshp->path);
|
||||
myssh_to(data, sshc, SSH_SFTP_CREATE_DIRS_MKDIR);
|
||||
return SSH_NO_ERROR;
|
||||
}
|
||||
myssh_to(data, sshc, SSH_SFTP_UPLOAD_INIT);
|
||||
return SSH_NO_ERROR;
|
||||
}
|
||||
|
||||
static int myssh_in_SFTP_CREATE_DIRS_MKDIR(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc,
|
||||
struct SSHPROTO *sshp)
|
||||
{
|
||||
int rc;
|
||||
int err;
|
||||
/* 'mode' - parameter is preliminary - default to 0644 */
|
||||
if(!sshp)
|
||||
return myssh_to_ERROR(data, sshc, CURLE_FAILED_INIT);
|
||||
|
||||
rc = sftp_mkdir(sshc->sftp_session, sshp->path,
|
||||
(mode_t)data->set.new_directory_perms);
|
||||
if(rc == SSH_AGAIN)
|
||||
return rc;
|
||||
*sshc->slash_pos = '/';
|
||||
++sshc->slash_pos;
|
||||
if(rc < 0) {
|
||||
/*
|
||||
* Abort if failure was not that the directory already
|
||||
* exists or the permission was denied (creation might
|
||||
* succeed further down the path) - retry on unspecific
|
||||
* FAILURE also
|
||||
*/
|
||||
err = sftp_get_error(sshc->sftp_session);
|
||||
if((err != SSH_FX_FILE_ALREADY_EXISTS) &&
|
||||
(err != SSH_FX_FAILURE) &&
|
||||
(err != SSH_FX_PERMISSION_DENIED)) {
|
||||
return myssh_to_SFTP_CLOSE(data, sshc);
|
||||
}
|
||||
rc = 0; /* clear rc and continue */
|
||||
}
|
||||
myssh_to(data, sshc, SSH_SFTP_CREATE_DIRS);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int myssh_in_SCP_UPLOAD_INIT(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc,
|
||||
struct SSHPROTO *sshp)
|
||||
{
|
||||
int rc;
|
||||
if(!sshp)
|
||||
return myssh_to_ERROR(data, sshc, CURLE_FAILED_INIT);
|
||||
|
||||
rc = ssh_scp_init(sshc->scp_session);
|
||||
if(rc != SSH_OK) {
|
||||
const char *err_msg = ssh_get_error(sshc->ssh_session);
|
||||
failf(data, "%s", err_msg);
|
||||
return myssh_to_ERROR(data, sshc, CURLE_UPLOAD_FAILED);
|
||||
}
|
||||
|
||||
rc = ssh_scp_push_file64(sshc->scp_session, sshp->path,
|
||||
(uint64_t)data->state.infilesize,
|
||||
(int)data->set.new_file_perms);
|
||||
|
||||
if(rc != SSH_OK) {
|
||||
const char *err_msg = ssh_get_error(sshc->ssh_session);
|
||||
failf(data, "%s", err_msg);
|
||||
return myssh_to_ERROR(data, sshc, CURLE_UPLOAD_FAILED);
|
||||
}
|
||||
|
||||
/* upload data */
|
||||
Curl_xfer_setup_send(data, FIRSTSOCKET);
|
||||
|
||||
/* not set by Curl_xfer_setup to preserve io_flags */
|
||||
data->conn->recv_idx = FIRSTSOCKET;
|
||||
|
||||
myssh_to(data, sshc, SSH_STOP);
|
||||
return SSH_NO_ERROR;
|
||||
}
|
||||
|
||||
static int myssh_in_SCP_DOWNLOAD_INIT(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc)
|
||||
{
|
||||
int rc = ssh_scp_init(sshc->scp_session);
|
||||
if(rc != SSH_OK) {
|
||||
const char *err_msg = ssh_get_error(sshc->ssh_session);
|
||||
failf(data, "%s", err_msg);
|
||||
return myssh_to_ERROR(data, sshc,
|
||||
CURLE_COULDNT_CONNECT);
|
||||
}
|
||||
myssh_to(data, sshc, SSH_SCP_DOWNLOAD);
|
||||
return SSH_NO_ERROR;
|
||||
}
|
||||
|
||||
static int myssh_in_SCP_DONE(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc)
|
||||
{
|
||||
if(data->state.upload)
|
||||
myssh_to(data, sshc, SSH_SCP_SEND_EOF);
|
||||
else
|
||||
myssh_to(data, sshc, SSH_SCP_CHANNEL_FREE);
|
||||
return SSH_NO_ERROR;
|
||||
}
|
||||
|
||||
static int myssh_in_SCP_SEND_EOF(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc)
|
||||
{
|
||||
if(sshc->scp_session) {
|
||||
int rc = ssh_scp_close(sshc->scp_session);
|
||||
if(rc == SSH_AGAIN) {
|
||||
/* Currently the ssh_scp_close handles waiting for
|
||||
* EOF in blocking way.
|
||||
*/
|
||||
return SSH_AGAIN;
|
||||
}
|
||||
if(rc != SSH_OK) {
|
||||
infof(data,
|
||||
"Failed to close libssh scp channel: %s",
|
||||
ssh_get_error(sshc->ssh_session));
|
||||
}
|
||||
}
|
||||
|
||||
myssh_to(data, sshc, SSH_SCP_CHANNEL_FREE);
|
||||
return SSH_NO_ERROR;
|
||||
}
|
||||
|
||||
static int myssh_in_SCP_CHANNEL_FREE(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc)
|
||||
{
|
||||
if(sshc->scp_session) {
|
||||
ssh_scp_free(sshc->scp_session);
|
||||
sshc->scp_session = NULL;
|
||||
}
|
||||
CURL_TRC_SSH(data, "SCP DONE phase complete");
|
||||
|
||||
ssh_set_blocking(sshc->ssh_session, 0);
|
||||
|
||||
myssh_to(data, sshc, SSH_SESSION_DISCONNECT);
|
||||
return SSH_NO_ERROR;
|
||||
}
|
||||
|
||||
static CURLcode myssh_in_SESSION_FREE(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc)
|
||||
{
|
||||
CURLcode result;
|
||||
sshc_cleanup(sshc);
|
||||
/* the code we are about to return */
|
||||
result = sshc->actualcode;
|
||||
memset(sshc, 0, sizeof(struct ssh_conn));
|
||||
connclose(data->conn, "SSH session free");
|
||||
sshc->state = SSH_SESSION_FREE; /* current */
|
||||
sshc->nextstate = SSH_NO_STATE;
|
||||
myssh_to(data, sshc, SSH_STOP);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* ssh_statemach_act() runs the SSH state machine as far as it can without
|
||||
* myssh_statemachine() runs the SSH state machine as far as it can without
|
||||
* blocking and without reaching the end. The data the pointer 'block' points
|
||||
* to is set to TRUE if the libssh function returns SSH_AGAIN
|
||||
* meaning it wants to be called again when the socket is ready
|
||||
*/
|
||||
static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc,
|
||||
struct SSHPROTO *sshp,
|
||||
bool *block)
|
||||
static CURLcode myssh_statemachine(struct Curl_easy *data,
|
||||
struct ssh_conn *sshc,
|
||||
struct SSHPROTO *sshp,
|
||||
bool *block)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
int rc = SSH_NO_ERROR, err;
|
||||
int rc = SSH_NO_ERROR;
|
||||
|
||||
*block = FALSE; /* we are not blocking by default */
|
||||
do {
|
||||
@ -1910,14 +2247,13 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
||||
rc = myssh_in_SFTP_REALPATH(data, sshc);
|
||||
break;
|
||||
case SSH_SFTP_QUOTE_INIT:
|
||||
rc = sshp ? myssh_in_SFTP_QUOTE_INIT(data, sshc, sshp) :
|
||||
CURLE_FAILED_INIT;
|
||||
rc = myssh_in_SFTP_QUOTE_INIT(data, sshc, sshp);
|
||||
break;
|
||||
case SSH_SFTP_POSTQUOTE_INIT:
|
||||
rc = myssh_in_SFTP_POSTQUOTE_INIT(data, sshc);
|
||||
break;
|
||||
case SSH_SFTP_QUOTE:
|
||||
rc = sshp ? myssh_in_SFTP_QUOTE(data, sshc, sshp) : CURLE_FAILED_INIT;
|
||||
rc = myssh_in_SFTP_QUOTE(data, sshc, sshp);
|
||||
break;
|
||||
case SSH_SFTP_NEXT_QUOTE:
|
||||
rc = myssh_in_SFTP_NEXT_QUOTE(data, sshc);
|
||||
@ -1926,188 +2262,52 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
||||
rc = myssh_in_SFTP_QUOTE_STAT(data, sshc);
|
||||
break;
|
||||
case SSH_SFTP_QUOTE_SETSTAT:
|
||||
rc = sftp_setstat(sshc->sftp_session, sshc->quote_path2,
|
||||
sshc->quote_attrs);
|
||||
if(rc == SSH_AGAIN)
|
||||
break;
|
||||
if(rc && !sshc->acceptfail) {
|
||||
myssh_quote_error(data, sshc, "setstat");
|
||||
break;
|
||||
}
|
||||
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
||||
rc = myssh_in_SFTP_QUOTE_SETSTAT(data, sshc);
|
||||
break;
|
||||
|
||||
case SSH_SFTP_QUOTE_SYMLINK:
|
||||
rc = sftp_symlink(sshc->sftp_session, sshc->quote_path2,
|
||||
sshc->quote_path1);
|
||||
if(rc == SSH_AGAIN)
|
||||
break;
|
||||
if(rc && !sshc->acceptfail) {
|
||||
myssh_quote_error(data, sshc, "symlink");
|
||||
break;
|
||||
}
|
||||
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
||||
rc = myssh_in_SFTP_QUOTE_SYMLINK(data, sshc);
|
||||
break;
|
||||
|
||||
case SSH_SFTP_QUOTE_MKDIR:
|
||||
rc = sftp_mkdir(sshc->sftp_session, sshc->quote_path1,
|
||||
(mode_t)data->set.new_directory_perms);
|
||||
if(rc == SSH_AGAIN)
|
||||
break;
|
||||
if(rc && !sshc->acceptfail) {
|
||||
myssh_quote_error(data, sshc, "mkdir");
|
||||
break;
|
||||
}
|
||||
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
||||
rc = myssh_in_SFTP_QUOTE_MKDIR(data, sshc);
|
||||
break;
|
||||
|
||||
case SSH_SFTP_QUOTE_RENAME:
|
||||
rc = sftp_rename(sshc->sftp_session, sshc->quote_path1,
|
||||
sshc->quote_path2);
|
||||
if(rc == SSH_AGAIN)
|
||||
break;
|
||||
if(rc && !sshc->acceptfail) {
|
||||
myssh_quote_error(data, sshc, "rename");
|
||||
break;
|
||||
}
|
||||
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
||||
rc = myssh_in_SFTP_QUOTE_RENAME(data, sshc);
|
||||
break;
|
||||
|
||||
case SSH_SFTP_QUOTE_RMDIR:
|
||||
rc = sftp_rmdir(sshc->sftp_session, sshc->quote_path1);
|
||||
if(rc == SSH_AGAIN)
|
||||
break;
|
||||
if(rc && !sshc->acceptfail) {
|
||||
myssh_quote_error(data, sshc, "rmdir");
|
||||
break;
|
||||
}
|
||||
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
||||
rc = myssh_in_SFTP_QUOTE_RMDIR(data, sshc);
|
||||
break;
|
||||
|
||||
case SSH_SFTP_QUOTE_UNLINK:
|
||||
rc = sftp_unlink(sshc->sftp_session, sshc->quote_path1);
|
||||
if(rc == SSH_AGAIN)
|
||||
break;
|
||||
if(rc && !sshc->acceptfail) {
|
||||
myssh_quote_error(data, sshc, "rm");
|
||||
break;
|
||||
}
|
||||
myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
|
||||
rc = myssh_in_SFTP_QUOTE_UNLINK(data, sshc);
|
||||
break;
|
||||
|
||||
case SSH_SFTP_QUOTE_STATVFS:
|
||||
rc = myssh_in_SFTP_QUOTE_STATVFS(data, sshc);
|
||||
break;
|
||||
|
||||
case SSH_SFTP_GETINFO:
|
||||
if(data->set.get_filetime) {
|
||||
myssh_to(data, sshc, SSH_SFTP_FILETIME);
|
||||
}
|
||||
else {
|
||||
myssh_to(data, sshc, SSH_SFTP_TRANS_INIT);
|
||||
}
|
||||
rc = myssh_in_SFTP_GETINFO(data, sshc);
|
||||
break;
|
||||
|
||||
case SSH_SFTP_FILETIME: {
|
||||
sftp_attributes attrs;
|
||||
if(!sshp) {
|
||||
result = CURLE_FAILED_INIT;
|
||||
break;
|
||||
}
|
||||
attrs = sftp_stat(sshc->sftp_session, sshp->path);
|
||||
if(attrs) {
|
||||
data->info.filetime = attrs->mtime;
|
||||
sftp_attributes_free(attrs);
|
||||
}
|
||||
|
||||
myssh_to(data, sshc, SSH_SFTP_TRANS_INIT);
|
||||
case SSH_SFTP_FILETIME:
|
||||
rc = myssh_in_SFTP_FILETIME(data, sshc, sshp);
|
||||
break;
|
||||
}
|
||||
|
||||
case SSH_SFTP_TRANS_INIT:
|
||||
if(data->state.upload)
|
||||
myssh_to(data, sshc, SSH_SFTP_UPLOAD_INIT);
|
||||
else if(sshp) {
|
||||
size_t path_len = strlen(sshp->path);
|
||||
|
||||
if(path_len && sshp->path[path_len - 1] == '/')
|
||||
myssh_to(data, sshc, SSH_SFTP_READDIR_INIT);
|
||||
else
|
||||
myssh_to(data, sshc, SSH_SFTP_DOWNLOAD_INIT);
|
||||
}
|
||||
else
|
||||
result = CURLE_FAILED_INIT;
|
||||
rc = myssh_in_SFTP_TRANS_INIT(data, sshc, sshp);
|
||||
break;
|
||||
|
||||
case SSH_SFTP_UPLOAD_INIT:
|
||||
rc = sshp ? myssh_in_UPLOAD_INIT(data, sshc, sshp) :
|
||||
CURLE_FAILED_INIT;
|
||||
rc = myssh_in_UPLOAD_INIT(data, sshc, sshp);
|
||||
break;
|
||||
|
||||
case SSH_SFTP_CREATE_DIRS_INIT:
|
||||
if(!sshp) {
|
||||
result = CURLE_FAILED_INIT;
|
||||
break;
|
||||
}
|
||||
else if(strlen(sshp->path) > 1) {
|
||||
sshc->slash_pos = sshp->path + 1; /* ignore the leading '/' */
|
||||
myssh_to(data, sshc, SSH_SFTP_CREATE_DIRS);
|
||||
}
|
||||
else {
|
||||
myssh_to(data, sshc, SSH_SFTP_UPLOAD_INIT);
|
||||
}
|
||||
rc = myssh_in_SFTP_CREATE_DIRS_INIT(data, sshc, sshp);
|
||||
break;
|
||||
|
||||
case SSH_SFTP_CREATE_DIRS:
|
||||
sshc->slash_pos = strchr(sshc->slash_pos, '/');
|
||||
if(!sshp) {
|
||||
result = CURLE_FAILED_INIT;
|
||||
break;
|
||||
}
|
||||
else if(sshc->slash_pos) {
|
||||
*sshc->slash_pos = 0;
|
||||
|
||||
infof(data, "Creating directory '%s'", sshp->path);
|
||||
myssh_to(data, sshc, SSH_SFTP_CREATE_DIRS_MKDIR);
|
||||
break;
|
||||
}
|
||||
myssh_to(data, sshc, SSH_SFTP_UPLOAD_INIT);
|
||||
rc = myssh_in_SFTP_CREATE_DIRS(data, sshc, sshp);
|
||||
break;
|
||||
|
||||
case SSH_SFTP_CREATE_DIRS_MKDIR:
|
||||
/* 'mode' - parameter is preliminary - default to 0644 */
|
||||
if(!sshp) {
|
||||
result = CURLE_FAILED_INIT;
|
||||
break;
|
||||
}
|
||||
rc = sftp_mkdir(sshc->sftp_session, sshp->path,
|
||||
(mode_t)data->set.new_directory_perms);
|
||||
*sshc->slash_pos = '/';
|
||||
++sshc->slash_pos;
|
||||
if(rc < 0) {
|
||||
/*
|
||||
* Abort if failure was not that the directory already exists or
|
||||
* the permission was denied (creation might succeed further down
|
||||
* the path) - retry on unspecific FAILURE also
|
||||
*/
|
||||
err = sftp_get_error(sshc->sftp_session);
|
||||
if((err != SSH_FX_FILE_ALREADY_EXISTS) &&
|
||||
(err != SSH_FX_FAILURE) &&
|
||||
(err != SSH_FX_PERMISSION_DENIED)) {
|
||||
rc = myssh_to_SFTP_CLOSE(data, sshc);
|
||||
break;
|
||||
}
|
||||
rc = 0; /* clear rc and continue */
|
||||
}
|
||||
myssh_to(data, sshc, SSH_SFTP_CREATE_DIRS);
|
||||
rc = myssh_in_SFTP_CREATE_DIRS_MKDIR(data, sshc, sshp);
|
||||
break;
|
||||
|
||||
case SSH_SFTP_READDIR_INIT:
|
||||
rc = sshp ? myssh_in_SFTP_READDIR_INIT(data, sshc, sshp) :
|
||||
CURLE_FAILED_INIT;
|
||||
rc = myssh_in_SFTP_READDIR_INIT(data, sshc, sshp);
|
||||
break;
|
||||
case SSH_SFTP_READDIR:
|
||||
rc = sshp ? myssh_in_SFTP_READDIR(data, sshc, sshp) : CURLE_FAILED_INIT;
|
||||
rc = myssh_in_SFTP_READDIR(data, sshc, sshp);
|
||||
break;
|
||||
case SSH_SFTP_READDIR_LINK:
|
||||
rc = myssh_in_SFTP_READDIR_LINK(data, sshc);
|
||||
@ -2119,14 +2319,13 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
||||
rc = myssh_in_SFTP_READDIR_DONE(data, sshc);
|
||||
break;
|
||||
case SSH_SFTP_DOWNLOAD_INIT:
|
||||
rc = sshp ? myssh_in_SFTP_DOWNLOAD_INIT(data, sshc, sshp) :
|
||||
CURLE_FAILED_INIT;
|
||||
rc = myssh_in_SFTP_DOWNLOAD_INIT(data, sshc, sshp);
|
||||
break;
|
||||
case SSH_SFTP_DOWNLOAD_STAT:
|
||||
rc = myssh_in_SFTP_DOWNLOAD_STAT(data, sshc);
|
||||
break;
|
||||
case SSH_SFTP_CLOSE:
|
||||
rc = sshp ? myssh_in_SFTP_CLOSE(data, sshc, sshp) : CURLE_FAILED_INIT;
|
||||
rc = myssh_in_SFTP_CLOSE(data, sshc, sshp);
|
||||
break;
|
||||
case SSH_SFTP_SHUTDOWN:
|
||||
rc = myssh_in_SFTP_SHUTDOWN(data, sshc);
|
||||
@ -2134,107 +2333,32 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
|
||||
case SSH_SCP_TRANS_INIT:
|
||||
rc = myssh_in_TRANS_INIT(data, sshc, sshp);
|
||||
break;
|
||||
|
||||
case SSH_SCP_UPLOAD_INIT:
|
||||
if(!sshp) {
|
||||
result = CURLE_FAILED_INIT;
|
||||
break;
|
||||
}
|
||||
rc = ssh_scp_init(sshc->scp_session);
|
||||
if(rc != SSH_OK) {
|
||||
const char *err_msg = ssh_get_error(sshc->ssh_session);
|
||||
failf(data, "%s", err_msg);
|
||||
rc = myssh_to_ERROR(data, sshc, CURLE_UPLOAD_FAILED);
|
||||
break;
|
||||
}
|
||||
|
||||
rc = ssh_scp_push_file64(sshc->scp_session, sshp->path,
|
||||
(uint64_t)data->state.infilesize,
|
||||
(int)data->set.new_file_perms);
|
||||
|
||||
if(rc != SSH_OK) {
|
||||
const char *err_msg = ssh_get_error(sshc->ssh_session);
|
||||
failf(data, "%s", err_msg);
|
||||
rc = myssh_to_ERROR(data, sshc, CURLE_UPLOAD_FAILED);
|
||||
break;
|
||||
}
|
||||
|
||||
/* upload data */
|
||||
Curl_xfer_setup_send(data, FIRSTSOCKET);
|
||||
|
||||
/* not set by Curl_xfer_setup to preserve io_flags */
|
||||
data->conn->recv_idx = FIRSTSOCKET;
|
||||
|
||||
myssh_to(data, sshc, SSH_STOP);
|
||||
|
||||
rc = myssh_in_SCP_UPLOAD_INIT(data, sshc, sshp);
|
||||
break;
|
||||
|
||||
case SSH_SCP_DOWNLOAD_INIT:
|
||||
rc = ssh_scp_init(sshc->scp_session);
|
||||
if(rc != SSH_OK) {
|
||||
const char *err_msg = ssh_get_error(sshc->ssh_session);
|
||||
failf(data, "%s", err_msg);
|
||||
rc = myssh_to_ERROR(data, sshc, CURLE_COULDNT_CONNECT);
|
||||
rc = myssh_in_SCP_DOWNLOAD_INIT(data, sshc);
|
||||
if(rc)
|
||||
break;
|
||||
}
|
||||
myssh_to(data, sshc, SSH_SCP_DOWNLOAD);
|
||||
FALLTHROUGH();
|
||||
|
||||
case SSH_SCP_DOWNLOAD:
|
||||
rc = myssh_SSH_SCP_DOWNLOAD(data, sshc);
|
||||
break;
|
||||
|
||||
case SSH_SCP_DONE:
|
||||
if(data->state.upload)
|
||||
myssh_to(data, sshc, SSH_SCP_SEND_EOF);
|
||||
else
|
||||
myssh_to(data, sshc, SSH_SCP_CHANNEL_FREE);
|
||||
rc = myssh_in_SCP_DONE(data, sshc);
|
||||
break;
|
||||
|
||||
case SSH_SCP_SEND_EOF:
|
||||
if(sshc->scp_session) {
|
||||
rc = ssh_scp_close(sshc->scp_session);
|
||||
if(rc == SSH_AGAIN) {
|
||||
/* Currently the ssh_scp_close handles waiting for EOF in
|
||||
* blocking way.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
if(rc != SSH_OK) {
|
||||
infof(data, "Failed to close libssh scp channel: %s",
|
||||
ssh_get_error(sshc->ssh_session));
|
||||
}
|
||||
}
|
||||
|
||||
myssh_to(data, sshc, SSH_SCP_CHANNEL_FREE);
|
||||
rc = myssh_in_SCP_SEND_EOF(data, sshc);
|
||||
break;
|
||||
|
||||
case SSH_SCP_CHANNEL_FREE:
|
||||
if(sshc->scp_session) {
|
||||
ssh_scp_free(sshc->scp_session);
|
||||
sshc->scp_session = NULL;
|
||||
}
|
||||
CURL_TRC_SSH(data, "SCP DONE phase complete");
|
||||
|
||||
ssh_set_blocking(sshc->ssh_session, 0);
|
||||
|
||||
myssh_to(data, sshc, SSH_SESSION_DISCONNECT);
|
||||
myssh_in_SCP_CHANNEL_FREE(data, sshc);
|
||||
FALLTHROUGH();
|
||||
|
||||
case SSH_SESSION_DISCONNECT:
|
||||
myssh_SESSION_DISCONNECT(data, sshc);
|
||||
FALLTHROUGH();
|
||||
case SSH_SESSION_FREE:
|
||||
sshc_cleanup(sshc);
|
||||
/* the code we are about to return */
|
||||
result = sshc->actualcode;
|
||||
memset(sshc, 0, sizeof(struct ssh_conn));
|
||||
connclose(data->conn, "SSH session free");
|
||||
sshc->state = SSH_SESSION_FREE; /* current */
|
||||
sshc->nextstate = SSH_NO_STATE;
|
||||
myssh_to(data, sshc, SSH_STOP);
|
||||
result = myssh_in_SESSION_FREE(data, sshc);
|
||||
break;
|
||||
|
||||
case SSH_QUIT:
|
||||
default:
|
||||
/* internal error */
|
||||
@ -2301,7 +2425,7 @@ static CURLcode myssh_multi_statemach(struct Curl_easy *data,
|
||||
|
||||
if(!sshc || !sshp)
|
||||
return CURLE_FAILED_INIT;
|
||||
result = myssh_statemach_act(data, sshc, sshp, &block);
|
||||
result = myssh_statemachine(data, sshc, sshp, &block);
|
||||
*done = (sshc->state == SSH_STOP);
|
||||
myssh_block2waitfor(conn, sshc, block);
|
||||
|
||||
@ -2320,7 +2444,7 @@ static CURLcode myssh_block_statemach(struct Curl_easy *data,
|
||||
bool block;
|
||||
timediff_t left_ms = 1000;
|
||||
|
||||
result = myssh_statemach_act(data, sshc, sshp, &block);
|
||||
result = myssh_statemachine(data, sshc, sshp, &block);
|
||||
if(result)
|
||||
break;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user