1/* 2 * Python UUID module that wraps libuuid or Windows rpcrt4.dll. 3 * DCE compatible Universally Unique Identifier library. 4 */ 5 6#define PY_SSIZE_T_CLEAN 7 8#include "Python.h" 9#if defined(HAVE_UUID_H) 10 // AIX, FreeBSD, libuuid with pkgconf 11 #include <uuid.h> 12#elif defined(HAVE_UUID_UUID_H) 13 // libuuid without pkgconf 14 #include <uuid/uuid.h> 15#endif 16 17#ifdef MS_WINDOWS 18#include <rpc.h> 19#endif 20 21#ifndef MS_WINDOWS 22 23static PyObject * 24py_uuid_generate_time_safe(PyObject *Py_UNUSED(context), 25 PyObject *Py_UNUSED(ignored)) 26{ 27 uuid_t uuid; 28#ifdef HAVE_UUID_GENERATE_TIME_SAFE 29 int res; 30 31 res = uuid_generate_time_safe(uuid); 32 return Py_BuildValue("y#i", (const char *) uuid, sizeof(uuid), res); 33#elif defined(HAVE_UUID_CREATE) 34 uint32_t status; 35 uuid_create(&uuid, &status); 36# if defined(HAVE_UUID_ENC_BE) 37 unsigned char buf[sizeof(uuid)]; 38 uuid_enc_be(buf, &uuid); 39 return Py_BuildValue("y#i", buf, sizeof(uuid), (int) status); 40# else 41 return Py_BuildValue("y#i", (const char *) &uuid, sizeof(uuid), (int) status); 42# endif /* HAVE_UUID_CREATE */ 43#else /* HAVE_UUID_GENERATE_TIME_SAFE */ 44 uuid_generate_time(uuid); 45 return Py_BuildValue("y#O", (const char *) uuid, sizeof(uuid), Py_None); 46#endif /* HAVE_UUID_GENERATE_TIME_SAFE */ 47} 48 49#else /* MS_WINDOWS */ 50 51static PyObject * 52py_UuidCreate(PyObject *Py_UNUSED(context), 53 PyObject *Py_UNUSED(ignored)) 54{ 55 UUID uuid; 56 RPC_STATUS res; 57 58 Py_BEGIN_ALLOW_THREADS 59 res = UuidCreateSequential(&uuid); 60 Py_END_ALLOW_THREADS 61 62 switch (res) { 63 case RPC_S_OK: 64 case RPC_S_UUID_LOCAL_ONLY: 65 case RPC_S_UUID_NO_ADDRESS: 66 /* 67 All success codes, but the latter two indicate that the UUID is random 68 rather than based on the MAC address. If the OS can't figure this out, 69 neither can we, so we'll take it anyway. 70 */ 71 return Py_BuildValue("y#", (const char *)&uuid, sizeof(uuid)); 72 } 73 PyErr_SetFromWindowsErr(res); 74 return NULL; 75} 76 77#endif /* MS_WINDOWS */ 78 79 80static int 81uuid_exec(PyObject *module) { 82 assert(sizeof(uuid_t) == 16); 83#if defined(MS_WINDOWS) 84 int has_uuid_generate_time_safe = 0; 85#elif defined(HAVE_UUID_GENERATE_TIME_SAFE) 86 int has_uuid_generate_time_safe = 1; 87#else 88 int has_uuid_generate_time_safe = 0; 89#endif 90 if (PyModule_AddIntConstant(module, "has_uuid_generate_time_safe", 91 has_uuid_generate_time_safe) < 0) { 92 return -1; 93 } 94 return 0; 95} 96 97static PyMethodDef uuid_methods[] = { 98#if defined(HAVE_UUID_UUID_H) || defined(HAVE_UUID_H) 99 {"generate_time_safe", py_uuid_generate_time_safe, METH_NOARGS, NULL}, 100#endif 101#if defined(MS_WINDOWS) 102 {"UuidCreate", py_UuidCreate, METH_NOARGS, NULL}, 103#endif 104 {NULL, NULL, 0, NULL} /* sentinel */ 105}; 106 107static PyModuleDef_Slot uuid_slots[] = { 108 {Py_mod_exec, uuid_exec}, 109 {0, NULL} 110}; 111 112static struct PyModuleDef uuidmodule = { 113 PyModuleDef_HEAD_INIT, 114 .m_name = "_uuid", 115 .m_size = 0, 116 .m_methods = uuid_methods, 117 .m_slots = uuid_slots, 118}; 119 120PyMODINIT_FUNC 121PyInit__uuid(void) 122{ 123 return PyModuleDef_Init(&uuidmodule); 124} 125