/*
* 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;
}
/* 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)
{
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;
PyObject *result = Py_BuildValue("s", s);
if (!result)
PyErr_SetString(PyExc_RuntimeError, CONSTRUCT_ERR);
return result;
}
/* wrapper around a common use case for PyString_AsString() */
char *pystos(PyObject *pys)
{
if (!PyString_Check(pys)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return PyString_AsString(pys);
}
/*
* 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. Contex.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."
static PyMethodDef libmount_methods[] = {
{NULL} /* Sentinel */
};
#ifndef PyMODINIT_FUNC
# define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC initpylibmount(void);
PyMODINIT_FUNC initpylibmount(void)
{
PyObject *m = Py_InitModule3("pylibmount", libmount_methods, PYLIBMOUNT_DESC);
if (!m)
return;
/*
* 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, 0, 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);
Context_AddModuleObject(m);
/*
* 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);
}