]> git.ipfire.org Git - thirdparty/util-linux.git/blame - libmount/python/pylibmount.c
libmount: add support for verity devices via libcryptsetup
[thirdparty/util-linux.git] / libmount / python / pylibmount.c
CommitLineData
813683a3
OO
1/*
2 * Python bindings for the libmount library.
3 *
4 * Copyright (C) 2013, Red Hat, Inc. All rights reserved.
5 * Written by Ondrej Oprala and Karel Zak
6 *
7 * This file is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 3 of the License, or (at your option) any later version.
11 *
12 * This file is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this file; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21#include "pylibmount.h"
22
23/* Libmount-specific Exception class */
24PyObject *LibmountError;
b7e47ac1
KZ
25int pylibmount_debug_mask;
26
813683a3
OO
27PyObject *UL_IncRef(void *killme)
28{
29 Py_INCREF(killme);
30 return killme;
31}
32
46407453
OO
33void PyFree(void *o)
34{
35#if PY_MAJOR_VERSION >= 3
36 Py_TYPE(o)->tp_free((PyObject *)o);
37#else
38 ((PyObject *)o)->ob_type->tp_free((PyObject *)o);
39#endif
40}
41
813683a3
OO
42/* Demultiplexer for various possible error conditions across the libmount library */
43void *UL_RaiseExc(int e)
44{
45 /* TODO: Do we need to deal with -1/1? */
46 switch (e) {
47 case ENOMEM:
48 PyErr_SetString(PyExc_MemoryError, strerror(e));
49 break;
50 case EINVAL:
51 PyErr_SetString(PyExc_TypeError, strerror(e));
52 break;
53 /* libmount-specific errors */
54 case MNT_ERR_APPLYFLAGS:
55 PyErr_SetString(LibmountError, "Failed to apply MS_PROPAGATION flags");
56 break;
57 case MNT_ERR_MOUNTOPT:
58 PyErr_SetString(LibmountError, "Failed to parse/use userspace mount options");
59 break;
60 case MNT_ERR_NOFSTAB:
61 PyErr_SetString(LibmountError, "Failed to detect filesystem type");
62 break;
63 case MNT_ERR_NOFSTYPE:
64 PyErr_SetString(LibmountError, "Required mount source undefined");
65 break;
66 case MNT_ERR_NOSOURCE:
67 PyErr_SetString(LibmountError, "Loopdev setup failed");
68 break;
69 case MNT_ERR_AMBIFS:
70 PyErr_SetString(LibmountError, "Libblkid detected more filesystems on the device");
71 break;
72 /* some other errno */
73 default:
74 PyErr_SetString(PyExc_Exception, strerror(e));
75 break;
76 }
77 return NULL;
78}
79
80/*
81 * General functions
82 */
83PyObject *PyObjectResultInt(int i)
84{
85 PyObject *result = Py_BuildValue("i", i);
86 if (!result)
87 PyErr_SetString(PyExc_RuntimeError, CONSTRUCT_ERR);
88 return result;
89}
90
91PyObject *PyObjectResultStr(const char *s)
92{
5d324c6b 93 PyObject *result;
813683a3
OO
94 if (!s)
95 /* TODO: maybe lie about it and return "":
96 * which would allow for
97 * fs = libmount.Fs()
98 * fs.comment += "comment"
99 return Py_BuildValue("s", ""); */
100 Py_RETURN_NONE;
5d324c6b 101 result = Py_BuildValue("s", s);
813683a3
OO
102 if (!result)
103 PyErr_SetString(PyExc_RuntimeError, CONSTRUCT_ERR);
104 return result;
105}
106
46407453 107/* wrapper around a common use case for PyUnicode_AsASCIIString() */
813683a3
OO
108char *pystos(PyObject *pys)
109{
46407453
OO
110#if PY_MAJOR_VERSION >= 3
111 if (!PyUnicode_Check(pys)) {
112 PyErr_SetString(PyExc_TypeError, ARG_ERR);
113 return NULL;
114 }
115 return (char *)PyUnicode_1BYTE_DATA(pys);
116#else
813683a3
OO
117 if (!PyString_Check(pys)) {
118 PyErr_SetString(PyExc_TypeError, ARG_ERR);
119 return NULL;
120 }
121 return PyString_AsString(pys);
46407453 122#endif
813683a3
OO
123}
124
125/*
126 * the libmount module
127 */
128#define PYLIBMOUNT_DESC \
129 "Python API for the util-linux libmount library.\n\n" \
130 "Please note that none of the classes' attributes may be deleted.\n" \
131 "This is not a complete mapping to the libmount C API, nor is it\n" \
132 "attempting to be one.\n" "Iterator functions only allow forward\n" \
9e930041 133 "iteration for now. Context.get_{user_,}mflags() differs from the C API\n" \
813683a3
OO
134 "and returns the flags directly. Fs.get_tag() differs from the C API\n" \
135 "and returns a (tag, value) tuple. Every attribute is \"filtered\"" \
136 "through appropriate getters/setters, no values are set directly."
137
46407453
OO
138
139struct module_state {
140 PyObject *error;
813683a3
OO
141};
142
46407453
OO
143#if PY_MAJOR_VERSION >= 3
144#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
145#else
146#define GETSTATE(m) (&_state)
147static struct module_state _state;
813683a3 148#endif
46407453
OO
149
150static PyObject *
151error_out(PyObject *m __attribute__((unused))) {
152 struct module_state *st = GETSTATE(m);
153 PyErr_SetString(st->error, "something bad happened");
154 return NULL;
155}
156
157static PyMethodDef pylibmount_methods[] = {
158 {"error_out", (PyCFunction)error_out, METH_NOARGS, NULL},
159 {NULL, NULL}
160};
161
162#if PY_MAJOR_VERSION >= 3
163
164static int pylibmount_traverse(PyObject *m, visitproc visit, void *arg) {
165 Py_VISIT(GETSTATE(m)->error);
166 return 0;
167}
168
169static int pylibmount_clear(PyObject *m) {
170 Py_CLEAR(GETSTATE(m)->error);
171 return 0;
172}
173
174static struct PyModuleDef moduledef = {
175 PyModuleDef_HEAD_INIT,
176 "pylibmount",
177 NULL,
178 sizeof(struct module_state),
179 pylibmount_methods,
180 NULL,
181 pylibmount_traverse,
182 pylibmount_clear,
183 NULL
184};
185#define INITERROR return NULL
186PyObject * PyInit_pylibmount(void);
187PyObject * PyInit_pylibmount(void)
188#else
189#define INITERROR return
190# ifndef PyMODINIT_FUNC
191# define PyMODINIT_FUNC void
192# endif
813683a3
OO
193PyMODINIT_FUNC initpylibmount(void);
194PyMODINIT_FUNC initpylibmount(void)
46407453 195#endif
813683a3 196{
46407453
OO
197#if PY_MAJOR_VERSION >= 3
198 PyObject *m = PyModule_Create(&moduledef);
199#else
200 PyObject *m = Py_InitModule3("pylibmount", pylibmount_methods, PYLIBMOUNT_DESC);
201#endif
813683a3
OO
202
203 if (!m)
46407453 204 INITERROR;
b7e47ac1
KZ
205 /*
206 * init debug stuff
207 */
208 if (!(pylibmount_debug_mask & PYMNT_DEBUG_INIT)) {
209 char *str = getenv("PYLIBMOUNT_DEBUG");
210
211 pylibmount_debug_mask = 0;
212 if (str)
87918040 213 pylibmount_debug_mask = strtoul(str, NULL, 0);
813683a3 214
b7e47ac1
KZ
215 pylibmount_debug_mask |= PYMNT_DEBUG_INIT;
216 }
217
218 if (pylibmount_debug_mask && pylibmount_debug_mask != PYMNT_DEBUG_INIT)
219 DBG(INIT, pymnt_debug("library debug mask: 0x%04x",
220 pylibmount_debug_mask));
221 mnt_init_debug(0);
20b222ec 222
b7e47ac1
KZ
223 /*
224 * Add module objects
225 */
813683a3
OO
226 LibmountError = PyErr_NewException("libmount.Error", NULL, NULL);
227 Py_INCREF(LibmountError);
228 PyModule_AddObject(m, "Error", (PyObject *)LibmountError);
229
20b222ec
KZ
230 FS_AddModuleObject(m);
231 Table_AddModuleObject(m);
a5b3be92 232#ifdef __linux__
20b222ec 233 Context_AddModuleObject(m);
a5b3be92 234#endif
813683a3
OO
235
236 /*
237 * mount(8) userspace options masks (MNT_MAP_USERSPACE map)
238 */
239 PyModule_AddIntConstant(m, "MNT_MS_COMMENT", MNT_MS_COMMENT);
240 PyModule_AddIntConstant(m, "MNT_MS_GROUP", MNT_MS_GROUP);
241 PyModule_AddIntConstant(m, "MNT_MS_HELPER", MNT_MS_HELPER);
242 PyModule_AddIntConstant(m, "MNT_MS_LOOP", MNT_MS_LOOP);
243 PyModule_AddIntConstant(m, "MNT_MS_NETDEV", MNT_MS_NETDEV);
244 PyModule_AddIntConstant(m, "MNT_MS_NOAUTO", MNT_MS_NOAUTO);
245 PyModule_AddIntConstant(m, "MNT_MS_NOFAIL", MNT_MS_NOFAIL);
246 PyModule_AddIntConstant(m, "MNT_MS_OFFSET", MNT_MS_OFFSET);
247 PyModule_AddIntConstant(m, "MNT_MS_OWNER", MNT_MS_OWNER);
248 PyModule_AddIntConstant(m, "MNT_MS_SIZELIMIT", MNT_MS_SIZELIMIT);
249 PyModule_AddIntConstant(m, "MNT_MS_ENCRYPTION", MNT_MS_ENCRYPTION);
250 PyModule_AddIntConstant(m, "MNT_MS_UHELPER", MNT_MS_UHELPER);
251 PyModule_AddIntConstant(m, "MNT_MS_USER", MNT_MS_USER);
252 PyModule_AddIntConstant(m, "MNT_MS_USERS", MNT_MS_USERS);
253 PyModule_AddIntConstant(m, "MNT_MS_XCOMMENT", MNT_MS_XCOMMENT);
e6a49887
LB
254 PyModule_AddIntConstant(m, "MNT_MS_HASH_DEVICE", MNT_MS_HASH_DEVICE);
255 PyModule_AddIntConstant(m, "MNT_MS_ROOT_HASH", MNT_MS_ROOT_HASH);
256 PyModule_AddIntConstant(m, "MNT_MS_HASH_OFFSET", MNT_MS_HASH_OFFSET);
813683a3
OO
257
258 /*
259 * mount(2) MS_* masks (MNT_MAP_LINUX map)
260 */
261 PyModule_AddIntConstant(m, "MS_BIND", MS_BIND);
262 PyModule_AddIntConstant(m, "MS_DIRSYNC", MS_DIRSYNC);
263 PyModule_AddIntConstant(m, "MS_I_VERSION", MS_I_VERSION);
264 PyModule_AddIntConstant(m, "MS_MANDLOCK", MS_MANDLOCK);
265 PyModule_AddIntConstant(m, "MS_MGC_MSK", MS_MGC_MSK);
266 PyModule_AddIntConstant(m, "MS_MGC_VAL", MS_MGC_VAL);
267 PyModule_AddIntConstant(m, "MS_MOVE", MS_MOVE);
268 PyModule_AddIntConstant(m, "MS_NOATIME", MS_NOATIME);
269 PyModule_AddIntConstant(m, "MS_NODEV", MS_NODEV);
270 PyModule_AddIntConstant(m, "MS_NODIRATIME", MS_NODIRATIME);
271 PyModule_AddIntConstant(m, "MS_NOEXEC", MS_NOEXEC);
272 PyModule_AddIntConstant(m, "MS_NOSUID", MS_NOSUID);
273 PyModule_AddIntConstant(m, "MS_OWNERSECURE", MS_OWNERSECURE);
274 PyModule_AddIntConstant(m, "MS_PRIVATE", MS_PRIVATE);
275 PyModule_AddIntConstant(m, "MS_PROPAGATION", MS_PROPAGATION);
276 PyModule_AddIntConstant(m, "MS_RDONLY", MS_RDONLY);
277 PyModule_AddIntConstant(m, "MS_REC", MS_REC);
278 PyModule_AddIntConstant(m, "MS_RELATIME", MS_RELATIME);
279 PyModule_AddIntConstant(m, "MS_REMOUNT", MS_REMOUNT);
280 PyModule_AddIntConstant(m, "MS_SECURE", MS_SECURE);
281 PyModule_AddIntConstant(m, "MS_SHARED", MS_SHARED);
282 PyModule_AddIntConstant(m, "MS_SILENT", MS_SILENT);
283 PyModule_AddIntConstant(m, "MS_SLAVE", MS_SLAVE);
284 PyModule_AddIntConstant(m, "MS_STRICTATIME", MS_STRICTATIME);
285 PyModule_AddIntConstant(m, "MS_SYNCHRONOUS", MS_SYNCHRONOUS);
286 PyModule_AddIntConstant(m, "MS_UNBINDABLE", MS_UNBINDABLE);
287
288 /* Will we need these directly?
289 PyModule_AddIntConstant(m, "MNT_ERR_AMBIFS", MNT_ERR_AMBIFS);
290 PyModule_AddIntConstant(m, "MNT_ERR_APPLYFLAGS", MNT_ERR_APPLYFLAGS);
291 PyModule_AddIntConstant(m, "MNT_ERR_LOOPDEV", MNT_ERR_LOOPDEV);
292 PyModule_AddIntConstant(m, "MNT_ERR_MOUNTOPT", MNT_ERR_MOUNTOPT);
293 PyModule_AddIntConstant(m, "MNT_ERR_NOFSTAB", MNT_ERR_NOFSTAB);
294 PyModule_AddIntConstant(m, "MNT_ERR_NOFSTYPE", MNT_ERR_NOFSTYPE);
295 PyModule_AddIntConstant(m, "MNT_ERR_NOSOURCE", MNT_ERR_NOSOURCE);
296 */
297
298 /* Still useful for functions using iterators internally */
299 PyModule_AddIntConstant(m, "MNT_ITER_FORWARD", MNT_ITER_FORWARD);
300 PyModule_AddIntConstant(m, "MNT_ITER_BACKWARD", MNT_ITER_BACKWARD);
46407453
OO
301
302#if PY_MAJOR_VERSION >= 3
303 return m;
304#endif
813683a3
OO
305}
306