1
1

scp_recv: improved treatment of channel_read() returning zero

As a zero return code from channel_read() is not an error we must make
sure that the SCP functions deal with that properly. channel_read()
always returns 0 if the channel is EOFed already so we check for EOF
after 0-reads to be able to return error properly.
Этот коммит содержится в:
Daniel Stenberg 2010-10-11 22:24:11 +02:00
родитель c36f379b88
Коммит cd6d41b806

Просмотреть файл

@ -390,12 +390,15 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for SCP response");
return NULL;
} else if (rc <= 0) {
/* Timeout, give up */
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Timed out waiting for SCP response");
}
else if (rc < 0) {
/* error, give up */
_libssh2_error(session, rc, "Failed reading SCP response");
goto scp_recv_error;
}
else if(rc == 0)
goto scp_recv_empty_channel;
session->scpRecv_response_len++;
if (session->scpRecv_response[0] != 'T') {
@ -421,18 +424,9 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
rc = _libssh2_channel_read(session->scpRecv_channel, 0,
session->scpRecv_err_msg,
session->scpRecv_err_len);
if (rc <= 0) {
/*
* Since we have alread started reading this packet,
* it is already in the systems so it can't return
* LIBSSH2_ERROR_EAGAIN
*/
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Unknown error" );
}
else
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"SCP protocol error");
/* If it failed for any reason, we ignore it anyway. */
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"SCP protocol error");
/* TODO: for debugging purposes, the
session->scpRecv_err_msg should be displayed here
@ -599,12 +593,15 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for SCP response");
return NULL;
} else if (rc <= 0) {
/* Timeout, give up */
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Timed out waiting for SCP response");
}
else if (rc < 0) {
/* error, bail out*/
_libssh2_error(session, rc, "Failed reading SCP response");
goto scp_recv_error;
}
else if(rc == 0)
goto scp_recv_empty_channel;
session->scpRecv_response_len++;
if (session->scpRecv_response[0] != 'C') {
@ -745,8 +742,18 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
session->scpRecv_state = libssh2_NB_state_idle;
return session->scpRecv_channel;
scp_recv_empty_channel:
/* the code only jumps here as a result of a zero read from channel_read()
so we check EOF status to avoid getting stuck in a loop */
if(libssh2_channel_eof(session->scpRecv_channel))
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Unexpected channel close");
else
return session->scpRecv_channel;
/* fall-through */
scp_recv_error:
while (libssh2_channel_free(session->scpRecv_channel) == LIBSSH2_ERROR_EAGAIN);
while (libssh2_channel_free(session->scpRecv_channel) ==
LIBSSH2_ERROR_EAGAIN);
session->scpRecv_channel = NULL;
session->scpRecv_state = libssh2_NB_state_idle;
return NULL;
@ -867,12 +874,19 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response from remote");
return NULL;
} else if ((rc <= 0) || (session->scpSend_response[0] != 0)) {
}
else if (rc < 0) {
_libssh2_error(session, rc, "SCP failure");
goto scp_send_error;
}
else if(!rc)
/* remain in the same state */
goto scp_send_empty_channel;
else if (session->scpSend_response[0] != 0) {
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid ACK response from remote");
goto scp_send_error;
}
if (mtime || atime) {
/* Send mtime and atime to be used for file */
session->scpSend_response_len =
@ -913,9 +927,17 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response");
return NULL;
} else if ((rc <= 0) || (session->scpSend_response[0] != 0)) {
}
else if (rc < 0) {
_libssh2_error(session, rc, "SCP failure");
goto scp_send_error;
}
else if(!rc)
/* remain in the same state */
goto scp_send_empty_channel;
else if (session->scpSend_response[0] != 0) {
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid ACK response from remote");
"Invalid SCP ACK response");
goto scp_send_error;
}
@ -971,11 +993,16 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response");
return NULL;
} else if (rc <= 0) {
}
else if (rc < 0) {
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Invalid ACK response from remote");
goto scp_send_error;
} else if (session->scpSend_response[0] != 0) {
}
else if (rc == 0)
goto scp_send_empty_channel;
else if (session->scpSend_response[0] != 0) {
/*
* Set this as the default error for here, if
* we are successful it will be replaced
@ -1013,9 +1040,18 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
}
session->scpSend_state = libssh2_NB_state_idle;
return session->scpSend_channel;
scp_send_empty_channel:
/* the code only jumps here as a result of a zero read from channel_read()
so we check EOF status to avoid getting stuck in a loop */
if(libssh2_channel_eof(session->scpSend_channel)) {
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
"Unexpected channel close");
}
else
return session->scpSend_channel;
/* fall-through */
scp_send_error:
while (libssh2_channel_free(session->scpSend_channel) ==
LIBSSH2_ERROR_EAGAIN);