Add helper to receive sftp response messages

For the sake of reducing code repetition, this commit
adds a helper function to receive sftp response
messages. The function can operate in both blocking
and non-blocking modes.

Signed-off-by: Eshan Kelkar <eshankelkar@galorithm.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
This commit is contained in:
Eshan Kelkar
2024-09-13 00:52:40 +05:30
committed by Jakub Jelen
parent f16b3539da
commit a02268a254
4 changed files with 183 additions and 176 deletions

View File

@@ -701,12 +701,9 @@ sftp_dir sftp_opendir(sftp_session sftp, const char *path)
return NULL;
}
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
/* something nasty has happened */
return NULL;
}
msg = sftp_dequeue(sftp, id);
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc != SSH_OK) {
return NULL;
}
switch (msg->packet_type) {
@@ -798,12 +795,9 @@ sftp_attributes sftp_readdir(sftp_session sftp, sftp_dir dir)
SSH_LOG(SSH_LOG_PACKET,
"Sent a ssh_fxp_readdir with id %" PRIu32, id);
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
/* something nasty has happened */
return NULL;
}
msg = sftp_dequeue(sftp, id);
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc != SSH_OK) {
return NULL;
}
switch (msg->packet_type){
@@ -928,12 +922,9 @@ static int sftp_handle_close(sftp_session sftp, ssh_string handle)
return -1;
}
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
/* something nasty has happened */
return -1;
}
msg = sftp_dequeue(sftp,id);
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc != SSH_OK) {
return -1;
}
switch (msg->packet_type) {
@@ -1073,12 +1064,9 @@ sftp_file sftp_open(sftp_session sftp,
return NULL;
}
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
/* something nasty has happened */
return NULL;
}
msg = sftp_dequeue(sftp, id);
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc != SSH_OK) {
return NULL;
}
switch (msg->packet_type) {
@@ -1197,18 +1185,17 @@ ssize_t sftp_read(sftp_file handle, void *buf, size_t count) {
}
SSH_BUFFER_FREE(buffer);
while (msg == NULL) {
if (handle->nonblocking) {
if (ssh_channel_poll(handle->sftp->channel, 0) == 0) {
/* we cannot block */
return 0;
}
}
if (sftp_read_and_dispatch(handle->sftp) < 0) {
/* something nasty has happened */
rc = sftp_recv_response_msg(handle->sftp, id, !handle->nonblocking, &msg);
if (rc == SSH_ERROR) {
return -1;
}
msg = sftp_dequeue(handle->sftp, id);
}
if (rc == SSH_AGAIN) {
/*
* file opened in non blocking mode and the response has not arrived yet.
* Since we cannot block, return 0 as the number of bytes read.
*/
return 0;
}
switch (msg->packet_type) {
@@ -1309,7 +1296,7 @@ int sftp_async_read(sftp_file file, void *data, uint32_t size, uint32_t id){
sftp_message msg = NULL;
sftp_status_message status;
ssh_string datastring;
int err = SSH_OK;
int rc, err = SSH_OK;
uint32_t len;
if (file == NULL) {
@@ -1322,20 +1309,9 @@ int sftp_async_read(sftp_file file, void *data, uint32_t size, uint32_t id){
}
/* handle an existing request */
while (msg == NULL) {
if (file->nonblocking){
if (ssh_channel_poll(sftp->channel, 0) == 0) {
/* we cannot block */
return SSH_AGAIN;
}
}
if (sftp_read_and_dispatch(sftp) < 0) {
/* something nasty has happened */
return SSH_ERROR;
}
msg = sftp_dequeue(sftp,id);
rc = sftp_recv_response_msg(sftp, id, !file->nonblocking, &msg);
if (rc == SSH_ERROR || rc == SSH_AGAIN) {
return rc;
}
switch (msg->packet_type) {
@@ -1446,12 +1422,10 @@ ssize_t sftp_write(sftp_file file, const void *buf, size_t count) {
"Could not write as much data as expected");
}
while (msg == NULL) {
if (sftp_read_and_dispatch(file->sftp) < 0) {
/* something nasty has happened */
/* Wait for the response in blocking mode */
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc != SSH_OK) {
return -1;
}
msg = sftp_dequeue(file->sftp, id);
}
switch (msg->packet_type) {
@@ -1558,11 +1532,9 @@ int sftp_unlink(sftp_session sftp, const char *file) {
}
SSH_BUFFER_FREE(buffer);
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp)) {
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc != SSH_OK) {
return -1;
}
msg = sftp_dequeue(sftp, id);
}
if (msg->packet_type == SSH_FXP_STATUS) {
@@ -1632,11 +1604,9 @@ int sftp_rmdir(sftp_session sftp, const char *directory) {
}
SSH_BUFFER_FREE(buffer);
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc != SSH_OK) {
return -1;
}
msg = sftp_dequeue(sftp, id);
}
/* By specification, this command returns SSH_FXP_STATUS */
@@ -1718,11 +1688,9 @@ int sftp_mkdir(sftp_session sftp, const char *directory, mode_t mode)
return -1;
}
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
return -1;
}
msg = sftp_dequeue(sftp, id);
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc != SSH_OK) {
return -1;
}
/* By specification, this command only returns SSH_FXP_STATUS */
@@ -1842,11 +1810,9 @@ int sftp_rename(sftp_session sftp, const char *original, const char *newname)
return -1;
}
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
return -1;
}
msg = sftp_dequeue(sftp, id);
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc != SSH_OK) {
return -1;
}
/* By specification, this command only returns SSH_FXP_STATUS */
@@ -1931,11 +1897,9 @@ int sftp_setstat(sftp_session sftp, const char *file, sftp_attributes attr)
return -1;
}
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
return -1;
}
msg = sftp_dequeue(sftp, id);
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc != SSH_OK) {
return -1;
}
/* By specification, this command only returns SSH_FXP_STATUS */
@@ -2016,11 +1980,9 @@ sftp_lsetstat(sftp_session sftp, const char *file, sftp_attributes attr)
return -1;
}
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
return -1;
}
msg = sftp_dequeue(sftp, id);
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc != SSH_OK) {
return -1;
}
/* By specification, this command only returns SSH_FXP_STATUS */
@@ -2156,11 +2118,9 @@ int sftp_symlink(sftp_session sftp, const char *target, const char *dest)
}
SSH_BUFFER_FREE(buffer);
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc != SSH_OK) {
return -1;
}
msg = sftp_dequeue(sftp, id);
}
/* By specification, this command only returns SSH_FXP_STATUS */
@@ -2244,11 +2204,9 @@ char *sftp_readlink(sftp_session sftp, const char *path)
return NULL;
}
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
return NULL;
}
msg = sftp_dequeue(sftp, id);
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc != SSH_OK) {
return NULL;
}
if (msg->packet_type == SSH_FXP_NAME) {
@@ -2336,11 +2294,9 @@ int sftp_hardlink(sftp_session sftp, const char *oldpath, const char *newpath)
return -1;
}
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
return -1;
}
msg = sftp_dequeue(sftp, id);
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc != SSH_OK) {
return -1;
}
/* By specification, this command only returns SSH_FXP_STATUS */
@@ -2459,11 +2415,9 @@ sftp_statvfs_t sftp_statvfs(sftp_session sftp, const char *path)
return NULL;
}
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
return NULL;
}
msg = sftp_dequeue(sftp, id);
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc != SSH_OK) {
return NULL;
}
if (msg->packet_type == SSH_FXP_EXTENDED_REPLY) {
@@ -2533,15 +2487,10 @@ int sftp_fsync(sftp_file file)
goto done;
}
do {
rc = sftp_read_and_dispatch(sftp);
if (rc < 0) {
ssh_set_error_oom(sftp->session);
rc = -1;
goto done;
}
msg = sftp_dequeue(sftp, id);
} while (msg == NULL);
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc != SSH_OK) {
return -1;
}
/* By specification, this command only returns SSH_FXP_STATUS */
if (msg->packet_type == SSH_FXP_STATUS) {
@@ -2634,11 +2583,9 @@ sftp_statvfs_t sftp_fstatvfs(sftp_file file)
return NULL;
}
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
return NULL;
}
msg = sftp_dequeue(sftp, id);
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc == -1) {
return NULL;
}
if (msg->packet_type == SSH_FXP_EXTENDED_REPLY) {
@@ -2747,11 +2694,9 @@ static sftp_limits_t sftp_limits_use_extension(sftp_session sftp)
return NULL;
}
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
return NULL;
}
msg = sftp_dequeue(sftp, id);
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc != SSH_OK) {
return NULL;
}
if (msg->packet_type == SSH_FXP_EXTENDED_REPLY) {
@@ -2897,11 +2842,9 @@ char *sftp_canonicalize_path(sftp_session sftp, const char *path)
return NULL;
}
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
return NULL;
}
msg = sftp_dequeue(sftp, id);
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc == -1) {
return NULL;
}
if (msg->packet_type == SSH_FXP_NAME) {
@@ -2988,11 +2931,9 @@ static sftp_attributes sftp_xstat(sftp_session sftp,
return NULL;
}
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
return NULL;
}
msg = sftp_dequeue(sftp, id);
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc != SSH_OK) {
return NULL;
}
if (msg->packet_type == SSH_FXP_ATTRS) {
@@ -3066,11 +3007,9 @@ sftp_attributes sftp_fstat(sftp_file file)
return NULL;
}
while (msg == NULL) {
if (sftp_read_and_dispatch(file->sftp) < 0) {
return NULL;
}
msg = sftp_dequeue(file->sftp, id);
rc = sftp_recv_response_msg(file->sftp, id, true, &msg);
if (rc != SSH_OK) {
return NULL;
}
if (msg->packet_type == SSH_FXP_ATTRS){
@@ -3146,12 +3085,9 @@ char *sftp_expand_path(sftp_session sftp, const char *path)
return NULL;
}
while (msg == NULL) {
rc = sftp_read_and_dispatch(sftp);
if (rc < 0) {
return NULL;
}
msg = sftp_dequeue(sftp, id);
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc != SSH_OK) {
return NULL;
}
if (msg->packet_type == SSH_FXP_NAME) {
@@ -3233,12 +3169,9 @@ sftp_home_directory(sftp_session sftp, const char *username)
return NULL;
}
while (msg == NULL) {
rc = sftp_read_and_dispatch(sftp);
if (rc < 0) {
return NULL;
}
msg = sftp_dequeue(sftp, id);
rc = sftp_recv_response_msg(sftp, id, true, &msg);
if (rc != SSH_OK) {
return NULL;
}
if (msg->packet_type == SSH_FXP_NAME) {

View File

@@ -202,21 +202,15 @@ ssize_t sftp_aio_wait_read(sftp_aio *aio,
}
/* handle an existing request */
while (msg == NULL) {
if (file->nonblocking) {
if (ssh_channel_poll(sftp->channel, 0) == 0) {
/* we cannot block */
return SSH_AGAIN;
}
}
rc = sftp_recv_response_msg(sftp, (*aio)->id, !file->nonblocking, &msg);
if (rc == SSH_ERROR) {
SFTP_AIO_FREE(*aio);
return SSH_ERROR;
}
if (sftp_read_and_dispatch(sftp) < 0) {
/* something nasty has happened */
SFTP_AIO_FREE(*aio);
return SSH_ERROR;
}
msg = sftp_dequeue(sftp, (*aio)->id);
if (rc == SSH_AGAIN) {
/* return without freeing the (*aio) */
return SSH_AGAIN;
}
/*
@@ -410,6 +404,7 @@ ssize_t sftp_aio_wait_write(sftp_aio *aio)
sftp_session sftp = NULL;
sftp_message msg = NULL;
sftp_status_message status = NULL;
int rc;
/*
* This function releases the memory of the structure
@@ -446,21 +441,15 @@ ssize_t sftp_aio_wait_write(sftp_aio *aio)
return SSH_ERROR;
}
while (msg == NULL) {
if (file->nonblocking) {
if (ssh_channel_poll(sftp->channel, 0) == 0) {
/* we cannot block */
return SSH_AGAIN;
}
}
rc = sftp_recv_response_msg(sftp, (*aio)->id, !file->nonblocking, &msg);
if (rc == SSH_ERROR) {
SFTP_AIO_FREE(*aio);
return SSH_ERROR;
}
if (sftp_read_and_dispatch(sftp) < 0) {
/* something nasty has happened */
SFTP_AIO_FREE(*aio);
return SSH_ERROR;
}
msg = sftp_dequeue(sftp, (*aio)->id);
if (rc == SSH_AGAIN) {
/* Return without freeing the (*aio) */
return SSH_AGAIN;
}
/*

View File

@@ -859,6 +859,56 @@ int sftp_read_and_dispatch(sftp_session sftp)
return 0;
}
int sftp_recv_response_msg(sftp_session sftp,
uint32_t id,
bool blocking,
sftp_message *msg_ptr)
{
sftp_message msg = NULL;
int rc;
if (sftp == NULL) {
return SSH_ERROR;
}
if (msg_ptr == NULL) {
ssh_set_error_invalid(sftp->session);
sftp_set_error(sftp, SSH_FX_FAILURE);
return SSH_ERROR;
}
SSH_LOG(SSH_LOG_PACKET,
"Trying to receive response of request id %" PRIu32 " in %s mode",
id,
blocking ? "blocking" : "non-blocking");
do {
if (!blocking) {
rc = ssh_channel_poll(sftp->channel, 0);
if (rc == SSH_ERROR) {
sftp_set_error(sftp, SSH_FX_FAILURE);
return SSH_ERROR;
}
if (rc == 0) {
/* nothing available and we cannot block */
return SSH_AGAIN;
}
}
rc = sftp_read_and_dispatch(sftp);
if (rc == -1) {
/* something nasty has happened */
return SSH_ERROR;
}
msg = sftp_dequeue(sftp, id);
} while (msg == NULL);
*msg_ptr = msg;
return SSH_OK;
}
sftp_status_message parse_status_msg(sftp_message msg)
{
sftp_status_message status = NULL;