aboutsummaryrefslogtreecommitdiff
path: root/libssh/sftp.c
diff options
context:
space:
mode:
Diffstat (limited to 'libssh/sftp.c')
-rw-r--r--libssh/sftp.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/libssh/sftp.c b/libssh/sftp.c
index 4aa63c97..f0007d8c 100644
--- a/libssh/sftp.c
+++ b/libssh/sftp.c
@@ -2212,6 +2212,89 @@ int sftp_utimes(SFTP_SESSION *sftp, const char *file,
return sftp_setstat(sftp, file, &attr);
}
+int sftp_symlink(SFTP_SESSION *sftp, const char *target, const char *dest) {
+ STATUS_MESSAGE *status = NULL;
+ SFTP_MESSAGE *msg = NULL;
+ STRING *target_s;
+ STRING *dest_s;
+ BUFFER *buffer;
+ u32 id;
+
+ if (sftp == NULL || target == NULL || dest == NULL) {
+ return -1;
+ }
+
+ buffer = buffer_new();
+ if (buffer == NULL) {
+ return -1;
+ }
+
+ target_s = string_from_char(target);
+ if (target_s == NULL) {
+ buffer_free(buffer);
+ return -1;
+ }
+
+ dest_s = string_from_char(dest);
+ if (dest_s == NULL) {
+ string_free(target_s);
+ buffer_free(buffer);
+ return -1;
+ }
+
+ id = sftp_get_new_id(sftp);
+ if (buffer_add_u32(buffer, id) < 0 ||
+ buffer_add_ssh_string(buffer, target_s) < 0 ||
+ buffer_add_ssh_string(buffer, dest_s) < 0 ||
+ sftp_packet_write(sftp, SSH_FXP_SYMLINK, buffer) < 0) {
+ buffer_free(buffer);
+ string_free(dest_s);
+ string_free(target_s);
+ return -1;
+ }
+ buffer_free(buffer);
+ string_free(dest_s);
+ string_free(target_s);
+
+ while (msg == NULL) {
+ if (sftp_read_and_dispatch(sftp) < 0) {
+ return -1;
+ }
+ msg = sftp_dequeue(sftp, id);
+ }
+
+ /* By specification, this command only returns SSH_FXP_STATUS */
+ if (msg->packet_type == SSH_FXP_STATUS) {
+ status = parse_status_msg(msg);
+ sftp_message_free(msg);
+ if (status == NULL) {
+ return -1;
+ }
+ sftp_set_error(sftp, status->status);
+ switch (status->status) {
+ case SSH_FX_OK:
+ status_msg_free(status);
+ return 0;
+ default:
+ break;
+ }
+ /*
+ * The status should be SSH_FX_OK if the command was successful, if it
+ * didn't, then there was an error
+ */
+ ssh_set_error(sftp->session, SSH_REQUEST_DENIED,
+ "SFTP server: %s", status->errormsg);
+ status_msg_free(status);
+ return -1;
+ } else {
+ ssh_set_error(sftp->session, SSH_FATAL,
+ "Received message %d when attempting to set stats", msg->packet_type);
+ sftp_message_free(msg);
+ }
+
+ return -1;
+}
+
/* another code written by Nick */
char *sftp_canonicalize_path(SFTP_SESSION *sftp, const char *path) {
STATUS_MESSAGE *status = NULL;