os_uuid.c 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. /**
  2. * \file os_uuid.c
  3. * \brief Create a new UUID.
  4. * \author Copyright (c) 2002-2012 Jason Perkins and the Premake project
  5. */
  6. #include "premake.h"
  7. #if PLATFORM_WINDOWS
  8. #include <objbase.h>
  9. #endif
  10. /*
  11. * Pull off the four lowest bytes of a value and add them to my array,
  12. * without the help of the determinately sized C99 data types that
  13. * are not yet universally supported.
  14. */
  15. static void add(unsigned char* bytes, int offset, unsigned long value)
  16. {
  17. int i;
  18. for (i = 0; i < 4; ++i)
  19. {
  20. bytes[offset++] = (unsigned char)(value & 0xff);
  21. value >>= 8;
  22. }
  23. }
  24. int os_uuid(lua_State* L)
  25. {
  26. char uuid[38];
  27. unsigned char bytes[16];
  28. /* If a name argument is supplied, build the UUID from that. For speed we
  29. * are using a simple DBJ2 hashing function; if this isn't sufficient we
  30. * can switch to a full RFC 4122 §4.3 implementation later. */
  31. const char* name = luaL_optstring(L, 1, NULL);
  32. if (name != NULL)
  33. {
  34. add(bytes, 0, do_hash(name, 0));
  35. add(bytes, 4, do_hash(name, 'L'));
  36. add(bytes, 8, do_hash(name, 'u'));
  37. add(bytes, 12, do_hash(name, 'a'));
  38. }
  39. /* If no name is supplied, try to build one properly */
  40. else
  41. {
  42. #if PLATFORM_WINDOWS
  43. CoCreateGuid((GUID*)bytes);
  44. #elif PLATFORM_OS2
  45. int i;
  46. for (i = 0; i < 16; i++)
  47. bytes[i] = (unsigned char)gethrtime();
  48. #else
  49. int result;
  50. /* not sure how to get a UUID here, so I fake it */
  51. FILE* rnd = fopen("/dev/urandom", "rb");
  52. result = fread(bytes, 16, 1, rnd);
  53. fclose(rnd);
  54. if (!result)
  55. {
  56. return 0;
  57. }
  58. #endif
  59. }
  60. sprintf(uuid, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
  61. bytes[0], bytes[1], bytes[2], bytes[3],
  62. bytes[4], bytes[5],
  63. bytes[6], bytes[7],
  64. bytes[8], bytes[9],
  65. bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]);
  66. lua_pushstring(L, uuid);
  67. return 1;
  68. }