1
0
mirror of https://git.libssh.org/projects/libssh.git synced 2025-08-10 06:23:01 +03:00

buffers: adapt sftp.c to ssh_buffer_(un)pack()

Reviewed-by: Andreas Schneider <asn@samba.org>
This commit is contained in:
Aris Adamantiadis
2014-04-22 18:46:29 +02:00
committed by Andreas Schneider
parent c238136010
commit c341da03d3
2 changed files with 231 additions and 379 deletions

View File

@@ -143,10 +143,10 @@ struct sftp_request_queue_struct {
/* SSH_FXP_MESSAGE described into .7 page 26 */
struct sftp_status_message_struct {
uint32_t id;
uint32_t status;
ssh_string error;
ssh_string lang;
uint32_t id;
uint32_t status;
ssh_string error_unused; /* not used anymore */
ssh_string lang_unused; /* not used anymore */
char *errormsg;
char *langmsg;
};

View File

@@ -497,11 +497,10 @@ void sftp_packet_free(sftp_packet packet) {
int sftp_init(sftp_session sftp) {
sftp_packet packet = NULL;
ssh_buffer buffer = NULL;
ssh_string ext_name_s = NULL;
ssh_string ext_data_s = NULL;
char *ext_name = NULL;
char *ext_data = NULL;
uint32_t version = htonl(LIBSFTP_VERSION);
uint32_t version;
int rc;
buffer = ssh_buffer_new();
if (buffer == NULL) {
@@ -509,7 +508,8 @@ int sftp_init(sftp_session sftp) {
return -1;
}
if (buffer_add_u32(buffer, version) < 0) {
rc = ssh_buffer_pack(buffer, "d", LIBSFTP_VERSION);
if (rc != SSH_OK) {
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
return -1;
@@ -533,68 +533,48 @@ int sftp_init(sftp_session sftp) {
}
/* TODO: are we sure there are 4 bytes ready? */
buffer_get_u32(packet->payload, &version);
version = ntohl(version);
rc = ssh_buffer_unpack(packet->payload, "d", &version);
if (rc != SSH_OK){
return -1;
}
SSH_LOG(SSH_LOG_RARE,
"SFTP server version %d",
version);
ext_name_s = buffer_get_ssh_string(packet->payload);
while (ext_name_s != NULL) {
rc = ssh_buffer_unpack(packet->payload, "s", &ext_name);
while (rc == SSH_OK) {
int count = sftp->ext->count;
char **tmp;
ext_data_s = buffer_get_ssh_string(packet->payload);
if (ext_data_s == NULL) {
ssh_string_free(ext_name_s);
rc = ssh_buffer_unpack(packet->payload, "s", &ext_data);
if (rc == SSH_ERROR) {
break;
}
ext_name = ssh_string_to_char(ext_name_s);
ext_data = ssh_string_to_char(ext_data_s);
if (ext_name == NULL || ext_data == NULL) {
ssh_set_error_oom(sftp->session);
SAFE_FREE(ext_name);
SAFE_FREE(ext_data);
ssh_string_free(ext_name_s);
ssh_string_free(ext_data_s);
return -1;
}
SSH_LOG(SSH_LOG_RARE,
"SFTP server extension: %s, version: %s",
ext_name, ext_data);
count++;
tmp = realloc(sftp->ext->name, count * sizeof(char *));
if (tmp == NULL) {
sftp->ext->name = realloc(sftp->ext->name, count * sizeof(char *));
if (sftp->ext->name == NULL) {
ssh_set_error_oom(sftp->session);
SAFE_FREE(ext_name);
SAFE_FREE(ext_data);
ssh_string_free(ext_name_s);
ssh_string_free(ext_data_s);
return -1;
}
tmp[count - 1] = ext_name;
sftp->ext->name = tmp;
sftp->ext->name[count - 1] = ext_name;
tmp = realloc(sftp->ext->data, count * sizeof(char *));
if (tmp == NULL) {
sftp->ext->data = realloc(sftp->ext->data, count * sizeof(char *));
if (sftp->ext->data == NULL) {
ssh_set_error_oom(sftp->session);
SAFE_FREE(ext_name);
SAFE_FREE(ext_data);
ssh_string_free(ext_name_s);
ssh_string_free(ext_data_s);
return -1;
}
tmp[count - 1] = ext_data;
sftp->ext->data = tmp;
sftp->ext->data[count - 1] = ext_data;
sftp->ext->count = count;
ssh_string_free(ext_name_s);
ssh_string_free(ext_data_s);
ext_name_s = buffer_get_ssh_string(packet->payload);
rc = ssh_buffer_unpack(packet->payload, "s", &ext_name);
}
sftp_packet_free(packet);
@@ -766,6 +746,7 @@ static inline uint32_t sftp_get_new_id(sftp_session session) {
static sftp_status_message parse_status_msg(sftp_message msg){
sftp_status_message status;
int rc;
if (msg->packet_type != SSH_FXP_STATUS) {
ssh_set_error(msg->sftp->session, SSH_FATAL,
@@ -781,34 +762,28 @@ static sftp_status_message parse_status_msg(sftp_message msg){
ZERO_STRUCTP(status);
status->id = msg->id;
if (buffer_get_u32(msg->payload,&status->status) != 4){
rc = ssh_buffer_unpack(msg->payload, "dSS",
&status->status);
if (rc != SSH_OK){
SAFE_FREE(status);
ssh_set_error(msg->sftp->session, SSH_FATAL,
"Invalid SSH_FXP_STATUS message");
return NULL;
}
status->error = buffer_get_ssh_string(msg->payload);
status->lang = buffer_get_ssh_string(msg->payload);
if(status->error == NULL || status->lang == NULL){
if(msg->sftp->version >=3){
rc = ssh_buffer_unpack(msg->payload, "ss",
&status->errormsg,
&status->langmsg);
if(rc != SSH_OK && msg->sftp->version >=3){
/* These are mandatory from version 3 */
ssh_string_free(status->error);
/* status->lang never get allocated if something failed */
SAFE_FREE(status);
ssh_set_error(msg->sftp->session, SSH_FATAL,
"Invalid SSH_FXP_STATUS message");
return NULL;
}
}
status->status = ntohl(status->status);
if(status->error)
status->errormsg = ssh_string_to_char(status->error);
else
if (status->errormsg == NULL)
status->errormsg = strdup("No error message in packet");
if(status->lang)
status->langmsg = ssh_string_to_char(status->lang);
else
if (status->langmsg == NULL)
status->langmsg = strdup("");
if (status->errormsg == NULL || status->langmsg == NULL) {
ssh_set_error_oom(msg->sftp->session);
@@ -824,8 +799,6 @@ static void status_msg_free(sftp_status_message status){
return;
}
ssh_string_free(status->error);
ssh_string_free(status->lang);
SAFE_FREE(status->errormsg);
SAFE_FREE(status->langmsg);
SAFE_FREE(status);
@@ -1191,148 +1164,135 @@ static char *sftp_parse_longname(const char *longname,
... more extended data (extended_type - extended_data pairs),
so that number of pairs equals extended_count */
static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf,
int expectname) {
ssh_string longname;
ssh_string name;
sftp_attributes attr;
uint32_t flags = 0;
int ok = 0;
int expectname) {
sftp_attributes attr;
int rc;
attr = malloc(sizeof(struct sftp_attributes_struct));
if (attr == NULL) {
ssh_set_error_oom(sftp->session);
return NULL;
}
ZERO_STRUCTP(attr);
attr = malloc(sizeof(struct sftp_attributes_struct));
if (attr == NULL) {
ssh_set_error_oom(sftp->session);
return NULL;
}
ZERO_STRUCTP(attr);
/* This isn't really a loop, but it is like a try..catch.. */
do {
if (expectname) {
name = buffer_get_ssh_string(buf);
if (name == NULL) {
break;
}
attr->name = ssh_string_to_char(name);
ssh_string_free(name);
if (attr->name == NULL) {
break;
}
SSH_LOG(SSH_LOG_RARE, "Name: %s", attr->name);
longname = buffer_get_ssh_string(buf);
if (longname == NULL) {
break;
}
attr->longname = ssh_string_to_char(longname);
ssh_string_free(longname);
if (attr->longname == NULL) {
break;
}
/* Set owner and group if we talk to openssh and have the longname */
if (ssh_get_openssh_version(sftp->session)) {
attr->owner = sftp_parse_longname(attr->longname, SFTP_LONGNAME_OWNER);
if (attr->owner == NULL) {
break;
rc = ssh_buffer_unpack(buf, "ss",
&attr->name,
&attr->longname);
if (rc != SSH_OK){
goto error;
}
SSH_LOG(SSH_LOG_RARE, "Name: %s", attr->name);
attr->group = sftp_parse_longname(attr->longname, SFTP_LONGNAME_GROUP);
if (attr->group == NULL) {
break;
/* Set owner and group if we talk to openssh and have the longname */
if (ssh_get_openssh_version(sftp->session)) {
attr->owner = sftp_parse_longname(attr->longname, SFTP_LONGNAME_OWNER);
if (attr->owner == NULL) {
goto error;
}
attr->group = sftp_parse_longname(attr->longname, SFTP_LONGNAME_GROUP);
if (attr->group == NULL) {
goto error;
}
}
}
}
if (buffer_get_u32(buf, &flags) != sizeof(uint32_t)) {
break;
rc = ssh_buffer_unpack(buf, "d", &attr->flags);
if (rc != SSH_OK){
goto error;
}
flags = ntohl(flags);
attr->flags = flags;
SSH_LOG(SSH_LOG_RARE,
"Flags: %.8lx\n", (long unsigned int) flags);
"Flags: %.8lx\n", (long unsigned int) attr->flags);
if (flags & SSH_FILEXFER_ATTR_SIZE) {
if(buffer_get_u64(buf, &attr->size) != sizeof(uint64_t)) {
break;
}
attr->size = ntohll(attr->size);
SSH_LOG(SSH_LOG_RARE,
"Size: %llu\n",
(long long unsigned int) attr->size);
if (attr->flags & SSH_FILEXFER_ATTR_SIZE) {
rc = ssh_buffer_unpack(buf, "q", &attr->size);
if(rc != SSH_OK) {
goto error;
}
SSH_LOG(SSH_LOG_RARE,
"Size: %llu\n",
(long long unsigned int) attr->size);
}
if (flags & SSH_FILEXFER_ATTR_UIDGID) {
if (buffer_get_u32(buf, &attr->uid) != sizeof(uint32_t)) {
break;
}
if (buffer_get_u32(buf, &attr->gid) != sizeof(uint32_t)) {
break;
}
attr->uid = ntohl(attr->uid);
attr->gid = ntohl(attr->gid);
if (attr->flags & SSH_FILEXFER_ATTR_UIDGID) {
rc = ssh_buffer_unpack(buf, "dd",
&attr->uid,
&attr->gid);
if (rc != SSH_OK){
goto error;
}
}
if (flags & SSH_FILEXFER_ATTR_PERMISSIONS) {
if (buffer_get_u32(buf, &attr->permissions) != sizeof(uint32_t)) {
break;
}
attr->permissions = ntohl(attr->permissions);
if (attr->flags & SSH_FILEXFER_ATTR_PERMISSIONS) {
rc = ssh_buffer_unpack(buf, "d", &attr->permissions);
if (rc != SSH_OK){
goto error;
}
switch (attr->permissions & S_IFMT) {
switch (attr->permissions & S_IFMT) {
case S_IFSOCK:
case S_IFBLK:
case S_IFCHR:
case S_IFIFO:
attr->type = SSH_FILEXFER_TYPE_SPECIAL;
break;
attr->type = SSH_FILEXFER_TYPE_SPECIAL;
break;
case S_IFLNK:
attr->type = SSH_FILEXFER_TYPE_SYMLINK;
break;
attr->type = SSH_FILEXFER_TYPE_SYMLINK;
break;
case S_IFREG:
attr->type = SSH_FILEXFER_TYPE_REGULAR;
break;
attr->type = SSH_FILEXFER_TYPE_REGULAR;
break;
case S_IFDIR:
attr->type = SSH_FILEXFER_TYPE_DIRECTORY;
break;
attr->type = SSH_FILEXFER_TYPE_DIRECTORY;
break;
default:
attr->type = SSH_FILEXFER_TYPE_UNKNOWN;
break;
}
attr->type = SSH_FILEXFER_TYPE_UNKNOWN;
break;
}
}
if (flags & SSH_FILEXFER_ATTR_ACMODTIME) {
if (buffer_get_u32(buf, &attr->atime) != sizeof(uint32_t)) {
break;
}
attr->atime = ntohl(attr->atime);
if (buffer_get_u32(buf, &attr->mtime) != sizeof(uint32_t)) {
break;
}
attr->mtime = ntohl(attr->mtime);
if (attr->flags & SSH_FILEXFER_ATTR_ACMODTIME) {
rc = ssh_buffer_unpack(buf, "dd",
&attr->atime,
&attr->mtime);
if (rc != SSH_OK){
goto error;
}
}
if (flags & SSH_FILEXFER_ATTR_EXTENDED) {
if (buffer_get_u32(buf, &attr->extended_count) != sizeof(uint32_t)) {
break;
}
if (attr->flags & SSH_FILEXFER_ATTR_EXTENDED) {
rc = ssh_buffer_unpack(buf, "d", &attr->extended_count);
if (rc != SSH_OK){
goto error;
}
attr->extended_count = ntohl(attr->extended_count);
while (attr->extended_count &&
(attr->extended_type = buffer_get_ssh_string(buf))
&& (attr->extended_data = buffer_get_ssh_string(buf))) {
attr->extended_count--;
}
if (attr->extended_count > 0){
rc = ssh_buffer_unpack(buf, "ss",
&attr->extended_type,
&attr->extended_data);
if (rc != SSH_OK){
goto error;
}
attr->extended_count--;
}
/* just ignore the remaining extensions */
if (attr->extended_count) {
break;
}
while (attr->extended_count > 0){
ssh_string tmp1,tmp2;
rc = ssh_buffer_unpack(buf, "SS", &tmp1, &tmp2);
if (rc != SSH_OK){
goto error;
}
SAFE_FREE(tmp1);
SAFE_FREE(tmp2);
attr->extended_count--;
}
}
ok = 1;
} while (0);
if (!ok) {
/* break issued somewhere */
return attr;
error:
ssh_string_free(attr->extended_type);
ssh_string_free(attr->extended_data);
SAFE_FREE(attr->name);
@@ -1340,55 +1300,53 @@ static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf,
SAFE_FREE(attr->owner);
SAFE_FREE(attr->group);
SAFE_FREE(attr);
ssh_set_error(sftp->session, SSH_FATAL, "Invalid ATTR structure");
return NULL;
}
/* everything went smoothly */
return attr;
}
/* FIXME is this really needed as a public function? */
int buffer_add_attributes(ssh_buffer buffer, sftp_attributes attr) {
uint32_t flags = (attr ? attr->flags : 0);
int rc;
flags &= (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_UIDGID |
SSH_FILEXFER_ATTR_PERMISSIONS | SSH_FILEXFER_ATTR_ACMODTIME);
if (buffer_add_u32(buffer, htonl(flags)) < 0) {
rc = ssh_buffer_pack(buffer, "d", flags);
if (rc != SSH_OK) {
return -1;
}
if (attr) {
if (attr != NULL) {
if (flags & SSH_FILEXFER_ATTR_SIZE) {
if (buffer_add_u64(buffer, htonll(attr->size)) < 0) {
rc = ssh_buffer_pack(buffer, "q", attr->size);
if (rc != SSH_OK) {
return -1;
}
}
if (flags & SSH_FILEXFER_ATTR_UIDGID) {
if (buffer_add_u32(buffer,htonl(attr->uid)) < 0 ||
buffer_add_u32(buffer,htonl(attr->gid)) < 0) {
rc = ssh_buffer_pack(buffer, "dd", attr->uid, attr->gid);
if (rc != SSH_OK) {
return -1;
}
}
if (flags & SSH_FILEXFER_ATTR_PERMISSIONS) {
if (buffer_add_u32(buffer, htonl(attr->permissions)) < 0) {
rc = ssh_buffer_pack(buffer, "d", attr->permissions);
if (rc != SSH_OK) {
return -1;
}
}
if (flags & SSH_FILEXFER_ATTR_ACMODTIME) {
if (buffer_add_u32(buffer, htonl(attr->atime)) < 0 ||
buffer_add_u32(buffer, htonl(attr->mtime)) < 0) {
rc = ssh_buffer_pack(buffer, "dd", attr->atime, attr->mtime);
if (rc != SSH_OK) {
return -1;
}
}
}
return 0;
}
@@ -1751,6 +1709,7 @@ ssize_t sftp_read(sftp_file handle, void *buf, size_t count) {
ssh_string datastring;
ssh_buffer buffer;
int id;
int rc;
if (handle->eof) {
return 0;
@@ -1761,11 +1720,14 @@ ssize_t sftp_read(sftp_file handle, void *buf, size_t count) {
ssh_set_error_oom(sftp->session);
return -1;
}
id = sftp_get_new_id(handle->sftp);
if (buffer_add_u32(buffer, id) < 0 ||
buffer_add_ssh_string(buffer, handle->handle) < 0 ||
buffer_add_u64(buffer, htonll(handle->offset)) < 0 ||
buffer_add_u32(buffer,htonl(count)) < 0) {
id = ntohl(sftp_get_new_id(handle->sftp));
rc = ssh_buffer_pack(buffer,
"dSqd",
id,
handle->handle,
handle->offset,
count);
if (rc != SSH_OK){
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
return -1;
@@ -1847,6 +1809,7 @@ int sftp_async_read_begin(sftp_file file, uint32_t len){
sftp_session sftp = file->sftp;
ssh_buffer buffer;
uint32_t id;
int rc;
buffer = ssh_buffer_new();
if (buffer == NULL) {
@@ -1854,11 +1817,15 @@ int sftp_async_read_begin(sftp_file file, uint32_t len){
return -1;
}
id = sftp_get_new_id(sftp);
if (buffer_add_u32(buffer, id) < 0 ||
buffer_add_ssh_string(buffer, file->handle) < 0 ||
buffer_add_u64(buffer, htonll(file->offset)) < 0 ||
buffer_add_u32(buffer, htonl(len)) < 0) {
id = ntohl(sftp_get_new_id(sftp));
rc = ssh_buffer_pack(buffer,
"dSqd",
id,
file->handle,
file->offset,
len);
if (rc != SSH_OK) {
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
return -1;
@@ -1961,11 +1928,11 @@ ssize_t sftp_write(sftp_file file, const void *buf, size_t count) {
sftp_session sftp = file->sftp;
sftp_message msg = NULL;
sftp_status_message status;
ssh_string datastring;
ssh_buffer buffer;
uint32_t id;
int len;
int packetlen;
int rc;
buffer = ssh_buffer_new();
if (buffer == NULL) {
@@ -1973,25 +1940,21 @@ ssize_t sftp_write(sftp_file file, const void *buf, size_t count) {
return -1;
}
datastring = ssh_string_new(count);
if (datastring == NULL) {
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
return -1;
}
ssh_string_fill(datastring, buf, count);
id = sftp_get_new_id(file->sftp);
if (buffer_add_u32(buffer, id) < 0 ||
buffer_add_ssh_string(buffer, file->handle) < 0 ||
buffer_add_u64(buffer, htonll(file->offset)) < 0 ||
buffer_add_ssh_string(buffer, datastring) < 0) {
rc = buffer_add_u32(buffer, id) != 4 ? SSH_ERROR:SSH_OK;
if (rc != SSH_ERROR){
rc = ssh_buffer_pack(buffer,
"SqdP",
file->handle,
file->offset,
count, /* len of datastring */
(size_t)count, buf);
}
if (rc != SSH_OK){
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
ssh_string_free(datastring);
return -1;
}
ssh_string_free(datastring);
packetlen=buffer_get_rest_len(buffer);
len = sftp_packet_write(file->sftp, SSH_FXP_WRITE, buffer);
ssh_buffer_free(buffer);
@@ -2083,9 +2046,9 @@ void sftp_rewind(sftp_file file) {
int sftp_unlink(sftp_session sftp, const char *file) {
sftp_status_message status = NULL;
sftp_message msg = NULL;
ssh_string filename;
ssh_buffer buffer;
uint32_t id;
int rc;
buffer = ssh_buffer_new();
if (buffer == NULL) {
@@ -2093,27 +2056,22 @@ int sftp_unlink(sftp_session sftp, const char *file) {
return -1;
}
filename = ssh_string_from_char(file);
if (filename == NULL) {
id = ntohl(sftp_get_new_id(sftp));
rc = ssh_buffer_pack(buffer,
"ds",
id,
file);
if (rc != SSH_OK) {
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
return -1;
}
id = sftp_get_new_id(sftp);
if (buffer_add_u32(buffer, id) < 0 ||
buffer_add_ssh_string(buffer, filename) < 0) {
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
ssh_string_free(filename);
return -1;
}
if (sftp_packet_write(sftp, SSH_FXP_REMOVE, buffer) < 0) {
ssh_buffer_free(buffer);
ssh_string_free(filename);
return -1;
}
ssh_string_free(filename);
ssh_buffer_free(buffer);
while (msg == NULL) {
@@ -2160,9 +2118,9 @@ int sftp_unlink(sftp_session sftp, const char *file) {
int sftp_rmdir(sftp_session sftp, const char *directory) {
sftp_status_message status = NULL;
sftp_message msg = NULL;
ssh_string filename;
ssh_buffer buffer;
uint32_t id;
int rc;
buffer = ssh_buffer_new();
if (buffer == NULL) {
@@ -2170,28 +2128,22 @@ int sftp_rmdir(sftp_session sftp, const char *directory) {
return -1;
}
filename = ssh_string_from_char(directory);
if (filename == NULL) {
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
return -1;
}
id = ntohl(sftp_get_new_id(sftp));
id = sftp_get_new_id(sftp);
if (buffer_add_u32(buffer, id) < 0 ||
buffer_add_ssh_string(buffer, filename) < 0) {
rc = ssh_buffer_pack(buffer,
"ds",
id,
directory);
if (rc != SSH_OK) {
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
ssh_string_free(filename);
return -1;
}
if (sftp_packet_write(sftp, SSH_FXP_RMDIR, buffer) < 0) {
ssh_buffer_free(buffer);
ssh_string_free(filename);
return -1;
}
ssh_buffer_free(buffer);
ssh_string_free(filename);
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
@@ -2327,9 +2279,8 @@ int sftp_rename(sftp_session sftp, const char *original, const char *newname) {
sftp_status_message status = NULL;
sftp_message msg = NULL;
ssh_buffer buffer;
ssh_string oldpath;
ssh_string newpath;
uint32_t id;
int rc;
buffer = ssh_buffer_new();
if (buffer == NULL) {
@@ -2337,43 +2288,30 @@ int sftp_rename(sftp_session sftp, const char *original, const char *newname) {
return -1;
}
oldpath = ssh_string_from_char(original);
if (oldpath == NULL) {
id = ntohl(sftp_get_new_id(sftp));
rc = ssh_buffer_pack(buffer,
"dss",
id,
original,
newname);
if (rc != SSH_OK) {
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
return -1;
}
newpath = ssh_string_from_char(newname);
if (newpath == NULL) {
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
ssh_string_free(oldpath);
return -1;
}
id = sftp_get_new_id(sftp);
if (buffer_add_u32(buffer, id) < 0 ||
buffer_add_ssh_string(buffer, oldpath) < 0 ||
buffer_add_ssh_string(buffer, newpath) < 0 ||
if (sftp->version >= 4){
/* POSIX rename atomically replaces newpath, we should do the same
* only available on >=v4 */
sftp->version>=4 ? (buffer_add_u32(buffer, SSH_FXF_RENAME_OVERWRITE) < 0):0) {
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
ssh_string_free(oldpath);
ssh_string_free(newpath);
return -1;
buffer_add_u32(buffer, SSH_FXF_RENAME_OVERWRITE);
}
if (sftp_packet_write(sftp, SSH_FXP_RENAME, buffer) < 0) {
ssh_buffer_free(buffer);
ssh_string_free(oldpath);
ssh_string_free(newpath);
return -1;
}
ssh_buffer_free(buffer);
ssh_string_free(oldpath);
ssh_string_free(newpath);
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
@@ -2537,10 +2475,9 @@ int sftp_utimes(sftp_session sftp, const char *file,
int sftp_symlink(sftp_session sftp, const char *target, const char *dest) {
sftp_status_message status = NULL;
sftp_message msg = NULL;
ssh_string target_s;
ssh_string dest_s;
ssh_buffer buffer;
uint32_t id;
int rc;
if (sftp == NULL)
return -1;
@@ -2555,59 +2492,33 @@ int sftp_symlink(sftp_session sftp, const char *target, const char *dest) {
return -1;
}
target_s = ssh_string_from_char(target);
if (target_s == NULL) {
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
return -1;
}
id = ntohl(sftp_get_new_id(sftp));
dest_s = ssh_string_from_char(dest);
if (dest_s == NULL) {
ssh_set_error_oom(sftp->session);
ssh_string_free(target_s);
ssh_buffer_free(buffer);
return -1;
}
id = sftp_get_new_id(sftp);
if (buffer_add_u32(buffer, id) < 0) {
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
ssh_string_free(dest_s);
ssh_string_free(target_s);
return -1;
}
/* TODO check for version number if they ever fix it. */
if (ssh_get_openssh_version(sftp->session)) {
/* TODO check for version number if they ever fix it. */
if (buffer_add_ssh_string(buffer, target_s) < 0 ||
buffer_add_ssh_string(buffer, dest_s) < 0) {
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
ssh_string_free(dest_s);
ssh_string_free(target_s);
return -1;
}
rc = ssh_buffer_pack(buffer,
"dss",
id,
target,
dest);
} else {
if (buffer_add_ssh_string(buffer, dest_s) < 0 ||
buffer_add_ssh_string(buffer, target_s) < 0) {
rc = ssh_buffer_pack(buffer,
"dss",
id,
dest,
target);
}
if (rc != SSH_OK){
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
ssh_string_free(dest_s);
ssh_string_free(target_s);
return -1;
}
}
if (sftp_packet_write(sftp, SSH_FXP_SYMLINK, buffer) < 0) {
ssh_buffer_free(buffer);
ssh_string_free(dest_s);
ssh_string_free(target_s);
return -1;
}
ssh_buffer_free(buffer);
ssh_string_free(dest_s);
ssh_string_free(target_s);
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
@@ -2737,9 +2648,8 @@ char *sftp_readlink(sftp_session sftp, const char *path) {
}
static sftp_statvfs_t sftp_parse_statvfs(sftp_session sftp, ssh_buffer buf) {
sftp_statvfs_t statvfs;
uint64_t tmp;
int ok = 0;
sftp_statvfs_t statvfs;
int rc;
statvfs = malloc(sizeof(struct sftp_statvfs_struct));
if (statvfs == NULL) {
@@ -2748,78 +2658,20 @@ static sftp_statvfs_t sftp_parse_statvfs(sftp_session sftp, ssh_buffer buf) {
}
ZERO_STRUCTP(statvfs);
/* try .. catch */
do {
/* file system block size */
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) {
break;
}
statvfs->f_bsize = ntohll(tmp);
/* fundamental fs block size */
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) {
break;
}
statvfs->f_frsize = ntohll(tmp);
/* number of blocks (unit f_frsize) */
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) {
break;
}
statvfs->f_blocks = ntohll(tmp);
/* free blocks in file system */
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) {
break;
}
statvfs->f_bfree = ntohll(tmp);
/* free blocks for non-root */
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) {
break;
}
statvfs->f_bavail = ntohll(tmp);
/* total file inodes */
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) {
break;
}
statvfs->f_files = ntohll(tmp);
/* free file inodes */
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) {
break;
}
statvfs->f_ffree = ntohll(tmp);
/* free file inodes for to non-root */
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) {
break;
}
statvfs->f_favail = ntohll(tmp);
/* file system id */
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) {
break;
}
statvfs->f_fsid = ntohll(tmp);
/* bit mask of f_flag values */
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) {
break;
}
statvfs->f_flag = ntohll(tmp);
/* maximum filename length */
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) {
break;
}
statvfs->f_namemax = ntohll(tmp);
ok = 1;
} while(0);
if (!ok) {
rc = ssh_buffer_unpack(buf, "qqqqqqqqqqq",
&statvfs->f_bsize, /* file system block size */
&statvfs->f_frsize, /* fundamental fs block size */
&statvfs->f_blocks, /* number of blocks (unit f_frsize) */
&statvfs->f_bfree, /* free blocks in file system */
&statvfs->f_bavail, /* free blocks for non-root */
&statvfs->f_files, /* total file inodes */
&statvfs->f_ffree, /* free file inodes */
&statvfs->f_favail, /* free file inodes for to non-root */
&statvfs->f_fsid, /* file system id */
&statvfs->f_flag, /* bit mask of f_flag values */
&statvfs->f_namemax/* maximum filename length */
);
if (rc != SSH_OK) {
SAFE_FREE(statvfs);
ssh_set_error(sftp->session, SSH_FATAL, "Invalid statvfs structure");
return NULL;