uniqueid.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. /* uniqueid.c implementation of entryid functionality */
  42. #include <stdlib.h>
  43. #include <stdio.h>
  44. #include <string.h>
  45. #include <ctype.h>
  46. #include "slap.h"
  47. #define UIDSTR_SIZE 35 /* size of the string representation of the id */
  48. #define MODULE "uniqueid" /* for logging */
  49. static int isValidFormat (const char * buff);
  50. /* All functions that strat with slapi_ are exposed to the plugins */
  51. /* Function: slapi_uniqueIDNew
  52. Description: creates new Slapi_UniqueID object
  53. Parameters: none
  54. Return: pointer to the new uId object if successful
  55. NULL if memory allocation failed
  56. */
  57. Slapi_UniqueID *slapi_uniqueIDNew ()
  58. {
  59. Slapi_UniqueID *uId;
  60. uId = (Slapi_UniqueID*)slapi_ch_malloc (sizeof (Slapi_UniqueID));
  61. if (uId == NULL)
  62. {
  63. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "uniqueIDNew: "
  64. "failed to allocate new id.\n");
  65. return NULL;
  66. }
  67. memset (uId, 0, sizeof (Slapi_UniqueID));
  68. return uId;
  69. }
  70. /* Function: slapi_uniqueIDDestroy
  71. Description: destroys Slapi_UniqueID objects and sets the pointer to NULL
  72. Parameters: uId - id to destroy
  73. Return: none
  74. */
  75. void slapi_uniqueIDDestroy (Slapi_UniqueID **uId)
  76. {
  77. if (uId && *uId)
  78. {
  79. slapi_ch_free ((void**)uId);
  80. *uId = NULL;
  81. }
  82. }
  83. /* Function: slapi_uniqueIDCompare
  84. Description: this function lexically compares two entry ids.
  85. both Ids must have UUID type.
  86. Parameters: uId1, uId2 - ids to compare
  87. Return: -1 if uId1 < uId2
  88. 0 if uId2 == uId2
  89. 1 if uId2 > uId2
  90. UID_BADDATA if invalid pointer passed to the function
  91. */
  92. int slapi_uniqueIDCompare (const Slapi_UniqueID *uId1, const Slapi_UniqueID *uId2){
  93. if (uId1 == NULL || uId2 == NULL)
  94. {
  95. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "uniqueIDCompare: "
  96. "NULL argument passed to the function.\n");
  97. return UID_BADDATA;
  98. }
  99. return(uuid_compare(uId1, uId2));
  100. }
  101. /* Function: slapi_uniqueIDCompareString
  102. Description: this function compares two uniqueids, represented as strings
  103. Parameters: uuid1, uuid2 - ids to compare
  104. Return: 0 if uuid1 == uuid2
  105. non-zero if uuid1 != uuid2 or uuid1 == NULL or uuid2 == NULL
  106. */
  107. int slapi_uniqueIDCompareString(const char *uuid1, const char *uuid2)
  108. {
  109. int return_value = 0; /* assume not equal */
  110. if (NULL != uuid1)
  111. {
  112. if (NULL != uuid2)
  113. {
  114. if (strcmp(uuid1, uuid2) == 0)
  115. {
  116. return_value = 1;
  117. }
  118. }
  119. }
  120. return return_value;
  121. }
  122. /* Function: slapi_uniqueIDFormat
  123. Description: this function converts Slapi_UniqueID to its string representation.
  124. The id format is HHHHHHHH-HHHHHHHH-HHHHHHHH-HHHHHHHH
  125. where H is a hex digit. The data will be outputed in the
  126. network byte order.
  127. Parameters: uId - entry id
  128. buff - buffer in which id is returned; caller must free this
  129. buffer
  130. Return: UID_SUCCESS - function was successfull
  131. UID_BADDATA - invalid parameter passed to the function
  132. UID_MEMORY_ERROR - failed to allocate the buffer
  133. */
  134. int slapi_uniqueIDFormat (const Slapi_UniqueID *uId, char **buff){
  135. guid_t uuid_tmp;
  136. char *ptr;
  137. if (uId == NULL || buff == NULL)
  138. {
  139. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "uniqueIDFormat: "
  140. "NULL argument passed to the function.\n");
  141. return UID_BADDATA;
  142. }
  143. *buff = (char*)slapi_ch_malloc (UIDSTR_SIZE + 1);
  144. if (*buff == NULL)
  145. {
  146. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "uniqueIDFormat: "
  147. "failed to allocate buffer.\n");
  148. return UID_MEMORY_ERROR;
  149. }
  150. uuid_tmp = *uId;
  151. uuid_tmp.time_low = htonl(uuid_tmp.time_low);
  152. uuid_tmp.time_mid = htons(uuid_tmp.time_mid);
  153. uuid_tmp.time_hi_and_version = htons(uuid_tmp.time_hi_and_version);
  154. ptr = slapi_u8_to_hex(((uint8_t *)&uuid_tmp.time_low)[0], *buff, 0);
  155. ptr = slapi_u8_to_hex(((uint8_t *)&uuid_tmp.time_low)[1], ptr, 0);
  156. ptr = slapi_u8_to_hex(((uint8_t *)&uuid_tmp.time_low)[2], ptr, 0);
  157. ptr = slapi_u8_to_hex(((uint8_t *)&uuid_tmp.time_low)[3], ptr, 0);
  158. *ptr++ = '-';
  159. ptr = slapi_u8_to_hex(((uint8_t *)&uuid_tmp.time_mid)[0], ptr, 0);
  160. ptr = slapi_u8_to_hex(((uint8_t *)&uuid_tmp.time_mid)[1], ptr, 0);
  161. ptr = slapi_u8_to_hex(((uint8_t *)&uuid_tmp.time_hi_and_version)[0], ptr, 0);
  162. ptr = slapi_u8_to_hex(((uint8_t *)&uuid_tmp.time_hi_and_version)[1], ptr, 0);
  163. *ptr++ = '-';
  164. ptr = slapi_u8_to_hex(uuid_tmp.clock_seq_hi_and_reserved, ptr, 0);
  165. ptr = slapi_u8_to_hex(uuid_tmp.clock_seq_low, ptr, 0);
  166. ptr = slapi_u8_to_hex(uuid_tmp.node[0], ptr, 0);
  167. ptr = slapi_u8_to_hex(uuid_tmp.node[1], ptr, 0);
  168. *ptr++ = '-';
  169. ptr = slapi_u8_to_hex(uuid_tmp.node[2], ptr, 0);
  170. ptr = slapi_u8_to_hex(uuid_tmp.node[3], ptr, 0);
  171. ptr = slapi_u8_to_hex(uuid_tmp.node[4], ptr, 0);
  172. ptr = slapi_u8_to_hex(uuid_tmp.node[5], ptr, 0);
  173. *ptr = 0;
  174. return UID_SUCCESS;
  175. }
  176. /* Function: slapi_uniqueIDScan
  177. Description: this function converts a string buffer into uniqueID.
  178. Parameters: uId - unique id to be returned
  179. buff - buffer with uniqueID in the format returned by
  180. uniqueIDFormat function
  181. Return: UID_SUCCESS - function was successfull
  182. UID_BADDATA - null parameter(s) or bad format
  183. */
  184. int slapi_uniqueIDScan (Slapi_UniqueID *uId, const char *buff){
  185. if (uId == NULL || buff == NULL)
  186. {
  187. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "uniqueIDScan: "
  188. "NULL argument passed to the function.\n");
  189. return UID_BADDATA;
  190. }
  191. if (!isValidFormat (buff))
  192. {
  193. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "uniqueIDScan: "
  194. "invalid data format.\n");
  195. return UID_BADDATA;
  196. }
  197. ((PRUint8 *) &uId->time_low)[0] = slapi_str_to_u8 (&(buff[0]));
  198. ((PRUint8 *) &uId->time_low)[1] = slapi_str_to_u8 (&(buff[2]));
  199. ((PRUint8 *) &uId->time_low)[2] = slapi_str_to_u8 (&(buff[4]));
  200. ((PRUint8 *) &uId->time_low)[3] = slapi_str_to_u8 (&(buff[6]));
  201. /* next field is at 9 because we skip the - */
  202. ((PRUint8 *) &uId->time_mid)[0] = slapi_str_to_u8 (&(buff[9]));
  203. ((PRUint8 *) &uId->time_mid)[1] = slapi_str_to_u8 (&(buff[11]));
  204. ((PRUint8 *) &uId->time_hi_and_version)[0] = slapi_str_to_u8 (&(buff[13]));
  205. ((PRUint8 *) &uId->time_hi_and_version)[1] = slapi_str_to_u8 (&(buff[15]));
  206. /* next field is at 18 because we skip the - */
  207. uId->clock_seq_hi_and_reserved = slapi_str_to_u8 (&(buff[18]));
  208. uId->clock_seq_low = slapi_str_to_u8 (&(buff[20]));
  209. uId->node[0] = slapi_str_to_u8 (&(buff[22]));
  210. uId->node[1] = slapi_str_to_u8 (&(buff[24]));
  211. /* next field is at 27 because we skip the - */
  212. uId->node[2] = slapi_str_to_u8 (&(buff[27]));
  213. uId->node[3] = slapi_str_to_u8 (&(buff[29]));
  214. uId->node[4] = slapi_str_to_u8 (&(buff[31]));
  215. uId->node[5] = slapi_str_to_u8 (&(buff[33]));
  216. uId->time_low = ntohl(uId->time_low);
  217. uId->time_mid = ntohs(uId->time_mid);
  218. uId->time_hi_and_version = ntohs(uId->time_hi_and_version);
  219. return UID_SUCCESS;
  220. }
  221. /* Function: slapi_uniqueIDIsUUID
  222. Description: tests if given entry id is in UUID format
  223. Parameters: uId - id to test
  224. Return 0 - it is UUID
  225. 1 - it is not UUID
  226. UID_BADDATA - invalid data passed to the function
  227. Note: LPXXX - This call is not used currently. Keep it ???
  228. */
  229. int slapi_uniqueIDIsUUID (const Slapi_UniqueID *uId){
  230. if (uId == NULL)
  231. return UID_BADDATA;
  232. /* Shortening Slapi_UniqueID: This call does nothing */
  233. return (0);
  234. }
  235. /* Name: slapi_uniqueIDSize
  236. Description: returns size of the string version of uniqueID in bytes
  237. Parameters: none
  238. Return: size of the string version of uniqueID in bytes
  239. */
  240. int slapi_uniqueIDSize ()
  241. {
  242. return (UIDSTR_SIZE);
  243. }
  244. /* Name: slapi_uniqueIDDup
  245. Description: duplicates an UniqueID object
  246. Parameters: uId - id to duplicate
  247. Return: duplicate of the Id
  248. */
  249. Slapi_UniqueID* slapi_uniqueIDDup (Slapi_UniqueID *uId)
  250. {
  251. Slapi_UniqueID *uIdDup = slapi_uniqueIDNew ();
  252. memcpy (uIdDup, uId, sizeof (Slapi_UniqueID));
  253. return uIdDup;
  254. }
  255. /* helper functions */
  256. static char* format = "XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX";
  257. static size_t format_len = 35;
  258. /* This function verifies that buff contains data in the correct
  259. format (specified above). */
  260. static int isValidFormat (const char * buff)
  261. {
  262. int i;
  263. if (strlen (buff) != strlen (format))
  264. return UID_BADDATA;
  265. for (i = 0; i < format_len; i++)
  266. {
  267. if (format[i] == '-' && buff [i] != '-')
  268. return 0;
  269. else if (format[i] == 'X' && ! isxdigit (buff[i]))
  270. return 0;
  271. }
  272. return 1;
  273. }