]> www.infradead.org Git - users/sagi/libnvme.git/commitdiff
util: Add simple UUID type
authorDaniel Wagner <dwagner@suse.de>
Thu, 13 Oct 2022 15:05:50 +0000 (17:05 +0200)
committerDaniel Wagner <dwagner@suse.de>
Thu, 27 Oct 2022 14:10:11 +0000 (16:10 +0200)
Provide our own UUID type as there is no point to have a dependency on
libuuid just for a couple function we use.

Signed-off-by: Daniel Wagner <dwagner@suse.de>
12 files changed:
meson.build
src/libnvme.map
src/meson.build
src/nvme/fabrics.c
src/nvme/private.h
src/nvme/tree.c
src/nvme/tree.h
src/nvme/util.c
src/nvme/util.h
test/meson.build
test/test.c
test/uuid.c [new file with mode: 0644]

index 07f098de7155d9a36900a64c11e28b34d3243aa6..4735a231208be51560e3239fb12b9d49c06ca6e4 100644 (file)
@@ -52,10 +52,6 @@ conf.set('PROJECT_VERSION', '"@0@"'.format(meson.project_version()))
 
 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',
index d619f395ef455a3a21ccaf6536494e72ddf77482..be9bca35347d793cb4d07a654a71ed060d642de0 100644 (file)
@@ -7,6 +7,9 @@ LIBNVME_1_2 {
                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 {
index 3076be6bf9e496b0ad2ecc8a1781fd418a0981ca..9e49a077d8889c623cc953bac6393dc15d649702 100644 (file)
@@ -28,13 +28,11 @@ if conf.get('CONFIG_JSONC')
 endif
 
 deps = [
-    libuuid_dep,
     json_c_dep,
     openssl_dep,
 ]
 
 mi_deps = [
-    libuuid_dep,
     libsystemd_dep,
 ]
 
@@ -68,7 +66,6 @@ pkg.generate(libnvme,
 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,
@@ -88,9 +85,6 @@ libnvme_mi = library(
 
 libnvme_mi_dep = declare_dependency(
     include_directories: ['.'],
-    dependencies: [
-      libuuid_dep.partial_dependency(compile_args: true, includes: true),
-    ],
     link_with: libnvme_mi,
 )
 
@@ -107,9 +101,6 @@ libnvme_mi_test = library(
 
 libnvme_mi_test_dep = declare_dependency(
     include_directories: ['.'],
-    dependencies: [
-      libuuid_dep.partial_dependency(compile_args: true, includes: true),
-    ],
     link_with: libnvme_mi_test,
 )
 
index 1a4ac4a5426136809c5079e45ce604a45678ed0b..7c2b371140c7f619451c23e0c00900b3ce88bbb7 100644 (file)
@@ -39,7 +39,6 @@
 #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"
@@ -929,8 +928,8 @@ static int uuid_from_device_tree(char *system_uuid)
        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;
@@ -1018,7 +1017,7 @@ static int uuid_from_product_uuid(char *system_uuid)
        system_uuid[0] = '\0';
 
        nread = getline(&line, &len, stream);
-       if (nread != UUID_SIZE) {
+       if (nread != NVME_UUID_LEN_STRING) {
                ret = -ENXIO;
                goto out;
        }
@@ -1026,8 +1025,8 @@ static int uuid_from_product_uuid(char *system_uuid)
        /* 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;
 
@@ -1063,16 +1062,17 @@ char *nvmf_hostnqn_generate()
 {
        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)
@@ -1125,7 +1125,7 @@ static __u32 nvmf_get_tel(const char *hostsymname)
        __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;
@@ -1169,8 +1169,8 @@ static void nvmf_fill_die(struct nvmf_ext_die *die, struct nvme_host *h,
        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;
index 0aac4300978f85c5f4e78e1d73c5aba1f3016466..cdd1bbf5eb5146fbeacc76d987fee9af04e4607b 100644 (file)
@@ -16,8 +16,6 @@
 #include "fabrics.h"
 #include "mi.h"
 
-#include <uuid.h>
-
 
 extern const char *nvme_ctrl_sysfs_dir;
 extern const char *nvme_subsys_sysfs_dir;
@@ -57,7 +55,7 @@ struct nvme_ns {
 
        uint8_t eui64[8];
        uint8_t nguid[16];
-       uuid_t  uuid;
+       unsigned char uuid[NVME_UUID_LEN];
        enum nvme_csi csi;
 };
 
index 193051ca543de6ca2379c74d069cc0405321347f..b992824d74553339e3d68c63904ebf76f34a44e6 100644 (file)
@@ -1551,9 +1551,9 @@ const uint8_t *nvme_ns_get_nguid(nvme_ns_t n)
        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)
index 379dcb1d78d2569bada265bf3a9cdd922ac82a24..156cb79118ba41380a3bd19991be386b460a79c4 100644 (file)
@@ -15,7 +15,6 @@
 #include <stddef.h>
 
 #include <sys/types.h>
-#include <uuid.h>
 
 #include "ioctl.h"
 #include "util.h"
@@ -521,7 +520,7 @@ const uint8_t *nvme_ns_get_nguid(nvme_ns_t n);
  *
  * 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
index 653bb3623b211ba2ee805797edf59f45dc3893b6..c61dbe9214ba82ef960fba5534e160e337c14708 100644 (file)
@@ -11,6 +11,8 @@
 #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>
@@ -833,3 +835,57 @@ const char *nvme_get_version(enum nvme_version type)
                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;
+}
index 6c3163dbe9840165de517fa8f6b9d8c9dae6be2b..73be6e962977b5bb5a0d1d9720e743cc647e0196 100644 (file)
@@ -606,4 +606,36 @@ enum nvme_version {
  */
 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 */
index 00c9ceb2486802bc4d9d19c061e5ed9927e9cda6..d90f835ea14fba75572535fb3db1c54996985eae 100644 (file)
@@ -12,7 +12,7 @@
 main = executable(
     'main-test',
     ['test.c'],
-    dependencies: [libnvme_dep, libuuid_dep],
+    dependencies: [libnvme_dep],
     include_directories: [incdir, internal_incdir]
 )
 
@@ -56,3 +56,12 @@ mi_mctp = executable(
 )
 
 test('mi-mctp', mi_mctp)
+
+uuid = executable(
+    'test-uuid',
+    ['uuid.c'],
+    dependencies: libnvme_dep,
+    include_directories: [incdir, internal_incdir]
+)
+
+test('uuid', uuid)
index bc5393ba664daf500a658b7fc1ba61488b10b148..2f24e1ecf1155f612a96e3fcb90e2110c297215c 100644 (file)
@@ -19,7 +19,6 @@
 #include <string.h>
 #include <stdbool.h>
 #include <inttypes.h>
-#include <uuid.h>
 #include <libnvme.h>
 
 #include <ccan/endian/endian.h>
@@ -377,8 +376,8 @@ int main(int argc, char **argv)
                                       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),
@@ -388,7 +387,7 @@ int main(int argc, char **argv)
                                        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));
                                }
diff --git a/test/uuid.c b/test/uuid.c
new file mode 100644 (file)
index 0000000..9146453
--- /dev/null
@@ -0,0 +1,120 @@
+// 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;
+}