Add three patches from upstream git required for qemu ssh block driver.

This commit is contained in:
Richard W.M. Jones 2013-04-09 16:01:23 +01:00
parent e53393977d
commit fe8b55ff64
4 changed files with 312 additions and 0 deletions

View File

@ -0,0 +1,54 @@
From 486bb376218a37fe15318d7724d6eada36b81e6c Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 26 Mar 2013 17:58:04 +0100
Subject: [PATCH 1/3] sftp: seek: Don't flush buffers on same offset
Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
---
src/sftp.c | 27 +++++++++++++++------------
1 file changed, 15 insertions(+), 12 deletions(-)
diff --git a/src/sftp.c b/src/sftp.c
index d0536dd..3760025 100644
--- a/src/sftp.c
+++ b/src/sftp.c
@@ -2132,21 +2132,24 @@ libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE *hnd,
LIBSSH2_API void
libssh2_sftp_seek64(LIBSSH2_SFTP_HANDLE *handle, libssh2_uint64_t offset)
{
- if(handle) {
- handle->u.file.offset = handle->u.file.offset_sent = offset;
- /* discard all pending requests and currently read data */
- sftp_packetlist_flush(handle);
+ if(!handle)
+ return;
+ if(handle->u.file.offset == offset && handle->u.file.offset_sent == offset)
+ return;
- /* free the left received buffered data */
- if (handle->u.file.data_left) {
- LIBSSH2_FREE(handle->sftp->channel->session, handle->u.file.data);
- handle->u.file.data_left = handle->u.file.data_len = 0;
- handle->u.file.data = NULL;
- }
+ handle->u.file.offset = handle->u.file.offset_sent = offset;
+ /* discard all pending requests and currently read data */
+ sftp_packetlist_flush(handle);
- /* reset EOF to False */
- handle->u.file.eof = FALSE;
+ /* free the left received buffered data */
+ if (handle->u.file.data_left) {
+ LIBSSH2_FREE(handle->sftp->channel->session, handle->u.file.data);
+ handle->u.file.data_left = handle->u.file.data_len = 0;
+ handle->u.file.data = NULL;
}
+
+ /* reset EOF to False */
+ handle->u.file.eof = FALSE;
}
/* libssh2_sftp_seek
--
1.8.1.4

View File

@ -0,0 +1,26 @@
From a12f3ffab579b514eeb7fdfaca0ade271961cdb4 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Mon, 8 Apr 2013 17:30:10 +0100
Subject: [PATCH 2/3] sftp: statvfs: Along error path, reset the correct
'state' variable.
---
src/sftp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/sftp.c b/src/sftp.c
index 3760025..65fa77a 100644
--- a/src/sftp.c
+++ b/src/sftp.c
@@ -2752,7 +2752,7 @@ static int sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path,
"Error waiting for FXP EXTENDED REPLY");
} else if (data_len < 93) {
LIBSSH2_FREE(session, data);
- sftp->fstatvfs_state = libssh2_NB_state_idle;
+ sftp->statvfs_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"SFTP Protocol Error: short response");
}
--
1.8.1.4

View File

@ -0,0 +1,223 @@
From 6e0d757f24a45252c4cae9ea09732eda2562c767 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 9 Apr 2013 11:42:09 +0200
Subject: [PATCH 3/3] 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
---
docs/Makefile.am | 1 +
docs/libssh2_sftp_fsync.3 | 39 +++++++++++++++++++
include/libssh2_sftp.h | 1 +
src/sftp.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++
src/sftp.h | 5 +++
5 files changed, 143 insertions(+)
create mode 100644 docs/libssh2_sftp_fsync.3
diff --git a/docs/Makefile.am b/docs/Makefile.am
index e4cf487..e6ab394 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -120,6 +120,7 @@ dist_man_MANS = \
libssh2_sftp_fstat.3 \
libssh2_sftp_fstat_ex.3 \
libssh2_sftp_fstatvfs.3 \
+ libssh2_sftp_fsync.3 \
libssh2_sftp_get_channel.3 \
libssh2_sftp_init.3 \
libssh2_sftp_last_error.3 \
diff --git a/docs/libssh2_sftp_fsync.3 b/docs/libssh2_sftp_fsync.3
new file mode 100644
index 0000000..646760a
--- /dev/null
+++ b/docs/libssh2_sftp_fsync.3
@@ -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 fsync@openssh.com 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)
diff --git a/include/libssh2_sftp.h b/include/libssh2_sftp.h
index 74884fb..677faf2 100644
--- a/include/libssh2_sftp.h
+++ b/include/libssh2_sftp.h
@@ -247,6 +247,7 @@ LIBSSH2_API int libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *handle, \
LIBSSH2_API ssize_t libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *handle,
const char *buffer, size_t count);
+LIBSSH2_API int libssh2_sftp_fsync(LIBSSH2_SFTP_HANDLE *handle);
LIBSSH2_API int libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle);
#define libssh2_sftp_close(handle) libssh2_sftp_close_handle(handle)
diff --git a/src/sftp.c b/src/sftp.c
index 65fa77a..01017fd 100644
--- a/src/sftp.c
+++ b/src/sftp.c
@@ -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("fsync@openssh.com")(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, "fsync@openssh.com", 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
*
diff --git a/src/sftp.h b/src/sftp.h
index 55bdb46..63e8139 100644
--- a/src/sftp.h
+++ b/src/sftp.h
@@ -175,6 +175,11 @@ struct _LIBSSH2_SFTP
/* State variable used in sftp_write() */
libssh2_nonblocking_states write_state;
+ /* State variables used in sftp_fsync() */
+ libssh2_nonblocking_states fsync_state;
+ unsigned char *fsync_packet;
+ uint32_t fsync_request_id;
+
/* State variables used in libssh2_sftp_readdir() */
libssh2_nonblocking_states readdir_state;
unsigned char *readdir_packet;
--
1.8.1.4

View File

@ -19,6 +19,9 @@ URL: http://www.libssh2.org/
Source0: http://libssh2.org/download/libssh2-%{version}.tar.gz
Patch0: libssh2-1.4.2-utf8.patch
Patch1: 0001-sftp-seek-Don-t-flush-buffers-on-same-offset.patch
Patch2: 0002-sftp-statvfs-Along-error-path-reset-the-correct-stat.patch
Patch3: 0003-sftp-Add-support-for-fsync-OpenSSH-extension.patch
BuildRequires: openssl-devel
BuildRequires: zlib-devel
@ -70,6 +73,11 @@ sed -i s/4711/47%{?__isa_bits}/ tests/ssh2.{c,sh}
# Make sure things are UTF-8...
%patch0 -p1
# Three upstream patches required for qemu ssh block driver.
%patch1 -p1
%patch2 -p1
%patch3 -p1
# Make sshd transition appropriately if building in an SELinux environment
%if !(0%{?fedora} >= 17 || 0%{?rhel} >= 7)
chcon $(/usr/sbin/matchpathcon -n /etc/rc.d/init.d/sshd) tests/ssh2.sh || :
@ -133,6 +141,7 @@ make -C tests check
%changelog
* Tue Apr 9 2013 Richard W.M. Jones <rjones@redhat.com> 1.4.3-5
- Add three patches from upstream git required for qemu ssh block driver.
- Modernize the spec file:
* Remove BuildRoot.
* Remove Group.