aboutsummaryrefslogtreecommitdiff
path: root/libssh/sftp.c
diff options
context:
space:
mode:
authorAndreas Schneider <mail@cynapses.org>2009-07-28 13:21:05 +0200
committerAndreas Schneider <mail@cynapses.org>2009-07-28 13:25:35 +0200
commitb9b7174d858faa070e66db9b7710c384756f90fc (patch)
tree307dfc1278438c6779530733a52917f7210c2756 /libssh/sftp.c
parent69ceaae9a9f69dba11ab01889da5b41cb1487896 (diff)
downloadlibssh-b9b7174d858faa070e66db9b7710c384756f90fc.tar.gz
libssh-b9b7174d858faa070e66db9b7710c384756f90fc.tar.xz
libssh-b9b7174d858faa070e66db9b7710c384756f90fc.zip
Add support to read and store sftp extensions.
Diffstat (limited to 'libssh/sftp.c')
-rw-r--r--libssh/sftp.c138
1 files changed, 117 insertions, 21 deletions
diff --git a/libssh/sftp.c b/libssh/sftp.c
index 41402810..9363955a 100644
--- a/libssh/sftp.c
+++ b/libssh/sftp.c
@@ -44,12 +44,55 @@
#define sftp_enter_function() _enter_function(sftp->channel->session)
#define sftp_leave_function() _leave_function(sftp->channel->session)
+struct sftp_ext_struct {
+ int rename_openssh;
+ int rename_openssh_version;
+ int statvfs_openssh;
+ int statvfs_openssh_version;
+ int fstatvfs_openssh;
+ int fstatvfs_openssh_version;
+ unsigned int count;
+ char **name;
+ char **data;
+};
+
/* functions */
static int sftp_enqueue(SFTP_SESSION *session, SFTP_MESSAGE *msg);
static void sftp_message_free(SFTP_MESSAGE *msg);
static void sftp_set_error(SFTP_SESSION *sftp, int errnum);
static void status_msg_free(STATUS_MESSAGE *status);
+static sftp_ext sftp_ext_new(void) {
+ sftp_ext ext;
+
+ ext = malloc(sizeof(struct sftp_ext_struct));
+ if (ext == NULL) {
+ return NULL;
+ }
+ ZERO_STRUCTP(ext);
+
+ return ext;
+}
+
+static void sftp_ext_free(sftp_ext ext) {
+ unsigned int i;
+
+ if (ext == NULL) {
+ return;
+ }
+
+ if (ext->count) {
+ for (i = 0; i < ext->count; i++) {
+ SAFE_FREE(ext->name[i]);
+ SAFE_FREE(ext->data[i]);
+ }
+ SAFE_FREE(ext->name);
+ SAFE_FREE(ext->data);
+ }
+
+ SAFE_FREE(ext);
+}
+
SFTP_SESSION *sftp_new(SSH_SESSION *session){
SFTP_SESSION *sftp;
@@ -65,7 +108,14 @@ SFTP_SESSION *sftp_new(SSH_SESSION *session){
leave_function();
return NULL;
}
- memset(sftp,0,sizeof(SFTP_SESSION));
+ ZERO_STRUCTP(sftp);
+
+ sftp->ext = sftp_ext_new();
+ if (sftp->ext == NULL) {
+ SAFE_FREE(sftp);
+ sftp_leave_function();
+ return NULL;
+ }
sftp->session = session;
sftp->channel = channel_new(session);
@@ -191,7 +241,8 @@ void sftp_free(SFTP_SESSION *sftp){
}
channel_free(sftp->channel);
- memset(sftp, 0, sizeof(*sftp));
+ sftp_ext_free(sftp->ext);
+ ZERO_STRUCTP(sftp);
SAFE_FREE(sftp);
}
@@ -455,39 +506,84 @@ int sftp_init(SFTP_SESSION *sftp) {
return -1;
}
- buffer_get_u32(packet->payload,&version);
+ buffer_get_u32(packet->payload, &version);
version = ntohl(version);
+ ssh_log(sftp->session, SSH_LOG_RARE,
+ "SFTP server version %d",
+ version);
ext_name_s = buffer_get_ssh_string(packet->payload);
- ext_data_s = buffer_get_ssh_string(packet->payload);
- if (ext_name_s == NULL || (ext_data_s == NULL)) {
- string_free(ext_name_s);
- string_free(ext_data_s);
- ssh_log(sftp->session, SSH_LOG_RARE,
- "SFTP server version %d", version);
- } else {
+ while (ext_name_s != NULL) {
+ int count = sftp->ext->count;
+ char **tmp;
+
+ ext_data_s = buffer_get_ssh_string(packet->payload);
+ if (ext_data_s == NULL) {
+ string_free(ext_name_s);
+ break;
+ }
+
ext_name = string_to_char(ext_name_s);
ext_data = string_to_char(ext_data_s);
+ if (ext_name == NULL || ext_data == NULL) {
+ SAFE_FREE(ext_name);
+ SAFE_FREE(ext_data);
+ string_free(ext_name_s);
+ string_free(ext_data_s);
+ return -1;
+ }
+ ssh_log(sftp->session, SSH_LOG_RARE,
+ "SFTP server extension: %s, version: %s",
+ ext_name, ext_data);
+
+ if (strcmp(ext_name, "posix-rename@openssh.com") == 0) {
+ sftp->ext->rename_openssh = 1;
+ sftp->ext->rename_openssh_version = strtol(ext_data, (char **) NULL, 10);
+ } else if (strcmp(ext_name, "statvfs@openssh.com") == 0) {
+ sftp->ext->statvfs_openssh = 1;
+ sftp->ext->statvfs_openssh_version = strtol(ext_data, (char **) NULL, 10);
+ } else if (strcmp(ext_name, "fstatvfs@openssh.com") == 0) {
+ sftp->ext->fstatvfs_openssh = 1;
+ sftp->ext->fstatvfs_openssh_version = strtol(ext_data, (char **) NULL, 10);
+ }
+
+ count++;
+ tmp = realloc(sftp->ext->name, count * sizeof(char *));
+ if (tmp == NULL) {
+ SAFE_FREE(ext_name);
+ SAFE_FREE(ext_data);
+ string_free(ext_name_s);
+ string_free(ext_data_s);
+ return -1;
+ }
+ tmp[count - 1] = ext_name;
+ sftp->ext->name = tmp;
- if (ext_name != NULL || ext_data != NULL) {
- ssh_log(sftp->session, SSH_LOG_RARE,
- "SFTP server version %d (%s,%s)",
- version, ext_name, ext_data);
- } else {
- ssh_log(sftp->session, SSH_LOG_RARE,
- "SFTP server version %d", version);
+ tmp = realloc(sftp->ext->data, count * sizeof(char *));
+ if (tmp == NULL) {
+ SAFE_FREE(ext_name);
+ SAFE_FREE(ext_data);
+ string_free(ext_name_s);
+ string_free(ext_data_s);
+ return -1;
}
- SAFE_FREE(ext_name);
- SAFE_FREE(ext_data);
+ tmp[count - 1] = ext_data;
+ sftp->ext->data = tmp;
+
+ sftp->ext->count = count;
+
+ string_free(ext_name_s);
+ string_free(ext_data_s);
+
+ ext_name_s = buffer_get_ssh_string(packet->payload);
}
- string_free(ext_name_s);
- string_free(ext_data_s);
sftp_packet_free(packet);
sftp->version = sftp->server_version = version;
sftp_leave_function();
+
return 0;
}