]> git.ipfire.org Git - thirdparty/util-linux.git/blame - libmount/python/fs.c
[clang-tidy] do not use else after return
[thirdparty/util-linux.git] / libmount / python / fs.c
CommitLineData
813683a3
OO
1/*
2 * Python bindings for the libmount library.
3 *
4 * Copyright (C) 2013, Red Hat, Inc. All rights reserved.
5 * Written by Ondrej Oprala and Karel Zak
6 *
7 * This file is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 3 of the License, or (at your option) any later version.
11 *
12 * This file is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this file; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22/*
23 * TODO:
24 * mnt_fs_match_{source,target}
25 * mnt_fs_get_{attribute,option}
26 */
27
28#include "pylibmount.h"
46407453 29#include <errno.h>
813683a3 30
71fbe151 31#define Fs_HELP "Fs(source=None, root=None, target=None, fstype=None, options=None, attributes=None, freq=0, passno=0)"
813683a3
OO
32
33static PyMemberDef Fs_members[] = {
34 {NULL}
35};
36
37static PyObject *Fs_get_tag(FsObject *self)
38{
39 const char *tag = NULL, *val = NULL;
40 PyObject *result;
41
1d4d4b42
KZ
42 if (mnt_fs_get_tag(self->fs, &tag, &val) != 0)
43 return NULL;
813683a3
OO
44
45 result = Py_BuildValue("(ss)", tag, val);
46 if (!result)
47 PyErr_SetString(PyExc_RuntimeError, CONSTRUCT_ERR);
48 return result;
49}
71fbe151 50
813683a3
OO
51static PyObject *Fs_get_id(FsObject *self)
52{
53 return PyObjectResultInt(mnt_fs_get_id(self->fs));
54}
71fbe151 55
813683a3
OO
56static PyObject *Fs_get_parent_id(FsObject *self)
57{
58 return PyObjectResultInt(mnt_fs_get_parent_id(self->fs));
59}
71fbe151 60
813683a3
OO
61static PyObject *Fs_get_devno(FsObject *self)
62{
63 return PyObjectResultInt(mnt_fs_get_devno(self->fs));
64}
71fbe151 65
8a12ab57
FS
66static void _dump_debug_string(const char *lead, const char *s, char quote)
67{
68 /* PySys_WriteStdout() will automatically truncate any '%s' token
69 * longer than a certain length (documented as 1000 bytes, but we
70 * give ourselves some margin here just in case). The only way I
71 * know to get around this is to print such strings in bite-sized
72 * chunks.
73 */
74 static const unsigned int _PY_MAX_LEN = 900;
75 static const char *_PY_MAX_LEN_FMT = "%.900s";
76 unsigned int len;
77
78 if (lead != NULL)
79 PySys_WriteStdout("%s", lead);
80
81 if (quote != 0)
82 PySys_WriteStdout("%c", quote);
83
2bb3aa36 84 for (len = strlen(s); len > _PY_MAX_LEN; len -= _PY_MAX_LEN, s += _PY_MAX_LEN)
8a12ab57
FS
85 PySys_WriteStdout(_PY_MAX_LEN_FMT, s);
86
87 if (len > 0)
88 PySys_WriteStdout(_PY_MAX_LEN_FMT, s);
89
90 if (quote != 0)
91 PySys_WriteStdout("%c\n", quote);
92 else
93 PySys_WriteStdout("\n");
94}
95
46407453
OO
96#define Fs_print_debug_HELP "print_debug()\n\n"
97static PyObject *Fs_print_debug(FsObject *self)
98{
99 PySys_WriteStdout("------ fs: %p\n", self->fs);
8a12ab57
FS
100 _dump_debug_string("source: ", mnt_fs_get_source(self->fs), 0);
101 _dump_debug_string("target: ", mnt_fs_get_target(self->fs), 0);
102 _dump_debug_string("fstype: ", mnt_fs_get_fstype(self->fs), 0);
46407453
OO
103
104 if (mnt_fs_get_options(self->fs))
8a12ab57 105 _dump_debug_string("optstr: ", mnt_fs_get_options(self->fs), 0);
46407453 106 if (mnt_fs_get_vfs_options(self->fs))
8a12ab57 107 _dump_debug_string("VFS-optstr: ", mnt_fs_get_vfs_options(self->fs), 0);
46407453 108 if (mnt_fs_get_fs_options(self->fs))
8a12ab57 109 _dump_debug_string("FS-opstr: ", mnt_fs_get_fs_options(self->fs), 0);
46407453 110 if (mnt_fs_get_user_options(self->fs))
8a12ab57 111 _dump_debug_string("user-optstr: ", mnt_fs_get_user_options(self->fs), 0);
46407453 112 if (mnt_fs_get_optional_fields(self->fs))
8a12ab57 113 _dump_debug_string("optional-fields: ", mnt_fs_get_optional_fields(self->fs), '\'');
46407453 114 if (mnt_fs_get_attributes(self->fs))
8a12ab57 115 _dump_debug_string("attributes: ", mnt_fs_get_attributes(self->fs), 0);
46407453
OO
116
117 if (mnt_fs_get_root(self->fs))
8a12ab57 118 _dump_debug_string("root: ", mnt_fs_get_root(self->fs), 0);
46407453
OO
119
120 if (mnt_fs_get_swaptype(self->fs))
8a12ab57 121 _dump_debug_string("swaptype: ", mnt_fs_get_swaptype(self->fs), 0);
46407453
OO
122 if (mnt_fs_get_size(self->fs))
123 PySys_WriteStdout("size: %jd\n", mnt_fs_get_size(self->fs));
124 if (mnt_fs_get_usedsize(self->fs))
125 PySys_WriteStdout("usedsize: %jd\n", mnt_fs_get_usedsize(self->fs));
126 if (mnt_fs_get_priority(self->fs))
127 PySys_WriteStdout("priority: %d\n", mnt_fs_get_priority(self->fs));
128
129 if (mnt_fs_get_bindsrc(self->fs))
8a12ab57 130 _dump_debug_string("bindsrc: ", mnt_fs_get_bindsrc(self->fs), 0);
46407453
OO
131 if (mnt_fs_get_freq(self->fs))
132 PySys_WriteStdout("freq: %d\n", mnt_fs_get_freq(self->fs));
133 if (mnt_fs_get_passno(self->fs))
134 PySys_WriteStdout("pass: %d\n", mnt_fs_get_passno(self->fs));
135 if (mnt_fs_get_id(self->fs))
136 PySys_WriteStdout("id: %d\n", mnt_fs_get_id(self->fs));
137 if (mnt_fs_get_parent_id(self->fs))
138 PySys_WriteStdout("parent: %d\n", mnt_fs_get_parent_id(self->fs));
139 if (mnt_fs_get_devno(self->fs))
140 PySys_WriteStdout("devno: %d:%d\n", major(mnt_fs_get_devno(self->fs)),
141 minor(mnt_fs_get_devno(self->fs)));
142 if (mnt_fs_get_tid(self->fs))
143 PySys_WriteStdout("tid: %d\n", mnt_fs_get_tid(self->fs));
144 if (mnt_fs_get_comment(self->fs))
8a12ab57 145 _dump_debug_string("comment: ", mnt_fs_get_comment(self->fs), '\'');
46407453 146 return UL_IncRef(self);
813683a3
OO
147}
148/*
149 ** Fs getters/setters
150 */
151
813683a3
OO
152static PyObject *Fs_get_comment(FsObject *self, void *closure __attribute__((unused)))
153{
154 return PyObjectResultStr(mnt_fs_get_comment(self->fs));
155}
156
157static int Fs_set_comment(FsObject *self, PyObject *value, void *closure __attribute__((unused)))
158{
159 char *comment = NULL;
160 int rc = 0;
161
162 if (!value) {
163 PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
164 return -1;
165 }
166 if (!(comment = pystos(value)))
167 return -1;
168
169 rc = mnt_fs_set_comment(self->fs, comment);
170 if (rc) {
171 UL_RaiseExc(-rc);
172 return -1;
173 }
174 return 0;
175}
176/* source */
177static PyObject *Fs_get_source(FsObject *self)
178{
179 return PyObjectResultStr(mnt_fs_get_source(self->fs));
180}
181
182static int Fs_set_source(FsObject *self, PyObject *value, void *closure __attribute__((unused)))
183{
184 char *source = NULL;
185 int rc = 0;
679f086c 186
813683a3
OO
187 if (!value) {
188 PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
189 return -1;
190 }
191 if (!(source = pystos(value)))
192 return -1;
193
194 rc = mnt_fs_set_source(self->fs, source);
195 if (rc) {
196 UL_RaiseExc(-rc);
197 return -1;
198 }
199 return 0;
200}
a2cb0250 201
813683a3
OO
202static PyObject *Fs_get_srcpath(FsObject *self)
203{
204 return PyObjectResultStr(mnt_fs_get_srcpath(self->fs));
205}
a2cb0250 206
813683a3
OO
207static PyObject *Fs_get_root(FsObject *self)
208{
209 return PyObjectResultStr(mnt_fs_get_root(self->fs));
210}
211
212static int Fs_set_root(FsObject *self, PyObject *value, void *closure __attribute__((unused)))
213{
214 char *root = NULL;
215 int rc = 0;
679f086c 216
813683a3
OO
217 if (!value) {
218 PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
219 return -1;
220 }
221 if (!(root = pystos(value)))
222 return -1;
223
224 rc = mnt_fs_set_root(self->fs, root);
225 if (rc) {
226 UL_RaiseExc(-rc);
227 return -1;
228 }
229 return 0;
230}
a2cb0250 231
813683a3
OO
232static PyObject *Fs_get_target(FsObject *self)
233{
234 return PyObjectResultStr(mnt_fs_get_target(self->fs));
235}
236
237static int Fs_set_target(FsObject *self, PyObject *value, void *closure __attribute__((unused)))
238{
239 char *target = NULL;
240 int rc = 0;
679f086c 241
813683a3
OO
242 if (!value) {
243 PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
244 return -1;
245 }
246 if (!(target = pystos(value)))
247 return -1;
248
249 rc = mnt_fs_set_target(self->fs, target);
250 if (rc) {
251 UL_RaiseExc(-rc);
252 return -1;
253 }
254 return 0;
255}
a2cb0250 256
813683a3
OO
257static PyObject *Fs_get_fstype(FsObject *self)
258{
259 return PyObjectResultStr(mnt_fs_get_fstype(self->fs));
260}
261
a2cb0250
KZ
262static int Fs_set_fstype(FsObject *self, PyObject *value,
263 void *closure __attribute__((unused)))
813683a3
OO
264{
265 char *fstype = NULL;
266 int rc = 0;
679f086c 267
813683a3
OO
268 if (!value) {
269 PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
270 return -1;
271 }
272 if (!(fstype = pystos(value)))
273 return -1;
274
275 rc = mnt_fs_set_fstype(self->fs, fstype);
276 if (rc) {
277 UL_RaiseExc(-rc);
278 return -1;
279 }
280 return 0;
281}
a2cb0250 282
813683a3
OO
283static PyObject *Fs_get_options(FsObject *self)
284{
285 return PyObjectResultStr(mnt_fs_get_options(self->fs));
286}
287
a2cb0250
KZ
288static int Fs_set_options(FsObject *self, PyObject *value,
289 void *closure __attribute__((unused)))
813683a3
OO
290{
291 char *options = NULL;
292 int rc = 0;
679f086c 293
813683a3
OO
294 if (!value) {
295 PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
296 return -1;
297 }
298 if (!(options = pystos(value)))
299 return -1;
300
301 rc = mnt_fs_set_options(self->fs, options);
302 if (rc) {
303 UL_RaiseExc(-rc);
304 return -1;
305 }
306 return 0;
307}
a2cb0250 308
813683a3
OO
309static PyObject *Fs_get_vfs_options(FsObject *self)
310{
311 return PyObjectResultStr(mnt_fs_get_vfs_options(self->fs));
312}
313
a2cb0250 314
813683a3
OO
315static PyObject *Fs_get_optional_fields(FsObject *self)
316{
317 return PyObjectResultStr(mnt_fs_get_optional_fields(self->fs));
318}
319
a2cb0250 320
813683a3
OO
321static PyObject *Fs_get_fs_options(FsObject *self)
322{
323 return PyObjectResultStr(mnt_fs_get_fs_options(self->fs));
324}
325
a2cb0250 326
813683a3
OO
327static PyObject *Fs_get_user_options(FsObject *self)
328{
329 return PyObjectResultStr(mnt_fs_get_user_options(self->fs));
330}
331
a2cb0250 332
813683a3
OO
333static PyObject *Fs_get_attributes(FsObject *self)
334{
335 return PyObjectResultStr(mnt_fs_get_attributes(self->fs));
336}
337
a2cb0250
KZ
338static int Fs_set_attributes(FsObject *self, PyObject *value,
339 void *closure __attribute__((unused)))
813683a3
OO
340{
341 char *attributes = NULL;
342 int rc = 0;
679f086c 343
813683a3
OO
344 if (!value) {
345 PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
346 return -1;
347 }
348 if (!(attributes = pystos(value)))
349 return -1;
350
351 rc = mnt_fs_set_attributes(self->fs, attributes);
352 if (rc) {
353 UL_RaiseExc(-rc);
354 return -1;
355 }
356 return 0;
357}
a2cb0250 358
813683a3
OO
359static PyObject *Fs_get_freq(FsObject *self, void *closure __attribute__((unused)))
360{
361 return PyObjectResultInt(mnt_fs_get_freq(self->fs));
362}
363
a2cb0250
KZ
364static int Fs_set_freq(FsObject *self, PyObject *value,
365 void *closure __attribute__((unused)))
813683a3
OO
366{
367 int freq = 0;
679f086c 368
813683a3
OO
369 if (!value) {
370 PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
371 return -1;
a2cb0250 372
042f62df
RP
373 }
374
375 if (!PyLong_Check(value)) {
813683a3
OO
376 PyErr_SetString(PyExc_TypeError, ARG_ERR);
377 return -1;
378 }
379
46407453 380 freq = PyLong_AsLong(value);
813683a3
OO
381 if (freq == -1 && PyErr_Occurred()) {
382 PyErr_SetString(PyExc_RuntimeError, "type conversion failed");
383 return -1;
384 }
385 return mnt_fs_set_freq(self->fs, freq);
386}
a2cb0250 387
813683a3
OO
388static PyObject *Fs_get_passno(FsObject *self)
389{
390 return PyObjectResultInt(mnt_fs_get_passno(self->fs));
391}
392
393static int Fs_set_passno(FsObject *self, PyObject *value, void *closure __attribute__((unused)))
394{
395 int passno = 0;
679f086c 396
813683a3
OO
397 if (!value) {
398 PyErr_SetString(PyExc_TypeError, NODEL_ATTR);
399 return -1;
042f62df
RP
400 }
401
402 if (!PyLong_Check(value)) {
813683a3
OO
403 PyErr_SetString(PyExc_TypeError, ARG_ERR);
404 return -1;
405 }
406
46407453 407 passno = PyLong_AsLong(value);
813683a3
OO
408 if (passno == -1 && PyErr_Occurred()) {
409 PyErr_SetString(PyExc_RuntimeError, "type conversion failed");
410 return -1;
411 }
412 return mnt_fs_set_passno(self->fs, passno);
413}
813683a3
OO
414
415static PyObject *Fs_get_swaptype(FsObject *self)
416{
417 return PyObjectResultStr(mnt_fs_get_swaptype(self->fs));
418}
419
813683a3
OO
420static PyObject *Fs_get_size(FsObject *self)
421{
422 return PyObjectResultInt(mnt_fs_get_size(self->fs));
423}
424
813683a3
OO
425static PyObject *Fs_get_usedsize(FsObject *self)
426{
427 return PyObjectResultInt(mnt_fs_get_usedsize(self->fs));
428}
813683a3
OO
429
430static PyObject *Fs_get_priority(FsObject *self)
431{
432 return PyObjectResultInt(mnt_fs_get_priority(self->fs));
433}
a2cb0250 434
813683a3
OO
435#define Fs_get_propagation_HELP "get_propagation(flags)\n\n\
436Note that this function set flags to zero if not found any propagation flag\n\
437in mountinfo file. The kernel default is MS_PRIVATE, this flag is not stored\n\
438in the mountinfo file.\n\
439\n\
440Returns self or raises an exception in case of an error."
f218d8d2 441static PyObject *Fs_get_propagation(FsObject *self)
813683a3
OO
442{
443 unsigned long flags;
f218d8d2 444 int rc;
679f086c 445
f218d8d2
GS
446 rc = mnt_fs_get_propagation(self->fs, &flags);
447 return rc ? UL_RaiseExc(-rc) : PyObjectResultInt(flags);
813683a3 448}
813683a3
OO
449
450static PyObject *Fs_get_tid(FsObject *self)
451{
452 return PyObjectResultInt(mnt_fs_get_tid(self->fs));
453}
a2cb0250
KZ
454
455#define Fs_is_kernel_HELP "is_kernel()\n\nReturns 1 if the filesystem " \
456 "description is read from kernel e.g. /proc/mounts."
813683a3
OO
457static PyObject *Fs_is_kernel(FsObject *self)
458{
459 return PyBool_FromLong(mnt_fs_is_kernel(self->fs));
460}
a2cb0250
KZ
461
462#define Fs_is_netfs_HELP "is_netfs()\n\nReturns 1 if the filesystem is " \
463 "a network filesystem"
813683a3
OO
464static PyObject *Fs_is_netfs(FsObject *self)
465{
466 return PyBool_FromLong(mnt_fs_is_netfs(self->fs));
467}
a2cb0250
KZ
468
469#define Fs_is_pseudofs_HELP "is_pseudofs()\n\nReturns 1 if the filesystem is "\
470 "a pseudo fs type (proc, cgroups)"
813683a3
OO
471static PyObject *Fs_is_pseudofs(FsObject *self)
472{
473 return PyBool_FromLong(mnt_fs_is_pseudofs(self->fs));
474}
a2cb0250
KZ
475
476#define Fs_is_swaparea_HELP "is_swaparea()\n\nReturns 1 if the filesystem " \
477 "uses \"swap\" as a type"
813683a3
OO
478static PyObject *Fs_is_swaparea(FsObject *self)
479{
480 return PyBool_FromLong(mnt_fs_is_swaparea(self->fs));
481}
a2cb0250
KZ
482
483#define Fs_append_attributes_HELP "append_attributes(optstr)\n\n" \
484 "Appends mount attributes."
813683a3
OO
485static PyObject *Fs_append_attributes(FsObject *self, PyObject *args, PyObject *kwds)
486{
487 char *kwlist[] = {"optstr", NULL};
488 char *optstr = NULL;
489 int rc;
679f086c 490
813683a3
OO
491 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &optstr)) {
492 PyErr_SetString(PyExc_TypeError, ARG_ERR);
493 return NULL;
494 }
679f086c
KZ
495 rc = mnt_fs_append_attributes(self->fs, optstr);
496 return rc ? UL_RaiseExc(-rc) : UL_IncRef(self);
813683a3 497}
a2cb0250
KZ
498
499#define Fs_append_options_HELP "append_options(optstr)\n\n" \
500 "Parses (splits) optstr and appends results to VFS, " \
501 "FS and userspace lists of options."
813683a3
OO
502static PyObject *Fs_append_options(FsObject *self, PyObject *args, PyObject *kwds)
503{
504 char *kwlist[] = {"optstr", NULL};
505 char *optstr = NULL;
506 int rc;
679f086c 507
813683a3
OO
508 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &optstr)) {
509 PyErr_SetString(PyExc_TypeError, ARG_ERR);
510 return NULL;
511 }
679f086c
KZ
512 rc = mnt_fs_append_options(self->fs, optstr);
513 return rc ? UL_RaiseExc(-rc) : UL_IncRef(self);
813683a3 514}
679f086c 515
a2cb0250
KZ
516#define Fs_prepend_attributes_HELP "prepend_attributes(optstr)\n\n" \
517 "Prepends mount attributes."
813683a3
OO
518static PyObject *Fs_prepend_attributes(FsObject *self, PyObject *args, PyObject *kwds)
519{
520 char *kwlist[] = {"optstr", NULL};
521 char *optstr = NULL;
522 int rc;
679f086c 523
813683a3
OO
524 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &optstr)) {
525 PyErr_SetString(PyExc_TypeError, ARG_ERR);
526 return NULL;
527 }
679f086c
KZ
528 rc = mnt_fs_prepend_attributes(self->fs, optstr);
529 return rc ? UL_RaiseExc(-rc) : UL_IncRef(self);
813683a3 530}
679f086c 531
a2cb0250
KZ
532#define Fs_prepend_options_HELP "prepend_options(optstr)\n\n" \
533 "Parses (splits) optstr and prepends results to VFS, " \
534 "FS and userspace lists of options."
813683a3
OO
535static PyObject *Fs_prepend_options(FsObject *self, PyObject *args, PyObject *kwds)
536{
537 char *kwlist[] = {"optstr", NULL};
538 char *optstr = NULL;
539 int rc;
679f086c 540
813683a3
OO
541 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &optstr)) {
542 PyErr_SetString(PyExc_TypeError, ARG_ERR);
543 return NULL;
544 }
679f086c
KZ
545 rc = mnt_fs_prepend_options(self->fs, optstr);
546 return rc ? UL_RaiseExc(-rc) : UL_IncRef(self);
813683a3 547}
679f086c 548
a2cb0250
KZ
549#define Fs_match_fstype_HELP "match_fstype(pattern)\n\n" \
550 "pattern: filesystem name or comma delimited list(string) of names\n\n" \
551 "The pattern list of filesystem can be prefixed with a global\n" \
552 "\"no\" prefix to invert matching of the whole list. The \"no\" could\n" \
553 "also be used for individual items in the pattern list. So,\n" \
554 "\"nofoo,bar\" has the same meaning as \"nofoo,nobar\".\n" \
555 "\"bar\" : \"nofoo,bar\" -> False (global \"no\" prefix)\n" \
556 "\"bar\" : \"foo,bar\" -> True\n" \
557 "\"bar\" : \"foo,nobar\" -> False\n\n" \
558 "Returns True if type is matching, else False."
813683a3
OO
559static PyObject *Fs_match_fstype(FsObject *self, PyObject *args, PyObject *kwds)
560{
561 char *kwlist[] = {"pattern", NULL};
562 char *pattern = NULL;
679f086c 563
813683a3
OO
564 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &pattern)) {
565 PyErr_SetString(PyExc_TypeError, ARG_ERR);
566 return NULL;
567 }
568 return PyBool_FromLong(mnt_fs_match_fstype(self->fs, pattern));
569}
679f086c 570
a2cb0250
KZ
571#define Fs_match_options_HELP "match_options(options)\n\n" \
572 "options: comma delimited list of options (and nooptions)\n" \
573 "Returns True if fs type is matching to options else False."
813683a3
OO
574static PyObject *Fs_match_options(FsObject *self, PyObject *args, PyObject *kwds)
575{
576 char *kwlist[] = {"options", NULL};
577 char *options = NULL;
679f086c 578
813683a3
OO
579 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &options)) {
580 PyErr_SetString(PyExc_TypeError, ARG_ERR);
581 return NULL;
582 }
583 return PyBool_FromLong(mnt_fs_match_options(self->fs, options));
584}
679f086c 585
a2cb0250
KZ
586#define Fs_streq_srcpath_HELP "streq_srcpath(srcpath)\n\n" \
587 "Compares fs source path with path. The tailing slash is ignored.\n" \
588 "Returns True if fs source path equal to path, otherwise False."
813683a3
OO
589static PyObject *Fs_streq_srcpath(FsObject *self, PyObject *args, PyObject *kwds)
590{
591 char *kwlist[] = {"srcpath", NULL};
592 char *srcpath = NULL;
679f086c 593
813683a3
OO
594 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &srcpath)) {
595 PyErr_SetString(PyExc_TypeError, ARG_ERR);
596 return NULL;
597 }
598 return PyBool_FromLong(mnt_fs_streq_srcpath(self->fs, srcpath));
599}
679f086c 600
a2cb0250
KZ
601#define Fs_streq_target_HELP "streq_target(target)\n\n" \
602 "Compares fs target path with path. The tailing slash is ignored.\n" \
603 "See also Fs.match_target().\n" \
604 "Returns True if fs target path equal to path, otherwise False."
813683a3
OO
605static PyObject *Fs_streq_target(FsObject *self, PyObject *args, PyObject *kwds)
606{
607 char *kwlist[] = {"target", NULL};
608 char *target = NULL;
679f086c 609
813683a3
OO
610 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &target)) {
611 PyErr_SetString(PyExc_TypeError, ARG_ERR);
612 return NULL;
613 }
614 return PyBool_FromLong(mnt_fs_streq_target(self->fs, target));
615}
616
a2cb0250
KZ
617#define Fs_copy_fs_HELP "copy_fs(dest=None)\n\n" \
618 "If dest is None, a new object is created, if any fs " \
619 "field is already set, then the field is NOT overwritten."
813683a3 620static PyObject *Fs_copy_fs(FsObject *self, PyObject *args, PyObject *kwds);
a2cb0250 621
813683a3 622static PyMethodDef Fs_methods[] = {
f218d8d2 623 {"get_propagation", (PyCFunction)Fs_get_propagation, METH_NOARGS, Fs_get_propagation_HELP},
813683a3
OO
624 {"mnt_fs_append_attributes", (PyCFunction)Fs_append_attributes, METH_VARARGS|METH_KEYWORDS, Fs_append_attributes_HELP},
625 {"append_options", (PyCFunction)Fs_append_options, METH_VARARGS|METH_KEYWORDS, Fs_append_options_HELP},
626 {"mnt_fs_prepend_attributes", (PyCFunction)Fs_prepend_attributes, METH_VARARGS|METH_KEYWORDS, Fs_prepend_attributes_HELP},
627 {"prepend_options", (PyCFunction)Fs_prepend_options, METH_VARARGS|METH_KEYWORDS, Fs_prepend_options_HELP},
a2cb0250
KZ
628 {"copy_fs", (PyCFunction)Fs_copy_fs, METH_VARARGS|METH_KEYWORDS, Fs_copy_fs_HELP},
629 {"is_kernel", (PyCFunction)Fs_is_kernel, METH_NOARGS, Fs_is_kernel_HELP},
630 {"is_netfs", (PyCFunction)Fs_is_netfs, METH_NOARGS, Fs_is_netfs_HELP},
631 {"is_pseudofs", (PyCFunction)Fs_is_pseudofs, METH_NOARGS, Fs_is_pseudofs_HELP},
632 {"is_swaparea", (PyCFunction)Fs_is_swaparea, METH_NOARGS, Fs_is_swaparea_HELP},
813683a3
OO
633 {"match_fstype", (PyCFunction)Fs_match_fstype, METH_VARARGS|METH_KEYWORDS, Fs_match_fstype_HELP},
634 {"match_options", (PyCFunction)Fs_match_options, METH_VARARGS|METH_KEYWORDS, Fs_match_options_HELP},
635 {"streq_srcpath", (PyCFunction)Fs_streq_srcpath, METH_VARARGS|METH_KEYWORDS, Fs_streq_srcpath_HELP},
636 {"streq_target", (PyCFunction)Fs_streq_target, METH_VARARGS|METH_KEYWORDS, Fs_streq_target_HELP},
46407453 637 {"print_debug", (PyCFunction)Fs_print_debug, METH_NOARGS, Fs_print_debug_HELP},
813683a3
OO
638 {NULL}
639};
640
b7e47ac1 641static void Fs_destructor(FsObject *self)
813683a3 642{
9e930041 643 DBG(FS, pymnt_debug_h(self->fs, "destructor py-obj: %p, py-refcnt=%d",
b7e47ac1 644 self, (int) ((PyObject *) self)->ob_refcnt));
20b222ec 645 mnt_unref_fs(self->fs);
46407453 646 PyFree(self);
813683a3
OO
647}
648
649static PyObject *Fs_new(PyTypeObject *type, PyObject *args __attribute__((unused)),
650 PyObject *kwds __attribute__((unused)))
651{
652 FsObject *self = (FsObject*)type->tp_alloc(type, 0);
679f086c 653
b7e47ac1 654 if (self) {
813683a3 655 self->fs = NULL;
b7e47ac1
KZ
656 DBG(FS, pymnt_debug_h(self, "new"));
657 }
679f086c 658 return (PyObject *) self;
813683a3
OO
659}
660
661static int Fs_init(FsObject *self, PyObject *args, PyObject *kwds)
662{
71fbe151 663 char *source = NULL, *root = NULL, *target = NULL;
813683a3
OO
664 char *fstype = NULL, *options = NULL, *attributes =NULL;
665 int freq = 0; int passno = 0;
666 int rc = 0;
a2cb0250
KZ
667 char *kwlist[] = {
668 "source", "root", "target",
669 "fstype", "options", "attributes",
670 "freq", "passno", NULL
671 };
679f086c 672
71fbe151
KZ
673 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ssssssii", kwlist,
674 &source, &root, &target, &fstype, &options,
813683a3
OO
675 &attributes, &freq, &passno)) {
676 PyErr_SetString(PyExc_TypeError, "Invalid type");
677 return -1;
678 }
b7e47ac1
KZ
679
680 DBG(FS, pymnt_debug_h(self, "init"));
681
813683a3 682 if (self->fs)
20b222ec
KZ
683 mnt_unref_fs(self->fs);
684
685 self->fs = mnt_new_fs(); /* new FS with refcount=1 */
813683a3 686
679f086c
KZ
687 if (source && (rc = mnt_fs_set_source(self->fs, source))) {
688 PyErr_SetString(PyExc_MemoryError, MEMORY_ERR);
689 return rc;
690 }
691 if (root && (rc = mnt_fs_set_root(self->fs, root))) {
692 PyErr_SetString(PyExc_MemoryError, MEMORY_ERR);
693 return rc;
813683a3 694 }
679f086c
KZ
695 if (target && (rc = mnt_fs_set_target(self->fs, target))) {
696 PyErr_SetString(PyExc_MemoryError, MEMORY_ERR);
697 return rc;
698 }
699 if (fstype && (rc = mnt_fs_set_fstype(self->fs, fstype))) {
700 PyErr_SetString(PyExc_MemoryError, MEMORY_ERR);
701 return rc;
702 }
703 if (options && (rc = mnt_fs_set_options(self->fs, options))) {
704 PyErr_SetString(PyExc_MemoryError, MEMORY_ERR);
705 return rc;
706 }
707 if (attributes && (rc = mnt_fs_set_attributes(self->fs, attributes))) {
708 PyErr_SetString(PyExc_MemoryError, MEMORY_ERR);
709 return rc;
710 }
711
813683a3
OO
712 mnt_fs_set_freq(self->fs, freq);
713 mnt_fs_set_passno(self->fs, passno);
279a6d5f 714 mnt_fs_set_userdata(self->fs, self); /* store a pointer to self, convenient when resetting the table */
813683a3
OO
715 return 0;
716}
717
718/*
719 * missing:
720 * attribute
721 * option
722 */
723static PyGetSetDef Fs_getseters[] = {
724 {"id", (getter)Fs_get_id, NULL, "mountinfo[1]: ID", NULL},
725 {"parent", (getter)Fs_get_parent_id, NULL, "mountinfo[2]: parent", NULL},
726 {"devno", (getter)Fs_get_devno, NULL, "mountinfo[3]: st_dev", NULL},
813683a3
OO
727 {"comment", (getter)Fs_get_comment, (setter)Fs_set_comment, "fstab entry comment", NULL},
728 {"source", (getter)Fs_get_source, (setter)Fs_set_source, "fstab[1], mountinfo[10], swaps[1]: source dev, file, dir or TAG", NULL},
729 {"srcpath", (getter)Fs_get_srcpath, NULL, "mount source path or NULL in case of error or when the path is not defined.", NULL},
730 {"root", (getter)Fs_get_root, (setter)Fs_set_root, "mountinfo[4]: root of the mount within the FS", NULL},
731 {"target", (getter)Fs_get_target, (setter)Fs_set_target, "mountinfo[5], fstab[2]: mountpoint", NULL},
732 {"fstype", (getter)Fs_get_fstype, (setter)Fs_set_fstype, "mountinfo[9], fstab[3]: filesystem type", NULL},
733 {"options", (getter)Fs_get_options, (setter)Fs_set_options, "fstab[4]: merged options", NULL},
734 {"vfs_options", (getter)Fs_get_vfs_options, NULL, "mountinfo[6]: fs-independent (VFS) options", NULL},
735 {"opt_fields", (getter)Fs_get_optional_fields, NULL, "mountinfo[7]: optional fields", NULL},
736 {"fs_options", (getter)Fs_get_fs_options, NULL, "mountinfo[11]: fs-dependent options", NULL},
737 {"usr_options", (getter)Fs_get_user_options, NULL, "userspace mount options", NULL},
738 {"attributes", (getter)Fs_get_attributes, (setter)Fs_set_attributes, "mount attributes", NULL},
739 {"freq", (getter)Fs_get_freq, (setter)Fs_set_freq, "fstab[5]: dump frequency in days", NULL},
740 {"passno", (getter)Fs_get_passno, (setter)Fs_set_passno, "fstab[6]: pass number on parallel fsck", NULL},
741 {"swaptype", (getter)Fs_get_swaptype, NULL, "swaps[2]: device type", NULL},
742 {"size", (getter)Fs_get_size, NULL, "saps[3]: swaparea size", NULL},
743 {"usedsize", (getter)Fs_get_usedsize, NULL, "swaps[4]: used size", NULL},
744 {"priority", (getter)Fs_get_priority, NULL, "swaps[5]: swap priority", NULL},
745 {"tag", (getter)Fs_get_tag, NULL, "(Name, Value)", NULL},
746 {"tid", (getter)Fs_get_tid, NULL, "/proc/<tid>/mountinfo, otherwise zero", NULL},
747 {NULL}
748};
749
750static PyObject *Fs_repr(FsObject *self)
751{
a2cb0250
KZ
752 const char *src = mnt_fs_get_source(self->fs),
753 *tgt = mnt_fs_get_target(self->fs),
754 *type = mnt_fs_get_fstype(self->fs);
755
46407453 756 return PyUnicode_FromFormat(
a2cb0250
KZ
757 "<libmount.Fs object at %p, "
758 "source=%s, target=%s, fstype=%s>",
813683a3 759 self,
a2cb0250
KZ
760 src ? src : "None",
761 tgt ? tgt : "None",
762 type ? type : "None");
813683a3
OO
763}
764
765PyObject *PyObjectResultFs(struct libmnt_fs *fs)
766{
279a6d5f
KZ
767 FsObject *result;
768
813683a3
OO
769 if (!fs) {
770 PyErr_SetString(LibmountError, "internal exception");
771 return NULL;
772 }
279a6d5f
KZ
773
774 result = mnt_fs_get_userdata(fs);
775 if (result) {
776 Py_INCREF(result);
b7e47ac1
KZ
777 DBG(FS, pymnt_debug_h(fs, "result py-obj %p: already exists, py-refcnt=%d",
778 result, (int) ((PyObject *) result)->ob_refcnt));
279a6d5f 779 return (PyObject *) result;
813683a3
OO
780 }
781
9e930041 782 /* Creating an encapsulating object: increment the refcount, so that code
279a6d5f
KZ
783 * such as tab.next_fs() doesn't call the destructor, which would free
784 * our fs struct as well
785 */
786 result = PyObject_New(FsObject, &FsType);
813683a3
OO
787 if (!result) {
788 UL_RaiseExc(ENOMEM);
789 return NULL;
790 }
279a6d5f 791
813683a3 792 Py_INCREF(result);
20b222ec
KZ
793 mnt_ref_fs(fs);
794
b7e47ac1
KZ
795 DBG(FS, pymnt_debug_h(fs, "result py-obj %p new, py-refcnt=%d",
796 result, (int) ((PyObject *) result)->ob_refcnt));
813683a3 797 result->fs = fs;
279a6d5f 798 mnt_fs_set_userdata(fs, result);
a2cb0250 799 return (PyObject *) result;
813683a3
OO
800}
801
802static PyObject *Fs_copy_fs(FsObject *self, PyObject *args, PyObject *kwds)
803{
804 PyObject *dest = NULL;
805 char *kwlist[] = {"dest", NULL};
679f086c 806
813683a3
OO
807 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &dest)) {
808 PyErr_SetString(PyExc_TypeError, ARG_ERR);
809 return NULL;
810 }
a2cb0250 811 if (PyObject_TypeCheck(dest, &FsType)) { /* existing object passed as argument */
813683a3
OO
812 if (!mnt_copy_fs(((FsObject *)dest)->fs, self->fs))
813 return NULL;
b7e47ac1 814 DBG(FS, pymnt_debug_h(dest, "copy data"));
679f086c 815 return (PyObject *)dest;
a2cb0250 816
042f62df
RP
817 }
818
819 if (dest == Py_None) { /* create new object */
813683a3 820 FsObject *result = PyObject_New(FsObject, &FsType);
b7e47ac1
KZ
821
822 DBG(FS, pymnt_debug_h(result, "new copy"));
813683a3 823 result->fs = mnt_copy_fs(NULL, self->fs);
279a6d5f 824 mnt_fs_set_userdata(result->fs, result); /* keep a pointer to encapsulating object */
813683a3
OO
825 return (PyObject *)result;
826 }
679f086c
KZ
827
828 PyErr_SetString(PyExc_TypeError, ARG_ERR);
829 return NULL;
813683a3
OO
830}
831
832
833PyTypeObject FsType = {
46407453 834 PyVarObject_HEAD_INIT(NULL, 0)
813683a3
OO
835 "libmount.Fs", /*tp_name*/
836 sizeof(FsObject), /*tp_basicsize*/
837 0, /*tp_itemsize*/
b7e47ac1 838 (destructor)Fs_destructor, /*tp_dealloc*/
87918040
SK
839 NULL, /*tp_print*/
840 NULL, /*tp_getattr*/
841 NULL, /*tp_setattr*/
842 NULL, /*tp_compare*/
813683a3 843 (reprfunc)Fs_repr, /*tp_repr*/
87918040
SK
844 NULL, /*tp_as_number*/
845 NULL, /*tp_as_sequence*/
846 NULL, /*tp_as_mapping*/
847 NULL, /*tp_hash */
848 NULL, /*tp_call*/
849 NULL, /*tp_str*/
850 NULL, /*tp_getattro*/
851 NULL, /*tp_setattro*/
852 NULL, /*tp_as_buffer*/
813683a3
OO
853 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
854 Fs_HELP, /* tp_doc */
87918040
SK
855 NULL, /* tp_traverse */
856 NULL, /* tp_clear */
857 NULL, /* tp_richcompare */
813683a3 858 0, /* tp_weaklistoffset */
87918040
SK
859 NULL, /* tp_iter */
860 NULL, /* tp_iternext */
813683a3
OO
861 Fs_methods, /* tp_methods */
862 Fs_members, /* tp_members */
863 Fs_getseters, /* tp_getset */
87918040
SK
864 NULL, /* tp_base */
865 NULL, /* tp_dict */
866 NULL, /* tp_descr_get */
867 NULL, /* tp_descr_set */
813683a3
OO
868 0, /* tp_dictoffset */
869 (initproc)Fs_init, /* tp_init */
87918040 870 NULL, /* tp_alloc */
813683a3
OO
871 Fs_new, /* tp_new */
872};
873
20b222ec 874void FS_AddModuleObject(PyObject *mod)
813683a3
OO
875{
876 if (PyType_Ready(&FsType) < 0)
877 return;
878
b7e47ac1 879 DBG(FS, pymnt_debug("add to module"));
813683a3
OO
880 Py_INCREF(&FsType);
881 PyModule_AddObject(mod, "Fs", (PyObject *)&FsType);
882}
883