Branch data Line data Source code
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 : :
23 : : static PyObject *
24 : 1017 : py_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 : 1017 : res = uuid_generate_time_safe(uuid);
32 : 1017 : 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 : :
51 : : static PyObject *
52 : : py_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 : :
80 : : static int
81 : 13 : uuid_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 : 13 : int has_uuid_generate_time_safe = 1;
87 : : #else
88 : : int has_uuid_generate_time_safe = 0;
89 : : #endif
90 [ - + ]: 13 : if (PyModule_AddIntConstant(module, "has_uuid_generate_time_safe",
91 : : has_uuid_generate_time_safe) < 0) {
92 : 0 : return -1;
93 : : }
94 : 13 : return 0;
95 : : }
96 : :
97 : : static 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 : :
107 : : static PyModuleDef_Slot uuid_slots[] = {
108 : : {Py_mod_exec, uuid_exec},
109 : : {0, NULL}
110 : : };
111 : :
112 : : static 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 : :
120 : : PyMODINIT_FUNC
121 : 13 : PyInit__uuid(void)
122 : : {
123 : 13 : return PyModuleDef_Init(&uuidmodule);
124 : : }
|