guid_new() returns GUIDs compatible with RFC4122

This commit is contained in:
matt335672 2022-11-09 16:41:34 +00:00
parent 9940f2f5ee
commit c3bb7dc294
3 changed files with 72 additions and 2 deletions

View File

@ -30,11 +30,27 @@
#include "os_calls.h" #include "os_calls.h"
#include "string_calls.h" #include "string_calls.h"
enum
{
/* Field offsets in the UUID */
E_CLOCK_SEQ_HI_AND_RESERVED = 8,
E_TIME_HI_AND_VERSION_MSB = 7,
/* UUID versions from RFC4122 section 4.1.3 */
E_UUID_VERSION_RANDOM = 4
};
struct guid struct guid
guid_new(void) guid_new(void)
{ {
struct guid guid = {0}; struct guid guid = {0};
g_random(guid.g, sizeof(guid.g)); g_random(guid.g, sizeof(guid.g));
/* Show this UUID as conforming to RFC4122 (section 4.1.1) */
guid.g[E_CLOCK_SEQ_HI_AND_RESERVED] &= ~0x40; /* Clear bit 6 */
guid.g[E_CLOCK_SEQ_HI_AND_RESERVED] |= (char)0x80; /* Set bit 7 */
guid.g[E_TIME_HI_AND_VERSION_MSB] &= ~0xf0;
guid.g[E_TIME_HI_AND_VERSION_MSB] |= (E_UUID_VERSION_RANDOM << 4);
return guid; return guid;
} }

View File

@ -32,8 +32,23 @@
/** /**
* Use a struct for the guid so we can easily copy by assignment * Use a struct for the guid so we can easily copy by assignment.
*/ * We use an array of char so that
* we can compare GUIDs with a straight memcmp()
*
* Some fields of the GUID are in little-endian-order as specified by
* [MS-DTYP]. This is at odds with RFC4122 which specifies big-endian
* order for all fields.
*
* Octets RFC4122 field
* ------ -------------
* 0-3 time_low (little-endian)
* 4-5 time_mid (little-endian)
* 6-7 time_hi_and_version (little-endian)
* 8 clock_seq_hi_and_reserved
* 9 clock_seq_low (in order)
* 10-15 node
*/
struct guid struct guid
{ {
char g[GUID_SIZE]; char g[GUID_SIZE];
@ -42,6 +57,8 @@ struct guid
/** /**
* Get an initialised GUID * Get an initialised GUID
* *
* The GUID is compatible with RFC4122 section 4.4.
*
* @return new GUID * @return new GUID
*/ */
struct guid guid_new(void); struct guid guid_new(void);

View File

@ -57,6 +57,42 @@ START_TEST(test_guid_to_str_ignore)
} }
END_TEST END_TEST
START_TEST(test_guid_to_str_random)
{
/* setup */
char dest[GUID_STR_SIZE];
struct guid guid;
unsigned int i;
for (i = 0 ; i < 100; ++i)
{
guid = guid_new();
/* test */
guid_to_str(&guid, dest);
/* Check all the '-' signs are in the right places */
ck_assert_int_eq(dest[8], '-');
ck_assert_int_eq(dest[13], '-');
ck_assert_int_eq(dest[18], '-');
ck_assert_int_eq(dest[23], '-');
/* Check the variant is RFC4122 */
char c = dest[18 + 1]; /* char after 3rd dash */
if (c != '8' && c != '9' && c != 'A' && c != 'B')
{
ck_abort_msg("Generated UUID is not RFC4122 compliant");
}
/* Check the version is 'randomly generated' */
c = dest[13 + 1]; /* char after 2nd dash */
if (c != '4')
{
ck_abort_msg("Generated UUID is not RFC4122 randomly-generated");
}
}
}
END_TEST
/******************************************************************************/ /******************************************************************************/
Suite * Suite *
@ -72,6 +108,7 @@ make_suite_test_guid(void)
tcase_add_test(tc_guid, test_guid_to_str_remotefx); tcase_add_test(tc_guid, test_guid_to_str_remotefx);
tcase_add_test(tc_guid, test_guid_to_str_nscodec); tcase_add_test(tc_guid, test_guid_to_str_nscodec);
tcase_add_test(tc_guid, test_guid_to_str_ignore); tcase_add_test(tc_guid, test_guid_to_str_ignore);
tcase_add_test(tc_guid, test_guid_to_str_random);
return s; return s;
} }