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