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:
parent
d78df0ac65
commit
813683a352
|
@ -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 = \
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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 */
|
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue