conf.set('SYSCONFDIR', '"@0@"'.format(sysconfdir))
-# Check for libuuid availability
-libuuid_dep = dependency('uuid', required: true, fallback : ['uuid', 'uuid_dep'])
-conf.set('CONFIG_LIBUUID', libuuid_dep.found(), description: 'Is libuuid required?')
-
# Check for json-c availability
json_c_dep = dependency('json-c',
version: '>=0.13',
nvmf_get_discovery_wargs;
nvme_get_feature_length2;
nvme_ctrl_is_persistent;
+ nvme_uuid_from_string;
+ nvme_uuid_to_string;
+ nvme_uuid_random;
};
LIBNVME_1_1 {
endif
deps = [
- libuuid_dep,
json_c_dep,
openssl_dep,
]
mi_deps = [
- libuuid_dep,
libsystemd_dep,
]
libnvme_dep = declare_dependency(
include_directories: ['.'],
dependencies: [
- libuuid_dep.partial_dependency(compile_args: true, includes: true),
json_c_dep.partial_dependency(compile_args: true, includes: true),
],
link_with: libnvme,
libnvme_mi_dep = declare_dependency(
include_directories: ['.'],
- dependencies: [
- libuuid_dep.partial_dependency(compile_args: true, includes: true),
- ],
link_with: libnvme_mi,
)
libnvme_mi_test_dep = declare_dependency(
include_directories: ['.'],
- dependencies: [
- libuuid_dep.partial_dependency(compile_args: true, includes: true),
- ],
link_with: libnvme_mi_test,
)
#include "private.h"
#define NVMF_HOSTID_SIZE 37
-#define UUID_SIZE 37 /* 1b4e28ba-2fa1-11d2-883f-0016d3cca427 + \0 */
#define NVMF_HOSTNQN_FILE SYSCONFDIR "/nvme/hostnqn"
#define NVMF_HOSTID_FILE SYSCONFDIR "/nvme/hostid"
if (f < 0)
return -ENXIO;
- memset(system_uuid, 0, UUID_SIZE);
- len = read(f, system_uuid, UUID_SIZE - 1);
+ memset(system_uuid, 0, NVME_UUID_LEN_STRING);
+ len = read(f, system_uuid, NVME_UUID_LEN_STRING - 1);
close(f);
if (len < 0)
return -ENXIO;
system_uuid[0] = '\0';
nread = getline(&line, &len, stream);
- if (nread != UUID_SIZE) {
+ if (nread != NVME_UUID_LEN_STRING) {
ret = -ENXIO;
goto out;
}
/* The kernel is handling the byte swapping according DMTF
* SMBIOS 3.0 Section 7.2.1 System UUID */
- memcpy(system_uuid, line, UUID_SIZE - 1);
- system_uuid[UUID_SIZE - 1] = '\0';
+ memcpy(system_uuid, line, NVME_UUID_LEN_STRING - 1);
+ system_uuid[NVME_UUID_LEN_STRING - 1] = '\0';
ret = 0;
{
char *hostnqn;
int ret;
- char uuid_str[UUID_SIZE];
- uuid_t uuid;
+ char uuid_str[NVME_UUID_LEN_STRING];
+ unsigned char uuid[NVME_UUID_LEN];
ret = uuid_from_dmi(uuid_str);
if (ret < 0) {
ret = uuid_from_device_tree(uuid_str);
}
if (ret < 0) {
- uuid_generate_random(uuid);
- uuid_unparse_lower(uuid, uuid_str);
+ if (nvme_uuid_random(uuid) < 0)
+ memset(uuid, 0, NVME_UUID_LEN);
+ nvme_uuid_to_string(uuid, uuid_str);
}
if (asprintf(&hostnqn, "nqn.2014-08.org.nvmexpress:uuid:%s", uuid_str) < 0)
__u16 len;
/* Host ID is mandatory */
- tel += nvmf_exat_size(sizeof(uuid_t));
+ tel += nvmf_exat_size(NVME_UUID_LEN_STRING);
/* Symbolic name is optional */
len = hostsymname ? strlen(hostsymname) : 0;
numexat++;
exat = die->exat;
exat->exattype = cpu_to_le16(NVMF_EXATTYPE_HOSTID);
- exat->exatlen = cpu_to_le16(nvmf_exat_len(sizeof(uuid_t)));
- uuid_parse(h->hostid, exat->exatval);
+ exat->exatlen = cpu_to_le16(nvmf_exat_len(NVME_UUID_LEN));
+ nvme_uuid_from_string(h->hostid, exat->exatval);
/* Extended Attribute for the Symbolic Name (optional) */
symname_len = h->hostsymname ? strlen(h->hostsymname) : 0;
#include "fabrics.h"
#include "mi.h"
-#include <uuid.h>
-
extern const char *nvme_ctrl_sysfs_dir;
extern const char *nvme_subsys_sysfs_dir;
uint8_t eui64[8];
uint8_t nguid[16];
- uuid_t uuid;
+ unsigned char uuid[NVME_UUID_LEN];
enum nvme_csi csi;
};
return n->nguid;
}
-void nvme_ns_get_uuid(nvme_ns_t n, uuid_t out)
+void nvme_ns_get_uuid(nvme_ns_t n, unsigned char out[NVME_UUID_LEN])
{
- uuid_copy(out, n->uuid);
+ memcpy(out, n->uuid, NVME_UUID_LEN);
}
int nvme_ns_identify(nvme_ns_t n, struct nvme_id_ns *ns)
#include <stddef.h>
#include <sys/types.h>
-#include <uuid.h>
#include "ioctl.h"
#include "util.h"
*
* Copies the namespace's uuid into @out
*/
-void nvme_ns_get_uuid(nvme_ns_t n, uuid_t out);
+void nvme_ns_get_uuid(nvme_ns_t n, unsigned char out[NVME_UUID_LEN]);
/**
* nvme_ns_get_sysfs_dir() - sysfs directory of a namespace
#include <string.h>
#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include <sys/param.h>
#include <sys/types.h>
#include <arpa/inet.h>
return "n/a";
}
}
+
+int nvme_uuid_to_string(unsigned char uuid[NVME_UUID_LEN], char *str)
+{
+ int n;
+ n = snprintf(str, NVME_UUID_LEN_STRING,
+ "%02x%02x%02x%02x-%02x%02x-%02x%02x-"
+ "%02x%02x-%02x%02x%02x%02x%02x%02x",
+ uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5],
+ uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11],
+ uuid[12], uuid[13], uuid[14], uuid[15]);
+ return n != NVME_UUID_LEN_STRING - 1 ? -EINVAL : 0;
+}
+
+int nvme_uuid_from_string(const char *str, unsigned char uuid[NVME_UUID_LEN])
+{
+ int n;
+
+ n = sscanf(str,
+ "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-"
+ "%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
+ &uuid[0], &uuid[1], &uuid[2], &uuid[3], &uuid[4], &uuid[5],
+ &uuid[6], &uuid[7], &uuid[8], &uuid[9], &uuid[10], &uuid[11],
+ &uuid[12], &uuid[13], &uuid[14], &uuid[15]);
+ return n != NVME_UUID_LEN ? -EINVAL : 0;
+
+}
+
+int nvme_uuid_random(unsigned char uuid[NVME_UUID_LEN])
+{
+ int f;
+ ssize_t n;
+
+ f = open("/dev/urandom", O_RDONLY);
+ if (f < 0)
+ return -errno;
+ n = read(f, uuid, NVME_UUID_LEN);
+ if (n < 0) {
+ close(f);
+ return -errno;
+ } else if (n != NVME_UUID_LEN) {
+ close(f);
+ return -EIO;
+ }
+
+ /*
+ * See https://www.rfc-editor.org/rfc/rfc4122#section-4.4
+ * Algorithms for Creating a UUID from Truly Random
+ * or Pseudo-Random Numbers
+ */
+ uuid[6] = (uuid[6] & 0x0f) | 0x40;
+ uuid[8] = (uuid[8] & 0x3f) | 0x80;
+
+ return 0;
+}
*/
const char *nvme_get_version(enum nvme_version type);
+#define NVME_UUID_LEN_STRING 37 /* 1b4e28ba-2fa1-11d2-883f-0016d3cca427 + \0 */
+#define NVME_UUID_LEN 16
+
+/**
+ * nvme_uuid_to_string - Return string represenation of encoded UUID
+ * @uuid: Binary encoded input UUID
+ * @str: Output string represenation of UUID
+ *
+ * Return: Returns error code if type conversion fails.
+ */
+int nvme_uuid_to_string(unsigned char uuid[NVME_UUID_LEN], char *str);
+
+/**
+ * nvme_uuid_from_string - Return encoded UUID represenation of string UUID
+ * @uuid: Binary encoded input UUID
+ * @str: Output string represenation of UUID
+ *
+ * Return: Returns error code if type conversion fails.
+ */
+int nvme_uuid_from_string(const char *str, unsigned char uuid[NVME_UUID_LEN]);
+
+/**
+ * nvme_uuid_random - Generate random UUID
+ * @uuid: Generated random UUID
+ *
+ * Generate random number according
+ * https://www.rfc-editor.org/rfc/rfc4122#section-4.4
+ *
+ * Return: Returns error code if generating of random number fails.
+ */
+int nvme_uuid_random(unsigned char uuid[NVME_UUID_LEN]);
+
#endif /* _LIBNVME_UTIL_H */
main = executable(
'main-test',
['test.c'],
- dependencies: [libnvme_dep, libuuid_dep],
+ dependencies: [libnvme_dep],
include_directories: [incdir, internal_incdir]
)
)
test('mi-mctp', mi_mctp)
+
+uuid = executable(
+ 'test-uuid',
+ ['uuid.c'],
+ dependencies: libnvme_dep,
+ include_directories: [incdir, internal_incdir]
+)
+
+test('uuid', uuid)
#include <string.h>
#include <stdbool.h>
#include <inttypes.h>
-#include <uuid.h>
#include <libnvme.h>
#include <ccan/endian/endian.h>
nvme_ctrl_get_state(c));
nvme_ctrl_for_each_ns(c, n) {
- char uuid_str[40];
- uuid_t uuid;
+ char uuid_str[NVME_UUID_LEN_STRING];
+ unsigned char uuid[NVME_UUID_LEN];
printf(" `- %s lba size:%d lba max:%" PRIu64 "\n",
nvme_ns_get_name(n),
nvme_ns_get_lba_size(n),
printf(" nguid:");
print_hex(nvme_ns_get_nguid(n), 16);
nvme_ns_get_uuid(n, uuid);
- uuid_unparse_lower(uuid, uuid_str);
+ nvme_uuid_to_string(uuid, uuid_str);
printf(" uuid:%s csi:%d\n", uuid_str,
nvme_ns_get_csi(n));
}
--- /dev/null
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/**
+ * This file is part of libnvme.
+ * Copyright (c) 2022 Daniel Wagner, SUSE Software Solutions
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <ccan/array_size/array_size.h>
+
+#include <libnvme.h>
+
+static int test_rc;
+
+struct test_data {
+ unsigned char uuid[NVME_UUID_LEN];
+ const char *str;
+};
+
+static struct test_data test_data[] = {
+ { { 0 }, "00000000-0000-0000-0000-000000000000" },
+ { { [0 ... 15] = 0xff }, "ffffffff-ffff-ffff-ffff-ffffffffffff" },
+ { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0f, 0x10 },
+ "00010203-0405-0607-0809-0a0b0c0d0f10" },
+};
+
+static void check_str(const char *exp, const char *res)
+{
+ if (!strcmp(res, exp))
+ return;
+
+ printf("ERROR: got '%s', expected '%s'\n", res, exp);
+
+ test_rc = 1;
+}
+
+static void print_uuid_hex(const unsigned char uuid[NVME_UUID_LEN])
+{
+ for (int i = 0; i < NVME_UUID_LEN; i++)
+ printf("%02x", uuid[i]);
+}
+
+static void check_uuid(unsigned char exp[NVME_UUID_LEN],
+ unsigned char res[NVME_UUID_LEN])
+{
+ if (!memcmp(exp, res, NVME_UUID_LEN))
+ return;
+
+ printf("ERROR: got '");
+ print_uuid_hex(exp);
+ printf("', expected '");
+ print_uuid_hex(res);
+ printf("'\n");
+}
+
+static void tostr_test(struct test_data *test)
+{
+ char str[NVME_UUID_LEN_STRING];
+
+ if (nvme_uuid_to_string(test->uuid, str)) {
+ test_rc = 1;
+ printf("ERROR: nvme_uuid_to_string() failed\n");
+ return;
+ }
+ check_str(test->str, str);
+}
+
+static void fromstr_test(struct test_data *test)
+{
+
+ unsigned char uuid[NVME_UUID_LEN];
+
+ if (nvme_uuid_from_string(test->str, uuid)) {
+ test_rc = 1;
+ printf("ERROR: nvme_uuid_from_string() failed\n");
+ return;
+ }
+ check_uuid(test->uuid, uuid);
+}
+
+static void random_uuid_test(void)
+{
+ unsigned char uuid1[NVME_UUID_LEN], uuid2[NVME_UUID_LEN];
+ char str1[NVME_UUID_LEN_STRING], str2[NVME_UUID_LEN_STRING];
+
+ if (nvme_uuid_random(uuid1) || nvme_uuid_random(uuid2)) {
+ test_rc = 1;
+ printf("ERROR: nvme_uuid_random() failed\n");
+ return;
+ }
+
+ if (!memcmp(uuid1, uuid2, NVME_UUID_LEN)) {
+ test_rc = 1;
+ printf("ERROR: generated random numbers are equal\n");
+ return;
+ }
+
+ if (nvme_uuid_to_string(uuid1, str1) ||
+ nvme_uuid_to_string(uuid2, str2)) {
+ test_rc = 1;
+ printf("ERROR: could not stringify randomly generated UUID\n");
+ return;
+ }
+ printf("PASS: generated UUIDs %s %s\n", str1, str2);
+}
+
+int main(void)
+{
+ for (int i = 0; i < ARRAY_SIZE(test_data); i++)
+ tostr_test(&test_data[i]);
+
+ for (int i = 0; i < ARRAY_SIZE(test_data); i++)
+ fromstr_test(&test_data[i]);
+
+ random_uuid_test();
+
+ return test_rc ? EXIT_FAILURE : EXIT_SUCCESS;
+}