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