]> git.ipfire.org Git - thirdparty/util-linux.git/blame - libmount/src/fs.c
more: Use ul_strtou16() in a robust way
[thirdparty/util-linux.git] / libmount / src / fs.c
CommitLineData
2c37ca7c 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
d115ee9b 2/*
2c37ca7c 3 * This file is part of libmount from util-linux project.
d115ee9b 4 *
2c37ca7c
KZ
5 * Copyright (C) 2008-2018 Karel Zak <kzak@redhat.com>
6 *
7 * libmount is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
d115ee9b
KZ
11 */
12
192c6aad
KZ
13/**
14 * SECTION: fs
15 * @title: Filesystem
e9d52e6e 16 * @short_description: represents one entry from fstab, or mountinfo file
192c6aad
KZ
17 *
18 */
d115ee9b 19#include <ctype.h>
8e368761 20#include <blkid.h>
9ecdf48f 21#include <stddef.h>
d115ee9b 22
d115ee9b 23#include "mountP.h"
b106d052 24#include "strutils.h"
d115ee9b
KZ
25
26/**
27 * mnt_new_fs:
28 *
26d0c0ae
KZ
29 * The initial refcount is 1, and needs to be decremented to
30 * release the resources of the filesystem.
31 *
68164f6c 32 * Returns: newly allocated struct libmnt_fs.
d115ee9b 33 */
68164f6c 34struct libmnt_fs *mnt_new_fs(void)
d115ee9b 35{
68164f6c 36 struct libmnt_fs *fs = calloc(1, sizeof(*fs));
2903c98e 37
d115ee9b
KZ
38 if (!fs)
39 return NULL;
40
26d0c0ae 41 fs->refcount = 1;
d115ee9b 42 INIT_LIST_HEAD(&fs->ents);
fe0d12d4 43 DBG(FS, ul_debugobj(fs, "alloc"));
d115ee9b
KZ
44 return fs;
45}
46
47/**
48 * mnt_free_fs:
49 * @fs: fs pointer
50 *
26d0c0ae 51 * Deallocates the fs. This function does not care about reference count. Don't
a7349ee3 52 * use this function directly -- it's better to use mnt_unref_fs().
26d0c0ae
KZ
53 *
54 * The reference counting is supported since util-linux v2.24.
d115ee9b 55 */
68164f6c 56void mnt_free_fs(struct libmnt_fs *fs)
d115ee9b
KZ
57{
58 if (!fs)
59 return;
309139c7 60
a504eaed 61 DBG(FS, ul_debugobj(fs, "free [refcount=%d]", fs->refcount));
d115ee9b 62
a504eaed 63 mnt_reset_fs(fs);
d115ee9b
KZ
64 free(fs);
65}
66
309139c7
KZ
67/**
68 * mnt_reset_fs:
69 * @fs: fs pointer
70 *
71 * Resets (zeroize) @fs.
72 */
73void mnt_reset_fs(struct libmnt_fs *fs)
74{
26d0c0ae
KZ
75 int ref;
76
77 if (!fs)
78 return;
79
80 ref = fs->refcount;
a504eaed
KZ
81
82 list_del(&fs->ents);
83 free(fs->source);
84 free(fs->bindsrc);
85 free(fs->tagname);
86 free(fs->tagval);
87 free(fs->root);
88 free(fs->swaptype);
89 free(fs->target);
90 free(fs->fstype);
91 free(fs->optstr);
92 free(fs->vfs_optstr);
93 free(fs->fs_optstr);
94 free(fs->user_optstr);
95 free(fs->attrs);
96 free(fs->opt_fields);
97 free(fs->comment);
98
22c4b548
KZ
99 mnt_unref_optlist(fs->optlist);
100 fs->optlist = NULL;
101
faa3d718 102 fs->opts_age = 0;
ba353afb 103 fs->propagation = 0;
faa3d718 104
0affb7ae
KZ
105 mnt_unref_statmnt(fs->stmnt);
106 fs->stmnt = NULL;
107 fs->stmnt_done = 0;
108
26d0c0ae 109 memset(fs, 0, sizeof(*fs));
14104e93 110 INIT_LIST_HEAD(&fs->ents);
26d0c0ae
KZ
111 fs->refcount = ref;
112}
113
114/**
115 * mnt_ref_fs:
116 * @fs: fs pointer
117 *
118 * Increments reference counter.
119 */
120void mnt_ref_fs(struct libmnt_fs *fs)
121{
122 if (fs) {
123 fs->refcount++;
83a78332 124 /*DBG(FS, ul_debugobj(fs, "ref=%d", fs->refcount));*/
26d0c0ae
KZ
125 }
126}
127
128/**
129 * mnt_unref_fs:
130 * @fs: fs pointer
131 *
47cca899 132 * De-increments reference counter, on zero the @fs is automatically
26d0c0ae
KZ
133 * deallocated by mnt_free_fs().
134 */
135void mnt_unref_fs(struct libmnt_fs *fs)
136{
137 if (fs) {
138 fs->refcount--;
83a78332 139 /*DBG(FS, ul_debugobj(fs, "unref=%d", fs->refcount));*/
26d0c0ae
KZ
140 if (fs->refcount <= 0)
141 mnt_free_fs(fs);
142 }
309139c7
KZ
143}
144
145static inline int update_str(char **dest, const char *src)
9ecdf48f 146{
8b95253f
KZ
147 size_t sz;
148 char *x;
149
150 assert(dest);
9ecdf48f 151
8b95253f
KZ
152 if (!src) {
153 free(*dest);
154 *dest = NULL;
9ecdf48f 155 return 0; /* source (old) is empty */
8b95253f 156 }
9ecdf48f 157
8b95253f
KZ
158 sz = strlen(src) + 1;
159 x = realloc(*dest, sz);
160 if (!x)
56be757f 161 return -ENOMEM;
8b95253f
KZ
162 *dest = x;
163 memcpy(*dest, src, sz);
9ecdf48f
KZ
164 return 0;
165}
166
bd0f347f
SN
167/* This function does NOT overwrite (replace) the string in @new, the string in
168 * @new has to be NULL otherwise this is no-op. */
8b95253f
KZ
169static inline int cpy_str_at_offset(void *new, const void *old, size_t offset)
170{
fef00631
BE
171 char **o = (char **) ((char *) old + offset);
172 char **n = (char **) ((char *) new + offset);
8b95253f 173
309139c7 174 if (*n)
d58b3157 175 return 0; /* already set, don't overwrite */
309139c7
KZ
176
177 return update_str(n, *o);
8b95253f
KZ
178}
179
faa3d718
KZ
180static inline int sync_opts_from_optlist(struct libmnt_fs *fs, struct libmnt_optlist *ol)
181{
2903c98e
KZ
182 unsigned int age;
183
184 assert(fs);
185 assert(ol);
faa3d718 186
2903c98e 187 age = mnt_optlist_get_age(ol);
faa3d718
KZ
188 if (age != fs->opts_age) {
189 const char *p;
190 int rc;
191
192 /* All options */
193 rc = mnt_optlist_get_optstr(ol, &p, NULL, 0);
194 if (!rc)
195 rc = strdup_to_struct_member(fs, optstr, p);
196
197 /* FS options */
198 if (!rc)
199 rc = mnt_optlist_get_optstr(ol, &p, NULL, MNT_OL_FLTR_UNKNOWN);
200 if (!rc)
201 rc = strdup_to_struct_member(fs, fs_optstr, p);
202
203 /* VFS options */
204 if (!rc)
205 rc = mnt_optlist_get_optstr(ol, &p, mnt_get_builtin_optmap(MNT_LINUX_MAP), 0);
206 if (!rc)
207 rc = strdup_to_struct_member(fs, vfs_optstr, p);
208
209 /* Userspace options */
210 if (!rc)
211 rc = mnt_optlist_get_optstr(ol, &p, mnt_get_builtin_optmap(MNT_USERSPACE_MAP), 0);
212 if (!rc)
213 rc = strdup_to_struct_member(fs, user_optstr, p);
214
215 if (rc) {
216 DBG(FS, ul_debugobj(fs, "sync failed [rc=%d]", rc));
217 return rc;
218 } else {
219 DBG(FS, ul_debugobj(fs, "synced: "
220 "vfs: '%s' fs: '%s' user: '%s', optstr: '%s'",
221 fs->vfs_optstr, fs->fs_optstr, fs->user_optstr, fs->optstr));
222 fs->opts_age = age;
223 }
224 }
225 return 0;
226}
227
228/* If @optlist is not NULL then @fs will read all option strings from @optlist.
229 * It means that mnt_fs_get_*_options() won't be read-only operations. */
230int mnt_fs_follow_optlist(struct libmnt_fs *fs, struct libmnt_optlist *ol)
231{
2903c98e
KZ
232 assert(fs);
233
faa3d718
KZ
234 if (fs->optlist == ol)
235 return 0;
7b37d5b5
KZ
236 if (fs->optlist)
237 mnt_unref_optlist(fs->optlist);
faa3d718
KZ
238
239 fs->opts_age = 0;
240 fs->optlist = ol;
7b37d5b5
KZ
241
242 if (ol)
243 mnt_ref_optlist(ol);
faa3d718
KZ
244 return 0;
245}
246
9ecdf48f
KZ
247/**
248 * mnt_copy_fs:
309139c7
KZ
249 * @dest: destination FS
250 * @src: source FS
251 *
252 * If @dest is NULL, then a new FS is allocated, if any @dest field is already
d58b3157 253 * set, then the field is NOT overwritten.
9ecdf48f
KZ
254 *
255 * This function does not copy userdata (se mnt_fs_set_userdata()). A new copy is
22c4b548 256 * not linked with any existing mnt_tab or optlist.
9ecdf48f 257 *
309139c7 258 * Returns: @dest or NULL in case of error
9ecdf48f 259 */
309139c7
KZ
260struct libmnt_fs *mnt_copy_fs(struct libmnt_fs *dest,
261 const struct libmnt_fs *src)
9ecdf48f 262{
309139c7 263 const struct libmnt_fs *org = dest;
9ecdf48f 264
52a285bf
KZ
265 if (!src)
266 return NULL;
309139c7
KZ
267 if (!dest) {
268 dest = mnt_new_fs();
269 if (!dest)
270 return NULL;
042057d8
KH
271
272 dest->tab = NULL;
309139c7 273 }
9ecdf48f 274
309139c7
KZ
275 dest->id = src->id;
276 dest->parent = src->parent;
277 dest->devno = src->devno;
f7f29b56 278 dest->tid = src->tid;
309139c7
KZ
279
280 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, source)))
9ecdf48f 281 goto err;
309139c7 282 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, tagname)))
9ecdf48f 283 goto err;
309139c7 284 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, tagval)))
9ecdf48f 285 goto err;
309139c7 286 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, root)))
9ecdf48f 287 goto err;
ce4dd666
KZ
288 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, swaptype)))
289 goto err;
309139c7 290 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, target)))
9ecdf48f 291 goto err;
309139c7 292 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, fstype)))
9ecdf48f 293 goto err;
f2b3a3a3
KZ
294 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, optstr)))
295 goto err;
309139c7 296 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, vfs_optstr)))
9ecdf48f 297 goto err;
309139c7 298 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, fs_optstr)))
9ecdf48f 299 goto err;
309139c7 300 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, user_optstr)))
76a06ca4 301 goto err;
309139c7 302 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, attrs)))
76a06ca4 303 goto err;
c4c66355
KZ
304 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, bindsrc)))
305 goto err;
76a06ca4 306
309139c7
KZ
307 dest->freq = src->freq;
308 dest->passno = src->passno;
309 dest->flags = src->flags;
ce4dd666
KZ
310 dest->size = src->size;
311 dest->usedsize = src->usedsize;
312 dest->priority = src->priority;
9ecdf48f 313
309139c7 314 return dest;
9ecdf48f 315err:
309139c7
KZ
316 if (!org)
317 mnt_free_fs(dest);
9ecdf48f
KZ
318 return NULL;
319}
320
0f32f1e2 321/*
f84fa6f7
KZ
322 * This function copies all @fs description except information that does not
323 * belong to /etc/mtab (e.g. VFS and userspace mount options with MNT_NOMTAB
324 * mask).
325 *
326 * Returns: copy of @fs.
327 */
faa3d718 328struct libmnt_fs *mnt_copy_mtab_fs(struct libmnt_fs *fs)
f84fa6f7 329{
68164f6c 330 struct libmnt_fs *n = mnt_new_fs();
f84fa6f7 331
4569bbea 332 assert(fs);
f84fa6f7
KZ
333 if (!n)
334 return NULL;
faa3d718
KZ
335 if (fs->optlist)
336 sync_opts_from_optlist(fs, fs->optlist);
f84fa6f7 337
eee7ea55 338 if (strdup_between_structs(n, fs, source))
f84fa6f7 339 goto err;
eee7ea55 340 if (strdup_between_structs(n, fs, target))
f84fa6f7 341 goto err;
eee7ea55 342 if (strdup_between_structs(n, fs, fstype))
f84fa6f7
KZ
343 goto err;
344
345 if (fs->vfs_optstr) {
346 char *p = NULL;
347 mnt_optstr_get_options(fs->vfs_optstr, &p,
348 mnt_get_builtin_optmap(MNT_LINUX_MAP),
349 MNT_NOMTAB);
350 n->vfs_optstr = p;
351 }
352
353 if (fs->user_optstr) {
354 char *p = NULL;
355 mnt_optstr_get_options(fs->user_optstr, &p,
356 mnt_get_builtin_optmap(MNT_USERSPACE_MAP),
357 MNT_NOMTAB);
358 n->user_optstr = p;
359 }
360
eee7ea55 361 if (strdup_between_structs(n, fs, fs_optstr))
f84fa6f7
KZ
362 goto err;
363
f2b3a3a3
KZ
364 /* we cannot copy original optstr, the new optstr has to be without
365 * non-mtab options -- so, let's generate a new string */
366 n->optstr = mnt_fs_strdup_options(n);
367
f84fa6f7
KZ
368 n->freq = fs->freq;
369 n->passno = fs->passno;
370 n->flags = fs->flags;
371
372 return n;
373err:
374 mnt_free_fs(n);
375 return NULL;
376
377}
378
26b4f9e4
KZ
379/**
380 * mnt_fs_get_userdata:
68164f6c 381 * @fs: struct libmnt_file instance
26b4f9e4 382 *
192c6aad 383 * Returns: private data set by mnt_fs_set_userdata() or NULL.
26b4f9e4 384 */
68164f6c 385void *mnt_fs_get_userdata(struct libmnt_fs *fs)
26b4f9e4 386{
14104e93
KZ
387 if (!fs)
388 return NULL;
14104e93 389 return fs->userdata;
26b4f9e4
KZ
390}
391
392/**
393 * mnt_fs_set_userdata:
68164f6c 394 * @fs: struct libmnt_file instance
0f32f1e2 395 * @data: user data
26b4f9e4
KZ
396 *
397 * The "userdata" are library independent data.
398 *
56be757f 399 * Returns: 0 or negative number in case of error (if @fs is NULL).
26b4f9e4 400 */
68164f6c 401int mnt_fs_set_userdata(struct libmnt_fs *fs, void *data)
26b4f9e4
KZ
402{
403 if (!fs)
56be757f 404 return -EINVAL;
26b4f9e4
KZ
405 fs->userdata = data;
406 return 0;
407}
408
d115ee9b
KZ
409/**
410 * mnt_fs_get_srcpath:
68164f6c 411 * @fs: struct libmnt_file (fstab/mtab/mountinfo) fs
d115ee9b
KZ
412 *
413 * The mount "source path" is:
192c6aad
KZ
414 * - a directory for 'bind' mounts (in fstab or mtab only)
415 * - a device name for standard mounts
d115ee9b
KZ
416 *
417 * See also mnt_fs_get_tag() and mnt_fs_get_source().
418 *
192c6aad 419 * Returns: mount source path or NULL in case of error or when the path
d115ee9b 420 * is not defined.
d115ee9b 421 */
68164f6c 422const char *mnt_fs_get_srcpath(struct libmnt_fs *fs)
d115ee9b 423{
d115ee9b
KZ
424 if (!fs)
425 return NULL;
426
427 /* fstab-like fs */
428 if (fs->tagname)
429 return NULL; /* the source contains a "NAME=value" */
781a960c
KZ
430
431 return mnt_fs_get_source(fs);
d115ee9b
KZ
432}
433
434/**
3d735589 435 * mnt_fs_get_source:
68164f6c 436 * @fs: struct libmnt_file (fstab/mtab/mountinfo) fs
d115ee9b 437 *
192c6aad 438 * Returns: mount source. Note that the source could be unparsed TAG
d115ee9b
KZ
439 * (LABEL/UUID). See also mnt_fs_get_srcpath() and mnt_fs_get_tag().
440 */
68164f6c 441const char *mnt_fs_get_source(struct libmnt_fs *fs)
d115ee9b 442{
781a960c
KZ
443 if (!fs)
444 return NULL;
445
446#ifdef HAVE_STATMOUNT_API
447 mnt_fs_try_statmount(fs, source, STATMOUNT_SB_SOURCE);
448#endif
449 return fs->source;
d115ee9b
KZ
450}
451
5af0769d 452/*
d58b3157 453 * Used by the parser ONLY (@source has to be freed on error)
5af0769d 454 */
68164f6c 455int __mnt_fs_set_source_ptr(struct libmnt_fs *fs, char *source)
d115ee9b 456{
b2d0b74d
KZ
457 char *t = NULL, *v = NULL;
458
d115ee9b
KZ
459 assert(fs);
460
2c6b25f0
KZ
461 if (source && blkid_parse_tag_string(source, &t, &v) == 0 &&
462 !mnt_valid_tagname(t)) {
463 /* parsable but unknown tag -- ignore */
464 free(t);
465 free(v);
466 t = v = NULL;
d115ee9b
KZ
467 }
468
b2d0b74d
KZ
469 if (fs->source != source)
470 free(fs->source);
471
472 free(fs->tagname);
473 free(fs->tagval);
474
d115ee9b 475 fs->source = source;
b2d0b74d
KZ
476 fs->tagname = t;
477 fs->tagval = v;
d115ee9b
KZ
478 return 0;
479}
480
481/**
482 * mnt_fs_set_source:
483 * @fs: fstab/mtab/mountinfo entry
484 * @source: new source
485 *
192c6aad
KZ
486 * This function creates a private copy (strdup()) of @source.
487 *
56be757f 488 * Returns: 0 on success or negative number in case of error.
d115ee9b 489 */
68164f6c 490int mnt_fs_set_source(struct libmnt_fs *fs, const char *source)
d115ee9b 491{
f5017242 492 char *p = NULL;
b2d0b74d 493 int rc;
d115ee9b 494
f5017242 495 if (!fs)
56be757f 496 return -EINVAL;
d0ce7c07 497
f5017242
KZ
498 if (source) {
499 p = strdup(source);
500 if (!p)
501 return -ENOMEM;
502 }
d115ee9b 503
b2d0b74d
KZ
504 rc = __mnt_fs_set_source_ptr(fs, p);
505 if (rc)
506 free(p);
507 return rc;
d115ee9b
KZ
508}
509
6699e742
KZ
510/**
511 * mnt_fs_streq_srcpath:
512 * @fs: fs
513 * @path: source path
514 *
73afd3f8
RM
515 * Compares @fs source path with @path. The redundant slashes are ignored.
516 * This function compares strings and does not canonicalize the paths.
d4e89dea 517 * See also more heavy and generic mnt_fs_match_source().
6699e742
KZ
518 *
519 * Returns: 1 if @fs source path equal to @path, otherwise 0.
520 */
ab8c6e05
KZ
521int mnt_fs_streq_srcpath(struct libmnt_fs *fs, const char *path)
522{
6699e742 523 const char *p;
ab8c6e05 524
6699e742 525 if (!fs)
ab8c6e05
KZ
526 return 0;
527
6699e742 528 p = mnt_fs_get_srcpath(fs);
ab8c6e05 529
6699e742 530 if (!mnt_fs_is_pseudofs(fs))
d4e89dea 531 return streq_paths(p, path);
6699e742
KZ
532
533 if (!p && !path)
534 return 1;
535
536 return p && path && strcmp(p, path) == 0;
ab8c6e05
KZ
537}
538
9d5eb4c4
TH
539/**
540 * mnt_fs_get_table:
541 * @fs: table entry
542 * @tb: table that contains @fs
543 *
544 * Returns: 0 or negative number on error (if @fs or @tb is NULL).
2089538a
KZ
545 *
546 * Since: 2.34
9d5eb4c4
TH
547 */
548int mnt_fs_get_table(struct libmnt_fs *fs, struct libmnt_table **tb)
549{
550 if (!fs || !tb)
551 return -EINVAL;
552
553 *tb = fs->tab;
554 return 0;
555}
556
6699e742
KZ
557/**
558 * mnt_fs_streq_target:
559 * @fs: fs
560 * @path: mount point
561 *
73afd3f8
RM
562 * Compares @fs target path with @path. The redundant slashes are ignored.
563 * This function compares strings and does not canonicalize the paths.
d4e89dea 564 * See also more generic mnt_fs_match_target().
6699e742
KZ
565 *
566 * Returns: 1 if @fs target path equal to @path, otherwise 0.
567 */
568int mnt_fs_streq_target(struct libmnt_fs *fs, const char *path)
569{
d4e89dea 570 return fs && streq_paths(mnt_fs_get_target(fs), path);
6699e742 571}
ab8c6e05 572
d115ee9b
KZ
573/**
574 * mnt_fs_get_tag:
575 * @fs: fs
576 * @name: returns pointer to NAME string
577 * @value: returns pointer to VALUE string
578 *
579 * "TAG" is NAME=VALUE (e.g. LABEL=foo)
580 *
d58b3157
OO
581 * The TAG is the first column in the fstab file. The TAG or "srcpath" always has
582 * to be set for all entries.
d115ee9b
KZ
583 *
584 * See also mnt_fs_get_source().
585 *
192c6aad
KZ
586 * <informalexample>
587 * <programlisting>
d115ee9b 588 * char *src;
68164f6c 589 * struct libmnt_fs *fs = mnt_table_find_target(tb, "/home", MNT_ITER_FORWARD);
d115ee9b
KZ
590 *
591 * if (!fs)
592 * goto err;
593 *
594 * src = mnt_fs_get_srcpath(fs);
595 * if (!src) {
596 * char *tag, *val;
597 * if (mnt_fs_get_tag(fs, &tag, &val) == 0)
598 * printf("%s: %s\n", tag, val); // LABEL or UUID
599 * } else
600 * printf("device: %s\n", src); // device or bind path
192c6aad
KZ
601 * </programlisting>
602 * </informalexample>
d115ee9b 603 *
d58b3157 604 * Returns: 0 on success or negative number in case a TAG is not defined.
d115ee9b 605 */
68164f6c 606int mnt_fs_get_tag(struct libmnt_fs *fs, const char **name, const char **value)
d115ee9b
KZ
607{
608 if (fs == NULL || !fs->tagname)
56be757f 609 return -EINVAL;
d115ee9b
KZ
610 if (name)
611 *name = fs->tagname;
612 if (value)
613 *value = fs->tagval;
614 return 0;
615}
616
617/**
618 * mnt_fs_get_target:
619 * @fs: fstab/mtab/mountinfo entry pointer
620 *
192c6aad 621 * Returns: pointer to mountpoint path or NULL
d115ee9b 622 */
68164f6c 623const char *mnt_fs_get_target(struct libmnt_fs *fs)
d115ee9b 624{
0affb7ae
KZ
625 if (!fs)
626 return NULL;
ec7c579a
KZ
627#ifdef HAVE_STATMOUNT_API
628 mnt_fs_try_statmount(fs, target, STATMOUNT_MNT_POINT);
629#endif
0affb7ae 630 return fs->target;;
d115ee9b
KZ
631}
632
633/**
634 * mnt_fs_set_target:
635 * @fs: fstab/mtab/mountinfo entry
deb1c903 636 * @tgt: mountpoint
d115ee9b 637 *
deb1c903 638 * This function creates a private copy (strdup()) of @tgt.
192c6aad 639 *
56be757f 640 * Returns: 0 on success or negative number in case of error.
d115ee9b 641 */
deb1c903 642int mnt_fs_set_target(struct libmnt_fs *fs, const char *tgt)
d115ee9b 643{
deb1c903 644 return strdup_to_struct_member(fs, target, tgt);
d115ee9b
KZ
645}
646
8241fb00
KZ
647int __mnt_fs_set_target_ptr(struct libmnt_fs *fs, char *tgt)
648{
2903c98e
KZ
649 assert(fs);
650
8241fb00
KZ
651 free(fs->target);
652 fs->target = tgt;
653 return 0;
654}
655
c70d9d76 656static int mnt_fs_get_flags(struct libmnt_fs *fs)
309139c7
KZ
657{
658 return fs ? fs->flags : 0;
659}
660
4b9d67a2
KZ
661/**
662 * mnt_fs_get_propagation:
663 * @fs: mountinfo entry
d58b3157 664 * @flags: returns propagation MS_* flags as present in the mountinfo file
4b9d67a2 665 *
d58b3157
OO
666 * Note that this function sets @flags to zero if no propagation flags are found
667 * in the mountinfo file. The kernel default is MS_PRIVATE, this flag is not stored
4b9d67a2
KZ
668 * in the mountinfo file.
669 *
670 * Returns: 0 on success or negative number in case of error.
671 */
672int mnt_fs_get_propagation(struct libmnt_fs *fs, unsigned long *flags)
673{
674 if (!fs || !flags)
675 return -EINVAL;
ec7c579a
KZ
676#ifdef HAVE_STATMOUNT_API
677 mnt_fs_try_statmount(fs, propagation, STATMOUNT_MNT_BASIC);
678#endif
ba353afb
KZ
679 if (!fs->propagation && fs->opt_fields) {
680 /*
681 * The optional fields format is incompatible with mount options
682 * ... we have to parse the field here.
683 */
684 fs->propagation |= strstr(fs->opt_fields, "shared:") ?
685 MS_SHARED : MS_PRIVATE;
686
687 if (strstr(fs->opt_fields, "master:"))
688 fs->propagation |= MS_SLAVE;
689 if (strstr(fs->opt_fields, "unbindable"))
690 fs->propagation |= MS_UNBINDABLE;
691 }
4b9d67a2 692
ba353afb 693 *flags = fs->propagation;
4b9d67a2
KZ
694
695 return 0;
696}
697
309139c7
KZ
698/**
699 * mnt_fs_is_kernel:
700 * @fs: filesystem
701 *
702 * Returns: 1 if the filesystem description is read from kernel e.g. /proc/mounts.
703 */
704int mnt_fs_is_kernel(struct libmnt_fs *fs)
705{
dfb5f064 706 return mnt_fs_get_flags(fs) & MNT_FS_KERNEL ? 1 : 0;
c70d9d76
KZ
707}
708
709/**
710 * mnt_fs_is_swaparea:
711 * @fs: filesystem
712 *
713 * Returns: 1 if the filesystem uses "swap" as a type
714 */
715int mnt_fs_is_swaparea(struct libmnt_fs *fs)
716{
dfb5f064 717 return mnt_fs_get_flags(fs) & MNT_FS_SWAP ? 1 : 0;
c70d9d76
KZ
718}
719
720/**
721 * mnt_fs_is_pseudofs:
722 * @fs: filesystem
723 *
724 * Returns: 1 if the filesystem is a pseudo fs type (proc, cgroups)
725 */
b928ab01 726int mnt_fs_is_pseudofs(struct libmnt_fs *fs)
c70d9d76 727{
0affb7ae
KZ
728 if (!fs)
729 return 0;
ec7c579a
KZ
730#ifdef HAVE_STATMOUNT_API
731 mnt_fs_try_statmount(fs, fstype, STATMOUNT_FS_TYPE);
732#endif
dfb5f064 733 return mnt_fs_get_flags(fs) & MNT_FS_PSEUDO ? 1 : 0;
c70d9d76
KZ
734}
735
736/**
737 * mnt_fs_is_netfs:
738 * @fs: filesystem
739 *
740 * Returns: 1 if the filesystem is a network filesystem
741 */
742int mnt_fs_is_netfs(struct libmnt_fs *fs)
743{
0affb7ae
KZ
744 if (!fs)
745 return 0;
ec7c579a
KZ
746#ifdef HAVE_STATMOUNT_API
747 mnt_fs_try_statmount(fs, fstype, STATMOUNT_FS_TYPE);
748#endif
dfb5f064 749 return mnt_fs_get_flags(fs) & MNT_FS_NET ? 1 : 0;
309139c7
KZ
750}
751
ac8697d6
KZ
752/**
753 * mnt_fs_is_regularfs:
754 * @fs: filesystem
755 *
756 * Returns: 1 if the filesystem is a regular filesystem (not network or pseudo filesystem).
757 *
758 * Since: 2.38
759 */
760int mnt_fs_is_regularfs(struct libmnt_fs *fs)
761{
762 return !(mnt_fs_is_pseudofs(fs)
763 || mnt_fs_is_netfs(fs)
764 || mnt_fs_is_swaparea(fs));
765}
766
d115ee9b
KZ
767/**
768 * mnt_fs_get_fstype:
769 * @fs: fstab/mtab/mountinfo entry pointer
770 *
192c6aad 771 * Returns: pointer to filesystem type.
d115ee9b 772 */
68164f6c 773const char *mnt_fs_get_fstype(struct libmnt_fs *fs)
d115ee9b 774{
0affb7ae
KZ
775 if (!fs)
776 return NULL;
ec7c579a
KZ
777#ifdef HAVE_STATMOUNT_API
778 mnt_fs_try_statmount(fs, fstype, STATMOUNT_FS_TYPE);
779#endif
0affb7ae 780 return fs->fstype;
d115ee9b
KZ
781}
782
d58b3157 783/* Used by the struct libmnt_file parser only */
68164f6c 784int __mnt_fs_set_fstype_ptr(struct libmnt_fs *fs, char *fstype)
d115ee9b
KZ
785{
786 assert(fs);
787
b2d0b74d
KZ
788 if (fstype != fs->fstype)
789 free(fs->fstype);
790
d115ee9b
KZ
791 fs->fstype = fstype;
792 fs->flags &= ~MNT_FS_PSEUDO;
793 fs->flags &= ~MNT_FS_NET;
5dfc9843 794 fs->flags &= ~MNT_FS_SWAP;
d115ee9b
KZ
795
796 /* save info about pseudo filesystems */
8485e709
KZ
797 if (fs->fstype) {
798 if (mnt_fstype_is_pseudofs(fs->fstype))
799 fs->flags |= MNT_FS_PSEUDO;
800 else if (mnt_fstype_is_netfs(fs->fstype))
801 fs->flags |= MNT_FS_NET;
802 else if (!strcmp(fs->fstype, "swap"))
803 fs->flags |= MNT_FS_SWAP;
804 }
d115ee9b
KZ
805 return 0;
806}
807
808/**
809 * mnt_fs_set_fstype:
810 * @fs: fstab/mtab/mountinfo entry
811 * @fstype: filesystem type
812 *
192c6aad
KZ
813 * This function creates a private copy (strdup()) of @fstype.
814 *
56be757f 815 * Returns: 0 on success or negative number in case of error.
d115ee9b 816 */
68164f6c 817int mnt_fs_set_fstype(struct libmnt_fs *fs, const char *fstype)
d115ee9b 818{
8485e709 819 char *p = NULL;
d115ee9b 820
8485e709 821 if (!fs)
56be757f 822 return -EINVAL;
8485e709
KZ
823 if (fstype) {
824 p = strdup(fstype);
825 if (!p)
826 return -ENOMEM;
827 }
f5017242 828 return __mnt_fs_set_fstype_ptr(fs, p);
d115ee9b
KZ
829}
830
76a06ca4 831/*
e61d02d2
KZ
832 * Merges @vfs and @fs options strings into a new string. This function cares
833 * about 'ro/rw' options. The 'ro' is always used if @vfs or @fs is read-only.
76a06ca4
KZ
834 */
835static char *merge_optstr(const char *vfs, const char *fs)
836{
837 char *res, *p;
838 size_t sz;
839 int ro = 0, rw = 0;
840
841 if (!vfs && !fs)
842 return NULL;
843 if (!vfs || !fs)
844 return strdup(fs ? fs : vfs);
845 if (!strcmp(vfs, fs))
846 return strdup(vfs); /* e.g. "aaa" and "aaa" */
847
d58b3157 848 /* leave space for the leading "r[ow],", "," and the trailing zero */
76a06ca4
KZ
849 sz = strlen(vfs) + strlen(fs) + 5;
850 res = malloc(sz);
851 if (!res)
852 return NULL;
853 p = res + 3; /* make a room for rw/ro flag */
854
855 snprintf(p, sz - 3, "%s,%s", vfs, fs);
856
857 /* remove 'rw' flags */
858 rw += !mnt_optstr_remove_option(&p, "rw"); /* from vfs */
859 rw += !mnt_optstr_remove_option(&p, "rw"); /* from fs */
860
861 /* remove 'ro' flags if necessary */
862 if (rw != 2) {
863 ro += !mnt_optstr_remove_option(&p, "ro");
864 if (ro + rw < 2)
865 ro += !mnt_optstr_remove_option(&p, "ro");
866 }
867
868 if (!strlen(p))
869 memcpy(res, ro ? "ro" : "rw", 3);
870 else
871 memcpy(res, ro ? "ro," : "rw,", 3);
872 return res;
873}
874
e61d02d2
KZ
875static char *fs_strdup_options(struct libmnt_fs *fs)
876{
877 char *res;
878
879 errno = 0;
880 if (fs->optstr)
881 return strdup(fs->optstr);
882
883 res = merge_optstr(fs->vfs_optstr, fs->fs_optstr);
884 if (!res && errno)
885 return NULL;
886 if (fs->user_optstr &&
887 mnt_optstr_append_option(&res, fs->user_optstr, NULL)) {
888 free(res);
889 res = NULL;
890 }
891 return res;
892}
893
d115ee9b 894/**
76a06ca4 895 * mnt_fs_strdup_options:
d115ee9b
KZ
896 * @fs: fstab/mtab/mountinfo entry pointer
897 *
d58b3157 898 * Merges all mount options (VFS, FS and userspace) to one options string
9e930041 899 * and returns the result. This function does not modify @fs.
76a06ca4
KZ
900 *
901 * Returns: pointer to string (can be freed by free(3)) or NULL in case of error.
d115ee9b 902 */
68164f6c 903char *mnt_fs_strdup_options(struct libmnt_fs *fs)
d115ee9b 904{
37290a53
KZ
905 if (!fs)
906 return NULL;
faa3d718
KZ
907 if (fs->optlist)
908 sync_opts_from_optlist(fs, fs->optlist);
ec7c579a
KZ
909#ifdef HAVE_STATMOUNT_API
910 else
e61d02d2
KZ
911 mnt_fs_try_statmount(fs, optstr, STATMOUNT_SB_BASIC
912 | STATMOUNT_MNT_BASIC | STATMOUNT_MNT_OPTS);
ec7c579a 913#endif
e61d02d2 914 return fs_strdup_options(fs);
f2b3a3a3 915
d115ee9b
KZ
916}
917
f2b3a3a3
KZ
918/**
919 * mnt_fs_get_options:
920 * @fs: fstab/mtab/mountinfo entry pointer
921 *
922 * Returns: pointer to string or NULL in case of error.
923 */
924const char *mnt_fs_get_options(struct libmnt_fs *fs)
925{
0affb7ae
KZ
926 if (!fs)
927 return NULL;
928 if (fs->optlist)
faa3d718 929 sync_opts_from_optlist(fs, fs->optlist);
ec7c579a 930#ifdef HAVE_STATMOUNT_API
e61d02d2
KZ
931 else {
932 mnt_fs_try_statmount(fs, optstr, STATMOUNT_SB_BASIC
933 | STATMOUNT_MNT_BASIC | STATMOUNT_MNT_OPTS);
934 if (!fs->optstr)
935 fs->optstr = fs_strdup_options(fs);
936 }
ec7c579a 937#endif
0affb7ae 938 return fs->optstr;
f2b3a3a3
KZ
939}
940
e47a1931
OO
941/**
942 * mnt_fs_get_optional_fields
943 * @fs: mountinfo entry pointer
944 *
945 * Returns: pointer to string with mountinfo optional fields
946 * or NULL in case of error.
947 */
948const char *mnt_fs_get_optional_fields(struct libmnt_fs *fs)
949{
e47a1931
OO
950 return fs ? fs->opt_fields : NULL;
951}
f2b3a3a3 952
76a06ca4
KZ
953/**
954 * mnt_fs_set_options:
955 * @fs: fstab/mtab/mountinfo entry pointer
0f32f1e2 956 * @optstr: options string
76a06ca4 957 *
d58b3157 958 * Splits @optstr to VFS, FS and userspace mount options and updates relevant
76a06ca4
KZ
959 * parts of @fs.
960 *
d58b3157 961 * Returns: 0 on success, or negative number in case of error.
76a06ca4 962 */
68164f6c 963int mnt_fs_set_options(struct libmnt_fs *fs, const char *optstr)
d115ee9b 964{
f2b3a3a3 965 char *v = NULL, *f = NULL, *u = NULL, *n = NULL;
192c6aad 966
be1a5180 967 if (!fs)
56be757f 968 return -EINVAL;
7b37d5b5
KZ
969
970 if (fs->optlist) {
971 fs->opts_age = 0;
972 return mnt_optlist_set_optstr(fs->optlist, optstr, NULL);
973 }
faa3d718 974
76a06ca4
KZ
975 if (optstr) {
976 int rc = mnt_split_optstr(optstr, &u, &v, &f, 0, 0);
56be757f
KZ
977 if (rc)
978 return rc;
f2b3a3a3 979 n = strdup(optstr);
c470cbfc
NK
980 if (!n) {
981 free(u);
982 free(v);
983 free(f);
f2b3a3a3 984 return -ENOMEM;
c470cbfc 985 }
3661b841 986 }
192c6aad 987
d115ee9b
KZ
988 free(fs->fs_optstr);
989 free(fs->vfs_optstr);
76a06ca4 990 free(fs->user_optstr);
f2b3a3a3 991 free(fs->optstr);
d6fead1e 992
3661b841
KZ
993 fs->fs_optstr = f;
994 fs->vfs_optstr = v;
76a06ca4 995 fs->user_optstr = u;
f2b3a3a3
KZ
996 fs->optstr = n;
997
192c6aad 998 return 0;
d115ee9b
KZ
999}
1000
76a06ca4
KZ
1001/**
1002 * mnt_fs_append_options:
1003 * @fs: fstab/mtab/mountinfo entry
1004 * @optstr: mount options
1005 *
1006 * Parses (splits) @optstr and appends results to VFS, FS and userspace lists
1007 * of options.
1008 *
d58b3157 1009 * If @optstr is NULL, then @fs is not modified and 0 is returned.
76a06ca4
KZ
1010 *
1011 * Returns: 0 on success or negative number in case of error.
1012 */
68164f6c 1013int mnt_fs_append_options(struct libmnt_fs *fs, const char *optstr)
b2d0b74d 1014{
76a06ca4 1015 char *v = NULL, *f = NULL, *u = NULL;
b2d0b74d
KZ
1016 int rc;
1017
76a06ca4
KZ
1018 if (!fs)
1019 return -EINVAL;
1020 if (!optstr)
1021 return 0;
7b37d5b5
KZ
1022 if (fs->optlist) {
1023 fs->opts_age = 0;
1024 return mnt_optlist_append_optstr(fs->optlist, optstr, NULL);
1025 }
faa3d718 1026
b00dd55a 1027 rc = mnt_split_optstr(optstr, &u, &v, &f, 0, 0);
1e670193
KZ
1028 if (rc)
1029 return rc;
1030
76a06ca4
KZ
1031 if (!rc && v)
1032 rc = mnt_optstr_append_option(&fs->vfs_optstr, v, NULL);
1033 if (!rc && f)
f2b3a3a3 1034 rc = mnt_optstr_append_option(&fs->fs_optstr, f, NULL);
76a06ca4 1035 if (!rc && u)
f2b3a3a3
KZ
1036 rc = mnt_optstr_append_option(&fs->user_optstr, u, NULL);
1037 if (!rc)
1038 rc = mnt_optstr_append_option(&fs->optstr, optstr, NULL);
1039
1040 free(v);
1041 free(f);
1042 free(u);
76a06ca4 1043
b2d0b74d
KZ
1044 return rc;
1045}
1046
3661b841 1047/**
76a06ca4
KZ
1048 * mnt_fs_prepend_options:
1049 * @fs: fstab/mtab/mountinfo entry
1050 * @optstr: mount options
1051 *
d58b3157 1052 * Parses (splits) @optstr and prepends the results to VFS, FS and userspace lists
76a06ca4
KZ
1053 * of options.
1054 *
d58b3157 1055 * If @optstr is NULL, then @fs is not modified and 0 is returned.
76a06ca4
KZ
1056 *
1057 * Returns: 0 on success or negative number in case of error.
1058 */
68164f6c 1059int mnt_fs_prepend_options(struct libmnt_fs *fs, const char *optstr)
76a06ca4
KZ
1060{
1061 char *v = NULL, *f = NULL, *u = NULL;
1062 int rc;
1063
76a06ca4
KZ
1064 if (!fs)
1065 return -EINVAL;
1066 if (!optstr)
1067 return 0;
1068
7b37d5b5
KZ
1069 if (fs->optlist) {
1070 fs->opts_age = 0;
1071 return mnt_optlist_prepend_optstr(fs->optlist, optstr, NULL);
1072 }
faa3d718 1073
b00dd55a 1074 rc = mnt_split_optstr(optstr, &u, &v, &f, 0, 0);
1e670193
KZ
1075 if (rc)
1076 return rc;
1077
76a06ca4
KZ
1078 if (!rc && v)
1079 rc = mnt_optstr_prepend_option(&fs->vfs_optstr, v, NULL);
1080 if (!rc && f)
1081 rc = mnt_optstr_prepend_option(&fs->fs_optstr, f, NULL);
1082 if (!rc && u)
1083 rc = mnt_optstr_prepend_option(&fs->user_optstr, u, NULL);
f2b3a3a3
KZ
1084 if (!rc)
1085 rc = mnt_optstr_prepend_option(&fs->optstr, optstr, NULL);
1086
1087 free(v);
1088 free(f);
1089 free(u);
76a06ca4
KZ
1090
1091 return rc;
1092}
1093
faa3d718
KZ
1094
1095/**
76a06ca4
KZ
1096 * mnt_fs_get_fs_options:
1097 * @fs: fstab/mtab/mountinfo entry pointer
1098 *
1099 * Returns: pointer to superblock (fs-depend) mount option string or NULL.
1100 */
68164f6c 1101const char *mnt_fs_get_fs_options(struct libmnt_fs *fs)
76a06ca4 1102{
2903c98e
KZ
1103 if (!fs)
1104 return NULL;
faa3d718
KZ
1105 if (fs->optlist)
1106 sync_opts_from_optlist(fs, fs->optlist);
ec7c579a
KZ
1107#ifdef HAVE_STATMOUNT_API
1108 else
e61d02d2 1109 mnt_fs_try_statmount(fs, fs_optstr, STATMOUNT_SB_BASIC | STATMOUNT_MNT_OPTS);
ec7c579a 1110#endif
2903c98e 1111 return fs->fs_optstr;
76a06ca4
KZ
1112}
1113
76a06ca4
KZ
1114/**
1115 * mnt_fs_get_vfs_options:
1116 * @fs: fstab/mtab entry pointer
1117 *
1118 * Returns: pointer to fs-independent (VFS) mount option string or NULL.
1119 */
68164f6c 1120const char *mnt_fs_get_vfs_options(struct libmnt_fs *fs)
76a06ca4 1121{
2903c98e
KZ
1122 if (!fs)
1123 return NULL;
faa3d718
KZ
1124 if (fs->optlist)
1125 sync_opts_from_optlist(fs, fs->optlist);
ec7c579a
KZ
1126#ifdef HAVE_STATMOUNT_API
1127 else
1128 mnt_fs_try_statmount(fs, vfs_optstr, STATMOUNT_MNT_BASIC);
1129#endif
2903c98e 1130 return fs->vfs_optstr;
76a06ca4
KZ
1131}
1132
ff21f476
RBC
1133/**
1134 * mnt_fs_get_vfs_options_all:
1135 * @fs: fstab/mtab entry pointer
1136 *
1137 * Returns: pointer to newlly allocated string (can be freed by free(3)) or
1138 * NULL in case of error. The string contains all (including defaults) mount
1139 * options.
1140 */
1141char *mnt_fs_get_vfs_options_all(struct libmnt_fs *fs)
1142{
1143 const struct libmnt_optmap *map = mnt_get_builtin_optmap(MNT_LINUX_MAP);
1144 const struct libmnt_optmap *ent;
1145 const char *opts = mnt_fs_get_options(fs);
1146 char *result = NULL;
1147 unsigned long flags = 0;
1148
1149 if (!opts || mnt_optstr_get_flags(opts, &flags, map))
1150 return NULL;
1151
1152 for (ent = map ; ent && ent->name ; ent++){
1153 if (ent->id & flags) { /* non-default value */
1154 if (!(ent->mask & MNT_INVERT))
1155 mnt_optstr_append_option(&result, ent->name, NULL);
1156 else
1157 continue;
1158 } else if (ent->mask & MNT_INVERT)
1159 mnt_optstr_append_option(&result, ent->name, NULL);
1160 }
1161
1162 return result;
1163}
1164
76a06ca4 1165/**
68164f6c 1166 * mnt_fs_get_user_options:
76a06ca4
KZ
1167 * @fs: fstab/mtab entry pointer
1168 *
1169 * Returns: pointer to userspace mount option string or NULL.
1170 */
68164f6c 1171const char *mnt_fs_get_user_options(struct libmnt_fs *fs)
76a06ca4 1172{
2903c98e
KZ
1173 if (!fs)
1174 return NULL;
faa3d718
KZ
1175 if (fs->optlist)
1176 sync_opts_from_optlist(fs, fs->optlist);
1177
2903c98e 1178 return fs->user_optstr;
569f95b7
KZ
1179}
1180
d115ee9b 1181/**
76a06ca4
KZ
1182 * mnt_fs_get_attributes:
1183 * @fs: fstab/mtab entry pointer
d115ee9b 1184 *
76a06ca4 1185 * Returns: pointer to attributes string or NULL.
d115ee9b 1186 */
68164f6c 1187const char *mnt_fs_get_attributes(struct libmnt_fs *fs)
d115ee9b 1188{
76a06ca4 1189 return fs ? fs->attrs : NULL;
d115ee9b
KZ
1190}
1191
1192/**
76a06ca4
KZ
1193 * mnt_fs_set_attributes:
1194 * @fs: fstab/mtab/mountinfo entry
1195 * @optstr: options string
d115ee9b 1196 *
76a06ca4 1197 * Sets mount attributes. The attributes are mount(2) and mount(8) independent
d58b3157 1198 * options, these options are not sent to the kernel and are not interpreted by
a362ae60 1199 * libmount. The attributes are stored in /run/mount/utab only.
76a06ca4 1200 *
d58b3157 1201 * The attributes are managed by libmount in userspace only. It's possible
76a06ca4 1202 * that information stored in userspace will not be available for libmount
7007991f 1203 * after CLONE_FS unshare. Be careful, and don't use attributes if possible.
76a06ca4 1204 *
0affb7ae
KZ
1205 * Please note that the new mount kernel API calls some VFS flags "mount attributes"
1206 * (MOUNT_ATTR_*), but these flags are not related to the old libmount functionality.
1207 *
76a06ca4 1208 * Returns: 0 on success or negative number in case of error.
d115ee9b 1209 */
68164f6c 1210int mnt_fs_set_attributes(struct libmnt_fs *fs, const char *optstr)
d115ee9b 1211{
deb1c903 1212 return strdup_to_struct_member(fs, attrs, optstr);
76a06ca4
KZ
1213}
1214
1215/**
1216 * mnt_fs_append_attributes
1217 * @fs: fstab/mtab/mountinfo entry
1218 * @optstr: options string
1219 *
1220 * Appends mount attributes. (See mnt_fs_set_attributes()).
1221 *
1222 * Returns: 0 on success or negative number in case of error.
1223 */
68164f6c 1224int mnt_fs_append_attributes(struct libmnt_fs *fs, const char *optstr)
76a06ca4
KZ
1225{
1226 if (!fs)
1227 return -EINVAL;
1228 if (!optstr)
1229 return 0;
1230 return mnt_optstr_append_option(&fs->attrs, optstr, NULL);
1231}
1232
1233/**
1234 * mnt_fs_prepend_attributes
1235 * @fs: fstab/mtab/mountinfo entry
1236 * @optstr: options string
1237 *
1238 * Prepends mount attributes. (See mnt_fs_set_attributes()).
1239 *
1240 * Returns: 0 on success or negative number in case of error.
1241 */
68164f6c 1242int mnt_fs_prepend_attributes(struct libmnt_fs *fs, const char *optstr)
76a06ca4
KZ
1243{
1244 if (!fs)
1245 return -EINVAL;
1246 if (!optstr)
1247 return 0;
1248 return mnt_optstr_prepend_option(&fs->attrs, optstr, NULL);
d115ee9b
KZ
1249}
1250
1251
1252/**
1253 * mnt_fs_get_freq:
1254 * @fs: fstab/mtab/mountinfo entry pointer
1255 *
3d735589 1256 * Returns: dump frequency in days.
d115ee9b 1257 */
68164f6c 1258int mnt_fs_get_freq(struct libmnt_fs *fs)
d115ee9b 1259{
d115ee9b
KZ
1260 return fs ? fs->freq : 0;
1261}
1262
1263/**
1264 * mnt_fs_set_freq:
efe73c3e 1265 * @fs: fstab/mtab entry pointer
d115ee9b
KZ
1266 * @freq: dump frequency in days
1267 *
56be757f 1268 * Returns: 0 on success or negative number in case of error.
d115ee9b 1269 */
68164f6c 1270int mnt_fs_set_freq(struct libmnt_fs *fs, int freq)
d115ee9b 1271{
d115ee9b 1272 if (!fs)
56be757f 1273 return -EINVAL;
d115ee9b
KZ
1274 fs->freq = freq;
1275 return 0;
1276}
1277
1278/**
1279 * mnt_fs_get_passno:
efe73c3e 1280 * @fs: fstab/mtab entry pointer
d115ee9b 1281 *
192c6aad 1282 * Returns: "pass number on parallel fsck".
d115ee9b 1283 */
68164f6c 1284int mnt_fs_get_passno(struct libmnt_fs *fs)
d115ee9b 1285{
d115ee9b
KZ
1286 return fs ? fs->passno: 0;
1287}
1288
1289/**
1290 * mnt_fs_set_passno:
efe73c3e 1291 * @fs: fstab/mtab entry pointer
d115ee9b
KZ
1292 * @passno: pass number
1293 *
56be757f 1294 * Returns: 0 on success or negative number in case of error.
d115ee9b 1295 */
68164f6c 1296int mnt_fs_set_passno(struct libmnt_fs *fs, int passno)
d115ee9b 1297{
d115ee9b 1298 if (!fs)
56be757f 1299 return -EINVAL;
d115ee9b
KZ
1300 fs->passno = passno;
1301 return 0;
1302}
1303
0b3953a3
KZ
1304/**
1305 * mnt_fs_get_root:
1306 * @fs: /proc/self/mountinfo entry
1307 *
1308 * Returns: root of the mount within the filesystem or NULL
1309 */
68164f6c 1310const char *mnt_fs_get_root(struct libmnt_fs *fs)
0b3953a3 1311{
0affb7ae
KZ
1312 if (!fs)
1313 return NULL;
ec7c579a
KZ
1314#ifdef HAVE_STATMOUNT_API
1315 mnt_fs_try_statmount(fs, root, STATMOUNT_MNT_ROOT);
1316#endif
0affb7ae 1317 return fs->root;
0b3953a3
KZ
1318}
1319
9ecdf48f
KZ
1320/**
1321 * mnt_fs_set_root:
1322 * @fs: mountinfo entry
deb1c903 1323 * @path: root path
9ecdf48f 1324 *
56be757f 1325 * Returns: 0 on success or negative number in case of error.
9ecdf48f 1326 */
deb1c903 1327int mnt_fs_set_root(struct libmnt_fs *fs, const char *path)
9ecdf48f 1328{
deb1c903 1329 return strdup_to_struct_member(fs, root, path);
9ecdf48f
KZ
1330}
1331
ce4dd666
KZ
1332/**
1333 * mnt_fs_get_swaptype:
1334 * @fs: /proc/swaps entry
1335 *
1336 * Returns: swap type or NULL
1337 */
1338const char *mnt_fs_get_swaptype(struct libmnt_fs *fs)
1339{
ce4dd666
KZ
1340 return fs ? fs->swaptype : NULL;
1341}
1342
1343/**
1344 * mnt_fs_get_size:
1345 * @fs: /proc/swaps entry
1346 *
1347 * Returns: size
1348 */
1349off_t mnt_fs_get_size(struct libmnt_fs *fs)
1350{
ce4dd666
KZ
1351 return fs ? fs->size : 0;
1352}
1353
1354/**
1355 * mnt_fs_get_usedsize:
1356 * @fs: /proc/swaps entry
1357 *
1358 * Returns: used size
1359 */
1360off_t mnt_fs_get_usedsize(struct libmnt_fs *fs)
1361{
ce4dd666
KZ
1362 return fs ? fs->usedsize : 0;
1363}
1364
1365/**
1366 * mnt_fs_get_priority:
1367 * @fs: /proc/swaps entry
1368 *
1369 * Returns: priority
1370 */
1371int mnt_fs_get_priority(struct libmnt_fs *fs)
1372{
ce4dd666
KZ
1373 return fs ? fs->priority : 0;
1374}
1375
1376/**
1377 * mnt_fs_set_priority:
1378 * @fs: /proc/swaps entry
81b176c4 1379 * @prio: priority
ce4dd666 1380 *
a81b1946
KZ
1381 * Since: 2.28
1382 *
ce4dd666
KZ
1383 * Returns: 0 or -1 in case of error
1384 */
1385int mnt_fs_set_priority(struct libmnt_fs *fs, int prio)
1386{
ce4dd666
KZ
1387 if (!fs)
1388 return -EINVAL;
1389 fs->priority = prio;
1390 return 0;
1391}
1392
dd369652
KZ
1393/**
1394 * mnt_fs_get_bindsrc:
a362ae60 1395 * @fs: /run/mount/utab entry
dd369652
KZ
1396 *
1397 * Returns: full path that was used for mount(2) on MS_BIND
1398 */
68164f6c 1399const char *mnt_fs_get_bindsrc(struct libmnt_fs *fs)
dd369652 1400{
dd369652
KZ
1401 return fs ? fs->bindsrc : NULL;
1402}
1403
1404/**
1405 * mnt_fs_set_bindsrc:
1406 * @fs: filesystem
1407 * @src: path
1408 *
1409 * Returns: 0 on success or negative number in case of error.
1410 */
68164f6c 1411int mnt_fs_set_bindsrc(struct libmnt_fs *fs, const char *src)
dd369652 1412{
deb1c903 1413 return strdup_to_struct_member(fs, bindsrc, src);
dd369652
KZ
1414}
1415
efe73c3e
KZ
1416/**
1417 * mnt_fs_get_id:
1418 * @fs: /proc/self/mountinfo entry
1419 *
57ab4dc3
KZ
1420 * This ID is "old" and used in mountinfo only. Since Linux v6.8 there is also unique
1421 * 64-bit ID, see mnt_fs_get_uniq_id().
1422 *
1423 * Returns: mount ID or negative number in case of error.
efe73c3e 1424 */
68164f6c 1425int mnt_fs_get_id(struct libmnt_fs *fs)
efe73c3e 1426{
0affb7ae
KZ
1427 if (!fs)
1428 return 0;
ec7c579a
KZ
1429#ifdef HAVE_STATMOUNT_API
1430 mnt_fs_try_statmount(fs, id, STATMOUNT_MNT_BASIC);
1431#endif
0affb7ae 1432 return fs->id;
efe73c3e
KZ
1433}
1434
57ab4dc3
KZ
1435/**
1436 * mnt_fs_get_uniq_id:
1437 * @fs: filesystem instance
1438 *
1439 * This ID is provided by statmount() or statx(STATX_MNT_ID_UNIQUE) since Linux
1440 * kernel since v6.8.
1441 *
1442 * Returns: unique mount ID
1443 *
1444 * Since: 2.41
1445 */
1446uint64_t mnt_fs_get_uniq_id(struct libmnt_fs *fs)
1447{
0affb7ae
KZ
1448 if (!fs)
1449 return 0;
ec7c579a
KZ
1450#ifdef HAVE_STATMOUNT_API
1451 mnt_fs_try_statmount(fs, uniq_id, STATMOUNT_MNT_BASIC);
1452#endif
0affb7ae 1453 return fs->uniq_id;
57ab4dc3
KZ
1454}
1455
1456/**
1457 * mnt_fs_set_uniq_id:
1458 * @fs: filesystem instance
1459 * @id: mount node ID
1460 *
1461 * This ID is provided by statmount() or statx(STATX_MNT_ID_UNIQUE) since Linux
1462 * kernel since v6.8.
1463 *
1464 * Returns: 0 or negative number in case of error.
1465 *
1466 * Since: 2.41
1467 */
1468int mnt_fs_set_uniq_id(struct libmnt_fs *fs, uint64_t id)
1469{
1470 if (!fs)
1471 return -EINVAL;
1472 fs->uniq_id = id;
1473 return 0;
1474}
1475
efe73c3e
KZ
1476/**
1477 * mnt_fs_get_parent_id:
1478 * @fs: /proc/self/mountinfo entry
1479 *
56be757f 1480 * Returns: parent mount ID or negative number in case of error.
efe73c3e 1481 */
68164f6c 1482int mnt_fs_get_parent_id(struct libmnt_fs *fs)
efe73c3e 1483{
0affb7ae
KZ
1484 if (!fs)
1485 return 0;
ec7c579a
KZ
1486#ifdef HAVE_STATMOUNT_API
1487 mnt_fs_try_statmount(fs, parent, STATMOUNT_MNT_BASIC);
1488#endif
0affb7ae 1489 return fs->parent;
efe73c3e
KZ
1490}
1491
57ab4dc3
KZ
1492/**
1493 * mnt_fs_get_parent_uniq_id:
1494 * @fs: filesystem instance
1495 *
1496 * This ID is provided by statmount() since Linux kernel since v6.8.
1497 *
1498 * Returns: parent mount ID or 0 if not avalable
1499 */
1500uint64_t mnt_fs_get_parent_uniq_id(struct libmnt_fs *fs)
1501{
0affb7ae
KZ
1502 if (!fs)
1503 return 0;
ec7c579a
KZ
1504#ifdef HAVE_STATMOUNT_API
1505 mnt_fs_try_statmount(fs, uniq_parent, STATMOUNT_MNT_BASIC);
1506#endif
0affb7ae 1507 return fs->uniq_parent;
57ab4dc3
KZ
1508}
1509
0affb7ae
KZ
1510/**
1511 * mnt_fs_get_ns:
1512 * @fs: filesystem instance
1513 *
1514 * This ID is provided by statmount() since Linux kernel since v6.10
1515 *
1516 * Returns: parent namespace ID or 0 if not avalable.
1517 *
1518 * Since: 2.41
1519 */
1520uint64_t mnt_fs_get_ns(struct libmnt_fs *fs)
1521{
1522 if (!fs)
1523 return 0;
ec7c579a
KZ
1524#ifdef HAVE_STATMOUNT_API
1525 mnt_fs_try_statmount(fs, ns_id, STATMOUNT_MNT_NS_ID);
1526#endif
0affb7ae
KZ
1527 return fs->ns_id;
1528}
1529
1530/**
1531 * mnt_fs_set_ns:
1532 * @fs: filesystem instance
1533 * @id: namespace ID (or 0)
1534 *
1535 * Returns: 0 or <0 in case of error.
1536 *
1537 * Sinse: 2.41
1538 */
1539int mnt_fs_set_ns(struct libmnt_fs *fs, uint64_t id)
1540{
1541 if (!fs)
1542 return -EINVAL;
1543 fs->ns_id = id;
1544 return 0;
1545}
1546
1547
efe73c3e
KZ
1548/**
1549 * mnt_fs_get_devno:
0b3953a3 1550 * @fs: /proc/self/mountinfo entry
efe73c3e
KZ
1551 *
1552 * Returns: value of st_dev for files on filesystem or 0 in case of error.
1553 */
68164f6c 1554dev_t mnt_fs_get_devno(struct libmnt_fs *fs)
efe73c3e 1555{
0affb7ae
KZ
1556 if (!fs)
1557 return 0;
ec7c579a
KZ
1558#ifdef HAVE_STATMOUNT_API
1559 mnt_fs_try_statmount(fs, devno, STATMOUNT_SB_BASIC);
1560#endif
0affb7ae 1561 return fs->devno;
efe73c3e
KZ
1562}
1563
f7f29b56
KZ
1564/**
1565 * mnt_fs_get_tid:
a3bb7e65 1566 * @fs: /proc/tid/mountinfo entry
f7f29b56 1567 *
d58b3157 1568 * Returns: TID (task ID) for filesystems read from the mountinfo file
f7f29b56
KZ
1569 */
1570pid_t mnt_fs_get_tid(struct libmnt_fs *fs)
1571{
f7f29b56
KZ
1572 return fs ? fs->tid : 0;
1573}
1574
d115ee9b
KZ
1575/**
1576 * mnt_fs_get_option:
1577 * @fs: fstab/mtab/mountinfo entry pointer
1578 * @name: option name
d58b3157 1579 * @value: returns pointer to the beginning of the value (e.g. name=VALUE) or NULL
d115ee9b
KZ
1580 * @valsz: returns size of options value or 0
1581 *
d58b3157 1582 * Returns: 0 on success, 1 when @name not found or negative number in case of error.
d115ee9b 1583 */
68164f6c 1584int mnt_fs_get_option(struct libmnt_fs *fs, const char *name,
d115ee9b
KZ
1585 char **value, size_t *valsz)
1586{
76a06ca4
KZ
1587 char rc = 1;
1588
ba2bdf41
KZ
1589 if (!fs)
1590 return -EINVAL;
faa3d718
KZ
1591
1592 if (fs->optlist)
1593 sync_opts_from_optlist(fs, fs->optlist);
ec7c579a
KZ
1594#ifdef HAVE_STATMOUNT_API
1595 else
1596 mnt_fs_try_statmount(fs, vfs_optstr, STATMOUNT_SB_BASIC | STATMOUNT_MNT_BASIC);
1597#endif
76a06ca4
KZ
1598 if (fs->fs_optstr)
1599 rc = mnt_optstr_get_option(fs->fs_optstr, name, value, valsz);
1600 if (rc == 1 && fs->vfs_optstr)
1601 rc = mnt_optstr_get_option(fs->vfs_optstr, name, value, valsz);
1602 if (rc == 1 && fs->user_optstr)
1603 rc = mnt_optstr_get_option(fs->user_optstr, name, value, valsz);
1604 return rc;
1605}
1606
1607/**
1608 * mnt_fs_get_attribute:
1609 * @fs: fstab/mtab/mountinfo entry pointer
1610 * @name: option name
d58b3157 1611 * @value: returns pointer to the beginning of the value (e.g. name=VALUE) or NULL
76a06ca4
KZ
1612 * @valsz: returns size of options value or 0
1613 *
d58b3157 1614 * Returns: 0 on success, 1 when @name not found or negative number in case of error.
76a06ca4 1615 */
68164f6c 1616int mnt_fs_get_attribute(struct libmnt_fs *fs, const char *name,
76a06ca4
KZ
1617 char **value, size_t *valsz)
1618{
1619 char rc = 1;
1620
4569bbea
KZ
1621 if (!fs)
1622 return -EINVAL;
76a06ca4
KZ
1623 if (fs->attrs)
1624 rc = mnt_optstr_get_option(fs->attrs, name, value, valsz);
1625 return rc;
d115ee9b
KZ
1626}
1627
cb90e24e
OO
1628/**
1629 * mnt_fs_get_comment:
1630 * @fs: fstab/mtab/mountinfo entry pointer
1631 *
c630dbc3 1632 * Returns: comment string
cb90e24e
OO
1633 */
1634const char *mnt_fs_get_comment(struct libmnt_fs *fs)
1635{
cb90e24e
OO
1636 if (!fs)
1637 return NULL;
1638 return fs->comment;
1639}
1640
1641/**
1642 * mnt_fs_set_comment:
1643 * @fs: fstab entry pointer
1644 * @comm: comment string
1645 *
d22f2822 1646 * Note that the comment has to be terminated by '\n' (new line), otherwise
d58b3157 1647 * the whole filesystem entry will be written as a comment to the tabfile (e.g.
d22f2822
OO
1648 * fstab).
1649 *
cb90e24e
OO
1650 * Returns: 0 on success or <0 in case of error.
1651 */
1652int mnt_fs_set_comment(struct libmnt_fs *fs, const char *comm)
1653{
deb1c903 1654 return strdup_to_struct_member(fs, comment, comm);
cb90e24e
OO
1655}
1656
1657/**
1658 * mnt_fs_append_comment:
1659 * @fs: fstab entry pointer
7b1333fa 1660 * @comm: comment string
cb90e24e 1661 *
d22f2822
OO
1662 * See also mnt_fs_set_comment().
1663 *
cb90e24e
OO
1664 * Returns: 0 on success or <0 in case of error.
1665 */
1666int mnt_fs_append_comment(struct libmnt_fs *fs, const char *comm)
1667{
cb90e24e
OO
1668 if (!fs)
1669 return -EINVAL;
1670
d42e5e4b 1671 return ul_strappend(&fs->comment, comm);
cb90e24e
OO
1672}
1673
3fca8422
KZ
1674/**
1675 * mnt_fs_match_target:
1676 * @fs: filesystem
1677 * @target: mountpoint path
1678 * @cache: tags/paths cache or NULL
1679 *
1680 * Possible are three attempts:
1681 * 1) compare @target with @fs->target
8642cd7b 1682 *
3fca8422 1683 * 2) realpath(@target) with @fs->target
8642cd7b 1684 *
fa705b54 1685 * 3) realpath(@target) with realpath(@fs->target) if @fs is not from
8642cd7b
KZ
1686 * /proc/self/mountinfo.
1687 *
1688 * However, if mnt_cache_set_targets(cache, mtab) was called, and the
1689 * path @target or @fs->target is found in the @mtab, the canonicalization is
1690 * is not performed (see mnt_resolve_target()).
3fca8422
KZ
1691 *
1692 * The 2nd and 3rd attempts are not performed when @cache is NULL.
1693 *
d58b3157 1694 * Returns: 1 if @fs target is equal to @target, else 0.
3fca8422 1695 */
16b8db49
KZ
1696int mnt_fs_match_target(struct libmnt_fs *fs, const char *target,
1697 struct libmnt_cache *cache)
3fca8422
KZ
1698{
1699 int rc = 0;
1700
0affb7ae
KZ
1701 if (!fs || !target)
1702 return 0;
ec7c579a 1703#ifdef HAVE_STATMOUNT_API
7a666fb1 1704 mnt_fs_try_statmount(fs, target, STATMOUNT_MNT_POINT);
ec7c579a 1705#endif
0affb7ae 1706 if (!fs->target)
3fca8422
KZ
1707 return 0;
1708
1709 /* 1) native paths */
6699e742 1710 rc = mnt_fs_streq_target(fs, target);
3fca8422
KZ
1711
1712 if (!rc && cache) {
1713 /* 2) - canonicalized and non-canonicalized */
8642cd7b 1714 char *cn = mnt_resolve_target(target, cache);
ab131f00 1715 rc = (cn && mnt_fs_streq_target(fs, cn));
3fca8422
KZ
1716
1717 /* 3) - canonicalized and canonicalized */
45e8cdba 1718 if (!rc && cn && !mnt_fs_is_kernel(fs) && !mnt_fs_is_swaparea(fs)) {
0382ba32 1719 char *tcn = mnt_resolve_target(fs->target, cache);
3fca8422
KZ
1720 rc = (tcn && strcmp(cn, tcn) == 0);
1721 }
1722 }
1723
1724 return rc;
1725}
1726
1727/**
1728 * mnt_fs_match_source:
1729 * @fs: filesystem
f12aac6e 1730 * @source: tag or path (device or so) or NULL
3fca8422
KZ
1731 * @cache: tags/paths cache or NULL
1732 *
d58b3157 1733 * Four attempts are possible:
3fca8422
KZ
1734 * 1) compare @source with @fs->source
1735 * 2) compare realpath(@source) with @fs->source
1736 * 3) compare realpath(@source) with realpath(@fs->source)
1737 * 4) compare realpath(@source) with evaluated tag from @fs->source
1738 *
1739 * The 2nd, 3rd and 4th attempts are not performed when @cache is NULL. The
1740 * 2nd and 3rd attempts are not performed if @fs->source is tag.
1741 *
d58b3157 1742 * Returns: 1 if @fs source is equal to @source, else 0.
3fca8422 1743 */
16b8db49
KZ
1744int mnt_fs_match_source(struct libmnt_fs *fs, const char *source,
1745 struct libmnt_cache *cache)
3fca8422 1746{
3fca8422
KZ
1747 char *cn;
1748 const char *src, *t, *v;
1749
f12aac6e
KZ
1750 if (!fs)
1751 return 0;
1752
ab8c6e05
KZ
1753 /* 1) native paths... */
1754 if (mnt_fs_streq_srcpath(fs, source) == 1)
f12aac6e
KZ
1755 return 1;
1756
ab8c6e05 1757 if (!source || !fs->source)
3fca8422
KZ
1758 return 0;
1759
ab8c6e05
KZ
1760 /* ... and tags */
1761 if (fs->tagname && strcmp(source, fs->source) == 0)
3ef87248 1762 return 1;
3fca8422 1763
3ef87248
KZ
1764 if (!cache)
1765 return 0;
3fca8422
KZ
1766 if (fs->flags & (MNT_FS_NET | MNT_FS_PSEUDO))
1767 return 0;
1768
1769 cn = mnt_resolve_spec(source, cache);
1770 if (!cn)
1771 return 0;
1772
1773 /* 2) canonicalized and native */
1774 src = mnt_fs_get_srcpath(fs);
ab8c6e05 1775 if (src && mnt_fs_streq_srcpath(fs, cn))
3ef87248 1776 return 1;
3fca8422
KZ
1777
1778 /* 3) canonicalized and canonicalized */
3ef87248 1779 if (src) {
3fca8422 1780 src = mnt_resolve_path(src, cache);
3ef87248
KZ
1781 if (src && !strcmp(cn, src))
1782 return 1;
3fca8422 1783 }
3ef87248 1784 if (src || mnt_fs_get_tag(fs, &t, &v))
d58b3157 1785 /* src path does not match and the tag is not defined */
3fca8422
KZ
1786 return 0;
1787
1788 /* read @source's tags to the cache */
ba7232a1 1789 if (mnt_cache_read_tags(cache, cn) < 0) {
3fca8422
KZ
1790 if (errno == EACCES) {
1791 /* we don't have permissions to read TAGs from
d58b3157 1792 * @source, but can translate the @fs tag to devname.
3fca8422
KZ
1793 *
1794 * (because libblkid uses udev symlinks and this is
1795 * accessible for non-root uses)
1796 */
1797 char *x = mnt_resolve_tag(t, v, cache);
1798 if (x && !strcmp(x, cn))
1799 return 1;
1800 }
1801 return 0;
1802 }
1803
d58b3157 1804 /* 4) has the @source a tag that matches with the tag from @fs ? */
3ef87248
KZ
1805 if (mnt_cache_device_has_tag(cache, cn, t, v))
1806 return 1;
3fca8422 1807
3ef87248 1808 return 0;
3fca8422
KZ
1809}
1810
1811/**
1812 * mnt_fs_match_fstype:
1813 * @fs: filesystem
1814 * @types: filesystem name or comma delimited list of filesystems
1815 *
1816 * For more details see mnt_match_fstype().
1817 *
d58b3157 1818 * Returns: 1 if @fs type is matching to @types, else 0. The function returns
3fca8422
KZ
1819 * 0 when types is NULL.
1820 */
68164f6c 1821int mnt_fs_match_fstype(struct libmnt_fs *fs, const char *types)
3fca8422 1822{
0affb7ae 1823 return mnt_match_fstype(mnt_fs_get_fstype(fs), types);
3fca8422
KZ
1824}
1825
1826/**
1827 * mnt_fs_match_options:
1828 * @fs: filesystem
1829 * @options: comma delimited list of options (and nooptions)
1830 *
1831 * For more details see mnt_match_options().
1832 *
d58b3157 1833 * Returns: 1 if @fs type is matching to @options, else 0. The function returns
3fca8422
KZ
1834 * 0 when types is NULL.
1835 */
68164f6c 1836int mnt_fs_match_options(struct libmnt_fs *fs, const char *options)
3fca8422 1837{
d84508cf 1838 return mnt_match_options(mnt_fs_get_options(fs), options);
3fca8422
KZ
1839}
1840
d115ee9b
KZ
1841/**
1842 * mnt_fs_print_debug
1843 * @fs: fstab/mtab/mountinfo entry
486d3972 1844 * @file: file stream
d115ee9b 1845 *
56be757f 1846 * Returns: 0 on success or negative number in case of error.
d115ee9b 1847 */
68164f6c 1848int mnt_fs_print_debug(struct libmnt_fs *fs, FILE *file)
d115ee9b 1849{
0affb7ae
KZ
1850 unsigned long pro = 0;
1851 int stmnt_disabled = 1;
1852
4569bbea 1853 if (!fs || !file)
56be757f 1854 return -EINVAL;
faa3d718
KZ
1855
1856 if (fs->optlist)
1857 sync_opts_from_optlist(fs, fs->optlist);
1858
0affb7ae
KZ
1859 if (fs->stmnt)
1860 stmnt_disabled = mnt_statmnt_disable_fetching(fs->stmnt, 1);
1861
8d31f146 1862 fprintf(file, "------ fs:\n");
0affb7ae
KZ
1863 if (mnt_fs_get_source(fs))
1864 fprintf(file, "source: %s\n", mnt_fs_get_source(fs));
1865 if (mnt_fs_get_target(fs))
1866 fprintf(file, "target: %s\n", mnt_fs_get_target(fs));
1867 if (mnt_fs_get_fstype(fs))
1868 fprintf(file, "fstype: %s\n", mnt_fs_get_fstype(fs));
76a06ca4 1869
f2b3a3a3
KZ
1870 if (mnt_fs_get_options(fs))
1871 fprintf(file, "optstr: %s\n", mnt_fs_get_options(fs));
76a06ca4
KZ
1872 if (mnt_fs_get_vfs_options(fs))
1873 fprintf(file, "VFS-optstr: %s\n", mnt_fs_get_vfs_options(fs));
1874 if (mnt_fs_get_fs_options(fs))
1875 fprintf(file, "FS-opstr: %s\n", mnt_fs_get_fs_options(fs));
68164f6c
KZ
1876 if (mnt_fs_get_user_options(fs))
1877 fprintf(file, "user-optstr: %s\n", mnt_fs_get_user_options(fs));
e47a1931
OO
1878 if (mnt_fs_get_optional_fields(fs))
1879 fprintf(file, "optional-fields: '%s'\n", mnt_fs_get_optional_fields(fs));
76a06ca4
KZ
1880 if (mnt_fs_get_attributes(fs))
1881 fprintf(file, "attributes: %s\n", mnt_fs_get_attributes(fs));
dd369652 1882
0affb7ae
KZ
1883 if (mnt_fs_get_propagation(fs, &pro) == 0 && pro)
1884 fprintf(file, "propagation: %s %s %s\n",
1885 pro & MS_SHARED ? "shared" : "private",
1886 pro & MS_SLAVE ? "slave" : "",
1887 pro & MS_UNBINDABLE ? "unbindable" : "");
1888
dd369652 1889 if (mnt_fs_get_root(fs))
77417bc0 1890 fprintf(file, "root: %s\n", mnt_fs_get_root(fs));
ce4dd666
KZ
1891
1892 if (mnt_fs_get_swaptype(fs))
1893 fprintf(file, "swaptype: %s\n", mnt_fs_get_swaptype(fs));
1894 if (mnt_fs_get_size(fs))
1895 fprintf(file, "size: %jd\n", mnt_fs_get_size(fs));
1896 if (mnt_fs_get_usedsize(fs))
1897 fprintf(file, "usedsize: %jd\n", mnt_fs_get_usedsize(fs));
1898 if (mnt_fs_get_priority(fs))
1899 fprintf(file, "priority: %d\n", mnt_fs_get_priority(fs));
1900
dd369652
KZ
1901 if (mnt_fs_get_bindsrc(fs))
1902 fprintf(file, "bindsrc: %s\n", mnt_fs_get_bindsrc(fs));
9dd75aa6 1903 if (mnt_fs_get_freq(fs))
77417bc0 1904 fprintf(file, "freq: %d\n", mnt_fs_get_freq(fs));
9dd75aa6 1905 if (mnt_fs_get_passno(fs))
77417bc0 1906 fprintf(file, "pass: %d\n", mnt_fs_get_passno(fs));
9dd75aa6 1907 if (mnt_fs_get_id(fs))
77417bc0 1908 fprintf(file, "id: %d\n", mnt_fs_get_id(fs));
9dd75aa6 1909 if (mnt_fs_get_parent_id(fs))
77417bc0 1910 fprintf(file, "parent: %d\n", mnt_fs_get_parent_id(fs));
57ab4dc3
KZ
1911 if (mnt_fs_get_uniq_id(fs))
1912 fprintf(file, "uniq-id: %" PRIu64 "\n", mnt_fs_get_uniq_id(fs));
1913 if (mnt_fs_get_parent_uniq_id(fs))
1914 fprintf(file, "uniq-parent: %" PRIu64 "\n", mnt_fs_get_parent_uniq_id(fs));
0affb7ae 1915
9dd75aa6 1916 if (mnt_fs_get_devno(fs))
77417bc0 1917 fprintf(file, "devno: %d:%d\n", major(mnt_fs_get_devno(fs)),
f7f29b56
KZ
1918 minor(mnt_fs_get_devno(fs)));
1919 if (mnt_fs_get_tid(fs))
1920 fprintf(file, "tid: %d\n", mnt_fs_get_tid(fs));
cb90e24e
OO
1921 if (mnt_fs_get_comment(fs))
1922 fprintf(file, "comment: '%s'\n", mnt_fs_get_comment(fs));
f7f29b56 1923
0affb7ae
KZ
1924 if (fs->stmnt)
1925 mnt_statmnt_disable_fetching(fs->stmnt, stmnt_disabled);
d115ee9b
KZ
1926 return 0;
1927}
8b95253f
KZ
1928
1929/**
1930 * mnt_free_mntent:
1931 * @mnt: mount entry
1932 *
d58b3157 1933 * Deallocates the "mntent.h" mount entry.
8b95253f
KZ
1934 */
1935void mnt_free_mntent(struct mntent *mnt)
1936{
1937 if (mnt) {
1938 free(mnt->mnt_fsname);
1939 free(mnt->mnt_dir);
1940 free(mnt->mnt_type);
1941 free(mnt->mnt_opts);
1942 free(mnt);
1943 }
1944}
1945
1946/**
1947 * mnt_fs_to_mntent:
1948 * @fs: filesystem
1949 * @mnt: mount description (as described in mntent.h)
1950 *
d58b3157 1951 * Copies the information from @fs to struct mntent @mnt. If @mnt is already set,
8b95253f
KZ
1952 * then the struct mntent items are reallocated and updated. See also
1953 * mnt_free_mntent().
1954 *
d58b3157 1955 * Returns: 0 on success and a negative number in case of error.
8b95253f 1956 */
68164f6c 1957int mnt_fs_to_mntent(struct libmnt_fs *fs, struct mntent **mnt)
8b95253f
KZ
1958{
1959 int rc;
1960 struct mntent *m;
1961
1962 if (!fs || !mnt)
1963 return -EINVAL;
1964
1965 m = *mnt;
1966 if (!m) {
1967 m = calloc(1, sizeof(*m));
1968 if (!m)
1969 return -ENOMEM;
1970 }
1971
309139c7 1972 if ((rc = update_str(&m->mnt_fsname, mnt_fs_get_source(fs))))
8b95253f 1973 goto err;
309139c7 1974 if ((rc = update_str(&m->mnt_dir, mnt_fs_get_target(fs))))
8b95253f 1975 goto err;
309139c7 1976 if ((rc = update_str(&m->mnt_type, mnt_fs_get_fstype(fs))))
8b95253f 1977 goto err;
76a06ca4
KZ
1978
1979 errno = 0;
1980 m->mnt_opts = mnt_fs_strdup_options(fs);
1981 if (!m->mnt_opts && errno) {
1982 rc = -errno;
8b95253f 1983 goto err;
76a06ca4
KZ
1984 }
1985
8b95253f
KZ
1986 m->mnt_freq = mnt_fs_get_freq(fs);
1987 m->mnt_passno = mnt_fs_get_passno(fs);
1988
de511a88
KZ
1989 if (!m->mnt_fsname) {
1990 m->mnt_fsname = strdup("none");
1991 if (!m->mnt_fsname)
1992 goto err;
1993 }
8b95253f
KZ
1994 *mnt = m;
1995
1996 return 0;
1997err:
1998 if (m != *mnt)
1999 mnt_free_mntent(m);
2000 return rc;
2001}