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