diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 14:30:35 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 14:30:35 +0000 |
commit | 378c18e5f024ac5a8aef4cb40d7c9aa9633d144c (patch) | |
tree | 44dfb6ca500d32cabd450649b322a42e70a30683 /libmount/python/fs.c | |
parent | Initial commit. (diff) | |
download | util-linux-upstream.tar.xz util-linux-upstream.zip |
Adding upstream version 2.38.1.upstream/2.38.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'libmount/python/fs.c')
-rw-r--r-- | libmount/python/fs.c | 883 |
1 files changed, 883 insertions, 0 deletions
diff --git a/libmount/python/fs.c b/libmount/python/fs.c new file mode 100644 index 0000000..e989124 --- /dev/null +++ b/libmount/python/fs.c @@ -0,0 +1,883 @@ +/* + * 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); +} + |