diff options
author | Andreas Schneider <mail@cynapses.org> | 2009-07-25 11:35:33 +0200 |
---|---|---|
committer | Andreas Schneider <mail@cynapses.org> | 2009-07-25 12:32:51 +0200 |
commit | 11a6ed907d7d54a388ee1eb148803a326cee54f6 (patch) | |
tree | d9a0e8ce5e15072a0d361612b061274e7f2bc63f | |
parent | a8ce546f69e1d1d2425cdd3358b2083b0a6cebcb (diff) | |
download | libssh-11a6ed907d7d54a388ee1eb148803a326cee54f6.tar.gz libssh-11a6ed907d7d54a388ee1eb148803a326cee54f6.tar.xz libssh-11a6ed907d7d54a388ee1eb148803a326cee54f6.zip |
Add sftp_symlink function.
-rw-r--r-- | include/libssh/sftp.h | 13 | ||||
-rw-r--r-- | libssh/sftp.c | 83 |
2 files changed, 96 insertions, 0 deletions
diff --git a/include/libssh/sftp.h b/include/libssh/sftp.h index 83c6f1de..8aede051 100644 --- a/include/libssh/sftp.h +++ b/include/libssh/sftp.h @@ -593,6 +593,19 @@ int sftp_chmod(SFTP_SESSION *sftp, const char *file, mode_t mode); int sftp_utimes(SFTP_SESSION *sftp, const char *file, const struct timeval *times); /** + * @brief Create a symbolic link. + * + * @param sftp The sftp session handle. + * + * @param target Specifies the target of the symlink. + * + * @param dest Specifies the path name of the symlink to be created. + * + * @return 0 on success, < 0 on error with ssh and sftp error set. + */ +int sftp_symlink(SFTP_SESSION *sftp, const char *target, const char *dest); + +/** * @brief Canonicalize a sftp path. * * @param sftp The sftp session handle. 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; |