File kdump-sftp-mkpath.patch of Package kdump
From: Petr Tesarik <ptesarik@suse.cz>
Date: Tue, 14 Apr 2015 23:14:56 +0200
Subject: Implement SFTPTransfer::mkpath and call it at initialization
References: FATE#318874, bsc#917747
Patch-mainline: v0.8.16
Git-commit: 3d32bb0bb6e2e5954066214f48d82cbcbf7d890c
Similar to other transfer methods, the target directory is created in
the constructor.
Signed-off-by: Petr Tesarik <ptesarik@suse.cz>
---
kdumptool/sshtransfer.cc | 72 +++++++++++++++++++++++++++++++++++++++++++++++
kdumptool/sshtransfer.h | 12 +++++++
2 files changed, 84 insertions(+)
--- a/kdumptool/sshtransfer.cc
+++ b/kdumptool/sshtransfer.cc
@@ -380,6 +380,10 @@ SFTPTransfer::SFTPTransfer(const RootDir
Stringutil::number2string(unsigned(type)));
m_proto_ver = initpkt.getInt32();
Debug::debug()->dbg("Remote SFTP version %lu", m_proto_ver);
+
+ FilePath fp = parser.getPath();
+ fp.appendPath(getSubDir());
+ mkpath(fp);
}
/* -------------------------------------------------------------------------- */
@@ -411,6 +415,74 @@ void SFTPTransfer::perform(DataProvider
}
/* -------------------------------------------------------------------------- */
+bool SFTPTransfer::exists(const string &file)
+{
+ Debug::debug()->trace("SFTPTransfer::exists(%s)", file.c_str());
+
+ SFTPPacket pkt;
+ pkt.addByte(SSH_FXP_STAT);
+ pkt.addInt32(nextId());
+ pkt.addString(file);
+ 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_ATTRS)
+ return true;
+
+ if (type != SSH_FXP_STATUS)
+ throw KError("Invalid response to SSH_FXP_LSTAT: type " +
+ Stringutil::number2string(unsigned(type)));
+
+ unsigned long errcode = pkt.getInt32();
+ if (errcode != SSH_FX_NO_SUCH_FILE)
+ throw KSFTPError("stat failed on " + file, errcode);
+
+ return false;
+}
+
+/* -------------------------------------------------------------------------- */
+void SFTPTransfer::mkpath(const std::string &path)
+{
+ Debug::debug()->trace("SFTPTransfer::mkpath(%s)", path.c_str());
+
+ if (!exists(path)) {
+ KString dir = path;
+ dir.rtrim(PATH_SEPARATOR);
+ KString::size_type pos = dir.rfind(PATH_SEPARATOR);
+ if (pos > 0 && pos != KString::npos) {
+ dir.erase(pos);
+ mkpath(dir);
+ }
+
+ SFTPPacket pkt;
+ pkt.addByte(SSH_FXP_MKDIR);
+ pkt.addInt32(nextId());
+ pkt.addString(path);
+ pkt.addInt32(0UL);
+ 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_MKDIR: type " +
+ Stringutil::number2string(unsigned(type)));
+
+ unsigned long errcode = pkt.getInt32();
+ if (errcode != SSH_FX_OK)
+ throw KSFTPError("mkdir failed on " + path, errcode);
+ }
+}
+
+/* -------------------------------------------------------------------------- */
StringVector SFTPTransfer::makeArgs(void)
{
const RootDirURL &target = getURLVector().front();
--- a/kdumptool/sshtransfer.h
+++ b/kdumptool/sshtransfer.h
@@ -122,6 +122,10 @@ typedef KCodeError<KSFTPErrorCode> KSFTP
enum {
SSH_FXP_INIT = 1,
SSH_FXP_VERSION = 2,
+ SSH_FXP_MKDIR = 14,
+ SSH_FXP_STAT = 17,
+ SSH_FXP_STATUS = 101,
+ SSH_FXP_ATTRS = 105,
};
/**
@@ -207,13 +211,21 @@ class SFTPTransfer : public URLTransfer
protected:
static const int MY_PROTO_VER = 3; // our advertised version
+ bool exists(const std::string &file);
+ void mkpath(const std::string &path);
+
private:
SubProcess m_process;
int m_fdreq, m_fdresp;
unsigned long m_proto_ver; // remote SFTP protocol version
+ unsigned long m_lastid;
StringVector makeArgs(void);
+ unsigned long nextId(void)
+ throw ()
+ { return m_lastid = (m_lastid + 1) & ((1UL << 32) - 1); }
+
void sendPacket(SFTPPacket &pkt);
void recvPacket(SFTPPacket &pkt);
void recvBuffer(unsigned char *bufp, size_t buflen);