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