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