Accepting request 234828 from Kernel:kdump
Fix service failures after online/offline CPU under systemd. URL-decode the target URL. (forwarded request 234827 from ptesarik) OBS-URL: https://build.opensuse.org/request/show/234828 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/kdump?expand=0&rev=70
This commit is contained in:
commit
b277353440
145
kdump-fix-udev-rules.patch
Normal file
145
kdump-fix-udev-rules.patch
Normal file
@ -0,0 +1,145 @@
|
||||
From: Petr Tesarik <ptesarik@suse.cz>
|
||||
Subject: Avoid entering failed state on CPU hotplug
|
||||
References: bnc#874992, bnc#809209
|
||||
Patch-mainline: scheduled for v0.8.13
|
||||
|
||||
When more than 5 CPUs are quickly offlined or onlined, the kdump
|
||||
service enters and remains in a "failed state".
|
||||
|
||||
This issue appears to be caused by systemd's service start rate
|
||||
limit default [more than 5 times within 10 seconds per
|
||||
systemd.service(5) man page] being exceeded due to the udev
|
||||
initiated kdump service restart for every CPU offline or online
|
||||
operation.
|
||||
|
||||
Avoid the problem by preventing the systemd rate limit threshold
|
||||
encounter by flushing the reset rate counter prior to each CPU
|
||||
offline and online related kdump service restart.
|
||||
|
||||
Additionally, limit the restart to IBM POWER, because other
|
||||
systems do not appear to be affected by bnc 389658.
|
||||
|
||||
And the z/Architecture do not need a restart on memory hotplug
|
||||
either, so the udev rules are not needed at all.
|
||||
|
||||
Signed-off-by: Petr Tesarik <ptesarik@suse.cz>
|
||||
diff --git a/70-kdump.rules b/70-kdump.rules
|
||||
deleted file mode 100644
|
||||
index c215f23..0000000
|
||||
--- a/70-kdump.rules
|
||||
+++ /dev/null
|
||||
@@ -1,12 +0,0 @@
|
||||
-#
|
||||
-# Kdump core headers needs to be regnerated if the CPUs or memory changes.
|
||||
-# For this, reload kdump.
|
||||
-#
|
||||
-# Novell Bug #389658
|
||||
-#
|
||||
-
|
||||
-SUBSYSTEM=="cpu", ACTION=="online", PROGRAM="/etc/init.d/boot.kdump try-restart"
|
||||
-SUBSYSTEM=="cpu", ACTION=="offline", PROGRAM="/etc/init.d/boot.kdump try-restart"
|
||||
-SUBSYSTEM=="memory", ACTION=="add", PROGRAM="/etc/init.d/boot.kdump try-restart"
|
||||
-SUBSYSTEM=="memory", ACTION=="remove", PROGRAM="/etc/init.d/boot.kdump try-restart"
|
||||
-
|
||||
diff --git a/70-kdump.rules.in b/70-kdump.rules.in
|
||||
new file mode 100644
|
||||
index 0000000..0ec2127
|
||||
--- /dev/null
|
||||
+++ b/70-kdump.rules.in
|
||||
@@ -0,0 +1,37 @@
|
||||
+@if @ARCH@ s390 s390x
|
||||
+#
|
||||
+# For s390x the ELF header is created in the kdump kernel and therefore
|
||||
+# no kdump udev rules are required.
|
||||
+#
|
||||
+@else
|
||||
+#
|
||||
+# Kdump core headers needs to be regnerated if the CPUs or memory changes.
|
||||
+# For this, reload kdump.
|
||||
+#
|
||||
+# Novell Bug #389658
|
||||
+#
|
||||
+
|
||||
+TEST=="/usr/bin/systemctl", GOTO="kdump_systemd"
|
||||
+
|
||||
+@if @ARCH@ ppc ppc64 ppc64le
|
||||
+SUBSYSTEM=="cpu", ACTION=="online", RUN+="/etc/init.d/boot.kdump try-restart"
|
||||
+SUBSYSTEM=="cpu", ACTION=="offline", RUN+="/etc/init.d/boot.kdump try-restart"
|
||||
+@endif
|
||||
+SUBSYSTEM=="memory", ACTION=="add", RUN+="/etc/init.d/boot.kdump try-restart"
|
||||
+SUBSYSTEM=="memory", ACTION=="remove", RUN+="/etc/init.d/boot.kdump try-restart"
|
||||
+
|
||||
+GOTO="kdump_end"
|
||||
+
|
||||
+# Systemd limits service start rate, so if udev events are emitted too
|
||||
+# often, kdump will enter failed state, unless the counter is reset here.
|
||||
+LABEL="kdump_systemd"
|
||||
+
|
||||
+@if @ARCH@ ppc ppc64 ppc64le
|
||||
+SUBSYSTEM=="cpu", ACTION=="online", RUN+="/usr/bin/systemctl reset-failed kdump", RUN+="/usr/bin/systemctl try-restart kdump"
|
||||
+SUBSYSTEM=="cpu", ACTION=="offline", RUN+="/usr/bin/systemctl reset-failed kdump", RUN+="/usr/bin/systemctl try-restart kdump"
|
||||
+@endif
|
||||
+SUBSYSTEM=="memory", ACTION=="add", RUN+="/usr/bin/systemctl reset-failed kdump", RUN+="/usr/bin/systemctl try-restart kdump"
|
||||
+SUBSYSTEM=="memory", ACTION=="remove", RUN+="/usr/bin/systemctl reset-failed kdump", RUN+="/usr/bin/systemctl try-restart kdump"
|
||||
+
|
||||
+LABEL="kdump_end"
|
||||
+@endif
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index 59c4607..e10afa9 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -26,7 +26,7 @@ SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
|
||||
|
||||
cmake_minimum_required(VERSION 2.6.2)
|
||||
set (PACKAGE_STRING "kdump")
|
||||
-set (PACKAGE_VERSION "0.8.12")
|
||||
+set (PACKAGE_VERSION "0.8.13")
|
||||
|
||||
include_directories("${PROJECT_BINARY_DIR}")
|
||||
|
||||
@@ -195,8 +195,26 @@ INSTALL(FILES
|
||||
/var/adm/fillup-templates/
|
||||
)
|
||||
|
||||
+ADD_CUSTOM_COMMAND(
|
||||
+ OUTPUT
|
||||
+ 70-kdump.rules
|
||||
+ COMMAND
|
||||
+ ARCH=${CMAKE_SYSTEM_PROCESSOR}
|
||||
+ awk -f ${CMAKE_CURRENT_SOURCE_DIR}/process_cond.awk
|
||||
+ ${CMAKE_CURRENT_SOURCE_DIR}/70-kdump.rules.in
|
||||
+ > ${CMAKE_CURRENT_BINARY_DIR}/70-kdump.rules
|
||||
+ DEPENDS
|
||||
+ 70-kdump.rules.in
|
||||
+)
|
||||
+ADD_CUSTOM_TARGET(
|
||||
+ kdump.rules
|
||||
+ ALL
|
||||
+ DEPENDS
|
||||
+ 70-kdump.rules
|
||||
+)
|
||||
+
|
||||
INSTALL(FILES
|
||||
- ${CMAKE_CURRENT_SOURCE_DIR}/70-kdump.rules
|
||||
+ ${CMAKE_CURRENT_BINARY_DIR}/70-kdump.rules
|
||||
DESTINATION
|
||||
/etc/udev/rules.d
|
||||
)
|
||||
diff --git a/process_cond.awk b/process_cond.awk
|
||||
index 82ffe92..d6f966b 100755
|
||||
--- a/process_cond.awk
|
||||
+++ b/process_cond.awk
|
||||
@@ -5,7 +5,12 @@
|
||||
ENVIRON[var[1]] \
|
||||
substr($0, RSTART + RLENGTH)
|
||||
stack[sp++] = remove
|
||||
- remove = remove || ($2 != $3)
|
||||
+ condition = 0
|
||||
+ for (i = 3; i <= NF; i++) {
|
||||
+ if ($2 == $i)
|
||||
+ condition = 1
|
||||
+ }
|
||||
+ remove = remove || !condition
|
||||
skip = 1
|
||||
}
|
||||
/^@else\>/ {
|
718
kdump-urldecode.patch
Normal file
718
kdump-urldecode.patch
Normal file
@ -0,0 +1,718 @@
|
||||
From: Petr Tesarik <ptesarik@suse.cz>
|
||||
Subject: Perform percent decoding on target URL
|
||||
References: bnc#869590
|
||||
Patch-mainline: scheduled for v0.8.13
|
||||
|
||||
Signed-off-by: Petr Tesarik <ptesarik@suse.cz>
|
||||
|
||||
diff --git a/kdumptool/CMakeLists.txt b/kdumptool/CMakeLists.txt
|
||||
index 81ce47e..9a5bc1a 100644
|
||||
--- a/kdumptool/CMakeLists.txt
|
||||
+++ b/kdumptool/CMakeLists.txt
|
||||
@@ -142,3 +142,8 @@ add_executable(testprocess
|
||||
testprocess.cc
|
||||
)
|
||||
target_link_libraries(testprocess common ${EXTRA_LIBS})
|
||||
+
|
||||
+add_executable(testurldecode
|
||||
+ testurldecode.cc
|
||||
+)
|
||||
+target_link_libraries(testurldecode common ${EXTRA_LIBS})
|
||||
diff --git a/kdumptool/stringutil.cc b/kdumptool/stringutil.cc
|
||||
index 807a30a..70d2dc5 100644
|
||||
--- a/kdumptool/stringutil.cc
|
||||
+++ b/kdumptool/stringutil.cc
|
||||
@@ -270,6 +270,19 @@ void Stringutil::digest_base64(const void *buf, size_t len,
|
||||
|
||||
#endif // HAVE_LIBSSL
|
||||
|
||||
+// -----------------------------------------------------------------------------
|
||||
+int Stringutil::hex2int(char c)
|
||||
+ throw (KError)
|
||||
+{
|
||||
+ if (c >= '0' && c <= '9')
|
||||
+ return c - '0';
|
||||
+ if (c >= 'a' && c <= 'f')
|
||||
+ return c - 'a' + 10;
|
||||
+ if (c >= 'A' && c <= 'F')
|
||||
+ return c - 'A' + 10;
|
||||
+ throw KError(string("Stringutil::hex2int: '") + c + "' is not a hex digit");
|
||||
+}
|
||||
+
|
||||
//}}}
|
||||
//{{{ KString ------------------------------------------------------------------
|
||||
|
||||
@@ -333,6 +346,27 @@ bool KString::endsWith(const string &part) const
|
||||
return strcmp(c_str() + size() - part.size(), part.c_str()) == 0;
|
||||
}
|
||||
|
||||
+// -----------------------------------------------------------------------------
|
||||
+KString &KString::decodeURL(bool formenc)
|
||||
+ throw()
|
||||
+{
|
||||
+ iterator src, dst;
|
||||
+ for (src = dst = begin(); src != end(); ++src) {
|
||||
+ char c1, c2;
|
||||
+ if (*src == '%' && end() - src >= 2 &&
|
||||
+ isxdigit(c1 = src[1]) && isxdigit(c2 = src[2])) {
|
||||
+ *dst++ = (Stringutil::hex2int(c1) << 4) |
|
||||
+ Stringutil::hex2int(c2);
|
||||
+ src += 2;
|
||||
+ } else if (formenc && *src == '+')
|
||||
+ *dst++ = ' ';
|
||||
+ else
|
||||
+ *dst++ = *src;
|
||||
+ }
|
||||
+ resize(dst - begin());
|
||||
+ return *this;
|
||||
+}
|
||||
+
|
||||
//}}}
|
||||
|
||||
// vim: set sw=4 ts=4 fdm=marker et: :collapseFolds=1:
|
||||
diff --git a/kdumptool/stringutil.h b/kdumptool/stringutil.h
|
||||
index 321ab59..4dad735 100644
|
||||
--- a/kdumptool/stringutil.h
|
||||
+++ b/kdumptool/stringutil.h
|
||||
@@ -200,6 +200,9 @@ class Stringutil {
|
||||
throw (KError);
|
||||
|
||||
#endif // HAVE_LIBSSL
|
||||
+
|
||||
+ static int hex2int(char c)
|
||||
+ throw (KError);
|
||||
};
|
||||
|
||||
//}}}
|
||||
@@ -289,6 +292,14 @@ class KString : public std::string {
|
||||
bool endsWith(const std::string &part) const
|
||||
throw ();
|
||||
|
||||
+ /**
|
||||
+ * Perform URL decoding on the string.
|
||||
+ *
|
||||
+ * @param[in] formenc if @c true, translate '+' into spaces
|
||||
+ * @return reference to this object (after decoding)
|
||||
+ */
|
||||
+ KString &decodeURL(bool formenc = false)
|
||||
+ throw();
|
||||
};
|
||||
|
||||
//}}}
|
||||
diff --git a/kdumptool/testurldecode.cc b/kdumptool/testurldecode.cc
|
||||
new file mode 100644
|
||||
index 0000000..36e639f
|
||||
--- /dev/null
|
||||
+++ b/kdumptool/testurldecode.cc
|
||||
@@ -0,0 +1,60 @@
|
||||
+/*
|
||||
+ * (c) 2014, Petr Tesarik <ptesarik@suse.de>, SUSE LINUX Products GmbH
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License
|
||||
+ * as published by the Free Software Foundation; either version 2
|
||||
+ * of the License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program; if not, write to the Free Software
|
||||
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
+ * 02110-1301, USA.
|
||||
+ */
|
||||
+#include <iostream>
|
||||
+#include <cstdlib>
|
||||
+
|
||||
+#include "global.h"
|
||||
+#include "stringutil.h"
|
||||
+#include "debug.h"
|
||||
+
|
||||
+using std::cout;
|
||||
+using std::cerr;
|
||||
+using std::endl;
|
||||
+
|
||||
+// -----------------------------------------------------------------------------
|
||||
+int main(int argc, char *argv[])
|
||||
+{
|
||||
+ Debug::debug()->setStderrLevel(Debug::DL_TRACE);
|
||||
+ bool formenc = false;
|
||||
+
|
||||
+ try {
|
||||
+ int i = 1;
|
||||
+ if (i < argc && KString(argv[i]) == "-f") {
|
||||
+ formenc = true;
|
||||
+ ++i;
|
||||
+ }
|
||||
+
|
||||
+ bool addspace = false;
|
||||
+ while (i < argc) {
|
||||
+ KString arg(argv[i]);
|
||||
+ if (addspace)
|
||||
+ cout << ' ';
|
||||
+ cout << arg.decodeURL(formenc);
|
||||
+ addspace = true;
|
||||
+ ++i;
|
||||
+ }
|
||||
+ cout << endl;
|
||||
+
|
||||
+ } catch(const std::exception &ex) {
|
||||
+ cerr << "Fatal exception: " << ex.what() << endl;
|
||||
+ return EXIT_FAILURE;
|
||||
+ }
|
||||
+
|
||||
+ return EXIT_SUCCESS;
|
||||
+}
|
||||
diff --git a/kdumptool/urlparser.cc b/kdumptool/urlparser.cc
|
||||
index 095415e..fda09ea 100644
|
||||
--- a/kdumptool/urlparser.cc
|
||||
+++ b/kdumptool/urlparser.cc
|
||||
@@ -86,166 +86,147 @@ string URLParser::protocol2string(URLParser::Protocol protocol)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
+string URLParser::extractScheme(string::iterator &it,
|
||||
+ const string::const_iterator &end)
|
||||
+{
|
||||
+ string::iterator const start = it;
|
||||
+
|
||||
+ if (it == m_url.end() || !isalpha(*it))
|
||||
+ return string();
|
||||
+
|
||||
+ do {
|
||||
+ ++it;
|
||||
+ if (it == m_url.end()) {
|
||||
+ it = start;
|
||||
+ return string();
|
||||
+ }
|
||||
+ } while (*it != ':' && *it != '/' && *it != '?' && *it != '#');
|
||||
+
|
||||
+ if (*it != ':') {
|
||||
+ it = start;
|
||||
+ return string();
|
||||
+ }
|
||||
+
|
||||
+ return string(start, it++);
|
||||
+}
|
||||
+
|
||||
+// -----------------------------------------------------------------------------
|
||||
+string URLParser::extractAuthority(string::iterator &it,
|
||||
+ const string::const_iterator &end)
|
||||
+{
|
||||
+ if (end - it < 2 || it[0] != '/' || it[1] != '/')
|
||||
+ return string();
|
||||
+
|
||||
+ it += 2;
|
||||
+ string::iterator const start = it;
|
||||
+ while (*it != '/' && *it != '?' && *it != '#')
|
||||
+ ++it;
|
||||
+
|
||||
+ return string(start, it);
|
||||
+}
|
||||
+
|
||||
+// -----------------------------------------------------------------------------
|
||||
URLParser::URLParser(const std::string &url)
|
||||
throw (KError)
|
||||
: m_url(url), m_port(-1)
|
||||
{
|
||||
Debug::debug()->trace("URLParser::URLParser(%s)", url.c_str());
|
||||
|
||||
- if (url.size() == 0)
|
||||
- throw KError("URL must be longer than 0 characters.");
|
||||
-
|
||||
- // local files that don't have URL syntax
|
||||
- // we support that for backward-compatibility
|
||||
- if (url[0] == '/') {
|
||||
- m_protocol = PROT_FILE;
|
||||
- m_path = url;
|
||||
- return;
|
||||
- }
|
||||
+ string::iterator it = m_url.begin();
|
||||
|
||||
//
|
||||
- // get the protocol
|
||||
+ // extract the three main URL componenets
|
||||
//
|
||||
+ string scheme = extractScheme(it, m_url.end());
|
||||
+ string authority = extractAuthority(it, m_url.end());
|
||||
+ m_path.assign(it, m_url.end());
|
||||
+ // TODO: query and fragment are not handled
|
||||
|
||||
- string::size_type first_colon = url.find(':');
|
||||
- if (first_colon == string::npos)
|
||||
- throw KError("The URL does not contain any protocol.");
|
||||
- string proto_part = url.substr(0, first_colon);
|
||||
- Debug::debug()->trace("Setting protocol to %s", proto_part.c_str());
|
||||
- m_protocol = string2protocol(proto_part);
|
||||
-
|
||||
- if (url.size() < (first_colon + 3) ||
|
||||
- url[first_colon+1] != '/' ||
|
||||
- url[first_colon+2] != '/')
|
||||
- throw KError("protocol: must be followed by '//'.");
|
||||
+ if (m_path.empty() || m_path[0] != '/')
|
||||
+ throw KError("URLParser: Only absolute paths are supported.");
|
||||
|
||||
//
|
||||
- // call the parse methods matching for the protocol
|
||||
+ // parse the authority part
|
||||
//
|
||||
|
||||
- if (m_protocol == PROT_FILE) {
|
||||
- m_path = url.substr(first_colon+3);
|
||||
- } else if (m_protocol == PROT_NFS) {
|
||||
- parseNFSUrl(url.substr(first_colon+3));
|
||||
- } else if (m_protocol == PROT_SFTP || m_protocol == PROT_SSH ||
|
||||
- m_protocol == PROT_FTP || m_protocol == PROT_CIFS) {
|
||||
- parseFTPUrl(url.substr(first_colon+3));
|
||||
- } else
|
||||
- throw KError("Invalid protocol: " +
|
||||
- Stringutil::number2string(m_protocol) + ".");
|
||||
+ // Look for (optional) port
|
||||
+ it = authority.end();
|
||||
+ while (it != authority.begin() && isdigit(it[-1]))
|
||||
+ --it;
|
||||
+ if (it != authority.begin() && it[-1] == ':') {
|
||||
+ string port(it, authority.end());
|
||||
+ authority.resize(it - authority.begin() - 1);
|
||||
|
||||
- Debug::debug()->dbg("URL parsed as: protocol=%s, host=%s, port=%d, "
|
||||
- "username=%s, password=%s, path=%s",
|
||||
- getProtocolAsString().c_str(),
|
||||
- getHostname().c_str(), getPort(), getUsername().c_str(),
|
||||
- getPassword().c_str(), getPath().c_str());
|
||||
+ if (port.size() > 0)
|
||||
+ m_port = Stringutil::string2number(port);
|
||||
+ }
|
||||
|
||||
-}
|
||||
+ // look for userinfo
|
||||
+ string::size_type last_at = authority.rfind('@');
|
||||
+ if (last_at != string::npos) {
|
||||
+ m_hostname = authority.substr(last_at+1);
|
||||
+ authority.resize(last_at);
|
||||
+
|
||||
+ // now separate user and password
|
||||
+ string::size_type first_colon = authority.find(':');
|
||||
+ if (first_colon != string::npos) {
|
||||
+ m_username = authority.substr(0, first_colon);
|
||||
+ m_password = authority.substr(first_colon+1);
|
||||
+ } else
|
||||
+ m_username = authority;
|
||||
+ } else
|
||||
+ m_hostname = authority;
|
||||
|
||||
-// -----------------------------------------------------------------------------
|
||||
-void URLParser::parseUserPassHostPort(const string &userpasshostport)
|
||||
- throw (KError)
|
||||
-{
|
||||
- // now scan for an '@' to separate userhost from hostport
|
||||
- string::size_type last_at = userpasshostport.rfind('@');
|
||||
- string userhost;
|
||||
- string hostport;
|
||||
- if (last_at == string::npos) {
|
||||
- hostport = userpasshostport;
|
||||
-
|
||||
- switch (m_protocol) {
|
||||
- case PROT_FTP:
|
||||
- m_username = FTP_DEFAULT_USER;
|
||||
- break;
|
||||
-
|
||||
- case PROT_SFTP:
|
||||
- case PROT_SSH:
|
||||
- m_username = SFTP_DEFAULT_USER;
|
||||
- break;
|
||||
-
|
||||
- default:
|
||||
- // do nothing but make the compiler happy
|
||||
- break;
|
||||
- }
|
||||
+ //
|
||||
+ // undo percent encoding
|
||||
+ //
|
||||
+ m_hostname.decodeURL();
|
||||
+ m_password.decodeURL();
|
||||
+ m_username.decodeURL();
|
||||
+ m_path.decodeURL();
|
||||
|
||||
+ //
|
||||
+ // guess the scheme, if omitted
|
||||
+ //
|
||||
+ if (scheme.empty()) {
|
||||
+ if (m_hostname.empty() || m_hostname == "localhost") {
|
||||
+ m_protocol = PROT_FILE;
|
||||
+ Debug::debug()->trace("URL looks like a local file");
|
||||
+ } else {
|
||||
+ m_protocol = PROT_NFS;
|
||||
+ Debug::debug()->trace("URL looks like a remote file");
|
||||
+ }
|
||||
} else {
|
||||
- string userpass = userpasshostport.substr(0, last_at);
|
||||
- hostport = userpasshostport.substr(last_at+1);
|
||||
-
|
||||
- // now separate user and passwort
|
||||
- string::size_type firstcolon = userpass.find(':');
|
||||
- if (firstcolon != string::npos) {
|
||||
- m_username = userpass.substr(0, firstcolon);
|
||||
- m_password = userpass.substr(firstcolon+1);
|
||||
- } else
|
||||
- m_username = userpass;
|
||||
+ Debug::debug()->trace("Scheme explicitly set to %s", scheme.c_str());
|
||||
+ m_protocol = string2protocol(scheme);
|
||||
}
|
||||
|
||||
- // look for a literal IPv6 addresses
|
||||
- string::size_type last_colon = hostport.rfind(':');
|
||||
- if (hostport[0] == '[') {
|
||||
- string::size_type bracket = hostport.find(']');
|
||||
- if (bracket != string::npos && bracket > last_colon)
|
||||
- last_colon = string::npos;
|
||||
- }
|
||||
-
|
||||
- // and separate host and port
|
||||
- if (last_colon != string::npos) {
|
||||
- m_hostname = hostport.substr(0, last_colon);
|
||||
- string portstr = hostport.substr(last_colon+1);
|
||||
- if (portstr.size() > 0)
|
||||
- m_port = Stringutil::string2number(portstr);
|
||||
- } else
|
||||
- m_hostname = hostport;
|
||||
-}
|
||||
-
|
||||
-// -----------------------------------------------------------------------------
|
||||
-void URLParser::parseNFSUrl(const string &partUrl)
|
||||
- throw (KError)
|
||||
-{
|
||||
- Debug::debug()->trace("URLParser::parseNFSUrl(%s)", partUrl.c_str());
|
||||
-
|
||||
- // look for the first '/'
|
||||
- string::size_type first_slash = partUrl.find('/');
|
||||
- if (first_slash == string::npos)
|
||||
- throw KError("NFS URL must contain at least one '/'.");
|
||||
+ //
|
||||
+ // protocol-specific defaults
|
||||
+ //
|
||||
|
||||
- m_hostname = partUrl.substr(0, first_slash);
|
||||
+ if (m_protocol == PROT_FILE && m_hostname == "localhost")
|
||||
+ m_hostname.clear();
|
||||
|
||||
- string::size_type last_colon = m_hostname.rfind(':');
|
||||
- if (m_hostname[0] == '[') {
|
||||
- string::size_type bracket = m_hostname.find(']');
|
||||
- if (bracket != string::npos && bracket > last_colon)
|
||||
- last_colon = string::npos;
|
||||
+ if (m_username.empty()) {
|
||||
+ if (m_protocol == PROT_FTP)
|
||||
+ m_username = FTP_DEFAULT_USER;
|
||||
+ else if (m_protocol == PROT_SFTP || m_protocol == PROT_SSH)
|
||||
+ m_username = SFTP_DEFAULT_USER;
|
||||
}
|
||||
- if (last_colon != string::npos) {
|
||||
- string hostport = m_hostname;
|
||||
- m_hostname = hostport.substr(0, last_colon);
|
||||
- string portstring = hostport.substr(last_colon+1);
|
||||
- if (portstring.size() > 0)
|
||||
- m_port = Stringutil::string2number(hostport.substr(last_colon+1));
|
||||
- }
|
||||
-
|
||||
- m_path = partUrl.substr(first_slash);
|
||||
-}
|
||||
-
|
||||
-// -----------------------------------------------------------------------------
|
||||
-void URLParser::parseFTPUrl(const string &partUrl)
|
||||
- throw (KError)
|
||||
-{
|
||||
- Debug::debug()->trace("URLParser::parseFTPUrl(%s)", partUrl.c_str());
|
||||
|
||||
- // look for the first '/' to separate the host name part from the
|
||||
- // path name
|
||||
- string::size_type first_slash = partUrl.find('/');
|
||||
- if (first_slash == string::npos)
|
||||
- throw KError(getProtocolAsString() +
|
||||
- " URL must contain at least one '/'.");
|
||||
+ //
|
||||
+ // sanity checks
|
||||
+ //
|
||||
+ if (m_protocol == PROT_FILE && !m_hostname.empty())
|
||||
+ throw KError("File protocol cannot specify a remote host");
|
||||
|
||||
- parseUserPassHostPort(partUrl.substr(0, first_slash));
|
||||
+ Debug::debug()->dbg("URL parsed as: protocol=%s, host=%s, port=%d, "
|
||||
+ "username=%s, password=%s, path=%s",
|
||||
+ getProtocolAsString().c_str(),
|
||||
+ getHostname().c_str(), getPort(), getUsername().c_str(),
|
||||
+ getPassword().c_str(), getPath().c_str());
|
||||
|
||||
- // and the rest is the path
|
||||
- m_path = partUrl.substr(first_slash);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
diff --git a/kdumptool/urlparser.h b/kdumptool/urlparser.h
|
||||
index aac01e7..94aab27 100644
|
||||
--- a/kdumptool/urlparser.h
|
||||
+++ b/kdumptool/urlparser.h
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "global.h"
|
||||
#include "optionparser.h"
|
||||
#include "subcommand.h"
|
||||
+#include "stringutil.h"
|
||||
|
||||
//{{{ URLParser ----------------------------------------------------------------
|
||||
|
||||
@@ -158,29 +159,32 @@ class URLParser {
|
||||
static std::string protocol2string(Protocol protocol)
|
||||
throw (KError);
|
||||
|
||||
- protected:
|
||||
-
|
||||
- void parseCifsUrl(const std::string &partUrl)
|
||||
- throw (KError);
|
||||
-
|
||||
- void parseNFSUrl(const std::string &partUrl)
|
||||
- throw (KError);
|
||||
-
|
||||
- void parseUserPassHostPort(const std::string &userpasshostport)
|
||||
- throw (KError);
|
||||
-
|
||||
- void parseFTPUrl(const std::string &partUrl)
|
||||
- throw (KError);
|
||||
-
|
||||
private:
|
||||
- std::string m_url;
|
||||
+ std::string m_url;
|
||||
Protocol m_protocol;
|
||||
- std::string m_hostname;
|
||||
- std::string m_password;
|
||||
- std::string m_username;
|
||||
+ KString m_hostname;
|
||||
+ KString m_password;
|
||||
+ KString m_username;
|
||||
int m_port;
|
||||
- std::string m_path;
|
||||
- std::string m_share;
|
||||
+ KString m_path;
|
||||
+
|
||||
+ /**
|
||||
+ * Extract scheme from a string
|
||||
+ *
|
||||
+ * @param[in,out] it starting position (updated if scheme is found)
|
||||
+ * @param[in] end end of input string
|
||||
+ */
|
||||
+ std::string extractScheme(std::string::iterator &it,
|
||||
+ const std::string::const_iterator &end);
|
||||
+
|
||||
+ /**
|
||||
+ * Extract authority from a string
|
||||
+ *
|
||||
+ * @param[in,out] it starting position (updated if authority is found)
|
||||
+ * @param[in] end end of input string
|
||||
+ */
|
||||
+ std::string extractAuthority(std::string::iterator &it,
|
||||
+ const std::string::const_iterator &end);
|
||||
};
|
||||
|
||||
//}}}
|
||||
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
|
||||
index 41c222b..0b35466 100644
|
||||
--- a/tests/CMakeLists.txt
|
||||
+++ b/tests/CMakeLists.txt
|
||||
@@ -60,3 +60,7 @@ ADD_TEST(delete_dumps
|
||||
ADD_TEST(process
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/process.sh
|
||||
${CMAKE_BINARY_DIR}/kdumptool/testprocess)
|
||||
+
|
||||
+ADD_TEST(urldecode
|
||||
+ ${CMAKE_CURRENT_SOURCE_DIR}/testurldecode.sh
|
||||
+ ${CMAKE_BINARY_DIR}/kdumptool/testurldecode)
|
||||
diff --git a/tests/testurldecode.sh b/tests/testurldecode.sh
|
||||
new file mode 100755
|
||||
index 0000000..a8076b4
|
||||
--- /dev/null
|
||||
+++ b/tests/testurldecode.sh
|
||||
@@ -0,0 +1,163 @@
|
||||
+#!/bin/bash
|
||||
+#
|
||||
+# (c) 2014, Petr Tesarik <ptesarik@suse.de>, SUSE LINUX Products GmbH
|
||||
+#
|
||||
+# This program is free software; you can redistribute it and/or
|
||||
+# modify it under the terms of the GNU General Public License
|
||||
+# as published by the Free Software Foundation; either version 2
|
||||
+# of the License, or (at your option) any later version.
|
||||
+#
|
||||
+# This program is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+# GNU General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with this program; if not, write to the Free Software
|
||||
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
+# 02110-1301, USA.
|
||||
+#
|
||||
+
|
||||
+# Check that results match expectation
|
||||
+# {{{
|
||||
+function check()
|
||||
+{
|
||||
+ local arg="$1"
|
||||
+ local expect="$2"
|
||||
+ local result="$3"
|
||||
+ if [ "$result" != "$expect" ] ; then
|
||||
+ echo "failed string: $arg"
|
||||
+ echo "Expected:"
|
||||
+ echo "$expect"
|
||||
+ echo "Result:"
|
||||
+ echo "$result"
|
||||
+ errornumber=$(( errornumber + 1 ))
|
||||
+ fi
|
||||
+}
|
||||
+# }}}
|
||||
+
|
||||
+#
|
||||
+# Program {{{
|
||||
+#
|
||||
+
|
||||
+# number of tested characters for random tests
|
||||
+NTEST=100
|
||||
+
|
||||
+URLDECODE=$1
|
||||
+HEXDUMP="od -Ax -tx1"
|
||||
+
|
||||
+if [ -z "$URLDECODE" ] ; then
|
||||
+ echo "Usage: $0 urldecode"
|
||||
+ exit 1
|
||||
+fi
|
||||
+
|
||||
+errornumber=0
|
||||
+
|
||||
+# TEST #1: Random uppercase %-sequences
|
||||
+
|
||||
+ARG=
|
||||
+EXPECT=
|
||||
+i=0
|
||||
+while [ $i -lt $NTEST ]
|
||||
+do
|
||||
+ ch=$(( $RANDOM % 256 ))
|
||||
+ hex=$( printf "%02X" $ch )
|
||||
+ ARG="$ARG%$hex"
|
||||
+ EXPECT="$EXPECT\\x$hex"
|
||||
+ i=$(( i + 1 ))
|
||||
+done
|
||||
+EXPECT=$( echo -e "$EXPECT" | $HEXDUMP )
|
||||
+RESULT=$( "$URLDECODE" "$ARG" | $HEXDUMP )
|
||||
+check "$ARG" "$EXPECT" "$RESULT"
|
||||
+
|
||||
+# TEST #2: Random lowercase %-sequences
|
||||
+
|
||||
+ARG=
|
||||
+EXPECT=
|
||||
+i=0
|
||||
+while [ $i -lt $NTEST ]
|
||||
+do
|
||||
+ ch=$(( $RANDOM % 256 ))
|
||||
+ hex=$( printf "%02x" $ch )
|
||||
+ ARG="$ARG%$hex"
|
||||
+ EXPECT="$EXPECT\\x$hex"
|
||||
+ i=$(( i + 1 ))
|
||||
+done
|
||||
+EXPECT=$( echo -e "$EXPECT" | $HEXDUMP )
|
||||
+RESULT=$( "$URLDECODE" "$ARG" | $HEXDUMP )
|
||||
+check "$ARG" "$EXPECT" "$RESULT"
|
||||
+
|
||||
+# TEST #3: Decoding '+'
|
||||
+
|
||||
+ARG=" + +begin hello+world end+"
|
||||
+EXPECT="+ +begin hello+world end+"
|
||||
+RESULT=$( "$URLDECODE" $ARG )
|
||||
+check "$ARG" "$EXPECT" "$RESULT"
|
||||
+
|
||||
+# now using form decoding
|
||||
+EXPECT=" begin hello world end "
|
||||
+RESULT=$( "$URLDECODE" -f $ARG )
|
||||
+check "$ARG" "$EXPECT" "$RESULT"
|
||||
+
|
||||
+# TEST #4: Transitions quoted <-> unquoted
|
||||
+
|
||||
+ARG=
|
||||
+EXPECT=
|
||||
+i=0
|
||||
+while [ $i -lt $NTEST ]
|
||||
+do
|
||||
+ ch=$(( $RANDOM % 256 ))
|
||||
+ hex=$( printf "%02x" $ch )
|
||||
+ case $(( $ch % 3 )) in
|
||||
+ 0)
|
||||
+ ARG="$ARG $hex%$hex"
|
||||
+ EXPECT="$EXPECT $hex\\x$hex"
|
||||
+ ;;
|
||||
+
|
||||
+ 1)
|
||||
+ ARG="$ARG %$hex$hex"
|
||||
+ EXPECT="$EXPECT \\x$hex$hex"
|
||||
+ ;;
|
||||
+
|
||||
+ 2)
|
||||
+ ARG="$ARG $hex%$hex$hex"
|
||||
+ EXPECT="$EXPECT $hex\\x$hex$hex"
|
||||
+ ;;
|
||||
+
|
||||
+ 3)
|
||||
+ ARG="$ARG +%$hex+$hex"
|
||||
+ EXPECT="$EXPECT \\x$hex $hex"
|
||||
+ ;;
|
||||
+ esac
|
||||
+ i=$(( i + 1 ))
|
||||
+done
|
||||
+EXPECT=$( echo -e "$EXPECT" | $HEXDUMP )
|
||||
+RESULT=$( "$URLDECODE" "$ARG" | $HEXDUMP )
|
||||
+check "$ARG" "$EXPECT" "$RESULT"
|
||||
+
|
||||
+# TEST #5: Test invalid sequence
|
||||
+
|
||||
+ARG=" %invalid %0invalid %ainvalid %x0invalid %+invalid %0+invalid"
|
||||
+EXPECT="%invalid %0invalid %ainvalid %x0invalid % invalid %0 invalid"
|
||||
+RESULT=$( "$URLDECODE" -f $ARG )
|
||||
+check "$ARG" "$EXPECT" "$RESULT"
|
||||
+
|
||||
+# TEST #6: More than two hex digits
|
||||
+
|
||||
+ARG="%4567 %456789abcdef0123"
|
||||
+EXPECT="E67 E6789abcdef0123"
|
||||
+RESULT=$( "$URLDECODE" $ARG )
|
||||
+check "$ARG" "$EXPECT" "$RESULT"
|
||||
+
|
||||
+# TEST #7: NUL character
|
||||
+
|
||||
+ARG="NUL character here: '%00'"
|
||||
+EXPECT=$( echo -e "NUL character here: '\000'" | $HEXDUMP )
|
||||
+RESULT=$( "$URLDECODE" $ARG | $HEXDUMP )
|
||||
+check "$ARG" "$EXPECT" "$RESULT"
|
||||
+
|
||||
+exit $errornumber
|
||||
+
|
||||
+# }}}
|
||||
+
|
||||
+# vim: set sw=4 ts=4 fdm=marker et: :collapseFolds=1:
|
||||
diff --git a/tests/testurlparser.sh b/tests/testurlparser.sh
|
||||
index 9cb9f1b..1d05353 100755
|
||||
--- a/tests/testurlparser.sh
|
||||
+++ b/tests/testurlparser.sh
|
||||
@@ -32,6 +32,7 @@ URLS=( "/var/log/dump"
|
||||
"cifs://bwalle:dontsay@neptunium:/var/log/dump"
|
||||
"smb://bwalle@192.168.0.70:/var/log"
|
||||
"cifs://bwalle:dontsay@neptunium:/var/log/dump"
|
||||
+ "ftp://pt%65sarik:don%27t%20say@fu%6eny+host/var/log/dum%70"
|
||||
)
|
||||
|
||||
# protocol:host:port:user:pass:path
|
||||
@@ -45,6 +46,7 @@ VALUES=( "file::-1:::/var/log/dump"
|
||||
"cifs:neptunium:-1:bwalle:dontsay:/var/log/dump"
|
||||
"cifs:192.168.0.70:-1:bwalle::/var/log"
|
||||
"cifs:neptunium:-1:bwalle:dontsay:/var/log/dump"
|
||||
+ "ftp:funny+host:-1:ptesarik:don't say:/var/log/dump"
|
||||
)
|
||||
# }}}
|
||||
|
@ -1,3 +1,15 @@
|
||||
-------------------------------------------------------------------
|
||||
Tue May 20 11:15:40 UTC 2014 - ptesarik@suse.cz
|
||||
|
||||
- kdump-urldecode.patch: Perform percent decoding on target URL
|
||||
(bnc#869590).
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon May 19 14:18:27 UTC 2014 - ptesarik@suse.cz
|
||||
|
||||
- kdump-fix-udev-rules.patch: Avoid entering failed state on CPU
|
||||
hotplug (bnc#874992, bnc#809209).
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Fri May 16 17:42:37 UTC 2014 - ptesarik@suse.cz
|
||||
|
||||
|
@ -59,6 +59,8 @@ PreReq: %insserv_prereq %fillup_prereq mkinitrd
|
||||
Source: %{name}-%{version}.tar.bz2
|
||||
Source2: %{name}-%{version}-rpmlintrc
|
||||
Source3: kdump.service
|
||||
Patch1: %{name}-fix-udev-rules.patch
|
||||
Patch2: %{name}-urldecode.patch
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
# rename "kdump-helpers" (10.3) -> "kdump" (11.0/SP2)
|
||||
Provides: kdump-helpers = %{version}
|
||||
@ -96,6 +98,9 @@ Authors:
|
||||
|
||||
%prep
|
||||
%setup
|
||||
%patch1 -p1
|
||||
%patch2 -p1
|
||||
chmod +x tests/testurldecode.sh
|
||||
|
||||
%build
|
||||
export CFLAGS="%optflags"
|
||||
|
Loading…
Reference in New Issue
Block a user