| /* |
| * 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; |
| |
| } else 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; |
| } else 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; |
| |
| } else 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*/ |
| NULL, /*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); |
| } |
| |