mirror of
https://git.libssh.org/projects/libssh.git
synced 2025-12-08 03:42:12 +03:00
sftp.c, sftp.h: Store the limits in the sftp_session
In the sftp_init() call, the limits are stored in the sftp_sesssion. If the limits@openssh.com extension is supported the limits are retrieved from the server, else libssh uses the default limits. The sftp library functions that require the limits can access them using the sftp session. The library user can call sftp_limits() to get a copy of the limits stored in the sftp session. Since the limits were already retrieved from the server during sftp_init(), this sftp_limits() call requires no communication with the server. Signed-off-by: Eshan Kelkar <eshankelkar@galorithm.com> Reviewed-by: Jakub Jelen <jjelen@redhat.com>
This commit is contained in:
committed by
Jakub Jelen
parent
5ea247df8e
commit
4f24fbd3a0
@@ -92,6 +92,7 @@ struct sftp_session_struct {
|
||||
void **handles;
|
||||
sftp_ext ext;
|
||||
sftp_packet read_packet;
|
||||
sftp_limits_t limits;
|
||||
};
|
||||
|
||||
struct sftp_packet_struct {
|
||||
|
||||
113
src/sftp.c
113
src/sftp.c
@@ -347,6 +347,7 @@ void sftp_free(sftp_session sftp)
|
||||
SAFE_FREE(sftp->read_packet);
|
||||
|
||||
sftp_ext_free(sftp->ext);
|
||||
sftp_limits_free(sftp->limits);
|
||||
|
||||
SAFE_FREE(sftp);
|
||||
}
|
||||
@@ -413,6 +414,9 @@ int sftp_get_error(sftp_session sftp) {
|
||||
return sftp->errnum;
|
||||
}
|
||||
|
||||
static sftp_limits_t sftp_limits_use_extension(sftp_session sftp);
|
||||
static sftp_limits_t sftp_limits_use_default(sftp_session sftp);
|
||||
|
||||
/* Initialize the sftp session with the server. */
|
||||
int sftp_init(sftp_session sftp)
|
||||
{
|
||||
@@ -514,6 +518,47 @@ int sftp_init(sftp_session sftp)
|
||||
|
||||
sftp->version = sftp->server_version = (int)version;
|
||||
|
||||
/* Set the limits */
|
||||
rc = sftp_extension_supported(sftp, "limits@openssh.com", "1");
|
||||
if (rc == 1) {
|
||||
/* Get the ssh and sftp errors */
|
||||
const char *static_ssh_err_msg = ssh_get_error(sftp->session);
|
||||
int ssh_err_code = ssh_get_error_code(sftp->session);
|
||||
int sftp_err_code = sftp_get_error(sftp);
|
||||
char *ssh_err_msg = strdup(static_ssh_err_msg);
|
||||
if (ssh_err_msg == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sftp->limits = sftp_limits_use_extension(sftp);
|
||||
if (sftp->limits == NULL) {
|
||||
/* fallback and use the default limits on failure */
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to get the limits from a server claiming to "
|
||||
"support the limits@openssh.com extension, falling back "
|
||||
"and using the default limits");
|
||||
|
||||
/* Restore the sftp and ssh errors to their previous state */
|
||||
ssh_set_error(sftp->session, ssh_err_code, "%s", ssh_err_msg);
|
||||
sftp_set_error(sftp, sftp_err_code);
|
||||
SAFE_FREE(ssh_err_msg);
|
||||
|
||||
sftp->limits = sftp_limits_use_default(sftp);
|
||||
if (sftp->limits == NULL) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
SAFE_FREE(ssh_err_msg);
|
||||
}
|
||||
} else {
|
||||
sftp->limits = sftp_limits_use_default(sftp);
|
||||
if (sftp->limits == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2523,12 +2568,17 @@ void sftp_statvfs_free(sftp_statvfs_t statvfs) {
|
||||
SAFE_FREE(statvfs);
|
||||
}
|
||||
|
||||
static sftp_limits_t sftp_limits_new(void)
|
||||
{
|
||||
return calloc(1, sizeof(struct sftp_limits_struct));
|
||||
}
|
||||
|
||||
static sftp_limits_t sftp_parse_limits(sftp_session sftp, ssh_buffer buf)
|
||||
{
|
||||
sftp_limits_t limits = NULL;
|
||||
int rc;
|
||||
|
||||
limits = calloc(1, sizeof(struct sftp_limits_struct));
|
||||
limits = sftp_limits_new();
|
||||
if (limits == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
@@ -2551,7 +2601,7 @@ static sftp_limits_t sftp_parse_limits(sftp_session sftp, ssh_buffer buf)
|
||||
return limits;
|
||||
}
|
||||
|
||||
sftp_limits_t sftp_limits(sftp_session sftp)
|
||||
static sftp_limits_t sftp_limits_use_extension(sftp_session sftp)
|
||||
{
|
||||
sftp_status_message status = NULL;
|
||||
sftp_message msg = NULL;
|
||||
@@ -2627,6 +2677,65 @@ sftp_limits_t sftp_limits(sftp_session sftp)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static sftp_limits_t sftp_limits_use_default(sftp_session sftp)
|
||||
{
|
||||
sftp_limits_t limits = NULL;
|
||||
|
||||
if (sftp == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
limits = sftp_limits_new();
|
||||
if (limits == NULL) {
|
||||
ssh_set_error_oom(sftp->session);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
limits->max_packet_length = 34000;
|
||||
limits->max_read_length = 32768;
|
||||
limits->max_write_length = 32768;
|
||||
|
||||
/*
|
||||
* For max-open-handles field openssh says :
|
||||
* If the server doesn't enforce a specific limit, then the field may
|
||||
* be set to 0. This implies the server relies on the OS to enforce
|
||||
* limits (e.g. available memory or file handles), and such limits
|
||||
* might be dynamic. The client SHOULD take care to not try to exceed
|
||||
* reasonable limits.
|
||||
*/
|
||||
limits->max_open_handles = 0;
|
||||
|
||||
return limits;
|
||||
}
|
||||
|
||||
sftp_limits_t sftp_limits(sftp_session sftp)
|
||||
{
|
||||
sftp_limits_t limits = NULL;
|
||||
|
||||
if (sftp == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sftp->limits == NULL) {
|
||||
ssh_set_error(sftp, SSH_FATAL,
|
||||
"Uninitialized sftp session, "
|
||||
"sftp_init() was not called or failed");
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
limits = sftp_limits_new();
|
||||
if (limits == NULL) {
|
||||
ssh_set_error_oom(sftp);
|
||||
sftp_set_error(sftp, SSH_FX_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(limits, sftp->limits, sizeof(struct sftp_limits_struct));
|
||||
return limits;
|
||||
}
|
||||
|
||||
void sftp_limits_free(sftp_limits_t limits)
|
||||
{
|
||||
if (limits == NULL) {
|
||||
|
||||
Reference in New Issue
Block a user