| /* | |
| * Python UUID module that wraps libuuid or Windows rpcrt4.dll. | |
| * DCE compatible Universally Unique Identifier library. | |
| */ | |
| // Need limited C API version 3.13 for Py_mod_gil | |
| #include "pyconfig.h" // Py_GIL_DISABLED | |
| #ifndef Py_GIL_DISABLED | |
| # define Py_LIMITED_API 0x030d0000 | |
| #endif | |
| #include "Python.h" | |
| #if defined(HAVE_UUID_H) | |
| // AIX, FreeBSD, libuuid with pkgconf | |
| #include <uuid.h> | |
| #elif defined(HAVE_UUID_UUID_H) | |
| // libuuid without pkgconf | |
| #include <uuid/uuid.h> | |
| #endif | |
| #ifdef MS_WINDOWS | |
| #include <rpc.h> | |
| #ifndef RPC_S_OK | |
| #define RPC_S_OK 0L | |
| #endif | |
| #endif | |
| #ifndef MS_WINDOWS | |
| static PyObject * | |
| py_uuid_generate_time_safe(PyObject *Py_UNUSED(context), | |
| PyObject *Py_UNUSED(ignored)) | |
| { | |
| uuid_t uuid; | |
| #ifdef HAVE_UUID_GENERATE_TIME_SAFE | |
| int res; | |
| res = uuid_generate_time_safe(uuid); | |
| return Py_BuildValue("y#i", (const char *) uuid, sizeof(uuid), res); | |
| #elif defined(HAVE_UUID_CREATE) | |
| uint32_t status; | |
| uuid_create(&uuid, &status); | |
| # if defined(HAVE_UUID_ENC_BE) | |
| unsigned char buf[sizeof(uuid)]; | |
| uuid_enc_be(buf, &uuid); | |
| return Py_BuildValue("y#i", buf, sizeof(uuid), (int) status); | |
| # else | |
| return Py_BuildValue("y#i", (const char *) &uuid, sizeof(uuid), (int) status); | |
| # endif /* HAVE_UUID_CREATE */ | |
| #else /* HAVE_UUID_GENERATE_TIME_SAFE */ | |
| uuid_generate_time(uuid); | |
| return Py_BuildValue("y#O", (const char *) uuid, sizeof(uuid), Py_None); | |
| #endif /* HAVE_UUID_GENERATE_TIME_SAFE */ | |
| } | |
| #else /* MS_WINDOWS */ | |
| static PyObject * | |
| py_UuidCreate(PyObject *Py_UNUSED(context), | |
| PyObject *Py_UNUSED(ignored)) | |
| { | |
| UUID uuid; | |
| RPC_STATUS res; | |
| Py_BEGIN_ALLOW_THREADS | |
| res = UuidCreateSequential(&uuid); | |
| Py_END_ALLOW_THREADS | |
| switch (res) { | |
| case RPC_S_OK: | |
| case RPC_S_UUID_LOCAL_ONLY: | |
| case RPC_S_UUID_NO_ADDRESS: | |
| /* | |
| All success codes, but the latter two indicate that the UUID is random | |
| rather than based on the MAC address. If the OS can't figure this out, | |
| neither can we, so we'll take it anyway. | |
| */ | |
| return Py_BuildValue("y#", (const char *)&uuid, sizeof(uuid)); | |
| } | |
| PyErr_SetFromWindowsErr(res); | |
| return NULL; | |
| } | |
| static int | |
| py_windows_has_stable_node(void) | |
| { | |
| UUID uuid; | |
| RPC_STATUS res; | |
| Py_BEGIN_ALLOW_THREADS | |
| res = UuidCreateSequential(&uuid); | |
| Py_END_ALLOW_THREADS | |
| return res == RPC_S_OK; | |
| } | |
| #endif /* MS_WINDOWS */ | |
| static int | |
| uuid_exec(PyObject *module) | |
| { | |
| #define ADD_INT(NAME, VALUE) \ | |
| do { \ | |
| if (PyModule_AddIntConstant(module, (NAME), (VALUE)) < 0) { \ | |
| return -1; \ | |
| } \ | |
| } while (0) | |
| assert(sizeof(uuid_t) == 16); | |
| #if defined(MS_WINDOWS) | |
| ADD_INT("has_uuid_generate_time_safe", 0); | |
| #elif defined(HAVE_UUID_GENERATE_TIME_SAFE) | |
| ADD_INT("has_uuid_generate_time_safe", 1); | |
| #else | |
| ADD_INT("has_uuid_generate_time_safe", 0); | |
| #endif | |
| #if defined(MS_WINDOWS) | |
| ADD_INT("has_stable_extractable_node", py_windows_has_stable_node()); | |
| #elif defined(HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC) | |
| ADD_INT("has_stable_extractable_node", 1); | |
| #else | |
| ADD_INT("has_stable_extractable_node", 0); | |
| #endif | |
| #undef ADD_INT | |
| return 0; | |
| } | |
| static PyMethodDef uuid_methods[] = { | |
| #if defined(HAVE_UUID_UUID_H) || defined(HAVE_UUID_H) | |
| {"generate_time_safe", py_uuid_generate_time_safe, METH_NOARGS, NULL}, | |
| #endif | |
| #if defined(MS_WINDOWS) | |
| {"UuidCreate", py_UuidCreate, METH_NOARGS, NULL}, | |
| #endif | |
| {NULL, NULL, 0, NULL} /* sentinel */ | |
| }; | |
| static PyModuleDef_Slot uuid_slots[] = { | |
| {Py_mod_exec, uuid_exec}, | |
| {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, | |
| {Py_mod_gil, Py_MOD_GIL_NOT_USED}, | |
| {0, NULL} | |
| }; | |
| static struct PyModuleDef uuidmodule = { | |
| PyModuleDef_HEAD_INIT, | |
| .m_name = "_uuid", | |
| .m_size = 0, | |
| .m_methods = uuid_methods, | |
| .m_slots = uuid_slots, | |
| }; | |
| PyMODINIT_FUNC | |
| PyInit__uuid(void) | |
| { | |
| return PyModuleDef_Init(&uuidmodule); | |
| } |