File kdump-sftp-file-create.patch of Package kdump

From: Petr Tesarik <ptesarik@suse.cz>
Date: Wed, 15 Apr 2015 11:48:24 +0200
Subject: Implement file create and close for SFTP
References: FATE#318874, bsc#917747
Patch-mainline: v0.8.16
Git-commit: a0facf10ce187afa2b0c52a2af891018b0c9a320

Signed-off-by: Petr Tesarik <ptesarik@suse.cz>
---
 kdumptool/sshtransfer.cc |   74 +++++++++++++++++++++++++++++++++++++++++++++++
 kdumptool/sshtransfer.h  |   17 ++++++++++
 2 files changed, 91 insertions(+)

--- a/kdumptool/sshtransfer.cc
+++ b/kdumptool/sshtransfer.cc
@@ -412,6 +412,24 @@ void SFTPTransfer::perform(DataProvider
     Debug::debug()->trace("SFTPTransfer::perform(%p, [ \"%s\"%s ])",
 	dataprovider, target_files.front().c_str(),
 	target_files.size() > 1 ? ", ..." : "");
+
+    if (directSave)
+        *directSave = false;
+
+    RootDirURLVector &urlv = getURLVector();
+    const RootDirURL &target = urlv.front();
+
+    FilePath fp = target.getPath();
+    fp.appendPath(getSubDir()).appendPath(target_files.front());
+
+    string handle = createfile(fp);
+    try {
+    } catch (...) {
+	closefile(handle);
+	throw;
+    }
+
+    closefile(handle);
 }
 
 /* -------------------------------------------------------------------------- */
@@ -483,6 +501,62 @@ void SFTPTransfer::mkpath(const std::str
 }
 
 /* -------------------------------------------------------------------------- */
+std::string SFTPTransfer::createfile(const std::string &file)
+{
+    Debug::debug()->trace("SFTPTransfer::createfile(%s)", file.c_str());
+
+    SFTPPacket pkt;
+    pkt.addByte(SSH_FXP_OPEN);
+    pkt.addInt32(nextId());
+    pkt.addString(file);
+    pkt.addInt32(SSH_FXF_WRITE | SSH_FXF_CREAT | SSH_FXF_TRUNC);
+    pkt.addInt32(0UL);		// no attrs
+    sendPacket(pkt);
+
+    recvPacket(pkt);
+    unsigned char type = pkt.getByte();
+    unsigned long id = pkt.getInt32();
+    if (id != m_lastid)
+	throw KError("SFTP request/reply id mismatch");
+
+    if (type == SSH_FXP_HANDLE)
+	return pkt.getString();
+
+    if (type != SSH_FXP_STATUS)
+	throw KError("Invalid response to SSH_FXP_OPEN: type " +
+		     Stringutil::number2string(unsigned(type)));
+
+    unsigned long errcode = pkt.getInt32();
+    throw KSFTPError("open failed on " + file, errcode);
+}
+
+/* -------------------------------------------------------------------------- */
+void SFTPTransfer::closefile(const std::string &handle)
+{
+    Debug::debug()->trace("SFTPTransfer::closefile(%s)", handle.c_str());
+
+    SFTPPacket pkt;
+    pkt.addByte(SSH_FXP_CLOSE);
+    pkt.addInt32(nextId());
+    pkt.addString(handle);
+    sendPacket(pkt);
+
+    recvPacket(pkt);
+    unsigned char type = pkt.getByte();
+    unsigned long id = pkt.getInt32();
+    if (id != m_lastid)
+	throw KError("SFTP request/reply id mismatch");
+
+    if (type != SSH_FXP_STATUS)
+	throw KError("Invalid response to SSH_FXP_OPEN: type " +
+		     Stringutil::number2string(unsigned(type)));
+
+    unsigned long errcode = pkt.getInt32();
+    if (errcode != SSH_FX_OK)
+	throw KSFTPError("close failed on " + handle, errcode);
+}
+
+/* -------------------------------------------------------------------------- */
 StringVector SFTPTransfer::makeArgs(void)
 {
     const RootDirURL &target = getURLVector().front();
--- a/kdumptool/sshtransfer.h
+++ b/kdumptool/sshtransfer.h
@@ -122,13 +122,28 @@ typedef KCodeError<KSFTPErrorCode> KSFTP
 enum {
     SSH_FXP_INIT	=   1,
     SSH_FXP_VERSION	=   2,
+    SSH_FXP_OPEN	=   3,
+    SSH_FXP_CLOSE	=   4,
     SSH_FXP_MKDIR	=  14,
     SSH_FXP_STAT	=  17,
     SSH_FXP_STATUS	= 101,
+    SSH_FXP_HANDLE	= 102,
     SSH_FXP_ATTRS	= 105,
 };
 
 /**
+ * Open flags
+ */
+enum {
+    SSH_FXF_READ	= 0x00000001,
+    SSH_FXF_WRITE	= 0x00000002,
+    SSH_FXF_APPEND	= 0x00000004,
+    SSH_FXF_CREAT	= 0x00000008,
+    SSH_FXF_TRUNC	= 0x00000010,
+    SSH_FXF_EXCL	= 0x00000020,
+};
+
+/**
  * Encode/decode an SFTP packet.
  */
 class SFTPPacket {
@@ -213,6 +228,8 @@ class SFTPTransfer : public URLTransfer
 
         bool exists(const std::string &file);
         void mkpath(const std::string &path);
+	std::string createfile(const std::string &file);
+	void closefile(const std::string &handle);
 
     private:
 	SubProcess m_process;
openSUSE Build Service is sponsored by