util: Add UUID API

A number of different places across the code base use CONFIG_UUID. Some
of them are soft dependency, some are not built if libuuid is not
available, some come with dummy fallback, some throws runtime error.

It is hard to maintain, and hard to reason for users.

Since UUID is a simple standard with only a small number of operations,
it is cleaner to have a central support in libqemuutil. This patch adds
qemu_uuid_* functions that all uuid users in the code base can
rely on. Except for qemu_uuid_generate which is new code, all other
functions are just copy from existing fallbacks from other files.

Note that qemu_uuid_parse is moved without updating the function
signature to use QemuUUID, to keep this patch simple.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
Message-Id: <1474432046-325-2-git-send-email-famz@redhat.com>
This commit is contained in:
Fam Zheng 2016-09-21 12:27:14 +08:00
parent 0679f98b40
commit cea25275a3
10 changed files with 156 additions and 25 deletions

View File

@ -235,25 +235,6 @@ void audio_init(void)
}
}
int qemu_uuid_parse(const char *str, uint8_t *uuid)
{
int ret;
if (strlen(str) != 36) {
return -1;
}
ret = sscanf(str, UUID_FMT, &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]);
if (ret != 16) {
return -1;
}
return 0;
}
void do_acpitable_option(const QemuOpts *opts)
{
#ifdef TARGET_I386

View File

@ -36,7 +36,7 @@
#include "block/block_int.h"
#include "block/scsi.h"
#include "qemu/iov.h"
#include "sysemu/sysemu.h"
#include "qemu/uuid.h"
#include "qmp-commands.h"
#include "qapi/qmp/qstring.h"
#include "crypto/secret.h"

View File

@ -20,6 +20,7 @@
#include "qemu/config-file.h"
#include "qemu/error-report.h"
#include "sysemu/sysemu.h"
#include "qemu/uuid.h"
#include "sysemu/cpus.h"
#include "hw/smbios/smbios.h"
#include "hw/loader.h"

59
include/qemu/uuid.h Normal file
View File

@ -0,0 +1,59 @@
/*
* QEMU UUID functions
*
* Copyright 2016 Red Hat, Inc.
*
* Authors:
* Fam Zheng <famz@redhat.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
*/
#ifndef QEMU_UUID_H
#define QEMU_UUID_H
#include "qemu-common.h"
/* Version 4 UUID (pseudo random numbers), RFC4122 4.4. */
typedef struct {
union {
unsigned char data[16];
struct {
/* Generated in BE endian, can be swapped with qemu_uuid_bswap. */
uint32_t time_low;
uint16_t time_mid;
uint16_t time_high_and_version;
uint8_t clock_seq_and_reserved;
uint8_t clock_seq_low;
uint8_t node[6];
} fields;
};
} QemuUUID;
#define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-" \
"%02hhx%02hhx-%02hhx%02hhx-" \
"%02hhx%02hhx-" \
"%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
#define UUID_FMT_LEN 36
#define UUID_NONE "00000000-0000-0000-0000-000000000000"
void qemu_uuid_generate(QemuUUID *out);
int qemu_uuid_is_null(const QemuUUID *uu);
void qemu_uuid_unparse(const QemuUUID *uuid, char *out);
char *qemu_uuid_unparse_strdup(const QemuUUID *uuid);
int qemu_uuid_parse(const char *str, uint8_t *uuid);
void qemu_uuid_bswap(QemuUUID *uuid);
#endif

View File

@ -18,10 +18,6 @@ extern const char *bios_name;
extern const char *qemu_name;
extern uint8_t qemu_uuid[];
extern bool qemu_uuid_set;
int qemu_uuid_parse(const char *str, uint8_t *uuid);
#define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
#define UUID_NONE "00000000-0000-0000-0000-000000000000"
bool runstate_check(RunState state);
void runstate_set(RunState new_state);

1
qmp.c
View File

@ -18,6 +18,7 @@
#include "qemu/cutils.h"
#include "monitor/monitor.h"
#include "sysemu/sysemu.h"
#include "qemu/uuid.h"
#include "qmp-commands.h"
#include "sysemu/char.h"
#include "ui/qemu-spice.h"

View File

@ -1,6 +1,6 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "sysemu/sysemu.h"
#include "qemu/uuid.h"
#include "qmp-commands.h"
UuidInfo *qmp_query_uuid(Error **errp)

View File

@ -21,6 +21,7 @@ util-obj-y += iov.o qemu-config.o qemu-sockets.o uri.o notify.o
util-obj-y += qemu-option.o qemu-progress.o
util-obj-y += hexdump.o
util-obj-y += crc32c.o
util-obj-y += uuid.o
util-obj-y += throttle.o
util-obj-y += getauxval.o
util-obj-y += readline.o

91
util/uuid.c Normal file
View File

@ -0,0 +1,91 @@
/*
* QEMU UUID functions
*
* Copyright 2016 Red Hat, Inc.
*
* Authors:
* Fam Zheng <famz@redhat.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/uuid.h"
#include "qemu/bswap.h"
void qemu_uuid_generate(QemuUUID *uuid)
{
int i;
uint32_t tmp[4];
QEMU_BUILD_BUG_ON(sizeof(QemuUUID) != 16);
for (i = 0; i < 4; ++i) {
tmp[i] = g_random_int();
}
memcpy(uuid, tmp, sizeof(tmp));
/* Set the two most significant bits (bits 6 and 7) of the
clock_seq_hi_and_reserved to zero and one, respectively. */
uuid->data[8] = (uuid->data[8] & 0x3f) | 0x80;
/* Set the four most significant bits (bits 12 through 15) of the
time_hi_and_version field to the 4-bit version number.
*/
uuid->data[6] = (uuid->data[6] & 0xf) | 0x40;
}
int qemu_uuid_is_null(const QemuUUID *uu)
{
QemuUUID null_uuid = { 0 };
return memcmp(uu, &null_uuid, sizeof(QemuUUID)) == 0;
}
void qemu_uuid_unparse(const QemuUUID *uuid, char *out)
{
const unsigned char *uu = &uuid->data[0];
snprintf(out, UUID_FMT_LEN + 1, UUID_FMT,
uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6], uu[7],
uu[8], uu[9], uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]);
}
char *qemu_uuid_unparse_strdup(const QemuUUID *uuid)
{
const unsigned char *uu = &uuid->data[0];
return g_strdup_printf(UUID_FMT,
uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6],
uu[7], uu[8], uu[9], uu[10], uu[11], uu[12],
uu[13], uu[14], uu[15]);
}
int qemu_uuid_parse(const char *str, uint8_t *uuid)
{
int ret;
if (strlen(str) != 36) {
return -1;
}
ret = sscanf(str, UUID_FMT, &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]);
if (ret != 16) {
return -1;
}
return 0;
}
/* Swap from UUID format endian (BE) to the opposite or vice versa.
*/
void qemu_uuid_bswap(QemuUUID *uuid)
{
assert(QEMU_PTR_IS_ALIGNED(uuid, sizeof(uint32_t)));
bswap32s(&uuid->fields.time_low);
bswap16s(&uuid->fields.time_mid);
bswap16s(&uuid->fields.time_high_and_version);
}

1
vl.c
View File

@ -25,6 +25,7 @@
#include "qemu-version.h"
#include "qemu/cutils.h"
#include "qemu/help_option.h"
#include "qemu/uuid.h"
#ifdef CONFIG_SECCOMP
#include "sysemu/seccomp.h"