blob: 3f33e22a055c6dc61181e913d7b03437907a2f8b [file] [log] [blame]
ziheng6ffd9b02019-06-25 01:59:51 +08001/*
Steve Dowerd6b727e2020-05-12 23:32:32 +01002 * Python UUID module that wraps libuuid or Windows rpcrt4.dll.
ziheng6ffd9b02019-06-25 01:59:51 +08003 * DCE compatible Universally Unique Identifier library.
4 */
5
Antoine Pitroua106aec2017-09-28 23:03:06 +02006#define PY_SSIZE_T_CLEAN
7
8#include "Python.h"
Michael Felt0d3ccb42017-12-30 22:39:20 +01009#ifdef HAVE_UUID_UUID_H
Antoine Pitroua106aec2017-09-28 23:03:06 +020010#include <uuid/uuid.h>
ziheng6ffd9b02019-06-25 01:59:51 +080011#elif defined(HAVE_UUID_H)
Michael Felt0d3ccb42017-12-30 22:39:20 +010012#include <uuid.h>
13#endif
Antoine Pitroua106aec2017-09-28 23:03:06 +020014
Steve Dowerd6b727e2020-05-12 23:32:32 +010015#ifdef MS_WINDOWS
16#include <rpc.h>
17#endif
18
19#ifndef MS_WINDOWS
20
Antoine Pitroua106aec2017-09-28 23:03:06 +020021static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +053022py_uuid_generate_time_safe(PyObject *Py_UNUSED(context),
23 PyObject *Py_UNUSED(ignored))
Antoine Pitroua106aec2017-09-28 23:03:06 +020024{
Michael Felt0d3ccb42017-12-30 22:39:20 +010025 uuid_t uuid;
Berker Peksag9a10ff42017-11-08 23:09:16 +030026#ifdef HAVE_UUID_GENERATE_TIME_SAFE
Antoine Pitroua106aec2017-09-28 23:03:06 +020027 int res;
28
Michael Felt0d3ccb42017-12-30 22:39:20 +010029 res = uuid_generate_time_safe(uuid);
30 return Py_BuildValue("y#i", (const char *) uuid, sizeof(uuid), res);
Serhiy Storchaka17d88302018-05-25 01:45:09 +030031#elif defined(HAVE_UUID_CREATE)
David Carlierb4ebaa72018-01-09 19:38:07 +000032 uint32_t status;
Michael Felt0d3ccb42017-12-30 22:39:20 +010033 uuid_create(&uuid, &status);
Serhiy Storchaka17d88302018-05-25 01:45:09 +030034# if defined(HAVE_UUID_ENC_BE)
35 unsigned char buf[sizeof(uuid)];
36 uuid_enc_be(buf, &uuid);
37 return Py_BuildValue("y#i", buf, sizeof(uuid), (int) status);
38# else
Michael Felt0d3ccb42017-12-30 22:39:20 +010039 return Py_BuildValue("y#i", (const char *) &uuid, sizeof(uuid), (int) status);
Steve Dowerd6b727e2020-05-12 23:32:32 +010040# endif /* HAVE_UUID_CREATE */
41#else /* HAVE_UUID_GENERATE_TIME_SAFE */
Michael Felt0d3ccb42017-12-30 22:39:20 +010042 uuid_generate_time(uuid);
43 return Py_BuildValue("y#O", (const char *) uuid, sizeof(uuid), Py_None);
Steve Dowerd6b727e2020-05-12 23:32:32 +010044#endif /* HAVE_UUID_GENERATE_TIME_SAFE */
Antoine Pitroua106aec2017-09-28 23:03:06 +020045}
46
Steve Dowerd6b727e2020-05-12 23:32:32 +010047#else /* MS_WINDOWS */
48
49static PyObject *
50py_UuidCreate(PyObject *Py_UNUSED(context),
51 PyObject *Py_UNUSED(ignored))
52{
53 UUID uuid;
54 RPC_STATUS res;
55
56 Py_BEGIN_ALLOW_THREADS
57 res = UuidCreateSequential(&uuid);
58 Py_END_ALLOW_THREADS
59
60 switch (res) {
61 case RPC_S_OK:
62 case RPC_S_UUID_LOCAL_ONLY:
63 case RPC_S_UUID_NO_ADDRESS:
64 /*
65 All success codes, but the latter two indicate that the UUID is random
66 rather than based on the MAC address. If the OS can't figure this out,
67 neither can we, so we'll take it anyway.
68 */
69 return Py_BuildValue("y#", (const char *)&uuid, sizeof(uuid));
70 }
71 PyErr_SetFromWindowsErr(res);
72 return NULL;
73}
74
75#endif /* MS_WINDOWS */
76
77
Dong-hee Na1cb763b2020-03-31 21:43:47 +090078static int
79uuid_exec(PyObject *module) {
Antoine Pitroua106aec2017-09-28 23:03:06 +020080 assert(sizeof(uuid_t) == 16);
Steve Dowerd6b727e2020-05-12 23:32:32 +010081#if defined(MS_WINDOWS)
82 int has_uuid_generate_time_safe = 0;
83#elif defined(HAVE_UUID_GENERATE_TIME_SAFE)
Victor Stinner4337a0d2017-10-02 07:57:59 -070084 int has_uuid_generate_time_safe = 1;
85#else
86 int has_uuid_generate_time_safe = 0;
87#endif
Dong-hee Na1cb763b2020-03-31 21:43:47 +090088 if (PyModule_AddIntConstant(module, "has_uuid_generate_time_safe",
Victor Stinner4337a0d2017-10-02 07:57:59 -070089 has_uuid_generate_time_safe) < 0) {
Dong-hee Na1cb763b2020-03-31 21:43:47 +090090 return -1;
Victor Stinner4337a0d2017-10-02 07:57:59 -070091 }
Dong-hee Na1cb763b2020-03-31 21:43:47 +090092 return 0;
93}
Victor Stinner4337a0d2017-10-02 07:57:59 -070094
Dong-hee Na1cb763b2020-03-31 21:43:47 +090095static PyMethodDef uuid_methods[] = {
Steve Dowerd6b727e2020-05-12 23:32:32 +010096#if defined(HAVE_UUID_UUID_H) || defined(HAVE_UUID_H)
Dong-hee Na1cb763b2020-03-31 21:43:47 +090097 {"generate_time_safe", py_uuid_generate_time_safe, METH_NOARGS, NULL},
Steve Dowerd6b727e2020-05-12 23:32:32 +010098#endif
99#if defined(MS_WINDOWS)
100 {"UuidCreate", py_UuidCreate, METH_NOARGS, NULL},
101#endif
Dong-hee Na1cb763b2020-03-31 21:43:47 +0900102 {NULL, NULL, 0, NULL} /* sentinel */
103};
104
105static PyModuleDef_Slot uuid_slots[] = {
106 {Py_mod_exec, uuid_exec},
107 {0, NULL}
108};
109
110static struct PyModuleDef uuidmodule = {
111 PyModuleDef_HEAD_INIT,
112 .m_name = "_uuid",
113 .m_size = 0,
114 .m_methods = uuid_methods,
115 .m_slots = uuid_slots,
116};
117
118PyMODINIT_FUNC
119PyInit__uuid(void)
120{
121 return PyModuleDef_Init(&uuidmodule);
Antoine Pitroua106aec2017-09-28 23:03:06 +0200122}