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