]>
Commit | Line | Data |
---|---|---|
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 | |
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 | ||
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 |
50 | static PyObject *Fs_get_id(FsObject *self) |
51 | { | |
52 | return PyObjectResultInt(mnt_fs_get_id(self->fs)); | |
53 | } | |
71fbe151 | 54 | |
813683a3 OO |
55 | static PyObject *Fs_get_parent_id(FsObject *self) |
56 | { | |
57 | return PyObjectResultInt(mnt_fs_get_parent_id(self->fs)); | |
58 | } | |
71fbe151 | 59 | |
813683a3 OO |
60 | static PyObject *Fs_get_devno(FsObject *self) |
61 | { | |
62 | return PyObjectResultInt(mnt_fs_get_devno(self->fs)); | |
63 | } | |
71fbe151 | 64 | |
8a12ab57 FS |
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 | ||
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" |
96 | static 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 |
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; | |
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 |
201 | static PyObject *Fs_get_srcpath(FsObject *self) |
202 | { | |
203 | return PyObjectResultStr(mnt_fs_get_srcpath(self->fs)); | |
204 | } | |
a2cb0250 | 205 | |
813683a3 OO |
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; | |
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 |
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; | |
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 |
256 | static PyObject *Fs_get_fstype(FsObject *self) |
257 | { | |
258 | return PyObjectResultStr(mnt_fs_get_fstype(self->fs)); | |
259 | } | |
260 | ||
a2cb0250 KZ |
261 | static 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 |
282 | static PyObject *Fs_get_options(FsObject *self) |
283 | { | |
284 | return PyObjectResultStr(mnt_fs_get_options(self->fs)); | |
285 | } | |
286 | ||
a2cb0250 KZ |
287 | static 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 |
308 | static PyObject *Fs_get_vfs_options(FsObject *self) |
309 | { | |
310 | return PyObjectResultStr(mnt_fs_get_vfs_options(self->fs)); | |
311 | } | |
312 | ||
a2cb0250 | 313 | |
813683a3 OO |
314 | static PyObject *Fs_get_optional_fields(FsObject *self) |
315 | { | |
316 | return PyObjectResultStr(mnt_fs_get_optional_fields(self->fs)); | |
317 | } | |
318 | ||
a2cb0250 | 319 | |
813683a3 OO |
320 | static PyObject *Fs_get_fs_options(FsObject *self) |
321 | { | |
322 | return PyObjectResultStr(mnt_fs_get_fs_options(self->fs)); | |
323 | } | |
324 | ||
a2cb0250 | 325 | |
813683a3 OO |
326 | static PyObject *Fs_get_user_options(FsObject *self) |
327 | { | |
328 | return PyObjectResultStr(mnt_fs_get_user_options(self->fs)); | |
329 | } | |
330 | ||
a2cb0250 | 331 | |
813683a3 OO |
332 | static PyObject *Fs_get_attributes(FsObject *self) |
333 | { | |
334 | return PyObjectResultStr(mnt_fs_get_attributes(self->fs)); | |
335 | } | |
336 | ||
a2cb0250 KZ |
337 | static 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 |
358 | static PyObject *Fs_get_freq(FsObject *self, void *closure __attribute__((unused))) |
359 | { | |
360 | return PyObjectResultInt(mnt_fs_get_freq(self->fs)); | |
361 | } | |
362 | ||
a2cb0250 KZ |
363 | static 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 |
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; | |
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 | |
414 | static PyObject *Fs_get_swaptype(FsObject *self) | |
415 | { | |
416 | return PyObjectResultStr(mnt_fs_get_swaptype(self->fs)); | |
417 | } | |
418 | ||
813683a3 OO |
419 | static PyObject *Fs_get_size(FsObject *self) |
420 | { | |
421 | return PyObjectResultInt(mnt_fs_get_size(self->fs)); | |
422 | } | |
423 | ||
813683a3 OO |
424 | static PyObject *Fs_get_usedsize(FsObject *self) |
425 | { | |
426 | return PyObjectResultInt(mnt_fs_get_usedsize(self->fs)); | |
427 | } | |
813683a3 OO |
428 | |
429 | static 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\ |
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." | |
f218d8d2 | 440 | static 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 | |
449 | static 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 |
456 | static 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 |
463 | static 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 |
470 | static 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 |
477 | static 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 |
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; | |
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 |
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; | |
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 |
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; | |
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 |
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; | |
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 |
558 | static 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 |
573 | static 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 |
588 | static 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 |
604 | static 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 | 619 | static PyObject *Fs_copy_fs(FsObject *self, PyObject *args, PyObject *kwds); |
a2cb0250 | 620 | |
813683a3 | 621 | static 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 | 640 | static 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 | ||
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); | |
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 | ||
660 | static 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 | */ | |
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}, | |
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 | ||
749 | static 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 | ||
764 | PyObject *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 | ||
801 | static 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 | ||
832 | PyTypeObject 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 | 847 | void 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 |