summaryrefslogtreecommitdiffstats
path: root/libmount/python/pylibmount.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmount/python/pylibmount.c')
-rw-r--r--libmount/python/pylibmount.c303
1 files changed, 303 insertions, 0 deletions
diff --git a/libmount/python/pylibmount.c b/libmount/python/pylibmount.c
new file mode 100644
index 0000000..a2e1286
--- /dev/null
+++ b/libmount/python/pylibmount.c
@@ -0,0 +1,303 @@
+/*
+ * Python bindings for the libmount library.
+ *
+ * Copyright (C) 2013, Red Hat, Inc. All rights reserved.
+ * Written by Ondrej Oprala and Karel Zak
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include "pylibmount.h"
+
+/* Libmount-specific Exception class */
+PyObject *LibmountError;
+int pylibmount_debug_mask;
+
+PyObject *UL_IncRef(void *killme)
+{
+ Py_INCREF(killme);
+ return killme;
+}
+
+void PyFree(void *o)
+{
+#if PY_MAJOR_VERSION >= 3
+ Py_TYPE(o)->tp_free((PyObject *)o);
+#else
+ ((PyObject *)o)->ob_type->tp_free((PyObject *)o);
+#endif
+}
+
+/* Demultiplexer for various possible error conditions across the libmount library */
+void *UL_RaiseExc(int e)
+{
+ /* TODO: Do we need to deal with -1/1? */
+ switch (e) {
+ case ENOMEM:
+ PyErr_SetString(PyExc_MemoryError, strerror(e));
+ break;
+ case EINVAL:
+ PyErr_SetString(PyExc_TypeError, strerror(e));
+ break;
+ /* libmount-specific errors */
+ case MNT_ERR_APPLYFLAGS:
+ PyErr_SetString(LibmountError, "Failed to apply MS_PROPAGATION flags");
+ break;
+ case MNT_ERR_MOUNTOPT:
+ PyErr_SetString(LibmountError, "Failed to parse/use userspace mount options");
+ break;
+ case MNT_ERR_NOFSTAB:
+ PyErr_SetString(LibmountError, "Failed to detect filesystem type");
+ break;
+ case MNT_ERR_NOFSTYPE:
+ PyErr_SetString(LibmountError, "Required mount source undefined");
+ break;
+ case MNT_ERR_NOSOURCE:
+ PyErr_SetString(LibmountError, "Loopdev setup failed");
+ break;
+ case MNT_ERR_AMBIFS:
+ PyErr_SetString(LibmountError, "Libblkid detected more filesystems on the device");
+ break;
+ /* some other errno */
+ default:
+ PyErr_SetString(PyExc_Exception, strerror(e));
+ break;
+ }
+ return NULL;
+}
+
+/*
+ * General functions
+ */
+PyObject *PyObjectResultInt(int i)
+{
+ PyObject *result = Py_BuildValue("i", i);
+ if (!result)
+ PyErr_SetString(PyExc_RuntimeError, CONSTRUCT_ERR);
+ return result;
+}
+
+PyObject *PyObjectResultStr(const char *s)
+{
+ PyObject *result;
+ if (!s)
+ /* TODO: maybe lie about it and return "":
+ * which would allow for
+ * fs = libmount.Fs()
+ * fs.comment += "comment"
+ return Py_BuildValue("s", ""); */
+ Py_RETURN_NONE;
+ result = Py_BuildValue("s", s);
+ if (!result)
+ PyErr_SetString(PyExc_RuntimeError, CONSTRUCT_ERR);
+ return result;
+}
+
+/* wrapper around a common use case for PyUnicode_AsASCIIString() */
+char *pystos(PyObject *pys)
+{
+#if PY_MAJOR_VERSION >= 3
+ if (!PyUnicode_Check(pys)) {
+ PyErr_SetString(PyExc_TypeError, ARG_ERR);
+ return NULL;
+ }
+ return (char *)PyUnicode_1BYTE_DATA(pys);
+#else
+ if (!PyString_Check(pys)) {
+ PyErr_SetString(PyExc_TypeError, ARG_ERR);
+ return NULL;
+ }
+ return PyString_AsString(pys);
+#endif
+}
+
+/*
+ * the libmount module
+ */
+#define PYLIBMOUNT_DESC \
+ "Python API for the util-linux libmount library.\n\n" \
+ "Please note that none of the classes' attributes may be deleted.\n" \
+ "This is not a complete mapping to the libmount C API, nor is it\n" \
+ "attempting to be one.\n" "Iterator functions only allow forward\n" \
+ "iteration for now. Context.get_{user_,}mflags() differs from the C API\n" \
+ "and returns the flags directly. Fs.get_tag() differs from the C API\n" \
+ "and returns a (tag, value) tuple. Every attribute is \"filtered\"" \
+ "through appropriate getters/setters, no values are set directly."
+
+
+struct module_state {
+ PyObject *error;
+};
+
+#if PY_MAJOR_VERSION >= 3
+#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
+#else
+#define GETSTATE(m) (&_state)
+static struct module_state _state;
+#endif
+
+static PyObject *
+error_out(PyObject *m __attribute__((unused))) {
+ struct module_state *st = GETSTATE(m);
+ PyErr_SetString(st->error, "something bad happened");
+ return NULL;
+}
+
+static PyMethodDef pylibmount_methods[] = {
+ {"error_out", (PyCFunction)error_out, METH_NOARGS, NULL},
+ {NULL, NULL}
+};
+
+#if PY_MAJOR_VERSION >= 3
+
+static int pylibmount_traverse(PyObject *m, visitproc visit, void *arg) {
+ Py_VISIT(GETSTATE(m)->error);
+ return 0;
+}
+
+static int pylibmount_clear(PyObject *m) {
+ Py_CLEAR(GETSTATE(m)->error);
+ return 0;
+}
+
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "pylibmount",
+ NULL,
+ sizeof(struct module_state),
+ pylibmount_methods,
+ NULL,
+ pylibmount_traverse,
+ pylibmount_clear,
+ NULL
+};
+#define INITERROR return NULL
+PyObject * PyInit_pylibmount(void);
+PyObject * PyInit_pylibmount(void)
+#else
+#define INITERROR return
+# ifndef PyMODINIT_FUNC
+# define PyMODINIT_FUNC void
+# endif
+PyMODINIT_FUNC initpylibmount(void);
+PyMODINIT_FUNC initpylibmount(void)
+#endif
+{
+#if PY_MAJOR_VERSION >= 3
+ PyObject *m = PyModule_Create(&moduledef);
+#else
+ PyObject *m = Py_InitModule3("pylibmount", pylibmount_methods, PYLIBMOUNT_DESC);
+#endif
+
+ if (!m)
+ INITERROR;
+ /*
+ * init debug stuff
+ */
+ if (!(pylibmount_debug_mask & PYMNT_DEBUG_INIT)) {
+ char *str = getenv("PYLIBMOUNT_DEBUG");
+
+ pylibmount_debug_mask = 0;
+ if (str)
+ pylibmount_debug_mask = strtoul(str, NULL, 0);
+
+ pylibmount_debug_mask |= PYMNT_DEBUG_INIT;
+ }
+
+ if (pylibmount_debug_mask && pylibmount_debug_mask != PYMNT_DEBUG_INIT)
+ DBG(INIT, pymnt_debug("library debug mask: 0x%04x",
+ pylibmount_debug_mask));
+ mnt_init_debug(0);
+
+ /*
+ * Add module objects
+ */
+ LibmountError = PyErr_NewException("libmount.Error", NULL, NULL);
+ Py_INCREF(LibmountError);
+ PyModule_AddObject(m, "Error", (PyObject *)LibmountError);
+
+ FS_AddModuleObject(m);
+ Table_AddModuleObject(m);
+#ifdef __linux__
+ Context_AddModuleObject(m);
+#endif
+
+ /*
+ * mount(8) userspace options masks (MNT_MAP_USERSPACE map)
+ */
+ PyModule_AddIntConstant(m, "MNT_MS_COMMENT", MNT_MS_COMMENT);
+ PyModule_AddIntConstant(m, "MNT_MS_GROUP", MNT_MS_GROUP);
+ PyModule_AddIntConstant(m, "MNT_MS_HELPER", MNT_MS_HELPER);
+ PyModule_AddIntConstant(m, "MNT_MS_LOOP", MNT_MS_LOOP);
+ PyModule_AddIntConstant(m, "MNT_MS_NETDEV", MNT_MS_NETDEV);
+ PyModule_AddIntConstant(m, "MNT_MS_NOAUTO", MNT_MS_NOAUTO);
+ PyModule_AddIntConstant(m, "MNT_MS_NOFAIL", MNT_MS_NOFAIL);
+ PyModule_AddIntConstant(m, "MNT_MS_OFFSET", MNT_MS_OFFSET);
+ PyModule_AddIntConstant(m, "MNT_MS_OWNER", MNT_MS_OWNER);
+ PyModule_AddIntConstant(m, "MNT_MS_SIZELIMIT", MNT_MS_SIZELIMIT);
+ PyModule_AddIntConstant(m, "MNT_MS_ENCRYPTION", MNT_MS_ENCRYPTION);
+ PyModule_AddIntConstant(m, "MNT_MS_UHELPER", MNT_MS_UHELPER);
+ PyModule_AddIntConstant(m, "MNT_MS_USER", MNT_MS_USER);
+ PyModule_AddIntConstant(m, "MNT_MS_USERS", MNT_MS_USERS);
+ PyModule_AddIntConstant(m, "MNT_MS_XCOMMENT", MNT_MS_XCOMMENT);
+
+ /*
+ * mount(2) MS_* masks (MNT_MAP_LINUX map)
+ */
+ PyModule_AddIntConstant(m, "MS_BIND", MS_BIND);
+ PyModule_AddIntConstant(m, "MS_DIRSYNC", MS_DIRSYNC);
+ PyModule_AddIntConstant(m, "MS_I_VERSION", MS_I_VERSION);
+ PyModule_AddIntConstant(m, "MS_MANDLOCK", MS_MANDLOCK);
+ PyModule_AddIntConstant(m, "MS_MGC_MSK", MS_MGC_MSK);
+ PyModule_AddIntConstant(m, "MS_MGC_VAL", MS_MGC_VAL);
+ PyModule_AddIntConstant(m, "MS_MOVE", MS_MOVE);
+ PyModule_AddIntConstant(m, "MS_NOATIME", MS_NOATIME);
+ PyModule_AddIntConstant(m, "MS_NODEV", MS_NODEV);
+ PyModule_AddIntConstant(m, "MS_NODIRATIME", MS_NODIRATIME);
+ PyModule_AddIntConstant(m, "MS_NOEXEC", MS_NOEXEC);
+ PyModule_AddIntConstant(m, "MS_NOSUID", MS_NOSUID);
+ PyModule_AddIntConstant(m, "MS_OWNERSECURE", MS_OWNERSECURE);
+ PyModule_AddIntConstant(m, "MS_PRIVATE", MS_PRIVATE);
+ PyModule_AddIntConstant(m, "MS_PROPAGATION", MS_PROPAGATION);
+ PyModule_AddIntConstant(m, "MS_RDONLY", MS_RDONLY);
+ PyModule_AddIntConstant(m, "MS_REC", MS_REC);
+ PyModule_AddIntConstant(m, "MS_RELATIME", MS_RELATIME);
+ PyModule_AddIntConstant(m, "MS_REMOUNT", MS_REMOUNT);
+ PyModule_AddIntConstant(m, "MS_SECURE", MS_SECURE);
+ PyModule_AddIntConstant(m, "MS_SHARED", MS_SHARED);
+ PyModule_AddIntConstant(m, "MS_SILENT", MS_SILENT);
+ PyModule_AddIntConstant(m, "MS_SLAVE", MS_SLAVE);
+ PyModule_AddIntConstant(m, "MS_STRICTATIME", MS_STRICTATIME);
+ PyModule_AddIntConstant(m, "MS_SYNCHRONOUS", MS_SYNCHRONOUS);
+ PyModule_AddIntConstant(m, "MS_UNBINDABLE", MS_UNBINDABLE);
+
+ /* Will we need these directly?
+ PyModule_AddIntConstant(m, "MNT_ERR_AMBIFS", MNT_ERR_AMBIFS);
+ PyModule_AddIntConstant(m, "MNT_ERR_APPLYFLAGS", MNT_ERR_APPLYFLAGS);
+ PyModule_AddIntConstant(m, "MNT_ERR_LOOPDEV", MNT_ERR_LOOPDEV);
+ PyModule_AddIntConstant(m, "MNT_ERR_MOUNTOPT", MNT_ERR_MOUNTOPT);
+ PyModule_AddIntConstant(m, "MNT_ERR_NOFSTAB", MNT_ERR_NOFSTAB);
+ PyModule_AddIntConstant(m, "MNT_ERR_NOFSTYPE", MNT_ERR_NOFSTYPE);
+ PyModule_AddIntConstant(m, "MNT_ERR_NOSOURCE", MNT_ERR_NOSOURCE);
+ */
+
+ /* Still useful for functions using iterators internally */
+ PyModule_AddIntConstant(m, "MNT_ITER_FORWARD", MNT_ITER_FORWARD);
+ PyModule_AddIntConstant(m, "MNT_ITER_BACKWARD", MNT_ITER_BACKWARD);
+
+#if PY_MAJOR_VERSION >= 3
+ return m;
+#endif
+}
+