pylibmount: basic code

[kzak@redhat.com: - split to more patches
                  - split to more .c files]

Signed-off-by: Ondrej Oprala <ooprala@redhat.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Ondrej Oprala 2013-08-19 15:00:15 +02:00 committed by Karel Zak
parent d78df0ac65
commit 813683a352
6 changed files with 3045 additions and 2 deletions

View File

@ -2,8 +2,13 @@
if BUILD_PYLIBMOUNT
pyexec_LTLIBRARIES += pylibmount.la
pylibmount_la_SOURCES =
pylibmount_la_SOURCES = \
libmount/python/pylibmount.c \
libmount/python/pylibmount.h \
libmount/python/fs.c \
libmount/python/tab.c \
libmount/python/context.c
pylibmount_la_LIBADD = libmount.la -lpython$(PYTHON_VERSION)
pylibmount_la_CFLAGS = \

1240
libmount/python/context.c Normal file

File diff suppressed because it is too large Load Diff

790
libmount/python/fs.c Normal file
View File

@ -0,0 +1,790 @@
/*
* 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.
*/
/*
* TODO:
* mnt_fs_match_{source,target}
* mnt_fs_get_{attribute,option}
*/
#include "pylibmount.h"
#define Fs_HELP "Fs(bindsrc=None, source=None, root=None, target=None, fstype=None, options=None, attributes=None, freq=0, passno=0)"
static PyMemberDef Fs_members[] = {
{NULL}
};
static PyObject *Fs_get_tag(FsObject *self)
{
const char *tag = NULL, *val = NULL;
PyObject *result;
mnt_fs_get_tag(self->fs, &tag, &val);
result = Py_BuildValue("(ss)", tag, val);
if (!result)
PyErr_SetString(PyExc_RuntimeError, CONSTRUCT_ERR);
return result;
}
/* id */
static PyObject *Fs_get_id(FsObject *self)
{
return PyObjectResultInt(mnt_fs_get_id(self->fs));
}
/* parent_id */
static PyObject *Fs_get_parent_id(FsObject *self)
{
return PyObjectResultInt(mnt_fs_get_parent_id(self->fs));
}
/* devno */
static PyObject *Fs_get_devno(FsObject *self)
{
return PyObjectResultInt(mnt_fs_get_devno(self->fs));
}
#define Fs_print_debug_HELP "print_debug(ostream)\n\n"
static PyObject *Fs_print_debug(FsObject *self, PyObject *args, PyObject *kwds)
{
PyFileObject *stream = NULL;
int rc;
FILE *f = NULL;
char *kwlist[] = {"ostream", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyFile_Type, &stream)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
f = PyFile_AsFile((PyObject *)stream);
return (rc = mnt_fs_print_debug(self->fs, f)) ? UL_RaiseExc(-rc) : UL_IncRef(self);
}
/*
** Fs getters/setters
*/
/* bindsrc */
static PyObject *Fs_get_bindsrc(FsObject *self, void *closure __attribute__((unused)))
{
return PyObjectResultStr(mnt_fs_get_bindsrc(self->fs));
}
static int Fs_set_bindsrc(FsObject *self, PyObject *value, void *closure __attribute__((unused)))
{
char *bindsrc = NULL;
int rc = 0;
if (!value) {
PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
return -1;
}
if (!(bindsrc = pystos(value)))
return -1;
rc = mnt_fs_set_bindsrc(self->fs, bindsrc);
if (rc) {
UL_RaiseExc(-rc);
return -1;
}
return 0;
}
/* comment */
static PyObject *Fs_get_comment(FsObject *self, void *closure __attribute__((unused)))
{
return PyObjectResultStr(mnt_fs_get_comment(self->fs));
}
static int Fs_set_comment(FsObject *self, PyObject *value, void *closure __attribute__((unused)))
{
char *comment = NULL;
int rc = 0;
if (!value) {
PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
return -1;
}
if (!(comment = pystos(value)))
return -1;
rc = mnt_fs_set_comment(self->fs, comment);
if (rc) {
UL_RaiseExc(-rc);
return -1;
}
return 0;
}
/* source */
static PyObject *Fs_get_source(FsObject *self)
{
return PyObjectResultStr(mnt_fs_get_source(self->fs));
}
static int Fs_set_source(FsObject *self, PyObject *value, void *closure __attribute__((unused)))
{
char *source = NULL;
int rc = 0;
if (!value) {
PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
return -1;
}
if (!(source = pystos(value)))
return -1;
rc = mnt_fs_set_source(self->fs, source);
if (rc) {
UL_RaiseExc(-rc);
return -1;
}
return 0;
}
/* srcpath */
static PyObject *Fs_get_srcpath(FsObject *self)
{
return PyObjectResultStr(mnt_fs_get_srcpath(self->fs));
}
/* root */
static PyObject *Fs_get_root(FsObject *self)
{
return PyObjectResultStr(mnt_fs_get_root(self->fs));
}
static int Fs_set_root(FsObject *self, PyObject *value, void *closure __attribute__((unused)))
{
char *root = NULL;
int rc = 0;
if (!value) {
PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
return -1;
}
if (!(root = pystos(value)))
return -1;
rc = mnt_fs_set_root(self->fs, root);
if (rc) {
UL_RaiseExc(-rc);
return -1;
}
return 0;
}
/* target */
static PyObject *Fs_get_target(FsObject *self)
{
return PyObjectResultStr(mnt_fs_get_target(self->fs));
}
static int Fs_set_target(FsObject *self, PyObject *value, void *closure __attribute__((unused)))
{
char *target = NULL;
int rc = 0;
if (!value) {
PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
return -1;
}
if (!(target = pystos(value)))
return -1;
rc = mnt_fs_set_target(self->fs, target);
if (rc) {
UL_RaiseExc(-rc);
return -1;
}
return 0;
}
/* fstype */
static PyObject *Fs_get_fstype(FsObject *self)
{
return PyObjectResultStr(mnt_fs_get_fstype(self->fs));
}
static int Fs_set_fstype(FsObject *self, PyObject *value, void *closure __attribute__((unused)))
{
char *fstype = NULL;
int rc = 0;
if (!value) {
PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
return -1;
}
if (!(fstype = pystos(value)))
return -1;
rc = mnt_fs_set_fstype(self->fs, fstype);
if (rc) {
UL_RaiseExc(-rc);
return -1;
}
return 0;
}
/* optstr */
static PyObject *Fs_get_options(FsObject *self)
{
return PyObjectResultStr(mnt_fs_get_options(self->fs));
}
static int Fs_set_options(FsObject *self, PyObject *value, void *closure __attribute__((unused)))
{
char *options = NULL;
int rc = 0;
if (!value) {
PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
return -1;
}
if (!(options = pystos(value)))
return -1;
rc = mnt_fs_set_options(self->fs, options);
if (rc) {
UL_RaiseExc(-rc);
return -1;
}
return 0;
}
/* vfs_optstr */
static PyObject *Fs_get_vfs_options(FsObject *self)
{
return PyObjectResultStr(mnt_fs_get_vfs_options(self->fs));
}
/* opt_fields */
static PyObject *Fs_get_optional_fields(FsObject *self)
{
return PyObjectResultStr(mnt_fs_get_optional_fields(self->fs));
}
/* fs_optstr */
static PyObject *Fs_get_fs_options(FsObject *self)
{
return PyObjectResultStr(mnt_fs_get_fs_options(self->fs));
}
/* user_optstr */
static PyObject *Fs_get_user_options(FsObject *self)
{
return PyObjectResultStr(mnt_fs_get_user_options(self->fs));
}
/* attrs */
static PyObject *Fs_get_attributes(FsObject *self)
{
return PyObjectResultStr(mnt_fs_get_attributes(self->fs));
}
static int Fs_set_attributes(FsObject *self, PyObject *value, void *closure __attribute__((unused)))
{
char *attributes = NULL;
int rc = 0;
if (!value) {
PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
return -1;
}
if (!(attributes = pystos(value)))
return -1;
rc = mnt_fs_set_attributes(self->fs, attributes);
if (rc) {
UL_RaiseExc(-rc);
return -1;
}
return 0;
}
/* freq */
static PyObject *Fs_get_freq(FsObject *self, void *closure __attribute__((unused)))
{
return PyObjectResultInt(mnt_fs_get_freq(self->fs));
}
static int Fs_set_freq(FsObject *self, PyObject *value, void *closure __attribute__((unused)))
{
int freq = 0;
if (!value) {
PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
return -1;
}
else if (!PyInt_Check(value)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return -1;
}
freq = PyInt_AsLong(value);
if (freq == -1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError, "type conversion failed");
return -1;
}
return mnt_fs_set_freq(self->fs, freq);
}
/* passno */
static PyObject *Fs_get_passno(FsObject *self)
{
return PyObjectResultInt(mnt_fs_get_passno(self->fs));
}
static int Fs_set_passno(FsObject *self, PyObject *value, void *closure __attribute__((unused)))
{
int passno = 0;
if (!value) {
PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
return -1;
}
else if (!PyInt_Check(value)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return -1;
}
passno = PyInt_AsLong(value);
if (passno == -1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError, "type conversion failed");
return -1;
}
return mnt_fs_set_passno(self->fs, passno);
}
/* swaptype */
static PyObject *Fs_get_swaptype(FsObject *self)
{
return PyObjectResultStr(mnt_fs_get_swaptype(self->fs));
}
/* size */
static PyObject *Fs_get_size(FsObject *self)
{
return PyObjectResultInt(mnt_fs_get_size(self->fs));
}
/* usedsize */
static PyObject *Fs_get_usedsize(FsObject *self)
{
return PyObjectResultInt(mnt_fs_get_usedsize(self->fs));
}
/* priority */
static PyObject *Fs_get_priority(FsObject *self)
{
return PyObjectResultInt(mnt_fs_get_priority(self->fs));
}
/* propagation */
#define Fs_get_propagation_HELP "get_propagation(flags)\n\n\
Note that this function set flags to zero if not found any propagation flag\n\
in mountinfo file. The kernel default is MS_PRIVATE, this flag is not stored\n\
in the mountinfo file.\n\
\n\
Returns self or raises an exception in case of an error."
static PyObject *Fs_get_propagation(FsObject *self, PyObject *args, PyObject *kwds)
{
unsigned long flags;
char *kwlist[] = {"flags", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "k", kwlist, &flags)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return PyObjectResultInt(mnt_fs_get_propagation(self->fs, &flags));
}
/* tid */
static PyObject *Fs_get_tid(FsObject *self)
{
return PyObjectResultInt(mnt_fs_get_tid(self->fs));
}
#define Fs_is_kernel_HELP "is_kernel()\n\nReturns 1 if the filesystem description is read from kernel e.g. /proc/mounts."
static PyObject *Fs_is_kernel(FsObject *self)
{
return PyBool_FromLong(mnt_fs_is_kernel(self->fs));
}
#define Fs_is_netfs_HELP "is_netfs()\n\nReturns 1 if the filesystem is a network filesystem"
static PyObject *Fs_is_netfs(FsObject *self)
{
return PyBool_FromLong(mnt_fs_is_netfs(self->fs));
}
#define Fs_is_pseudofs_HELP "is_pseudofs()\n\nReturns 1 if the filesystem is a pseudo fs type (proc, cgroups)"
static PyObject *Fs_is_pseudofs(FsObject *self)
{
return PyBool_FromLong(mnt_fs_is_pseudofs(self->fs));
}
#define Fs_is_swaparea_HELP "is_swaparea()\n\nReturns 1 if the filesystem uses \"swap\" as a type"
static PyObject *Fs_is_swaparea(FsObject *self)
{
return PyBool_FromLong(mnt_fs_is_swaparea(self->fs));
}
#define Fs_append_attributes_HELP "append_attributes(optstr)\n\n\
Appends mount attributes."
static PyObject *Fs_append_attributes(FsObject *self, PyObject *args, PyObject *kwds)
{
char *kwlist[] = {"optstr", NULL};
char *optstr = NULL;
int rc;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &optstr)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return (rc = mnt_fs_append_attributes(self->fs, optstr)) ? UL_RaiseExc(-rc) : UL_IncRef(self);
}
#define Fs_append_options_HELP "append_options(optstr)\n\n\
Parses (splits) optstr and appends results to VFS, FS and userspace lists \
of options."
static PyObject *Fs_append_options(FsObject *self, PyObject *args, PyObject *kwds)
{
char *kwlist[] = {"optstr", NULL};
char *optstr = NULL;
int rc;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &optstr)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return (rc = mnt_fs_append_options(self->fs, optstr)) ? UL_RaiseExc(-rc) : UL_IncRef(self);
}
#define Fs_prepend_attributes_HELP "prepend_attributes(optstr)\n\n\
Prepends mount attributes."
static PyObject *Fs_prepend_attributes(FsObject *self, PyObject *args, PyObject *kwds)
{
char *kwlist[] = {"optstr", NULL};
char *optstr = NULL;
int rc;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &optstr)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return (rc = mnt_fs_prepend_attributes(self->fs, optstr)) ? UL_RaiseExc(-rc) : UL_IncRef(self);
}
#define Fs_prepend_options_HELP "prepend_options(optstr)\n\n\
Parses (splits) optstr and prepends results to VFS, FS and userspace lists \
of options."
static PyObject *Fs_prepend_options(FsObject *self, PyObject *args, PyObject *kwds)
{
char *kwlist[] = {"optstr", NULL};
char *optstr = NULL;
int rc;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &optstr)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return (rc = mnt_fs_prepend_options(self->fs, optstr)) ? UL_RaiseExc(-rc) : UL_IncRef(self);
}
#define Fs_match_fstype_HELP "match_fstype(pattern)\n\n\
pattern: filesystem name or comma delimited list(string) of names\n\n\
The pattern list of filesystem can be prefixed with a global\n\
\"no\" prefix to invert matching of the whole list. The \"no\" could\n\
also be used for individual items in the pattern list. So,\n\
\"nofoo,bar\" has the same meaning as \"nofoo,nobar\".\n\
\"bar\" : \"nofoo,bar\" -> False (global \"no\" prefix)\n\
\"bar\" : \"foo,bar\" -> True\n\
\"bar\" : \"foo,nobar\" -> False\n\n\
Returns True if type is matching, else False." /* TODO: Test this */
static PyObject *Fs_match_fstype(FsObject *self, PyObject *args, PyObject *kwds)
{
char *kwlist[] = {"pattern", NULL};
char *pattern = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &pattern)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return PyBool_FromLong(mnt_fs_match_fstype(self->fs, pattern));
}
#define Fs_match_options_HELP "match_options(options)\n\n\
options: comma delimited list of options (and nooptions)\n\
Returns True if fs type is matching to options else False."
static PyObject *Fs_match_options(FsObject *self, PyObject *args, PyObject *kwds)
{
char *kwlist[] = {"options", NULL};
char *options = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &options)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return PyBool_FromLong(mnt_fs_match_options(self->fs, options));
}
#define Fs_streq_srcpath_HELP "streq_srcpath(srcpath)\n\n\
Compares fs source path with path. The tailing slash is ignored.\n\
Returns True if fs source path equal to path, otherwise False."
static PyObject *Fs_streq_srcpath(FsObject *self, PyObject *args, PyObject *kwds)
{
char *kwlist[] = {"srcpath", NULL};
char *srcpath = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &srcpath)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return PyBool_FromLong(mnt_fs_streq_srcpath(self->fs, srcpath));
}
#define Fs_streq_target_HELP "streq_target(target)\n\n\
Compares fs target path with path. The tailing slash is ignored.\n\
See also Fs.match_target().\n\
Returns True if fs target path equal to path, otherwise False."
static PyObject *Fs_streq_target(FsObject *self, PyObject *args, PyObject *kwds)
{
char *kwlist[] = {"target", NULL};
char *target = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &target)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return PyBool_FromLong(mnt_fs_streq_target(self->fs, target));
}
#define Fs_copy_fs_HELP "copy_fs(dest=None)\n\n\
If dest is None, a new object is created, if any fs \
field is already set, then the field is NOT overwritten."
static PyObject *Fs_copy_fs(FsObject *self, PyObject *args, PyObject *kwds);
static PyMethodDef Fs_methods[] = {
{"get_propagation", (PyCFunction)Fs_get_propagation, METH_VARARGS|METH_KEYWORDS, Fs_get_propagation_HELP},
{"mnt_fs_append_attributes", (PyCFunction)Fs_append_attributes, METH_VARARGS|METH_KEYWORDS, Fs_append_attributes_HELP},
{"append_options", (PyCFunction)Fs_append_options, METH_VARARGS|METH_KEYWORDS, Fs_append_options_HELP},
{"mnt_fs_prepend_attributes", (PyCFunction)Fs_prepend_attributes, METH_VARARGS|METH_KEYWORDS, Fs_prepend_attributes_HELP},
{"prepend_options", (PyCFunction)Fs_prepend_options, METH_VARARGS|METH_KEYWORDS, Fs_prepend_options_HELP},
{"copy_fs", (PyCFunction)Fs_copy_fs, METH_VARARGS|METH_KEYWORDS, Fs_copy_fs_HELP},
{"is_kernel", (PyCFunction)Fs_is_kernel, METH_NOARGS, Fs_is_kernel_HELP},
{"is_netfs", (PyCFunction)Fs_is_netfs, METH_NOARGS, Fs_is_netfs_HELP},
{"is_pseudofs", (PyCFunction)Fs_is_pseudofs, METH_NOARGS, Fs_is_pseudofs_HELP},
{"is_swaparea", (PyCFunction)Fs_is_swaparea, METH_NOARGS, Fs_is_swaparea_HELP},
{"match_fstype", (PyCFunction)Fs_match_fstype, METH_VARARGS|METH_KEYWORDS, Fs_match_fstype_HELP},
{"match_options", (PyCFunction)Fs_match_options, METH_VARARGS|METH_KEYWORDS, Fs_match_options_HELP},
{"streq_srcpath", (PyCFunction)Fs_streq_srcpath, METH_VARARGS|METH_KEYWORDS, Fs_streq_srcpath_HELP},
{"streq_target", (PyCFunction)Fs_streq_target, METH_VARARGS|METH_KEYWORDS, Fs_streq_target_HELP},
{"print_debug", (PyCFunction)Fs_print_debug, METH_VARARGS|METH_KEYWORDS, Fs_print_debug_HELP},
{NULL}
};
static void Fs_dealloc(FsObject *self)
{
mnt_free_fs(self->fs);
self->ob_type->tp_free((PyObject*)self);
}
static PyObject *Fs_new(PyTypeObject *type, PyObject *args __attribute__((unused)),
PyObject *kwds __attribute__((unused)))
{
FsObject *self = (FsObject*)type->tp_alloc(type, 0);
if (self)
self->fs = NULL;
return (PyObject *)self;
}
static int Fs_init(FsObject *self, PyObject *args, PyObject *kwds)
{
char *bindsrc = NULL, *source = NULL, *root = NULL, *target = NULL;
char *fstype = NULL, *options = NULL, *attributes =NULL;
int freq = 0; int passno = 0;
int rc = 0;
char *kwlist[] = {"bindsrc", "source", "root", "target",
"fstype", "options", "attributes", "freq", "passno", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sssssssii", kwlist,
&bindsrc, &source, &root, &target, &fstype, &options,
&attributes, &freq, &passno)) {
PyErr_SetString(PyExc_TypeError, "Invalid type");
return -1;
}
if (self->fs)
mnt_free_fs(self->fs);
self->fs = mnt_new_fs();
if (bindsrc) {
if ((rc = mnt_fs_set_bindsrc(self->fs, bindsrc))) {
PyErr_SetString(PyExc_MemoryError, MEMORY_ERR);
return rc;
}
}
if (source) {
if ((rc = mnt_fs_set_source(self->fs, source))) {
PyErr_SetString(PyExc_MemoryError, MEMORY_ERR);
return rc;
}
}
if (root) {
if ((rc = mnt_fs_set_root(self->fs, root))) {
PyErr_SetString(PyExc_MemoryError, MEMORY_ERR);
return rc;
}
}
if (target) {
if ((rc = mnt_fs_set_target(self->fs, target))) {
PyErr_SetString(PyExc_MemoryError, MEMORY_ERR);
return rc;
}
}
if (fstype) {
if ((rc = mnt_fs_set_fstype(self->fs, fstype))) {
PyErr_SetString(PyExc_MemoryError, MEMORY_ERR);
return rc;
}
}
if (options) {
if ((rc = mnt_fs_set_options(self->fs, options))) {
PyErr_SetString(PyExc_MemoryError, MEMORY_ERR);
return rc;
}
}
if (attributes) {
if ((rc = mnt_fs_set_attributes(self->fs, attributes))) {
PyErr_SetString(PyExc_MemoryError, MEMORY_ERR);
return rc;
}
}
mnt_fs_set_freq(self->fs, freq);
mnt_fs_set_passno(self->fs, passno);
self->fs->userdata = (void *)self; /* store a pointer to self, convenient when resetting the table */
return 0;
}
/*
* missing:
* attribute
* option
*/
static PyGetSetDef Fs_getseters[] = {
{"id", (getter)Fs_get_id, NULL, "mountinfo[1]: ID", NULL},
{"parent", (getter)Fs_get_parent_id, NULL, "mountinfo[2]: parent", NULL},
{"devno", (getter)Fs_get_devno, NULL, "mountinfo[3]: st_dev", NULL},
{"bindsrc", (getter)Fs_get_bindsrc, (setter)Fs_set_bindsrc, "utab, full path from fstab[1] for bind mounts", NULL},
{"comment", (getter)Fs_get_comment, (setter)Fs_set_comment, "fstab entry comment", NULL},
{"source", (getter)Fs_get_source, (setter)Fs_set_source, "fstab[1], mountinfo[10], swaps[1]: source dev, file, dir or TAG", NULL},
{"srcpath", (getter)Fs_get_srcpath, NULL, "mount source path or NULL in case of error or when the path is not defined.", NULL},
{"root", (getter)Fs_get_root, (setter)Fs_set_root, "mountinfo[4]: root of the mount within the FS", NULL},
{"target", (getter)Fs_get_target, (setter)Fs_set_target, "mountinfo[5], fstab[2]: mountpoint", NULL},
{"fstype", (getter)Fs_get_fstype, (setter)Fs_set_fstype, "mountinfo[9], fstab[3]: filesystem type", NULL},
{"options", (getter)Fs_get_options, (setter)Fs_set_options, "fstab[4]: merged options", NULL},
{"vfs_options", (getter)Fs_get_vfs_options, NULL, "mountinfo[6]: fs-independent (VFS) options", NULL},
{"opt_fields", (getter)Fs_get_optional_fields, NULL, "mountinfo[7]: optional fields", NULL},
{"fs_options", (getter)Fs_get_fs_options, NULL, "mountinfo[11]: fs-dependent options", NULL},
{"usr_options", (getter)Fs_get_user_options, NULL, "userspace mount options", NULL},
{"attributes", (getter)Fs_get_attributes, (setter)Fs_set_attributes, "mount attributes", NULL},
{"freq", (getter)Fs_get_freq, (setter)Fs_set_freq, "fstab[5]: dump frequency in days", NULL},
{"passno", (getter)Fs_get_passno, (setter)Fs_set_passno, "fstab[6]: pass number on parallel fsck", NULL},
{"swaptype", (getter)Fs_get_swaptype, NULL, "swaps[2]: device type", NULL},
{"size", (getter)Fs_get_size, NULL, "saps[3]: swaparea size", NULL},
{"usedsize", (getter)Fs_get_usedsize, NULL, "swaps[4]: used size", NULL},
{"priority", (getter)Fs_get_priority, NULL, "swaps[5]: swap priority", NULL},
{"tag", (getter)Fs_get_tag, NULL, "(Name, Value)", NULL},
{"tid", (getter)Fs_get_tid, NULL, "/proc/<tid>/mountinfo, otherwise zero", NULL},
{NULL}
};
static PyObject *Fs_repr(FsObject *self)
{
return PyString_FromFormat(
"<libmount.Fs object at %p, source=%s, target=%s, fstype=%s>",
self,
self->fs->source ? self->fs->source : "None",
self->fs->target ? self->fs->target : "None",
self->fs->fstype ? self->fs->fstype : "None");
}
PyObject *PyObjectResultFs(struct libmnt_fs *fs)
{
if (!fs) {
PyErr_SetString(LibmountError, "internal exception");
return NULL;
}
if (fs->userdata) {
Py_INCREF(fs->userdata);
return (PyObject *)fs->userdata;
}
FsObject *result = PyObject_New(FsObject, &FsType);
if (!result) {
UL_RaiseExc(ENOMEM);
return NULL;
}
/* Creating an encapsualing object: increment the refcount, so that code
* such as:
* tab.next_fs()
* doesn't call the destructor, which would free our fs struct as well
*/
Py_INCREF(result);
result->fs = fs;
result->fs->userdata = (void *)result;
return (PyObject *)result;
}
static PyObject *Fs_copy_fs(FsObject *self, PyObject *args, PyObject *kwds)
{
PyObject *dest = NULL;
char *kwlist[] = {"dest", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &dest)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
if (PyObject_TypeCheck(dest, &FsType)) { /* existing object passed as argument */
if (!mnt_copy_fs(((FsObject *)dest)->fs, self->fs))
return NULL;
else
return (PyObject *)dest;
}
else if (dest == Py_None) { /* create new object */
FsObject *result = PyObject_New(FsObject, &FsType);
result->fs = mnt_copy_fs(NULL, self->fs);
result->fs->userdata = (void *)result; /* keep a pointer to encapsulating object */
return (PyObject *)result;
}
else {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
}
PyTypeObject FsType = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"libmount.Fs", /*tp_name*/
sizeof(FsObject), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)Fs_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
(reprfunc)Fs_repr, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Fs_HELP, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
Fs_methods, /* tp_methods */
Fs_members, /* tp_members */
Fs_getseters, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)Fs_init, /* tp_init */
0, /* tp_alloc */
Fs_new, /* tp_new */
};
void pymnt_init_fs(PyObject *mod)
{
if (PyType_Ready(&FsType) < 0)
return;
Py_INCREF(&FsType);
PyModule_AddObject(mod, "Fs", (PyObject *)&FsType);
}

