import libnvme-1.9-4.el10

cs10 imports/cs10/libnvme-1.9-4.el10
MSVSphere Packaging Team 4 months ago
commit 67559c8ceb
Signed by: sys_gitsync
GPG Key ID: B2B0B9F29E528FE8

1
.gitignore vendored

@ -0,0 +1 @@
SOURCES/libnvme-1.9.tar.gz

@ -0,0 +1 @@
7ce814bb26bd5fc33b99f5ba48d99538f23756cd SOURCES/libnvme-1.9.tar.gz

@ -0,0 +1,39 @@
From 849cea06f88790eca5b0407aa4bf9ed94ac6403e Mon Sep 17 00:00:00 2001
From: Tomas Bzatek <tbzatek@redhat.com>
Date: Thu, 18 Jul 2024 17:23:50 +0200
Subject: [PATCH] linux: Remove the use of OpenSSL Engine API
OpenSSL engines are not FIPS compatible and corresponding API
is deprecated since OpenSSL 3.0. It appears this API is not
actually used in the code, so remove it.
Signed-off-by: Tomas Bzatek <tbzatek@redhat.com>
---
src/nvme/linux.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/src/nvme/linux.c b/src/nvme/linux.c
index 9d472e408b5d..7785416727ed 100644
--- a/src/nvme/linux.c
+++ b/src/nvme/linux.c
@@ -18,7 +18,6 @@
#include <unistd.h>
#ifdef CONFIG_OPENSSL
-#include <openssl/engine.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/kdf.h>
@@ -739,9 +738,6 @@ int nvme_gen_dhchap_key(char *hostnqn, enum nvme_hmac_alg hmac,
_cleanup_hmac_ctx_ HMAC_CTX *hmac_ctx = NULL;
const EVP_MD *md;
- ENGINE_load_builtin_engines();
- ENGINE_register_all_complete();
-
hmac_ctx = HMAC_CTX_new();
if (!hmac_ctx) {
errno = ENOMEM;
--
2.43.0

@ -0,0 +1,40 @@
From 91f7671ca54a200d652b9b9f34915325313511f5 Mon Sep 17 00:00:00 2001
From: Tomas Bzatek <tbzatek@redhat.com>
Date: Fri, 3 May 2024 17:19:39 +0200
Subject: [PATCH] linux: Fix uninitialized variables
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
In file included from ../src/nvme/linux.c:40:
In function freep,
inlined from nvme_get_telemetry_log at ../src/nvme/linux.c:169:23:
../src/nvme/cleanup.h:24:9: warning: log may be used uninitialized [-Wmaybe-uninitialized]
24 | free(*(void **)p);
| ^~~~~~~~~~~~~~~~~
../src/nvme/linux.c: In function nvme_get_telemetry_log:
../src/nvme/linux.c:169:30: note: log was declared here
169 | _cleanup_free_ void *log;
| ^~~
Signed-off-by: Tomas Bzatek <tbzatek@redhat.com>
---
src/nvme/linux.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/nvme/linux.c b/src/nvme/linux.c
index 25196fd5..35976011 100644
--- a/src/nvme/linux.c
+++ b/src/nvme/linux.c
@@ -166,7 +166,7 @@ int nvme_get_telemetry_log(int fd, bool create, bool ctrl, bool rae, size_t max_
struct nvme_telemetry_log *telem;
enum nvme_cmd_get_log_lid lid;
- _cleanup_free_ void *log;
+ _cleanup_free_ void *log = NULL;
void *tmp;
int err;
size_t dalb;
--
2.44.0

@ -0,0 +1,609 @@
From 6829a6903c7a32a7b4dd32597c7f2a811b5a58bb Mon Sep 17 00:00:00 2001
From: Tomas Bzatek <tbzatek@redhat.com>
Date: Wed, 17 Apr 2024 18:04:34 +0200
Subject: [PATCH 1/3] fabrics: Introduce simple URI parser
A very simple URI parser implementing URI syntax described
in the Boot Specification, rev. 1.0.
Signed-off-by: Tomas Bzatek <tbzatek@redhat.com>
---
src/libnvme.map | 2 +
src/nvme/fabrics.c | 116 +++++++++++++++++++++++++++++++++++++++++++++
src/nvme/fabrics.h | 44 +++++++++++++++++
3 files changed, 162 insertions(+)
diff -up libnvme-1.9/src/libnvme.map.bak libnvme-1.9/src/libnvme.map
--- libnvme-1.9/src/libnvme.map.bak 2024-05-03 14:08:20.000000000 +0200
+++ libnvme-1.9/src/libnvme.map 2024-06-21 15:46:53.920532333 +0200
@@ -10,6 +10,8 @@ LIBNVME_1.9 {
nvme_submit_passthru64;
nvme_update_key;
nvme_ctrl_get_cntlid;
+ nvme_parse_uri;
+ nvme_free_uri;
};
LIBNVME_1_8 {
diff --git a/src/nvme/fabrics.c b/src/nvme/fabrics.c
index 6738e9dc..324a7321 100644
--- a/src/nvme/fabrics.c
+++ b/src/nvme/fabrics.c
@@ -1703,3 +1703,119 @@ int nvmf_register_ctrl(nvme_ctrl_t c, enum nvmf_dim_tas tas, __u32 *result)
*/
return nvmf_dim(c, tas, NVMF_TRTYPE_TCP, nvme_get_adrfam(c), "", NULL, result);
}
+
+struct nvme_fabrics_uri *nvme_parse_uri(const char *str)
+{
+ struct nvme_fabrics_uri *uri;
+ _cleanup_free_ char *scheme = NULL;
+ _cleanup_free_ char *authority = NULL;
+ _cleanup_free_ char *path = NULL;
+ const char *host;
+ int i;
+
+ /* As defined in Boot Specification rev. 1.0:
+ *
+ * section 1.5.7: NVMe-oF URI Format
+ * nvme+tcp://192.168.1.1:4420/
+ * nvme+tcp://[FE80::1010]:4420/
+ *
+ * section 3.1.2.5.3: DHCP Root-Path - a hierarchical NVMe-oF URI Format
+ * NVME<+PROTOCOL>://<SERVERNAME/IP>[:TRANSPORT PORT]/<SUBSYS NQN>/<NID>
+ * or
+ * NVME<+PROTOCOL>://<DISCOVERY CONTROLLER ADDRESS>[:DISCOVERY-
+ * -CONTROLLER PORT]/NQN.2014-08.ORG.NVMEXPRESS.DISCOVERY/<NID>
+ */
+
+ /* TODO: unescape? */
+
+ uri = calloc(1, sizeof(struct nvme_fabrics_uri));
+ if (!uri)
+ return NULL;
+
+ if (sscanf(str, "%m[^:/]://%m[^/?#]%ms",
+ &scheme, &authority, &path) < 2) {
+ nvme_free_uri(uri);
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if (sscanf(scheme, "%m[^+]+%ms",
+ &uri->scheme, &uri->protocol) < 1) {
+ nvme_free_uri(uri);
+ errno = EINVAL;
+ return NULL;
+ }
+
+ /* split userinfo */
+ host = strrchr(authority, '@');
+ if (host) {
+ host++;
+ uri->userinfo = strndup(authority, host - authority);
+ } else
+ host = authority;
+
+ /* try matching IPv6 address first */
+ if (sscanf(host, "[%m[^]]]:%d",
+ &uri->host, &uri->port) < 1)
+ /* treat it as IPv4/hostname */
+ if (sscanf(host, "%m[^:]:%d",
+ &uri->host, &uri->port) < 1) {
+ nvme_free_uri(uri);
+ errno = EINVAL;
+ return NULL;
+ }
+
+ /* split path into elements */
+ if (path) {
+ char *e, *elem;
+
+ /* separate the fragment */
+ e = strrchr(path, '#');
+ if (e) {
+ uri->fragment = strdup(e + 1);
+ *e = '\0';
+ }
+ /* separate the query string */
+ e = strrchr(path, '?');
+ if (e) {
+ uri->query = strdup(e + 1);
+ *e = '\0';
+ }
+
+ /* count elements first */
+ for (i = 0, e = path; *e; e++)
+ if (*e == '/' && *(e + 1) != '/')
+ i++;
+ uri->path_segments = calloc(i + 2, sizeof(char *));
+
+ i = 0;
+ elem = strtok_r(path, "/", &e);
+ if (elem)
+ uri->path_segments[i++] = strdup(elem);
+ while (elem && strlen(elem)) {
+ elem = strtok_r(NULL, "/", &e);
+ if (elem)
+ uri->path_segments[i++] = strdup(elem);
+ }
+ }
+
+ return uri;
+}
+
+void nvme_free_uri(struct nvme_fabrics_uri *uri)
+{
+ char **s;
+
+ if (!uri)
+ return;
+ free(uri->scheme);
+ free(uri->protocol);
+ free(uri->userinfo);
+ free(uri->host);
+ for (s = uri->path_segments; s && *s; s++)
+ free(*s);
+ free(uri->path_segments);
+ free(uri->query);
+ free(uri->fragment);
+ free(uri);
+}
diff --git a/src/nvme/fabrics.h b/src/nvme/fabrics.h
index 4ebeb35e..3be35310 100644
--- a/src/nvme/fabrics.h
+++ b/src/nvme/fabrics.h
@@ -67,6 +67,28 @@ struct nvme_fabrics_config {
bool concat;
};
+/**
+ * struct nvme_fabrics_uri - Parsed URI structure
+ * @scheme: Scheme name (typically 'nvme')
+ * @protocol: Optional protocol/transport (e.g. 'tcp')
+ * @userinfo: Optional user information component of the URI authority
+ * @host: Host transport address
+ * @port: The port subcomponent or 0 if not specified
+ * @path_segments: NULL-terminated array of path segments
+ * @query: Optional query string component (separated by '?')
+ * @fragment: Optional fragment identifier component (separated by '#')
+ */
+struct nvme_fabrics_uri {
+ char *scheme;
+ char *protocol;
+ char *userinfo;
+ char *host;
+ int port;
+ char **path_segments;
+ char *query;
+ char *fragment;
+};
+
/**
* nvmf_trtype_str() - Decode TRTYPE field
* @trtype: value to be decoded
@@ -324,4 +346,26 @@ bool nvmf_is_registration_supported(nvme_ctrl_t c);
*/
int nvmf_register_ctrl(nvme_ctrl_t c, enum nvmf_dim_tas tas, __u32 *result);
+/**
+ * nvme_parse_uri() - Parse the URI string
+ * @str: URI string
+ *
+ * Parse the URI string as defined in the NVM Express Boot Specification.
+ * Supported URI elements looks as follows:
+ *
+ * nvme+tcp://user@host:port/subsys_nqn/nid?query=val#fragment
+ *
+ * Return: &nvme_fabrics_uri structure on success; NULL on failure with errno
+ * set.
+ */
+struct nvme_fabrics_uri *nvme_parse_uri(const char *str);
+
+/**
+ * nvme_free_uri() - Free the URI structure
+ * @uri: &nvme_fabrics_uri structure
+ *
+ * Free an &nvme_fabrics_uri structure.
+ */
+void nvme_free_uri(struct nvme_fabrics_uri *uri);
+
#endif /* _LIBNVME_FABRICS_H */
From 27ea060ef42c76ed1c88d92c435b88b481e7defb Mon Sep 17 00:00:00 2001
From: Tomas Bzatek <tbzatek@redhat.com>
Date: Wed, 17 Apr 2024 18:06:23 +0200
Subject: [PATCH 2/3] tests: Add uriparser tests
Simple testcase both for valid and malformed URI strings.
Signed-off-by: Tomas Bzatek <tbzatek@redhat.com>
---
test/meson.build | 9 ++
test/uriparser.c | 208 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 217 insertions(+)
create mode 100644 test/uriparser.c
diff --git a/test/meson.build b/test/meson.build
index 93e69991..55992df7 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -66,6 +66,15 @@ uuid = executable(
test('uuid', uuid)
+uriparser = executable(
+ 'test-uriparser',
+ ['uriparser.c'],
+ dependencies: libnvme_dep,
+ include_directories: [incdir, internal_incdir]
+)
+
+test('uriparser', uriparser)
+
if conf.get('HAVE_NETDB')
mock_ifaddrs = library(
'mock-ifaddrs',
diff --git a/test/uriparser.c b/test/uriparser.c
new file mode 100644
index 00000000..cf26bfd2
--- /dev/null
+++ b/test/uriparser.c
@@ -0,0 +1,208 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/**
+ * This file is part of libnvme.
+ * Copyright (c) 2024 Tomas Bzatek <tbzatek@redhat.com>
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <ccan/array_size/array_size.h>
+
+#include <libnvme.h>
+#include <nvme/private.h>
+
+struct test_data {
+ const char *uri;
+ /* parsed data */
+ const char *scheme;
+ const char *host;
+ const char *user;
+ const char *proto;
+ int port;
+ const char *path[7];
+ const char *query;
+ const char *frag;
+};
+
+static struct test_data test_data[] = {
+ { "nvme://192.168.1.1", "nvme", "192.168.1.1" },
+ { "nvme://192.168.1.1/", "nvme", "192.168.1.1" },
+ { "nvme://192.168.1.1:1234", "nvme", "192.168.1.1", .port = 1234 },
+ { "nvme://192.168.1.1:1234/", "nvme", "192.168.1.1", .port = 1234 },
+ { "nvme+tcp://192.168.1.1", "nvme", "192.168.1.1", .proto = "tcp" },
+ { "nvme+rdma://192.168.1.1/", "nvme", "192.168.1.1", .proto = "rdma" },
+ { "nvme+tcp://192.168.1.1:1234",
+ "nvme", "192.168.1.1", .proto = "tcp", .port = 1234 },
+ { "nvme+tcp://192.168.1.1:1234/",
+ "nvme", "192.168.1.1", .proto = "tcp", .port = 1234 },
+ { "nvme+tcp://192.168.1.1:4420/path",
+ "nvme", "192.168.1.1", .proto = "tcp", .port = 4420,
+ .path = { "path", NULL }},
+ { "nvme+tcp://192.168.1.1/path/",
+ "nvme", "192.168.1.1", .proto = "tcp", .path = { "path", NULL }},
+ { "nvme+tcp://192.168.1.1:4420/p1/p2/p3",
+ "nvme", "192.168.1.1", .proto = "tcp", .port = 4420,
+ .path = { "p1", "p2", "p3", NULL }},
+ { "nvme+tcp://192.168.1.1:4420/p1/p2/p3/",
+ "nvme", "192.168.1.1", .proto = "tcp", .port = 4420,
+ .path = { "p1", "p2", "p3", NULL }},
+ { "nvme+tcp://192.168.1.1:4420//p1//p2/////p3",
+ "nvme", "192.168.1.1", .proto = "tcp", .port = 4420,
+ .path = { "p1", "p2", "p3", NULL }},
+ { "nvme+tcp://192.168.1.1:4420//p1//p2/////p3/",
+ "nvme", "192.168.1.1", .proto = "tcp", .port = 4420,
+ .path = { "p1", "p2", "p3", NULL }},
+ { "nvme://[fe80::1010]", "nvme", "fe80::1010" },
+ { "nvme://[fe80::1010]/", "nvme", "fe80::1010" },
+ { "nvme://[fe80::1010]:1234", "nvme", "fe80::1010", .port = 1234 },
+ { "nvme://[fe80::1010]:1234/", "nvme", "fe80::1010", .port = 1234 },
+ { "nvme+tcp://[fe80::1010]", "nvme", "fe80::1010", .proto = "tcp" },
+ { "nvme+rdma://[fe80::1010]/", "nvme", "fe80::1010", .proto = "rdma" },
+ { "nvme+tcp://[fe80::1010]:1234",
+ "nvme", "fe80::1010", .proto = "tcp", .port = 1234 },
+ { "nvme+tcp://[fe80::1010]:1234/",
+ "nvme", "fe80::1010", .proto = "tcp", .port = 1234 },
+ { "nvme+tcp://[fe80::1010]:4420/path",
+ "nvme", "fe80::1010", .proto = "tcp", .port = 4420,
+ .path = { "path", NULL }},
+ { "nvme+tcp://[fe80::1010]/path/",
+ "nvme", "fe80::1010", .proto = "tcp", .path = { "path", NULL }},
+ { "nvme+tcp://[fe80::1010]:4420/p1/p2/p3",
+ "nvme", "fe80::1010", .proto = "tcp", .port = 4420,
+ .path = { "p1", "p2", "p3", NULL }},
+ { "nvme+tcp://[fe80::fc7d:8cff:fe5b:962e]:666/p1/p2/p3/",
+ "nvme", "fe80::fc7d:8cff:fe5b:962e", .proto = "tcp", .port = 666,
+ .path = { "p1", "p2", "p3", NULL }},
+ { "nvme://h?query", "nvme", "h", .query = "query" },
+ { "nvme://h/?query", "nvme", "h", .query = "query" },
+ { "nvme://h/x?query",
+ "nvme", "h", .path = { "x" }, .query = "query" },
+ { "nvme://h/p1/?query",
+ "nvme", "h", .path = { "p1" }, .query = "query" },
+ { "nvme://h/p1/x?query",
+ "nvme", "h", .path = { "p1", "x" }, .query = "query" },
+ { "nvme://h#fragment", "nvme", "h", .frag = "fragment" },
+ { "nvme://h/#fragment", "nvme", "h", .frag = "fragment" },
+ { "nvme://h/x#fragment",
+ "nvme", "h", .path = { "x" }, .frag = "fragment" },
+ { "nvme://h/p1/#fragment",
+ "nvme", "h", .path = { "p1" }, .frag = "fragment" },
+ { "nvme://h/p1/x#fragment",
+ "nvme", "h", .path = { "p1", "x" }, .frag = "fragment" },
+ { "nvme://h/?query#fragment",
+ "nvme", "h", .query = "query", .frag = "fragment" },
+ { "nvme://h/x?query#fragment",
+ "nvme", "h", .path = { "x" }, .query = "query", .frag = "fragment" },
+ { "nvme://h/p1/?query#fragment",
+ "nvme", "h", .path = { "p1" }, .query = "query", .frag = "fragment" },
+ { "nvme://h/p1/x?query#fragment",
+ "nvme", "h", .path = { "p1", "x" }, .query = "query",
+ .frag = "fragment" },
+ { "nvme://h/#fragment?query",
+ "nvme", "h", .frag = "fragment?query" },
+ { "nvme://h/x#fragment?query",
+ "nvme", "h", .path = { "x" }, .frag = "fragment?query" },
+ { "nvme://h/p1/#fragment?query",
+ "nvme", "h", .path = { "p1" }, .frag = "fragment?query" },
+ { "nvme://h/p1/x#fragment?query",
+ "nvme", "h", .path = { "p1", "x" }, .frag = "fragment?query" },
+ { "nvme://user@h", "nvme", "h", .user = "user" },
+ { "nvme://user@h/", "nvme", "h", .user = "user" },
+ { "nvme://user:pass@h/", "nvme", "h", .user = "user:pass" },
+ { "nvme://[fe80::1010]@h/", "nvme", "h", .user = "[fe80::1010]" },
+ { "nvme://u[fe80::1010]@h/", "nvme", "h", .user = "u[fe80::1010]" },
+ { "nvme://u[aa:bb::cc]@h/", "nvme", "h", .user = "u[aa:bb::cc]" },
+ { "nvme+rdma://u[aa:bb::cc]@[aa:bb::cc]:12345/p1/x?q=val#fr",
+ "nvme", "aa:bb::cc", .proto = "rdma", .port = 12345,
+ .user = "u[aa:bb::cc]", .path = { "p1", "x" },
+ .query = "q=val", .frag = "fr" },
+};
+
+const char *test_data_bad[] = {
+ "",
+ " ",
+ "nonsense",
+ "vnme:",
+ "vnme:/",
+ "vnme://",
+ "vnme:///",
+ "vnme+foo://",
+ "nvme:hostname/",
+ "nvme:/hostname/",
+ "nvme:///hostname/",
+ "nvme+foo:///hostname/",
+};
+
+static void test_uriparser(void)
+{
+ printf("Testing URI parser:\n");
+ for (int i = 0; i < ARRAY_SIZE(test_data); i++) {
+ const struct test_data *d = &test_data[i];
+ struct nvme_fabrics_uri *parsed_data;
+ char **s;
+ int i;
+
+ printf(" '%s'...", d->uri);
+ parsed_data = nvme_parse_uri(d->uri);
+ assert(parsed_data);
+
+ assert(strcmp(d->scheme, parsed_data->scheme) == 0);
+ if (d->proto) {
+ assert(parsed_data->protocol != NULL);
+ assert(strcmp(d->proto, parsed_data->protocol) == 0);
+ } else
+ assert(d->proto == parsed_data->protocol);
+ assert(strcmp(d->host, parsed_data->host) == 0);
+ assert(d->port == parsed_data->port);
+
+ if (!parsed_data->path_segments)
+ assert(d->path[0] == NULL);
+ else {
+ for (i = 0, s = parsed_data->path_segments;
+ s && *s; s++, i++) {
+ assert(d->path[i] != NULL);
+ assert(strcmp(d->path[i], *s) == 0);
+ }
+ /* trailing NULL element */
+ assert(d->path[i] == parsed_data->path_segments[i]);
+ }
+ if (d->query) {
+ assert(parsed_data->query != NULL);
+ assert(strcmp(d->query, parsed_data->query) == 0);
+ } else
+ assert(d->query == parsed_data->query);
+ if (d->frag) {
+ assert(parsed_data->fragment != NULL);
+ assert(strcmp(d->frag, parsed_data->fragment) == 0);
+ } else
+ assert(d->frag == parsed_data->fragment);
+ nvme_free_uri(parsed_data);
+ printf(" OK\n");
+ }
+}
+
+static void test_uriparser_bad(void)
+{
+ printf("Testing malformed URI strings:\n");
+ for (int i = 0; i < ARRAY_SIZE(test_data_bad); i++) {
+ struct nvme_fabrics_uri *parsed_data;
+
+ printf(" '%s'...", test_data_bad[i]);
+ parsed_data = nvme_parse_uri(test_data_bad[i]);
+ assert(parsed_data == NULL);
+ printf(" OK\n");
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ test_uriparser();
+ test_uriparser_bad();
+
+ fflush(stdout);
+
+ return 0;
+}
From b2044e8f416b54df34e0d162b59ca0745db92927 Mon Sep 17 00:00:00 2001
From: Tomas Bzatek <tbzatek@redhat.com>
Date: Mon, 13 May 2024 17:38:25 +0200
Subject: [PATCH 3/3] fabrics: Unescape URI elements
This adds support for unescaping percent-encoded URI parts.
Signed-off-by: Tomas Bzatek <tbzatek@redhat.com>
---
src/nvme/fabrics.c | 47 +++++++++++++++++++++++++++++++++++++---------
test/uriparser.c | 13 +++++++++++++
2 files changed, 51 insertions(+), 9 deletions(-)
diff --git a/src/nvme/fabrics.c b/src/nvme/fabrics.c
index 324a7321..e5921f8b 100644
--- a/src/nvme/fabrics.c
+++ b/src/nvme/fabrics.c
@@ -1704,12 +1704,41 @@ int nvmf_register_ctrl(nvme_ctrl_t c, enum nvmf_dim_tas tas, __u32 *result)
return nvmf_dim(c, tas, NVMF_TRTYPE_TCP, nvme_get_adrfam(c), "", NULL, result);
}
+#define IS_XDIGIT(c) ((c >= '0' && c <= '9') || \
+ (c >= 'A' && c <= 'F') || \
+ (c >= 'a' && c <= 'f'))
+#define XDIGIT_VAL(c) ((c >= '0' && c <= '9') ? c - '0' : ( \
+ (c >= 'A' && c <= 'F') ? c - 'A' + 10 : c - 'a' + 10))
+
+/* returns newly allocated string */
+static char *unescape_uri(const char *str, int len)
+{
+ char *dst;
+ int l;
+ int i, j;
+
+ l = len > 0 ? len : strlen(str);
+ dst = malloc(l + 1);
+ for (i = 0, j = 0; i < l; i++, j++) {
+ if (str[i] == '%' && i + 2 < l &&
+ IS_XDIGIT(str[i + 1]) && IS_XDIGIT(str[i + 2])) {
+ dst[j] = (XDIGIT_VAL(str[i + 1]) << 4) +
+ XDIGIT_VAL(str[i + 2]);
+ i += 2;
+ } else
+ dst[j] = str[i];
+ }
+ dst[j] = '\0';
+ return dst;
+}
+
struct nvme_fabrics_uri *nvme_parse_uri(const char *str)
{
struct nvme_fabrics_uri *uri;
_cleanup_free_ char *scheme = NULL;
_cleanup_free_ char *authority = NULL;
_cleanup_free_ char *path = NULL;
+ _cleanup_free_ char *h = NULL;
const char *host;
int i;
@@ -1726,8 +1755,6 @@ struct nvme_fabrics_uri *nvme_parse_uri(const char *str)
* -CONTROLLER PORT]/NQN.2014-08.ORG.NVMEXPRESS.DISCOVERY/<NID>
*/
- /* TODO: unescape? */
-
uri = calloc(1, sizeof(struct nvme_fabrics_uri));
if (!uri)
return NULL;
@@ -1750,20 +1777,22 @@ struct nvme_fabrics_uri *nvme_parse_uri(const char *str)
host = strrchr(authority, '@');
if (host) {
host++;
- uri->userinfo = strndup(authority, host - authority);
+ uri->userinfo = unescape_uri(authority, host - authority);
} else
host = authority;
/* try matching IPv6 address first */
if (sscanf(host, "[%m[^]]]:%d",
- &uri->host, &uri->port) < 1)
+ &uri->host, &uri->port) < 1) {
/* treat it as IPv4/hostname */
if (sscanf(host, "%m[^:]:%d",
- &uri->host, &uri->port) < 1) {
+ &h, &uri->port) < 1) {
nvme_free_uri(uri);
errno = EINVAL;
return NULL;
}
+ uri->host = unescape_uri(h, 0);
+ }
/* split path into elements */
if (path) {
@@ -1772,13 +1801,13 @@ struct nvme_fabrics_uri *nvme_parse_uri(const char *str)
/* separate the fragment */
e = strrchr(path, '#');
if (e) {
- uri->fragment = strdup(e + 1);
+ uri->fragment = unescape_uri(e + 1, 0);
*e = '\0';
}
/* separate the query string */
e = strrchr(path, '?');
if (e) {
- uri->query = strdup(e + 1);
+ uri->query = unescape_uri(e + 1, 0);
*e = '\0';
}
@@ -1791,11 +1820,11 @@ struct nvme_fabrics_uri *nvme_parse_uri(const char *str)
i = 0;
elem = strtok_r(path, "/", &e);
if (elem)
- uri->path_segments[i++] = strdup(elem);
+ uri->path_segments[i++] = unescape_uri(elem, 0);
while (elem && strlen(elem)) {
elem = strtok_r(NULL, "/", &e);
if (elem)
- uri->path_segments[i++] = strdup(elem);
+ uri->path_segments[i++] = unescape_uri(elem, 0);
}
}
diff --git a/test/uriparser.c b/test/uriparser.c
index cf26bfd2..09b2a732 100644
--- a/test/uriparser.c
+++ b/test/uriparser.c
@@ -119,6 +119,19 @@ static struct test_data test_data[] = {
"nvme", "aa:bb::cc", .proto = "rdma", .port = 12345,
.user = "u[aa:bb::cc]", .path = { "p1", "x" },
.query = "q=val", .frag = "fr" },
+ { "nvme://ex%5Cmp%3Ae", "nvme", "ex\\mp:e" },
+ { "nvme://ex%5Cmp%3Ae.com/", "nvme", "ex\\mp:e.com" },
+ { "nvme://u%24er@ex%5Cmp%3Ae.com/", "nvme", "ex\\mp:e.com",
+ .user = "u$er" },
+ { "nvme+tcp://ex%5Cmp%3Ae.com:1234",
+ "nvme", "ex\\mp:e.com", .proto = "tcp", .port = 1234 },
+ { "nvme+tcp://ex%5Cmp%3Ae.com:1234/p1/ex%3Camp%3Ele/p3",
+ "nvme", "ex\\mp:e.com", .proto = "tcp", .port = 1234,
+ .path = { "p1", "ex<amp>le", "p3", NULL } },
+ { "nvme+tcp://ex%5Cmp%3Ae.com:1234/p1/%3C%3E/p3?q%5E%24ry#fr%26gm%23nt",
+ "nvme", "ex\\mp:e.com", .proto = "tcp", .port = 1234,
+ .path = { "p1", "<>", "p3", NULL }, .query = "q^$ry",
+ .frag = "fr&gm#nt" },
};
const char *test_data_bad[] = {

@ -0,0 +1,214 @@
# RHEL 8 compatibility
%{!?version_no_tilde: %define version_no_tilde %{shrink:%(echo '%{version}' | tr '~' '-')}}
Name: libnvme
Summary: Linux-native nvme device management library
Version: 1.9
Release: 4%{?dist}
License: LGPL-2.1-or-later
URL: https://github.com/linux-nvme/libnvme
Source0: %{url}/archive/v%{version_no_tilde}/%{name}-%{version_no_tilde}.tar.gz
# https://github.com/linux-nvme/libnvme/pull/833
Patch0: libnvme-1.10-linux-Fix-uninitialized-variables.patch
Patch1: 0002-linux-Remove-the-use-of-OpenSSL-Engine-API.patch
Patch2: libnvme-1.10-uriparser.patch
BuildRequires: gcc gcc-c++
BuildRequires: swig
BuildRequires: python3-devel
BuildRequires: meson >= 0.50
BuildRequires: json-c-devel >= 0.13
BuildRequires: openssl-devel
BuildRequires: dbus-devel
BuildRequires: keyutils-libs-devel
%if 0%{?fedora} || 0%{?rhel} > 9
BuildRequires: kernel-headers >= 5.15
%endif
%description
Provides type definitions for NVMe specification structures,
enumerations, and bit fields, helper functions to construct,
dispatch, and decode commands and payloads, and utilities to connect,
scan, and manage nvme devices on a Linux system.
%package devel
Summary: Development files for %{name}
Requires: %{name}%{?_isa} = %{version}-%{release}
%description devel
This package provides header files to include and libraries to link with
for Linux-native nvme device management.
%package doc
Summary: Reference manual for libnvme
BuildArch: noarch
BuildRequires: perl-interpreter
BuildRequires: python3-sphinx
BuildRequires: python3-sphinx_rtd_theme
%description doc
This package contains the reference manual for %{name}.
%package -n python3-libnvme
Summary: Python3 bindings for libnvme
Requires: %{name}%{?_isa} = %{version}-%{release}
Provides: python3-nvme = %{version}-%{release}
Obsoletes: python3-nvme < 1.0~rc7
%{?python_provide:%python_provide python3-libnvme}
%description -n python3-libnvme
This package contains Python bindings for libnvme.
%prep
%autosetup -p1 -n %{name}-%{version_no_tilde}
%build
%meson -Dpython=enabled -Dlibdbus=enabled -Ddocs=all -Ddocs-build=true -Dhtmldir=%{_pkgdocdir}
%meson_build
%install
%meson_install
%{__install} -pm 644 README.md %{buildroot}%{_pkgdocdir}
%{__install} -pm 644 doc/config-schema.json %{buildroot}%{_pkgdocdir}
mv %{buildroot}%{_pkgdocdir}/nvme/html %{buildroot}%{_pkgdocdir}/html
rm -rf %{buildroot}%{_pkgdocdir}/nvme
mv %{buildroot}/usr/*.rst %{buildroot}%{_pkgdocdir}/
rm -r %{buildroot}%{_pkgdocdir}/html/{.buildinfo,.doctrees/}
%ldconfig_scriptlets
%files
%license COPYING ccan/licenses/*
%{_libdir}/libnvme.so.1
%{_libdir}/libnvme.so.1.9.0
%{_libdir}/libnvme-mi.so.1
%{_libdir}/libnvme-mi.so.1.9.0
%files devel
%{_libdir}/libnvme.so
%{_libdir}/libnvme-mi.so
%{_includedir}/libnvme.h
%{_includedir}/libnvme-mi.h
%dir %{_includedir}/nvme
%{_includedir}/nvme/*.h
%{_libdir}/pkgconfig/*.pc
%files doc
%doc %{_pkgdocdir}
%{_mandir}/man2/*.2*
%files -n python3-libnvme
%dir %{python3_sitearch}/libnvme
%{python3_sitearch}/libnvme/*
%changelog
* Fri Jul 26 2024 Maurizio Lombardi <mlombard@redhat.com> - 1.9-4
- Fix RHEL-37611
* Thu Jul 25 2024 Maurizio Lombardi <mlombard@redhat.com> - 1.9-3
- Fix RHEL-46699
* Mon Jun 24 2024 Troy Dawson <tdawson@redhat.com> - 1.9-2
- Bump release for June 2024 mass rebuild
* Fri May 03 2024 Tomas Bzatek <tbzatek@redhat.com> - 1.9-1
- Upstream v1.9 release
* Wed Feb 28 2024 Davide Cavalca <dcavalca@fedoraproject.org> - 1.8-2
- Do not package doctrees to make the package build reproducible
* Wed Feb 14 2024 Tomas Bzatek <tbzatek@redhat.com> - 1.8-1
- Upstream v1.8 release
* Fri Feb 09 2024 Tomas Bzatek <tbzatek@redhat.com> - 1.7.1-4
- nbft: Fix SSNS HFI indexes parsing
- cleanup: Explicitly initialize auto-cleanup variables
* Thu Jan 25 2024 Fedora Release Engineering <releng@fedoraproject.org> - 1.7.1-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
* Sun Jan 21 2024 Fedora Release Engineering <releng@fedoraproject.org> - 1.7.1-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
* Thu Dec 28 2023 Tomas Bzatek <tbzatek@redhat.com> - 1.7.1-1
- Upstream v1.7.1 release
* Tue Oct 24 2023 Tomas Bzatek <tbzatek@redhat.com> - 1.6-2
- Backport stack smashing fixes (#2245707)
* Fri Sep 29 2023 Tomas Bzatek <tbzatek@redhat.com> - 1.6-1
- Upstream v1.6 release
* Thu Jul 20 2023 Fedora Release Engineering <releng@fedoraproject.org> - 1.5-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
* Tue Jul 04 2023 Python Maint <python-maint@redhat.com> - 1.5-2
- Rebuilt for Python 3.12
* Tue Jul 04 2023 Tomas Bzatek <tbzatek@redhat.com> - 1.5-1
- Upstream v1.5 release
* Thu Jun 15 2023 Python Maint <python-maint@redhat.com> - 1.4-3
- Rebuilt for Python 3.12
* Thu Apr 20 2023 Tomas Bzatek <tbzatek@redhat.com> - 1.4-2
- Backport the NBFT parser from git master
* Mon Apr 03 2023 Tomas Bzatek <tbzatek@redhat.com> - 1.4-1
- Upstream v1.4 release
* Tue Jan 31 2023 Tomas Bzatek <tbzatek@redhat.com> - 1.3-1
- Upstream v1.3 release
* Thu Jan 19 2023 Fedora Release Engineering <releng@fedoraproject.org> - 1.2-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild
* Tue Nov 01 2022 Tomas Bzatek <tbzatek@redhat.com> - 1.2-1
- Upstream v1.2 release
* Fri Aug 05 2022 Tomas Bzatek <tbzatek@redhat.com> - 1.1-1
- Upstream v1.1 release
* Thu Jul 21 2022 Fedora Release Engineering <releng@fedoraproject.org> - 1.1~rc0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
* Fri Jul 15 2022 Tomas Bzatek <tbzatek@redhat.com> - 1.1~rc0-1
- Upstream v1.1 Release Candidate 0
* Mon Jun 13 2022 Python Maint <python-maint@redhat.com> - 1.0-2
- Rebuilt for Python 3.11
* Mon Apr 11 2022 Tomas Bzatek <tbzatek@redhat.com> - 1.0-1
- Upstream v1.0 release
* Fri Apr 01 2022 Tomas Bzatek <tbzatek@redhat.com> - 1.0~rc8-1
- Upstream v1.0 Release Candidate 8
* Wed Mar 23 2022 Tomas Bzatek <tbzatek@redhat.com> - 1.0~rc7-1
- Upstream v1.0 Release Candidate 7
- Renamed python3-nvme subpackage to python3-libnvme
* Mon Mar 14 2022 Tomas Bzatek <tbzatek@redhat.com> - 1.0~rc6-1
- Upstream v1.0 Release Candidate 6
* Fri Mar 04 2022 Tomas Bzatek <tbzatek@redhat.com> - 1.0~rc5-1
- Upstream v1.0 Release Candidate 5
* Mon Feb 28 2022 Tomas Bzatek <tbzatek@redhat.com> - 1.0~rc4-1
- Upstream v1.0 Release Candidate 4
* Fri Feb 11 2022 Tomas Bzatek <tbzatek@redhat.com> - 1.0~rc3-1
- Upstream v1.0 Release Candidate 3
* Tue Feb 01 2022 Tomas Bzatek <tbzatek@redhat.com> - 1.0~rc2-1
- Upstream v1.0 Release Candidate 2
* Thu Jan 27 2022 Tomas Bzatek <tbzatek@redhat.com> - 1.0~rc1-1
- Upstream v1.0 Release Candidate 1
* Mon Jan 17 2022 Tomas Bzatek <tbzatek@redhat.com> - 1.0~rc0-1
- Upstream v1.0 Release Candidate 0
* Wed Oct 20 2021 Tomas Bzatek <tbzatek@redhat.com> - 0.0.1-1.git1fe38d6
- Initial packaging
Loading…
Cancel
Save