]> git.ipfire.org Git - thirdparty/util-linux.git/blob - libmount/src/fs.c
libmount; fix and improve read+poll mountinfo
[thirdparty/util-linux.git] / libmount / src / fs.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /*
3 * This file is part of libmount from util-linux project.
4 *
5 * Copyright (C) 2008-2018 Karel Zak <kzak@redhat.com>
6 *
7 * libmount is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 */
12
13 /**
14 * SECTION: fs
15 * @title: Filesystem
16 * @short_description: represents one entry from fstab, mtab, or mountinfo file
17 *
18 */
19 #include <ctype.h>
20 #include <blkid.h>
21 #include <stddef.h>
22
23 #include "mountP.h"
24 #include "strutils.h"
25
26 /**
27 * mnt_new_fs:
28 *
29 * The initial refcount is 1, and needs to be decremented to
30 * release the resources of the filesystem.
31 *
32 * Returns: newly allocated struct libmnt_fs.
33 */
34 struct libmnt_fs *mnt_new_fs(void)
35 {
36 struct libmnt_fs *fs = calloc(1, sizeof(*fs));
37 if (!fs)
38 return NULL;
39
40 fs->refcount = 1;
41 INIT_LIST_HEAD(&fs->ents);
42 /*DBG(FS, ul_debugobj(fs, "alloc"));*/
43 return fs;
44 }
45
46 /**
47 * mnt_free_fs:
48 * @fs: fs pointer
49 *
50 * Deallocates the fs. This function does not care about reference count. Don't
51 * use this function directly -- it's better to use mnt_unref_fs().
52 *
53 * The reference counting is supported since util-linux v2.24.
54 */
55 void mnt_free_fs(struct libmnt_fs *fs)
56 {
57 if (!fs)
58 return;
59
60 DBG(FS, ul_debugobj(fs, "free [refcount=%d]", fs->refcount));
61
62 mnt_reset_fs(fs);
63 free(fs);
64 }
65
66 /**
67 * mnt_reset_fs:
68 * @fs: fs pointer
69 *
70 * Resets (zeroize) @fs.
71 */
72 void mnt_reset_fs(struct libmnt_fs *fs)
73 {
74 int ref;
75
76 if (!fs)
77 return;
78
79 ref = fs->refcount;
80
81 list_del(&fs->ents);
82 free(fs->source);
83 free(fs->bindsrc);
84 free(fs->tagname);
85 free(fs->tagval);
86 free(fs->root);
87 free(fs->swaptype);
88 free(fs->target);
89 free(fs->fstype);
90 free(fs->optstr);
91 free(fs->vfs_optstr);
92 free(fs->fs_optstr);
93 free(fs->user_optstr);
94 free(fs->attrs);
95 free(fs->opt_fields);
96 free(fs->comment);
97
98 memset(fs, 0, sizeof(*fs));
99 INIT_LIST_HEAD(&fs->ents);
100 fs->refcount = ref;
101 }
102
103 /**
104 * mnt_ref_fs:
105 * @fs: fs pointer
106 *
107 * Increments reference counter.
108 */
109 void mnt_ref_fs(struct libmnt_fs *fs)
110 {
111 if (fs) {
112 fs->refcount++;
113 /*DBG(FS, ul_debugobj(fs, "ref=%d", fs->refcount));*/
114 }
115 }
116
117 /**
118 * mnt_unref_fs:
119 * @fs: fs pointer
120 *
121 * De-increments reference counter, on zero the @fs is automatically
122 * deallocated by mnt_free_fs().
123 */
124 void mnt_unref_fs(struct libmnt_fs *fs)
125 {
126 if (fs) {
127 fs->refcount--;
128 /*DBG(FS, ul_debugobj(fs, "unref=%d", fs->refcount));*/
129 if (fs->refcount <= 0)
130 mnt_free_fs(fs);
131 }
132 }
133
134 static inline int update_str(char **dest, const char *src)
135 {
136 size_t sz;
137 char *x;
138
139 assert(dest);
140
141 if (!src) {
142 free(*dest);
143 *dest = NULL;
144 return 0; /* source (old) is empty */
145 }
146
147 sz = strlen(src) + 1;
148 x = realloc(*dest, sz);
149 if (!x)
150 return -ENOMEM;
151 *dest = x;
152 memcpy(*dest, src, sz);
153 return 0;
154 }
155
156 static inline int cpy_str_at_offset(void *new, const void *old, size_t offset)
157 {
158 char **o = (char **) ((char *) old + offset);
159 char **n = (char **) ((char *) new + offset);
160
161 if (*n)
162 return 0; /* already set, don't overwrite */
163
164 return update_str(n, *o);
165 }
166
167 /**
168 * mnt_copy_fs:
169 * @dest: destination FS
170 * @src: source FS
171 *
172 * If @dest is NULL, then a new FS is allocated, if any @dest field is already
173 * set, then the field is NOT overwritten.
174 *
175 * This function does not copy userdata (se mnt_fs_set_userdata()). A new copy is
176 * not linked with any existing mnt_tab.
177 *
178 * Returns: @dest or NULL in case of error
179 */
180 struct libmnt_fs *mnt_copy_fs(struct libmnt_fs *dest,
181 const struct libmnt_fs *src)
182 {
183 const struct libmnt_fs *org = dest;
184
185 if (!src)
186 return NULL;
187 if (!dest) {
188 dest = mnt_new_fs();
189 if (!dest)
190 return NULL;
191
192 dest->tab = NULL;
193 }
194
195 dest->id = src->id;
196 dest->parent = src->parent;
197 dest->devno = src->devno;
198 dest->tid = src->tid;
199
200 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, source)))
201 goto err;
202 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, tagname)))
203 goto err;
204 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, tagval)))
205 goto err;
206 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, root)))
207 goto err;
208 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, swaptype)))
209 goto err;
210 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, target)))
211 goto err;
212 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, fstype)))
213 goto err;
214 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, optstr)))
215 goto err;
216 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, vfs_optstr)))
217 goto err;
218 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, fs_optstr)))
219 goto err;
220 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, user_optstr)))
221 goto err;
222 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, attrs)))
223 goto err;
224 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, bindsrc)))
225 goto err;
226
227 dest->freq = src->freq;
228 dest->passno = src->passno;
229 dest->flags = src->flags;
230 dest->size = src->size;
231 dest->usedsize = src->usedsize;
232 dest->priority = src->priority;
233
234 return dest;
235 err:
236 if (!org)
237 mnt_free_fs(dest);
238 return NULL;
239 }
240
241 /*
242 * This function copies all @fs description except information that does not
243 * belong to /etc/mtab (e.g. VFS and userspace mount options with MNT_NOMTAB
244 * mask).
245 *
246 * Returns: copy of @fs.
247 */
248 struct libmnt_fs *mnt_copy_mtab_fs(const struct libmnt_fs *fs)
249 {
250 struct libmnt_fs *n = mnt_new_fs();
251
252 assert(fs);
253 if (!n)
254 return NULL;
255
256 if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, source)))
257 goto err;
258 if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, target)))
259 goto err;
260 if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, fstype)))
261 goto err;
262
263 if (fs->vfs_optstr) {
264 char *p = NULL;
265 mnt_optstr_get_options(fs->vfs_optstr, &p,
266 mnt_get_builtin_optmap(MNT_LINUX_MAP),
267 MNT_NOMTAB);
268 n->vfs_optstr = p;
269 }
270
271 if (fs->user_optstr) {
272 char *p = NULL;
273 mnt_optstr_get_options(fs->user_optstr, &p,
274 mnt_get_builtin_optmap(MNT_USERSPACE_MAP),
275 MNT_NOMTAB);
276 n->user_optstr = p;
277 }
278
279 if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, fs_optstr)))
280 goto err;
281
282 /* we cannot copy original optstr, the new optstr has to be without
283 * non-mtab options -- so, let's generate a new string */
284 n->optstr = mnt_fs_strdup_options(n);
285
286 n->freq = fs->freq;
287 n->passno = fs->passno;
288 n->flags = fs->flags;
289
290 return n;
291 err:
292 mnt_free_fs(n);
293 return NULL;
294
295 }
296
297 /**
298 * mnt_fs_get_userdata:
299 * @fs: struct libmnt_file instance
300 *
301 * Returns: private data set by mnt_fs_set_userdata() or NULL.
302 */
303 void *mnt_fs_get_userdata(struct libmnt_fs *fs)
304 {
305 if (!fs)
306 return NULL;
307 return fs->userdata;
308 }
309
310 /**
311 * mnt_fs_set_userdata:
312 * @fs: struct libmnt_file instance
313 * @data: user data
314 *
315 * The "userdata" are library independent data.
316 *
317 * Returns: 0 or negative number in case of error (if @fs is NULL).
318 */
319 int mnt_fs_set_userdata(struct libmnt_fs *fs, void *data)
320 {
321 if (!fs)
322 return -EINVAL;
323 fs->userdata = data;
324 return 0;
325 }
326
327 /**
328 * mnt_fs_get_srcpath:
329 * @fs: struct libmnt_file (fstab/mtab/mountinfo) fs
330 *
331 * The mount "source path" is:
332 * - a directory for 'bind' mounts (in fstab or mtab only)
333 * - a device name for standard mounts
334 *
335 * See also mnt_fs_get_tag() and mnt_fs_get_source().
336 *
337 * Returns: mount source path or NULL in case of error or when the path
338 * is not defined.
339 */
340 const char *mnt_fs_get_srcpath(struct libmnt_fs *fs)
341 {
342 if (!fs)
343 return NULL;
344
345 /* fstab-like fs */
346 if (fs->tagname)
347 return NULL; /* the source contains a "NAME=value" */
348 return fs->source;
349 }
350
351 /**
352 * mnt_fs_get_source:
353 * @fs: struct libmnt_file (fstab/mtab/mountinfo) fs
354 *
355 * Returns: mount source. Note that the source could be unparsed TAG
356 * (LABEL/UUID). See also mnt_fs_get_srcpath() and mnt_fs_get_tag().
357 */
358 const char *mnt_fs_get_source(struct libmnt_fs *fs)
359 {
360 return fs ? fs->source : NULL;
361 }
362
363 /*
364 * Used by the parser ONLY (@source has to be freed on error)
365 */
366 int __mnt_fs_set_source_ptr(struct libmnt_fs *fs, char *source)
367 {
368 char *t = NULL, *v = NULL;
369
370 assert(fs);
371
372 if (source && blkid_parse_tag_string(source, &t, &v) == 0 &&
373 !mnt_valid_tagname(t)) {
374 /* parsable but unknown tag -- ignore */
375 free(t);
376 free(v);
377 t = v = NULL;
378 }
379
380 if (fs->source != source)
381 free(fs->source);
382
383 free(fs->tagname);
384 free(fs->tagval);
385
386 fs->source = source;
387 fs->tagname = t;
388 fs->tagval = v;
389 return 0;
390 }
391
392 /**
393 * mnt_fs_set_source:
394 * @fs: fstab/mtab/mountinfo entry
395 * @source: new source
396 *
397 * This function creates a private copy (strdup()) of @source.
398 *
399 * Returns: 0 on success or negative number in case of error.
400 */
401 int mnt_fs_set_source(struct libmnt_fs *fs, const char *source)
402 {
403 char *p = NULL;
404 int rc;
405
406 if (!fs)
407 return -EINVAL;
408
409 if (source) {
410 p = strdup(source);
411 if (!p)
412 return -ENOMEM;
413 }
414
415 rc = __mnt_fs_set_source_ptr(fs, p);
416 if (rc)
417 free(p);
418 return rc;
419 }
420
421 /**
422 * mnt_fs_streq_srcpath:
423 * @fs: fs
424 * @path: source path
425 *
426 * Compares @fs source path with @path. The redundant slashes are ignored.
427 * This function compares strings and does not canonicalize the paths.
428 * See also more heavy and generic mnt_fs_match_source().
429 *
430 * Returns: 1 if @fs source path equal to @path, otherwise 0.
431 */
432 int mnt_fs_streq_srcpath(struct libmnt_fs *fs, const char *path)
433 {
434 const char *p;
435
436 if (!fs)
437 return 0;
438
439 p = mnt_fs_get_srcpath(fs);
440
441 if (!mnt_fs_is_pseudofs(fs))
442 return streq_paths(p, path);
443
444 if (!p && !path)
445 return 1;
446
447 return p && path && strcmp(p, path) == 0;
448 }
449
450 /**
451 * mnt_fs_get_table:
452 * @fs: table entry
453 * @tb: table that contains @fs
454 *
455 * Returns: 0 or negative number on error (if @fs or @tb is NULL).
456 *
457 * Since: 2.34
458 */
459 int mnt_fs_get_table(struct libmnt_fs *fs, struct libmnt_table **tb)
460 {
461 if (!fs || !tb)
462 return -EINVAL;
463
464 *tb = fs->tab;
465 return 0;
466 }
467
468 /**
469 * mnt_fs_streq_target:
470 * @fs: fs
471 * @path: mount point
472 *
473 * Compares @fs target path with @path. The redundant slashes are ignored.
474 * This function compares strings and does not canonicalize the paths.
475 * See also more generic mnt_fs_match_target().
476 *
477 * Returns: 1 if @fs target path equal to @path, otherwise 0.
478 */
479 int mnt_fs_streq_target(struct libmnt_fs *fs, const char *path)
480 {
481 return fs && streq_paths(mnt_fs_get_target(fs), path);
482 }
483
484 /**
485 * mnt_fs_get_tag:
486 * @fs: fs
487 * @name: returns pointer to NAME string
488 * @value: returns pointer to VALUE string
489 *
490 * "TAG" is NAME=VALUE (e.g. LABEL=foo)
491 *
492 * The TAG is the first column in the fstab file. The TAG or "srcpath" always has
493 * to be set for all entries.
494 *
495 * See also mnt_fs_get_source().
496 *
497 * <informalexample>
498 * <programlisting>
499 * char *src;
500 * struct libmnt_fs *fs = mnt_table_find_target(tb, "/home", MNT_ITER_FORWARD);
501 *
502 * if (!fs)
503 * goto err;
504 *
505 * src = mnt_fs_get_srcpath(fs);
506 * if (!src) {
507 * char *tag, *val;
508 * if (mnt_fs_get_tag(fs, &tag, &val) == 0)
509 * printf("%s: %s\n", tag, val); // LABEL or UUID
510 * } else
511 * printf("device: %s\n", src); // device or bind path
512 * </programlisting>
513 * </informalexample>
514 *
515 * Returns: 0 on success or negative number in case a TAG is not defined.
516 */
517 int mnt_fs_get_tag(struct libmnt_fs *fs, const char **name, const char **value)
518 {
519 if (fs == NULL || !fs->tagname)
520 return -EINVAL;
521 if (name)
522 *name = fs->tagname;
523 if (value)
524 *value = fs->tagval;
525 return 0;
526 }
527
528 /**
529 * mnt_fs_get_target:
530 * @fs: fstab/mtab/mountinfo entry pointer
531 *
532 * Returns: pointer to mountpoint path or NULL
533 */
534 const char *mnt_fs_get_target(struct libmnt_fs *fs)
535 {
536 return fs ? fs->target : NULL;
537 }
538
539 /**
540 * mnt_fs_set_target:
541 * @fs: fstab/mtab/mountinfo entry
542 * @tgt: mountpoint
543 *
544 * This function creates a private copy (strdup()) of @tgt.
545 *
546 * Returns: 0 on success or negative number in case of error.
547 */
548 int mnt_fs_set_target(struct libmnt_fs *fs, const char *tgt)
549 {
550 return strdup_to_struct_member(fs, target, tgt);
551 }
552
553 static int mnt_fs_get_flags(struct libmnt_fs *fs)
554 {
555 return fs ? fs->flags : 0;
556 }
557
558 /**
559 * mnt_fs_get_propagation:
560 * @fs: mountinfo entry
561 * @flags: returns propagation MS_* flags as present in the mountinfo file
562 *
563 * Note that this function sets @flags to zero if no propagation flags are found
564 * in the mountinfo file. The kernel default is MS_PRIVATE, this flag is not stored
565 * in the mountinfo file.
566 *
567 * Returns: 0 on success or negative number in case of error.
568 */
569 int mnt_fs_get_propagation(struct libmnt_fs *fs, unsigned long *flags)
570 {
571 if (!fs || !flags)
572 return -EINVAL;
573
574 *flags = 0;
575
576 if (!fs->opt_fields)
577 return 0;
578
579 /*
580 * The optional fields format is incompatible with mount options
581 * ... we have to parse the field here.
582 */
583 *flags |= strstr(fs->opt_fields, "shared:") ? MS_SHARED : MS_PRIVATE;
584
585 if (strstr(fs->opt_fields, "master:"))
586 *flags |= MS_SLAVE;
587 if (strstr(fs->opt_fields, "unbindable"))
588 *flags |= MS_UNBINDABLE;
589
590 return 0;
591 }
592
593 /**
594 * mnt_fs_is_kernel:
595 * @fs: filesystem
596 *
597 * Returns: 1 if the filesystem description is read from kernel e.g. /proc/mounts.
598 */
599 int mnt_fs_is_kernel(struct libmnt_fs *fs)
600 {
601 return mnt_fs_get_flags(fs) & MNT_FS_KERNEL;
602 }
603
604 /**
605 * mnt_fs_is_swaparea:
606 * @fs: filesystem
607 *
608 * Returns: 1 if the filesystem uses "swap" as a type
609 */
610 int mnt_fs_is_swaparea(struct libmnt_fs *fs)
611 {
612 return mnt_fs_get_flags(fs) & MNT_FS_SWAP;
613 }
614
615 /**
616 * mnt_fs_is_pseudofs:
617 * @fs: filesystem
618 *
619 * Returns: 1 if the filesystem is a pseudo fs type (proc, cgroups)
620 */
621 int mnt_fs_is_pseudofs(struct libmnt_fs *fs)
622 {
623 return mnt_fs_get_flags(fs) & MNT_FS_PSEUDO;
624 }
625
626 /**
627 * mnt_fs_is_netfs:
628 * @fs: filesystem
629 *
630 * Returns: 1 if the filesystem is a network filesystem
631 */
632 int mnt_fs_is_netfs(struct libmnt_fs *fs)
633 {
634 return mnt_fs_get_flags(fs) & MNT_FS_NET;
635 }
636
637 /**
638 * mnt_fs_get_fstype:
639 * @fs: fstab/mtab/mountinfo entry pointer
640 *
641 * Returns: pointer to filesystem type.
642 */
643 const char *mnt_fs_get_fstype(struct libmnt_fs *fs)
644 {
645 return fs ? fs->fstype : NULL;
646 }
647
648 /* Used by the struct libmnt_file parser only */
649 int __mnt_fs_set_fstype_ptr(struct libmnt_fs *fs, char *fstype)
650 {
651 assert(fs);
652
653 if (fstype != fs->fstype)
654 free(fs->fstype);
655
656 fs->fstype = fstype;
657 fs->flags &= ~MNT_FS_PSEUDO;
658 fs->flags &= ~MNT_FS_NET;
659 fs->flags &= ~MNT_FS_SWAP;
660
661 /* save info about pseudo filesystems */
662 if (fs->fstype) {
663 if (mnt_fstype_is_pseudofs(fs->fstype))
664 fs->flags |= MNT_FS_PSEUDO;
665 else if (mnt_fstype_is_netfs(fs->fstype))
666 fs->flags |= MNT_FS_NET;
667 else if (!strcmp(fs->fstype, "swap"))
668 fs->flags |= MNT_FS_SWAP;
669 }
670 return 0;
671 }
672
673 /**
674 * mnt_fs_set_fstype:
675 * @fs: fstab/mtab/mountinfo entry
676 * @fstype: filesystem type
677 *
678 * This function creates a private copy (strdup()) of @fstype.
679 *
680 * Returns: 0 on success or negative number in case of error.
681 */
682 int mnt_fs_set_fstype(struct libmnt_fs *fs, const char *fstype)
683 {
684 char *p = NULL;
685
686 if (!fs)
687 return -EINVAL;
688 if (fstype) {
689 p = strdup(fstype);
690 if (!p)
691 return -ENOMEM;
692 }
693 return __mnt_fs_set_fstype_ptr(fs, p);
694 }
695
696 /*
697 * Merges @vfs and @fs options strings into a new string.
698 * This function cares about 'ro/rw' options. The 'ro' is
699 * always used if @vfs or @fs is read-only.
700 * For example:
701 *
702 * mnt_merge_optstr("rw,noexec", "ro,journal=update")
703 *
704 * returns: "ro,noexec,journal=update"
705 *
706 * mnt_merge_optstr("rw,noexec", "rw,journal=update")
707 *
708 * returns: "rw,noexec,journal=update"
709 */
710 static char *merge_optstr(const char *vfs, const char *fs)
711 {
712 char *res, *p;
713 size_t sz;
714 int ro = 0, rw = 0;
715
716 if (!vfs && !fs)
717 return NULL;
718 if (!vfs || !fs)
719 return strdup(fs ? fs : vfs);
720 if (!strcmp(vfs, fs))
721 return strdup(vfs); /* e.g. "aaa" and "aaa" */
722
723 /* leave space for the leading "r[ow],", "," and the trailing zero */
724 sz = strlen(vfs) + strlen(fs) + 5;
725 res = malloc(sz);
726 if (!res)
727 return NULL;
728 p = res + 3; /* make a room for rw/ro flag */
729
730 snprintf(p, sz - 3, "%s,%s", vfs, fs);
731
732 /* remove 'rw' flags */
733 rw += !mnt_optstr_remove_option(&p, "rw"); /* from vfs */
734 rw += !mnt_optstr_remove_option(&p, "rw"); /* from fs */
735
736 /* remove 'ro' flags if necessary */
737 if (rw != 2) {
738 ro += !mnt_optstr_remove_option(&p, "ro");
739 if (ro + rw < 2)
740 ro += !mnt_optstr_remove_option(&p, "ro");
741 }
742
743 if (!strlen(p))
744 memcpy(res, ro ? "ro" : "rw", 3);
745 else
746 memcpy(res, ro ? "ro," : "rw,", 3);
747 return res;
748 }
749
750 /**
751 * mnt_fs_strdup_options:
752 * @fs: fstab/mtab/mountinfo entry pointer
753 *
754 * Merges all mount options (VFS, FS and userspace) to one options string
755 * and returns the result. This function does not modify @fs.
756 *
757 * Returns: pointer to string (can be freed by free(3)) or NULL in case of error.
758 */
759 char *mnt_fs_strdup_options(struct libmnt_fs *fs)
760 {
761 char *res;
762
763 if (!fs)
764 return NULL;
765
766 errno = 0;
767 if (fs->optstr)
768 return strdup(fs->optstr);
769
770 res = merge_optstr(fs->vfs_optstr, fs->fs_optstr);
771 if (!res && errno)
772 return NULL;
773 if (fs->user_optstr &&
774 mnt_optstr_append_option(&res, fs->user_optstr, NULL)) {
775 free(res);
776 res = NULL;
777 }
778 return res;
779 }
780
781 /**
782 * mnt_fs_get_options:
783 * @fs: fstab/mtab/mountinfo entry pointer
784 *
785 * Returns: pointer to string or NULL in case of error.
786 */
787 const char *mnt_fs_get_options(struct libmnt_fs *fs)
788 {
789 return fs ? fs->optstr : NULL;
790 }
791
792 /**
793 * mnt_fs_get_optional_fields
794 * @fs: mountinfo entry pointer
795 *
796 * Returns: pointer to string with mountinfo optional fields
797 * or NULL in case of error.
798 */
799 const char *mnt_fs_get_optional_fields(struct libmnt_fs *fs)
800 {
801 return fs ? fs->opt_fields : NULL;
802 }
803
804 /**
805 * mnt_fs_set_options:
806 * @fs: fstab/mtab/mountinfo entry pointer
807 * @optstr: options string
808 *
809 * Splits @optstr to VFS, FS and userspace mount options and updates relevant
810 * parts of @fs.
811 *
812 * Returns: 0 on success, or negative number in case of error.
813 */
814 int mnt_fs_set_options(struct libmnt_fs *fs, const char *optstr)
815 {
816 char *v = NULL, *f = NULL, *u = NULL, *n = NULL;
817
818 if (!fs)
819 return -EINVAL;
820 if (optstr) {
821 int rc = mnt_split_optstr(optstr, &u, &v, &f, 0, 0);
822 if (rc)
823 return rc;
824 n = strdup(optstr);
825 if (!n) {
826 free(u);
827 free(v);
828 free(f);
829 return -ENOMEM;
830 }
831 }
832
833 free(fs->fs_optstr);
834 free(fs->vfs_optstr);
835 free(fs->user_optstr);
836 free(fs->optstr);
837
838 fs->fs_optstr = f;
839 fs->vfs_optstr = v;
840 fs->user_optstr = u;
841 fs->optstr = n;
842
843 return 0;
844 }
845
846 /**
847 * mnt_fs_append_options:
848 * @fs: fstab/mtab/mountinfo entry
849 * @optstr: mount options
850 *
851 * Parses (splits) @optstr and appends results to VFS, FS and userspace lists
852 * of options.
853 *
854 * If @optstr is NULL, then @fs is not modified and 0 is returned.
855 *
856 * Returns: 0 on success or negative number in case of error.
857 */
858 int mnt_fs_append_options(struct libmnt_fs *fs, const char *optstr)
859 {
860 char *v = NULL, *f = NULL, *u = NULL;
861 int rc;
862
863 if (!fs)
864 return -EINVAL;
865 if (!optstr)
866 return 0;
867
868 rc = mnt_split_optstr(optstr, &u, &v, &f, 0, 0);
869 if (rc)
870 return rc;
871
872 if (!rc && v)
873 rc = mnt_optstr_append_option(&fs->vfs_optstr, v, NULL);
874 if (!rc && f)
875 rc = mnt_optstr_append_option(&fs->fs_optstr, f, NULL);
876 if (!rc && u)
877 rc = mnt_optstr_append_option(&fs->user_optstr, u, NULL);
878 if (!rc)
879 rc = mnt_optstr_append_option(&fs->optstr, optstr, NULL);
880
881 free(v);
882 free(f);
883 free(u);
884
885 return rc;
886 }
887
888 /**
889 * mnt_fs_prepend_options:
890 * @fs: fstab/mtab/mountinfo entry
891 * @optstr: mount options
892 *
893 * Parses (splits) @optstr and prepends the results to VFS, FS and userspace lists
894 * of options.
895 *
896 * If @optstr is NULL, then @fs is not modified and 0 is returned.
897 *
898 * Returns: 0 on success or negative number in case of error.
899 */
900 int mnt_fs_prepend_options(struct libmnt_fs *fs, const char *optstr)
901 {
902 char *v = NULL, *f = NULL, *u = NULL;
903 int rc;
904
905 if (!fs)
906 return -EINVAL;
907 if (!optstr)
908 return 0;
909
910 rc = mnt_split_optstr(optstr, &u, &v, &f, 0, 0);
911 if (rc)
912 return rc;
913
914 if (!rc && v)
915 rc = mnt_optstr_prepend_option(&fs->vfs_optstr, v, NULL);
916 if (!rc && f)
917 rc = mnt_optstr_prepend_option(&fs->fs_optstr, f, NULL);
918 if (!rc && u)
919 rc = mnt_optstr_prepend_option(&fs->user_optstr, u, NULL);
920 if (!rc)
921 rc = mnt_optstr_prepend_option(&fs->optstr, optstr, NULL);
922
923 free(v);
924 free(f);
925 free(u);
926
927 return rc;
928 }
929
930 /*
931 * mnt_fs_get_fs_options:
932 * @fs: fstab/mtab/mountinfo entry pointer
933 *
934 * Returns: pointer to superblock (fs-depend) mount option string or NULL.
935 */
936 const char *mnt_fs_get_fs_options(struct libmnt_fs *fs)
937 {
938 return fs ? fs->fs_optstr : NULL;
939 }
940
941 /**
942 * mnt_fs_get_vfs_options:
943 * @fs: fstab/mtab entry pointer
944 *
945 * Returns: pointer to fs-independent (VFS) mount option string or NULL.
946 */
947 const char *mnt_fs_get_vfs_options(struct libmnt_fs *fs)
948 {
949 return fs ? fs->vfs_optstr : NULL;
950 }
951
952 /**
953 * mnt_fs_get_user_options:
954 * @fs: fstab/mtab entry pointer
955 *
956 * Returns: pointer to userspace mount option string or NULL.
957 */
958 const char *mnt_fs_get_user_options(struct libmnt_fs *fs)
959 {
960 return fs ? fs->user_optstr : NULL;
961 }
962
963 /**
964 * mnt_fs_get_attributes:
965 * @fs: fstab/mtab entry pointer
966 *
967 * Returns: pointer to attributes string or NULL.
968 */
969 const char *mnt_fs_get_attributes(struct libmnt_fs *fs)
970 {
971 return fs ? fs->attrs : NULL;
972 }
973
974 /**
975 * mnt_fs_set_attributes:
976 * @fs: fstab/mtab/mountinfo entry
977 * @optstr: options string
978 *
979 * Sets mount attributes. The attributes are mount(2) and mount(8) independent
980 * options, these options are not sent to the kernel and are not interpreted by
981 * libmount. The attributes are stored in /run/mount/utab only.
982 *
983 * The attributes are managed by libmount in userspace only. It's possible
984 * that information stored in userspace will not be available for libmount
985 * after CLONE_FS unshare. Be careful, and don't use attributes if possible.
986 *
987 * Returns: 0 on success or negative number in case of error.
988 */
989 int mnt_fs_set_attributes(struct libmnt_fs *fs, const char *optstr)
990 {
991 return strdup_to_struct_member(fs, attrs, optstr);
992 }
993
994 /**
995 * mnt_fs_append_attributes
996 * @fs: fstab/mtab/mountinfo entry
997 * @optstr: options string
998 *
999 * Appends mount attributes. (See mnt_fs_set_attributes()).
1000 *
1001 * Returns: 0 on success or negative number in case of error.
1002 */
1003 int mnt_fs_append_attributes(struct libmnt_fs *fs, const char *optstr)
1004 {
1005 if (!fs)
1006 return -EINVAL;
1007 if (!optstr)
1008 return 0;
1009 return mnt_optstr_append_option(&fs->attrs, optstr, NULL);
1010 }
1011
1012 /**
1013 * mnt_fs_prepend_attributes
1014 * @fs: fstab/mtab/mountinfo entry
1015 * @optstr: options string
1016 *
1017 * Prepends mount attributes. (See mnt_fs_set_attributes()).
1018 *
1019 * Returns: 0 on success or negative number in case of error.
1020 */
1021 int mnt_fs_prepend_attributes(struct libmnt_fs *fs, const char *optstr)
1022 {
1023 if (!fs)
1024 return -EINVAL;
1025 if (!optstr)
1026 return 0;
1027 return mnt_optstr_prepend_option(&fs->attrs, optstr, NULL);
1028 }
1029
1030
1031 /**
1032 * mnt_fs_get_freq:
1033 * @fs: fstab/mtab/mountinfo entry pointer
1034 *
1035 * Returns: dump frequency in days.
1036 */
1037 int mnt_fs_get_freq(struct libmnt_fs *fs)
1038 {
1039 return fs ? fs->freq : 0;
1040 }
1041
1042 /**
1043 * mnt_fs_set_freq:
1044 * @fs: fstab/mtab entry pointer
1045 * @freq: dump frequency in days
1046 *
1047 * Returns: 0 on success or negative number in case of error.
1048 */
1049 int mnt_fs_set_freq(struct libmnt_fs *fs, int freq)
1050 {
1051 if (!fs)
1052 return -EINVAL;
1053 fs->freq = freq;
1054 return 0;
1055 }
1056
1057 /**
1058 * mnt_fs_get_passno:
1059 * @fs: fstab/mtab entry pointer
1060 *
1061 * Returns: "pass number on parallel fsck".
1062 */
1063 int mnt_fs_get_passno(struct libmnt_fs *fs)
1064 {
1065 return fs ? fs->passno: 0;
1066 }
1067
1068 /**
1069 * mnt_fs_set_passno:
1070 * @fs: fstab/mtab entry pointer
1071 * @passno: pass number
1072 *
1073 * Returns: 0 on success or negative number in case of error.
1074 */
1075 int mnt_fs_set_passno(struct libmnt_fs *fs, int passno)
1076 {
1077 if (!fs)
1078 return -EINVAL;
1079 fs->passno = passno;
1080 return 0;
1081 }
1082
1083 /**
1084 * mnt_fs_get_root:
1085 * @fs: /proc/self/mountinfo entry
1086 *
1087 * Returns: root of the mount within the filesystem or NULL
1088 */
1089 const char *mnt_fs_get_root(struct libmnt_fs *fs)
1090 {
1091 return fs ? fs->root : NULL;
1092 }
1093
1094 /**
1095 * mnt_fs_set_root:
1096 * @fs: mountinfo entry
1097 * @path: root path
1098 *
1099 * Returns: 0 on success or negative number in case of error.
1100 */
1101 int mnt_fs_set_root(struct libmnt_fs *fs, const char *path)
1102 {
1103 return strdup_to_struct_member(fs, root, path);
1104 }
1105
1106 /**
1107 * mnt_fs_get_swaptype:
1108 * @fs: /proc/swaps entry
1109 *
1110 * Returns: swap type or NULL
1111 */
1112 const char *mnt_fs_get_swaptype(struct libmnt_fs *fs)
1113 {
1114 return fs ? fs->swaptype : NULL;
1115 }
1116
1117 /**
1118 * mnt_fs_get_size:
1119 * @fs: /proc/swaps entry
1120 *
1121 * Returns: size
1122 */
1123 off_t mnt_fs_get_size(struct libmnt_fs *fs)
1124 {
1125 return fs ? fs->size : 0;
1126 }
1127
1128 /**
1129 * mnt_fs_get_usedsize:
1130 * @fs: /proc/swaps entry
1131 *
1132 * Returns: used size
1133 */
1134 off_t mnt_fs_get_usedsize(struct libmnt_fs *fs)
1135 {
1136 return fs ? fs->usedsize : 0;
1137 }
1138
1139 /**
1140 * mnt_fs_get_priority:
1141 * @fs: /proc/swaps entry
1142 *
1143 * Returns: priority
1144 */
1145 int mnt_fs_get_priority(struct libmnt_fs *fs)
1146 {
1147 return fs ? fs->priority : 0;
1148 }
1149
1150 /**
1151 * mnt_fs_set_priority:
1152 * @fs: /proc/swaps entry
1153 * @prio: priority
1154 *
1155 * Since: 2.28
1156 *
1157 * Returns: 0 or -1 in case of error
1158 */
1159 int mnt_fs_set_priority(struct libmnt_fs *fs, int prio)
1160 {
1161 if (!fs)
1162 return -EINVAL;
1163 fs->priority = prio;
1164 return 0;
1165 }
1166
1167 /**
1168 * mnt_fs_get_bindsrc:
1169 * @fs: /run/mount/utab entry
1170 *
1171 * Returns: full path that was used for mount(2) on MS_BIND
1172 */
1173 const char *mnt_fs_get_bindsrc(struct libmnt_fs *fs)
1174 {
1175 return fs ? fs->bindsrc : NULL;
1176 }
1177
1178 /**
1179 * mnt_fs_set_bindsrc:
1180 * @fs: filesystem
1181 * @src: path
1182 *
1183 * Returns: 0 on success or negative number in case of error.
1184 */
1185 int mnt_fs_set_bindsrc(struct libmnt_fs *fs, const char *src)
1186 {
1187 return strdup_to_struct_member(fs, bindsrc, src);
1188 }
1189
1190 /**
1191 * mnt_fs_get_id:
1192 * @fs: /proc/self/mountinfo entry
1193 *
1194 * Returns: mount ID (unique identifier of the mount) or negative number in case of error.
1195 */
1196 int mnt_fs_get_id(struct libmnt_fs *fs)
1197 {
1198 return fs ? fs->id : -EINVAL;
1199 }
1200
1201 /**
1202 * mnt_fs_get_parent_id:
1203 * @fs: /proc/self/mountinfo entry
1204 *
1205 * Returns: parent mount ID or negative number in case of error.
1206 */
1207 int mnt_fs_get_parent_id(struct libmnt_fs *fs)
1208 {
1209 return fs ? fs->parent : -EINVAL;
1210 }
1211
1212 /**
1213 * mnt_fs_get_devno:
1214 * @fs: /proc/self/mountinfo entry
1215 *
1216 * Returns: value of st_dev for files on filesystem or 0 in case of error.
1217 */
1218 dev_t mnt_fs_get_devno(struct libmnt_fs *fs)
1219 {
1220 return fs ? fs->devno : 0;
1221 }
1222
1223 /**
1224 * mnt_fs_get_tid:
1225 * @fs: /proc/tid/mountinfo entry
1226 *
1227 * Returns: TID (task ID) for filesystems read from the mountinfo file
1228 */
1229 pid_t mnt_fs_get_tid(struct libmnt_fs *fs)
1230 {
1231 return fs ? fs->tid : 0;
1232 }
1233
1234 /**
1235 * mnt_fs_get_option:
1236 * @fs: fstab/mtab/mountinfo entry pointer
1237 * @name: option name
1238 * @value: returns pointer to the beginning of the value (e.g. name=VALUE) or NULL
1239 * @valsz: returns size of options value or 0
1240 *
1241 * Returns: 0 on success, 1 when @name not found or negative number in case of error.
1242 */
1243 int mnt_fs_get_option(struct libmnt_fs *fs, const char *name,
1244 char **value, size_t *valsz)
1245 {
1246 char rc = 1;
1247
1248 if (!fs)
1249 return -EINVAL;
1250 if (fs->fs_optstr)
1251 rc = mnt_optstr_get_option(fs->fs_optstr, name, value, valsz);
1252 if (rc == 1 && fs->vfs_optstr)
1253 rc = mnt_optstr_get_option(fs->vfs_optstr, name, value, valsz);
1254 if (rc == 1 && fs->user_optstr)
1255 rc = mnt_optstr_get_option(fs->user_optstr, name, value, valsz);
1256 return rc;
1257 }
1258
1259 /**
1260 * mnt_fs_get_attribute:
1261 * @fs: fstab/mtab/mountinfo entry pointer
1262 * @name: option name
1263 * @value: returns pointer to the beginning of the value (e.g. name=VALUE) or NULL
1264 * @valsz: returns size of options value or 0
1265 *
1266 * Returns: 0 on success, 1 when @name not found or negative number in case of error.
1267 */
1268 int mnt_fs_get_attribute(struct libmnt_fs *fs, const char *name,
1269 char **value, size_t *valsz)
1270 {
1271 char rc = 1;
1272
1273 if (!fs)
1274 return -EINVAL;
1275 if (fs->attrs)
1276 rc = mnt_optstr_get_option(fs->attrs, name, value, valsz);
1277 return rc;
1278 }
1279
1280 /**
1281 * mnt_fs_get_comment:
1282 * @fs: fstab/mtab/mountinfo entry pointer
1283 *
1284 * Returns: 0 on success, 1 when not found the @name or negative number in case of error.
1285 */
1286 const char *mnt_fs_get_comment(struct libmnt_fs *fs)
1287 {
1288 if (!fs)
1289 return NULL;
1290 return fs->comment;
1291 }
1292
1293 /**
1294 * mnt_fs_set_comment:
1295 * @fs: fstab entry pointer
1296 * @comm: comment string
1297 *
1298 * Note that the comment has to be terminated by '\n' (new line), otherwise
1299 * the whole filesystem entry will be written as a comment to the tabfile (e.g.
1300 * fstab).
1301 *
1302 * Returns: 0 on success or <0 in case of error.
1303 */
1304 int mnt_fs_set_comment(struct libmnt_fs *fs, const char *comm)
1305 {
1306 return strdup_to_struct_member(fs, comment, comm);
1307 }
1308
1309 /**
1310 * mnt_fs_append_comment:
1311 * @fs: fstab entry pointer
1312 * @comm: comment string
1313 *
1314 * See also mnt_fs_set_comment().
1315 *
1316 * Returns: 0 on success or <0 in case of error.
1317 */
1318 int mnt_fs_append_comment(struct libmnt_fs *fs, const char *comm)
1319 {
1320 if (!fs)
1321 return -EINVAL;
1322
1323 return append_string(&fs->comment, comm);
1324 }
1325
1326 /**
1327 * mnt_fs_match_target:
1328 * @fs: filesystem
1329 * @target: mountpoint path
1330 * @cache: tags/paths cache or NULL
1331 *
1332 * Possible are three attempts:
1333 * 1) compare @target with @fs->target
1334 *
1335 * 2) realpath(@target) with @fs->target
1336 *
1337 * 3) realpath(@target) with realpath(@fs->target) if @fs is not from
1338 * /proc/self/mountinfo.
1339 *
1340 * However, if mnt_cache_set_targets(cache, mtab) was called, and the
1341 * path @target or @fs->target is found in the @mtab, the canonicalization is
1342 * is not performed (see mnt_resolve_target()).
1343 *
1344 * The 2nd and 3rd attempts are not performed when @cache is NULL.
1345 *
1346 * Returns: 1 if @fs target is equal to @target, else 0.
1347 */
1348 int mnt_fs_match_target(struct libmnt_fs *fs, const char *target,
1349 struct libmnt_cache *cache)
1350 {
1351 int rc = 0;
1352
1353 if (!fs || !target || !fs->target)
1354 return 0;
1355
1356 /* 1) native paths */
1357 rc = mnt_fs_streq_target(fs, target);
1358
1359 if (!rc && cache) {
1360 /* 2) - canonicalized and non-canonicalized */
1361 char *cn = mnt_resolve_target(target, cache);
1362 rc = (cn && mnt_fs_streq_target(fs, cn));
1363
1364 /* 3) - canonicalized and canonicalized */
1365 if (!rc && cn && !mnt_fs_is_kernel(fs) && !mnt_fs_is_swaparea(fs)) {
1366 char *tcn = mnt_resolve_target(fs->target, cache);
1367 rc = (tcn && strcmp(cn, tcn) == 0);
1368 }
1369 }
1370
1371 return rc;
1372 }
1373
1374 /**
1375 * mnt_fs_match_source:
1376 * @fs: filesystem
1377 * @source: tag or path (device or so) or NULL
1378 * @cache: tags/paths cache or NULL
1379 *
1380 * Four attempts are possible:
1381 * 1) compare @source with @fs->source
1382 * 2) compare realpath(@source) with @fs->source
1383 * 3) compare realpath(@source) with realpath(@fs->source)
1384 * 4) compare realpath(@source) with evaluated tag from @fs->source
1385 *
1386 * The 2nd, 3rd and 4th attempts are not performed when @cache is NULL. The
1387 * 2nd and 3rd attempts are not performed if @fs->source is tag.
1388 *
1389 * Returns: 1 if @fs source is equal to @source, else 0.
1390 */
1391 int mnt_fs_match_source(struct libmnt_fs *fs, const char *source,
1392 struct libmnt_cache *cache)
1393 {
1394 char *cn;
1395 const char *src, *t, *v;
1396
1397 if (!fs)
1398 return 0;
1399
1400 /* 1) native paths... */
1401 if (mnt_fs_streq_srcpath(fs, source) == 1)
1402 return 1;
1403
1404 if (!source || !fs->source)
1405 return 0;
1406
1407 /* ... and tags */
1408 if (fs->tagname && strcmp(source, fs->source) == 0)
1409 return 1;
1410
1411 if (!cache)
1412 return 0;
1413 if (fs->flags & (MNT_FS_NET | MNT_FS_PSEUDO))
1414 return 0;
1415
1416 cn = mnt_resolve_spec(source, cache);
1417 if (!cn)
1418 return 0;
1419
1420 /* 2) canonicalized and native */
1421 src = mnt_fs_get_srcpath(fs);
1422 if (src && mnt_fs_streq_srcpath(fs, cn))
1423 return 1;
1424
1425 /* 3) canonicalized and canonicalized */
1426 if (src) {
1427 src = mnt_resolve_path(src, cache);
1428 if (src && !strcmp(cn, src))
1429 return 1;
1430 }
1431 if (src || mnt_fs_get_tag(fs, &t, &v))
1432 /* src path does not match and the tag is not defined */
1433 return 0;
1434
1435 /* read @source's tags to the cache */
1436 if (mnt_cache_read_tags(cache, cn) < 0) {
1437 if (errno == EACCES) {
1438 /* we don't have permissions to read TAGs from
1439 * @source, but can translate the @fs tag to devname.
1440 *
1441 * (because libblkid uses udev symlinks and this is
1442 * accessible for non-root uses)
1443 */
1444 char *x = mnt_resolve_tag(t, v, cache);
1445 if (x && !strcmp(x, cn))
1446 return 1;
1447 }
1448 return 0;
1449 }
1450
1451 /* 4) has the @source a tag that matches with the tag from @fs ? */
1452 if (mnt_cache_device_has_tag(cache, cn, t, v))
1453 return 1;
1454
1455 return 0;
1456 }
1457
1458 /**
1459 * mnt_fs_match_fstype:
1460 * @fs: filesystem
1461 * @types: filesystem name or comma delimited list of filesystems
1462 *
1463 * For more details see mnt_match_fstype().
1464 *
1465 * Returns: 1 if @fs type is matching to @types, else 0. The function returns
1466 * 0 when types is NULL.
1467 */
1468 int mnt_fs_match_fstype(struct libmnt_fs *fs, const char *types)
1469 {
1470 return mnt_match_fstype(fs->fstype, types);
1471 }
1472
1473 /**
1474 * mnt_fs_match_options:
1475 * @fs: filesystem
1476 * @options: comma delimited list of options (and nooptions)
1477 *
1478 * For more details see mnt_match_options().
1479 *
1480 * Returns: 1 if @fs type is matching to @options, else 0. The function returns
1481 * 0 when types is NULL.
1482 */
1483 int mnt_fs_match_options(struct libmnt_fs *fs, const char *options)
1484 {
1485 return mnt_match_options(mnt_fs_get_options(fs), options);
1486 }
1487
1488 /**
1489 * mnt_fs_print_debug
1490 * @fs: fstab/mtab/mountinfo entry
1491 * @file: file stream
1492 *
1493 * Returns: 0 on success or negative number in case of error.
1494 */
1495 int mnt_fs_print_debug(struct libmnt_fs *fs, FILE *file)
1496 {
1497 if (!fs || !file)
1498 return -EINVAL;
1499 fprintf(file, "------ fs:\n");
1500 fprintf(file, "source: %s\n", mnt_fs_get_source(fs));
1501 fprintf(file, "target: %s\n", mnt_fs_get_target(fs));
1502 fprintf(file, "fstype: %s\n", mnt_fs_get_fstype(fs));
1503
1504 if (mnt_fs_get_options(fs))
1505 fprintf(file, "optstr: %s\n", mnt_fs_get_options(fs));
1506 if (mnt_fs_get_vfs_options(fs))
1507 fprintf(file, "VFS-optstr: %s\n", mnt_fs_get_vfs_options(fs));
1508 if (mnt_fs_get_fs_options(fs))
1509 fprintf(file, "FS-opstr: %s\n", mnt_fs_get_fs_options(fs));
1510 if (mnt_fs_get_user_options(fs))
1511 fprintf(file, "user-optstr: %s\n", mnt_fs_get_user_options(fs));
1512 if (mnt_fs_get_optional_fields(fs))
1513 fprintf(file, "optional-fields: '%s'\n", mnt_fs_get_optional_fields(fs));
1514 if (mnt_fs_get_attributes(fs))
1515 fprintf(file, "attributes: %s\n", mnt_fs_get_attributes(fs));
1516
1517 if (mnt_fs_get_root(fs))
1518 fprintf(file, "root: %s\n", mnt_fs_get_root(fs));
1519
1520 if (mnt_fs_get_swaptype(fs))
1521 fprintf(file, "swaptype: %s\n", mnt_fs_get_swaptype(fs));
1522 if (mnt_fs_get_size(fs))
1523 fprintf(file, "size: %jd\n", mnt_fs_get_size(fs));
1524 if (mnt_fs_get_usedsize(fs))
1525 fprintf(file, "usedsize: %jd\n", mnt_fs_get_usedsize(fs));
1526 if (mnt_fs_get_priority(fs))
1527 fprintf(file, "priority: %d\n", mnt_fs_get_priority(fs));
1528
1529 if (mnt_fs_get_bindsrc(fs))
1530 fprintf(file, "bindsrc: %s\n", mnt_fs_get_bindsrc(fs));
1531 if (mnt_fs_get_freq(fs))
1532 fprintf(file, "freq: %d\n", mnt_fs_get_freq(fs));
1533 if (mnt_fs_get_passno(fs))
1534 fprintf(file, "pass: %d\n", mnt_fs_get_passno(fs));
1535 if (mnt_fs_get_id(fs))
1536 fprintf(file, "id: %d\n", mnt_fs_get_id(fs));
1537 if (mnt_fs_get_parent_id(fs))
1538 fprintf(file, "parent: %d\n", mnt_fs_get_parent_id(fs));
1539 if (mnt_fs_get_devno(fs))
1540 fprintf(file, "devno: %d:%d\n", major(mnt_fs_get_devno(fs)),
1541 minor(mnt_fs_get_devno(fs)));
1542 if (mnt_fs_get_tid(fs))
1543 fprintf(file, "tid: %d\n", mnt_fs_get_tid(fs));
1544 if (mnt_fs_get_comment(fs))
1545 fprintf(file, "comment: '%s'\n", mnt_fs_get_comment(fs));
1546
1547 return 0;
1548 }
1549
1550 /**
1551 * mnt_free_mntent:
1552 * @mnt: mount entry
1553 *
1554 * Deallocates the "mntent.h" mount entry.
1555 */
1556 void mnt_free_mntent(struct mntent *mnt)
1557 {
1558 if (mnt) {
1559 free(mnt->mnt_fsname);
1560 free(mnt->mnt_dir);
1561 free(mnt->mnt_type);
1562 free(mnt->mnt_opts);
1563 free(mnt);
1564 }
1565 }
1566
1567 /**
1568 * mnt_fs_to_mntent:
1569 * @fs: filesystem
1570 * @mnt: mount description (as described in mntent.h)
1571 *
1572 * Copies the information from @fs to struct mntent @mnt. If @mnt is already set,
1573 * then the struct mntent items are reallocated and updated. See also
1574 * mnt_free_mntent().
1575 *
1576 * Returns: 0 on success and a negative number in case of error.
1577 */
1578 int mnt_fs_to_mntent(struct libmnt_fs *fs, struct mntent **mnt)
1579 {
1580 int rc;
1581 struct mntent *m;
1582
1583 if (!fs || !mnt)
1584 return -EINVAL;
1585
1586 m = *mnt;
1587 if (!m) {
1588 m = calloc(1, sizeof(*m));
1589 if (!m)
1590 return -ENOMEM;
1591 }
1592
1593 if ((rc = update_str(&m->mnt_fsname, mnt_fs_get_source(fs))))
1594 goto err;
1595 if ((rc = update_str(&m->mnt_dir, mnt_fs_get_target(fs))))
1596 goto err;
1597 if ((rc = update_str(&m->mnt_type, mnt_fs_get_fstype(fs))))
1598 goto err;
1599
1600 errno = 0;
1601 m->mnt_opts = mnt_fs_strdup_options(fs);
1602 if (!m->mnt_opts && errno) {
1603 rc = -errno;
1604 goto err;
1605 }
1606
1607 m->mnt_freq = mnt_fs_get_freq(fs);
1608 m->mnt_passno = mnt_fs_get_passno(fs);
1609
1610 if (!m->mnt_fsname) {
1611 m->mnt_fsname = strdup("none");
1612 if (!m->mnt_fsname)
1613 goto err;
1614 }
1615 *mnt = m;
1616
1617 return 0;
1618 err:
1619 if (m != *mnt)
1620 mnt_free_mntent(m);
1621 return rc;
1622 }