]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - libmount/src/context.c
2 * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
4 * This file may be redistributed under the terms of the
5 * GNU Lesser General Public License.
10 * @title: Library high-level context
11 * @short_description: high-level API to mount/umount devices.
15 * struct libmnt_context *cxt = mnt_new_context();
17 * mnt_context_set_options(cxt, "aaa,bbb,ccc=CCC");
18 * mnt_context_set_mflags(cxt, MS_NOATIME|MS_NOEXEC);
19 * mnt_context_set_target(cxt, "/mnt/foo");
21 * if (!mnt_context_mount(cxt))
22 * printf("successfully mounted\n");
23 * mnt_free_context(cxt);
28 * This code is similar to:
30 * mount -o aaa,bbb,ccc=CCC,noatime,noexec /mnt/foo
41 * Returns: newly allocated mount context
43 struct libmnt_context
*mnt_new_context(void)
45 struct libmnt_context
*cxt
;
48 cxt
= calloc(1, sizeof(*cxt
));
55 mnt_context_reset_status(cxt
);
59 /* if we're really root and aren't running setuid */
60 cxt
->restricted
= (uid_t
) 0 == ruid
&& ruid
== euid
? 0 : 1;
62 DBG(CXT
, mnt_debug_h(cxt
, "----> allocate %s",
63 cxt
->restricted
? "[RESTRICTED]" : ""));
65 mnt_has_regular_mtab(&cxt
->mtab_path
, &cxt
->mtab_writable
);
67 if (!cxt
->mtab_writable
)
68 /* use /run/mount/utab if /etc/mtab is useless */
69 mnt_has_regular_utab(&cxt
->utab_path
, &cxt
->utab_writable
);
78 * Deallocates context struct.
80 void mnt_free_context(struct libmnt_context
*cxt
)
85 mnt_reset_context(cxt
);
87 free(cxt
->fstype_pattern
);
88 free(cxt
->optstr_pattern
);
90 if (!(cxt
->flags
& MNT_FL_EXTERN_FSTAB
))
91 mnt_free_table(cxt
->fstab
);
92 if (!(cxt
->flags
& MNT_FL_EXTERN_CACHE
))
93 mnt_free_cache(cxt
->cache
);
95 mnt_context_clear_loopdev(cxt
);
96 mnt_free_lock(cxt
->lock
);
97 mnt_free_update(cxt
->update
);
101 DBG(CXT
, mnt_debug_h(cxt
, "<---- free"));
107 * @cxt: mount context
109 * Resets all information in the context that are directly related to
110 * the latest mount (spec, source, target, mount options, ....)
112 * The match patters, cached fstab, cached canonicalized paths and tags and
113 * [e]uid are not reseted. You have to use
115 * mnt_context_set_fstab(cxt, NULL);
116 * mnt_context_set_cache(cxt, NULL);
117 * mnt_context_set_fstype_pattern(cxt, NULL);
118 * mnt_context_set_options_pattern(cxt, NULL);
121 * to reset these stuff.
123 * Returns: 0 on success, negative number in case of error.
125 int mnt_reset_context(struct libmnt_context
*cxt
)
132 DBG(CXT
, mnt_debug_h(cxt
, "<---- reset [status=%d] ---->",
133 mnt_context_get_status(cxt
)));
137 if (!(cxt
->flags
& MNT_FL_EXTERN_FS
))
138 mnt_free_fs(cxt
->fs
);
140 mnt_free_table(cxt
->mtab
);
143 free(cxt
->orig_user
);
149 cxt
->orig_user
= NULL
;
151 cxt
->user_mountflags
= 0;
152 cxt
->mountdata
= NULL
;
153 cxt
->flags
= MNT_FL_DEFAULT
;
155 mnt_context_reset_status(cxt
);
157 /* restore non-resetable flags */
158 cxt
->flags
|= (fl
& MNT_FL_EXTERN_FSTAB
);
159 cxt
->flags
|= (fl
& MNT_FL_EXTERN_CACHE
);
160 cxt
->flags
|= (fl
& MNT_FL_NOMTAB
);
161 cxt
->flags
|= (fl
& MNT_FL_FAKE
);
162 cxt
->flags
|= (fl
& MNT_FL_SLOPPY
);
163 cxt
->flags
|= (fl
& MNT_FL_VERBOSE
);
164 cxt
->flags
|= (fl
& MNT_FL_NOHELPERS
);
165 cxt
->flags
|= (fl
& MNT_FL_LOOPDEL
);
166 cxt
->flags
|= (fl
& MNT_FL_LAZY
);
167 cxt
->flags
|= (fl
& MNT_FL_FORK
);
168 cxt
->flags
|= (fl
& MNT_FL_FORCE
);
169 cxt
->flags
|= (fl
& MNT_FL_NOCANONICALIZE
);
170 cxt
->flags
|= (fl
& MNT_FL_RDONLY_UMOUNT
);
175 * mnt_context_reset_status:
178 * Resets mount(2) and mount.<type> statuses, so mnt_context_do_mount() or
179 * mnt_context_do_umount() could be again called with the same settings.
181 * BE CAREFUL -- after this soft reset the libmount will NOT parse mount
182 * options, evaluate permissions or apply stuff from fstab.
184 * Returns: 0 on success, negative number in case of error.
186 int mnt_context_reset_status(struct libmnt_context
*cxt
)
191 cxt
->syscall_status
= 1; /* means not called yet */
192 cxt
->helper_exec_status
= 1;
193 cxt
->helper_status
= 0;
197 static int set_flag(struct libmnt_context
*cxt
, int flag
, int enable
)
202 DBG(CXT
, mnt_debug_h(cxt
, "enabling flag %04x", flag
));
205 DBG(CXT
, mnt_debug_h(cxt
, "disabling flag %04x", flag
));
212 * mnt_context_is_restricted:
213 * @cxt: mount context
215 * Returns: 0 for unrestricted mount (user is root), or 1 for non-root mounts
217 int mnt_context_is_restricted(struct libmnt_context
*cxt
)
220 return cxt
->restricted
;
224 * mnt_context_set_optsmode
225 * @cxt: mount context
226 * @mode: mask, see MNT_OMASK_* flags in libmount mount.h
228 * Controls how to use mount options from fstab/mtab.
230 * Returns: 0 on success, negative number in case of error.
232 int mnt_context_set_optsmode(struct libmnt_context
*cxt
, int mode
)
236 cxt
->optsmode
= mode
;
241 * mnt_context_get_optsmode
242 * @cxt: mount context
244 * Returns: MNT_OMASK_* mask or zero.
247 int mnt_context_get_optsmode(struct libmnt_context
*cxt
)
249 return cxt
? cxt
->optsmode
: 0;
253 * mnt_context_disable_canonicalize:
254 * @cxt: mount context
255 * @disable: TRUE or FALSE
257 * Enable/disable paths canonicalization and tags evaluation. The libmount context
258 * canonicalies paths when search in fstab and when prepare source and target paths
259 * for mount(2) syscall.
261 * This fuction has effect to the private fstab instance only (see
262 * mnt_context_set_fstab()). If you want to use an external fstab then you need
263 * manage your private struct libmnt_cache (see mnt_table_set_cache(fstab, NULL).
265 * Returns: 0 on success, negative number in case of error.
267 int mnt_context_disable_canonicalize(struct libmnt_context
*cxt
, int disable
)
269 return set_flag(cxt
, MNT_FL_NOCANONICALIZE
, disable
);
273 * mnt_context_enable_lazy:
274 * @cxt: mount context
275 * @enable: TRUE or FALSE
277 * Enable/disable lazy umount (see umount(8) man page, option -l).
279 * Returns: 0 on success, negative number in case of error.
281 int mnt_context_enable_lazy(struct libmnt_context
*cxt
, int enable
)
283 return set_flag(cxt
, MNT_FL_LAZY
, enable
);
287 * mnt_context_enable_fork:
288 * @cxt: mount context
289 * @enable: TRUE or FALSE
291 * Enable/disable fork(2) call in mnt_context_next_mount() (see mount(8) man
294 * Returns: 0 on success, negative number in case of error.
296 int mnt_context_enable_fork(struct libmnt_context
*cxt
, int enable
)
298 return set_flag(cxt
, MNT_FL_FORK
, enable
);
302 * mnt_context_is_lazy:
303 * @cxt: mount context
305 * Returns: 1 if lazy umount is enabled or 0
307 int mnt_context_is_lazy(struct libmnt_context
*cxt
)
309 return cxt
&& (cxt
->flags
& MNT_FL_LAZY
) ? 1 : 0;
314 * mnt_context_enable_rdonly_umount:
315 * @cxt: mount context
316 * @enable: TRUE or FALSE
318 * Enable/disable read-only remount on failed umount(2)
319 * (see umount(8) man page, option -r).
321 * Returns: 0 on success, negative number in case of error.
323 int mnt_context_enable_rdonly_umount(struct libmnt_context
*cxt
, int enable
)
325 return set_flag(cxt
, MNT_FL_RDONLY_UMOUNT
, enable
);
329 * mnt_context_is_rdonly_umount
330 * @cxt: mount context
332 * See also mnt_context_enable_rdonly_umount() and see umount(8) man page,
335 * Returns: 1 if read-only remount failed umount(2) is enables or 0
337 int mnt_context_is_rdonly_umount(struct libmnt_context
*cxt
)
339 return cxt
&& (cxt
->flags
& MNT_FL_RDONLY_UMOUNT
) ? 1 : 0;
343 * mnt_context_disable_helpers:
344 * @cxt: mount context
345 * @disable: TRUE or FALSE
347 * Enable/disable /sbin/[u]mount.* helpers (see mount(8) man page, option -i).
349 * Returns: 0 on success, negative number in case of error.
351 int mnt_context_disable_helpers(struct libmnt_context
*cxt
, int disable
)
353 return set_flag(cxt
, MNT_FL_NOHELPERS
, disable
);
357 * mnt_context_enable_sloppy:
358 * @cxt: mount context
359 * @enable: TRUE or FALSE
361 * Set/unset sloppy mounting (see mount(8) man page, option -s).
363 * Returns: 0 on success, negative number in case of error.
365 int mnt_context_enable_sloppy(struct libmnt_context
*cxt
, int enable
)
367 return set_flag(cxt
, MNT_FL_SLOPPY
, enable
);
371 * mnt_context_is_sloppy:
372 * @cxt: mount context
374 * Returns: 1 if sloppy flag is enabled or 0
376 int mnt_context_is_sloppy(struct libmnt_context
*cxt
)
378 return cxt
&& (cxt
->flags
& MNT_FL_SLOPPY
) ? 1 : 0;
382 * mnt_context_enable_fake:
383 * @cxt: mount context
384 * @enable: TRUE or FALSE
386 * Enable/disable fake mounting (see mount(8) man page, option -f).
388 * Returns: 0 on success, negative number in case of error.
390 int mnt_context_enable_fake(struct libmnt_context
*cxt
, int enable
)
392 return set_flag(cxt
, MNT_FL_FAKE
, enable
);
396 * mnt_context_is_fake:
397 * @cxt: mount context
399 * Returns: 1 if fake flag is enabled or 0
401 int mnt_context_is_fake(struct libmnt_context
*cxt
)
403 return cxt
&& (cxt
->flags
& MNT_FL_FAKE
) ? 1 : 0;
407 * mnt_context_disable_mtab:
408 * @cxt: mount context
409 * @disable: TRUE or FALSE
411 * Disable/enable mtab update (see mount(8) man page, option -n).
413 * Returns: 0 on success, negative number in case of error.
415 int mnt_context_disable_mtab(struct libmnt_context
*cxt
, int disable
)
417 return set_flag(cxt
, MNT_FL_NOMTAB
, disable
);
421 * mnt_context_is_nomtab
422 * @cxt: mount context
424 * Returns: 1 if no-mtab is enabled or 0
426 int mnt_context_is_nomtab(struct libmnt_context
*cxt
)
428 return cxt
&& (cxt
->flags
& MNT_FL_NOMTAB
) ? 1 : 0;
432 * mnt_context_enable_force:
433 * @cxt: mount context
434 * @enable: TRUE or FALSE
436 * Enable/disable force umounting (see umount(8) man page, option -f).
438 * Returns: 0 on success, negative number in case of error.
440 int mnt_context_enable_force(struct libmnt_context
*cxt
, int enable
)
442 return set_flag(cxt
, MNT_FL_FORCE
, enable
);
446 * mnt_context_is_force
447 * @cxt: mount context
449 * Returns: 1 if force umounting flag is enabled or 0
451 int mnt_context_is_force(struct libmnt_context
*cxt
)
453 return cxt
&& (cxt
->flags
& MNT_FL_FORCE
) ? 1 : 0;
457 * mnt_context_enable_verbose:
458 * @cxt: mount context
459 * @enable: TRUE or FALSE
461 * Enable/disable verbose output (TODO: not implemented yet)
463 * Returns: 0 on success, negative number in case of error.
465 int mnt_context_enable_verbose(struct libmnt_context
*cxt
, int enable
)
467 return set_flag(cxt
, MNT_FL_VERBOSE
, enable
);
471 * mnt_context_is_verbose
472 * @cxt: mount context
474 * Returns: 1 if verbose flag is enabled or 0
476 int mnt_context_is_verbose(struct libmnt_context
*cxt
)
478 return cxt
&& (cxt
->flags
& MNT_FL_VERBOSE
) ? 1 : 0;
482 * mnt_context_enable_loopdel:
483 * @cxt: mount context
484 * @enable: TRUE or FALSE
486 * Enable/disable loop delete (destroy) after umount (see umount(8), option -d)
488 * Returns: 0 on success, negative number in case of error.
490 int mnt_context_enable_loopdel(struct libmnt_context
*cxt
, int enable
)
492 return set_flag(cxt
, MNT_FL_LOOPDEL
, enable
);
496 * mnt_context_set_fs:
497 * @cxt: mount context
498 * @fs: filesystem description
500 * The mount context uses private @fs by default. This function allows to
501 * overwrite the private @fs with an external instance. Note that the external
502 * @fs instance is not deallocated by mnt_free_context() or mnt_reset_context().
504 * The @fs will be modified by mnt_context_set_{source,target,options,fstype}
505 * functions, If the @fs is NULL then all current FS specific setting (source,
506 * target, etc., exclude spec) is reseted.
508 * Returns: 0 on success, negative number in case of error.
510 int mnt_context_set_fs(struct libmnt_context
*cxt
, struct libmnt_fs
*fs
)
514 if (!(cxt
->flags
& MNT_FL_EXTERN_FS
))
515 mnt_free_fs(cxt
->fs
);
517 set_flag(cxt
, MNT_FL_EXTERN_FS
, fs
!= NULL
);
523 * mnt_context_get_fs:
524 * @cxt: mount context
526 * The FS contains the basic description of mountpoint, fs type and so on.
527 * Note that the FS is modified by mnt_context_set_{source,target,options,fstype}
530 * Returns: pointer to FS description or NULL in case of calloc() errrr.
532 struct libmnt_fs
*mnt_context_get_fs(struct libmnt_context
*cxt
)
537 cxt
->fs
= mnt_new_fs();
538 cxt
->flags
&= ~MNT_FL_EXTERN_FS
;
544 * mnt_context_set_source:
545 * @cxt: mount context
546 * @source: mount source (device, directory, UUID, LABEL, ...)
548 * Returns: 0 on success, negative number in case of error.
550 int mnt_context_set_source(struct libmnt_context
*cxt
, const char *source
)
552 return mnt_fs_set_source(mnt_context_get_fs(cxt
), source
);
556 * mnt_context_get_source:
557 * @cxt: mount context
559 * Returns: returns pointer or NULL in case of error pr if not set.
561 const char *mnt_context_get_source(struct libmnt_context
*cxt
)
563 return mnt_fs_get_source(mnt_context_get_fs(cxt
));
567 * mnt_context_set_target:
568 * @cxt: mount context
569 * @target: mountpoint
571 * Returns: 0 on success, negative number in case of error.
573 int mnt_context_set_target(struct libmnt_context
*cxt
, const char *target
)
575 return mnt_fs_set_target(mnt_context_get_fs(cxt
), target
);
579 * mnt_context_get_target:
580 * @cxt: mount context
582 * Returns: returns pointer or NULL in case of error pr if not set.
584 const char *mnt_context_get_target(struct libmnt_context
*cxt
)
586 return mnt_fs_get_target(mnt_context_get_fs(cxt
));
590 * mnt_context_set_fstype:
591 * @cxt: mount context
592 * @fstype: filesystem type
594 * Note that the @fstype has to be the real FS type. For comma-separated list of
595 * filesystems or for "nofs" notation use mnt_context_set_fstype_pattern().
597 * Returns: 0 on success, negative number in case of error.
599 int mnt_context_set_fstype(struct libmnt_context
*cxt
, const char *fstype
)
601 if (fstype
&& strchr(fstype
, ','))
603 return mnt_fs_set_fstype(mnt_context_get_fs(cxt
), fstype
);
607 * mnt_context_get_fstype:
608 * @cxt: mount context
610 * Returns: returns pointer or NULL in case of error pr if not set.
612 const char *mnt_context_get_fstype(struct libmnt_context
*cxt
)
614 return mnt_fs_get_fstype(mnt_context_get_fs(cxt
));
618 * mnt_context_set_options:
619 * @cxt: mount context
620 * @optstr: comma delimited mount options
622 * Returns: 0 on success, negative number in case of error.
624 int mnt_context_set_options(struct libmnt_context
*cxt
, const char *optstr
)
626 return mnt_fs_set_options(mnt_context_get_fs(cxt
), optstr
);
630 * mnt_context_append_options:
631 * @cxt: mount context
632 * @optstr: comma delimited mount options
634 * Returns: 0 on success, negative number in case of error.
636 int mnt_context_append_options(struct libmnt_context
*cxt
, const char *optstr
)
638 return mnt_fs_append_options(mnt_context_get_fs(cxt
), optstr
);
642 * mnt_context_set_fstype_pattern:
643 * @cxt: mount context
644 * @pattern: FS name pattern (or NULL to reset the current setting)
646 * See mount(8), option -t.
648 * Returns: 0 on success, negative number in case of error.
650 int mnt_context_set_fstype_pattern(struct libmnt_context
*cxt
, const char *pattern
)
661 free(cxt
->fstype_pattern
);
662 cxt
->fstype_pattern
= p
;
667 * mnt_context_set_options_pattern:
668 * @cxt: mount context
669 * @pattern: options pattern (or NULL to reset the current setting)
671 * See mount(8), option -O.
673 * Returns: 0 on success, negative number in case of error.
675 int mnt_context_set_options_pattern(struct libmnt_context
*cxt
, const char *pattern
)
686 free(cxt
->optstr_pattern
);
687 cxt
->optstr_pattern
= p
;
692 * mnt_context_set_fstab:
693 * @cxt: mount context
696 * The mount context reads /etc/fstab to the the private struct libmnt_table by default.
697 * This function allows to overwrite the private fstab with an external
698 * instance. Note that the external instance is not deallocated by mnt_free_context().
700 * The fstab is used read-only and is not modified, it should be possible to
701 * share the fstab between more mount contexts (TODO: tests it.)
703 * If the @tb argument is NULL then the current private fstab instance is
706 * Returns: 0 on success, negative number in case of error.
708 int mnt_context_set_fstab(struct libmnt_context
*cxt
, struct libmnt_table
*tb
)
712 if (!(cxt
->flags
& MNT_FL_EXTERN_FSTAB
))
713 mnt_free_table(cxt
->fstab
);
715 set_flag(cxt
, MNT_FL_EXTERN_FSTAB
, tb
!= NULL
);
721 * mnt_context_get_fstab:
722 * @cxt: mount context
725 * See also mnt_table_parse_fstab() for more details about fstab.
727 * Returns: 0 on success, negative number in case of error.
729 int mnt_context_get_fstab(struct libmnt_context
*cxt
, struct libmnt_table
**tb
)
731 struct libmnt_cache
*cache
;
739 cxt
->fstab
= mnt_new_table();
742 if (cxt
->table_errcb
)
743 mnt_table_set_parser_errcb(cxt
->fstab
, cxt
->table_errcb
);
744 cxt
->flags
&= ~MNT_FL_EXTERN_FSTAB
;
745 rc
= mnt_table_parse_fstab(cxt
->fstab
, NULL
);
750 cache
= mnt_context_get_cache(cxt
);
752 /* never touch an external fstab */
753 if (!(cxt
->flags
& MNT_FL_EXTERN_FSTAB
))
754 mnt_table_set_cache(cxt
->fstab
, cache
);
762 * mnt_context_get_mtab:
763 * @cxt: mount context
766 * See also mnt_table_parse_mtab() for more details about mtab/mountinfo. The
767 * result will deallocated by mnt_free_context(@cxt).
769 * Returns: 0 on success, negative number in case of error.
771 int mnt_context_get_mtab(struct libmnt_context
*cxt
, struct libmnt_table
**tb
)
773 struct libmnt_cache
*cache
;
781 cxt
->mtab
= mnt_new_table();
785 if (cxt
->table_errcb
)
786 mnt_table_set_parser_errcb(cxt
->mtab
, cxt
->table_errcb
);
788 rc
= mnt_table_parse_mtab(cxt
->mtab
, cxt
->mtab_path
);
793 cache
= mnt_context_get_cache(cxt
);
794 mnt_table_set_cache(cxt
->mtab
, cache
);
802 * mnt_context_get_table:
803 * @cxt: mount context
804 * @filename: e.g. /proc/self/mountinfo
805 * @tb: returns the table
807 * This function allocates a new table and parses the @file. The parser error
808 * callback and cache for tags and paths is set according to the @cxt setting.
809 * See also mnt_table_parse_file().
811 * It's strongly recommended use mnt_context_get_mtab() and
812 * mnt_context_get_fstab() functions for mtab and fstab files. This function
813 * does not care about LIBMOUNT_* env.variables and does not merge userspace
816 * The result will NOT be deallocated by mnt_free_context(@cxt).
818 * Returns: 0 on success, negative number in case of error.
820 int mnt_context_get_table(struct libmnt_context
*cxt
,
821 const char *filename
, struct libmnt_table
**tb
)
823 struct libmnt_cache
*cache
;
829 *tb
= mnt_new_table();
833 if (cxt
->table_errcb
)
834 mnt_table_set_parser_errcb(*tb
, cxt
->table_errcb
);
836 rc
= mnt_table_parse_file(*tb
, filename
);
842 cache
= mnt_context_get_cache(cxt
);
844 mnt_table_set_cache(*tb
, cache
);
850 * mnt_context_set_tables_errcb
851 * @cxt: mount context
852 * @cb: pointer to callback function
854 * The error callback is used for all tab files (e.g. mtab, fstab)
855 * parsed within the context.
857 * See also mnt_context_get_mtab(),
858 * mnt_context_get_fstab(),
859 * mnt_table_set_parser_errcb().
861 * Returns: 0 on success, negative number in case of error.
863 int mnt_context_set_tables_errcb(struct libmnt_context
*cxt
,
864 int (*cb
)(struct libmnt_table
*tb
, const char *filename
, int line
))
869 cxt
->table_errcb
= cb
;
874 * mnt_context_set_cache:
875 * @cxt: mount context
876 * @cache: cache instance or nULL
878 * The mount context maintains a private struct libmnt_cache by default. This function
879 * allows to overwrite the private cache with an external instance. Note that
880 * the external instance is not deallocated by mnt_free_context().
882 * If the @cache argument is NULL then the current private cache instance is
885 * Returns: 0 on success, negative number in case of error.
887 int mnt_context_set_cache(struct libmnt_context
*cxt
, struct libmnt_cache
*cache
)
891 if (!(cxt
->flags
& MNT_FL_EXTERN_CACHE
))
892 mnt_free_cache(cxt
->cache
);
894 set_flag(cxt
, MNT_FL_EXTERN_CACHE
, cache
!= NULL
);
900 * mnt_context_get_cache
901 * @cxt: mount context
903 * See also mnt_context_set_cache().
905 * Returns: pointer to cache or NULL if canonicalization is disabled.
907 struct libmnt_cache
*mnt_context_get_cache(struct libmnt_context
*cxt
)
909 if (!cxt
|| (cxt
->flags
& MNT_FL_NOCANONICALIZE
))
913 cxt
->cache
= mnt_new_cache();
916 cxt
->flags
&= ~MNT_FL_EXTERN_CACHE
;
922 * mnt_context_set_passwd_cb:
923 * @cxt: mount context
925 * Sets callbacks for encryption password.
927 * Returns: 0 on success, negative number in case of error.
929 int mnt_context_set_passwd_cb(struct libmnt_context
*cxt
,
930 char *(*get
)(struct libmnt_context
*),
931 void (*release
)(struct libmnt_context
*, char *))
936 cxt
->pwd_get_cb
= get
;
937 cxt
->pwd_release_cb
= release
;
942 * mnt_context_get_lock:
943 * @cxt: mount context
945 * The libmount applications don't have to care about mtab locking, but with a
946 * small exception: the application has to be able to remove the lock file when
947 * interrupted by signal or signals have to be ignored when the lock is locked.
949 * The default behavior is to ignore all signals (except SIGALRM and
950 * SIGTRAP for mtab udate) when the lock is locked. If this behavior
951 * is unacceptable then use:
953 * lc = mnt_context_get_lock(cxt);
955 * mnt_lock_block_signals(lc, FALSE);
957 * and don't forget to call mnt_unlock_file(lc) before exit.
959 * Returns: pointer to lock struct or NULL.
961 struct libmnt_lock
*mnt_context_get_lock(struct libmnt_context
*cxt
)
964 * DON'T call this function within libmount, it will always allocate
965 * the lock. The mnt_update_* functions are able to allocate the lock
966 * only when mtab/utab update is really necessary.
968 if (!cxt
|| (cxt
->flags
& MNT_FL_NOMTAB
))
972 cxt
->lock
= mnt_new_lock(cxt
->mtab_writable
?
973 cxt
->mtab_path
: cxt
->utab_path
, 0);
975 mnt_lock_block_signals(cxt
->lock
, TRUE
);
981 * mnt_context_set_mflags:
982 * @cxt: mount context
983 * @flags: mount(2) flags (MS_* flags)
985 * Sets mount flags (see mount(2) man page).
987 * Note that mount context allows to define mount options by mount flags. It
988 * means you can for example use
990 * mnt_context_set_mflags(cxt, MS_NOEXEC | MS_NOSUID);
994 * mnt_context_set_options(cxt, "noexec,nosuid");
996 * these both calls have the same effect.
998 * Returns: 0 on success, negative number in case of error.
1000 int mnt_context_set_mflags(struct libmnt_context
*cxt
, unsigned long flags
)
1004 cxt
->mountflags
= flags
;
1009 * mnt_context_get_mflags:
1010 * @cxt: mount context
1011 * @flags: returns MS_* mount flags
1013 * Converts mount options string to MS_* flags and bitewise-OR the result with
1014 * already defined flags (see mnt_context_set_mflags()).
1016 * Returns: 0 on success, negative number in case of error.
1018 int mnt_context_get_mflags(struct libmnt_context
*cxt
, unsigned long *flags
)
1025 if (!(cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
) && cxt
->fs
) {
1026 const char *o
= mnt_fs_get_options(cxt
->fs
);
1028 rc
= mnt_optstr_get_flags(o
, flags
,
1029 mnt_get_builtin_optmap(MNT_LINUX_MAP
));
1032 *flags
|= cxt
->mountflags
;
1037 * mnt_context_set_user_mflags:
1038 * @cxt: mount context
1039 * @flags: mount(2) flags (MNT_MS_* flags, e.g. MNT_MS_LOOP)
1041 * Sets userspace mount flags.
1043 * See also notest for mnt_context_set_mflags().
1045 * Returns: 0 on success, negative number in case of error.
1047 int mnt_context_set_user_mflags(struct libmnt_context
*cxt
, unsigned long flags
)
1051 cxt
->user_mountflags
= flags
;
1056 * mnt_context_get_user_mflags:
1057 * @cxt: mount context
1058 * @flags: returns mount flags
1060 * Converts mount options string to MNT_MS_* flags and bitewise-OR the result
1061 * with already defined flags (see mnt_context_set_user_mflags()).
1063 * Returns: 0 on success, negative number in case of error.
1065 int mnt_context_get_user_mflags(struct libmnt_context
*cxt
, unsigned long *flags
)
1072 if (!(cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
) && cxt
->fs
) {
1073 const char *o
= mnt_fs_get_user_options(cxt
->fs
);
1075 rc
= mnt_optstr_get_flags(o
, flags
,
1076 mnt_get_builtin_optmap(MNT_USERSPACE_MAP
));
1079 *flags
|= cxt
->user_mountflags
;
1084 * mnt_context_set_mountdata:
1085 * @cxt: mount context
1086 * @data: mount(2) data
1088 * The mount context generates mountdata from mount options by default. This
1089 * function allows to overwrite this behavior, and @data will be used instead
1092 * The libmount does not deallocated the data by mnt_free_context(). Note that
1093 * NULL is also valid mount data.
1095 * Returns: 0 on success, negative number in case of error.
1097 int mnt_context_set_mountdata(struct libmnt_context
*cxt
, void *data
)
1101 cxt
->mountdata
= data
;
1102 cxt
->flags
|= MNT_FL_MOUNTDATA
;
1107 * Translates LABEL/UUID/path to mountable path
1109 int mnt_context_prepare_srcpath(struct libmnt_context
*cxt
)
1111 const char *path
= NULL
;
1112 struct libmnt_cache
*cache
;
1113 const char *t
, *v
, *src
;
1118 assert((cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
));
1120 if (!cxt
|| !cxt
->fs
)
1123 DBG(CXT
, mnt_debug_h(cxt
, "preparing source path"));
1125 src
= mnt_fs_get_source(cxt
->fs
);
1127 /* ignore filesystems without source or filesystems
1128 * where the source is quasi-path (//foo/bar)
1130 if (!src
|| mnt_fs_is_netfs(cxt
->fs
))
1133 DBG(CXT
, mnt_debug_h(cxt
, "srcpath '%s'", src
));
1135 cache
= mnt_context_get_cache(cxt
);
1137 if (!mnt_fs_get_tag(cxt
->fs
, &t
, &v
)) {
1139 * Source is TAG (evaluate)
1142 path
= mnt_resolve_tag(t
, v
, cache
);
1144 rc
= path
? mnt_fs_set_source(cxt
->fs
, path
) : -EINVAL
;
1146 } else if (cache
&& !mnt_fs_is_pseudofs(cxt
->fs
)) {
1148 * Source is PATH (canonicalize)
1150 path
= mnt_resolve_path(src
, cache
);
1151 if (path
&& strcmp(path
, src
))
1152 rc
= mnt_fs_set_source(cxt
->fs
, path
);
1156 DBG(CXT
, mnt_debug_h(cxt
, "failed to prepare srcpath [rc=%d]", rc
));
1163 if ((cxt
->mountflags
& (MS_BIND
| MS_MOVE
| MS_PROPAGATION
)) ||
1164 mnt_fs_is_pseudofs(cxt
->fs
)) {
1165 DBG(CXT
, mnt_debug_h(cxt
, "PROPAGATION/pseudo FS source: %s", path
));
1170 * Initialize loop device
1172 if (mnt_context_is_loopdev(cxt
)) {
1173 rc
= mnt_context_setup_loopdev(cxt
);
1178 DBG(CXT
, mnt_debug_h(cxt
, "final srcpath '%s'",
1179 mnt_fs_get_source(cxt
->fs
)));
1183 int mnt_context_prepare_target(struct libmnt_context
*cxt
)
1186 struct libmnt_cache
*cache
;
1191 assert((cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
));
1193 if (!cxt
|| !cxt
->fs
)
1196 DBG(CXT
, mnt_debug_h(cxt
, "preparing target path"));
1198 tgt
= mnt_fs_get_target(cxt
->fs
);
1202 cache
= mnt_context_get_cache(cxt
);
1204 char *path
= mnt_resolve_path(tgt
, cache
);
1205 if (strcmp(path
, tgt
))
1206 rc
= mnt_fs_set_target(cxt
->fs
, path
);
1210 DBG(CXT
, mnt_debug_h(cxt
, "failed to prepare target '%s'", tgt
));
1212 DBG(CXT
, mnt_debug_h(cxt
, "final target '%s'",
1213 mnt_fs_get_target(cxt
->fs
)));
1217 int mnt_context_guess_fstype(struct libmnt_context
*cxt
)
1225 assert((cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
));
1227 if (!cxt
|| !cxt
->fs
)
1230 if (cxt
->mountflags
& (MS_BIND
| MS_MOVE
| MS_PROPAGATION
))
1233 type
= (char *) mnt_fs_get_fstype(cxt
->fs
);
1234 if (type
&& !strcmp(type
, "auto")) {
1235 mnt_fs_set_fstype(cxt
->fs
, NULL
);
1241 if (cxt
->flags
& MS_REMOUNT
)
1243 if (cxt
->fstype_pattern
)
1246 dev
= mnt_fs_get_srcpath(cxt
->fs
);
1250 if (access(dev
, F_OK
) == 0) {
1251 struct libmnt_cache
*cache
= mnt_context_get_cache(cxt
);
1253 type
= mnt_get_fstype(dev
, &cxt
->ambi
, cache
);
1255 rc
= mnt_fs_set_fstype(cxt
->fs
, type
);
1257 free(type
); /* type is not cached */
1260 if (strchr(dev
, ':') != NULL
)
1261 rc
= mnt_fs_set_fstype(cxt
->fs
, "nfs");
1262 else if (!strncmp(dev
, "//", 2))
1263 rc
= mnt_fs_set_fstype(cxt
->fs
, "cifs");
1268 DBG(CXT
, mnt_debug_h(cxt
, "FS type: %s",
1269 mnt_fs_get_fstype(cxt
->fs
)));
1272 return mnt_fs_set_fstype(cxt
->fs
, "none");
1274 DBG(CXT
, mnt_debug_h(cxt
, "failed to detect FS type"));
1279 * The default is to use fstype from cxt->fs, this could be overwritten by
1280 * @type. The @act is MNT_ACT_{MOUNT,UMOUNT}.
1282 * Returns: 0 on success or negative number in case of error. Note that success
1283 * does not mean that there is any usable helper, you have to check cxt->helper.
1285 int mnt_context_prepare_helper(struct libmnt_context
*cxt
, const char *name
,
1288 char search_path
[] = FS_SEARCH_PATH
; /* from config.h */
1289 char *p
= NULL
, *path
;
1293 assert((cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
));
1296 type
= mnt_fs_get_fstype(cxt
->fs
);
1298 if ((cxt
->flags
& MNT_FL_NOHELPERS
) || !type
||
1299 !strcmp(type
, "none") || mnt_fs_is_swaparea(cxt
->fs
))
1302 path
= strtok_r(search_path
, ":", &p
);
1304 char helper
[PATH_MAX
];
1308 rc
= snprintf(helper
, sizeof(helper
), "%s/%s.%s",
1310 path
= strtok_r(NULL
, ":", &p
);
1312 if (rc
< 0 || (size_t) rc
>= sizeof(helper
))
1315 rc
= stat(helper
, &st
);
1316 if (rc
== -1 && errno
== ENOENT
&& strchr(type
, '.')) {
1317 /* If type ends with ".subtype" try without it */
1318 *strrchr(helper
, '.') = '\0';
1319 rc
= stat(helper
, &st
);
1322 DBG(CXT
, mnt_debug_h(cxt
, "%-25s ... %s", helper
,
1323 rc
? "not found" : "found"));
1328 cxt
->helper
= strdup(helper
);
1337 int mnt_context_merge_mflags(struct libmnt_context
*cxt
)
1339 unsigned long fl
= 0;
1344 DBG(CXT
, mnt_debug_h(cxt
, "merging mount flags"));
1346 rc
= mnt_context_get_mflags(cxt
, &fl
);
1349 cxt
->mountflags
= fl
;
1351 /* TODO: if cxt->fs->fs_optstr contains 'ro' then set the MS_RDONLY to
1352 * mount flags, it's possible that superblock is read-only, but VFS is
1357 rc
= mnt_context_get_user_mflags(cxt
, &fl
);
1360 cxt
->user_mountflags
= fl
;
1362 DBG(CXT
, mnt_debug_h(cxt
, "final flags: VFS=%08lx user=%08lx",
1363 cxt
->mountflags
, cxt
->user_mountflags
));
1365 cxt
->flags
|= MNT_FL_MOUNTFLAGS_MERGED
;
1370 * Prepare /etc/mtab or /run/mount/utab
1372 int mnt_context_prepare_update(struct libmnt_context
*cxt
)
1379 assert(cxt
->action
);
1380 assert((cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
));
1382 DBG(CXT
, mnt_debug_h(cxt
, "prepare update"));
1384 if (cxt
->mountflags
& MS_PROPAGATION
) {
1385 DBG(CXT
, mnt_debug_h(cxt
, "skip update: MS_PROPAGATION"));
1389 target
= mnt_fs_get_target(cxt
->fs
);
1391 if (cxt
->action
== MNT_ACT_UMOUNT
&& target
&& !strcmp(target
, "/"))
1392 /* Don't try to touch mtab if umounting root FS */
1393 cxt
->flags
|= MNT_FL_NOMTAB
;
1395 if (cxt
->flags
& MNT_FL_NOMTAB
) {
1396 DBG(CXT
, mnt_debug_h(cxt
, "skip update: NOMTAB flag"));
1400 DBG(CXT
, mnt_debug_h(cxt
, "skip update: external helper"));
1403 if (!cxt
->mtab_writable
&& !cxt
->utab_writable
) {
1404 DBG(CXT
, mnt_debug_h(cxt
, "skip update: no writable destination"));
1407 /* 0 = success, 1 = not called yet */
1408 if (cxt
->syscall_status
!= 1 && cxt
->syscall_status
!= 0) {
1409 DBG(CXT
, mnt_debug_h(cxt
,
1410 "skip update: syscall failed [status=%d]",
1411 cxt
->syscall_status
));
1415 cxt
->update
= mnt_new_update();
1419 mnt_update_set_filename(cxt
->update
,
1420 cxt
->mtab_writable
? cxt
->mtab_path
: cxt
->utab_path
,
1421 !cxt
->mtab_writable
);
1424 if (cxt
->action
== MNT_ACT_UMOUNT
)
1425 rc
= mnt_update_set_fs(cxt
->update
, cxt
->mountflags
,
1426 mnt_context_get_target(cxt
), NULL
);
1428 rc
= mnt_update_set_fs(cxt
->update
, cxt
->mountflags
,
1431 return rc
< 0 ? rc
: 0;
1434 int mnt_context_update_tabs(struct libmnt_context
*cxt
)
1440 if (cxt
->flags
& MNT_FL_NOMTAB
) {
1441 DBG(CXT
, mnt_debug_h(cxt
, "don't update: NOMTAB flag"));
1445 DBG(CXT
, mnt_debug_h(cxt
, "don't update: external helper"));
1448 if (!cxt
->update
|| !mnt_update_is_ready(cxt
->update
)) {
1449 DBG(CXT
, mnt_debug_h(cxt
, "don't update: no update prepared"));
1452 if (cxt
->syscall_status
) {
1453 DBG(CXT
, mnt_debug_h(cxt
, "don't update: syscall failed/not called"));
1457 fl
= mnt_update_get_mflags(cxt
->update
);
1458 if ((cxt
->mountflags
& MS_RDONLY
) != (fl
& MS_RDONLY
))
1460 * fix MS_RDONLY in options
1462 mnt_update_force_rdonly(cxt
->update
,
1463 cxt
->mountflags
& MS_RDONLY
);
1465 return mnt_update_table(cxt
->update
, cxt
->lock
);
1468 static int apply_table(struct libmnt_context
*cxt
, struct libmnt_table
*tb
,
1471 struct libmnt_fs
*fs
= NULL
;
1472 const char *src
= NULL
, *tgt
= NULL
;
1481 src
= mnt_fs_get_source(cxt
->fs
);
1482 tgt
= mnt_fs_get_target(cxt
->fs
);
1485 fs
= mnt_table_find_pair(tb
, src
, tgt
, direction
);
1488 fs
= mnt_table_find_source(tb
, src
, direction
);
1490 fs
= mnt_table_find_target(tb
, tgt
, direction
);
1493 /* swap source and target (if @src is not LABEL/UUID),
1498 * the path could be a mountpoint as well as source (for
1499 * example bind mount, symlink to device, ...).
1501 if (src
&& !mnt_fs_get_tag(cxt
->fs
, NULL
, NULL
))
1502 fs
= mnt_table_find_target(tb
, src
, direction
);
1504 fs
= mnt_table_find_source(tb
, tgt
, direction
);
1511 DBG(CXT
, mnt_debug_h(cxt
, "apply entry:"));
1512 DBG(CXT
, mnt_fs_print_debug(fs
, stderr
));
1514 /* copy from tab to our FS description
1516 rc
= mnt_fs_set_source(cxt
->fs
, mnt_fs_get_source(fs
));
1518 rc
= mnt_fs_set_target(cxt
->fs
, mnt_fs_get_target(fs
));
1520 if (!rc
&& !mnt_fs_get_fstype(cxt
->fs
))
1521 rc
= mnt_fs_set_fstype(cxt
->fs
, mnt_fs_get_fstype(fs
));
1526 if (cxt
->optsmode
& MNT_OMODE_IGNORE
)
1528 else if (cxt
->optsmode
& MNT_OMODE_REPLACE
)
1529 rc
= mnt_fs_set_options(cxt
->fs
, mnt_fs_get_options(fs
));
1531 else if (cxt
->optsmode
& MNT_OMODE_APPEND
)
1532 rc
= mnt_fs_append_options(cxt
->fs
, mnt_fs_get_options(fs
));
1534 else if (cxt
->optsmode
& MNT_OMODE_PREPEND
)
1535 rc
= mnt_fs_prepend_options(cxt
->fs
, mnt_fs_get_options(fs
));
1538 cxt
->flags
|= MNT_FL_TAB_APPLIED
;
1543 * mnt_context_apply_fstab:
1544 * @cxt: mount context
1546 * This function is optional.
1548 * Returns: 0 on success, negative number in case of error.
1550 int mnt_context_apply_fstab(struct libmnt_context
*cxt
)
1553 struct libmnt_table
*tab
= NULL
;
1554 const char *src
= NULL
, *tgt
= NULL
;
1562 if (cxt
->flags
& MNT_FL_TAB_APPLIED
)
1565 if (mnt_context_is_restricted(cxt
)) {
1566 DBG(CXT
, mnt_debug_h(cxt
, "force fstab usage for non-root users!"));
1567 cxt
->optsmode
= MNT_OMODE_USER
;
1568 } else if (cxt
->optsmode
== 0) {
1569 DBG(CXT
, mnt_debug_h(cxt
, "use default optmode"));
1570 cxt
->optsmode
= MNT_OMODE_AUTO
;
1575 src
= mnt_fs_get_source(cxt
->fs
);
1576 tgt
= mnt_fs_get_target(cxt
->fs
);
1579 DBG(CXT
, mnt_debug_h(cxt
, "OPTSMODE: ignore=%d, append=%d, prepend=%d, "
1580 "replace=%d, force=%d, fstab=%d, mtab=%d",
1581 cxt
->optsmode
& MNT_OMODE_IGNORE
? 1 : 0,
1582 cxt
->optsmode
& MNT_OMODE_APPEND
? 1 : 0,
1583 cxt
->optsmode
& MNT_OMODE_PREPEND
? 1 : 0,
1584 cxt
->optsmode
& MNT_OMODE_REPLACE
? 1 : 0,
1585 cxt
->optsmode
& MNT_OMODE_FORCE
? 1 : 0,
1586 cxt
->optsmode
& MNT_OMODE_FSTAB
? 1 : 0,
1587 cxt
->optsmode
& MNT_OMODE_MTAB
? 1 : 0));
1589 /* fstab is not required if source and target are specified */
1590 if (src
&& tgt
&& !(cxt
->optsmode
& MNT_OMODE_FORCE
)) {
1591 DBG(CXT
, mnt_debug_h(cxt
, "fstab not required -- skip"));
1595 DBG(CXT
, mnt_debug_h(cxt
,
1596 "trying to apply fstab (src=%s, target=%s)", src
, tgt
));
1598 /* let's initialize cxt->fs */
1599 mnt_context_get_fs(cxt
);
1602 if (cxt
->optsmode
& MNT_OMODE_FSTAB
) {
1603 rc
= mnt_context_get_fstab(cxt
, &tab
);
1605 rc
= apply_table(cxt
, tab
, MNT_ITER_FORWARD
);
1609 if (rc
< 0 && (cxt
->optsmode
& MNT_OMODE_MTAB
)) {
1610 DBG(CXT
, mnt_debug_h(cxt
, "trying to apply from mtab"));
1611 rc
= mnt_context_get_mtab(cxt
, &tab
);
1613 rc
= apply_table(cxt
, tab
, MNT_ITER_BACKWARD
);
1616 DBG(CXT
, mnt_debug_h(cxt
, "failed to find entry in fstab/mtab"));
1621 * mnt_context_get_status:
1622 * @cxt: mount context
1624 * Global libmount status.
1626 * The real exit code of the mount.type helper has to be tested by
1627 * mnt_context_get_helper_status(). The mnt_context_get_status() only inform
1628 * that exec() has been sucessful.
1630 * Returns: 1 if mount.type or mount(2) syscall has been succesfully called.
1632 int mnt_context_get_status(struct libmnt_context
*cxt
)
1634 return cxt
&& (!cxt
->syscall_status
|| !cxt
->helper_exec_status
);
1638 * mnt_context_helper_executed:
1639 * @cxt: mount context
1641 * Returns: 1 if mount.type helper has been executed, or 0.
1643 int mnt_context_helper_executed(struct libmnt_context
*cxt
)
1645 return cxt
->helper_exec_status
!= 1;
1649 * mnt_context_get_helper_status:
1650 * @cxt: mount context
1652 * Return: mount.<type> exit status, result is reliable only if
1653 * mnt_context_helper_executed() returns 1.
1655 int mnt_context_get_helper_status(struct libmnt_context
*cxt
)
1657 return cxt
->helper_status
;
1661 * mnt_context_syscall_called:
1662 * @cxt: mount context
1664 * Returns: 1 if mount(2) syscall has been called, or 0.
1666 int mnt_context_syscall_called(struct libmnt_context
*cxt
)
1668 return cxt
->syscall_status
!= 1;
1672 * mnt_context_get_syscall_errno:
1673 * @cxt: mount context
1675 * The result from this function is reliable only if
1676 * mnt_context_syscall_called() returns 1.
1678 * Returns: mount(2) errno if the syscall failed or 0.
1680 int mnt_context_get_syscall_errno(struct libmnt_context
*cxt
)
1682 if (cxt
->syscall_status
< 0)
1683 return -cxt
->syscall_status
;
1689 * mnt_context_set_syscall_status:
1690 * @cxt: mount context
1691 * @status: mount(2) status
1693 * The @status should be 0 on success, or negative number on error (-errno).
1695 * This function should be used only if [u]mount(2) syscall is NOT called by
1698 * Returns: 0 or negative number in case of error.
1700 int mnt_context_set_syscall_status(struct libmnt_context
*cxt
, int status
)
1705 DBG(CXT
, mnt_debug_h(cxt
, "syscall status set to: %d", status
));
1706 cxt
->syscall_status
= status
;
1711 * mnt_context_strerror
1714 * @bufsiz: size of the buffer
1716 * Not implemented yet.
1718 * Returns: 0 or negative number in case of error.
1720 int mnt_context_strerror(struct libmnt_context
*cxt
__attribute__((__unused__
)),
1721 char *buf
__attribute__((__unused__
)),
1722 size_t bufsiz
__attribute__((__unused__
)))
1724 /* TODO: based on cxt->syscall_errno or cxt->helper_status */
1729 * mnt_context_init_helper
1730 * @cxt: mount context
1731 * @action: MNT_ACT_{UMOUNT,MOUNT}
1732 * @flags: not used now
1734 * This function infors libmount that used from [u]mount.type helper.
1736 * The function also calls mnt_context_disable_helpers() to avoid recursive
1737 * mount.type helpers calling. It you really want to call another
1738 * mount.type helper from your helper than you have to explicitly enable this
1741 * mnt_context_disable_helpers(cxt, FALSE);
1743 * Returns: 0 on success, negative number in case of error.
1745 int mnt_context_init_helper(struct libmnt_context
*cxt
, int action
,
1746 int flags
__attribute__((__unused__
)))
1748 int rc
= mnt_context_disable_helpers(cxt
, TRUE
);
1751 rc
= set_flag(cxt
, MNT_FL_HELPER
, 1);
1753 cxt
->action
= action
;
1755 DBG(CXT
, mnt_debug_h(cxt
, "initialized for [u]mount.<type> helper [rc=%d]", rc
));
1760 * mnt_context_helper_setopt:
1762 * @c: getopt() result
1763 * @arg: getopt() optarg
1765 * This function applies [u]mount.type command line option (for example parsed
1766 * by getopt or getopt_long) to @cxt. All unknown options are ignored and
1767 * then 1 is returned.
1769 * Returns: negative number on error, 1 if @c is unknown option, 0 on success.
1771 int mnt_context_helper_setopt(struct libmnt_context
*cxt
, int c
, char *arg
)
1774 switch(cxt
->action
) {
1776 return mnt_context_mount_setopt(cxt
, c
, arg
);
1777 case MNT_ACT_UMOUNT
:
1778 return mnt_context_umount_setopt(cxt
, c
, arg
);
1785 * mnt_context_is_fs_mounted:
1788 * @mounted: returns 1 for mounted and 0 for non-mounted filesystems
1790 * Returns: 0 on success and negative number in case of error.
1792 int mnt_context_is_fs_mounted(struct libmnt_context
*cxt
,
1793 struct libmnt_fs
*fs
, int *mounted
)
1795 struct libmnt_table
*mtab
;
1798 if (!cxt
|| !fs
|| !mounted
)
1801 rc
= mnt_context_get_mtab(cxt
, &mtab
);
1805 *mounted
= mnt_table_is_fs_mounted(mtab
, fs
);
1809 static int mnt_context_add_child(struct libmnt_context
*cxt
, pid_t pid
)
1816 pids
= realloc(cxt
->children
, sizeof(pid_t
) * cxt
->nchildren
+ 1);
1820 DBG(CXT
, mnt_debug_h(cxt
, "add new child %d", pid
));
1821 cxt
->children
= pids
;
1822 cxt
->children
[cxt
->nchildren
++] = pid
;
1827 int mnt_fork_context(struct libmnt_context
*cxt
)
1832 if (!mnt_context_is_parent(cxt
))
1835 DBG(CXT
, mnt_debug_h(cxt
, "forking context"));
1842 case -1: /* error */
1843 DBG(CXT
, mnt_debug_h(cxt
, "fork failed %m"));
1847 cxt
->pid
= getpid();
1848 cxt
->flags
&= ~MNT_FL_FORK
;
1849 DBG(CXT
, mnt_debug_h(cxt
, "child created"));
1853 rc
= mnt_context_add_child(cxt
, pid
);
1860 int mnt_context_wait_for_children(struct libmnt_context
*cxt
,
1861 int *nchildren
, int *nerrs
)
1868 assert(mnt_context_is_parent(cxt
));
1870 for (i
= 0; i
< cxt
->nchildren
; i
++) {
1871 pid_t pid
= cxt
->children
[i
];
1872 int rc
= 0, ret
= 0;
1877 DBG(CXT
, mnt_debug_h(cxt
,
1878 "waiting for child (%d/%d): %d",
1879 i
+ 1, cxt
->nchildren
, pid
));
1881 rc
= waitpid(pid
, &ret
, 0);
1883 } while (rc
== -1 && errno
== EINTR
);
1888 if (rc
!= -1 && nerrs
) {
1890 (*nerrs
) += WEXITSTATUS(ret
) == 0 ? 0 : 1;
1894 cxt
->children
[i
] = 0;
1898 free(cxt
->children
);
1899 cxt
->children
= NULL
;
1903 int mnt_context_is_fork(struct libmnt_context
*cxt
)
1905 return cxt
&& (cxt
->flags
& MNT_FL_FORK
);
1909 int mnt_context_is_parent(struct libmnt_context
*cxt
)
1911 return mnt_context_is_fork(cxt
) && cxt
->pid
== 0;
1914 int mnt_context_is_child(struct libmnt_context
*cxt
)
1916 return !mnt_context_is_fork(cxt
) && cxt
->pid
;
1921 struct libmnt_lock
*lock
;
1923 static void lock_fallback(void)
1926 mnt_unlock_file(lock
);
1929 int test_mount(struct libmnt_test
*ts
, int argc
, char *argv
[])
1931 int idx
= 1, rc
= 0;
1932 struct libmnt_context
*cxt
;
1937 cxt
= mnt_new_context();
1941 if (!strcmp(argv
[idx
], "-o")) {
1942 mnt_context_set_options(cxt
, argv
[idx
+ 1]);
1945 if (!strcmp(argv
[idx
], "-t")) {
1946 /* TODO: use mnt_context_set_fstype_pattern() */
1947 mnt_context_set_fstype(cxt
, argv
[idx
+ 1]);
1951 if (argc
== idx
+ 1)
1952 /* mount <mountpont>|<device> */
1953 mnt_context_set_target(cxt
, argv
[idx
++]);
1955 else if (argc
== idx
+ 2) {
1956 /* mount <device> <mountpoint> */
1957 mnt_context_set_source(cxt
, argv
[idx
++]);
1958 mnt_context_set_target(cxt
, argv
[idx
++]);
1961 /* this is unnecessary -- libmount is able to internaly
1962 * create and manage the lock
1964 lock
= mnt_context_get_lock(cxt
);
1966 atexit(lock_fallback
);
1968 rc
= mnt_context_mount(cxt
);
1970 printf("failed to mount: %m\n");
1972 printf("successfully mounted\n");
1974 mnt_free_context(cxt
);
1978 int test_umount(struct libmnt_test
*ts
, int argc
, char *argv
[])
1980 int idx
= 1, rc
= 0;
1981 struct libmnt_context
*cxt
;
1986 cxt
= mnt_new_context();
1990 if (!strcmp(argv
[idx
], "-t")) {
1991 mnt_context_set_fstype(cxt
, argv
[idx
+ 1]);
1995 if (!strcmp(argv
[idx
], "-f")) {
1996 mnt_context_enable_force(cxt
, TRUE
);
2000 if (!strcmp(argv
[idx
], "-l")) {
2001 mnt_context_enable_lazy(cxt
, TRUE
);
2005 if (!strcmp(argv
[idx
], "-r")) {
2006 mnt_context_enable_rdonly_umount(cxt
, TRUE
);
2010 if (argc
== idx
+ 1) {
2011 /* mount <mountpont>|<device> */
2012 mnt_context_set_target(cxt
, argv
[idx
++]);
2018 lock
= mnt_context_get_lock(cxt
);
2020 atexit(lock_fallback
);
2022 rc
= mnt_context_umount(cxt
);
2024 printf("failed to umount\n");
2026 printf("successfully umounted\n");
2028 mnt_free_context(cxt
);
2032 int test_flags(struct libmnt_test
*ts
, int argc
, char *argv
[])
2034 int idx
= 1, rc
= 0;
2035 struct libmnt_context
*cxt
;
2036 const char *opt
= NULL
;
2037 unsigned long flags
= 0;
2042 cxt
= mnt_new_context();
2046 if (!strcmp(argv
[idx
], "-o")) {
2047 mnt_context_set_options(cxt
, argv
[idx
+ 1]);
2051 if (argc
== idx
+ 1)
2052 /* mount <mountpont>|<device> */
2053 mnt_context_set_target(cxt
, argv
[idx
++]);
2055 rc
= mnt_context_prepare_mount(cxt
);
2057 printf("failed to prepare mount %s\n", strerror(-rc
));
2059 opt
= mnt_fs_get_options(cxt
->fs
);
2061 fprintf(stdout
, "options: %s\n", opt
);
2063 mnt_context_get_mflags(cxt
, &flags
);
2064 fprintf(stdout
, "flags: %08lx\n", flags
);
2066 mnt_free_context(cxt
);
2070 int test_mountall(struct libmnt_test
*ts
, int argc
, char *argv
[])
2072 struct libmnt_context
*cxt
;
2073 struct libmnt_iter
*itr
;
2074 struct libmnt_fs
*fs
;
2075 int mntrc
, ignored
, idx
= 1;
2077 cxt
= mnt_new_context();
2078 itr
= mnt_new_iter(MNT_ITER_FORWARD
);
2084 if (!strcmp(argv
[idx
], "-O")) {
2085 mnt_context_set_options_pattern(cxt
, argv
[idx
+ 1]);
2088 if (!strcmp(argv
[idx
], "-t")) {
2089 mnt_context_set_fstype_pattern(cxt
, argv
[idx
+ 1]);
2094 while (mnt_context_next_mount(cxt
, itr
, &fs
, &mntrc
, &ignored
) == 0) {
2096 const char *tgt
= mnt_fs_get_target(fs
);
2099 printf("%s: ignored: not match\n", tgt
);
2100 else if (ignored
== 2)
2101 printf("%s: ignored: already mounted\n", tgt
);
2103 else if (!mnt_context_get_status(cxt
)) {
2106 warn("%s: mount failed", tgt
);
2108 warnx("%s: mount failed", tgt
);
2110 printf("%s: successfully mounted\n", tgt
);
2113 mnt_free_context(cxt
);
2117 int main(int argc
, char *argv
[])
2119 struct libmnt_test tss
[] = {
2120 { "--mount", test_mount
, "[-o <opts>] [-t <type>] <spec>|<src> <target>" },
2121 { "--umount", test_umount
, "[-t <type>] [-f][-l][-r] <src>|<target>" },
2122 { "--mount-all", test_mountall
, "[-O <pattern>] [-t <pattern] mount all filesystems from fstab" },
2123 { "--flags", test_flags
, "[-o <opts>] <spec>" },
2126 umask(S_IWGRP
|S_IWOTH
); /* to be compatible with mount(8) */
2128 return mnt_run_test(tss
, argc
, argv
);
2131 #endif /* TEST_PROGRAM */