]> git.ipfire.org Git - thirdparty/util-linux.git/blame - shlibs/mount/src/fs.c
findmnt: use new libmount functions
[thirdparty/util-linux.git] / shlibs / mount / src / fs.c
CommitLineData
d115ee9b
KZ
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.
d115ee9b
KZ
6 */
7
192c6aad
KZ
8/**
9 * SECTION: fs
10 * @title: Filesystem
3d735589 11 * @short_description: mnt_fs represents one entry in fstab/mtab/mountinfo
192c6aad
KZ
12 *
13 */
d115ee9b
KZ
14#include <stdio.h>
15#include <string.h>
16#include <stdlib.h>
17#include <ctype.h>
3fca8422 18#include <errno.h>
8e368761 19#include <blkid.h>
9ecdf48f 20#include <stddef.h>
d115ee9b
KZ
21
22#include "nls.h"
23#include "mountP.h"
24
25/**
26 * mnt_new_fs:
27 *
192c6aad 28 * Returns: newly allocated mnt_file fs.
d115ee9b
KZ
29 */
30mnt_fs *mnt_new_fs(void)
31{
32 mnt_fs *fs = calloc(1, sizeof(struct _mnt_fs));
33 if (!fs)
34 return NULL;
35
36 INIT_LIST_HEAD(&fs->ents);
37 return fs;
38}
39
40/**
41 * mnt_free_fs:
42 * @fs: fs pointer
43 *
44 * Deallocates the fs.
45 */
46void mnt_free_fs(mnt_fs *fs)
47{
48 if (!fs)
49 return;
50 list_del(&fs->ents);
51
52 free(fs->source);
dd369652 53 free(fs->bindsrc);
d115ee9b
KZ
54 free(fs->tagname);
55 free(fs->tagval);
0b3953a3 56 free(fs->root);
d115ee9b
KZ
57 free(fs->target);
58 free(fs->fstype);
d115ee9b
KZ
59 free(fs->vfs_optstr);
60 free(fs->fs_optstr);
76a06ca4
KZ
61 free(fs->user_optstr);
62 free(fs->attrs);
d115ee9b
KZ
63
64 free(fs);
65}
66
8b95253f 67static inline int cpy_str(char **dest, const char *src)
9ecdf48f 68{
8b95253f
KZ
69 size_t sz;
70 char *x;
71
72 assert(dest);
9ecdf48f 73
8b95253f
KZ
74 if (!src) {
75 free(*dest);
76 *dest = NULL;
9ecdf48f 77 return 0; /* source (old) is empty */
8b95253f 78 }
9ecdf48f 79
8b95253f
KZ
80 sz = strlen(src) + 1;
81 x = realloc(*dest, sz);
82 if (!x)
56be757f 83 return -ENOMEM;
8b95253f
KZ
84 *dest = x;
85 memcpy(*dest, src, sz);
9ecdf48f
KZ
86 return 0;
87}
88
8b95253f
KZ
89static inline int cpy_str_at_offset(void *new, const void *old, size_t offset)
90{
91 char **o = (char **) (old + offset);
92 char **n = (char **) (new + offset);
93
94 return cpy_str(n, *o);
95}
96
9ecdf48f
KZ
97/**
98 * mnt_copy_fs:
99 * @fs: source FS
100 *
101 * This function does not copy userdata (se mnt_fs_set_userdata()). A new copy is
102 * not linked with any existing mnt_tab.
103 *
104 * Returns: copy of @fs
105 */
7714c689 106mnt_fs *mnt_copy_fs(const mnt_fs *fs)
9ecdf48f
KZ
107{
108 mnt_fs *n = mnt_new_fs();
109
110 if (!n)
111 return NULL;
112
113 n->id = fs->id;
114 n->parent = fs->parent;
115 n->devno = fs->devno;
116
8b95253f 117 if (cpy_str_at_offset(n, fs, offsetof(struct _mnt_fs, source)))
9ecdf48f 118 goto err;
8b95253f 119 if (cpy_str_at_offset(n, fs, offsetof(struct _mnt_fs, tagname)))
9ecdf48f 120 goto err;
8b95253f 121 if (cpy_str_at_offset(n, fs, offsetof(struct _mnt_fs, tagval)))
9ecdf48f 122 goto err;
8b95253f 123 if (cpy_str_at_offset(n, fs, offsetof(struct _mnt_fs, root)))
9ecdf48f 124 goto err;
8b95253f 125 if (cpy_str_at_offset(n, fs, offsetof(struct _mnt_fs, target)))
9ecdf48f 126 goto err;
8b95253f 127 if (cpy_str_at_offset(n, fs, offsetof(struct _mnt_fs, fstype)))
9ecdf48f 128 goto err;
8b95253f 129 if (cpy_str_at_offset(n, fs, offsetof(struct _mnt_fs, vfs_optstr)))
9ecdf48f 130 goto err;
8b95253f 131 if (cpy_str_at_offset(n, fs, offsetof(struct _mnt_fs, fs_optstr)))
9ecdf48f 132 goto err;
76a06ca4
KZ
133 if (cpy_str_at_offset(n, fs, offsetof(struct _mnt_fs, user_optstr)))
134 goto err;
135 if (cpy_str_at_offset(n, fs, offsetof(struct _mnt_fs, attrs)))
136 goto err;
137
9ecdf48f
KZ
138 n->freq = fs->freq;
139 n->passno = fs->passno;
140 n->flags = fs->flags;
141
142 return n;
143err:
144 mnt_free_fs(n);
145 return NULL;
146}
147
26b4f9e4
KZ
148/**
149 * mnt_fs_get_userdata:
150 * @fs: mnt_file instance
151 *
192c6aad 152 * Returns: private data set by mnt_fs_set_userdata() or NULL.
26b4f9e4
KZ
153 */
154void *mnt_fs_get_userdata(mnt_fs *fs)
155{
156 return fs ? fs->userdata : NULL;
157}
158
159/**
160 * mnt_fs_set_userdata:
161 * @fs: mnt_file instance
162 *
163 * The "userdata" are library independent data.
164 *
56be757f 165 * Returns: 0 or negative number in case of error (if @fs is NULL).
26b4f9e4
KZ
166 */
167int mnt_fs_set_userdata(mnt_fs *fs, void *data)
168{
169 if (!fs)
56be757f 170 return -EINVAL;
26b4f9e4
KZ
171 fs->userdata = data;
172 return 0;
173}
174
d115ee9b
KZ
175/**
176 * mnt_fs_get_srcpath:
177 * @fs: mnt_file (fstab/mtab/mountinfo) fs
178 *
179 * The mount "source path" is:
192c6aad
KZ
180 * - a directory for 'bind' mounts (in fstab or mtab only)
181 * - a device name for standard mounts
d115ee9b
KZ
182 *
183 * See also mnt_fs_get_tag() and mnt_fs_get_source().
184 *
192c6aad 185 * Returns: mount source path or NULL in case of error or when the path
d115ee9b 186 * is not defined.
d115ee9b
KZ
187 */
188const char *mnt_fs_get_srcpath(mnt_fs *fs)
189{
190 assert(fs);
191 if (!fs)
192 return NULL;
193
194 /* fstab-like fs */
195 if (fs->tagname)
196 return NULL; /* the source contains a "NAME=value" */
197 return fs->source;
198}
199
200/**
3d735589 201 * mnt_fs_get_source:
d115ee9b
KZ
202 * @fs: mnt_file (fstab/mtab/mountinfo) fs
203 *
192c6aad 204 * Returns: mount source. Note that the source could be unparsed TAG
d115ee9b
KZ
205 * (LABEL/UUID). See also mnt_fs_get_srcpath() and mnt_fs_get_tag().
206 */
207const char *mnt_fs_get_source(mnt_fs *fs)
208{
209 return fs ? fs->source : NULL;
210}
211
212/* Used by parser mnt_file ONLY (@source has to be allocated) */
b2d0b74d 213int __mnt_fs_set_source_ptr(mnt_fs *fs, char *source)
d115ee9b 214{
b2d0b74d
KZ
215 char *t = NULL, *v = NULL;
216
d115ee9b
KZ
217 assert(fs);
218
be1a5180
KZ
219 if (source && !strcmp(source, "none"))
220 source = NULL;
d115ee9b 221
be1a5180 222 if (source && strchr(source, '=')) {
b2d0b74d 223 if (blkid_parse_tag_string(source, &t, &v) != 0)
d115ee9b 224 return -1;
d115ee9b
KZ
225 }
226
b2d0b74d
KZ
227 if (fs->source != source)
228 free(fs->source);
229
230 free(fs->tagname);
231 free(fs->tagval);
232
d115ee9b 233 fs->source = source;
b2d0b74d
KZ
234 fs->tagname = t;
235 fs->tagval = v;
d115ee9b
KZ
236 return 0;
237}
238
239/**
240 * mnt_fs_set_source:
241 * @fs: fstab/mtab/mountinfo entry
242 * @source: new source
243 *
192c6aad
KZ
244 * This function creates a private copy (strdup()) of @source.
245 *
56be757f 246 * Returns: 0 on success or negative number in case of error.
d115ee9b
KZ
247 */
248int mnt_fs_set_source(mnt_fs *fs, const char *source)
249{
250 char *p;
b2d0b74d 251 int rc;
d115ee9b
KZ
252
253 if (!fs && !source)
56be757f 254 return -EINVAL;
d115ee9b
KZ
255 p = strdup(source);
256 if (!p)
56be757f 257 return -ENOMEM;
d115ee9b 258
b2d0b74d
KZ
259 rc = __mnt_fs_set_source_ptr(fs, p);
260 if (rc)
261 free(p);
262 return rc;
d115ee9b
KZ
263}
264
265/**
266 * mnt_fs_get_tag:
267 * @fs: fs
268 * @name: returns pointer to NAME string
269 * @value: returns pointer to VALUE string
270 *
271 * "TAG" is NAME=VALUE (e.g. LABEL=foo)
272 *
192c6aad
KZ
273 * The TAG is the first column in the fstab file. The TAG or "srcpath" has to
274 * be always set for all entries.
d115ee9b
KZ
275 *
276 * See also mnt_fs_get_source().
277 *
192c6aad
KZ
278 * <informalexample>
279 * <programlisting>
d115ee9b 280 * char *src;
192c6aad 281 * mnt_fs *fs = mnt_tab_find_target(tb, "/home", MNT_ITER_FORWARD);
d115ee9b
KZ
282 *
283 * if (!fs)
284 * goto err;
285 *
286 * src = mnt_fs_get_srcpath(fs);
287 * if (!src) {
288 * char *tag, *val;
289 * if (mnt_fs_get_tag(fs, &tag, &val) == 0)
290 * printf("%s: %s\n", tag, val); // LABEL or UUID
291 * } else
292 * printf("device: %s\n", src); // device or bind path
192c6aad
KZ
293 * </programlisting>
294 * </informalexample>
d115ee9b 295 *
56be757f 296 * Returns: 0 on success or negative number in case that a TAG is not defined.
d115ee9b
KZ
297 */
298int mnt_fs_get_tag(mnt_fs *fs, const char **name, const char **value)
299{
300 if (fs == NULL || !fs->tagname)
56be757f 301 return -EINVAL;
d115ee9b
KZ
302 if (name)
303 *name = fs->tagname;
304 if (value)
305 *value = fs->tagval;
306 return 0;
307}
308
309/**
310 * mnt_fs_get_target:
311 * @fs: fstab/mtab/mountinfo entry pointer
312 *
192c6aad 313 * Returns: pointer to mountpoint path or NULL
d115ee9b
KZ
314 */
315const char *mnt_fs_get_target(mnt_fs *fs)
316{
317 assert(fs);
318 return fs ? fs->target : NULL;
319}
320
321/**
322 * mnt_fs_set_target:
323 * @fs: fstab/mtab/mountinfo entry
324 * @target: mountpoint
325 *
192c6aad
KZ
326 * This function creates a private copy (strdup()) of @target.
327 *
56be757f 328 * Returns: 0 on success or negative number in case of error.
d115ee9b
KZ
329 */
330int mnt_fs_set_target(mnt_fs *fs, const char *target)
331{
332 char *p;
333
334 assert(fs);
335
336 if (!fs || !target)
56be757f 337 return -EINVAL;
d115ee9b
KZ
338 p = strdup(target);
339 if (!p)
56be757f 340 return -ENOMEM;
d115ee9b
KZ
341 free(fs->target);
342 fs->target = p;
343
344 return 0;
345}
346
347/**
348 * mnt_fs_get_fstype:
349 * @fs: fstab/mtab/mountinfo entry pointer
350 *
192c6aad 351 * Returns: pointer to filesystem type.
d115ee9b
KZ
352 */
353const char *mnt_fs_get_fstype(mnt_fs *fs)
354{
355 assert(fs);
356 return fs ? fs->fstype : NULL;
357}
358
359/* Used by mnt_file parser only */
b2d0b74d 360int __mnt_fs_set_fstype_ptr(mnt_fs *fs, char *fstype)
d115ee9b
KZ
361{
362 assert(fs);
363
b2d0b74d
KZ
364 if (fstype != fs->fstype)
365 free(fs->fstype);
366
d115ee9b
KZ
367 fs->fstype = fstype;
368 fs->flags &= ~MNT_FS_PSEUDO;
369 fs->flags &= ~MNT_FS_NET;
370
371 /* save info about pseudo filesystems */
8485e709
KZ
372 if (fs->fstype) {
373 if (mnt_fstype_is_pseudofs(fs->fstype))
374 fs->flags |= MNT_FS_PSEUDO;
375 else if (mnt_fstype_is_netfs(fs->fstype))
376 fs->flags |= MNT_FS_NET;
377 else if (!strcmp(fs->fstype, "swap"))
378 fs->flags |= MNT_FS_SWAP;
379 }
d115ee9b
KZ
380 return 0;
381}
382
383/**
384 * mnt_fs_set_fstype:
385 * @fs: fstab/mtab/mountinfo entry
386 * @fstype: filesystem type
387 *
192c6aad
KZ
388 * This function creates a private copy (strdup()) of @fstype.
389 *
56be757f 390 * Returns: 0 on success or negative number in case of error.
d115ee9b
KZ
391 */
392int mnt_fs_set_fstype(mnt_fs *fs, const char *fstype)
393{
8485e709 394 char *p = NULL;
b2d0b74d 395 int rc;
d115ee9b 396
8485e709 397 if (!fs)
56be757f 398 return -EINVAL;
8485e709
KZ
399 if (fstype) {
400 p = strdup(fstype);
401 if (!p)
402 return -ENOMEM;
403 }
b2d0b74d
KZ
404 rc = __mnt_fs_set_fstype_ptr(fs, p);
405 if (rc)
406 free(p);
407 return rc;
d115ee9b
KZ
408}
409
76a06ca4
KZ
410/*
411 * Merges @vfs and @fs options strings into a new string.
412 * This function cares about 'ro/rw' options. The 'ro' is
413 * always used if @vfs or @fs is read-only.
414 * For example:
415 *
416 * mnt_merge_optstr("rw,noexec", "ro,journal=update")
417 *
418 * returns: "ro,noexec,journal=update"
419 *
420 * mnt_merge_optstr("rw,noexec", "rw,journal=update")
421 *
422 * returns: "rw,noexec,journal=update"
423 */
424static char *merge_optstr(const char *vfs, const char *fs)
425{
426 char *res, *p;
427 size_t sz;
428 int ro = 0, rw = 0;
429
430 if (!vfs && !fs)
431 return NULL;
432 if (!vfs || !fs)
433 return strdup(fs ? fs : vfs);
434 if (!strcmp(vfs, fs))
435 return strdup(vfs); /* e.g. "aaa" and "aaa" */
436
437 /* leave space for leading "r[ow],", "," and trailing zero */
438 sz = strlen(vfs) + strlen(fs) + 5;
439 res = malloc(sz);
440 if (!res)
441 return NULL;
442 p = res + 3; /* make a room for rw/ro flag */
443
444 snprintf(p, sz - 3, "%s,%s", vfs, fs);
445
446 /* remove 'rw' flags */
447 rw += !mnt_optstr_remove_option(&p, "rw"); /* from vfs */
448 rw += !mnt_optstr_remove_option(&p, "rw"); /* from fs */
449
450 /* remove 'ro' flags if necessary */
451 if (rw != 2) {
452 ro += !mnt_optstr_remove_option(&p, "ro");
453 if (ro + rw < 2)
454 ro += !mnt_optstr_remove_option(&p, "ro");
455 }
456
457 if (!strlen(p))
458 memcpy(res, ro ? "ro" : "rw", 3);
459 else
460 memcpy(res, ro ? "ro," : "rw,", 3);
461 return res;
462}
463
d115ee9b 464/**
76a06ca4 465 * mnt_fs_strdup_options:
d115ee9b
KZ
466 * @fs: fstab/mtab/mountinfo entry pointer
467 *
76a06ca4
KZ
468 * Merges all mount options (VFS, FS and userspace) to the one options string
469 * and returns the result. This function does not modigy @fs.
470 *
471 * Returns: pointer to string (can be freed by free(3)) or NULL in case of error.
d115ee9b 472 */
76a06ca4 473char *mnt_fs_strdup_options(mnt_fs *fs)
d115ee9b 474{
76a06ca4
KZ
475 char *res;
476
d115ee9b 477 assert(fs);
76a06ca4
KZ
478
479 errno = 0;
480 res = merge_optstr(fs->vfs_optstr, fs->fs_optstr);
481 if (errno)
482 return NULL;
483 if (fs->user_optstr) {
484 if (mnt_optstr_append_option(&res, fs->user_optstr, NULL)) {
485 free(res);
486 res = NULL;
487 }
488 }
489 return res;
d115ee9b
KZ
490}
491
76a06ca4
KZ
492/**
493 * mnt_fs_set_options:
494 * @fs: fstab/mtab/mountinfo entry pointer
495 *
496 * Splits @optstr to VFS, FS and userspace mount options and update relevat
497 * parts of @fs.
498 *
499 * Returns: 0 on success, or negative number icase of error.
500 */
501int mnt_fs_set_options(mnt_fs *fs, const char *optstr)
d115ee9b 502{
76a06ca4 503 char *v = NULL, *f = NULL, *u = NULL;
192c6aad 504
d115ee9b
KZ
505 assert(fs);
506
be1a5180 507 if (!fs)
56be757f 508 return -EINVAL;
76a06ca4
KZ
509 if (optstr) {
510 int rc = mnt_split_optstr(optstr, &u, &v, &f, 0, 0);
56be757f
KZ
511 if (rc)
512 return rc;
3661b841 513 }
192c6aad 514
d115ee9b
KZ
515 free(fs->fs_optstr);
516 free(fs->vfs_optstr);
76a06ca4 517 free(fs->user_optstr);
d6fead1e 518
3661b841
KZ
519 fs->fs_optstr = f;
520 fs->vfs_optstr = v;
76a06ca4 521 fs->user_optstr = u;
192c6aad 522 return 0;
d115ee9b
KZ
523}
524
76a06ca4
KZ
525/**
526 * mnt_fs_append_options:
527 * @fs: fstab/mtab/mountinfo entry
528 * @optstr: mount options
529 *
530 * Parses (splits) @optstr and appends results to VFS, FS and userspace lists
531 * of options.
532 *
533 * If @optstr is NULL then @fs is not modified and 0 is returned.
534 *
535 * Returns: 0 on success or negative number in case of error.
536 */
537int mnt_fs_append_options(mnt_fs *fs, const char *optstr)
b2d0b74d 538{
76a06ca4 539 char *v = NULL, *f = NULL, *u = NULL;
b2d0b74d
KZ
540 int rc;
541
542 assert(fs);
543
76a06ca4
KZ
544 if (!fs)
545 return -EINVAL;
546 if (!optstr)
547 return 0;
548
549 rc = mnt_split_optstr((char *) optstr, &u, &v, &f, 0, 0);
550 if (!rc && v)
551 rc = mnt_optstr_append_option(&fs->vfs_optstr, v, NULL);
552 if (!rc && f)
553 rc = mnt_optstr_append_option(&fs->fs_optstr, f, NULL);
554 if (!rc && u)
555 rc = mnt_optstr_append_option(&fs->user_optstr, u, NULL);
556
b2d0b74d
KZ
557 return rc;
558}
559
3661b841 560/**
76a06ca4
KZ
561 * mnt_fs_prepend_options:
562 * @fs: fstab/mtab/mountinfo entry
563 * @optstr: mount options
564 *
565 * Parses (splits) @optstr and prepands results to VFS, FS and userspace lists
566 * of options.
567 *
568 * If @optstr is NULL then @fs is not modified and 0 is returned.
569 *
570 * Returns: 0 on success or negative number in case of error.
571 */
572int mnt_fs_prepend_options(mnt_fs *fs, const char *optstr)
573{
574 char *v = NULL, *f = NULL, *u = NULL;
575 int rc;
576
577 assert(fs);
578
579 if (!fs)
580 return -EINVAL;
581 if (!optstr)
582 return 0;
583
584 rc = mnt_split_optstr((char *) optstr, &u, &v, &f, 0, 0);
585 if (!rc && v)
586 rc = mnt_optstr_prepend_option(&fs->vfs_optstr, v, NULL);
587 if (!rc && f)
588 rc = mnt_optstr_prepend_option(&fs->fs_optstr, f, NULL);
589 if (!rc && u)
590 rc = mnt_optstr_prepend_option(&fs->user_optstr, u, NULL);
591
592 return rc;
593}
594
595/*
596 * mnt_fs_get_fs_options:
597 * @fs: fstab/mtab/mountinfo entry pointer
598 *
599 * Returns: pointer to superblock (fs-depend) mount option string or NULL.
600 */
601const char *mnt_fs_get_fs_options(mnt_fs *fs)
602{
603 assert(fs);
604 return fs ? fs->fs_optstr : NULL;
605}
606
607/**
608 * mnt_fs_set_fs_options:
569f95b7
KZ
609 * @fs: fstab/mtab/mountinfo entry
610 * @optstr: options string
611 *
76a06ca4 612 * Sets FS specific mount options.
569f95b7 613 *
56be757f 614 * Returns: 0 on success or negative number in case of error.
569f95b7 615 */
76a06ca4 616int mnt_fs_set_fs_options(mnt_fs *fs, const char *optstr)
569f95b7 617{
76a06ca4
KZ
618 char *p = NULL;
619
620 if (!fs)
621 return -EINVAL;
622 if (optstr) {
623 p = strdup(optstr);
624 if (!p)
625 return -ENOMEM;
626 }
627 free(fs->fs_optstr);
628 fs->fs_optstr = p;
629
630 return 0;
569f95b7
KZ
631}
632
633/**
76a06ca4 634 * mnt_fs_append_fs_options:
3661b841 635 * @fs: fstab/mtab/mountinfo entry
569f95b7 636 * @optstr: options string
3661b841 637 *
76a06ca4
KZ
638 * Appends FS specific mount options. If @optstr is NULL then @fs is not
639 * modified and 0 is returned.
3661b841 640 *
56be757f 641 * Returns: 0 on success or negative number in case of error.
3661b841 642 */
76a06ca4 643int mnt_fs_append_fs_options(mnt_fs *fs, const char *optstr)
3661b841 644{
76a06ca4 645 if (!fs)
56be757f 646 return -EINVAL;
76a06ca4
KZ
647 if (!optstr)
648 return 0;
649 return mnt_optstr_append_option(&fs->fs_optstr, optstr, NULL);
3661b841
KZ
650}
651
569f95b7 652/**
76a06ca4 653 * mnt_fs_prepend_fs_options:
569f95b7 654 * @fs: fstab/mtab/mountinfo entry
76a06ca4
KZ
655 * @optstr: options string
656 *
657 * Prepends FS specific mount options. If @optstr is NULL then @fs is not
658 * modified and 0 is returned.
569f95b7 659 *
56be757f 660 * Returns: 0 on success or negative number in case of error.
569f95b7 661 */
76a06ca4 662int mnt_fs_prepend_fs_options(mnt_fs *fs, const char *optstr)
569f95b7 663{
76a06ca4
KZ
664 if (!fs)
665 return -EINVAL;
666 if (!optstr)
667 return 0;
668 return mnt_optstr_prepend_option(&fs->fs_optstr, optstr, NULL);
669}
569f95b7 670
76a06ca4
KZ
671
672/**
673 * mnt_fs_get_vfs_options:
674 * @fs: fstab/mtab entry pointer
675 *
676 * Returns: pointer to fs-independent (VFS) mount option string or NULL.
677 */
678const char *mnt_fs_get_vfs_options(mnt_fs *fs)
679{
569f95b7 680 assert(fs);
76a06ca4
KZ
681 return fs ? fs->vfs_optstr : NULL;
682}
683
684/**
685 * mnt_fs_set_vfs_options:
686 * @fs: fstab/mtab/mountinfo entry
687 * @optstr: options string
688 *
689 * Sets VFS mount options.
690 *
691 * Returns: 0 on success or negative number in case of error.
692 */
693int mnt_fs_set_vfs_options(mnt_fs *fs, const char *optstr)
694{
695 char *p = NULL;
696
697 if (!fs)
698 return -EINVAL;
699 if (optstr) {
700 p = strdup(optstr);
701 if (!p)
702 return -ENOMEM;
703 }
704 free(fs->vfs_optstr);
705 fs->vfs_optstr = p;
706
707 return 0;
708}
569f95b7 709
76a06ca4
KZ
710/**
711 * mnt_fs_append_vfs_options:
712 * @fs: fstab/mtab/mountinfo entry
713 * @optstr: options string
714 *
715 * Appends VFS mount options. If @optstr is NULL then @fs is not
716 * modified and 0 is returned.
717 *
718 * Returns: 0 on success or negative number in case of error.
719 */
720int mnt_fs_append_vfs_options(mnt_fs *fs, const char *optstr)
721{
569f95b7 722 if (!fs)
56be757f 723 return -EINVAL;
569f95b7
KZ
724 if (!optstr)
725 return 0;
76a06ca4
KZ
726 return mnt_optstr_append_option(&fs->vfs_optstr, optstr, NULL);
727}
569f95b7 728
76a06ca4
KZ
729/**
730 * mnt_fs_prepend_vfs_options:
731 * @fs: fstab/mtab/mountinfo entry
732 * @optstr: options string
733 *
734 * Prepends VFS mount options. If @optstr is NULL then @fs is not
735 * modified and 0 is returned.
736 *
737 * Returns: 0 on success or negative number in case of error.
738 */
739int mnt_fs_prepend_vfs_options(mnt_fs *fs, const char *optstr)
740{
741 if (!fs)
742 return -EINVAL;
743 if (!optstr)
744 return 0;
745 return mnt_optstr_prepend_option(&fs->vfs_optstr, optstr, NULL);
746}
569f95b7 747
76a06ca4
KZ
748/**
749 * mnt_fs_get_userspace_options:
750 * @fs: fstab/mtab entry pointer
751 *
752 * Returns: pointer to userspace mount option string or NULL.
753 */
754const char *mnt_fs_get_userspace_options(mnt_fs *fs)
755{
756 assert(fs);
757 return fs ? fs->user_optstr : NULL;
569f95b7
KZ
758}
759
c83fd489 760/**
76a06ca4 761 * mnt_fs_set_userspace_options:
c83fd489 762 * @fs: fstab/mtab/mountinfo entry
76a06ca4
KZ
763 * @optstr: options string
764 *
765 * Sets userspace mount options.
c83fd489
KZ
766 *
767 * Returns: 0 on success or negative number in case of error.
768 */
76a06ca4 769int mnt_fs_set_userspace_options(mnt_fs *fs, const char *optstr)
c83fd489 770{
76a06ca4 771 char *p = NULL;
c83fd489 772
76a06ca4
KZ
773 if (!fs)
774 return -EINVAL;
775 if (optstr) {
776 p = strdup(optstr);
777 if (!p)
778 return -ENOMEM;
779 }
780 free(fs->user_optstr);
781 fs->user_optstr = p;
782
783 return 0;
784}
c83fd489 785
76a06ca4
KZ
786/**
787 * mnt_fs_append_userspace_options:
788 * @fs: fstab/mtab/mountinfo entry
789 * @optstr: options string
790 *
791 * Appends userspace mount options. If @optstr is NULL then @fs is not
792 * modified and 0 is returned.
793 *
794 * Returns: 0 on success or negative number in case of error.
795 */
796int mnt_fs_append_userspace_options(mnt_fs *fs, const char *optstr)
797{
c83fd489
KZ
798 if (!fs)
799 return -EINVAL;
800 if (!optstr)
801 return 0;
76a06ca4
KZ
802 return mnt_optstr_append_option(&fs->user_optstr, optstr, NULL);
803}
c83fd489 804
76a06ca4
KZ
805/**
806 * mnt_fs_prepend_userspace_options:
807 * @fs: fstab/mtab/mountinfo entry
808 * @optstr: options string
809 *
810 * Prepends userspace mount options. If @optstr is NULL then @fs is not
811 * modified and 0 is returned.
812 *
813 * Returns: 0 on success or negative number in case of error.
814 */
815int mnt_fs_prepend_userspace_options(mnt_fs *fs, const char *optstr)
816{
817 if (!fs)
818 return -EINVAL;
819 if (!optstr)
820 return 0;
c83fd489 821
76a06ca4 822 return mnt_optstr_prepend_option(&fs->user_optstr, optstr, NULL);
c83fd489
KZ
823}
824
d115ee9b 825/**
76a06ca4
KZ
826 * mnt_fs_get_attributes:
827 * @fs: fstab/mtab entry pointer
d115ee9b 828 *
76a06ca4 829 * Returns: pointer to attributes string or NULL.
d115ee9b 830 */
76a06ca4 831const char *mnt_fs_get_attributes(mnt_fs *fs)
d115ee9b
KZ
832{
833 assert(fs);
76a06ca4 834 return fs ? fs->attrs : NULL;
d115ee9b
KZ
835}
836
837/**
76a06ca4
KZ
838 * mnt_fs_set_attributes:
839 * @fs: fstab/mtab/mountinfo entry
840 * @optstr: options string
d115ee9b 841 *
76a06ca4
KZ
842 * Sets mount attributes. The attributes are mount(2) and mount(8) independent
843 * options, these options are not send to kernel and are not interpreted by
844 * libmount. The attributes are stored in /dev/.mount/utab only.
845 *
846 * The atrtributes are managed by libmount in userspace only. It's possible
847 * that information stored in userspace will not be available for libmount
848 * after CLONE_FS unshare. Be carefull, and don't use attributes if possible.
849 *
850 * Returns: 0 on success or negative number in case of error.
d115ee9b 851 */
76a06ca4 852int mnt_fs_set_attributes(mnt_fs *fs, const char *optstr)
d115ee9b 853{
76a06ca4
KZ
854 char *p = NULL;
855
856 if (!fs)
857 return -EINVAL;
858 if (optstr) {
859 p = strdup(optstr);
860 if (!p)
861 return -ENOMEM;
862 }
863 free(fs->attrs);
864 fs->attrs = p;
865
866 return 0;
867}
868
869/**
870 * mnt_fs_append_attributes
871 * @fs: fstab/mtab/mountinfo entry
872 * @optstr: options string
873 *
874 * Appends mount attributes. (See mnt_fs_set_attributes()).
875 *
876 * Returns: 0 on success or negative number in case of error.
877 */
878int mnt_fs_append_attributes(mnt_fs *fs, const char *optstr)
879{
880 if (!fs)
881 return -EINVAL;
882 if (!optstr)
883 return 0;
884 return mnt_optstr_append_option(&fs->attrs, optstr, NULL);
885}
886
887/**
888 * mnt_fs_prepend_attributes
889 * @fs: fstab/mtab/mountinfo entry
890 * @optstr: options string
891 *
892 * Prepends mount attributes. (See mnt_fs_set_attributes()).
893 *
894 * Returns: 0 on success or negative number in case of error.
895 */
896int mnt_fs_prepend_attributes(mnt_fs *fs, const char *optstr)
897{
898 if (!fs)
899 return -EINVAL;
900 if (!optstr)
901 return 0;
902 return mnt_optstr_prepend_option(&fs->attrs, optstr, NULL);
d115ee9b
KZ
903}
904
905
906/**
907 * mnt_fs_get_freq:
908 * @fs: fstab/mtab/mountinfo entry pointer
909 *
3d735589 910 * Returns: dump frequency in days.
d115ee9b
KZ
911 */
912int mnt_fs_get_freq(mnt_fs *fs)
913{
914 assert(fs);
915 return fs ? fs->freq : 0;
916}
917
918/**
919 * mnt_fs_set_freq:
efe73c3e 920 * @fs: fstab/mtab entry pointer
d115ee9b
KZ
921 * @freq: dump frequency in days
922 *
56be757f 923 * Returns: 0 on success or negative number in case of error.
d115ee9b
KZ
924 */
925int mnt_fs_set_freq(mnt_fs *fs, int freq)
926{
927 assert(fs);
d115ee9b 928 if (!fs)
56be757f 929 return -EINVAL;
d115ee9b
KZ
930 fs->freq = freq;
931 return 0;
932}
933
934/**
935 * mnt_fs_get_passno:
efe73c3e 936 * @fs: fstab/mtab entry pointer
d115ee9b 937 *
192c6aad 938 * Returns: "pass number on parallel fsck".
d115ee9b
KZ
939 */
940int mnt_fs_get_passno(mnt_fs *fs)
941{
942 assert(fs);
943 return fs ? fs->passno: 0;
944}
945
946/**
947 * mnt_fs_set_passno:
efe73c3e 948 * @fs: fstab/mtab entry pointer
d115ee9b
KZ
949 * @passno: pass number
950 *
56be757f 951 * Returns: 0 on success or negative number in case of error.
d115ee9b
KZ
952 */
953int mnt_fs_set_passno(mnt_fs *fs, int passno)
954{
955 assert(fs);
d115ee9b 956 if (!fs)
56be757f 957 return -EINVAL;
d115ee9b
KZ
958 fs->passno = passno;
959 return 0;
960}
961
0b3953a3
KZ
962/**
963 * mnt_fs_get_root:
964 * @fs: /proc/self/mountinfo entry
965 *
966 * Returns: root of the mount within the filesystem or NULL
967 */
968const char *mnt_fs_get_root(mnt_fs *fs)
969{
970 assert(fs);
971 return fs ? fs->root : NULL;
972}
973
9ecdf48f
KZ
974/**
975 * mnt_fs_set_root:
976 * @fs: mountinfo entry
977 * @root: path
978 *
56be757f 979 * Returns: 0 on success or negative number in case of error.
9ecdf48f
KZ
980 */
981int mnt_fs_set_root(mnt_fs *fs, const char *root)
982{
983 char *p = NULL;
984
985 assert(fs);
986 if (!fs)
56be757f 987 return -EINVAL;
9ecdf48f
KZ
988 if (root) {
989 p = strdup(root);
990 if (!p)
56be757f 991 return -ENOMEM;
9ecdf48f
KZ
992 }
993 free(fs->root);
994 fs->root = p;
995 return 0;
996}
997
dd369652
KZ
998/**
999 * mnt_fs_get_bindsrc:
1000 * @fs: /dev/.mount/utab entry
1001 *
1002 * Returns: full path that was used for mount(2) on MS_BIND
1003 */
1004const char *mnt_fs_get_bindsrc(mnt_fs *fs)
1005{
1006 assert(fs);
1007 return fs ? fs->bindsrc : NULL;
1008}
1009
1010/**
1011 * mnt_fs_set_bindsrc:
1012 * @fs: filesystem
1013 * @src: path
1014 *
1015 * Returns: 0 on success or negative number in case of error.
1016 */
1017int mnt_fs_set_bindsrc(mnt_fs *fs, const char *src)
1018{
1019 char *p = NULL;
1020
1021 assert(fs);
1022 if (!fs)
1023 return -EINVAL;
1024 if (src) {
1025 p = strdup(src);
1026 if (!p)
1027 return -ENOMEM;
1028 }
1029 free(fs->bindsrc);
1030 fs->bindsrc = p;
1031 return 0;
1032}
1033
efe73c3e
KZ
1034/**
1035 * mnt_fs_get_id:
1036 * @fs: /proc/self/mountinfo entry
1037 *
56be757f 1038 * Returns: mount ID (unique identifier of the mount) or negative number in case of error.
efe73c3e
KZ
1039 */
1040int mnt_fs_get_id(mnt_fs *fs)
1041{
1042 assert(fs);
56be757f 1043 return fs ? fs->id : -EINVAL;
efe73c3e
KZ
1044}
1045
1046/**
1047 * mnt_fs_get_parent_id:
1048 * @fs: /proc/self/mountinfo entry
1049 *
56be757f 1050 * Returns: parent mount ID or negative number in case of error.
efe73c3e
KZ
1051 */
1052int mnt_fs_get_parent_id(mnt_fs *fs)
1053{
1054 assert(fs);
56be757f 1055 return fs ? fs->parent : -EINVAL;
efe73c3e
KZ
1056}
1057
1058/**
1059 * mnt_fs_get_devno:
0b3953a3 1060 * @fs: /proc/self/mountinfo entry
efe73c3e
KZ
1061 *
1062 * Returns: value of st_dev for files on filesystem or 0 in case of error.
1063 */
1064dev_t mnt_fs_get_devno(mnt_fs *fs)
1065{
1066 assert(fs);
1067 return fs ? fs->devno : 0;
1068}
1069
d115ee9b
KZ
1070/**
1071 * mnt_fs_get_option:
1072 * @fs: fstab/mtab/mountinfo entry pointer
1073 * @name: option name
1074 * @value: returns pointer to the begin of the value (e.g. name=VALUE) or NULL
1075 * @valsz: returns size of options value or 0
1076 *
56be757f 1077 * Returns: 0 on success, 1 when not found the @name or negative number in case of error.
d115ee9b
KZ
1078 */
1079int mnt_fs_get_option(mnt_fs *fs, const char *name,
1080 char **value, size_t *valsz)
1081{
76a06ca4
KZ
1082 char rc = 1;
1083
1084 if (fs->fs_optstr)
1085 rc = mnt_optstr_get_option(fs->fs_optstr, name, value, valsz);
1086 if (rc == 1 && fs->vfs_optstr)
1087 rc = mnt_optstr_get_option(fs->vfs_optstr, name, value, valsz);
1088 if (rc == 1 && fs->user_optstr)
1089 rc = mnt_optstr_get_option(fs->user_optstr, name, value, valsz);
1090 return rc;
1091}
1092
1093/**
1094 * mnt_fs_get_attribute:
1095 * @fs: fstab/mtab/mountinfo entry pointer
1096 * @name: option name
1097 * @value: returns pointer to the begin of the value (e.g. name=VALUE) or NULL
1098 * @valsz: returns size of options value or 0
1099 *
1100 * Returns: 0 on success, 1 when not found the @name or negative number in case of error.
1101 */
1102int mnt_fs_get_attribute(mnt_fs *fs, const char *name,
1103 char **value, size_t *valsz)
1104{
1105 char rc = 1;
1106
1107 if (fs->attrs)
1108 rc = mnt_optstr_get_option(fs->attrs, name, value, valsz);
1109 return rc;
d115ee9b
KZ
1110}
1111
3fca8422
KZ
1112/**
1113 * mnt_fs_match_target:
1114 * @fs: filesystem
1115 * @target: mountpoint path
1116 * @cache: tags/paths cache or NULL
1117 *
1118 * Possible are three attempts:
1119 * 1) compare @target with @fs->target
1120 * 2) realpath(@target) with @fs->target
1121 * 3) realpath(@target) with realpath(@fs->target).
1122 *
1123 * The 2nd and 3rd attempts are not performed when @cache is NULL.
1124 *
192c6aad 1125 * Returns: 1 if @fs target is equal to @target else 0.
3fca8422
KZ
1126 */
1127int mnt_fs_match_target(mnt_fs *fs, const char *target, mnt_cache *cache)
1128{
1129 int rc = 0;
1130
1131 if (!fs || !target || !fs->target)
1132 return 0;
1133
1134 /* 1) native paths */
1135 rc = !strcmp(target, fs->target);
1136
1137 if (!rc && cache) {
1138 /* 2) - canonicalized and non-canonicalized */
1139 char *cn = mnt_resolve_path(target, cache);
1140 rc = (cn && strcmp(cn, fs->target) == 0);
1141
1142 /* 3) - canonicalized and canonicalized */
1143 if (!rc && cn) {
1144 char *tcn = mnt_resolve_path(fs->target, cache);
1145 rc = (tcn && strcmp(cn, tcn) == 0);
1146 }
1147 }
1148
1149 return rc;
1150}
1151
1152/**
1153 * mnt_fs_match_source:
1154 * @fs: filesystem
1155 * @source: tag or path (device or so)
1156 * @cache: tags/paths cache or NULL
1157 *
1158 * Possible are four attempts:
1159 * 1) compare @source with @fs->source
1160 * 2) compare realpath(@source) with @fs->source
1161 * 3) compare realpath(@source) with realpath(@fs->source)
1162 * 4) compare realpath(@source) with evaluated tag from @fs->source
1163 *
1164 * The 2nd, 3rd and 4th attempts are not performed when @cache is NULL. The
1165 * 2nd and 3rd attempts are not performed if @fs->source is tag.
1166 *
192c6aad 1167 * Returns: 1 if @fs source is equal to @source else 0.
3fca8422
KZ
1168 */
1169int mnt_fs_match_source(mnt_fs *fs, const char *source, mnt_cache *cache)
1170{
3fca8422
KZ
1171 char *cn;
1172 const char *src, *t, *v;
1173
1174 if (!fs || !source || !fs->source)
1175 return 0;
1176
1177 /* 1) native paths/tags */
3ef87248
KZ
1178 if (!strcmp(source, fs->source))
1179 return 1;
3fca8422 1180
3ef87248
KZ
1181 if (!cache)
1182 return 0;
3fca8422
KZ
1183 if (fs->flags & (MNT_FS_NET | MNT_FS_PSEUDO))
1184 return 0;
1185
1186 cn = mnt_resolve_spec(source, cache);
1187 if (!cn)
1188 return 0;
1189
1190 /* 2) canonicalized and native */
1191 src = mnt_fs_get_srcpath(fs);
3ef87248
KZ
1192 if (src && !strcmp(cn, src))
1193 return 1;
3fca8422
KZ
1194
1195 /* 3) canonicalized and canonicalized */
3ef87248 1196 if (src) {
3fca8422 1197 src = mnt_resolve_path(src, cache);
3ef87248
KZ
1198 if (src && !strcmp(cn, src))
1199 return 1;
3fca8422 1200 }
3ef87248
KZ
1201 if (src || mnt_fs_get_tag(fs, &t, &v))
1202 /* src path does not match and tag is not defined */
3fca8422
KZ
1203 return 0;
1204
1205 /* read @source's tags to the cache */
ba7232a1 1206 if (mnt_cache_read_tags(cache, cn) < 0) {
3fca8422
KZ
1207 if (errno == EACCES) {
1208 /* we don't have permissions to read TAGs from
1209 * @source, but can translate @fs tag to devname.
1210 *
1211 * (because libblkid uses udev symlinks and this is
1212 * accessible for non-root uses)
1213 */
1214 char *x = mnt_resolve_tag(t, v, cache);
1215 if (x && !strcmp(x, cn))
1216 return 1;
1217 }
1218 return 0;
1219 }
1220
1221 /* 4) has the @source a tag that matches with tag from @fs ? */
3ef87248
KZ
1222 if (mnt_cache_device_has_tag(cache, cn, t, v))
1223 return 1;
3fca8422 1224
3ef87248 1225 return 0;
3fca8422
KZ
1226}
1227
1228/**
1229 * mnt_fs_match_fstype:
1230 * @fs: filesystem
1231 * @types: filesystem name or comma delimited list of filesystems
1232 *
1233 * For more details see mnt_match_fstype().
1234 *
192c6aad 1235 * Returns: 1 if @fs type is matching to @types else 0. The function returns
3fca8422
KZ
1236 * 0 when types is NULL.
1237 */
1238int mnt_fs_match_fstype(mnt_fs *fs, const char *types)
1239{
1240 return mnt_match_fstype(fs->fstype, types);
1241}
1242
1243/**
1244 * mnt_fs_match_options:
1245 * @fs: filesystem
1246 * @options: comma delimited list of options (and nooptions)
1247 *
1248 * For more details see mnt_match_options().
1249 *
192c6aad 1250 * Returns: 1 if @fs type is matching to @options else 0. The function returns
3fca8422
KZ
1251 * 0 when types is NULL.
1252 */
1253int mnt_fs_match_options(mnt_fs *fs, const char *options)
1254{
76a06ca4
KZ
1255 char *o = mnt_fs_strdup_options(fs);
1256 int rc = 0;
1257
1258 if (o)
1259 rc = mnt_match_options(o, options);
1260 free(o);
1261 return rc;
3fca8422
KZ
1262}
1263
d115ee9b
KZ
1264/**
1265 * mnt_fs_print_debug
1266 * @fs: fstab/mtab/mountinfo entry
1267 * @file: output
1268 *
56be757f 1269 * Returns: 0 on success or negative number in case of error.
d115ee9b
KZ
1270 */
1271int mnt_fs_print_debug(mnt_fs *fs, FILE *file)
1272{
1273 if (!fs)
56be757f 1274 return -EINVAL;
d115ee9b 1275 fprintf(file, "------ fs: %p\n", fs);
77417bc0
KZ
1276 fprintf(file, "source: %s\n", mnt_fs_get_source(fs));
1277 fprintf(file, "target: %s\n", mnt_fs_get_target(fs));
1278 fprintf(file, "fstype: %s\n", mnt_fs_get_fstype(fs));
76a06ca4
KZ
1279
1280 if (mnt_fs_get_vfs_options(fs))
1281 fprintf(file, "VFS-optstr: %s\n", mnt_fs_get_vfs_options(fs));
1282 if (mnt_fs_get_fs_options(fs))
1283 fprintf(file, "FS-opstr: %s\n", mnt_fs_get_fs_options(fs));
1284 if (mnt_fs_get_userspace_options(fs))
1285 fprintf(file, "user-optstr: %s\n", mnt_fs_get_userspace_options(fs));
1286 if (mnt_fs_get_attributes(fs))
1287 fprintf(file, "attributes: %s\n", mnt_fs_get_attributes(fs));
dd369652
KZ
1288
1289 if (mnt_fs_get_root(fs))
77417bc0 1290 fprintf(file, "root: %s\n", mnt_fs_get_root(fs));
dd369652
KZ
1291 if (mnt_fs_get_bindsrc(fs))
1292 fprintf(file, "bindsrc: %s\n", mnt_fs_get_bindsrc(fs));
9dd75aa6 1293 if (mnt_fs_get_freq(fs))
77417bc0 1294 fprintf(file, "freq: %d\n", mnt_fs_get_freq(fs));
9dd75aa6 1295 if (mnt_fs_get_passno(fs))
77417bc0 1296 fprintf(file, "pass: %d\n", mnt_fs_get_passno(fs));
9dd75aa6 1297 if (mnt_fs_get_id(fs))
77417bc0 1298 fprintf(file, "id: %d\n", mnt_fs_get_id(fs));
9dd75aa6 1299 if (mnt_fs_get_parent_id(fs))
77417bc0 1300 fprintf(file, "parent: %d\n", mnt_fs_get_parent_id(fs));
9dd75aa6 1301 if (mnt_fs_get_devno(fs))
77417bc0 1302 fprintf(file, "devno: %d:%d\n", major(mnt_fs_get_devno(fs)),
9dd75aa6 1303 minor(mnt_fs_get_devno(fs)));
d115ee9b
KZ
1304 return 0;
1305}
8b95253f
KZ
1306
1307/**
1308 * mnt_free_mntent:
1309 * @mnt: mount entry
1310 *
1311 * Deallocates "mntent.h" mount entry.
1312 */
1313void mnt_free_mntent(struct mntent *mnt)
1314{
1315 if (mnt) {
1316 free(mnt->mnt_fsname);
1317 free(mnt->mnt_dir);
1318 free(mnt->mnt_type);
1319 free(mnt->mnt_opts);
1320 free(mnt);
1321 }
1322}
1323
1324/**
1325 * mnt_fs_to_mntent:
1326 * @fs: filesystem
1327 * @mnt: mount description (as described in mntent.h)
1328 *
1329 * Copies information from @fs to struct mntent @mnt. If @mnt is already set
1330 * then the struct mntent items are reallocated and updated. See also
1331 * mnt_free_mntent().
1332 *
1333 * Returns: 0 on success and negative number in case of error.
1334 */
1335int mnt_fs_to_mntent(mnt_fs *fs, struct mntent **mnt)
1336{
1337 int rc;
1338 struct mntent *m;
1339
1340 if (!fs || !mnt)
1341 return -EINVAL;
1342
1343 m = *mnt;
1344 if (!m) {
1345 m = calloc(1, sizeof(*m));
1346 if (!m)
1347 return -ENOMEM;
1348 }
1349
1350 if ((rc = cpy_str(&m->mnt_fsname, mnt_fs_get_source(fs))))
1351 goto err;
1352 if ((rc = cpy_str(&m->mnt_dir, mnt_fs_get_target(fs))))
1353 goto err;
1354 if ((rc = cpy_str(&m->mnt_type, mnt_fs_get_fstype(fs))))
1355 goto err;
76a06ca4
KZ
1356
1357 errno = 0;
1358 m->mnt_opts = mnt_fs_strdup_options(fs);
1359 if (!m->mnt_opts && errno) {
1360 rc = -errno;
8b95253f 1361 goto err;
76a06ca4
KZ
1362 }
1363
8b95253f
KZ
1364 m->mnt_freq = mnt_fs_get_freq(fs);
1365 m->mnt_passno = mnt_fs_get_passno(fs);
1366
1367 *mnt = m;
1368
1369 return 0;
1370err:
1371 if (m != *mnt)
1372 mnt_free_mntent(m);
1373 return rc;
1374}