mirror of
https://git.openafs.org/openafs.git
synced 2025-01-18 06:50:12 +00:00
opr: Add UUID handling functions
Add a set of functions to the opr library to handle creating and manipulating UUIDs. The opr_uuid_t type is held as a 16 octet character string, which comprises the UUID encoded into network byte order. This is the primary form for manipulating UUIDs with this library, as it avoids any nbo/hbo problems. For applications which require raw access to the UUID components, the opr_uuid_unpacked structure is provided, and opr_uuid_pack/opr_uuid_unpack can be used to convert to and from this format. Finally, functions to print the UUID as a string, and parse a UUID from a string, are provided. When printing, we use the standard UUID format of 000000-0000-0000-0000-00000000. However, the afsUUID library used to print UUIDs as 000000-0000-0000-00-00-00000000, so we also accept this format. Change-Id: I78ef79b7ab8ae15fb955c6495118722875c94f8d Reviewed-on: http://gerrit.openafs.org/7977 Tested-by: BuildBot <buildbot@rampaginggeek.com> Reviewed-by: Derrick Brashear <shadow@dementix.org>
This commit is contained in:
parent
b251b40572
commit
6f6bfb31ac
@ -149,7 +149,7 @@ config: prelude
|
||||
procmgmt: $(DIR_roken) config
|
||||
+${COMPILE_PART1} procmgmt ${COMPILE_PART2}
|
||||
|
||||
opr: config $(DIR_roken)
|
||||
opr: config hcrypto $(DIR_roken)
|
||||
+${COMPILE_PART1} opr ${COMPILE_PART2}
|
||||
|
||||
util: opr $(DIR_roken) procmgmt hcrypto lwp_depinstall rx_depinstall
|
||||
|
@ -1858,8 +1858,14 @@ LIB_hcrypto="-lafshcrypto"
|
||||
LDFLAGS_hcrypto="-L\$(TOP_LIBDIR)"
|
||||
AC_SUBST(LIB_hcrypto)
|
||||
AC_SUBST(LDFLAGS_hcrypto)
|
||||
|
||||
dnl Check for UUID library
|
||||
AC_CHECK_HEADERS([uuid/uuid.h])
|
||||
AC_CHECK_LIB(uuid, uuid_generate, LIBS_uuid="-luuid")
|
||||
AC_CHECK_FUNCS([uuid_generate])
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN([SUMMARY], [
|
||||
# Print a configuration summary
|
||||
echo
|
||||
|
@ -2,14 +2,15 @@ srcdir=@srcdir@
|
||||
include @TOP_OBJDIR@/src/config/Makefile.config
|
||||
include @TOP_OBJDIR@/src/config/Makefile.shared
|
||||
|
||||
objects = assert.o casestrcpy.o rbtree.o
|
||||
objects = assert.o casestrcpy.o rbtree.o uuid.o
|
||||
|
||||
HEADERS = $(TOP_INCDIR)/afs/opr.h \
|
||||
$(TOP_INCDIR)/afs/opr_assert.h \
|
||||
$(TOP_INCDIR)/opr/jhash.h \
|
||||
$(TOP_INCDIR)/opr/queue.h \
|
||||
$(TOP_INCDIR)/opr/rbtree.h \
|
||||
$(TOP_INCDIR)/opr/time.h
|
||||
$(TOP_INCDIR)/opr/time.h \
|
||||
$(TOP_INCDIR)/opr/uuid.h
|
||||
|
||||
all: $(HEADERS) $(TOP_LIBDIR)/libopr.a
|
||||
|
||||
@ -39,6 +40,9 @@ $(TOP_INCDIR)/opr/rbtree.h: ${srcdir}/rbtree.h
|
||||
$(TOP_INCDIR)/opr/time.h: ${srcdir}/opr_time.h
|
||||
$(INSTALL_DATA) $? $@
|
||||
|
||||
$(TOP_INCDIR)/opr/uuid.h: ${srcdir}/uuid.h
|
||||
$(INSTALL_DATA) $? $@
|
||||
|
||||
clean:
|
||||
rm -f $(objects) libopr.a
|
||||
|
||||
|
@ -16,7 +16,8 @@ INCFILES = \
|
||||
$(DESTDIR)\include\opr\jhash.h \
|
||||
$(DESTDIR)\include\opr\queue.h \
|
||||
$(DESTDIR)\include\opr\rbtree.h \
|
||||
$(DESTDIR)\include\opr\time.h
|
||||
$(DESTDIR)\include\opr\time.h \
|
||||
$(DESTDIR)\include\opr\uuid.h
|
||||
|
||||
$(DESTDIR)\include\opr\time.h: opr_time.h
|
||||
$(COPY) $** $@
|
||||
@ -27,6 +28,7 @@ LIBOBJS = \
|
||||
$(OUT)\assert.obj \
|
||||
$(OUT)\casestrcpy.obj \
|
||||
$(OUT)\rbtree.obj \
|
||||
$(OUT)\uuid.obj \
|
||||
$(OUT)\AFS_component_version_number.obj
|
||||
|
||||
$(LIBOBJS): $(INCFILES)
|
||||
|
163
src/opr/uuid.c
Normal file
163
src/opr/uuid.c
Normal file
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Your File System Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <afsconfig.h>
|
||||
#include <afs/param.h>
|
||||
|
||||
#include <roken.h>
|
||||
|
||||
#ifdef HAVE_UUID_UUID_H
|
||||
# include <uuid/uuid.h>
|
||||
#endif
|
||||
|
||||
#ifdef AFS_NT40_ENV
|
||||
# include <rpc.h>
|
||||
#endif
|
||||
|
||||
#include <hcrypto/rand.h>
|
||||
|
||||
#include "uuid.h"
|
||||
#include "jhash.h"
|
||||
|
||||
static const opr_uuid_t nilUid = {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
|
||||
|
||||
void
|
||||
opr_uuid_create(opr_uuid_t *uuid)
|
||||
{
|
||||
#if defined (AFS_NT40_ENV)
|
||||
struct opr_uuid_unpacked raw;
|
||||
|
||||
UuidCreate((UUID *) &raw);
|
||||
opr_uuid_pack(uuid, &raw);
|
||||
|
||||
#elif !defined(KERNEL) && defined(HAVE_UUID_GENERATE)
|
||||
|
||||
uuid_generate(uuid->data);
|
||||
|
||||
#else
|
||||
RAND_bytes(uuid->data, 16);
|
||||
|
||||
uuid->data[6] = (uuid->data[6] & 0x0F) | 0x40; /* verison is 4 */
|
||||
uuid->data[8] = (uuid->data[8] & 0x3F) | 0x80; /* variant is DCE */
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
opr_uuid_isNil(const opr_uuid_t *uuid)
|
||||
{
|
||||
return opr_uuid_equal(uuid, &nilUid);
|
||||
}
|
||||
|
||||
int
|
||||
opr_uuid_equal(const opr_uuid_t *uuid1, const opr_uuid_t *uuid2)
|
||||
{
|
||||
return memcmp(uuid1, uuid2, sizeof(opr_uuid_t)) == 0;
|
||||
}
|
||||
|
||||
int
|
||||
opr_uuid_hash(const opr_uuid_t *uuid)
|
||||
{
|
||||
/* uuid->data is a (unsigned char *), so there's every danger that this
|
||||
* may cause an unaligned access on some platforms */
|
||||
return opr_jhash((const afs_uint32 *)uuid->data, 4, 0);
|
||||
}
|
||||
|
||||
#if !defined(KERNEL)
|
||||
void
|
||||
opr_uuid_toString(const opr_uuid_t *uuid, char **string)
|
||||
{
|
||||
unsigned const char *p;
|
||||
|
||||
p = uuid->data;
|
||||
asprintf(string,
|
||||
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-"
|
||||
"%02x%02x%02x%02x%02x%02x",
|
||||
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
|
||||
p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
|
||||
}
|
||||
|
||||
void
|
||||
opr_uuid_freeString(char *string)
|
||||
{
|
||||
free(string);
|
||||
}
|
||||
|
||||
int
|
||||
opr_uuid_fromString(opr_uuid_t *uuid, const char *string)
|
||||
{
|
||||
unsigned int i[16];
|
||||
int items, c;
|
||||
|
||||
/* XXX - Traditionally, AFS has printed UUIDs as
|
||||
* 00000000-0000-00-00-00000000. We should perhaps also accept
|
||||
* that format here
|
||||
*/
|
||||
items = sscanf(string,
|
||||
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-"
|
||||
"%02x%02x%02x%02x%02x%02x",
|
||||
&i[0], &i[1], &i[2], &i[3], &i[4], &i[5],
|
||||
&i[6], &i[7], &i[8], &i[9], &i[10], &i[11],
|
||||
&i[12], &i[13], &i[14], &i[15]);
|
||||
if (items !=16) {
|
||||
/* Originally, AFS's printed UUIDs would take the form
|
||||
* 00000000-0000-0000-00-00-00000000. Also handle this. */
|
||||
items = sscanf(string,
|
||||
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x-%02x-"
|
||||
"%02x%02x%02x%02x%02x%02x",
|
||||
&i[0], &i[1], &i[2], &i[3], &i[4], &i[5],
|
||||
&i[6], &i[7], &i[8], &i[9], &i[10], &i[11],
|
||||
&i[12], &i[13], &i[14], &i[15]);
|
||||
}
|
||||
if (items !=16)
|
||||
return EINVAL;
|
||||
|
||||
for (c=0; c<16; c++)
|
||||
uuid->data[c] = i[c];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
opr_uuid_pack(opr_uuid_t *uuid, const struct opr_uuid_unpacked *raw)
|
||||
{
|
||||
afs_uint32 intval;
|
||||
unsigned short shortval;
|
||||
|
||||
intval = htonl(raw->time_low);
|
||||
memcpy(&uuid->data[0], &intval, sizeof(uint32_t));
|
||||
|
||||
shortval = htons(raw->time_mid);
|
||||
memcpy(&uuid->data[4], &shortval, sizeof(uint16_t));
|
||||
|
||||
shortval = htons(raw->time_hi_and_version);
|
||||
memcpy(&uuid->data[6], &shortval, sizeof(uint16_t));
|
||||
|
||||
uuid->data[8] = raw->clock_seq_hi_and_reserved;
|
||||
uuid->data[9] = raw->clock_seq_low;
|
||||
|
||||
memcpy(&uuid->data[10], &raw->node, 6);
|
||||
}
|
||||
|
||||
void
|
||||
opr_uuid_unpack(const opr_uuid_t *uuid, struct opr_uuid_unpacked *raw)
|
||||
{
|
||||
afs_uint32 intval;
|
||||
unsigned short shortval;
|
||||
|
||||
memcpy(&intval, &uuid->data[0], sizeof(uint32_t));
|
||||
raw->time_low = ntohl(intval);
|
||||
|
||||
memcpy(&shortval, &uuid->data[4], sizeof(uint16_t));
|
||||
raw->time_mid = ntohs(shortval);
|
||||
|
||||
memcpy(&shortval, &uuid->data[6], sizeof(uint16_t));
|
||||
raw->time_hi_and_version = ntohs(shortval);
|
||||
|
||||
raw->clock_seq_hi_and_reserved = uuid->data[8];
|
||||
raw->clock_seq_low = uuid->data[9];
|
||||
|
||||
memcpy(&raw->node, &uuid->data[10], 6);
|
||||
}
|
||||
|
||||
#endif
|
38
src/opr/uuid.h
Normal file
38
src/opr/uuid.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Your File System Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef OPENAFS_OPR_UUID_H
|
||||
#define OPENAFS_OPR_UUID_H 1
|
||||
|
||||
struct opr_uuid {
|
||||
unsigned char data[16];
|
||||
};
|
||||
|
||||
struct opr_uuid_unpacked {
|
||||
afs_uint32 time_low;
|
||||
unsigned short time_mid;
|
||||
unsigned short time_hi_and_version;
|
||||
char clock_seq_hi_and_reserved;
|
||||
char clock_seq_low;
|
||||
char node[6];
|
||||
};
|
||||
|
||||
typedef struct opr_uuid opr_uuid_t;
|
||||
typedef opr_uuid_t opr_uuid; /* For XDR */
|
||||
|
||||
extern void opr_uuid_create(opr_uuid_t *uuid);
|
||||
extern int opr_uuid_isNil(const opr_uuid_t *uuid);
|
||||
extern int opr_uuid_equal(const opr_uuid_t *uuid1, const opr_uuid_t *uuid2);
|
||||
extern int opr_uuid_hash(const opr_uuid_t *uuid);
|
||||
|
||||
#if !defined(KERNEL)
|
||||
extern void opr_uuid_toString(const opr_uuid_t *uuid, char **string);
|
||||
extern void opr_uuid_freeString(char *string);
|
||||
extern int opr_uuid_fromString(opr_uuid_t *uuid, const char *string);
|
||||
#endif
|
||||
|
||||
extern void opr_uuid_pack(opr_uuid_t *uuid, const struct opr_uuid_unpacked *raw);
|
||||
extern void opr_uuid_unpack(const opr_uuid_t *uuid, struct opr_uuid_unpacked *raw);
|
||||
|
||||
#endif
|
@ -9,6 +9,7 @@ opr/jhash
|
||||
opr/queues
|
||||
opr/rbtree
|
||||
opr/time
|
||||
opr/uuid
|
||||
ptserver/pt_util
|
||||
ptserver/pts-man
|
||||
rx/event
|
||||
|
@ -7,7 +7,7 @@ MODULE_CFLAGS = -I$(srcdir)/../..
|
||||
|
||||
LIBS=../tap/libtap.a $(abs_top_builddir)/lib/libopr.a
|
||||
|
||||
tests = jhash-t queues-t rbtree-t time-t
|
||||
tests = jhash-t queues-t rbtree-t time-t uuid-t
|
||||
|
||||
all check test tests: $(tests)
|
||||
|
||||
@ -23,5 +23,8 @@ jhash-t: jhash-t.o
|
||||
time-t: time-t.o
|
||||
$(AFS_LDRULE) time-t.o ../tap/libtap.a $(XLIBS)
|
||||
|
||||
uuid-t: uuid-t.o
|
||||
$(AFS_LDRULE) uuid-t.o ../tap/libtap.a $(LIBS) $(LIB_hcrypto) $(XLIBS)
|
||||
|
||||
clean distclean:
|
||||
$(RM) -f $(tests) *.o core
|
||||
|
65
tests/opr/uuid-t.c
Normal file
65
tests/opr/uuid-t.c
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Your File System Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <afsconfig.h>
|
||||
#include <afs/param.h>
|
||||
|
||||
#include <roken.h>
|
||||
|
||||
#include <opr/uuid.h>
|
||||
|
||||
#include <tests/tap/basic.h>
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
opr_uuid_t uuidA = {{0x4F, 0x44, 0x94, 0x47, 0x76, 0xBA, 0x47, 0x2C,
|
||||
0x97, 0x1A, 0x86, 0x6B, 0xC0, 0x10, 0x1A, 0x4B}};
|
||||
opr_uuid_t uuidB = {{0x5D, 0x2A, 0x39, 0x36, 0x94, 0xB2, 0x48, 0x90,
|
||||
0xA8, 0xD2, 0x7F, 0xBC, 0x1B, 0x29, 0xDA, 0x9B}};
|
||||
opr_uuid_t uuidC;
|
||||
char *str;
|
||||
int version;
|
||||
struct opr_uuid_unpacked raw;
|
||||
|
||||
memset(&uuidC, 0, sizeof(opr_uuid_t));
|
||||
|
||||
ok(opr_uuid_isNil(&uuidC), "opr_uuid_isNil(nilUuid) works");
|
||||
ok(!opr_uuid_isNil(&uuidA), "opr_uuid_isNil(uuid) works");
|
||||
|
||||
ok(opr_uuid_equal(&uuidA, &uuidA), "opr_uuid_equal(A, A) works");
|
||||
ok(!opr_uuid_equal(&uuidA, &uuidB), "opr_uuid_equal(A, B) works");
|
||||
ok(!opr_uuid_equal(&uuidA, &uuidC), "opr_uuid_equal(A, nilUid) works");
|
||||
|
||||
is_int(1187447773, opr_uuid_hash(&uuidA), "opr_uuid_hash(A) works");
|
||||
is_int(1251907497, opr_uuid_hash(&uuidB), "opr_uuid_hash(B) works");
|
||||
|
||||
opr_uuid_toString(&uuidA, &str);
|
||||
is_string("4f449447-76ba-472c-971a-866bc0101a4b", str,
|
||||
"opr_uuid_toString(uuidA) works");
|
||||
opr_uuid_freeString(str);
|
||||
|
||||
is_int(0, opr_uuid_fromString(&uuidC, "4F449447-76BA-472C-971A-866BC0101A4B"),
|
||||
"opr_uuid_fromString works with conventional UUID");
|
||||
ok(opr_uuid_equal(&uuidA, &uuidC), " ... and UUID is correct");
|
||||
|
||||
memset(&uuidC, 0, sizeof(opr_uuid_t));
|
||||
is_int(0, opr_uuid_fromString(&uuidC, "4F449447-76BA-472C-97-1A-866BC0101A4B"),
|
||||
"opr_uuid_fromString works with AFS style UUID");
|
||||
ok(opr_uuid_equal(&uuidA, &uuidC), " ... and UUID is correct");
|
||||
|
||||
memset(&uuidC, 0, sizeof(opr_uuid_t));
|
||||
opr_uuid_create(&uuidC);
|
||||
ok(!opr_uuid_isNil(&uuidC), "opr_uuid_create makes non-nil UUID");
|
||||
is_int(0x80, uuidC.data[8] & 0xB0, "variant is DCE as expected");
|
||||
version = (uuidC.data[6] & 0xF0) >> 4;
|
||||
ok(version >=1 && version <=5, "version %d is in expected range", version);
|
||||
|
||||
opr_uuid_unpack(&uuidB, &raw);
|
||||
opr_uuid_pack(&uuidC, &raw);
|
||||
ok(opr_uuid_equal(&uuidB, &uuidC),
|
||||
"opr_uuid_pack(opr_uuid_unpack()) works as expected");
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user