1 /* 2 * QEMU UUID functions 3 * 4 * Copyright 2016 Red Hat, Inc. 5 * 6 * Authors: 7 * Fam Zheng <famz@redhat.com> 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the Free 11 * Software Foundation; either version 2 of the License, or (at your option) 12 * any later version. 13 * 14 */ 15 16 #include "qemu/osdep.h" 17 #include "qemu-common.h" 18 #include "qemu/uuid.h" 19 #include "qemu/bswap.h" 20 21 void qemu_uuid_generate(QemuUUID *uuid) 22 { 23 int i; 24 uint32_t tmp[4]; 25 26 QEMU_BUILD_BUG_ON(sizeof(QemuUUID) != 16); 27 28 for (i = 0; i < 4; ++i) { 29 tmp[i] = g_random_int(); 30 } 31 memcpy(uuid, tmp, sizeof(tmp)); 32 /* Set the two most significant bits (bits 6 and 7) of the 33 clock_seq_hi_and_reserved to zero and one, respectively. */ 34 uuid->data[8] = (uuid->data[8] & 0x3f) | 0x80; 35 /* Set the four most significant bits (bits 12 through 15) of the 36 time_hi_and_version field to the 4-bit version number. 37 */ 38 uuid->data[6] = (uuid->data[6] & 0xf) | 0x40; 39 } 40 41 int qemu_uuid_is_null(const QemuUUID *uu) 42 { 43 static QemuUUID null_uuid; 44 return memcmp(uu, &null_uuid, sizeof(QemuUUID)) == 0; 45 } 46 47 void qemu_uuid_unparse(const QemuUUID *uuid, char *out) 48 { 49 const unsigned char *uu = &uuid->data[0]; 50 snprintf(out, UUID_FMT_LEN + 1, UUID_FMT, 51 uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6], uu[7], 52 uu[8], uu[9], uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]); 53 } 54 55 char *qemu_uuid_unparse_strdup(const QemuUUID *uuid) 56 { 57 const unsigned char *uu = &uuid->data[0]; 58 return g_strdup_printf(UUID_FMT, 59 uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6], 60 uu[7], uu[8], uu[9], uu[10], uu[11], uu[12], 61 uu[13], uu[14], uu[15]); 62 } 63 64 static bool qemu_uuid_is_valid(const char *str) 65 { 66 int i; 67 68 for (i = 0; i < strlen(str); i++) { 69 const char c = str[i]; 70 if (i == 8 || i == 13 || i == 18 || i == 23) { 71 if (str[i] != '-') { 72 return false; 73 } 74 } else { 75 if ((c >= '0' && c <= '9') || 76 (c >= 'A' && c <= 'F') || 77 (c >= 'a' && c <= 'f')) { 78 continue; 79 } 80 return false; 81 } 82 } 83 return i == 36; 84 } 85 86 int qemu_uuid_parse(const char *str, QemuUUID *uuid) 87 { 88 unsigned char *uu = &uuid->data[0]; 89 int ret; 90 91 if (!qemu_uuid_is_valid(str)) { 92 return -1; 93 } 94 95 ret = sscanf(str, UUID_FMT, &uu[0], &uu[1], &uu[2], &uu[3], 96 &uu[4], &uu[5], &uu[6], &uu[7], &uu[8], &uu[9], 97 &uu[10], &uu[11], &uu[12], &uu[13], &uu[14], 98 &uu[15]); 99 100 if (ret != 16) { 101 return -1; 102 } 103 return 0; 104 } 105 106 /* Swap from UUID format endian (BE) to the opposite or vice versa. 107 */ 108 void qemu_uuid_bswap(QemuUUID *uuid) 109 { 110 assert(QEMU_PTR_IS_ALIGNED(uuid, sizeof(uint32_t))); 111 bswap32s(&uuid->fields.time_low); 112 bswap16s(&uuid->fields.time_mid); 113 bswap16s(&uuid->fields.time_high_and_version); 114 } 115