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