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