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