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