]>
Commit | Line | Data |
---|---|---|
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 General Public License | |
18 | * along with this program. If not, see <https://gnu.org/licenses/>. | |
19 | */ | |
20 | ||
21 | /* | |
22 | * TODO: | |
23 | * mnt_fs_match_{source,target} | |
24 | * mnt_fs_get_{attribute,option} | |
25 | */ | |
26 | ||
27 | #include "pylibmount.h" | |
28 | #include <errno.h> | |
29 | ||
30 | #define Fs_HELP "Fs(source=None, root=None, target=None, fstype=None, options=None, attributes=None, freq=0, passno=0)" | |
31 | ||
32 | static PyMemberDef Fs_members[] = { | |
33 | {NULL} | |
34 | }; | |
35 | ||
36 | static PyObject *Fs_get_tag(FsObject *self) | |
37 | { | |
38 | const char *tag = NULL, *val = NULL; | |
39 | PyObject *result; | |
40 | ||
41 | if (mnt_fs_get_tag(self->fs, &tag, &val) != 0) | |
42 | return NULL; | |
43 | ||
44 | result = Py_BuildValue("(ss)", tag, val); | |
45 | if (!result) | |
46 | PyErr_SetString(PyExc_RuntimeError, CONSTRUCT_ERR); | |
47 | return result; | |
48 | } | |
49 | ||
50 | static PyObject *Fs_get_id(FsObject *self) | |
51 | { | |
52 | return PyObjectResultInt(mnt_fs_get_id(self->fs)); | |
53 | } | |
54 | ||
55 | static PyObject *Fs_get_parent_id(FsObject *self) | |
56 | { | |
57 | return PyObjectResultInt(mnt_fs_get_parent_id(self->fs)); | |
58 | } | |
59 | ||
60 | static PyObject *Fs_get_devno(FsObject *self) | |
61 | { | |
62 | return PyObjectResultInt(mnt_fs_get_devno(self->fs)); | |
63 | } | |
64 | ||
65 | static 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 | ||
83 | for (len = strlen(s); len > _PY_MAX_LEN; len -= _PY_MAX_LEN, s += _PY_MAX_LEN) | |
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 | ||
95 | #define Fs_print_debug_HELP "print_debug()\n\n" | |
96 | static PyObject *Fs_print_debug(FsObject *self) | |
97 | { | |
98 | PySys_WriteStdout("------ fs: %p\n", self->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); | |
102 | ||
103 | if (mnt_fs_get_options(self->fs)) | |
104 | _dump_debug_string("optstr: ", mnt_fs_get_options(self->fs), 0); | |
105 | if (mnt_fs_get_vfs_options(self->fs)) | |
106 | _dump_debug_string("VFS-optstr: ", mnt_fs_get_vfs_options(self->fs), 0); | |
107 | if (mnt_fs_get_fs_options(self->fs)) | |
108 | _dump_debug_string("FS-opstr: ", mnt_fs_get_fs_options(self->fs), 0); | |
109 | if (mnt_fs_get_user_options(self->fs)) | |
110 | _dump_debug_string("user-optstr: ", mnt_fs_get_user_options(self->fs), 0); | |
111 | if (mnt_fs_get_optional_fields(self->fs)) | |
112 | _dump_debug_string("optional-fields: ", mnt_fs_get_optional_fields(self->fs), '\''); | |
113 | if (mnt_fs_get_attributes(self->fs)) | |
114 | _dump_debug_string("attributes: ", mnt_fs_get_attributes(self->fs), 0); | |
115 | ||
116 | if (mnt_fs_get_root(self->fs)) | |
117 | _dump_debug_string("root: ", mnt_fs_get_root(self->fs), 0); | |
118 | ||
119 | if (mnt_fs_get_swaptype(self->fs)) | |
120 | _dump_debug_string("swaptype: ", mnt_fs_get_swaptype(self->fs), 0); | |
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)) | |
129 | _dump_debug_string("bindsrc: ", mnt_fs_get_bindsrc(self->fs), 0); | |
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)) | |
144 | _dump_debug_string("comment: ", mnt_fs_get_comment(self->fs), '\''); | |
145 | return UL_IncRef(self); | |
146 | } | |
147 | /* | |
148 | ** Fs getters/setters | |
149 | */ | |
150 | ||
151 | static PyObject *Fs_get_comment(FsObject *self, void *closure __attribute__((unused))) | |
152 | { | |
153 | return PyObjectResultStr(mnt_fs_get_comment(self->fs)); | |
154 | } | |
155 | ||
156 | static 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 */ | |
176 | static PyObject *Fs_get_source(FsObject *self) | |
177 | { | |
178 | return PyObjectResultStr(mnt_fs_get_source(self->fs)); | |
179 | } | |
180 | ||
181 | static int Fs_set_source(FsObject *self, PyObject *value, void *closure __attribute__((unused))) | |
182 | { | |
183 | char *source = NULL; | |
184 | int rc = 0; | |
185 | ||
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 | } | |
200 | ||
201 | static PyObject *Fs_get_srcpath(FsObject *self) | |
202 | { | |
203 | return PyObjectResultStr(mnt_fs_get_srcpath(self->fs)); | |
204 | } | |
205 | ||
206 | static PyObject *Fs_get_root(FsObject *self) | |
207 | { | |
208 | return PyObjectResultStr(mnt_fs_get_root(self->fs)); | |
209 | } | |
210 | ||
211 | static int Fs_set_root(FsObject *self, PyObject *value, void *closure __attribute__((unused))) | |
212 | { | |
213 | char *root = NULL; | |
214 | int rc = 0; | |
215 | ||
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 | } | |
230 | ||
231 | static PyObject *Fs_get_target(FsObject *self) | |
232 | { | |
233 | return PyObjectResultStr(mnt_fs_get_target(self->fs)); | |
234 | } | |
235 | ||
236 | static int Fs_set_target(FsObject *self, PyObject *value, void *closure __attribute__((unused))) | |
237 | { | |
238 | char *target = NULL; | |
239 | int rc = 0; | |
240 | ||
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 | } | |
255 | ||
256 | static PyObject *Fs_get_fstype(FsObject *self) | |
257 | { | |
258 | return PyObjectResultStr(mnt_fs_get_fstype(self->fs)); | |
259 | } | |
260 | ||
261 | static int Fs_set_fstype(FsObject *self, PyObject *value, | |
262 | void *closure __attribute__((unused))) | |
263 | { | |
264 | char *fstype = NULL; | |
265 | int rc = 0; | |
266 | ||
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 | } | |
281 | ||
282 | static PyObject *Fs_get_options(FsObject *self) | |
283 | { | |
284 | return PyObjectResultStr(mnt_fs_get_options(self->fs)); | |
285 | } | |
286 | ||
287 | static int Fs_set_options(FsObject *self, PyObject *value, | |
288 | void *closure __attribute__((unused))) | |
289 | { | |
290 | char *options = NULL; | |
291 | int rc = 0; | |
292 | ||
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 | } | |
307 | ||
308 | static PyObject *Fs_get_vfs_options(FsObject *self) | |
309 | { | |
310 | return PyObjectResultStr(mnt_fs_get_vfs_options(self->fs)); | |
311 | } | |
312 | ||
313 | ||
314 | static PyObject *Fs_get_optional_fields(FsObject *self) | |
315 | { | |
316 | return PyObjectResultStr(mnt_fs_get_optional_fields(self->fs)); | |
317 | } | |
318 | ||
319 | ||
320 | static PyObject *Fs_get_fs_options(FsObject *self) | |
321 | { | |
322 | return PyObjectResultStr(mnt_fs_get_fs_options(self->fs)); | |
323 | } | |
324 | ||
325 | ||
326 | static PyObject *Fs_get_user_options(FsObject *self) | |
327 | { | |
328 | return PyObjectResultStr(mnt_fs_get_user_options(self->fs)); | |
329 | } | |
330 | ||
331 | ||
332 | static PyObject *Fs_get_attributes(FsObject *self) | |
333 | { | |
334 | return PyObjectResultStr(mnt_fs_get_attributes(self->fs)); | |
335 | } | |
336 | ||
337 | static int Fs_set_attributes(FsObject *self, PyObject *value, | |
338 | void *closure __attribute__((unused))) | |
339 | { | |
340 | char *attributes = NULL; | |
341 | int rc = 0; | |
342 | ||
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 | } | |
357 | ||
358 | static PyObject *Fs_get_freq(FsObject *self, void *closure __attribute__((unused))) | |
359 | { | |
360 | return PyObjectResultInt(mnt_fs_get_freq(self->fs)); | |
361 | } | |
362 | ||
363 | static int Fs_set_freq(FsObject *self, PyObject *value, | |
364 | void *closure __attribute__((unused))) | |
365 | { | |
366 | int freq = 0; | |
367 | ||
368 | if (!value) { | |
369 | PyErr_SetString(PyExc_TypeError, NODEL_ATTR); | |
370 | return -1; | |
371 | ||
372 | } | |
373 | ||
374 | if (!PyLong_Check(value)) { | |
375 | PyErr_SetString(PyExc_TypeError, ARG_ERR); | |
376 | return -1; | |
377 | } | |
378 | ||
379 | freq = PyLong_AsLong(value); | |
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 | } | |
386 | ||
387 | static PyObject *Fs_get_passno(FsObject *self) | |
388 | { | |
389 | return PyObjectResultInt(mnt_fs_get_passno(self->fs)); | |
390 | } | |
391 | ||
392 | static int Fs_set_passno(FsObject *self, PyObject *value, void *closure __attribute__((unused))) | |
393 | { | |
394 | int passno = 0; | |
395 | ||
396 | if (!value) { | |
397 | PyErr_SetString(PyExc_TypeError, NODEL_ATTR); | |
398 | return -1; | |
399 | } | |
400 | ||
401 | if (!PyLong_Check(value)) { | |
402 | PyErr_SetString(PyExc_TypeError, ARG_ERR); | |
403 | return -1; | |
404 | } | |
405 | ||
406 | passno = PyLong_AsLong(value); | |
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 | } | |
413 | ||
414 | static PyObject *Fs_get_swaptype(FsObject *self) | |
415 | { | |
416 | return PyObjectResultStr(mnt_fs_get_swaptype(self->fs)); | |
417 | } | |
418 | ||
419 | static PyObject *Fs_get_size(FsObject *self) | |
420 | { | |
421 | return PyObjectResultInt(mnt_fs_get_size(self->fs)); | |
422 | } | |
423 | ||
424 | static PyObject *Fs_get_usedsize(FsObject *self) | |
425 | { | |
426 | return PyObjectResultInt(mnt_fs_get_usedsize(self->fs)); | |
427 | } | |
428 | ||
429 | static PyObject *Fs_get_priority(FsObject *self) | |
430 | { | |
431 | return PyObjectResultInt(mnt_fs_get_priority(self->fs)); | |
432 | } | |
433 | ||
434 | #define Fs_get_propagation_HELP "get_propagation(flags)\n\n\ | |
435 | Note that this function set flags to zero if not found any propagation flag\n\ | |
436 | in mountinfo file. The kernel default is MS_PRIVATE, this flag is not stored\n\ | |
437 | in the mountinfo file.\n\ | |
438 | \n\ | |
439 | Returns self or raises an exception in case of an error." | |
440 | static PyObject *Fs_get_propagation(FsObject *self) | |
441 | { | |
442 | unsigned long flags; | |
443 | int rc; | |
444 | ||
445 | rc = mnt_fs_get_propagation(self->fs, &flags); | |
446 | return rc ? UL_RaiseExc(-rc) : PyObjectResultInt(flags); | |
447 | } | |
448 | ||
449 | static PyObject *Fs_get_tid(FsObject *self) | |
450 | { | |
451 | return PyObjectResultInt(mnt_fs_get_tid(self->fs)); | |
452 | } | |
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." | |
456 | static PyObject *Fs_is_kernel(FsObject *self) | |
457 | { | |
458 | return PyBool_FromLong(mnt_fs_is_kernel(self->fs)); | |
459 | } | |
460 | ||
461 | #define Fs_is_netfs_HELP "is_netfs()\n\nReturns 1 if the filesystem is " \ | |
462 | "a network filesystem" | |
463 | static PyObject *Fs_is_netfs(FsObject *self) | |
464 | { | |
465 | return PyBool_FromLong(mnt_fs_is_netfs(self->fs)); | |
466 | } | |
467 | ||
468 | #define Fs_is_pseudofs_HELP "is_pseudofs()\n\nReturns 1 if the filesystem is "\ | |
469 | "a pseudo fs type (proc, cgroups)" | |
470 | static PyObject *Fs_is_pseudofs(FsObject *self) | |
471 | { | |
472 | return PyBool_FromLong(mnt_fs_is_pseudofs(self->fs)); | |
473 | } | |
474 | ||
475 | #define Fs_is_swaparea_HELP "is_swaparea()\n\nReturns 1 if the filesystem " \ | |
476 | "uses \"swap\" as a type" | |
477 | static PyObject *Fs_is_swaparea(FsObject *self) | |
478 | { | |
479 | return PyBool_FromLong(mnt_fs_is_swaparea(self->fs)); | |
480 | } | |
481 | ||
482 | #define Fs_append_attributes_HELP "append_attributes(optstr)\n\n" \ | |
483 | "Appends mount attributes." | |
484 | static PyObject *Fs_append_attributes(FsObject *self, PyObject *args, PyObject *kwds) | |
485 | { | |
486 | char *kwlist[] = {"optstr", NULL}; | |
487 | char *optstr = NULL; | |
488 | int rc; | |
489 | ||
490 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &optstr)) { | |
491 | PyErr_SetString(PyExc_TypeError, ARG_ERR); | |
492 | return NULL; | |
493 | } | |
494 | rc = mnt_fs_append_attributes(self->fs, optstr); | |
495 | return rc ? UL_RaiseExc(-rc) : UL_IncRef(self); | |
496 | } | |
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." | |
501 | static PyObject *Fs_append_options(FsObject *self, PyObject *args, PyObject *kwds) | |
502 | { | |
503 | char *kwlist[] = {"optstr", NULL}; | |
504 | char *optstr = NULL; | |
505 | int rc; | |
506 | ||
507 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &optstr)) { | |
508 | PyErr_SetString(PyExc_TypeError, ARG_ERR); | |
509 | return NULL; | |
510 | } | |
511 | rc = mnt_fs_append_options(self->fs, optstr); | |
512 | return rc ? UL_RaiseExc(-rc) : UL_IncRef(self); | |
513 | } | |
514 | ||
515 | #define Fs_prepend_attributes_HELP "prepend_attributes(optstr)\n\n" \ | |
516 | "Prepends mount attributes." | |
517 | static PyObject *Fs_prepend_attributes(FsObject *self, PyObject *args, PyObject *kwds) | |
518 | { | |
519 | char *kwlist[] = {"optstr", NULL}; | |
520 | char *optstr = NULL; | |
521 | int rc; | |
522 | ||
523 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &optstr)) { | |
524 | PyErr_SetString(PyExc_TypeError, ARG_ERR); | |
525 | return NULL; | |
526 | } | |
527 | rc = mnt_fs_prepend_attributes(self->fs, optstr); | |
528 | return rc ? UL_RaiseExc(-rc) : UL_IncRef(self); | |
529 | } | |
530 | ||
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." | |
534 | static PyObject *Fs_prepend_options(FsObject *self, PyObject *args, PyObject *kwds) | |
535 | { | |
536 | char *kwlist[] = {"optstr", NULL}; | |
537 | char *optstr = NULL; | |
538 | int rc; | |
539 | ||
540 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &optstr)) { | |
541 | PyErr_SetString(PyExc_TypeError, ARG_ERR); | |
542 | return NULL; | |
543 | } | |
544 | rc = mnt_fs_prepend_options(self->fs, optstr); | |
545 | return rc ? UL_RaiseExc(-rc) : UL_IncRef(self); | |
546 | } | |
547 | ||
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." | |
558 | static PyObject *Fs_match_fstype(FsObject *self, PyObject *args, PyObject *kwds) | |
559 | { | |
560 | char *kwlist[] = {"pattern", NULL}; | |
561 | char *pattern = NULL; | |
562 | ||
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 | } | |
569 | ||
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." | |
573 | static PyObject *Fs_match_options(FsObject *self, PyObject *args, PyObject *kwds) | |
574 | { | |
575 | char *kwlist[] = {"options", NULL}; | |
576 | char *options = NULL; | |
577 | ||
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 | } | |
584 | ||
585 | #define Fs_streq_srcpath_HELP "streq_srcpath(srcpath)\n\n" \ | |
586 | "Compares fs source path with path. The trailing slash is ignored.\n" \ | |
587 | "Returns True if fs source path equal to path, otherwise False." | |
588 | static PyObject *Fs_streq_srcpath(FsObject *self, PyObject *args, PyObject *kwds) | |
589 | { | |
590 | char *kwlist[] = {"srcpath", NULL}; | |
591 | char *srcpath = NULL; | |
592 | ||
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 | } | |
599 | ||
600 | #define Fs_streq_target_HELP "streq_target(target)\n\n" \ | |
601 | "Compares fs target path with path. The trailing slash is ignored.\n" \ | |
602 | "See also Fs.match_target().\n" \ | |
603 | "Returns True if fs target path equal to path, otherwise False." | |
604 | static PyObject *Fs_streq_target(FsObject *self, PyObject *args, PyObject *kwds) | |
605 | { | |
606 | char *kwlist[] = {"target", NULL}; | |
607 | char *target = NULL; | |
608 | ||
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 | ||
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." | |
619 | static PyObject *Fs_copy_fs(FsObject *self, PyObject *args, PyObject *kwds); | |
620 | ||
621 | static PyMethodDef Fs_methods[] = { | |
622 | {"get_propagation", (PyCFunction)Fs_get_propagation, METH_NOARGS, Fs_get_propagation_HELP}, | |
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}, | |
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}, | |
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}, | |
636 | {"print_debug", (PyCFunction)Fs_print_debug, METH_NOARGS, Fs_print_debug_HELP}, | |
637 | {NULL} | |
638 | }; | |
639 | ||
640 | static void Fs_destructor(FsObject *self) | |
641 | { | |
642 | DBG(FS, pymnt_debug_h(self->fs, "destructor py-obj: %p, py-refcnt=%d", | |
643 | self, (int) ((PyObject *) self)->ob_refcnt)); | |
644 | mnt_unref_fs(self->fs); | |
645 | PyFree(self); | |
646 | } | |
647 | ||
648 | static PyObject *Fs_new(PyTypeObject *type, PyObject *args __attribute__((unused)), | |
649 | PyObject *kwds __attribute__((unused))) | |
650 | { | |
651 | FsObject *self = (FsObject*)type->tp_alloc(type, 0); | |
652 | ||
653 | if (self) { | |
654 | self->fs = NULL; | |
655 | DBG(FS, pymnt_debug_h(self, "new")); | |
656 | } | |
657 | return (PyObject *) self; | |
658 | } | |
659 | ||
660 | static int Fs_init(FsObject *self, PyObject *args, PyObject *kwds) | |
661 | { | |
662 | char *source = NULL, *root = NULL, *target = NULL; | |
663 | char *fstype = NULL, *options = NULL, *attributes =NULL; | |
664 | int freq = 0; int passno = 0; | |
665 | int rc = 0; | |
666 | char *kwlist[] = { | |
667 | "source", "root", "target", | |
668 | "fstype", "options", "attributes", | |
669 | "freq", "passno", NULL | |
670 | }; | |
671 | ||
672 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ssssssii", kwlist, | |
673 | &source, &root, &target, &fstype, &options, | |
674 | &attributes, &freq, &passno)) { | |
675 | PyErr_SetString(PyExc_TypeError, "Invalid type"); | |
676 | return -1; | |
677 | } | |
678 | ||
679 | DBG(FS, pymnt_debug_h(self, "init")); | |
680 | ||
681 | if (self->fs) | |
682 | mnt_unref_fs(self->fs); | |
683 | ||
684 | self->fs = mnt_new_fs(); /* new FS with refcount=1 */ | |
685 | ||
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; | |
693 | } | |
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 | ||
711 | mnt_fs_set_freq(self->fs, freq); | |
712 | mnt_fs_set_passno(self->fs, passno); | |
713 | mnt_fs_set_userdata(self->fs, self); /* store a pointer to self, convenient when resetting the table */ | |
714 | return 0; | |
715 | } | |
716 | ||
717 | /* | |
718 | * missing: | |
719 | * attribute | |
720 | * option | |
721 | */ | |
722 | static 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}, | |
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 | ||
749 | static PyObject *Fs_repr(FsObject *self) | |
750 | { | |
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 | ||
755 | return PyUnicode_FromFormat( | |
756 | "<libmount.Fs object at %p, " | |
757 | "source=%s, target=%s, fstype=%s>", | |
758 | self, | |
759 | src ? src : "None", | |
760 | tgt ? tgt : "None", | |
761 | type ? type : "None"); | |
762 | } | |
763 | ||
764 | PyObject *PyObjectResultFs(struct libmnt_fs *fs) | |
765 | { | |
766 | FsObject *result; | |
767 | ||
768 | if (!fs) { | |
769 | PyErr_SetString(LibmountError, "internal exception"); | |
770 | return NULL; | |
771 | } | |
772 | ||
773 | result = mnt_fs_get_userdata(fs); | |
774 | if (result) { | |
775 | Py_INCREF(result); | |
776 | DBG(FS, pymnt_debug_h(fs, "result py-obj %p: already exists, py-refcnt=%d", | |
777 | result, (int) ((PyObject *) result)->ob_refcnt)); | |
778 | return (PyObject *) result; | |
779 | } | |
780 | ||
781 | /* Creating an encapsulating object: increment the refcount, so that code | |
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); | |
786 | if (!result) { | |
787 | UL_RaiseExc(ENOMEM); | |
788 | return NULL; | |
789 | } | |
790 | ||
791 | Py_INCREF(result); | |
792 | mnt_ref_fs(fs); | |
793 | ||
794 | DBG(FS, pymnt_debug_h(fs, "result py-obj %p new, py-refcnt=%d", | |
795 | result, (int) ((PyObject *) result)->ob_refcnt)); | |
796 | result->fs = fs; | |
797 | mnt_fs_set_userdata(fs, result); | |
798 | return (PyObject *) result; | |
799 | } | |
800 | ||
801 | static PyObject *Fs_copy_fs(FsObject *self, PyObject *args, PyObject *kwds) | |
802 | { | |
803 | PyObject *dest = NULL; | |
804 | char *kwlist[] = {"dest", NULL}; | |
805 | ||
806 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &dest)) { | |
807 | PyErr_SetString(PyExc_TypeError, ARG_ERR); | |
808 | return NULL; | |
809 | } | |
810 | if (PyObject_TypeCheck(dest, &FsType)) { /* existing object passed as argument */ | |
811 | if (!mnt_copy_fs(((FsObject *)dest)->fs, self->fs)) | |
812 | return NULL; | |
813 | DBG(FS, pymnt_debug_h(dest, "copy data")); | |
814 | return (PyObject *)dest; | |
815 | ||
816 | } | |
817 | ||
818 | if (dest == Py_None) { /* create new object */ | |
819 | FsObject *result = PyObject_New(FsObject, &FsType); | |
820 | ||
821 | DBG(FS, pymnt_debug_h(result, "new copy")); | |
822 | result->fs = mnt_copy_fs(NULL, self->fs); | |
823 | mnt_fs_set_userdata(result->fs, result); /* keep a pointer to encapsulating object */ | |
824 | return (PyObject *)result; | |
825 | } | |
826 | ||
827 | PyErr_SetString(PyExc_TypeError, ARG_ERR); | |
828 | return NULL; | |
829 | } | |
830 | ||
831 | ||
832 | PyTypeObject FsType = { | |
833 | PyVarObject_HEAD_INIT(NULL, 0) | |
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, | |
845 | }; | |
846 | ||
847 | void FS_AddModuleObject(PyObject *mod) | |
848 | { | |
849 | if (PyType_Ready(&FsType) < 0) | |
850 | return; | |
851 | ||
852 | DBG(FS, pymnt_debug("add to module")); | |
853 | Py_INCREF(&FsType); | |
854 | PyModule_AddObject(mod, "Fs", (PyObject *)&FsType); | |
855 | } | |
856 |