backport to buster
[hcoop/debian/openafs.git] / src / opr / uuid.c
CommitLineData
805e021f
CE
1/*
2 * Copyright (c) 2012 Your File System Inc. All rights reserved.
3 */
4
5#include <afsconfig.h>
6#include <afs/param.h>
7
8#include <roken.h>
9
10#ifdef HAVE_UUID_UUID_H
11# include <uuid/uuid.h>
12#endif
13
14#ifdef AFS_NT40_ENV
15# include <rpc.h>
16#endif
17
18#include <hcrypto/rand.h>
19
20#include "uuid.h"
21#include "jhash.h"
22
23static const opr_uuid_t nilUid = {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
24
25void
26opr_uuid_create(opr_uuid_t *uuid)
27{
28#if defined (AFS_NT40_ENV)
29 struct opr_uuid_unpacked raw;
30
31 UuidCreate((UUID *) &raw);
32 opr_uuid_pack(uuid, &raw);
33
34#elif !defined(KERNEL) && defined(HAVE_UUID_GENERATE)
35
36 uuid_generate(uuid->data);
37
38#else
39 RAND_bytes(uuid->data, 16);
40
41 uuid->data[6] = (uuid->data[6] & 0x0F) | 0x40; /* verison is 4 */
42 uuid->data[8] = (uuid->data[8] & 0x3F) | 0x80; /* variant is DCE */
43#endif
44}
45
46int
47opr_uuid_isNil(const opr_uuid_t *uuid)
48{
49 return opr_uuid_equal(uuid, &nilUid);
50}
51
52int
53opr_uuid_equal(const opr_uuid_t *uuid1, const opr_uuid_t *uuid2)
54{
55 return memcmp(uuid1, uuid2, sizeof(opr_uuid_t)) == 0;
56}
57
58unsigned int
59opr_uuid_hash(const opr_uuid_t *uuid)
60{
61 return opr_jhash_opaque(uuid->data, sizeof(uuid->data), 0);
62}
63
64#if !defined(KERNEL)
65int
66opr_uuid_toString(const opr_uuid_t *uuid, char **string)
67{
68 unsigned const char *p;
69 int r;
70
71 p = uuid->data;
72 r = asprintf(string,
73 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-"
74 "%02x%02x%02x%02x%02x%02x",
75 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
76 p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
77 if (r < 0) {
78 *string = NULL;
79 return ENOMEM;
80 }
81 return 0;
82}
83
84void
85opr_uuid_freeString(char *string)
86{
87 free(string);
88}
89
90int
91opr_uuid_fromString(opr_uuid_t *uuid, const char *string)
92{
93 unsigned int i[16];
94 int items, c;
95
96 /* XXX - Traditionally, AFS has printed UUIDs as
97 * 00000000-0000-00-00-00000000. We should perhaps also accept
98 * that format here
99 */
100 items = sscanf(string,
101 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-"
102 "%02x%02x%02x%02x%02x%02x",
103 &i[0], &i[1], &i[2], &i[3], &i[4], &i[5],
104 &i[6], &i[7], &i[8], &i[9], &i[10], &i[11],
105 &i[12], &i[13], &i[14], &i[15]);
106 if (items !=16) {
107 /* Originally, AFS's printed UUIDs would take the form
108 * 00000000-0000-0000-00-00-00000000. Also handle this. */
109 items = sscanf(string,
110 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x-%02x-"
111 "%02x%02x%02x%02x%02x%02x",
112 &i[0], &i[1], &i[2], &i[3], &i[4], &i[5],
113 &i[6], &i[7], &i[8], &i[9], &i[10], &i[11],
114 &i[12], &i[13], &i[14], &i[15]);
115 }
116 if (items !=16)
117 return EINVAL;
118
119 for (c=0; c<16; c++)
120 uuid->data[c] = i[c];
121
122 return 0;
123}
124
125#endif
126
127void
128opr_uuid_pack(opr_uuid_t *uuid, const struct opr_uuid_unpacked *raw)
129{
130 afs_uint32 intval;
131 unsigned short shortval;
132
133 intval = htonl(raw->time_low);
134 memcpy(&uuid->data[0], &intval, sizeof(uint32_t));
135
136 shortval = htons(raw->time_mid);
137 memcpy(&uuid->data[4], &shortval, sizeof(uint16_t));
138
139 shortval = htons(raw->time_hi_and_version);
140 memcpy(&uuid->data[6], &shortval, sizeof(uint16_t));
141
142 uuid->data[8] = raw->clock_seq_hi_and_reserved;
143 uuid->data[9] = raw->clock_seq_low;
144
145 memcpy(&uuid->data[10], &raw->node, 6);
146}
147
148void
149opr_uuid_unpack(const opr_uuid_t *uuid, struct opr_uuid_unpacked *raw)
150{
151 afs_uint32 intval;
152 unsigned short shortval;
153
154 memcpy(&intval, &uuid->data[0], sizeof(uint32_t));
155 raw->time_low = ntohl(intval);
156
157 memcpy(&shortval, &uuid->data[4], sizeof(uint16_t));
158 raw->time_mid = ntohs(shortval);
159
160 memcpy(&shortval, &uuid->data[6], sizeof(uint16_t));
161 raw->time_hi_and_version = ntohs(shortval);
162
163 raw->clock_seq_hi_and_reserved = uuid->data[8];
164 raw->clock_seq_low = uuid->data[9];
165
166 memcpy(&raw->node, &uuid->data[10], 6);
167}
168