1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #define _XOPEN_SOURCE 600
6
7 #include <errno.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12 #include "cdi.h"
13 #include "cdi_int.h"
14 #include "cdi_uuid.h"
15 #include "dmemory.h"
16
17
18 static const char uuidFmt[] = "%02hhx%02hhx%02hhx%02hhx-"
19 "%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-"
20 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx";
21
22
cdiUUID2Str(const unsigned char * uuid,char * uuidstr)23 int cdiUUID2Str(const unsigned char *uuid, char *uuidstr)
24 {
25 if (uuid == NULL || uuidstr == NULL) return 0;
26
27 int iret = sprintf(uuidstr, uuidFmt,
28 uuid[0], uuid[1], uuid[2], uuid[3],
29 uuid[4], uuid[5], uuid[6], uuid[7],
30 uuid[8], uuid[9], uuid[10], uuid[11],
31 uuid[12], uuid[13], uuid[14], uuid[15]);
32
33 if (iret != uuidNumHexChars)
34 {
35 uuidstr[0] = 0;
36 iret = -1;
37 }
38
39 return iret;
40 }
41
42
cdiStr2UUID(const char * uuidstr,unsigned char * uuid)43 int cdiStr2UUID(const char *uuidstr, unsigned char *uuid)
44 {
45 if (uuid == NULL || uuidstr == NULL || strlen(uuidstr) != uuidNumHexChars) return -1;
46
47 int iret = sscanf(uuidstr, uuidFmt,
48 &uuid[0], &uuid[1], &uuid[2], &uuid[3],
49 &uuid[4], &uuid[5], &uuid[6], &uuid[7],
50 &uuid[8], &uuid[9], &uuid[10], &uuid[11],
51 &uuid[12], &uuid[13], &uuid[14], &uuid[15]);
52 if (iret != CDI_UUID_SIZE) return -1;
53
54 return iret;
55 }
56
57 //Returns a malloc'ed string that escapes all spaces and backslashes with backslashes.
cdiEscapeSpaces(const char * string)58 char* cdiEscapeSpaces(const char* string)
59 {
60 //How much memory do we need?
61 size_t escapeCount = 0, length = 0;
62 for(; string[length]; ++length)
63 escapeCount += string[length] == ' ' || string[length] == '\\';
64
65 char* result = (char *) Malloc(length + escapeCount + 1);
66 if(!result) return NULL;
67
68 //Do the escaping.
69 for(size_t in = 0, out = 0; in < length; ++out, ++in)
70 {
71 if(string[in] == ' ' || string[in] == '\\') result[out++] = '\\';
72 result[out] = string[in];
73 }
74 result[length + escapeCount] = 0; //termination!
75 return result;
76 }
77
78 //input: a space terminated string that may contain escaped characters
79 //output: a new zero terminated string with the escape characters removed
80 //*outStringEnd points to the terminating character upon return.
cdiUnescapeSpaces(const char * string,const char ** outStringEnd)81 char* cdiUnescapeSpaces(const char* string, const char** outStringEnd)
82 {
83 //How much memory do we need?
84 size_t escapeCount = 0, length = 0;
85 for(const char* current = string; *current && *current != ' '; current++)
86 {
87 if(*current == '\\')
88 {
89 current++, escapeCount++;
90 if(!current) return NULL;
91 }
92 length++;
93 }
94
95 char* result = (char *) Malloc(length + 1);
96 if(!result) return NULL;
97
98 //Do the unescaping.
99 for(size_t in = 0, out = 0; out < length;)
100 {
101 if(string[in] == '\\') in++;
102 result[out++] = string[in++];
103 }
104 result[length] = 0; //termination!
105 if(outStringEnd) *outStringEnd = &string[length + escapeCount];
106 return result;
107 }
108
109 #if defined(HAVE_DECL_UUID_GENERATE) && defined(HAVE_UUID_UUID_H)
110 #ifdef HAVE_SYS_TIME_H
111 #include <sys/time.h>
112 #endif
113 #include <uuid/uuid.h>
cdiCreateUUID(unsigned char * uuid)114 void cdiCreateUUID(unsigned char *uuid)
115 {
116 static int uuid_seeded = 0;
117 static char uuid_rand_state[31 * sizeof (long)];
118 char *caller_rand_state;
119 if (uuid_seeded)
120 caller_rand_state = setstate(uuid_rand_state);
121 else
122 {
123 struct timeval tv;
124 int status = gettimeofday(&tv, NULL);
125 if (status != 0)
126 {
127 perror("uuid random seed generation failed!");
128 exit(1);
129 }
130 unsigned seed = (unsigned)(tv.tv_sec ^ tv.tv_usec);
131 caller_rand_state = initstate(seed, uuid_rand_state, sizeof (uuid_rand_state));
132 uuid_seeded = 1;
133 }
134 uuid_generate(uuid);
135 setstate(caller_rand_state);
136 }
137 #elif defined (HAVE_DECL_UUID_CREATE) && defined (HAVE_UUID_H)
138 # ifdef HAVE_DECL_UUID_MAKE_V5
139 # include <uuid.h>
cdiCreateUUID(unsigned char * uuid)140 void cdiCreateUUID(unsigned char *uuid)
141 {
142 static const char error_stage[][16]
143 = { "uuid_create", "uuid_create", "uuid_load", "uuid_make", "uuid_export",
144 "uuid_destroy1", "uuid_destroy2" };
145 uuid_t *objuuid = NULL, *nsuuid = NULL;
146 int stage = 0;
147 uuid_rc_t status;
148 if ((status = uuid_create(&objuuid)) == UUID_RC_OK)
149 {
150 ++stage;
151 if ((status = uuid_create(&nsuuid)) == UUID_RC_OK)
152 {
153 ++stage;
154 if ((status = uuid_load(nsuuid, "ns:OID")) == UUID_RC_OK)
155 {
156 ++stage;
157 if ((status = uuid_make(objuuid, UUID_MAKE_V5, nsuuid, cdiLibraryVersion()))
158 == UUID_RC_OK)
159 {
160 ++stage;
161 size_t datalen = CDI_UUID_SIZE;
162 status = uuid_export(objuuid, UUID_FMT_BIN, &uuid, &datalen);
163 }
164 }
165 }
166 }
167 if (status != UUID_RC_OK)
168 Error("failed to generate UUID at stage %s\n", error_stage[stage]);
169 stage = 5;
170 if ((status = uuid_destroy(nsuuid)) != UUID_RC_OK)
171 Error("failed to generate UUID at stage %s\n", error_stage[stage]);
172 ++stage;
173 if ((status = uuid_destroy(objuuid)) != UUID_RC_OK)
174 Error("failed to generate UUID at stage %s\n", error_stage[stage]);
175 }
176 # else
177 #include <inttypes.h>
178 typedef uint8_t u_int8_t;
179 typedef uint16_t u_int16_t;
180 typedef uint32_t u_int32_t;
181 #include <uuid.h>
cdiCreateUUID(unsigned char * uuid)182 void cdiCreateUUID(unsigned char *uuid)
183 {
184 uint32_t status;
185 uuid_create((uuid_t *)(void *)uuid, &status);
186 if (status != uuid_s_ok)
187 {
188 perror("uuid generation failed!");
189 exit(1);
190 }
191 }
192 # endif
193 #else
194 #ifdef HAVE_SYS_TIME_H
195 #include <sys/time.h>
196 #endif
cdiCreateUUID(unsigned char * uuid)197 void cdiCreateUUID(unsigned char *uuid)
198 {
199 static int uuid_seeded = 0;
200 #ifndef _SX
201 static char uuid_rand_state[31 * sizeof (long)];
202 char *caller_rand_state;
203 if (uuid_seeded)
204 caller_rand_state = setstate(uuid_rand_state);
205 else
206 {
207 #ifdef HAVE_SYS_TIME_H
208 struct timeval tv;
209 int status = gettimeofday(&tv, NULL);
210 if (status != 0)
211 {
212 perror("failed seed generation!");
213 exit(1);
214 }
215 unsigned seed = tv.tv_sec ^ tv.tv_usec;
216 #else
217 unsigned seed = 0;
218 #endif
219 caller_rand_state = initstate(seed, uuid_rand_state,
220 sizeof (uuid_rand_state));
221 uuid_seeded = 1;
222 }
223 for (size_t i = 0; i < CDI_UUID_SIZE; ++i)
224 uuid[i] = (unsigned char)random();
225 #else
226 unsigned short caller_rand_state[3];
227 {
228 static unsigned short our_rand_state[3];
229 if (!uuid_seeded)
230 {
231 #ifdef HAVE_SYS_TIME_H
232 struct timeval tv;
233 int status = gettimeofday(&tv, NULL);
234 if (status != 0)
235 {
236 perror("failed seed generation!");
237 exit(1);
238 }
239 unsigned seed = tv.tv_sec ^ tv.tv_usec;
240 #else
241 unsigned seed = 0;
242 #endif
243 our_rand_state[0] = 0x330E;
244 our_rand_state[1] = (unsigned short)(seed & 0xFFFFU);
245 our_rand_state[2] = (unsigned short)((seed >> 16) & 0xFFFFU);
246 }
247 unsigned short *p = seed48(our_rand_state);
248 uuid_seeded = 1;
249 memcpy(caller_rand_state, p, sizeof (caller_rand_state));
250 }
251 for (size_t i = 0; i < CDI_UUID_SIZE; ++i)
252 uuid[i] = (unsigned char)lrand48();
253 #endif
254 /* encode variant into msb of octet 8 */
255 uuid[8] = (unsigned char)((uuid[8] & 0x3f) | (1 << 7));
256 /* encode version 4 ((pseudo-)random uuid) into msb of octet 7 */
257 uuid[7] = (unsigned char)((uuid[7] & 0x0f) | (4 << 4));
258 #ifndef _SX
259 setstate(caller_rand_state);
260 #else
261 seed48(caller_rand_state);
262 #endif
263 }
264 #endif
265
266 /*
267 * Local Variables:
268 * c-file-style: "Java"
269 * c-basic-offset: 2
270 * indent-tabs-mode: nil
271 * show-trailing-whitespace: t
272 * require-trailing-newline: t
273 * End:
274 */
275