17db96d56Sopenharmony_ci/*
27db96d56Sopenharmony_ci * Python UUID module that wraps libuuid or Windows rpcrt4.dll.
37db96d56Sopenharmony_ci * DCE compatible Universally Unique Identifier library.
47db96d56Sopenharmony_ci */
57db96d56Sopenharmony_ci
67db96d56Sopenharmony_ci#define PY_SSIZE_T_CLEAN
77db96d56Sopenharmony_ci
87db96d56Sopenharmony_ci#include "Python.h"
97db96d56Sopenharmony_ci#if defined(HAVE_UUID_H)
107db96d56Sopenharmony_ci  // AIX, FreeBSD, libuuid with pkgconf
117db96d56Sopenharmony_ci  #include <uuid.h>
127db96d56Sopenharmony_ci#elif defined(HAVE_UUID_UUID_H)
137db96d56Sopenharmony_ci  // libuuid without pkgconf
147db96d56Sopenharmony_ci  #include <uuid/uuid.h>
157db96d56Sopenharmony_ci#endif
167db96d56Sopenharmony_ci
177db96d56Sopenharmony_ci#ifdef MS_WINDOWS
187db96d56Sopenharmony_ci#include <rpc.h>
197db96d56Sopenharmony_ci#endif
207db96d56Sopenharmony_ci
217db96d56Sopenharmony_ci#ifndef MS_WINDOWS
227db96d56Sopenharmony_ci
237db96d56Sopenharmony_cistatic PyObject *
247db96d56Sopenharmony_cipy_uuid_generate_time_safe(PyObject *Py_UNUSED(context),
257db96d56Sopenharmony_ci                           PyObject *Py_UNUSED(ignored))
267db96d56Sopenharmony_ci{
277db96d56Sopenharmony_ci    uuid_t uuid;
287db96d56Sopenharmony_ci#ifdef HAVE_UUID_GENERATE_TIME_SAFE
297db96d56Sopenharmony_ci    int res;
307db96d56Sopenharmony_ci
317db96d56Sopenharmony_ci    res = uuid_generate_time_safe(uuid);
327db96d56Sopenharmony_ci    return Py_BuildValue("y#i", (const char *) uuid, sizeof(uuid), res);
337db96d56Sopenharmony_ci#elif defined(HAVE_UUID_CREATE)
347db96d56Sopenharmony_ci    uint32_t status;
357db96d56Sopenharmony_ci    uuid_create(&uuid, &status);
367db96d56Sopenharmony_ci# if defined(HAVE_UUID_ENC_BE)
377db96d56Sopenharmony_ci    unsigned char buf[sizeof(uuid)];
387db96d56Sopenharmony_ci    uuid_enc_be(buf, &uuid);
397db96d56Sopenharmony_ci    return Py_BuildValue("y#i", buf, sizeof(uuid), (int) status);
407db96d56Sopenharmony_ci# else
417db96d56Sopenharmony_ci    return Py_BuildValue("y#i", (const char *) &uuid, sizeof(uuid), (int) status);
427db96d56Sopenharmony_ci# endif /* HAVE_UUID_CREATE */
437db96d56Sopenharmony_ci#else /* HAVE_UUID_GENERATE_TIME_SAFE */
447db96d56Sopenharmony_ci    uuid_generate_time(uuid);
457db96d56Sopenharmony_ci    return Py_BuildValue("y#O", (const char *) uuid, sizeof(uuid), Py_None);
467db96d56Sopenharmony_ci#endif /* HAVE_UUID_GENERATE_TIME_SAFE */
477db96d56Sopenharmony_ci}
487db96d56Sopenharmony_ci
497db96d56Sopenharmony_ci#else /* MS_WINDOWS */
507db96d56Sopenharmony_ci
517db96d56Sopenharmony_cistatic PyObject *
527db96d56Sopenharmony_cipy_UuidCreate(PyObject *Py_UNUSED(context),
537db96d56Sopenharmony_ci              PyObject *Py_UNUSED(ignored))
547db96d56Sopenharmony_ci{
557db96d56Sopenharmony_ci    UUID uuid;
567db96d56Sopenharmony_ci    RPC_STATUS res;
577db96d56Sopenharmony_ci
587db96d56Sopenharmony_ci    Py_BEGIN_ALLOW_THREADS
597db96d56Sopenharmony_ci    res = UuidCreateSequential(&uuid);
607db96d56Sopenharmony_ci    Py_END_ALLOW_THREADS
617db96d56Sopenharmony_ci
627db96d56Sopenharmony_ci    switch (res) {
637db96d56Sopenharmony_ci    case RPC_S_OK:
647db96d56Sopenharmony_ci    case RPC_S_UUID_LOCAL_ONLY:
657db96d56Sopenharmony_ci    case RPC_S_UUID_NO_ADDRESS:
667db96d56Sopenharmony_ci        /*
677db96d56Sopenharmony_ci        All success codes, but the latter two indicate that the UUID is random
687db96d56Sopenharmony_ci        rather than based on the MAC address. If the OS can't figure this out,
697db96d56Sopenharmony_ci        neither can we, so we'll take it anyway.
707db96d56Sopenharmony_ci        */
717db96d56Sopenharmony_ci        return Py_BuildValue("y#", (const char *)&uuid, sizeof(uuid));
727db96d56Sopenharmony_ci    }
737db96d56Sopenharmony_ci    PyErr_SetFromWindowsErr(res);
747db96d56Sopenharmony_ci    return NULL;
757db96d56Sopenharmony_ci}
767db96d56Sopenharmony_ci
777db96d56Sopenharmony_ci#endif /* MS_WINDOWS */
787db96d56Sopenharmony_ci
797db96d56Sopenharmony_ci
807db96d56Sopenharmony_cistatic int
817db96d56Sopenharmony_ciuuid_exec(PyObject *module) {
827db96d56Sopenharmony_ci    assert(sizeof(uuid_t) == 16);
837db96d56Sopenharmony_ci#if defined(MS_WINDOWS)
847db96d56Sopenharmony_ci    int has_uuid_generate_time_safe = 0;
857db96d56Sopenharmony_ci#elif defined(HAVE_UUID_GENERATE_TIME_SAFE)
867db96d56Sopenharmony_ci    int has_uuid_generate_time_safe = 1;
877db96d56Sopenharmony_ci#else
887db96d56Sopenharmony_ci    int has_uuid_generate_time_safe = 0;
897db96d56Sopenharmony_ci#endif
907db96d56Sopenharmony_ci    if (PyModule_AddIntConstant(module, "has_uuid_generate_time_safe",
917db96d56Sopenharmony_ci                                has_uuid_generate_time_safe) < 0) {
927db96d56Sopenharmony_ci        return -1;
937db96d56Sopenharmony_ci    }
947db96d56Sopenharmony_ci    return 0;
957db96d56Sopenharmony_ci}
967db96d56Sopenharmony_ci
977db96d56Sopenharmony_cistatic PyMethodDef uuid_methods[] = {
987db96d56Sopenharmony_ci#if defined(HAVE_UUID_UUID_H) || defined(HAVE_UUID_H)
997db96d56Sopenharmony_ci    {"generate_time_safe", py_uuid_generate_time_safe, METH_NOARGS, NULL},
1007db96d56Sopenharmony_ci#endif
1017db96d56Sopenharmony_ci#if defined(MS_WINDOWS)
1027db96d56Sopenharmony_ci    {"UuidCreate", py_UuidCreate, METH_NOARGS, NULL},
1037db96d56Sopenharmony_ci#endif
1047db96d56Sopenharmony_ci    {NULL, NULL, 0, NULL}           /* sentinel */
1057db96d56Sopenharmony_ci};
1067db96d56Sopenharmony_ci
1077db96d56Sopenharmony_cistatic PyModuleDef_Slot uuid_slots[] = {
1087db96d56Sopenharmony_ci    {Py_mod_exec, uuid_exec},
1097db96d56Sopenharmony_ci    {0, NULL}
1107db96d56Sopenharmony_ci};
1117db96d56Sopenharmony_ci
1127db96d56Sopenharmony_cistatic struct PyModuleDef uuidmodule = {
1137db96d56Sopenharmony_ci    PyModuleDef_HEAD_INIT,
1147db96d56Sopenharmony_ci    .m_name = "_uuid",
1157db96d56Sopenharmony_ci    .m_size = 0,
1167db96d56Sopenharmony_ci    .m_methods = uuid_methods,
1177db96d56Sopenharmony_ci    .m_slots = uuid_slots,
1187db96d56Sopenharmony_ci};
1197db96d56Sopenharmony_ci
1207db96d56Sopenharmony_ciPyMODINIT_FUNC
1217db96d56Sopenharmony_ciPyInit__uuid(void)
1227db96d56Sopenharmony_ci{
1237db96d56Sopenharmony_ci    return PyModuleDef_Init(&uuidmodule);
1247db96d56Sopenharmony_ci}
125