View File

@ -0,0 +1,205 @@
/*
* 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;
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;
LibmountError = PyErr_NewException("libmount.Error", NULL, NULL);
Py_INCREF(LibmountError);
PyModule_AddObject(m, "Error", (PyObject *)LibmountError);
pymnt_init_fs(m);
pymnt_init_table(m);
pymnt_init_context(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);
}

View File

@ -0,0 +1,78 @@
#ifndef UTIL_LINUX_PYLIBMOUNT_H
#define UTIL_LINUX_PYLIBMOUNT_H
#include <Python.h>
#include <structmember.h>
#include "libmount.h"
#include "mountP.h"
#define NODEL_ATTR "This attribute cannot be deleted"
#define CONSTRUCT_ERR "Error during object construction"
#define ARG_ERR "Invalid number or type of arguments"
#define NOFS_ERR "No filesystems to mount"
#define MEMORY_ERR strerror(ENOMEM)
#define CONV_ERR "Type conversion failed"
/*
* fs.c
*/
typedef struct {
PyObject_HEAD
struct libmnt_fs *fs;
} FsObject;
extern PyTypeObject FsType;
extern PyObject *PyObjectResultFs(struct libmnt_fs *fs);
extern void pymnt_init_fs(PyObject *mod);
/*
* tab.c
*/
typedef struct {
PyObject_HEAD
struct libmnt_table *tab;
struct libmnt_iter *iter;
PyObject *errcb;
} TabObject;
extern PyTypeObject TabType;
extern PyObject *PyObjectResultTab(struct libmnt_table *tab);
extern void pymnt_init_table(PyObject *mod);
extern void pymnt_free_table(struct libmnt_table *tab);
extern int pymnt_table_parser_errcb(struct libmnt_table *tb, const char *filename, int line);
/*
* context.c
*/
typedef struct {
PyObject_HEAD
struct libmnt_context *cxt;
PyObject *table_errcb;
} CxtObject;
extern PyTypeObject CxtType;
extern void pymnt_init_context(PyObject *mod);
/*
* misc
*/
extern PyObject *LibmountError;
extern PyObject *UL_IncRef(void *killme);
extern void *UL_RaiseExc(int e);
extern PyObject *PyObjectResultInt(int i);
extern PyObject *PyObjectResultStr(const char *s);
extern char *pystos(PyObject *pys);
#endif /* UTIL_LINUX_PYLIBMOUNT */

