-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sftp: Add support for fsync (OpenSSH extension).
The new libssh2_sftp_fsync API causes data and metadata in the currently open file to be committed to disk at the server. This is an OpenSSH extension to the SFTP protocol. See: https://bugzilla.mindrot.org/show_bug.cgi?id=1798
- Loading branch information
Showing
5 changed files
with
143 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
.TH libssh2_sftp_fsync 3 "8 Apr 2013" "libssh2 1.4.4" "libssh2 manual" | ||
.SH NAME | ||
libssh2_sftp_fsync - synchronize file to disk | ||
.SH SYNOPSIS | ||
.nf | ||
#include <libssh2.h> | ||
#include <libssh2_sftp.h> | ||
|
||
int | ||
libssh2_sftp_fsync(LIBSSH2_SFTP_HANDLE *handle) | ||
.fi | ||
.SH DESCRIPTION | ||
This function causes the remote server to synchronize the file | ||
data and metadata to disk (like fsync(2)). | ||
|
||
For this to work requires [email protected] support on the server. | ||
|
||
\fIhandle\fP - SFTP File Handle as returned by | ||
.BR libssh2_sftp_open_ex(3) | ||
|
||
.SH RETURN VALUE | ||
Returns 0 on success or negative on failure. If used in non-blocking mode, it | ||
returns LIBSSH2_ERROR_EAGAIN when it would otherwise block. While | ||
LIBSSH2_ERROR_EAGAIN is a negative number, it isn't really a failure per se. | ||
.SH ERRORS | ||
\fILIBSSH2_ERROR_ALLOC\fP - An internal memory allocation call failed. | ||
|
||
\fILIBSSH2_ERROR_SOCKET_SEND\fP - Unable to send data on socket. | ||
|
||
\fILIBSSH2_ERROR_SFTP_PROTOCOL\fP - An invalid SFTP protocol response | ||
was received on the socket, or an SFTP operation caused an errorcode | ||
to be returned by the server. In particular, this can be returned if | ||
the SSH server does not support the fsync operation: the SFTP subcode | ||
\fILIBSSH2_FX_OP_UNSUPPORTED\fP will be returned in this case. | ||
|
||
.SH AVAILABILITY | ||
Added in libssh2 1.4.4 and OpenSSH 6.3. | ||
.SH SEE ALSO | ||
.BR fsync(2) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -986,6 +986,10 @@ sftp_shutdown(LIBSSH2_SFTP *sftp) | |
LIBSSH2_FREE(session, sftp->symlink_packet); | ||
sftp->symlink_packet = NULL; | ||
} | ||
if (sftp->fsync_packet) { | ||
LIBSSH2_FREE(session, sftp->fsync_packet); | ||
sftp->fsync_packet = NULL; | ||
} | ||
|
||
sftp_packet_flush(sftp); | ||
|
||
|
@@ -2014,6 +2018,99 @@ libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *hnd, const char *buffer, | |
|
||
} | ||
|
||
static int sftp_fsync(LIBSSH2_SFTP_HANDLE *handle) | ||
{ | ||
LIBSSH2_SFTP *sftp = handle->sftp; | ||
LIBSSH2_CHANNEL *channel = sftp->channel; | ||
LIBSSH2_SESSION *session = channel->session; | ||
/* 34 = packet_len(4) + packet_type(1) + request_id(4) + | ||
string_len(4) + strlen("[email protected]")(17) + handle_len(4) */ | ||
uint32_t packet_len = handle->handle_len + 34; | ||
size_t data_len; | ||
unsigned char *packet, *s, *data; | ||
ssize_t rc; | ||
uint32_t retcode; | ||
|
||
if (sftp->fsync_state == libssh2_NB_state_idle) { | ||
_libssh2_debug(session, LIBSSH2_TRACE_SFTP, | ||
"Issuing fsync command"); | ||
s = packet = LIBSSH2_ALLOC(session, packet_len); | ||
if (!packet) { | ||
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, | ||
"Unable to allocate memory for FXP_EXTENDED " | ||
"packet"); | ||
} | ||
|
||
_libssh2_store_u32(&s, packet_len - 4); | ||
*(s++) = SSH_FXP_EXTENDED; | ||
sftp->fsync_request_id = sftp->request_id++; | ||
_libssh2_store_u32(&s, sftp->fsync_request_id); | ||
_libssh2_store_str(&s, "[email protected]", 17); | ||
_libssh2_store_str(&s, handle->handle, handle->handle_len); | ||
|
||
sftp->fsync_state = libssh2_NB_state_created; | ||
} else { | ||
packet = sftp->fsync_packet; | ||
} | ||
|
||
if (sftp->fsync_state == libssh2_NB_state_created) { | ||
rc = _libssh2_channel_write(channel, 0, packet, packet_len); | ||
if (rc == LIBSSH2_ERROR_EAGAIN || | ||
(0 <= rc && rc < (ssize_t)packet_len)) { | ||
sftp->fsync_packet = packet; | ||
return LIBSSH2_ERROR_EAGAIN; | ||
} | ||
|
||
LIBSSH2_FREE(session, packet); | ||
sftp->fsync_packet = NULL; | ||
|
||
if (rc < 0) { | ||
sftp->fsync_state = libssh2_NB_state_idle; | ||
return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, | ||
"_libssh2_channel_write() failed"); | ||
} | ||
sftp->fsync_state = libssh2_NB_state_sent; | ||
} | ||
|
||
rc = sftp_packet_require(sftp, SSH_FXP_STATUS, | ||
sftp->fsync_request_id, &data, &data_len); | ||
if (rc == LIBSSH2_ERROR_EAGAIN) { | ||
return rc; | ||
} else if (rc) { | ||
sftp->fsync_state = libssh2_NB_state_idle; | ||
return _libssh2_error(session, rc, | ||
"Error waiting for FXP EXTENDED REPLY"); | ||
} | ||
|
||
sftp->fsync_state = libssh2_NB_state_idle; | ||
|
||
retcode = _libssh2_ntohu32(data + 5); | ||
LIBSSH2_FREE(session, data); | ||
|
||
if (retcode != LIBSSH2_FX_OK) { | ||
sftp->last_errno = retcode; | ||
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, | ||
"fsync failed"); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
/* libssh2_sftp_fsync | ||
* Commit data on the handle to disk. | ||
*/ | ||
LIBSSH2_API int | ||
libssh2_sftp_fsync(LIBSSH2_SFTP_HANDLE *hnd) | ||
{ | ||
int rc; | ||
if(!hnd) | ||
return LIBSSH2_ERROR_BAD_USE; | ||
BLOCK_ADJUST(rc, hnd->sftp->channel->session, | ||
sftp_fsync(hnd)); | ||
return rc; | ||
} | ||
|
||
|
||
/* | ||
* sftp_fstat | ||
* | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters