chiark / gitweb /
systemd-python: fix memory leak in _reader and minor bugs
[elogind.git] / src / python-systemd / id128.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Zbigniew JÄ™drzejewski-Szmek <zbyszek@in.waw.pl>
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <Python.h>
23
24 #include <systemd/sd-messages.h>
25
26 #define _cleanup_Py_DECREF_ __attribute__((cleanup(cleanup_Py_DECREFp)))
27
28 static void cleanup_Py_DECREFp(PyObject **p) {
29         if (!*p)
30                 return;
31
32         Py_DECREF(*p);
33 }
34
35 PyDoc_STRVAR(module__doc__,
36              "Python interface to the libsystemd-id128 library.\n\n"
37              "Provides SD_MESSAGE_* constants and functions to query and generate\n"
38              "128bit unique identifiers."
39 );
40
41 PyDoc_STRVAR(randomize__doc__,
42              "randomize() -> UUID\n\n"
43              "Return a new random 128bit unique identifier.\n"
44              "Wraps sd_id128_randomize(3)."
45 );
46
47 PyDoc_STRVAR(get_machine__doc__,
48              "get_machine() -> UUID\n\n"
49              "Return a 128bit unique identifier for this machine.\n"
50              "Wraps sd_id128_get_machine(3)."
51 );
52
53 PyDoc_STRVAR(get_boot__doc__,
54              "get_boot() -> UUID\n\n"
55              "Return a 128bit unique identifier for this boot.\n"
56              "Wraps sd_id128_get_boot(3)."
57 );
58
59 static PyObject* make_uuid(sd_id128_t id) {
60         PyObject _cleanup_Py_DECREF_
61                 *uuid = NULL, *UUID = NULL, *bytes = NULL,
62                 *args = NULL, *kwargs = NULL, *obj = NULL;
63
64         uuid = PyImport_ImportModule("uuid");
65         if (!uuid)
66                 return NULL;
67
68         UUID = PyObject_GetAttrString(uuid, "UUID");
69         bytes = PyBytes_FromStringAndSize((const char*) &id.bytes, sizeof(id.bytes));
70         args = Py_BuildValue("()");
71         kwargs = PyDict_New();
72         if (!UUID || !bytes || !args || !kwargs)
73                 return NULL;
74
75         if (PyDict_SetItemString(kwargs, "bytes", bytes) < 0)
76                 return NULL;
77
78         return PyObject_Call(UUID, args, kwargs);
79 }
80
81 #define helper(name)                                                    \
82         static PyObject *name(PyObject *self, PyObject *args) {         \
83                 sd_id128_t id;                                          \
84                 int r;                                                  \
85                                                                         \
86                 assert(args == NULL);                                   \
87                                                                         \
88                 r = sd_id128_##name(&id);                               \
89                 if (r < 0) {                                            \
90                         errno = -r;                                     \
91                         return PyErr_SetFromErrno(PyExc_IOError);       \
92                 }                                                       \
93                                                                         \
94                 return make_uuid(id);                                   \
95         }
96
97 helper(randomize)
98 helper(get_machine)
99 helper(get_boot)
100
101 static PyMethodDef methods[] = {
102         { "randomize", randomize, METH_NOARGS, randomize__doc__},
103         { "get_machine", get_machine, METH_NOARGS, get_machine__doc__},
104         { "get_boot", get_boot, METH_NOARGS, get_boot__doc__},
105         { NULL, NULL, 0, NULL }        /* Sentinel */
106 };
107
108 static int add_id(PyObject *module, const char* name, sd_id128_t id) {
109         PyObject _cleanup_Py_DECREF_ *obj;
110
111         obj = make_uuid(id);
112         if (!obj)
113                 return -1;
114
115         return PyObject_SetAttrString(module, name, obj);
116 }
117
118 #pragma GCC diagnostic push
119 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
120
121 #if PY_MAJOR_VERSION < 3
122
123 PyMODINIT_FUNC initid128(void) {
124         PyObject *m;
125
126         m = Py_InitModule3("id128", methods, module__doc__);
127         if (m == NULL)
128                 return;
129
130 #include "id128-constants.h"
131 }
132
133 #else
134
135 static struct PyModuleDef module = {
136         PyModuleDef_HEAD_INIT,
137         "id128", /* name of module */
138         module__doc__, /* module documentation, may be NULL */
139         0, /* size of per-interpreter state of the module */
140         methods
141 };
142
143 PyMODINIT_FUNC PyInit_id128(void) {
144         PyObject *m;
145
146         m = PyModule_Create(&module);
147         if (m == NULL)
148                 return NULL;
149
150 #include "id128-constants.h"
151
152         return m;
153 }
154
155 #endif
156
157 #pragma GCC diagnostic pop