725
libmount/python/tab.c Normal file
View File

@ -0,0 +1,725 @@
/*
* 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"
static PyMemberDef Tab_members[] = {
{NULL}
};
static int Tab_set_parser_errcb(TabObject *self, PyObject *func, void *closure __attribute__((unused)))
{
if (!func) {
PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
return -1;
}
if (!PyCallable_Check(func))
return -1;
else {
PyObject *tmp = self->errcb;
Py_INCREF(func);
self->errcb = func;
Py_XDECREF(tmp);
}
return 0;
}
static PyObject *Tab_get_intro_comment(TabObject *self, void *closure __attribute__((unused)))
{
return PyObjectResultStr(mnt_table_get_intro_comment(self->tab));
}
static int Tab_set_intro_comment(TabObject *self, PyObject *value, void *closure __attribute__((unused)))
{
char *comment = NULL;
int rc = 0;
if (!value) {
PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
return -1;
}
if (!(comment = pystos(value)))
return -1;
if ((rc = mnt_table_set_intro_comment(self->tab, comment))) {
UL_RaiseExc(-rc);
return -1;
}
return 0;
}
static PyObject *Tab_get_trailing_comment(TabObject *self, void *closure __attribute__((unused)))
{
return PyObjectResultStr(mnt_table_get_trailing_comment(self->tab));
}
static int Tab_set_trailing_comment(TabObject *self, PyObject *value, void *closure __attribute__((unused)))
{
char *comment = NULL;
int rc = 0;
if (!value) {
PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
return -1;
}
if (!(comment = pystos(value)))
return -1;
if ((rc = mnt_table_set_trailing_comment(self->tab, comment))) {
UL_RaiseExc(-rc);
return -1;
}
return 0;
}
#define Tab_enable_comments_HELP "enable_comments(enable)\n\n\
Enables parsing of comments.\n\n\
The initial (intro) file comment is accessible by\n\
Tab.intro_comment. The intro and the comment of the first fstab\
entry has to be separated by blank line. The filesystem comments are\n\
accessible by Fs.comment. The tailing fstab comment is accessible\n\
by Tab.trailing_comment.\n\
\n\
<informalexample>\n\
<programlisting>\n\
#\n\
# Intro comment\n\
#\n\
\n\
# this comments belongs to the first fs\n\
LABEL=foo /mnt/foo auto defaults 1 2\n\
# this comments belongs to the second fs\n\
LABEL=bar /mnt/bar auto defaults 1 2 \n\
# tailing comment\n\
</programlisting>\n\
</informalexample>"
static PyObject *Tab_enable_comments(TabObject *self, PyObject *args, PyObject *kwds)
{
int enable = 0;
char *kwlist[] = {"enable", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &enable)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
mnt_table_enable_comments(self->tab, enable);
Py_INCREF(self);
return (PyObject *)self;
}
#define Tab_replace_file_HELP "replace_file(filename)\n\n\
This function replaces filename with the new content from TabObject."
static PyObject *Tab_replace_file(TabObject *self, PyObject *args, PyObject *kwds)
{
int rc;
char *filename = NULL;
char *kwlist[] = {"filename", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &filename)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return (rc = mnt_table_replace_file(self->tab, filename)) ? UL_RaiseExc(-rc) : UL_IncRef(self);
}
#define Tab_write_file_HELP "write_file(file)\n\n\
This function writes tab to file(stream)"
static PyObject *Tab_write_file(TabObject *self, PyObject *args, PyObject *kwds)
{
int rc;
PyFileObject *stream = NULL;
FILE *f = NULL;
char *kwlist[] = {"file", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &PyFile_Type, &stream)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
f = PyFile_AsFile((PyObject *)stream);
return (rc = mnt_table_write_file(self->tab, f)) ? UL_RaiseExc(-rc) : UL_IncRef(self);
}
#define Tab_find_devno_HELP "find_devno(devno, [direction])\n\n\
Note that zero could be valid device number for root pseudo filesystem (e.g.\
tmpfs\n\
Returns a tab entry or None"
static PyObject *Tab_find_devno(TabObject *self, PyObject *args, PyObject *kwds)
{
dev_t devno;
int direction = MNT_ITER_BACKWARD;
char *kwlist[] = {"devno", "direction", NULL};
if (! PyArg_ParseTupleAndKeywords(args, kwds, "I|i", kwlist, &devno, &direction)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return PyObjectResultFs(mnt_table_find_devno(self->tab, devno, direction));
}
#define Tab_find_mountpoint_HELP "find_mountpoint(path, [direction])\n\n\
Returns a tab entry or None."
static PyObject *Tab_find_mountpoint(TabObject *self, PyObject *args, PyObject *kwds)
{
char *path;
int direction = MNT_ITER_BACKWARD;
char *kwlist[] = {"path", "direction", NULL};
if (! PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, &path, &direction)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return PyObjectResultFs(mnt_table_find_mountpoint(self->tab, path, direction));
}
#define Tab_find_pair_HELP "find_pair(source, target, [direction])\n\n\
Returns a tab entry or None."
static PyObject *Tab_find_pair(TabObject *self, PyObject *args, PyObject *kwds)
{
char *kwlist[] = {"source", "target", "direction", NULL};
char *source;
char *target;
int direction = MNT_ITER_BACKWARD;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|i", kwlist, &source, &target, &direction)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return PyObjectResultFs(mnt_table_find_pair(self->tab, source, target, direction));
}
#define Tab_find_source_HELP "find_source(source, [direction])\n\n\
Returns a tab entry or None."
static PyObject *Tab_find_source(TabObject *self, PyObject *args, PyObject *kwds)
{
char *kwlist[] = {"source", "direction", NULL};
char *source;
int direction = MNT_ITER_BACKWARD;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, &source, &direction)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return PyObjectResultFs(mnt_table_find_source(self->tab, source, direction));
}
#define Tab_find_target_HELP "find_target(target, [direction])\n\n\
Try to lookup an entry in given tab, possible are three iterations, first\n\
with path, second with realpath(path) and third with realpath(path)\n\
against realpath(fs->target). The 2nd and 3rd iterations are not performed\n\
when tb cache is not set (cache not implemented yet).n\
\n\
Returns a tab entry or None."
static PyObject *Tab_find_target(TabObject *self, PyObject *args, PyObject *kwds)
{
char *kwlist[] = {"target", "direction", NULL};
char *target;
int direction = MNT_ITER_BACKWARD;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, &target, &direction)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return PyObjectResultFs(mnt_table_find_target(self->tab, target, direction));
}
#define Tab_find_srcpath_HELP "find_srcpath(srcpath, [direction])\n\n\
Try to lookup an entry in given tab, possible are four iterations, first\n\
with path, second with realpath(path), third with tags (LABEL, UUID, ..)\n\
from path and fourth with realpath(path) against realpath(entry->srcpath).\n\
\n\
The 2nd, 3rd and 4th iterations are not performed when tb cache is not\n\
set (not implemented yet).\n\
\n\
Note that None is a valid source path; it will be replaced with \"none\". The\n\
\"none\" is used in /proc/{mounts,self/mountinfo} for pseudo filesystems.\n\
\n\
Returns a tab entry or None."
static PyObject *Tab_find_srcpath(TabObject *self, PyObject *args, PyObject *kwds)
{
char *kwlist[] = {"srcpath", "direction", NULL};
char *srcpath;
int direction = MNT_ITER_BACKWARD;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, &srcpath, &direction)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return PyObjectResultFs(mnt_table_find_srcpath(self->tab, srcpath, direction));
}
#define Tab_find_tag_HELP "find_tag(tag, val, [direction])\n\n\
Try to lookup an entry in given tab, first attempt is lookup by tag and\n\
val, for the second attempt the tag is evaluated (converted to the device\n\
name) and Tab.find_srcpath() is preformed. The second attempt is not\n\
performed when tb cache is not set (not implemented yet).\n\
\n\
Returns a tab entry or NULL."
static PyObject *Tab_find_tag(TabObject *self, PyObject *args, PyObject *kwds)
{
char *kwlist[] = {"tag", "val", "direction", NULL};
char *tag;
char *val;
int direction = MNT_ITER_BACKWARD;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|i", kwlist, &tag, &val, &direction)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return PyObjectResultFs(mnt_table_find_tag(self->tab, tag, val, direction));
}
static PyObject *Tab_get_nents(TabObject *self)
{
return PyObjectResultInt(mnt_table_get_nents(self->tab));
}
#define Tab_is_fs_mounted_HELP "is_fs_mounted(fstab_fs)\n\n\
Checks if the fstab_fs entry is already in the tb table. The \"swap\" is\n\
ignored. This function explicitly compares source, target and root of the\n\
filesystems.\n\
\n\
Note that source and target are canonicalized only if a cache for tb is\n\
defined (not implemented yet). The target canonicalization may\n\
trigger automount on autofs mountpoints!\n\
\n\
Don't use it if you want to know if a device is mounted, just use\n\
Tab.find_source() for the device.\n\
\n\
This function is designed mostly for \"mount -a\".\n\
\n\
Returns a boolean value."
static PyObject *Tab_is_fs_mounted(TabObject *self, PyObject *args, PyObject *kwds)
{
FsObject *fs;
char *kwlist[] = {"fstab_fs", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &FsType, &fs)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return PyBool_FromLong(mnt_table_is_fs_mounted(self->tab, fs->fs));
}
#define Tab_parse_file_HELP "parse_file(file)\n\n\
Parses whole table (e.g. /etc/mtab) and appends new records to the tab.\n\
\n\
The libmount parser ignores broken (syntax error) lines, these lines are\n\
reported to caller by errcb() function (see Tab.parser_errcb).\n\
\n\
Returns self or raises an exception in case of an error."
static PyObject *Tab_parse_file(TabObject *self, PyObject* args, PyObject *kwds)
{
int rc;
char *file = NULL;
char *kwlist[] = {"file", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &file)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return (rc = mnt_table_parse_file(self->tab, file)) ? UL_RaiseExc(-rc) : UL_IncRef(self);
}
#define Tab_parse_fstab_HELP "parse_fstab([fstab])\n\n\
This function parses /etc/fstab and appends new lines to the tab. If the\n\
filename is a directory then Tab.parse_dir() is called.\n\
\n\
See also Tab.parser_errcb.\n\
\n\
Returns self or raises an exception in case of an error."
static PyObject *Tab_parse_fstab(TabObject *self, PyObject* args, PyObject *kwds)
{
int rc;
char *fstab = NULL;
char *kwlist[] = {"fstab", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &fstab)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return (rc = mnt_table_parse_fstab(self->tab, fstab)) ? UL_RaiseExc(-rc) : UL_IncRef(self);
}
#define Tab_parse_mtab_HELP "parse_mtab([mtab])\n\n\
This function parses /etc/mtab or /proc/self/mountinfo\n\
/run/mount/utabs or /proc/mounts.\n\
\n\
See also Tab.parser_errcb().\n\
\n\
Returns self or raises an exception in case of an error."
static PyObject *Tab_parse_mtab(TabObject *self, PyObject* args, PyObject *kwds)
{
int rc;
char *mtab = NULL;
char *kwlist[] = {"mtab", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &mtab)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return (rc = mnt_table_parse_mtab(self->tab, mtab)) ? UL_RaiseExc(-rc) : UL_IncRef(self);
}
#define Tab_parse_dir_HELP "parse_dir(dir)\n\n\
The directory:\n\
- files are sorted by strverscmp(3)\n\
- files that start with \".\" are ignored (e.g. \".10foo.fstab\")\n\
- files without the \".fstab\" extension are ignored\n\
\n\
Returns self or raises an exception in case of an error."
static PyObject *Tab_parse_dir(TabObject *self, PyObject* args, PyObject *kwds)
{
int rc;
char *dir = NULL;
char *kwlist[] = {"dir", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &dir)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return (rc = mnt_table_parse_dir(self->tab, dir)) ? UL_RaiseExc(-rc) : UL_IncRef(self);
}
#define Tab_parse_swaps_HELP "parse_swaps(swaps)\n\n\
This function parses /proc/swaps and appends new lines to the tab"
static PyObject *Tab_parse_swaps(TabObject *self, PyObject* args, PyObject *kwds)
{
int rc;
char *swaps = NULL;
char *kwlist[] = {"swaps", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &swaps)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
return (rc = mnt_table_parse_swaps(self->tab, swaps)) ? UL_RaiseExc(-rc) : UL_IncRef(self);
}
#define Tab_parse_stream_HELP "parse_stream(stream, filename)\n\n\
Returns self or raises an exception in case of an error."
static PyObject *Tab_parse_stream(TabObject *self, PyObject* args, PyObject *kwds)
{
int rc;
PyFileObject *stream = NULL;
char *filename = NULL;
FILE *f;
char *kwlist[] = {"stream", "filename", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!s", kwlist, &PyFile_Type, &stream, &filename)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
f = PyFile_AsFile((PyObject *)stream);
return (rc = mnt_table_parse_stream(self->tab, f, filename)) ? UL_RaiseExc(-rc) : UL_IncRef(self);
}
#define Tab_add_fs_HELP "add_fs(fs)\n\nAdds a new entry to tab.\n\
Returns self or raises an exception in case of an error."
static PyObject *Tab_add_fs(TabObject *self, PyObject* args, PyObject *kwds)
{
int rc;
FsObject *fs = NULL;
char *kwlist[] = {"fs", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &FsType, &fs)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
Py_INCREF(fs);
return (rc = mnt_table_add_fs(self->tab, fs->fs)) ? UL_RaiseExc(-rc) : UL_IncRef(self);
}
#define Tab_remove_fs_HELP "remove_fs(fs)\n\n\
Returns self or raises an exception in case of an error."
static PyObject *Tab_remove_fs(TabObject *self, PyObject* args, PyObject *kwds)
{
int rc;
FsObject *fs = NULL;
char *kwlist[] = {"fs", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &FsType, &fs)) {
PyErr_SetString(PyExc_TypeError, ARG_ERR);
return NULL;
}
rc = mnt_table_remove_fs(self->tab, fs->fs);
Py_DECREF(fs);
return (rc) ? UL_RaiseExc(-rc) : UL_IncRef(self);
}
#define Tab_next_fs_HELP "next_fs()\n\n\
Returns the next Fs on success, raises an exception in case of an error and None at end of list.\n\
\n\
Example:\n\
<informalexample>\n\
<programlisting>\n\
import libmount\n\
import functools\n\
for fs in iter(functools.partial(tb.next_fs), None): {\n\
dir = Fs.target\n\
print \"mount point: {:s}\n\".format(dir)\n\
}\n\
</programlisting>\n\
</informalexample>\n\
\n\
lists all mountpoints from fstab in backward order."
static PyObject *Tab_next_fs(TabObject *self)
{
struct libmnt_fs *fs;
int rc;
/* Reset the builtin iterator after reaching the end of the list */
rc = mnt_table_next_fs(self->tab, self->iter, &fs);
if (rc == 1) {
mnt_reset_iter(self->iter, MNT_ITER_FORWARD);
Py_RETURN_NONE;
} else if (rc)
return UL_RaiseExc(-rc);
return PyObjectResultFs(fs);
}
static PyMethodDef Tab_methods[] = {
{"enable_comments", (PyCFunction)Tab_enable_comments, METH_VARARGS|METH_KEYWORDS, Tab_enable_comments_HELP},
{"find_pair", (PyCFunction)Tab_find_pair, METH_VARARGS|METH_KEYWORDS, Tab_find_pair_HELP},
{"find_source", (PyCFunction)Tab_find_source, METH_VARARGS|METH_KEYWORDS, Tab_find_source_HELP},
{"find_srcpath", (PyCFunction)Tab_find_srcpath, METH_VARARGS|METH_KEYWORDS, Tab_find_srcpath_HELP},
{"find_tag", (PyCFunction)Tab_find_tag, METH_VARARGS|METH_KEYWORDS, Tab_find_tag_HELP},
{"find_target", (PyCFunction)Tab_find_target, METH_VARARGS|METH_KEYWORDS, Tab_find_target_HELP},
{"find_devno", (PyCFunction)Tab_find_devno, METH_VARARGS|METH_KEYWORDS, Tab_find_devno_HELP},
{"find_mountpoint", (PyCFunction)Tab_find_mountpoint, METH_VARARGS|METH_KEYWORDS, Tab_find_mountpoint_HELP},
{"parse_file", (PyCFunction)Tab_parse_file, METH_VARARGS|METH_KEYWORDS, Tab_parse_file_HELP},
{"parse_fstab", (PyCFunction)Tab_parse_fstab, METH_VARARGS|METH_KEYWORDS, Tab_parse_fstab_HELP},
{"parse_mtab", (PyCFunction)Tab_parse_mtab, METH_VARARGS|METH_KEYWORDS, Tab_parse_mtab_HELP},
{"parse_dir", (PyCFunction)Tab_parse_dir, METH_VARARGS|METH_KEYWORDS, Tab_parse_dir_HELP},
{"parse_swaps", (PyCFunction)Tab_parse_swaps, METH_VARARGS|METH_KEYWORDS, Tab_parse_swaps_HELP},
{"is_fs_mounted", (PyCFunction)Tab_is_fs_mounted, METH_VARARGS|METH_KEYWORDS, Tab_is_fs_mounted_HELP},
{"parse_stream", (PyCFunction)Tab_parse_stream, METH_VARARGS|METH_KEYWORDS, Tab_parse_stream_HELP},
{"add_fs", (PyCFunction)Tab_add_fs, METH_VARARGS|METH_KEYWORDS, Tab_add_fs_HELP},
{"remove_fs", (PyCFunction)Tab_remove_fs, METH_VARARGS|METH_KEYWORDS, Tab_remove_fs_HELP},
{"next_fs", (PyCFunction)Tab_next_fs, METH_NOARGS, Tab_next_fs_HELP},
{"write_file", (PyCFunction)Tab_write_file, METH_VARARGS|METH_KEYWORDS, Tab_write_file_HELP},
{"replace_file", (PyCFunction)Tab_replace_file, METH_VARARGS|METH_KEYWORDS, Tab_replace_file_HELP},
{NULL}
};
/* mnt_free_tab() with a few necessary additions */
void pymnt_free_table(struct libmnt_table *tab)
{
if (!tab)
return;
while (!list_empty(&tab->ents)) {
struct libmnt_fs *fs = list_entry(tab->ents.next, struct libmnt_fs, ents);
if (fs->userdata)
Py_DECREF(fs->userdata); /* (possible) destruction via object destructor */
else
mnt_free_fs(fs); /* no encapsulating object, free fs */
}
mnt_free_table(tab);
}
static void Tab_destructor(TabObject *self)
{
pymnt_free_table(self->tab);
mnt_free_iter(self->iter);
Py_XDECREF(self->errcb);
self->ob_type->tp_free((PyObject*)self);
}
static PyObject *Tab_new(PyTypeObject *type, PyObject *args __attribute__((unused)),
PyObject *kwds __attribute__((unused)))
{
TabObject *self = (TabObject*)type->tp_alloc(type, 0);
if (self) {
self->tab = NULL;
self->iter = NULL;
self->errcb = NULL;
}
return (PyObject *)self;
}
/* explicit tab.__init__() serves as mnt_reset_table(tab) would in C
* and as mnt_new_table{,_from_dir,_from_file}() with proper arguments */
#define Tab_HELP "Tab(path=None, errcb=None)"
static int Tab_init(TabObject *self, PyObject *args, PyObject *kwds)
{
struct libmnt_cache *cache;
char *path = NULL;
char *kwlist[] = {"path", "errcb", NULL};
PyObject *errcb = NULL;
struct stat buf;
memset (&buf, 0, sizeof(struct stat));
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sO", kwlist, &path, &errcb)) {
return -1;
}
pymnt_free_table(self->tab);
self->tab = NULL;
if (self->iter)
mnt_reset_iter(self->iter, MNT_ITER_FORWARD);
else
self->iter = mnt_new_iter(MNT_ITER_FORWARD);
if (errcb) {
if (!PyCallable_Check(errcb)) {
return -1;
}
PyObject *tmp = self->errcb;
Py_INCREF(errcb);
self->errcb = errcb;
Py_XDECREF(tmp);
} else {
Py_XDECREF(self->errcb);
self->errcb = NULL;
}
if (path) {
if (stat(path, &buf)) {
/* TODO: weird */
PyErr_SetFromErrno(PyExc_RuntimeError);
return -1;
}
if (S_ISREG(buf.st_mode))
self->tab = mnt_new_table_from_file(path);
else if (S_ISDIR(buf.st_mode))
self->tab = mnt_new_table_from_dir(path);
} else
self->tab = mnt_new_table();
/* Always set custom handler when using libmount from python */
self->tab->errcb = pymnt_table_parser_errcb;
self->tab->userdata = (void *)self;
/* TODO: perhaps make this optional? */
cache = mnt_new_cache();
if (!cache)
return -1;
mnt_table_set_cache(self->tab, cache);
return 0;
}
/* Handler for the tab->errcb callback */
int pymnt_table_parser_errcb(struct libmnt_table *tb, const char *filename, int line)
{
int rc = 0;
PyObject *arglist, *result;
if (tb->userdata && ((TabObject*)(tb->userdata))->errcb) {
arglist = Py_BuildValue("(Osi)", tb->userdata, filename, line);
if (!arglist)
return -ENOMEM;
/* A python callback was set, so tb is definitely encapsulated in an object */
result = PyEval_CallObject(((TabObject *)(tb->userdata))->errcb, arglist);
Py_DECREF(arglist);
if (!result)
return -EINVAL;
if (!PyArg_Parse(result, "i", &rc))
rc = -EINVAL;
Py_DECREF(result);
}
return rc;
}
PyObject *PyObjectResultTab(struct libmnt_table *tab)
{
if (!tab) {
PyErr_SetString(LibmountError, "internal exception");
return NULL;
}
if (tab->userdata) {
Py_INCREF(tab->userdata);
return (PyObject *)tab->userdata;
}
TabObject *result = PyObject_New(TabObject, &TabType);
if (!result) {
UL_RaiseExc(ENOMEM);
return NULL;
}
/* Creating an encapsualing object: increment the refcount, so that code
* such as:
* cxt.get_fstab()
* doesn't call the destructor, which would free our tab struct as well
*/
Py_INCREF(result);
result->tab = tab;
result->iter = mnt_new_iter(MNT_ITER_FORWARD);
result->tab->userdata = (void *)result;
result->errcb = NULL;
return (PyObject *)result;
}
static PyGetSetDef Tab_getseters[] = {
{"nents", (getter)Tab_get_nents, NULL, "number of valid entries in tab", NULL},
{"intro_comment", (getter)Tab_get_intro_comment, (setter)Tab_set_intro_comment, "fstab intro comment", NULL},
{"trailing_comment", (getter)Tab_get_trailing_comment, (setter)Tab_set_trailing_comment, "fstab trailing comment", NULL},
{"errcb", NULL, (setter)Tab_set_parser_errcb, "parser error callback", NULL},
{NULL}
};
static PyObject *Table_repr(TabObject *self)
{
return PyString_FromFormat(
"<libmount.Table object at %p, entries=%d, comments_enabled=%s, errcb=%s>",
self,
self->tab->nents,
self->tab->comms ? "True" : "False",
self->errcb ? pystos(PyObject_Repr(self->errcb)) : "None");
}
PyTypeObject TabType = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"libmount.Tab", /*tp_name*/
sizeof(TabObject), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)Tab_destructor, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
(reprfunc) Table_repr, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Tab_HELP, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
Tab_methods, /* tp_methods */
Tab_members, /* tp_members */
Tab_getseters, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)Tab_init, /* tp_init */
0, /* tp_alloc */
Tab_new, /* tp_new */
};
void pymnt_init_table(PyObject *mod)
{
if (PyType_Ready(&TabType) < 0)
return;
Py_INCREF(&TabType);
PyModule_AddObject(mod, "Tab", (PyObject *)&TabType);
}