884 lines
26 KiB
C
884 lines
26 KiB
C
/*
|
|
* 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"
|
|
#include <errno.h>
|
|
|
|
#define Fs_HELP "Fs(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;
|
|
|
|
if (mnt_fs_get_tag(self->fs, &tag, &val) != 0)
|
|
return NULL;
|
|
|
|
result = Py_BuildValue("(ss)", tag, val);
|
|
if (!result)
|
|
PyErr_SetString(PyExc_RuntimeError, CONSTRUCT_ERR);
|
|
return result;
|
|
}
|
|
|
|
static PyObject *Fs_get_id(FsObject *self)
|
|
{
|
|
return PyObjectResultInt(mnt_fs_get_id(self->fs));
|
|
}
|
|
|
|
static PyObject *Fs_get_parent_id(FsObject *self)
|
|
{
|
|
return PyObjectResultInt(mnt_fs_get_parent_id(self->fs));
|
|
}
|
|
|
|
static PyObject *Fs_get_devno(FsObject *self)
|
|
{
|
|
return PyObjectResultInt(mnt_fs_get_devno(self->fs));
|
|
}
|
|
|
|
static void _dump_debug_string(const char *lead, const char *s, char quote)
|
|
{
|
|
/* PySys_WriteStdout() will automatically truncate any '%s' token
|
|
* longer than a certain length (documented as 1000 bytes, but we
|
|
* give ourselves some margin here just in case). The only way I
|
|
* know to get around this is to print such strings in bite-sized
|
|
* chunks.
|
|
*/
|
|
static const unsigned int _PY_MAX_LEN = 900;
|
|
static const char *_PY_MAX_LEN_FMT = "%.900s";
|
|
unsigned int len;
|
|
|
|
if (lead != NULL)
|
|
PySys_WriteStdout("%s", lead);
|
|
|
|
if (quote != 0)
|
|
PySys_WriteStdout("%c", quote);
|
|
|
|
for (len = strlen(s); len > _PY_MAX_LEN; len -= _PY_MAX_LEN, s += _PY_MAX_LEN)
|
|
PySys_WriteStdout(_PY_MAX_LEN_FMT, s);
|
|
|
|
if (len > 0)
|
|
PySys_WriteStdout(_PY_MAX_LEN_FMT, s);
|
|
|
|
if (quote != 0)
|
|
PySys_WriteStdout("%c\n", quote);
|
|
else
|
|
PySys_WriteStdout("\n");
|
|
}
|
|
|
|
#define Fs_print_debug_HELP "print_debug()\n\n"
|
|
static PyObject *Fs_print_debug(FsObject *self)
|
|
{
|
|
PySys_WriteStdout("------ fs: %p\n", self->fs);
|
|
_dump_debug_string("source: ", mnt_fs_get_source(self->fs), 0);
|
|
_dump_debug_string("target: ", mnt_fs_get_target(self->fs), 0);
|
|
_dump_debug_string("fstype: ", mnt_fs_get_fstype(self->fs), 0);
|
|
|
|
if (mnt_fs_get_options(self->fs))
|
|
_dump_debug_string("optstr: ", mnt_fs_get_options(self->fs), 0);
|
|
if (mnt_fs_get_vfs_options(self->fs))
|
|
_dump_debug_string("VFS-optstr: ", mnt_fs_get_vfs_options(self->fs), 0);
|
|
if (mnt_fs_get_fs_options(self->fs))
|
|
_dump_debug_string("FS-opstr: ", mnt_fs_get_fs_options(self->fs), 0);
|
|
if (mnt_fs_get_user_options(self->fs))
|
|
_dump_debug_string("user-optstr: ", mnt_fs_get_user_options(self->fs), 0);
|
|
if (mnt_fs_get_optional_fields(self->fs))
|
|
_dump_debug_string("optional-fields: ", mnt_fs_get_optional_fields(self->fs), '\'');
|
|
if (mnt_fs_get_attributes(self->fs))
|
|
_dump_debug_string("attributes: ", mnt_fs_get_attributes(self->fs), 0);
|
|
|
|
if (mnt_fs_get_root(self->fs))
|
|
_dump_debug_string("root: ", mnt_fs_get_root(self->fs), 0);
|
|
|
|
if (mnt_fs_get_swaptype(self->fs))
|
|
_dump_debug_string("swaptype: ", mnt_fs_get_swaptype(self->fs), 0);
|
|
if (mnt_fs_get_size(self->fs))
|
|
PySys_WriteStdout("size: %jd\n", mnt_fs_get_size(self->fs));
|
|
if (mnt_fs_get_usedsize(self->fs))
|
|
PySys_WriteStdout("usedsize: %jd\n", mnt_fs_get_usedsize(self->fs));
|
|
if (mnt_fs_get_priority(self->fs))
|
|
PySys_WriteStdout("priority: %d\n", mnt_fs_get_priority(self->fs));
|
|
|
|
if (mnt_fs_get_bindsrc(self->fs))
|
|
_dump_debug_string("bindsrc: ", mnt_fs_get_bindsrc(self->fs), 0);
|
|
if (mnt_fs_get_freq(self->fs))
|
|
PySys_WriteStdout("freq: %d\n", mnt_fs_get_freq(self->fs));
|
|
if (mnt_fs_get_passno(self->fs))
|
|
PySys_WriteStdout("pass: %d\n", mnt_fs_get_passno(self->fs));
|
|
if (mnt_fs_get_id(self->fs))
|
|
PySys_WriteStdout("id: %d\n", mnt_fs_get_id(self->fs));
|
|
if (mnt_fs_get_parent_id(self->fs))
|
|
PySys_WriteStdout("parent: %d\n", mnt_fs_get_parent_id(self->fs));
|
|
if (mnt_fs_get_devno(self->fs))
|
|
PySys_WriteStdout("devno: %d:%d\n", major(mnt_fs_get_devno(self->fs)),
|
|
minor(mnt_fs_get_devno(self->fs)));
|
|
if (mnt_fs_get_tid(self->fs))
|
|
PySys_WriteStdout("tid: %d\n", mnt_fs_get_tid(self->fs));
|
|
if (mnt_fs_get_comment(self->fs))
|
|
_dump_debug_string("comment: ", mnt_fs_get_comment(self->fs), '\'');
|
|
return UL_IncRef(self);
|
|
}
|
|
/*
|
|
** Fs getters/setters
|
|
*/
|
|
|
|
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;
|
|
}
|
|
|
|
static PyObject *Fs_get_srcpath(FsObject *self)
|
|
{
|
|
return PyObjectResultStr(mnt_fs_get_srcpath(self->fs));
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
static PyObject *Fs_get_vfs_options(FsObject *self)
|
|
{
|
|
return PyObjectResultStr(mnt_fs_get_vfs_options(self->fs));
|
|
}
|
|
|
|
|
|
static PyObject *Fs_get_optional_fields(FsObject *self)
|
|
{
|
|
return PyObjectResultStr(mnt_fs_get_optional_fields(self->fs));
|
|
}
|
|
|
|
|
|
static PyObject *Fs_get_fs_options(FsObject *self)
|
|
{
|
|
return PyObjectResultStr(mnt_fs_get_fs_options(self->fs));
|
|
}
|
|
|
|
|
|
static PyObject *Fs_get_user_options(FsObject *self)
|
|
{
|
|
return PyObjectResultStr(mnt_fs_get_user_options(self->fs));
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
if (!PyLong_Check(value)) {
|
|
PyErr_SetString(PyExc_TypeError, ARG_ERR);
|
|
return -1;
|
|
}
|
|
|
|
freq = PyLong_AsLong(value);
|
|
if (freq == -1 && PyErr_Occurred()) {
|
|
PyErr_SetString(PyExc_RuntimeError, "type conversion failed");
|
|
return -1;
|
|
}
|
|
return mnt_fs_set_freq(self->fs, freq);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
if (!PyLong_Check(value)) {
|
|
PyErr_SetString(PyExc_TypeError, ARG_ERR);
|
|
return -1;
|
|
}
|
|
|
|
passno = PyLong_AsLong(value);
|
|
if (passno == -1 && PyErr_Occurred()) {
|
|
PyErr_SetString(PyExc_RuntimeError, "type conversion failed");
|
|
return -1;
|
|
}
|
|
return mnt_fs_set_passno(self->fs, passno);
|
|
}
|
|
|
|
static PyObject *Fs_get_swaptype(FsObject *self)
|
|
{
|
|
return PyObjectResultStr(mnt_fs_get_swaptype(self->fs));
|
|
}
|
|
|
|
static PyObject *Fs_get_size(FsObject *self)
|
|
{
|
|
return PyObjectResultInt(mnt_fs_get_size(self->fs));
|
|
}
|
|
|
|
static PyObject *Fs_get_usedsize(FsObject *self)
|
|
{
|
|
return PyObjectResultInt(mnt_fs_get_usedsize(self->fs));
|
|
}
|
|
|
|
static PyObject *Fs_get_priority(FsObject *self)
|
|
{
|
|
return PyObjectResultInt(mnt_fs_get_priority(self->fs));
|
|
}
|
|
|
|
#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)
|
|
{
|
|
unsigned long flags;
|
|
int rc;
|
|
|
|
rc = mnt_fs_get_propagation(self->fs, &flags);
|
|
return rc ? UL_RaiseExc(-rc) : PyObjectResultInt(flags);
|
|
}
|
|
|
|
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;
|
|
}
|
|
rc = mnt_fs_append_attributes(self->fs, optstr);
|
|
return rc ? 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;
|
|
}
|
|
rc = mnt_fs_append_options(self->fs, optstr);
|
|
return rc ? 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;
|
|
}
|
|
rc = mnt_fs_prepend_attributes(self->fs, optstr);
|
|
return rc ? 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;
|
|
}
|
|
rc = mnt_fs_prepend_options(self->fs, optstr);
|
|
return rc ? 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."
|
|
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_NOARGS, 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_NOARGS, Fs_print_debug_HELP},
|
|
{NULL}
|
|
};
|
|
|
|
static void Fs_destructor(FsObject *self)
|
|
{
|
|
DBG(FS, pymnt_debug_h(self->fs, "destructor py-obj: %p, py-refcnt=%d",
|
|
self, (int) ((PyObject *) self)->ob_refcnt));
|
|
mnt_unref_fs(self->fs);
|
|
PyFree(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;
|
|
DBG(FS, pymnt_debug_h(self, "new"));
|
|
}
|
|
return (PyObject *) self;
|
|
}
|
|
|
|
static int Fs_init(FsObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
char *source = NULL, *root = NULL, *target = NULL;
|
|
char *fstype = NULL, *options = NULL, *attributes =NULL;
|
|
int freq = 0; int passno = 0;
|
|
int rc = 0;
|
|
char *kwlist[] = {
|
|
"source", "root", "target",
|
|
"fstype", "options", "attributes",
|
|
"freq", "passno", NULL
|
|
};
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ssssssii", kwlist,
|
|
&source, &root, &target, &fstype, &options,
|
|
&attributes, &freq, &passno)) {
|
|
PyErr_SetString(PyExc_TypeError, "Invalid type");
|
|
return -1;
|
|
}
|
|
|
|
DBG(FS, pymnt_debug_h(self, "init"));
|
|
|
|
if (self->fs)
|
|
mnt_unref_fs(self->fs);
|
|
|
|
self->fs = mnt_new_fs(); /* new FS with refcount=1 */
|
|
|
|
if (source && (rc = mnt_fs_set_source(self->fs, source))) {
|
|
PyErr_SetString(PyExc_MemoryError, MEMORY_ERR);
|
|
return rc;
|
|
}
|
|
if (root && (rc = mnt_fs_set_root(self->fs, root))) {
|
|
PyErr_SetString(PyExc_MemoryError, MEMORY_ERR);
|
|
return rc;
|
|
}
|
|
if (target && (rc = mnt_fs_set_target(self->fs, target))) {
|
|
PyErr_SetString(PyExc_MemoryError, MEMORY_ERR);
|
|
return rc;
|
|
}
|
|
if (fstype && (rc = mnt_fs_set_fstype(self->fs, fstype))) {
|
|
PyErr_SetString(PyExc_MemoryError, MEMORY_ERR);
|
|
return rc;
|
|
}
|
|
if (options && (rc = mnt_fs_set_options(self->fs, options))) {
|
|
PyErr_SetString(PyExc_MemoryError, MEMORY_ERR);
|
|
return rc;
|
|
}
|
|
if (attributes && (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);
|
|
mnt_fs_set_userdata(self->fs, 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},
|
|
{"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)
|
|
{
|
|
const char *src = mnt_fs_get_source(self->fs),
|
|
*tgt = mnt_fs_get_target(self->fs),
|
|
*type = mnt_fs_get_fstype(self->fs);
|
|
|
|
return PyUnicode_FromFormat(
|
|
"<libmount.Fs object at %p, "
|
|
"source=%s, target=%s, fstype=%s>",
|
|
self,
|
|
src ? src : "None",
|
|
tgt ? tgt : "None",
|
|
type ? type : "None");
|
|
}
|
|
|
|
PyObject *PyObjectResultFs(struct libmnt_fs *fs)
|
|
{
|
|
FsObject *result;
|
|
|
|
if (!fs) {
|
|
PyErr_SetString(LibmountError, "internal exception");
|
|
return NULL;
|
|
}
|
|
|
|
result = mnt_fs_get_userdata(fs);
|
|
if (result) {
|
|
Py_INCREF(result);
|
|
DBG(FS, pymnt_debug_h(fs, "result py-obj %p: already exists, py-refcnt=%d",
|
|
result, (int) ((PyObject *) result)->ob_refcnt));
|
|
return (PyObject *) result;
|
|
}
|
|
|
|
/* Creating an encapsulating 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
|
|
*/
|
|
result = PyObject_New(FsObject, &FsType);
|
|
if (!result) {
|
|
UL_RaiseExc(ENOMEM);
|
|
return NULL;
|
|
}
|
|
|
|
Py_INCREF(result);
|
|
mnt_ref_fs(fs);
|
|
|
|
DBG(FS, pymnt_debug_h(fs, "result py-obj %p new, py-refcnt=%d",
|
|
result, (int) ((PyObject *) result)->ob_refcnt));
|
|
result->fs = fs;
|
|
mnt_fs_set_userdata(fs, 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;
|
|
DBG(FS, pymnt_debug_h(dest, "copy data"));
|
|
return (PyObject *)dest;
|
|
|
|
}
|
|
|
|
if (dest == Py_None) { /* create new object */
|
|
FsObject *result = PyObject_New(FsObject, &FsType);
|
|
|
|
DBG(FS, pymnt_debug_h(result, "new copy"));
|
|
result->fs = mnt_copy_fs(NULL, self->fs);
|
|
mnt_fs_set_userdata(result->fs, result); /* keep a pointer to encapsulating object */
|
|
return (PyObject *)result;
|
|
}
|
|
|
|
PyErr_SetString(PyExc_TypeError, ARG_ERR);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
PyTypeObject FsType = {
|
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
"libmount.Fs", /*tp_name*/
|
|
sizeof(FsObject), /*tp_basicsize*/
|
|
0, /*tp_itemsize*/
|
|
(destructor)Fs_destructor, /*tp_dealloc*/
|
|
0, /*tp_print*/
|
|
NULL, /*tp_getattr*/
|
|
NULL, /*tp_setattr*/
|
|
NULL, /*tp_compare*/
|
|
(reprfunc)Fs_repr, /*tp_repr*/
|
|
NULL, /*tp_as_number*/
|
|
NULL, /*tp_as_sequence*/
|
|
NULL, /*tp_as_mapping*/
|
|
NULL, /*tp_hash */
|
|
NULL, /*tp_call*/
|
|
NULL, /*tp_str*/
|
|
NULL, /*tp_getattro*/
|
|
NULL, /*tp_setattro*/
|
|
NULL, /*tp_as_buffer*/
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
|
Fs_HELP, /* tp_doc */
|
|
NULL, /* tp_traverse */
|
|
NULL, /* tp_clear */
|
|
NULL, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
NULL, /* tp_iter */
|
|
NULL, /* tp_iternext */
|
|
Fs_methods, /* tp_methods */
|
|
Fs_members, /* tp_members */
|
|
Fs_getseters, /* tp_getset */
|
|
NULL, /* tp_base */
|
|
NULL, /* tp_dict */
|
|
NULL, /* tp_descr_get */
|
|
NULL, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)Fs_init, /* tp_init */
|
|
NULL, /* tp_alloc */
|
|
Fs_new, /* tp_new */
|
|
};
|
|
|
|
void FS_AddModuleObject(PyObject *mod)
|
|
{
|
|
if (PyType_Ready(&FsType) < 0)
|
|
return;
|
|
|
|
DBG(FS, pymnt_debug("add to module"));
|
|
Py_INCREF(&FsType);
|
|
PyModule_AddObject(mod, "Fs", (PyObject *)&FsType);
|
|
}
|
|
|