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