]>
Commit | Line | Data |
---|---|---|
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 */ | |
24 | PyObject *LibmountError; | |
b7e47ac1 KZ |
25 | int pylibmount_debug_mask; |
26 | ||
813683a3 OO |
27 | PyObject *UL_IncRef(void *killme) |
28 | { | |
29 | Py_INCREF(killme); | |
30 | return killme; | |
31 | } | |
32 | ||
46407453 OO |
33 | void 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 */ |
43 | void *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 | */ | |
83 | PyObject *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 | ||
91 | PyObject *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 |
108 | char *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 | |
139 | struct 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) | |
147 | static struct module_state _state; | |
813683a3 | 148 | #endif |
46407453 OO |
149 | |
150 | static PyObject * | |
151 | error_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 | ||
157 | static PyMethodDef pylibmount_methods[] = { | |
158 | {"error_out", (PyCFunction)error_out, METH_NOARGS, NULL}, | |
159 | {NULL, NULL} | |
160 | }; | |
161 | ||
162 | #if PY_MAJOR_VERSION >= 3 | |
163 | ||
164 | static int pylibmount_traverse(PyObject *m, visitproc visit, void *arg) { | |
165 | Py_VISIT(GETSTATE(m)->error); | |
166 | return 0; | |
167 | } | |
168 | ||
169 | static int pylibmount_clear(PyObject *m) { | |
170 | Py_CLEAR(GETSTATE(m)->error); | |
171 | return 0; | |
172 | } | |
173 | ||
174 | static 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 | |
186 | PyObject * PyInit_pylibmount(void); | |
187 | PyObject * PyInit_pylibmount(void) | |
188 | #else | |
189 | #define INITERROR return | |
190 | # ifndef PyMODINIT_FUNC | |
191 | # define PyMODINIT_FUNC void | |
192 | # endif | |
813683a3 OO |
193 | PyMODINIT_FUNC initpylibmount(void); |
194 | PyMODINIT_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 |