summaryrefslogtreecommitdiff
path: root/Utilities/cmcurl/lib/vssh/libssh.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmcurl/lib/vssh/libssh.c')
-rw-r--r--Utilities/cmcurl/lib/vssh/libssh.c558
1 files changed, 295 insertions, 263 deletions
diff --git a/Utilities/cmcurl/lib/vssh/libssh.c b/Utilities/cmcurl/lib/vssh/libssh.c
index 8988e2392..08896ab5b 100644
--- a/Utilities/cmcurl/lib/vssh/libssh.c
+++ b/Utilities/cmcurl/lib/vssh/libssh.c
@@ -5,14 +5,14 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2017 - 2020 Red Hat, Inc.
+ * Copyright (C) 2017 - 2021 Red Hat, Inc.
*
* Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek,
* Robert Kolcun, Andreas Schneider
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
@@ -107,34 +107,37 @@
#endif
/* Local functions: */
-static CURLcode myssh_connect(struct connectdata *conn, bool *done);
-static CURLcode myssh_multi_statemach(struct connectdata *conn,
+static CURLcode myssh_connect(struct Curl_easy *data, bool *done);
+static CURLcode myssh_multi_statemach(struct Curl_easy *data,
bool *done);
-static CURLcode myssh_do_it(struct connectdata *conn, bool *done);
+static CURLcode myssh_do_it(struct Curl_easy *data, bool *done);
-static CURLcode scp_done(struct connectdata *conn,
+static CURLcode scp_done(struct Curl_easy *data,
CURLcode, bool premature);
-static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done);
-static CURLcode scp_disconnect(struct connectdata *conn,
+static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done);
+static CURLcode scp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
bool dead_connection);
-static CURLcode sftp_done(struct connectdata *conn,
+static CURLcode sftp_done(struct Curl_easy *data,
CURLcode, bool premature);
-static CURLcode sftp_doing(struct connectdata *conn,
+static CURLcode sftp_doing(struct Curl_easy *data,
bool *dophase_done);
-static CURLcode sftp_disconnect(struct connectdata *conn, bool dead);
+static CURLcode sftp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool dead);
static
-CURLcode sftp_perform(struct connectdata *conn,
+CURLcode sftp_perform(struct Curl_easy *data,
bool *connected,
bool *dophase_done);
-static void sftp_quote(struct connectdata *conn);
-static void sftp_quote_stat(struct connectdata *conn);
-static int myssh_getsock(struct connectdata *conn, curl_socket_t *sock);
-static int myssh_perform_getsock(const struct connectdata *conn,
- curl_socket_t *sock);
+static void sftp_quote(struct Curl_easy *data);
+static void sftp_quote_stat(struct Curl_easy *data);
+static int myssh_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *sock);
-static CURLcode myssh_setup_connection(struct connectdata *conn);
+static CURLcode myssh_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
/*
* SCP protocol handler.
@@ -152,12 +155,13 @@ const struct Curl_handler Curl_handler_scp = {
myssh_getsock, /* proto_getsock */
myssh_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- myssh_perform_getsock, /* perform_getsock */
+ myssh_getsock, /* perform_getsock */
scp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_SSH, /* defport */
CURLPROTO_SCP, /* protocol */
+ CURLPROTO_SCP, /* family */
PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY /* flags */
};
@@ -177,12 +181,13 @@ const struct Curl_handler Curl_handler_sftp = {
myssh_getsock, /* proto_getsock */
myssh_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- myssh_perform_getsock, /* perform_getsock */
+ myssh_getsock, /* perform_getsock */
sftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_SSH, /* defport */
CURLPROTO_SFTP, /* protocol */
+ CURLPROTO_SFTP, /* family */
PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
| PROTOPT_NOURLQUERY /* flags */
};
@@ -221,12 +226,13 @@ static CURLcode sftp_error_to_CURLE(int err)
* SSH State machine related code
*/
/* This is the ONLY way to change SSH state! */
-static void mystate(struct connectdata *conn, sshstate nowstate
+static void mystate(struct Curl_easy *data, sshstate nowstate
#ifdef DEBUGBUILD
, int lineno
#endif
)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
@@ -295,7 +301,7 @@ static void mystate(struct connectdata *conn, sshstate nowstate
if(sshc->state != nowstate) {
- infof(conn->data, "SSH %p state change from %s to %s (line %d)\n",
+ infof(data, "SSH %p state change from %s to %s (line %d)\n",
(void *) sshc, names[sshc->state], names[nowstate],
lineno);
}
@@ -314,10 +320,10 @@ static void mystate(struct connectdata *conn, sshstate nowstate
*
* Returns SSH_OK or SSH_ERROR.
*/
-static int myssh_is_known(struct connectdata *conn)
+static int myssh_is_known(struct Curl_easy *data)
{
int rc;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
ssh_key pubkey;
size_t hlen;
@@ -527,10 +533,10 @@ static int myssh_is_known(struct connectdata *conn)
cleanup:
if(found_base64) {
- free(found_base64);
+ (free)(found_base64);
}
if(known_base64) {
- free(known_base64);
+ (free)(known_base64);
}
if(hash)
ssh_clean_pubkey_hash(&hash);
@@ -544,14 +550,14 @@ cleanup:
}
#define MOVE_TO_ERROR_STATE(_r) { \
- state(conn, SSH_SESSION_DISCONNECT); \
+ state(data, SSH_SESSION_DISCONNECT); \
sshc->actualcode = _r; \
rc = SSH_ERROR; \
break; \
}
#define MOVE_TO_SFTP_CLOSE_STATE() { \
- state(conn, SSH_SFTP_CLOSE); \
+ state(data, SSH_SFTP_CLOSE); \
sshc->actualcode = sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session)); \
rc = SSH_ERROR; \
break; \
@@ -560,7 +566,7 @@ cleanup:
#define MOVE_TO_LAST_AUTH \
if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \
rc = SSH_OK; \
- state(conn, SSH_AUTH_PASS_INIT); \
+ state(data, SSH_AUTH_PASS_INIT); \
break; \
} \
else { \
@@ -570,7 +576,7 @@ cleanup:
#define MOVE_TO_TERTIARY_AUTH \
if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \
rc = SSH_OK; \
- state(conn, SSH_AUTH_KEY_INIT); \
+ state(data, SSH_AUTH_KEY_INIT); \
break; \
} \
else { \
@@ -580,7 +586,7 @@ cleanup:
#define MOVE_TO_SECONDARY_AUTH \
if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \
rc = SSH_OK; \
- state(conn, SSH_AUTH_GSSAPI); \
+ state(data, SSH_AUTH_GSSAPI); \
break; \
} \
else { \
@@ -658,11 +664,11 @@ restart:
* to will be 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 connectdata *conn, bool *block)
+static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct SSHPROTO *protop = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct SSHPROTO *protop = data->req.p.ssh;
struct ssh_conn *sshc = &conn->proto.sshc;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
int rc = SSH_NO_ERROR, err;
@@ -687,7 +693,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
non-blocking */
ssh_set_blocking(sshc->ssh_session, 0);
- state(conn, SSH_S_STARTUP);
+ state(data, SSH_S_STARTUP);
/* FALLTHROUGH */
case SSH_S_STARTUP:
@@ -700,17 +706,17 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
MOVE_TO_ERROR_STATE(CURLE_FAILED_INIT);
}
- state(conn, SSH_HOSTKEY);
+ state(data, SSH_HOSTKEY);
/* FALLTHROUGH */
case SSH_HOSTKEY:
- rc = myssh_is_known(conn);
+ rc = myssh_is_known(data);
if(rc != SSH_OK) {
MOVE_TO_ERROR_STATE(CURLE_PEER_FAILED_VERIFICATION);
}
- state(conn, SSH_AUTHLIST);
+ state(data, SSH_AUTHLIST);
/* FALLTHROUGH */
case SSH_AUTHLIST:{
sshc->authed = FALSE;
@@ -724,7 +730,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == SSH_AUTH_SUCCESS) {
sshc->authed = TRUE;
infof(data, "Authenticated with none\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
break;
}
else if(rc == SSH_AUTH_ERROR) {
@@ -733,17 +739,17 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL);
if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
- state(conn, SSH_AUTH_PKEY_INIT);
+ state(data, SSH_AUTH_PKEY_INIT);
infof(data, "Authentication using SSH public key file\n");
}
else if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) {
- state(conn, SSH_AUTH_GSSAPI);
+ state(data, SSH_AUTH_GSSAPI);
}
else if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) {
- state(conn, SSH_AUTH_KEY_INIT);
+ state(data, SSH_AUTH_KEY_INIT);
}
else if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) {
- state(conn, SSH_AUTH_PASS_INIT);
+ state(data, SSH_AUTH_PASS_INIT);
}
else { /* unsupported authentication method */
MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
@@ -783,7 +789,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
- state(conn, SSH_AUTH_PKEY);
+ state(data, SSH_AUTH_PKEY);
break;
}
@@ -798,7 +804,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
rc = SSH_OK;
sshc->authed = TRUE;
infof(data, "Completed public key authentication\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
break;
}
@@ -815,7 +821,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == SSH_AUTH_SUCCESS) {
sshc->authed = TRUE;
infof(data, "Completed public key authentication\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
break;
}
else {
@@ -839,7 +845,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
rc = SSH_OK;
sshc->authed = TRUE;
infof(data, "Completed gssapi authentication\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
break;
}
@@ -848,7 +854,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
case SSH_AUTH_KEY_INIT:
if(data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) {
- state(conn, SSH_AUTH_KEY);
+ state(data, SSH_AUTH_KEY);
}
else {
MOVE_TO_LAST_AUTH;
@@ -866,7 +872,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->authed = TRUE;
infof(data, "completed keyboard interactive authentication\n");
}
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
break;
case SSH_AUTH_PASS_INIT:
@@ -874,7 +880,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
/* Host key authentication is intentionally not implemented */
MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
}
- state(conn, SSH_AUTH_PASS);
+ state(data, SSH_AUTH_PASS);
/* FALLTHROUGH */
case SSH_AUTH_PASS:
@@ -887,7 +893,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == SSH_AUTH_SUCCESS) {
sshc->authed = TRUE;
infof(data, "Completed password authentication\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
}
else {
MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
@@ -906,17 +912,17 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
*/
infof(data, "Authentication complete\n");
- Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */
+ Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSH is connected */
conn->sockfd = sock;
conn->writesockfd = CURL_SOCKET_BAD;
if(conn->handler->protocol == CURLPROTO_SFTP) {
- state(conn, SSH_SFTP_INIT);
+ state(data, SSH_SFTP_INIT);
break;
}
infof(data, "SSH CONNECT phase done\n");
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_SFTP_INIT:
@@ -938,7 +944,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
MOVE_TO_ERROR_STATE(sftp_error_to_CURLE(rc));
break;
}
- state(conn, SSH_SFTP_REALPATH);
+ state(data, SSH_SFTP_REALPATH);
/* FALLTHROUGH */
case SSH_SFTP_REALPATH:
/*
@@ -948,32 +954,31 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(sshc->homedir == NULL) {
MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
}
- conn->data->state.most_recent_ftp_entrypath = sshc->homedir;
+ data->state.most_recent_ftp_entrypath = sshc->homedir;
/* This is the last step in the SFTP connect phase. Do note that while
we get the homedir here, we get the "workingpath" in the DO action
since the homedir will remain the same between request but the
working path will not. */
DEBUGF(infof(data, "SSH CONNECT phase done\n"));
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_SFTP_QUOTE_INIT:
-
- result = Curl_getworkingpath(conn, sshc->homedir, &protop->path);
+ result = Curl_getworkingpath(data, sshc->homedir, &protop->path);
if(result) {
sshc->actualcode = result;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
if(data->set.quote) {
infof(data, "Sending quote commands\n");
sshc->quote_item = data->set.quote;
- state(conn, SSH_SFTP_QUOTE);
+ state(data, SSH_SFTP_QUOTE);
}
else {
- state(conn, SSH_SFTP_GETINFO);
+ state(data, SSH_SFTP_GETINFO);
}
break;
@@ -981,16 +986,16 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(data->set.postquote) {
infof(data, "Sending quote commands\n");
sshc->quote_item = data->set.postquote;
- state(conn, SSH_SFTP_QUOTE);
+ state(data, SSH_SFTP_QUOTE);
}
else {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
case SSH_SFTP_QUOTE:
/* Send any quote commands */
- sftp_quote(conn);
+ sftp_quote(data);
break;
case SSH_SFTP_NEXT_QUOTE:
@@ -1000,21 +1005,21 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->quote_item = sshc->quote_item->next;
if(sshc->quote_item) {
- state(conn, SSH_SFTP_QUOTE);
+ state(data, SSH_SFTP_QUOTE);
}
else {
if(sshc->nextstate != SSH_NO_STATE) {
- state(conn, sshc->nextstate);
+ state(data, sshc->nextstate);
sshc->nextstate = SSH_NO_STATE;
}
else {
- state(conn, SSH_SFTP_GETINFO);
+ state(data, SSH_SFTP_GETINFO);
}
}
break;
case SSH_SFTP_QUOTE_STAT:
- sftp_quote_stat(conn);
+ sftp_quote_stat(data);
break;
case SSH_SFTP_QUOTE_SETSTAT:
@@ -1025,7 +1030,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "Attempt to set SFTP stats failed: %s",
ssh_get_error(sshc->ssh_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
/* sshc->actualcode = sftp_error_to_CURLE(err);
@@ -1033,7 +1038,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
* the error the libssh2 backend is returning */
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_SYMLINK:
@@ -1044,12 +1049,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "symlink command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_MKDIR:
@@ -1059,12 +1064,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "mkdir command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_RENAME:
@@ -1075,12 +1080,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "rename command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_RMDIR:
@@ -1089,12 +1094,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "rmdir command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_UNLINK:
@@ -1103,12 +1108,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "rm command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_STATVFS:
@@ -1120,7 +1125,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "statvfs command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
@@ -1143,29 +1148,29 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(!tmp) {
result = CURLE_OUT_OF_MEMORY;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
break;
}
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
free(tmp);
if(result) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
}
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
}
case SSH_SFTP_GETINFO:
if(data->set.get_filetime) {
- state(conn, SSH_SFTP_FILETIME);
+ state(data, SSH_SFTP_FILETIME);
}
else {
- state(conn, SSH_SFTP_TRANS_INIT);
+ state(data, SSH_SFTP_TRANS_INIT);
}
break;
@@ -1179,18 +1184,18 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sftp_attributes_free(attrs);
}
- state(conn, SSH_SFTP_TRANS_INIT);
+ state(data, SSH_SFTP_TRANS_INIT);
break;
}
case SSH_SFTP_TRANS_INIT:
if(data->set.upload)
- state(conn, SSH_SFTP_UPLOAD_INIT);
+ state(data, SSH_SFTP_UPLOAD_INIT);
else {
if(protop->path[strlen(protop->path)-1] == '/')
- state(conn, SSH_SFTP_READDIR_INIT);
+ state(data, SSH_SFTP_READDIR_INIT);
else
- state(conn, SSH_SFTP_DOWNLOAD_INIT);
+ state(data, SSH_SFTP_DOWNLOAD_INIT);
}
break;
@@ -1226,7 +1231,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
/* If we have restart position then open for append */
flags = O_WRONLY|O_APPEND;
else
- /* Clear file before writing (normal behaviour) */
+ /* Clear file before writing (normal behavior) */
flags = O_WRONLY|O_CREAT|O_TRUNC;
if(sshc->sftp_file)
@@ -1244,7 +1249,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
/* try to create the path remotely */
rc = 0;
sshc->secondCreateDirs = 1;
- state(conn, SSH_SFTP_CREATE_DIRS_INIT);
+ state(data, SSH_SFTP_CREATE_DIRS_INIT);
break;
}
else {
@@ -1327,17 +1332,17 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
timeout here */
Curl_expire(data, 0, EXPIRE_RUN_NOW);
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
case SSH_SFTP_CREATE_DIRS_INIT:
if(strlen(protop->path) > 1) {
sshc->slash_pos = protop->path + 1; /* ignore the leading '/' */
- state(conn, SSH_SFTP_CREATE_DIRS);
+ state(data, SSH_SFTP_CREATE_DIRS);
}
else {
- state(conn, SSH_SFTP_UPLOAD_INIT);
+ state(data, SSH_SFTP_UPLOAD_INIT);
}
break;
@@ -1347,10 +1352,10 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
*sshc->slash_pos = 0;
infof(data, "Creating directory '%s'\n", protop->path);
- state(conn, SSH_SFTP_CREATE_DIRS_MKDIR);
+ state(data, SSH_SFTP_CREATE_DIRS_MKDIR);
break;
}
- state(conn, SSH_SFTP_UPLOAD_INIT);
+ state(data, SSH_SFTP_UPLOAD_INIT);
break;
case SSH_SFTP_CREATE_DIRS_MKDIR:
@@ -1373,13 +1378,13 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
}
rc = 0; /* clear rc and continue */
}
- state(conn, SSH_SFTP_CREATE_DIRS);
+ state(data, SSH_SFTP_CREATE_DIRS);
break;
case SSH_SFTP_READDIR_INIT:
Curl_pgrsSetDownloadSize(data, -1);
if(data->set.opt_no_body) {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
@@ -1394,7 +1399,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
ssh_get_error(sshc->ssh_session));
MOVE_TO_SFTP_CLOSE_STATE();
}
- state(conn, SSH_SFTP_READDIR);
+ state(data, SSH_SFTP_READDIR);
break;
case SSH_SFTP_READDIR:
@@ -1413,16 +1418,16 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
tmpLine = aprintf("%s\n", sshc->readdir_filename);
if(tmpLine == NULL) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
tmpLine, sshc->readdir_len + 1);
free(tmpLine);
if(result) {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
/* since this counts what we send to the client, we include the
@@ -1430,18 +1435,15 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
data->req.bytecount += sshc->readdir_len + 1;
/* output debug output if that is requested */
- if(data->set.verbose) {
- Curl_debug(data, CURLINFO_DATA_OUT,
- (char *)sshc->readdir_filename,
- sshc->readdir_len);
- }
+ Curl_debug(data, CURLINFO_DATA_OUT, (char *)sshc->readdir_filename,
+ sshc->readdir_len);
}
else {
sshc->readdir_currLen = strlen(sshc->readdir_longentry);
sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
if(!sshc->readdir_line) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
@@ -1453,7 +1455,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
S_IFLNK)) {
sshc->readdir_linkPath = malloc(PATH_MAX + 1);
if(sshc->readdir_linkPath == NULL) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
@@ -1461,15 +1463,15 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
msnprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", protop->path,
sshc->readdir_filename);
- state(conn, SSH_SFTP_READDIR_LINK);
+ state(data, SSH_SFTP_READDIR_LINK);
break;
}
- state(conn, SSH_SFTP_READDIR_BOTTOM);
+ state(data, SSH_SFTP_READDIR_BOTTOM);
break;
}
}
else if(sftp_dir_eof(sshc->sftp_dir)) {
- state(conn, SSH_SFTP_READDIR_DONE);
+ state(data, SSH_SFTP_READDIR_DONE);
break;
}
else {
@@ -1516,7 +1518,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->readdir_totalLen);
if(!new_readdir_line) {
sshc->readdir_line = NULL;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
@@ -1534,24 +1536,21 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->readdir_filename = NULL;
sshc->readdir_longentry = NULL;
- state(conn, SSH_SFTP_READDIR_BOTTOM);
+ state(data, SSH_SFTP_READDIR_BOTTOM);
/* FALLTHROUGH */
case SSH_SFTP_READDIR_BOTTOM:
sshc->readdir_currLen += msnprintf(sshc->readdir_line +
sshc->readdir_currLen,
sshc->readdir_totalLen -
sshc->readdir_currLen, "\n");
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
sshc->readdir_line,
sshc->readdir_currLen);
if(!result) {
-
/* output debug output if that is requested */
- if(data->set.verbose) {
- Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
- sshc->readdir_currLen);
- }
+ Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
+ sshc->readdir_currLen);
data->req.bytecount += sshc->readdir_currLen;
}
Curl_safefree(sshc->readdir_line);
@@ -1559,10 +1558,10 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->readdir_tmp = NULL;
if(result) {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
else
- state(conn, SSH_SFTP_READDIR);
+ state(data, SSH_SFTP_READDIR);
break;
case SSH_SFTP_READDIR_DONE:
@@ -1571,7 +1570,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_SFTP_DOWNLOAD_INIT:
@@ -1590,7 +1589,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
MOVE_TO_SFTP_CLOSE_STATE();
}
- state(conn, SSH_SFTP_DOWNLOAD_STAT);
+ state(data, SSH_SFTP_DOWNLOAD_STAT);
break;
case SSH_SFTP_DOWNLOAD_STAT:
@@ -1622,14 +1621,14 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
return CURLE_BAD_DOWNLOAD_RESUME;
}
- if(conn->data->state.use_range) {
+ if(data->state.use_range) {
curl_off_t from, to;
char *ptr;
char *ptr2;
CURLofft to_t;
CURLofft from_t;
- from_t = curlx_strtoofft(conn->data->state.range, &ptr, 0, &from);
+ from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
if(from_t == CURL_OFFT_FLOW) {
return CURLE_RANGE_ERROR;
}
@@ -1712,7 +1711,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
infof(data, "File already completely downloaded\n");
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);
@@ -1728,12 +1727,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(result) {
/* this should never occur; the close state should be entered
at the time the error occurs */
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = result;
}
else {
sshc->sftp_recv_state = 0;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
@@ -1751,11 +1750,11 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
SSH_SFTP_CLOSE to pass the correct result back */
if(sshc->nextstate != SSH_NO_STATE &&
sshc->nextstate != SSH_SFTP_CLOSE) {
- state(conn, sshc->nextstate);
+ state(data, sshc->nextstate);
sshc->nextstate = SSH_SFTP_CLOSE;
}
else {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
result = sshc->actualcode;
}
break;
@@ -1776,17 +1775,16 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
}
SSH_STRING_FREE_CHAR(sshc->homedir);
- conn->data->state.most_recent_ftp_entrypath = NULL;
+ data->state.most_recent_ftp_entrypath = NULL;
- state(conn, SSH_SESSION_DISCONNECT);
+ state(data, SSH_SESSION_DISCONNECT);
break;
-
case SSH_SCP_TRANS_INIT:
- result = Curl_getworkingpath(conn, sshc->homedir, &protop->path);
+ result = Curl_getworkingpath(data, sshc->homedir, &protop->path);
if(result) {
sshc->actualcode = result;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
@@ -1802,17 +1800,17 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->scp_session =
ssh_scp_new(sshc->ssh_session, SSH_SCP_WRITE, protop->path);
- state(conn, SSH_SCP_UPLOAD_INIT);
+ state(data, SSH_SCP_UPLOAD_INIT);
}
else {
sshc->scp_session =
ssh_scp_new(sshc->ssh_session, SSH_SCP_READ, protop->path);
- state(conn, SSH_SCP_DOWNLOAD_INIT);
+ state(data, SSH_SCP_DOWNLOAD_INIT);
}
if(!sshc->scp_session) {
err_msg = ssh_get_error(sshc->ssh_session);
- failf(conn->data, "%s", err_msg);
+ failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
}
@@ -1823,7 +1821,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
rc = ssh_scp_init(sshc->scp_session);
if(rc != SSH_OK) {
err_msg = ssh_get_error(sshc->ssh_session);
- failf(conn->data, "%s", err_msg);
+ failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
}
@@ -1832,7 +1830,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
(int)data->set.new_file_perms);
if(rc != SSH_OK) {
err_msg = ssh_get_error(sshc->ssh_session);
- failf(conn->data, "%s", err_msg);
+ failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
}
@@ -1851,7 +1849,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
with both accordingly */
conn->cselect_bits = CURL_CSELECT_OUT;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
@@ -1860,10 +1858,10 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
rc = ssh_scp_init(sshc->scp_session);
if(rc != SSH_OK) {
err_msg = ssh_get_error(sshc->ssh_session);
- failf(conn->data, "%s", err_msg);
+ failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
}
- state(conn, SSH_SCP_DOWNLOAD);
+ state(data, SSH_SCP_DOWNLOAD);
/* FALLTHROUGH */
case SSH_SCP_DOWNLOAD:{
@@ -1872,7 +1870,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
rc = ssh_scp_pull_request(sshc->scp_session);
if(rc != SSH_SCP_REQUEST_NEWFILE) {
err_msg = ssh_get_error(sshc->ssh_session);
- failf(conn->data, "%s", err_msg);
+ failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_REMOTE_FILE_NOT_FOUND);
break;
}
@@ -1890,14 +1888,14 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
with both accordingly */
conn->cselect_bits = CURL_CSELECT_IN;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
case SSH_SCP_DONE:
if(data->set.upload)
- state(conn, SSH_SCP_SEND_EOF);
+ state(data, SSH_SCP_SEND_EOF);
else
- state(conn, SSH_SCP_CHANNEL_FREE);
+ state(data, SSH_SCP_CHANNEL_FREE);
break;
case SSH_SCP_SEND_EOF:
@@ -1915,7 +1913,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
}
}
- state(conn, SSH_SCP_CHANNEL_FREE);
+ state(data, SSH_SCP_CHANNEL_FREE);
break;
case SSH_SCP_CHANNEL_FREE:
@@ -1927,7 +1925,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
ssh_set_blocking(sshc->ssh_session, 0);
- state(conn, SSH_SESSION_DISCONNECT);
+ state(data, SSH_SESSION_DISCONNECT);
/* FALLTHROUGH */
case SSH_SESSION_DISCONNECT:
@@ -1942,9 +1940,9 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
ssh_disconnect(sshc->ssh_session);
SSH_STRING_FREE_CHAR(sshc->homedir);
- conn->data->state.most_recent_ftp_entrypath = NULL;
+ data->state.most_recent_ftp_entrypath = NULL;
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
/* FALLTHROUGH */
case SSH_SESSION_FREE:
if(sshc->ssh_session) {
@@ -1992,7 +1990,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
connclose(conn, "SSH session free");
sshc->state = SSH_SESSION_FREE; /* current */
sshc->nextstate = SSH_NO_STATE;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_QUIT:
@@ -2000,7 +1998,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
default:
/* internal error */
sshc->nextstate = SSH_NO_STATE;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
@@ -2019,10 +2017,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
/* called by the multi interface to figure out what socket(s) to wait for and
for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
-static int myssh_perform_getsock(const struct connectdata *conn,
- curl_socket_t *sock)
+static int myssh_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
+ curl_socket_t *sock)
{
int bitmap = GETSOCK_BLANK;
+ (void)data;
sock[0] = conn->sock[FIRSTSOCKET];
if(conn->waitfor & KEEP_RECV)
@@ -2034,16 +2034,6 @@ static int myssh_perform_getsock(const struct connectdata *conn,
return bitmap;
}
-/* Generic function called by the multi interface to figure out what socket(s)
- to wait for and for what actions during the DOING and PROTOCONNECT states*/
-static int myssh_getsock(struct connectdata *conn,
- curl_socket_t *sock)
-{
- /* if we know the direction we can use the generic *_getsock() function even
- for the protocol_connect and doing states */
- return myssh_perform_getsock(conn, sock);
-}
-
static void myssh_block2waitfor(struct connectdata *conn, bool block)
{
struct ssh_conn *sshc = &conn->proto.sshc;
@@ -2065,13 +2055,14 @@ static void myssh_block2waitfor(struct connectdata *conn, bool block)
}
/* called repeatedly until done from multi.c */
-static CURLcode myssh_multi_statemach(struct connectdata *conn,
+static CURLcode myssh_multi_statemach(struct Curl_easy *data,
bool *done)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
bool block; /* we store the status and use that to provide a ssh_getsock()
implementation */
- CURLcode result = myssh_statemach_act(conn, &block);
+ CURLcode result = myssh_statemach_act(data, &block);
*done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
myssh_block2waitfor(conn, block);
@@ -2079,24 +2070,24 @@ static CURLcode myssh_multi_statemach(struct connectdata *conn,
return result;
}
-static CURLcode myssh_block_statemach(struct connectdata *conn,
+static CURLcode myssh_block_statemach(struct Curl_easy *data,
bool disconnect)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
while((sshc->state != SSH_STOP) && !result) {
bool block;
timediff_t left = 1000;
struct curltime now = Curl_now();
- result = myssh_statemach_act(conn, &block);
+ result = myssh_statemach_act(data, &block);
if(result)
break;
if(!disconnect) {
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
return CURLE_ABORTED_BY_CALLBACK;
result = Curl_speedcheck(data, now);
@@ -2125,11 +2116,13 @@ static CURLcode myssh_block_statemach(struct connectdata *conn,
/*
* SSH setup connection
*/
-static CURLcode myssh_setup_connection(struct connectdata *conn)
+static CURLcode myssh_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct SSHPROTO *ssh;
+ (void)conn;
- conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO));
+ data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
if(!ssh)
return CURLE_OUT_OF_MEMORY;
@@ -2143,17 +2136,17 @@ static Curl_send scp_send, sftp_send;
* Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
* do protocol-specific actions at connect-time.
*/
-static CURLcode myssh_connect(struct connectdata *conn, bool *done)
+static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
{
struct ssh_conn *ssh;
CURLcode result;
+ struct connectdata *conn = data->conn;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
- struct Curl_easy *data = conn->data;
int rc;
/* initialize per-handle data if not already */
- if(!data->req.protop)
- myssh_setup_connection(conn);
+ if(!data->req.p.ssh)
+ myssh_setup_connection(data, conn);
/* We default to persistent connections. We set this already in this connect
function to make the re-use checks properly be able to check this bit. */
@@ -2246,22 +2239,22 @@ static CURLcode myssh_connect(struct connectdata *conn, bool *done)
/* we do not verify here, we do it at the state machine,
* after connection */
- state(conn, SSH_INIT);
+ state(data, SSH_INIT);
- result = myssh_multi_statemach(conn, done);
+ result = myssh_multi_statemach(data, done);
return result;
}
/* called from multi.c while DOing */
-static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done)
+static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done)
{
CURLcode result;
- result = myssh_multi_statemach(conn, dophase_done);
+ result = myssh_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
@@ -2276,34 +2269,35 @@ static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done)
*/
static
-CURLcode scp_perform(struct connectdata *conn,
+CURLcode scp_perform(struct Curl_easy *data,
bool *connected, bool *dophase_done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
*dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */
- state(conn, SSH_SCP_TRANS_INIT);
+ state(data, SSH_SCP_TRANS_INIT);
- result = myssh_multi_statemach(conn, dophase_done);
+ result = myssh_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
-static CURLcode myssh_do_it(struct connectdata *conn, bool *done)
+static CURLcode myssh_do_it(struct Curl_easy *data, bool *done)
{
CURLcode result;
bool connected = 0;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
*done = FALSE; /* default to false */
@@ -2320,9 +2314,9 @@ static CURLcode myssh_do_it(struct connectdata *conn, bool *done)
Curl_pgrsSetDownloadSize(data, -1);
if(conn->handler->protocol & CURLPROTO_SCP)
- result = scp_perform(conn, &connected, done);
+ result = scp_perform(data, &connected, done);
else
- result = sftp_perform(conn, &connected, done);
+ result = sftp_perform(data, &connected, done);
return result;
}
@@ -2330,7 +2324,8 @@ static CURLcode myssh_do_it(struct connectdata *conn, bool *done)
/* BLOCKING, but the function is using the state machine so the only reason
this is still blocking is that the multi interface code has no support for
disconnecting operations that takes a while */
-static CURLcode scp_disconnect(struct connectdata *conn,
+static CURLcode scp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
bool dead_connection)
{
CURLcode result = CURLE_OK;
@@ -2340,9 +2335,9 @@ static CURLcode scp_disconnect(struct connectdata *conn,
if(ssh->ssh_session) {
/* only if there's a session still around to use! */
- state(conn, SSH_SESSION_DISCONNECT);
+ state(data, SSH_SESSION_DISCONNECT);
- result = myssh_block_statemach(conn, TRUE);
+ result = myssh_block_statemach(data, TRUE);
}
return result;
@@ -2350,44 +2345,45 @@ static CURLcode scp_disconnect(struct connectdata *conn,
/* generic done function for both SCP and SFTP called from their specific
done functions */
-static CURLcode myssh_done(struct connectdata *conn, CURLcode status)
+static CURLcode myssh_done(struct Curl_easy *data, CURLcode status)
{
CURLcode result = CURLE_OK;
- struct SSHPROTO *protop = conn->data->req.protop;
+ struct SSHPROTO *protop = data->req.p.ssh;
if(!status) {
/* run the state-machine */
- result = myssh_block_statemach(conn, FALSE);
+ result = myssh_block_statemach(data, FALSE);
}
else
result = status;
if(protop)
Curl_safefree(protop->path);
- if(Curl_pgrsDone(conn))
+ if(Curl_pgrsDone(data))
return CURLE_ABORTED_BY_CALLBACK;
- conn->data->req.keepon = 0; /* clear all bits */
+ data->req.keepon = 0; /* clear all bits */
return result;
}
-static CURLcode scp_done(struct connectdata *conn, CURLcode status,
+static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
(void) premature; /* not used */
if(!status)
- state(conn, SSH_SCP_DONE);
+ state(data, SSH_SCP_DONE);
- return myssh_done(conn, status);
+ return myssh_done(data, status);
}
-static ssize_t scp_send(struct connectdata *conn, int sockindex,
+static ssize_t scp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
int rc;
+ struct connectdata *conn = data->conn;
(void) sockindex; /* we only support SCP on the fixed known primary socket */
(void) err;
@@ -2413,10 +2409,11 @@ static ssize_t scp_send(struct connectdata *conn, int sockindex,
return len;
}
-static ssize_t scp_recv(struct connectdata *conn, int sockindex,
+static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
{
ssize_t nread;
+ struct connectdata *conn = data->conn;
(void) err;
(void) sockindex; /* we only support SCP on the fixed known primary socket */
@@ -2452,38 +2449,39 @@ static ssize_t scp_recv(struct connectdata *conn, int sockindex,
*/
static
-CURLcode sftp_perform(struct connectdata *conn,
+CURLcode sftp_perform(struct Curl_easy *data,
bool *connected,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
*dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */
- state(conn, SSH_SFTP_QUOTE_INIT);
+ state(data, SSH_SFTP_QUOTE_INIT);
/* run the state-machine */
- result = myssh_multi_statemach(conn, dophase_done);
+ result = myssh_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
/* called from multi.c while DOing */
-static CURLcode sftp_doing(struct connectdata *conn,
+static CURLcode sftp_doing(struct Curl_easy *data,
bool *dophase_done)
{
- CURLcode result = myssh_multi_statemach(conn, dophase_done);
+ CURLcode result = myssh_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
@@ -2491,46 +2489,50 @@ static CURLcode sftp_doing(struct connectdata *conn,
/* BLOCKING, but the function is using the state machine so the only reason
this is still blocking is that the multi interface code has no support for
disconnecting operations that takes a while */
-static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode sftp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool dead_connection)
{
CURLcode result = CURLE_OK;
(void) dead_connection;
- DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT starts now\n"));
if(conn->proto.sshc.ssh_session) {
/* only if there's a session still around to use! */
- state(conn, SSH_SFTP_SHUTDOWN);
- result = myssh_block_statemach(conn, TRUE);
+ state(data, SSH_SFTP_SHUTDOWN);
+ result = myssh_block_statemach(data, TRUE);
}
- DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT is done\n"));
return result;
}
-static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
- bool premature)
+static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
+ bool premature)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
if(!status) {
/* Post quote commands are executed after the SFTP_CLOSE state to avoid
errors that could happen due to open file handles during POSTQUOTE
operation */
- if(!premature && conn->data->set.postquote && !conn->bits.retry)
+ if(!premature && data->set.postquote && !conn->bits.retry)
sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
}
- return myssh_done(conn, status);
+ return myssh_done(data, status);
}
/* return number of sent bytes */
-static ssize_t sftp_send(struct connectdata *conn, int sockindex,
+static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
ssize_t nwrite;
+ struct connectdata *conn = data->conn;
(void)sockindex;
nwrite = sftp_write(conn->proto.sshc.sftp_file, mem, len);
@@ -2556,10 +2558,11 @@ static ssize_t sftp_send(struct connectdata *conn, int sockindex,
* Return number of received (decrypted) bytes
* or <0 on error
*/
-static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
+static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
{
ssize_t nread;
+ struct connectdata *conn = data->conn;
(void)sockindex;
DEBUGASSERT(len < CURL_MAX_READ_SIZE);
@@ -2567,8 +2570,8 @@ static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
switch(conn->proto.sshc.sftp_recv_state) {
case 0:
conn->proto.sshc.sftp_file_index =
- sftp_async_read_begin(conn->proto.sshc.sftp_file,
- (uint32_t)len);
+ sftp_async_read_begin(conn->proto.sshc.sftp_file,
+ (uint32_t)len);
if(conn->proto.sshc.sftp_file_index < 0) {
*err = CURLE_RECV_ERROR;
return -1;
@@ -2602,11 +2605,11 @@ static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
}
}
-static void sftp_quote(struct connectdata *conn)
+static void sftp_quote(struct Curl_easy *data)
{
const char *cp;
- struct Curl_easy *data = conn->data;
- struct SSHPROTO *protop = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct SSHPROTO *protop = data->req.p.ssh;
struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result;
@@ -2632,26 +2635,25 @@ static void sftp_quote(struct connectdata *conn)
protop->path);
if(!tmp) {
sshc->actualcode = CURLE_OUT_OF_MEMORY;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
return;
}
- if(data->set.verbose) {
- Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4);
- Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
- }
+ Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4);
+ Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
+
/* this sends an FTP-like "header" to the header callback so that the
current directory can be read very similar to how it is read when
using ordinary FTP. */
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
free(tmp);
if(result) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
}
else
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
return;
}
@@ -2662,7 +2664,7 @@ static void sftp_quote(struct connectdata *conn)
cp = strchr(cmd, ' ');
if(cp == NULL) {
failf(data, "Syntax error in SFTP command. Supply parameter(s)!");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
@@ -2678,7 +2680,7 @@ static void sftp_quote(struct connectdata *conn)
failf(data, "Out of memory");
else
failf(data, "Syntax error: Bad first parameter");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
return;
@@ -2692,7 +2694,9 @@ static void sftp_quote(struct connectdata *conn)
*/
if(strncasecompare(cmd, "chgrp ", 6) ||
strncasecompare(cmd, "chmod ", 6) ||
- strncasecompare(cmd, "chown ", 6)) {
+ strncasecompare(cmd, "chown ", 6) ||
+ strncasecompare(cmd, "atime ", 6) ||
+ strncasecompare(cmd, "mtime ", 6)) {
/* attribute change */
/* sshc->quote_path1 contains the mode to set */
@@ -2702,16 +2706,16 @@ static void sftp_quote(struct connectdata *conn)
if(result == CURLE_OUT_OF_MEMORY)
failf(data, "Out of memory");
else
- failf(data, "Syntax error in chgrp/chmod/chown: "
+ failf(data, "Syntax error in chgrp/chmod/chown/atime/mtime: "
"Bad second parameter");
Curl_safefree(sshc->quote_path1);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
return;
}
sshc->quote_attrs = NULL;
- state(conn, SSH_SFTP_QUOTE_STAT);
+ state(data, SSH_SFTP_QUOTE_STAT);
return;
}
if(strncasecompare(cmd, "ln ", 3) ||
@@ -2726,17 +2730,17 @@ static void sftp_quote(struct connectdata *conn)
else
failf(data, "Syntax error in ln/symlink: Bad second parameter");
Curl_safefree(sshc->quote_path1);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
return;
}
- state(conn, SSH_SFTP_QUOTE_SYMLINK);
+ state(data, SSH_SFTP_QUOTE_SYMLINK);
return;
}
else if(strncasecompare(cmd, "mkdir ", 6)) {
/* create dir */
- state(conn, SSH_SFTP_QUOTE_MKDIR);
+ state(data, SSH_SFTP_QUOTE_MKDIR);
return;
}
else if(strncasecompare(cmd, "rename ", 7)) {
@@ -2750,26 +2754,26 @@ static void sftp_quote(struct connectdata *conn)
else
failf(data, "Syntax error in rename: Bad second parameter");
Curl_safefree(sshc->quote_path1);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
return;
}
- state(conn, SSH_SFTP_QUOTE_RENAME);
+ state(data, SSH_SFTP_QUOTE_RENAME);
return;
}
else if(strncasecompare(cmd, "rmdir ", 6)) {
/* delete dir */
- state(conn, SSH_SFTP_QUOTE_RMDIR);
+ state(data, SSH_SFTP_QUOTE_RMDIR);
return;
}
else if(strncasecompare(cmd, "rm ", 3)) {
- state(conn, SSH_SFTP_QUOTE_UNLINK);
+ state(data, SSH_SFTP_QUOTE_UNLINK);
return;
}
#ifdef HAS_STATVFS_SUPPORT
else if(strncasecompare(cmd, "statvfs ", 8)) {
- state(conn, SSH_SFTP_QUOTE_STATVFS);
+ state(data, SSH_SFTP_QUOTE_STATVFS);
return;
}
#endif
@@ -2777,14 +2781,14 @@ static void sftp_quote(struct connectdata *conn)
failf(data, "Unknown SFTP command");
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
}
-static void sftp_quote_stat(struct connectdata *conn)
+static void sftp_quote_stat(struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
char *cmd = sshc->quote_item->data;
sshc->acceptfail = FALSE;
@@ -2812,7 +2816,7 @@ static void sftp_quote_stat(struct connectdata *conn)
Curl_safefree(sshc->quote_path2);
failf(data, "Attempt to get SFTP stats failed: %d",
sftp_get_error(sshc->sftp_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
@@ -2826,7 +2830,7 @@ static void sftp_quote_stat(struct connectdata *conn)
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chgrp gid not a number");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
@@ -2841,7 +2845,7 @@ static void sftp_quote_stat(struct connectdata *conn)
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chmod permissions not a number");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
@@ -2856,16 +2860,44 @@ static void sftp_quote_stat(struct connectdata *conn)
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chown uid not a number");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
}
sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
}
+ else if(strncasecompare(cmd, "atime", 5)) {
+ time_t date = Curl_getdate_capped(sshc->quote_path1);
+ if(date == -1) {
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Syntax error: incorrect access date format");
+ state(data, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ return;
+ }
+ sshc->quote_attrs->atime = (uint32_t)date;
+ sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_ACMODTIME;
+ }
+ else if(strncasecompare(cmd, "mtime", 5)) {
+ time_t date = Curl_getdate_capped(sshc->quote_path1);
+ if(date == -1) {
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Syntax error: incorrect modification date format");
+ state(data, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ return;
+ }
+ sshc->quote_attrs->mtime = (uint32_t)date;
+ sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_ACMODTIME;
+ }
/* Now send the completed structure... */
- state(conn, SSH_SFTP_QUOTE_SETSTAT);
+ state(data, SSH_SFTP_QUOTE_SETSTAT);
return;
}