]> git.ipfire.org Git - thirdparty/util-linux.git/blame - libmount/src/fs.c
libmount: Keep the mnt_tab info for the existent dest in mnt_copy_fs()
[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
63de90d4 16 * @short_description: represents one entry from fstab, mtab, 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));
d115ee9b
KZ
37 if (!fs)
38 return NULL;
39
26d0c0ae 40 fs->refcount = 1;
d115ee9b 41 INIT_LIST_HEAD(&fs->ents);
83a78332 42 /*DBG(FS, ul_debugobj(fs, "alloc"));*/
d115ee9b
KZ
43 return fs;
44}
45
46/**
47 * mnt_free_fs:
48 * @fs: fs pointer
49 *
26d0c0ae 50 * Deallocates the fs. This function does not care about reference count. Don't
a7349ee3 51 * use this function directly -- it's better to use mnt_unref_fs().
26d0c0ae
KZ
52 *
53 * The reference counting is supported since util-linux v2.24.
d115ee9b 54 */
68164f6c 55void mnt_free_fs(struct libmnt_fs *fs)
d115ee9b
KZ
56{
57 if (!fs)
58 return;
309139c7 59
a504eaed 60 DBG(FS, ul_debugobj(fs, "free [refcount=%d]", fs->refcount));
d115ee9b 61
a504eaed 62 mnt_reset_fs(fs);
d115ee9b
KZ
63 free(fs);
64}
65
309139c7
KZ
66/**
67 * mnt_reset_fs:
68 * @fs: fs pointer
69 *
70 * Resets (zeroize) @fs.
71 */
72void mnt_reset_fs(struct libmnt_fs *fs)
73{
26d0c0ae
KZ
74 int ref;
75
76 if (!fs)
77 return;
78
79 ref = fs->refcount;
a504eaed
KZ
80
81 list_del(&fs->ents);
82 free(fs->source);
83 free(fs->bindsrc);
84 free(fs->tagname);
85 free(fs->tagval);
86 free(fs->root);
87 free(fs->swaptype);
88 free(fs->target);
89 free(fs->fstype);
90 free(fs->optstr);
91 free(fs->vfs_optstr);
92 free(fs->fs_optstr);
93 free(fs->user_optstr);
94 free(fs->attrs);
95 free(fs->opt_fields);
96 free(fs->comment);
97
26d0c0ae 98 memset(fs, 0, sizeof(*fs));
14104e93 99 INIT_LIST_HEAD(&fs->ents);
26d0c0ae
KZ
100 fs->refcount = ref;
101}
102
103/**
104 * mnt_ref_fs:
105 * @fs: fs pointer
106 *
107 * Increments reference counter.
108 */
109void mnt_ref_fs(struct libmnt_fs *fs)
110{
111 if (fs) {
112 fs->refcount++;
83a78332 113 /*DBG(FS, ul_debugobj(fs, "ref=%d", fs->refcount));*/
26d0c0ae
KZ
114 }
115}
116
117/**
118 * mnt_unref_fs:
119 * @fs: fs pointer
120 *
47cca899 121 * De-increments reference counter, on zero the @fs is automatically
26d0c0ae
KZ
122 * deallocated by mnt_free_fs().
123 */
124void mnt_unref_fs(struct libmnt_fs *fs)
125{
126 if (fs) {
127 fs->refcount--;
83a78332 128 /*DBG(FS, ul_debugobj(fs, "unref=%d", fs->refcount));*/
26d0c0ae
KZ
129 if (fs->refcount <= 0)
130 mnt_free_fs(fs);
131 }
309139c7
KZ
132}
133
134static inline int update_str(char **dest, const char *src)
9ecdf48f 135{
8b95253f
KZ
136 size_t sz;
137 char *x;
138
139 assert(dest);
9ecdf48f 140
8b95253f
KZ
141 if (!src) {
142 free(*dest);
143 *dest = NULL;
9ecdf48f 144 return 0; /* source (old) is empty */
8b95253f 145 }
9ecdf48f 146
8b95253f
KZ
147 sz = strlen(src) + 1;
148 x = realloc(*dest, sz);
149 if (!x)
56be757f 150 return -ENOMEM;
8b95253f
KZ
151 *dest = x;
152 memcpy(*dest, src, sz);
9ecdf48f
KZ
153 return 0;
154}
155
8b95253f
KZ
156static inline int cpy_str_at_offset(void *new, const void *old, size_t offset)
157{
fef00631
BE
158 char **o = (char **) ((char *) old + offset);
159 char **n = (char **) ((char *) new + offset);
8b95253f 160
309139c7 161 if (*n)
d58b3157 162 return 0; /* already set, don't overwrite */
309139c7
KZ
163
164 return update_str(n, *o);
8b95253f
KZ
165}
166
9ecdf48f
KZ
167/**
168 * mnt_copy_fs:
309139c7
KZ
169 * @dest: destination FS
170 * @src: source FS
171 *
172 * If @dest is NULL, then a new FS is allocated, if any @dest field is already
d58b3157 173 * set, then the field is NOT overwritten.
9ecdf48f
KZ
174 *
175 * This function does not copy userdata (se mnt_fs_set_userdata()). A new copy is
176 * not linked with any existing mnt_tab.
177 *
309139c7 178 * Returns: @dest or NULL in case of error
9ecdf48f 179 */
309139c7
KZ
180struct libmnt_fs *mnt_copy_fs(struct libmnt_fs *dest,
181 const struct libmnt_fs *src)
9ecdf48f 182{
309139c7 183 const struct libmnt_fs *org = dest;
9ecdf48f 184
52a285bf
KZ
185 if (!src)
186 return NULL;
309139c7
KZ
187 if (!dest) {
188 dest = mnt_new_fs();
189 if (!dest)
190 return NULL;
042057d8
KH
191
192 dest->tab = NULL;
309139c7 193 }
9ecdf48f 194
309139c7
KZ
195 dest->id = src->id;
196 dest->parent = src->parent;
197 dest->devno = src->devno;
f7f29b56 198 dest->tid = src->tid;
309139c7
KZ
199
200 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, source)))
9ecdf48f 201 goto err;
309139c7 202 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, tagname)))
9ecdf48f 203 goto err;
309139c7 204 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, tagval)))
9ecdf48f 205 goto err;
309139c7 206 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, root)))
9ecdf48f 207 goto err;
ce4dd666
KZ
208 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, swaptype)))
209 goto err;
309139c7 210 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, target)))
9ecdf48f 211 goto err;
309139c7 212 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, fstype)))
9ecdf48f 213 goto err;
f2b3a3a3
KZ
214 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, optstr)))
215 goto err;
309139c7 216 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, vfs_optstr)))
9ecdf48f 217 goto err;
309139c7 218 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, fs_optstr)))
9ecdf48f 219 goto err;
309139c7 220 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, user_optstr)))
76a06ca4 221 goto err;
309139c7 222 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, attrs)))
76a06ca4 223 goto err;
c4c66355
KZ
224 if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, bindsrc)))
225 goto err;
76a06ca4 226
309139c7
KZ
227 dest->freq = src->freq;
228 dest->passno = src->passno;
229 dest->flags = src->flags;
ce4dd666
KZ
230 dest->size = src->size;
231 dest->usedsize = src->usedsize;
232 dest->priority = src->priority;
9ecdf48f 233
309139c7 234 return dest;
9ecdf48f 235err:
309139c7
KZ
236 if (!org)
237 mnt_free_fs(dest);
9ecdf48f
KZ
238 return NULL;
239}
240
0f32f1e2 241/*
f84fa6f7
KZ
242 * This function copies all @fs description except information that does not
243 * belong to /etc/mtab (e.g. VFS and userspace mount options with MNT_NOMTAB
244 * mask).
245 *
246 * Returns: copy of @fs.
247 */
68164f6c 248struct libmnt_fs *mnt_copy_mtab_fs(const struct libmnt_fs *fs)
f84fa6f7 249{
68164f6c 250 struct libmnt_fs *n = mnt_new_fs();
f84fa6f7 251
4569bbea 252 assert(fs);
f84fa6f7
KZ
253 if (!n)
254 return NULL;
255
68164f6c 256 if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, source)))
f84fa6f7 257 goto err;
68164f6c 258 if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, target)))
f84fa6f7 259 goto err;
68164f6c 260 if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, fstype)))
f84fa6f7
KZ
261 goto err;
262
263 if (fs->vfs_optstr) {
264 char *p = NULL;
265 mnt_optstr_get_options(fs->vfs_optstr, &p,
266 mnt_get_builtin_optmap(MNT_LINUX_MAP),
267 MNT_NOMTAB);
268 n->vfs_optstr = p;
269 }
270
271 if (fs->user_optstr) {
272 char *p = NULL;
273 mnt_optstr_get_options(fs->user_optstr, &p,
274 mnt_get_builtin_optmap(MNT_USERSPACE_MAP),
275 MNT_NOMTAB);
276 n->user_optstr = p;
277 }
278
68164f6c 279 if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, fs_optstr)))
f84fa6f7
KZ
280 goto err;
281
f2b3a3a3
KZ
282 /* we cannot copy original optstr, the new optstr has to be without
283 * non-mtab options -- so, let's generate a new string */
284 n->optstr = mnt_fs_strdup_options(n);
285
f84fa6f7
KZ
286 n->freq = fs->freq;
287 n->passno = fs->passno;
288 n->flags = fs->flags;
289
290 return n;
291err:
292 mnt_free_fs(n);
293 return NULL;
294
295}
296
26b4f9e4
KZ
297/**
298 * mnt_fs_get_userdata:
68164f6c 299 * @fs: struct libmnt_file instance
26b4f9e4 300 *
192c6aad 301 * Returns: private data set by mnt_fs_set_userdata() or NULL.
26b4f9e4 302 */
68164f6c 303void *mnt_fs_get_userdata(struct libmnt_fs *fs)
26b4f9e4 304{
14104e93
KZ
305 if (!fs)
306 return NULL;
14104e93 307 return fs->userdata;
26b4f9e4
KZ
308}
309
310/**
311 * mnt_fs_set_userdata:
68164f6c 312 * @fs: struct libmnt_file instance
0f32f1e2 313 * @data: user data
26b4f9e4
KZ
314 *
315 * The "userdata" are library independent data.
316 *
56be757f 317 * Returns: 0 or negative number in case of error (if @fs is NULL).
26b4f9e4 318 */
68164f6c 319int mnt_fs_set_userdata(struct libmnt_fs *fs, void *data)
26b4f9e4
KZ
320{
321 if (!fs)
56be757f 322 return -EINVAL;
26b4f9e4
KZ
323 fs->userdata = data;
324 return 0;
325}
326
d115ee9b
KZ
327/**
328 * mnt_fs_get_srcpath:
68164f6c 329 * @fs: struct libmnt_file (fstab/mtab/mountinfo) fs
d115ee9b
KZ
330 *
331 * The mount "source path" is:
192c6aad
KZ
332 * - a directory for 'bind' mounts (in fstab or mtab only)
333 * - a device name for standard mounts
d115ee9b
KZ
334 *
335 * See also mnt_fs_get_tag() and mnt_fs_get_source().
336 *
192c6aad 337 * Returns: mount source path or NULL in case of error or when the path
d115ee9b 338 * is not defined.
d115ee9b 339 */
68164f6c 340const char *mnt_fs_get_srcpath(struct libmnt_fs *fs)
d115ee9b 341{
d115ee9b
KZ
342 if (!fs)
343 return NULL;
344
345 /* fstab-like fs */
346 if (fs->tagname)
347 return NULL; /* the source contains a "NAME=value" */
348 return fs->source;
349}
350
351/**
3d735589 352 * mnt_fs_get_source:
68164f6c 353 * @fs: struct libmnt_file (fstab/mtab/mountinfo) fs
d115ee9b 354 *
192c6aad 355 * Returns: mount source. Note that the source could be unparsed TAG
d115ee9b
KZ
356 * (LABEL/UUID). See also mnt_fs_get_srcpath() and mnt_fs_get_tag().
357 */
68164f6c 358const char *mnt_fs_get_source(struct libmnt_fs *fs)
d115ee9b
KZ
359{
360 return fs ? fs->source : NULL;
361}
362
5af0769d 363/*
d58b3157 364 * Used by the parser ONLY (@source has to be freed on error)
5af0769d 365 */
68164f6c 366int __mnt_fs_set_source_ptr(struct libmnt_fs *fs, char *source)
d115ee9b 367{
b2d0b74d
KZ
368 char *t = NULL, *v = NULL;
369
d115ee9b
KZ
370 assert(fs);
371
2c6b25f0
KZ
372 if (source && blkid_parse_tag_string(source, &t, &v) == 0 &&
373 !mnt_valid_tagname(t)) {
374 /* parsable but unknown tag -- ignore */
375 free(t);
376 free(v);
377 t = v = NULL;
d115ee9b
KZ
378 }
379
b2d0b74d
KZ
380 if (fs->source != source)
381 free(fs->source);
382
383 free(fs->tagname);
384 free(fs->tagval);
385
d115ee9b 386 fs->source = source;
b2d0b74d
KZ
387 fs->tagname = t;
388 fs->tagval = v;
d115ee9b
KZ
389 return 0;
390}
391
392/**
393 * mnt_fs_set_source:
394 * @fs: fstab/mtab/mountinfo entry
395 * @source: new source
396 *
192c6aad
KZ
397 * This function creates a private copy (strdup()) of @source.
398 *
56be757f 399 * Returns: 0 on success or negative number in case of error.
d115ee9b 400 */
68164f6c 401int mnt_fs_set_source(struct libmnt_fs *fs, const char *source)
d115ee9b 402{
f5017242 403 char *p = NULL;
b2d0b74d 404 int rc;
d115ee9b 405
f5017242 406 if (!fs)
56be757f 407 return -EINVAL;
d0ce7c07 408
f5017242
KZ
409 if (source) {
410 p = strdup(source);
411 if (!p)
412 return -ENOMEM;
413 }
d115ee9b 414
b2d0b74d
KZ
415 rc = __mnt_fs_set_source_ptr(fs, p);
416 if (rc)
417 free(p);
418 return rc;
d115ee9b
KZ
419}
420
6699e742
KZ
421/**
422 * mnt_fs_streq_srcpath:
423 * @fs: fs
424 * @path: source path
425 *
73afd3f8
RM
426 * Compares @fs source path with @path. The redundant slashes are ignored.
427 * This function compares strings and does not canonicalize the paths.
d4e89dea 428 * See also more heavy and generic mnt_fs_match_source().
6699e742
KZ
429 *
430 * Returns: 1 if @fs source path equal to @path, otherwise 0.
431 */
ab8c6e05
KZ
432int mnt_fs_streq_srcpath(struct libmnt_fs *fs, const char *path)
433{
6699e742 434 const char *p;
ab8c6e05 435
6699e742 436 if (!fs)
ab8c6e05
KZ
437 return 0;
438
6699e742 439 p = mnt_fs_get_srcpath(fs);
ab8c6e05 440
6699e742 441 if (!mnt_fs_is_pseudofs(fs))
d4e89dea 442 return streq_paths(p, path);
6699e742
KZ
443
444 if (!p && !path)
445 return 1;
446
447 return p && path && strcmp(p, path) == 0;
ab8c6e05
KZ
448}
449
9d5eb4c4
TH
450/**
451 * mnt_fs_get_table:
452 * @fs: table entry
453 * @tb: table that contains @fs
454 *
455 * Returns: 0 or negative number on error (if @fs or @tb is NULL).
2089538a
KZ
456 *
457 * Since: 2.34
9d5eb4c4
TH
458 */
459int mnt_fs_get_table(struct libmnt_fs *fs, struct libmnt_table **tb)
460{
461 if (!fs || !tb)
462 return -EINVAL;
463
464 *tb = fs->tab;
465 return 0;
466}
467
6699e742
KZ
468/**
469 * mnt_fs_streq_target:
470 * @fs: fs
471 * @path: mount point
472 *
73afd3f8
RM
473 * Compares @fs target path with @path. The redundant slashes are ignored.
474 * This function compares strings and does not canonicalize the paths.
d4e89dea 475 * See also more generic mnt_fs_match_target().
6699e742
KZ
476 *
477 * Returns: 1 if @fs target path equal to @path, otherwise 0.
478 */
479int mnt_fs_streq_target(struct libmnt_fs *fs, const char *path)
480{
d4e89dea 481 return fs && streq_paths(mnt_fs_get_target(fs), path);
6699e742 482}
ab8c6e05 483
d115ee9b
KZ
484/**
485 * mnt_fs_get_tag:
486 * @fs: fs
487 * @name: returns pointer to NAME string
488 * @value: returns pointer to VALUE string
489 *
490 * "TAG" is NAME=VALUE (e.g. LABEL=foo)
491 *
d58b3157
OO
492 * The TAG is the first column in the fstab file. The TAG or "srcpath" always has
493 * to be set for all entries.
d115ee9b
KZ
494 *
495 * See also mnt_fs_get_source().
496 *
192c6aad
KZ
497 * <informalexample>
498 * <programlisting>
d115ee9b 499 * char *src;
68164f6c 500 * struct libmnt_fs *fs = mnt_table_find_target(tb, "/home", MNT_ITER_FORWARD);
d115ee9b
KZ
501 *
502 * if (!fs)
503 * goto err;
504 *
505 * src = mnt_fs_get_srcpath(fs);
506 * if (!src) {
507 * char *tag, *val;
508 * if (mnt_fs_get_tag(fs, &tag, &val) == 0)
509 * printf("%s: %s\n", tag, val); // LABEL or UUID
510 * } else
511 * printf("device: %s\n", src); // device or bind path
192c6aad
KZ
512 * </programlisting>
513 * </informalexample>
d115ee9b 514 *
d58b3157 515 * Returns: 0 on success or negative number in case a TAG is not defined.
d115ee9b 516 */
68164f6c 517int mnt_fs_get_tag(struct libmnt_fs *fs, const char **name, const char **value)
d115ee9b
KZ
518{
519 if (fs == NULL || !fs->tagname)
56be757f 520 return -EINVAL;
d115ee9b
KZ
521 if (name)
522 *name = fs->tagname;
523 if (value)
524 *value = fs->tagval;
525 return 0;
526}
527
528/**
529 * mnt_fs_get_target:
530 * @fs: fstab/mtab/mountinfo entry pointer
531 *
192c6aad 532 * Returns: pointer to mountpoint path or NULL
d115ee9b 533 */
68164f6c 534const char *mnt_fs_get_target(struct libmnt_fs *fs)
d115ee9b 535{
d115ee9b
KZ
536 return fs ? fs->target : NULL;
537}
538
539/**
540 * mnt_fs_set_target:
541 * @fs: fstab/mtab/mountinfo entry
deb1c903 542 * @tgt: mountpoint
d115ee9b 543 *
deb1c903 544 * This function creates a private copy (strdup()) of @tgt.
192c6aad 545 *
56be757f 546 * Returns: 0 on success or negative number in case of error.
d115ee9b 547 */
deb1c903 548int mnt_fs_set_target(struct libmnt_fs *fs, const char *tgt)
d115ee9b 549{
deb1c903 550 return strdup_to_struct_member(fs, target, tgt);
d115ee9b
KZ
551}
552
c70d9d76 553static int mnt_fs_get_flags(struct libmnt_fs *fs)
309139c7
KZ
554{
555 return fs ? fs->flags : 0;
556}
557
4b9d67a2
KZ
558/**
559 * mnt_fs_get_propagation:
560 * @fs: mountinfo entry
d58b3157 561 * @flags: returns propagation MS_* flags as present in the mountinfo file
4b9d67a2 562 *
d58b3157
OO
563 * Note that this function sets @flags to zero if no propagation flags are found
564 * in the mountinfo file. The kernel default is MS_PRIVATE, this flag is not stored
4b9d67a2
KZ
565 * in the mountinfo file.
566 *
567 * Returns: 0 on success or negative number in case of error.
568 */
569int mnt_fs_get_propagation(struct libmnt_fs *fs, unsigned long *flags)
570{
571 if (!fs || !flags)
572 return -EINVAL;
573
574 *flags = 0;
575
576 if (!fs->opt_fields)
577 return 0;
578
579 /*
580 * The optional fields format is incompatible with mount options
581 * ... we have to parse the field here.
582 */
583 *flags |= strstr(fs->opt_fields, "shared:") ? MS_SHARED : MS_PRIVATE;
584
585 if (strstr(fs->opt_fields, "master:"))
586 *flags |= MS_SLAVE;
587 if (strstr(fs->opt_fields, "unbindable"))
588 *flags |= MS_UNBINDABLE;
589
590 return 0;
591}
592
309139c7
KZ
593/**
594 * mnt_fs_is_kernel:
595 * @fs: filesystem
596 *
597 * Returns: 1 if the filesystem description is read from kernel e.g. /proc/mounts.
598 */
599int mnt_fs_is_kernel(struct libmnt_fs *fs)
600{
c70d9d76
KZ
601 return mnt_fs_get_flags(fs) & MNT_FS_KERNEL;
602}
603
604/**
605 * mnt_fs_is_swaparea:
606 * @fs: filesystem
607 *
608 * Returns: 1 if the filesystem uses "swap" as a type
609 */
610int mnt_fs_is_swaparea(struct libmnt_fs *fs)
611{
612 return mnt_fs_get_flags(fs) & MNT_FS_SWAP;
613}
614
615/**
616 * mnt_fs_is_pseudofs:
617 * @fs: filesystem
618 *
619 * Returns: 1 if the filesystem is a pseudo fs type (proc, cgroups)
620 */
b928ab01 621int mnt_fs_is_pseudofs(struct libmnt_fs *fs)
c70d9d76
KZ
622{
623 return mnt_fs_get_flags(fs) & MNT_FS_PSEUDO;
624}
625
626/**
627 * mnt_fs_is_netfs:
628 * @fs: filesystem
629 *
630 * Returns: 1 if the filesystem is a network filesystem
631 */
632int mnt_fs_is_netfs(struct libmnt_fs *fs)
633{
634 return mnt_fs_get_flags(fs) & MNT_FS_NET;
309139c7
KZ
635}
636
d115ee9b
KZ
637/**
638 * mnt_fs_get_fstype:
639 * @fs: fstab/mtab/mountinfo entry pointer
640 *
192c6aad 641 * Returns: pointer to filesystem type.
d115ee9b 642 */
68164f6c 643const char *mnt_fs_get_fstype(struct libmnt_fs *fs)
d115ee9b 644{
d115ee9b
KZ
645 return fs ? fs->fstype : NULL;
646}
647
d58b3157 648/* Used by the struct libmnt_file parser only */
68164f6c 649int __mnt_fs_set_fstype_ptr(struct libmnt_fs *fs, char *fstype)
d115ee9b
KZ
650{
651 assert(fs);
652
b2d0b74d
KZ
653 if (fstype != fs->fstype)
654 free(fs->fstype);
655
d115ee9b
KZ
656 fs->fstype = fstype;
657 fs->flags &= ~MNT_FS_PSEUDO;
658 fs->flags &= ~MNT_FS_NET;
5dfc9843 659 fs->flags &= ~MNT_FS_SWAP;
d115ee9b
KZ
660
661 /* save info about pseudo filesystems */
8485e709
KZ
662 if (fs->fstype) {
663 if (mnt_fstype_is_pseudofs(fs->fstype))
664 fs->flags |= MNT_FS_PSEUDO;
665 else if (mnt_fstype_is_netfs(fs->fstype))
666 fs->flags |= MNT_FS_NET;
667 else if (!strcmp(fs->fstype, "swap"))
668 fs->flags |= MNT_FS_SWAP;
669 }
d115ee9b
KZ
670 return 0;
671}
672
673/**
674 * mnt_fs_set_fstype:
675 * @fs: fstab/mtab/mountinfo entry
676 * @fstype: filesystem type
677 *
192c6aad
KZ
678 * This function creates a private copy (strdup()) of @fstype.
679 *
56be757f 680 * Returns: 0 on success or negative number in case of error.
d115ee9b 681 */
68164f6c 682int mnt_fs_set_fstype(struct libmnt_fs *fs, const char *fstype)
d115ee9b 683{
8485e709 684 char *p = NULL;
d115ee9b 685
8485e709 686 if (!fs)
56be757f 687 return -EINVAL;
8485e709
KZ
688 if (fstype) {
689 p = strdup(fstype);
690 if (!p)
691 return -ENOMEM;
692 }
f5017242 693 return __mnt_fs_set_fstype_ptr(fs, p);
d115ee9b
KZ
694}
695
76a06ca4
KZ
696/*
697 * Merges @vfs and @fs options strings into a new string.
698 * This function cares about 'ro/rw' options. The 'ro' is
699 * always used if @vfs or @fs is read-only.
700 * For example:
701 *
702 * mnt_merge_optstr("rw,noexec", "ro,journal=update")
703 *
704 * returns: "ro,noexec,journal=update"
705 *
706 * mnt_merge_optstr("rw,noexec", "rw,journal=update")
707 *
708 * returns: "rw,noexec,journal=update"
709 */
710static char *merge_optstr(const char *vfs, const char *fs)
711{
712 char *res, *p;
713 size_t sz;
714 int ro = 0, rw = 0;
715
716 if (!vfs && !fs)
717 return NULL;
718 if (!vfs || !fs)
719 return strdup(fs ? fs : vfs);
720 if (!strcmp(vfs, fs))
721 return strdup(vfs); /* e.g. "aaa" and "aaa" */
722
d58b3157 723 /* leave space for the leading "r[ow],", "," and the trailing zero */
76a06ca4
KZ
724 sz = strlen(vfs) + strlen(fs) + 5;
725 res = malloc(sz);
726 if (!res)
727 return NULL;
728 p = res + 3; /* make a room for rw/ro flag */
729
730 snprintf(p, sz - 3, "%s,%s", vfs, fs);
731
732 /* remove 'rw' flags */
733 rw += !mnt_optstr_remove_option(&p, "rw"); /* from vfs */
734 rw += !mnt_optstr_remove_option(&p, "rw"); /* from fs */
735
736 /* remove 'ro' flags if necessary */
737 if (rw != 2) {
738 ro += !mnt_optstr_remove_option(&p, "ro");
739 if (ro + rw < 2)
740 ro += !mnt_optstr_remove_option(&p, "ro");
741 }
742
743 if (!strlen(p))
744 memcpy(res, ro ? "ro" : "rw", 3);
745 else
746 memcpy(res, ro ? "ro," : "rw,", 3);
747 return res;
748}
749
d115ee9b 750/**
76a06ca4 751 * mnt_fs_strdup_options:
d115ee9b
KZ
752 * @fs: fstab/mtab/mountinfo entry pointer
753 *
d58b3157 754 * Merges all mount options (VFS, FS and userspace) to one options string
9e930041 755 * and returns the result. This function does not modify @fs.
76a06ca4
KZ
756 *
757 * Returns: pointer to string (can be freed by free(3)) or NULL in case of error.
d115ee9b 758 */
68164f6c 759char *mnt_fs_strdup_options(struct libmnt_fs *fs)
d115ee9b 760{
76a06ca4
KZ
761 char *res;
762
37290a53
KZ
763 if (!fs)
764 return NULL;
765
76a06ca4 766 errno = 0;
f2b3a3a3
KZ
767 if (fs->optstr)
768 return strdup(fs->optstr);
769
76a06ca4 770 res = merge_optstr(fs->vfs_optstr, fs->fs_optstr);
87a07a4c 771 if (!res && errno)
76a06ca4 772 return NULL;
74ce680a
SK
773 if (fs->user_optstr &&
774 mnt_optstr_append_option(&res, fs->user_optstr, NULL)) {
775 free(res);
776 res = NULL;
76a06ca4
KZ
777 }
778 return res;
d115ee9b
KZ
779}
780
f2b3a3a3
KZ
781/**
782 * mnt_fs_get_options:
783 * @fs: fstab/mtab/mountinfo entry pointer
784 *
785 * Returns: pointer to string or NULL in case of error.
786 */
787const char *mnt_fs_get_options(struct libmnt_fs *fs)
788{
f2b3a3a3
KZ
789 return fs ? fs->optstr : NULL;
790}
791
e47a1931
OO
792/**
793 * mnt_fs_get_optional_fields
794 * @fs: mountinfo entry pointer
795 *
796 * Returns: pointer to string with mountinfo optional fields
797 * or NULL in case of error.
798 */
799const char *mnt_fs_get_optional_fields(struct libmnt_fs *fs)
800{
e47a1931
OO
801 return fs ? fs->opt_fields : NULL;
802}
f2b3a3a3 803
76a06ca4
KZ
804/**
805 * mnt_fs_set_options:
806 * @fs: fstab/mtab/mountinfo entry pointer
0f32f1e2 807 * @optstr: options string
76a06ca4 808 *
d58b3157 809 * Splits @optstr to VFS, FS and userspace mount options and updates relevant
76a06ca4
KZ
810 * parts of @fs.
811 *
d58b3157 812 * Returns: 0 on success, or negative number in case of error.
76a06ca4 813 */
68164f6c 814int mnt_fs_set_options(struct libmnt_fs *fs, const char *optstr)
d115ee9b 815{
f2b3a3a3 816 char *v = NULL, *f = NULL, *u = NULL, *n = NULL;
192c6aad 817
be1a5180 818 if (!fs)
56be757f 819 return -EINVAL;
76a06ca4
KZ
820 if (optstr) {
821 int rc = mnt_split_optstr(optstr, &u, &v, &f, 0, 0);
56be757f
KZ
822 if (rc)
823 return rc;
f2b3a3a3 824 n = strdup(optstr);
c470cbfc
NK
825 if (!n) {
826 free(u);
827 free(v);
828 free(f);
f2b3a3a3 829 return -ENOMEM;
c470cbfc 830 }
3661b841 831 }
192c6aad 832
d115ee9b
KZ
833 free(fs->fs_optstr);
834 free(fs->vfs_optstr);
76a06ca4 835 free(fs->user_optstr);
f2b3a3a3 836 free(fs->optstr);
d6fead1e 837
3661b841
KZ
838 fs->fs_optstr = f;
839 fs->vfs_optstr = v;
76a06ca4 840 fs->user_optstr = u;
f2b3a3a3
KZ
841 fs->optstr = n;
842
192c6aad 843 return 0;
d115ee9b
KZ
844}
845
76a06ca4
KZ
846/**
847 * mnt_fs_append_options:
848 * @fs: fstab/mtab/mountinfo entry
849 * @optstr: mount options
850 *
851 * Parses (splits) @optstr and appends results to VFS, FS and userspace lists
852 * of options.
853 *
d58b3157 854 * If @optstr is NULL, then @fs is not modified and 0 is returned.
76a06ca4
KZ
855 *
856 * Returns: 0 on success or negative number in case of error.
857 */
68164f6c 858int mnt_fs_append_options(struct libmnt_fs *fs, const char *optstr)
b2d0b74d 859{
76a06ca4 860 char *v = NULL, *f = NULL, *u = NULL;
b2d0b74d
KZ
861 int rc;
862
76a06ca4
KZ
863 if (!fs)
864 return -EINVAL;
865 if (!optstr)
866 return 0;
867
b00dd55a 868 rc = mnt_split_optstr(optstr, &u, &v, &f, 0, 0);
1e670193
KZ
869 if (rc)
870 return rc;
871
76a06ca4
KZ
872 if (!rc && v)
873 rc = mnt_optstr_append_option(&fs->vfs_optstr, v, NULL);
874 if (!rc && f)
f2b3a3a3 875 rc = mnt_optstr_append_option(&fs->fs_optstr, f, NULL);
76a06ca4 876 if (!rc && u)
f2b3a3a3
KZ
877 rc = mnt_optstr_append_option(&fs->user_optstr, u, NULL);
878 if (!rc)
879 rc = mnt_optstr_append_option(&fs->optstr, optstr, NULL);
880
881 free(v);
882 free(f);
883 free(u);
76a06ca4 884
b2d0b74d
KZ
885 return rc;
886}
887
3661b841 888/**
76a06ca4
KZ
889 * mnt_fs_prepend_options:
890 * @fs: fstab/mtab/mountinfo entry
891 * @optstr: mount options
892 *
d58b3157 893 * Parses (splits) @optstr and prepends the results to VFS, FS and userspace lists
76a06ca4
KZ
894 * of options.
895 *
d58b3157 896 * If @optstr is NULL, then @fs is not modified and 0 is returned.
76a06ca4
KZ
897 *
898 * Returns: 0 on success or negative number in case of error.
899 */
68164f6c 900int mnt_fs_prepend_options(struct libmnt_fs *fs, const char *optstr)
76a06ca4
KZ
901{
902 char *v = NULL, *f = NULL, *u = NULL;
903 int rc;
904
76a06ca4
KZ
905 if (!fs)
906 return -EINVAL;
907 if (!optstr)
908 return 0;
909
b00dd55a 910 rc = mnt_split_optstr(optstr, &u, &v, &f, 0, 0);
1e670193
KZ
911 if (rc)
912 return rc;
913
76a06ca4
KZ
914 if (!rc && v)
915 rc = mnt_optstr_prepend_option(&fs->vfs_optstr, v, NULL);
916 if (!rc && f)
917 rc = mnt_optstr_prepend_option(&fs->fs_optstr, f, NULL);
918 if (!rc && u)
919 rc = mnt_optstr_prepend_option(&fs->user_optstr, u, NULL);
f2b3a3a3
KZ
920 if (!rc)
921 rc = mnt_optstr_prepend_option(&fs->optstr, optstr, NULL);
922
923 free(v);
924 free(f);
925 free(u);
76a06ca4
KZ
926
927 return rc;
928}
929
930/*
931 * mnt_fs_get_fs_options:
932 * @fs: fstab/mtab/mountinfo entry pointer
933 *
934 * Returns: pointer to superblock (fs-depend) mount option string or NULL.
935 */
68164f6c 936const char *mnt_fs_get_fs_options(struct libmnt_fs *fs)
76a06ca4 937{
76a06ca4
KZ
938 return fs ? fs->fs_optstr : NULL;
939}
940
76a06ca4
KZ
941/**
942 * mnt_fs_get_vfs_options:
943 * @fs: fstab/mtab entry pointer
944 *
945 * Returns: pointer to fs-independent (VFS) mount option string or NULL.
946 */
68164f6c 947const char *mnt_fs_get_vfs_options(struct libmnt_fs *fs)
76a06ca4 948{
76a06ca4
KZ
949 return fs ? fs->vfs_optstr : NULL;
950}
951
76a06ca4 952/**
68164f6c 953 * mnt_fs_get_user_options:
76a06ca4
KZ
954 * @fs: fstab/mtab entry pointer
955 *
956 * Returns: pointer to userspace mount option string or NULL.
957 */
68164f6c 958const char *mnt_fs_get_user_options(struct libmnt_fs *fs)
76a06ca4 959{
76a06ca4 960 return fs ? fs->user_optstr : NULL;
569f95b7
KZ
961}
962
d115ee9b 963/**
76a06ca4
KZ
964 * mnt_fs_get_attributes:
965 * @fs: fstab/mtab entry pointer
d115ee9b 966 *
76a06ca4 967 * Returns: pointer to attributes string or NULL.
d115ee9b 968 */
68164f6c 969const char *mnt_fs_get_attributes(struct libmnt_fs *fs)
d115ee9b 970{
76a06ca4 971 return fs ? fs->attrs : NULL;
d115ee9b
KZ
972}
973
974/**
76a06ca4
KZ
975 * mnt_fs_set_attributes:
976 * @fs: fstab/mtab/mountinfo entry
977 * @optstr: options string
d115ee9b 978 *
76a06ca4 979 * Sets mount attributes. The attributes are mount(2) and mount(8) independent
d58b3157 980 * options, these options are not sent to the kernel and are not interpreted by
a362ae60 981 * libmount. The attributes are stored in /run/mount/utab only.
76a06ca4 982 *
d58b3157 983 * The attributes are managed by libmount in userspace only. It's possible
76a06ca4 984 * that information stored in userspace will not be available for libmount
7007991f 985 * after CLONE_FS unshare. Be careful, and don't use attributes if possible.
76a06ca4
KZ
986 *
987 * Returns: 0 on success or negative number in case of error.
d115ee9b 988 */
68164f6c 989int mnt_fs_set_attributes(struct libmnt_fs *fs, const char *optstr)
d115ee9b 990{
deb1c903 991 return strdup_to_struct_member(fs, attrs, optstr);
76a06ca4
KZ
992}
993
994/**
995 * mnt_fs_append_attributes
996 * @fs: fstab/mtab/mountinfo entry
997 * @optstr: options string
998 *
999 * Appends mount attributes. (See mnt_fs_set_attributes()).
1000 *
1001 * Returns: 0 on success or negative number in case of error.
1002 */
68164f6c 1003int mnt_fs_append_attributes(struct libmnt_fs *fs, const char *optstr)
76a06ca4
KZ
1004{
1005 if (!fs)
1006 return -EINVAL;
1007 if (!optstr)
1008 return 0;
1009 return mnt_optstr_append_option(&fs->attrs, optstr, NULL);
1010}
1011
1012/**
1013 * mnt_fs_prepend_attributes
1014 * @fs: fstab/mtab/mountinfo entry
1015 * @optstr: options string
1016 *
1017 * Prepends mount attributes. (See mnt_fs_set_attributes()).
1018 *
1019 * Returns: 0 on success or negative number in case of error.
1020 */
68164f6c 1021int mnt_fs_prepend_attributes(struct libmnt_fs *fs, const char *optstr)
76a06ca4
KZ
1022{
1023 if (!fs)
1024 return -EINVAL;
1025 if (!optstr)
1026 return 0;
1027 return mnt_optstr_prepend_option(&fs->attrs, optstr, NULL);
d115ee9b
KZ
1028}
1029
1030
1031/**
1032 * mnt_fs_get_freq:
1033 * @fs: fstab/mtab/mountinfo entry pointer
1034 *
3d735589 1035 * Returns: dump frequency in days.
d115ee9b 1036 */
68164f6c 1037int mnt_fs_get_freq(struct libmnt_fs *fs)
d115ee9b 1038{
d115ee9b
KZ
1039 return fs ? fs->freq : 0;
1040}
1041
1042/**
1043 * mnt_fs_set_freq:
efe73c3e 1044 * @fs: fstab/mtab entry pointer
d115ee9b
KZ
1045 * @freq: dump frequency in days
1046 *
56be757f 1047 * Returns: 0 on success or negative number in case of error.
d115ee9b 1048 */
68164f6c 1049int mnt_fs_set_freq(struct libmnt_fs *fs, int freq)
d115ee9b 1050{
d115ee9b 1051 if (!fs)
56be757f 1052 return -EINVAL;
d115ee9b
KZ
1053 fs->freq = freq;
1054 return 0;
1055}
1056
1057/**
1058 * mnt_fs_get_passno:
efe73c3e 1059 * @fs: fstab/mtab entry pointer
d115ee9b 1060 *
192c6aad 1061 * Returns: "pass number on parallel fsck".
d115ee9b 1062 */
68164f6c 1063int mnt_fs_get_passno(struct libmnt_fs *fs)
d115ee9b 1064{
d115ee9b
KZ
1065 return fs ? fs->passno: 0;
1066}
1067
1068/**
1069 * mnt_fs_set_passno:
efe73c3e 1070 * @fs: fstab/mtab entry pointer
d115ee9b
KZ
1071 * @passno: pass number
1072 *
56be757f 1073 * Returns: 0 on success or negative number in case of error.
d115ee9b 1074 */
68164f6c 1075int mnt_fs_set_passno(struct libmnt_fs *fs, int passno)
d115ee9b 1076{
d115ee9b 1077 if (!fs)
56be757f 1078 return -EINVAL;
d115ee9b
KZ
1079 fs->passno = passno;
1080 return 0;
1081}
1082
0b3953a3
KZ
1083/**
1084 * mnt_fs_get_root:
1085 * @fs: /proc/self/mountinfo entry
1086 *
1087 * Returns: root of the mount within the filesystem or NULL
1088 */
68164f6c 1089const char *mnt_fs_get_root(struct libmnt_fs *fs)
0b3953a3 1090{
0b3953a3
KZ
1091 return fs ? fs->root : NULL;
1092}
1093
9ecdf48f
KZ
1094/**
1095 * mnt_fs_set_root:
1096 * @fs: mountinfo entry
deb1c903 1097 * @path: root path
9ecdf48f 1098 *
56be757f 1099 * Returns: 0 on success or negative number in case of error.
9ecdf48f 1100 */
deb1c903 1101int mnt_fs_set_root(struct libmnt_fs *fs, const char *path)
9ecdf48f 1102{
deb1c903 1103 return strdup_to_struct_member(fs, root, path);
9ecdf48f
KZ
1104}
1105
ce4dd666
KZ
1106/**
1107 * mnt_fs_get_swaptype:
1108 * @fs: /proc/swaps entry
1109 *
1110 * Returns: swap type or NULL
1111 */
1112const char *mnt_fs_get_swaptype(struct libmnt_fs *fs)
1113{
ce4dd666
KZ
1114 return fs ? fs->swaptype : NULL;
1115}
1116
1117/**
1118 * mnt_fs_get_size:
1119 * @fs: /proc/swaps entry
1120 *
1121 * Returns: size
1122 */
1123off_t mnt_fs_get_size(struct libmnt_fs *fs)
1124{
ce4dd666
KZ
1125 return fs ? fs->size : 0;
1126}
1127
1128/**
1129 * mnt_fs_get_usedsize:
1130 * @fs: /proc/swaps entry
1131 *
1132 * Returns: used size
1133 */
1134off_t mnt_fs_get_usedsize(struct libmnt_fs *fs)
1135{
ce4dd666
KZ
1136 return fs ? fs->usedsize : 0;
1137}
1138
1139/**
1140 * mnt_fs_get_priority:
1141 * @fs: /proc/swaps entry
1142 *
1143 * Returns: priority
1144 */
1145int mnt_fs_get_priority(struct libmnt_fs *fs)
1146{
ce4dd666
KZ
1147 return fs ? fs->priority : 0;
1148}
1149
1150/**
1151 * mnt_fs_set_priority:
1152 * @fs: /proc/swaps entry
81b176c4 1153 * @prio: priority
ce4dd666 1154 *
a81b1946
KZ
1155 * Since: 2.28
1156 *
ce4dd666
KZ
1157 * Returns: 0 or -1 in case of error
1158 */
1159int mnt_fs_set_priority(struct libmnt_fs *fs, int prio)
1160{
ce4dd666
KZ
1161 if (!fs)
1162 return -EINVAL;
1163 fs->priority = prio;
1164 return 0;
1165}
1166
dd369652
KZ
1167/**
1168 * mnt_fs_get_bindsrc:
a362ae60 1169 * @fs: /run/mount/utab entry
dd369652
KZ
1170 *
1171 * Returns: full path that was used for mount(2) on MS_BIND
1172 */
68164f6c 1173const char *mnt_fs_get_bindsrc(struct libmnt_fs *fs)
dd369652 1174{
dd369652
KZ
1175 return fs ? fs->bindsrc : NULL;
1176}
1177
1178/**
1179 * mnt_fs_set_bindsrc:
1180 * @fs: filesystem
1181 * @src: path
1182 *
1183 * Returns: 0 on success or negative number in case of error.
1184 */
68164f6c 1185int mnt_fs_set_bindsrc(struct libmnt_fs *fs, const char *src)
dd369652 1186{
deb1c903 1187 return strdup_to_struct_member(fs, bindsrc, src);
dd369652
KZ
1188}
1189
efe73c3e
KZ
1190/**
1191 * mnt_fs_get_id:
1192 * @fs: /proc/self/mountinfo entry
1193 *
56be757f 1194 * Returns: mount ID (unique identifier of the mount) or negative number in case of error.
efe73c3e 1195 */
68164f6c 1196int mnt_fs_get_id(struct libmnt_fs *fs)
efe73c3e 1197{
56be757f 1198 return fs ? fs->id : -EINVAL;
efe73c3e
KZ
1199}
1200
1201/**
1202 * mnt_fs_get_parent_id:
1203 * @fs: /proc/self/mountinfo entry
1204 *
56be757f 1205 * Returns: parent mount ID or negative number in case of error.
efe73c3e 1206 */
68164f6c 1207int mnt_fs_get_parent_id(struct libmnt_fs *fs)
efe73c3e 1208{
56be757f 1209 return fs ? fs->parent : -EINVAL;
efe73c3e
KZ
1210}
1211
1212/**
1213 * mnt_fs_get_devno:
0b3953a3 1214 * @fs: /proc/self/mountinfo entry
efe73c3e
KZ
1215 *
1216 * Returns: value of st_dev for files on filesystem or 0 in case of error.
1217 */
68164f6c 1218dev_t mnt_fs_get_devno(struct libmnt_fs *fs)
efe73c3e 1219{
efe73c3e
KZ
1220 return fs ? fs->devno : 0;
1221}
1222
f7f29b56
KZ
1223/**
1224 * mnt_fs_get_tid:
a3bb7e65 1225 * @fs: /proc/tid/mountinfo entry
f7f29b56 1226 *
d58b3157 1227 * Returns: TID (task ID) for filesystems read from the mountinfo file
f7f29b56
KZ
1228 */
1229pid_t mnt_fs_get_tid(struct libmnt_fs *fs)
1230{
f7f29b56
KZ
1231 return fs ? fs->tid : 0;
1232}
1233
d115ee9b
KZ
1234/**
1235 * mnt_fs_get_option:
1236 * @fs: fstab/mtab/mountinfo entry pointer
1237 * @name: option name
d58b3157 1238 * @value: returns pointer to the beginning of the value (e.g. name=VALUE) or NULL
d115ee9b
KZ
1239 * @valsz: returns size of options value or 0
1240 *
d58b3157 1241 * Returns: 0 on success, 1 when @name not found or negative number in case of error.
d115ee9b 1242 */
68164f6c 1243int mnt_fs_get_option(struct libmnt_fs *fs, const char *name,
d115ee9b
KZ
1244 char **value, size_t *valsz)
1245{
76a06ca4
KZ
1246 char rc = 1;
1247
ba2bdf41
KZ
1248 if (!fs)
1249 return -EINVAL;
76a06ca4
KZ
1250 if (fs->fs_optstr)
1251 rc = mnt_optstr_get_option(fs->fs_optstr, name, value, valsz);
1252 if (rc == 1 && fs->vfs_optstr)
1253 rc = mnt_optstr_get_option(fs->vfs_optstr, name, value, valsz);
1254 if (rc == 1 && fs->user_optstr)
1255 rc = mnt_optstr_get_option(fs->user_optstr, name, value, valsz);
1256 return rc;
1257}
1258
1259/**
1260 * mnt_fs_get_attribute:
1261 * @fs: fstab/mtab/mountinfo entry pointer
1262 * @name: option name
d58b3157 1263 * @value: returns pointer to the beginning of the value (e.g. name=VALUE) or NULL
76a06ca4
KZ
1264 * @valsz: returns size of options value or 0
1265 *
d58b3157 1266 * Returns: 0 on success, 1 when @name not found or negative number in case of error.
76a06ca4 1267 */
68164f6c 1268int mnt_fs_get_attribute(struct libmnt_fs *fs, const char *name,
76a06ca4
KZ
1269 char **value, size_t *valsz)
1270{
1271 char rc = 1;
1272
4569bbea
KZ
1273 if (!fs)
1274 return -EINVAL;
76a06ca4
KZ
1275 if (fs->attrs)
1276 rc = mnt_optstr_get_option(fs->attrs, name, value, valsz);
1277 return rc;
d115ee9b
KZ
1278}
1279
cb90e24e
OO
1280/**
1281 * mnt_fs_get_comment:
1282 * @fs: fstab/mtab/mountinfo entry pointer
1283 *
1284 * Returns: 0 on success, 1 when not found the @name or negative number in case of error.
1285 */
1286const char *mnt_fs_get_comment(struct libmnt_fs *fs)
1287{
cb90e24e
OO
1288 if (!fs)
1289 return NULL;
1290 return fs->comment;
1291}
1292
1293/**
1294 * mnt_fs_set_comment:
1295 * @fs: fstab entry pointer
1296 * @comm: comment string
1297 *
d22f2822 1298 * Note that the comment has to be terminated by '\n' (new line), otherwise
d58b3157 1299 * the whole filesystem entry will be written as a comment to the tabfile (e.g.
d22f2822
OO
1300 * fstab).
1301 *
cb90e24e
OO
1302 * Returns: 0 on success or <0 in case of error.
1303 */
1304int mnt_fs_set_comment(struct libmnt_fs *fs, const char *comm)
1305{
deb1c903 1306 return strdup_to_struct_member(fs, comment, comm);
cb90e24e
OO
1307}
1308
1309/**
1310 * mnt_fs_append_comment:
1311 * @fs: fstab entry pointer
7b1333fa 1312 * @comm: comment string
cb90e24e 1313 *
d22f2822
OO
1314 * See also mnt_fs_set_comment().
1315 *
cb90e24e
OO
1316 * Returns: 0 on success or <0 in case of error.
1317 */
1318int mnt_fs_append_comment(struct libmnt_fs *fs, const char *comm)
1319{
cb90e24e
OO
1320 if (!fs)
1321 return -EINVAL;
1322
1323 return append_string(&fs->comment, comm);
1324}
1325
3fca8422
KZ
1326/**
1327 * mnt_fs_match_target:
1328 * @fs: filesystem
1329 * @target: mountpoint path
1330 * @cache: tags/paths cache or NULL
1331 *
1332 * Possible are three attempts:
1333 * 1) compare @target with @fs->target
8642cd7b 1334 *
3fca8422 1335 * 2) realpath(@target) with @fs->target
8642cd7b 1336 *
fa705b54 1337 * 3) realpath(@target) with realpath(@fs->target) if @fs is not from
8642cd7b
KZ
1338 * /proc/self/mountinfo.
1339 *
1340 * However, if mnt_cache_set_targets(cache, mtab) was called, and the
1341 * path @target or @fs->target is found in the @mtab, the canonicalization is
1342 * is not performed (see mnt_resolve_target()).
3fca8422
KZ
1343 *
1344 * The 2nd and 3rd attempts are not performed when @cache is NULL.
1345 *
d58b3157 1346 * Returns: 1 if @fs target is equal to @target, else 0.
3fca8422 1347 */
16b8db49
KZ
1348int mnt_fs_match_target(struct libmnt_fs *fs, const char *target,
1349 struct libmnt_cache *cache)
3fca8422
KZ
1350{
1351 int rc = 0;
1352
1353 if (!fs || !target || !fs->target)
1354 return 0;
1355
1356 /* 1) native paths */
6699e742 1357 rc = mnt_fs_streq_target(fs, target);
3fca8422
KZ
1358
1359 if (!rc && cache) {
1360 /* 2) - canonicalized and non-canonicalized */
8642cd7b 1361 char *cn = mnt_resolve_target(target, cache);
ab131f00 1362 rc = (cn && mnt_fs_streq_target(fs, cn));
3fca8422
KZ
1363
1364 /* 3) - canonicalized and canonicalized */
45e8cdba 1365 if (!rc && cn && !mnt_fs_is_kernel(fs) && !mnt_fs_is_swaparea(fs)) {
0382ba32 1366 char *tcn = mnt_resolve_target(fs->target, cache);
3fca8422
KZ
1367 rc = (tcn && strcmp(cn, tcn) == 0);
1368 }
1369 }
1370
1371 return rc;
1372}
1373
1374/**
1375 * mnt_fs_match_source:
1376 * @fs: filesystem
f12aac6e 1377 * @source: tag or path (device or so) or NULL
3fca8422
KZ
1378 * @cache: tags/paths cache or NULL
1379 *
d58b3157 1380 * Four attempts are possible:
3fca8422
KZ
1381 * 1) compare @source with @fs->source
1382 * 2) compare realpath(@source) with @fs->source
1383 * 3) compare realpath(@source) with realpath(@fs->source)
1384 * 4) compare realpath(@source) with evaluated tag from @fs->source
1385 *
1386 * The 2nd, 3rd and 4th attempts are not performed when @cache is NULL. The
1387 * 2nd and 3rd attempts are not performed if @fs->source is tag.
1388 *
d58b3157 1389 * Returns: 1 if @fs source is equal to @source, else 0.
3fca8422 1390 */
16b8db49
KZ
1391int mnt_fs_match_source(struct libmnt_fs *fs, const char *source,
1392 struct libmnt_cache *cache)
3fca8422 1393{
3fca8422
KZ
1394 char *cn;
1395 const char *src, *t, *v;
1396
f12aac6e
KZ
1397 if (!fs)
1398 return 0;
1399
ab8c6e05
KZ
1400 /* 1) native paths... */
1401 if (mnt_fs_streq_srcpath(fs, source) == 1)
f12aac6e
KZ
1402 return 1;
1403
ab8c6e05 1404 if (!source || !fs->source)
3fca8422
KZ
1405 return 0;
1406
ab8c6e05
KZ
1407 /* ... and tags */
1408 if (fs->tagname && strcmp(source, fs->source) == 0)
3ef87248 1409 return 1;
3fca8422 1410
3ef87248
KZ
1411 if (!cache)
1412 return 0;
3fca8422
KZ
1413 if (fs->flags & (MNT_FS_NET | MNT_FS_PSEUDO))
1414 return 0;
1415
1416 cn = mnt_resolve_spec(source, cache);
1417 if (!cn)
1418 return 0;
1419
1420 /* 2) canonicalized and native */
1421 src = mnt_fs_get_srcpath(fs);
ab8c6e05 1422 if (src && mnt_fs_streq_srcpath(fs, cn))
3ef87248 1423 return 1;
3fca8422
KZ
1424
1425 /* 3) canonicalized and canonicalized */
3ef87248 1426 if (src) {
3fca8422 1427 src = mnt_resolve_path(src, cache);
3ef87248
KZ
1428 if (src && !strcmp(cn, src))
1429 return 1;
3fca8422 1430 }
3ef87248 1431 if (src || mnt_fs_get_tag(fs, &t, &v))
d58b3157 1432 /* src path does not match and the tag is not defined */
3fca8422
KZ
1433 return 0;
1434
1435 /* read @source's tags to the cache */
ba7232a1 1436 if (mnt_cache_read_tags(cache, cn) < 0) {
3fca8422
KZ
1437 if (errno == EACCES) {
1438 /* we don't have permissions to read TAGs from
d58b3157 1439 * @source, but can translate the @fs tag to devname.
3fca8422
KZ
1440 *
1441 * (because libblkid uses udev symlinks and this is
1442 * accessible for non-root uses)
1443 */
1444 char *x = mnt_resolve_tag(t, v, cache);
1445 if (x && !strcmp(x, cn))
1446 return 1;
1447 }
1448 return 0;
1449 }
1450
d58b3157 1451 /* 4) has the @source a tag that matches with the tag from @fs ? */
3ef87248
KZ
1452 if (mnt_cache_device_has_tag(cache, cn, t, v))
1453 return 1;
3fca8422 1454
3ef87248 1455 return 0;
3fca8422
KZ
1456}
1457
1458/**
1459 * mnt_fs_match_fstype:
1460 * @fs: filesystem
1461 * @types: filesystem name or comma delimited list of filesystems
1462 *
1463 * For more details see mnt_match_fstype().
1464 *
d58b3157 1465 * Returns: 1 if @fs type is matching to @types, else 0. The function returns
3fca8422
KZ
1466 * 0 when types is NULL.
1467 */
68164f6c 1468int mnt_fs_match_fstype(struct libmnt_fs *fs, const char *types)
3fca8422
KZ
1469{
1470 return mnt_match_fstype(fs->fstype, types);
1471}
1472
1473/**
1474 * mnt_fs_match_options:
1475 * @fs: filesystem
1476 * @options: comma delimited list of options (and nooptions)
1477 *
1478 * For more details see mnt_match_options().
1479 *
d58b3157 1480 * Returns: 1 if @fs type is matching to @options, else 0. The function returns
3fca8422
KZ
1481 * 0 when types is NULL.
1482 */
68164f6c 1483int mnt_fs_match_options(struct libmnt_fs *fs, const char *options)
3fca8422 1484{
d84508cf 1485 return mnt_match_options(mnt_fs_get_options(fs), options);
3fca8422
KZ
1486}
1487
d115ee9b
KZ
1488/**
1489 * mnt_fs_print_debug
1490 * @fs: fstab/mtab/mountinfo entry
486d3972 1491 * @file: file stream
d115ee9b 1492 *
56be757f 1493 * Returns: 0 on success or negative number in case of error.
d115ee9b 1494 */
68164f6c 1495int mnt_fs_print_debug(struct libmnt_fs *fs, FILE *file)
d115ee9b 1496{
4569bbea 1497 if (!fs || !file)
56be757f 1498 return -EINVAL;
8d31f146 1499 fprintf(file, "------ fs:\n");
77417bc0
KZ
1500 fprintf(file, "source: %s\n", mnt_fs_get_source(fs));
1501 fprintf(file, "target: %s\n", mnt_fs_get_target(fs));
1502 fprintf(file, "fstype: %s\n", mnt_fs_get_fstype(fs));
76a06ca4 1503
f2b3a3a3
KZ
1504 if (mnt_fs_get_options(fs))
1505 fprintf(file, "optstr: %s\n", mnt_fs_get_options(fs));
76a06ca4
KZ
1506 if (mnt_fs_get_vfs_options(fs))
1507 fprintf(file, "VFS-optstr: %s\n", mnt_fs_get_vfs_options(fs));
1508 if (mnt_fs_get_fs_options(fs))
1509 fprintf(file, "FS-opstr: %s\n", mnt_fs_get_fs_options(fs));
68164f6c
KZ
1510 if (mnt_fs_get_user_options(fs))
1511 fprintf(file, "user-optstr: %s\n", mnt_fs_get_user_options(fs));
e47a1931
OO
1512 if (mnt_fs_get_optional_fields(fs))
1513 fprintf(file, "optional-fields: '%s'\n", mnt_fs_get_optional_fields(fs));
76a06ca4
KZ
1514 if (mnt_fs_get_attributes(fs))
1515 fprintf(file, "attributes: %s\n", mnt_fs_get_attributes(fs));
dd369652
KZ
1516
1517 if (mnt_fs_get_root(fs))
77417bc0 1518 fprintf(file, "root: %s\n", mnt_fs_get_root(fs));
ce4dd666
KZ
1519
1520 if (mnt_fs_get_swaptype(fs))
1521 fprintf(file, "swaptype: %s\n", mnt_fs_get_swaptype(fs));
1522 if (mnt_fs_get_size(fs))
1523 fprintf(file, "size: %jd\n", mnt_fs_get_size(fs));
1524 if (mnt_fs_get_usedsize(fs))
1525 fprintf(file, "usedsize: %jd\n", mnt_fs_get_usedsize(fs));
1526 if (mnt_fs_get_priority(fs))
1527 fprintf(file, "priority: %d\n", mnt_fs_get_priority(fs));
1528
dd369652
KZ
1529 if (mnt_fs_get_bindsrc(fs))
1530 fprintf(file, "bindsrc: %s\n", mnt_fs_get_bindsrc(fs));
9dd75aa6 1531 if (mnt_fs_get_freq(fs))
77417bc0 1532 fprintf(file, "freq: %d\n", mnt_fs_get_freq(fs));
9dd75aa6 1533 if (mnt_fs_get_passno(fs))
77417bc0 1534 fprintf(file, "pass: %d\n", mnt_fs_get_passno(fs));
9dd75aa6 1535 if (mnt_fs_get_id(fs))
77417bc0 1536 fprintf(file, "id: %d\n", mnt_fs_get_id(fs));
9dd75aa6 1537 if (mnt_fs_get_parent_id(fs))
77417bc0 1538 fprintf(file, "parent: %d\n", mnt_fs_get_parent_id(fs));
9dd75aa6 1539 if (mnt_fs_get_devno(fs))
77417bc0 1540 fprintf(file, "devno: %d:%d\n", major(mnt_fs_get_devno(fs)),
f7f29b56
KZ
1541 minor(mnt_fs_get_devno(fs)));
1542 if (mnt_fs_get_tid(fs))
1543 fprintf(file, "tid: %d\n", mnt_fs_get_tid(fs));
cb90e24e
OO
1544 if (mnt_fs_get_comment(fs))
1545 fprintf(file, "comment: '%s'\n", mnt_fs_get_comment(fs));
f7f29b56 1546
d115ee9b
KZ
1547 return 0;
1548}
8b95253f
KZ
1549
1550/**
1551 * mnt_free_mntent:
1552 * @mnt: mount entry
1553 *
d58b3157 1554 * Deallocates the "mntent.h" mount entry.
8b95253f
KZ
1555 */
1556void mnt_free_mntent(struct mntent *mnt)
1557{
1558 if (mnt) {
1559 free(mnt->mnt_fsname);
1560 free(mnt->mnt_dir);
1561 free(mnt->mnt_type);
1562 free(mnt->mnt_opts);
1563 free(mnt);
1564 }
1565}
1566
1567/**
1568 * mnt_fs_to_mntent:
1569 * @fs: filesystem
1570 * @mnt: mount description (as described in mntent.h)
1571 *
d58b3157 1572 * Copies the information from @fs to struct mntent @mnt. If @mnt is already set,
8b95253f
KZ
1573 * then the struct mntent items are reallocated and updated. See also
1574 * mnt_free_mntent().
1575 *
d58b3157 1576 * Returns: 0 on success and a negative number in case of error.
8b95253f 1577 */
68164f6c 1578int mnt_fs_to_mntent(struct libmnt_fs *fs, struct mntent **mnt)
8b95253f
KZ
1579{
1580 int rc;
1581 struct mntent *m;
1582
1583 if (!fs || !mnt)
1584 return -EINVAL;
1585
1586 m = *mnt;
1587 if (!m) {
1588 m = calloc(1, sizeof(*m));
1589 if (!m)
1590 return -ENOMEM;
1591 }
1592
309139c7 1593 if ((rc = update_str(&m->mnt_fsname, mnt_fs_get_source(fs))))
8b95253f 1594 goto err;
309139c7 1595 if ((rc = update_str(&m->mnt_dir, mnt_fs_get_target(fs))))
8b95253f 1596 goto err;
309139c7 1597 if ((rc = update_str(&m->mnt_type, mnt_fs_get_fstype(fs))))
8b95253f 1598 goto err;
76a06ca4
KZ
1599
1600 errno = 0;
1601 m->mnt_opts = mnt_fs_strdup_options(fs);
1602 if (!m->mnt_opts && errno) {
1603 rc = -errno;
8b95253f 1604 goto err;
76a06ca4
KZ
1605 }
1606
8b95253f
KZ
1607 m->mnt_freq = mnt_fs_get_freq(fs);
1608 m->mnt_passno = mnt_fs_get_passno(fs);
1609
de511a88
KZ
1610 if (!m->mnt_fsname) {
1611 m->mnt_fsname = strdup("none");
1612 if (!m->mnt_fsname)
1613 goto err;
1614 }
8b95253f
KZ
1615 *mnt = m;
1616
1617 return 0;
1618err:
1619 if (m != *mnt)
1620 mnt_free_mntent(m);
1621 return rc;
1622}