]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - libmount/src/context.c
2 * Copyright (C) 2010,2011,2012 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
);
156 mnt_context_set_tabfilter(cxt
, NULL
, NULL
);
158 /* restore non-resetable flags */
159 cxt
->flags
|= (fl
& MNT_FL_EXTERN_FSTAB
);
160 cxt
->flags
|= (fl
& MNT_FL_EXTERN_CACHE
);
161 cxt
->flags
|= (fl
& MNT_FL_NOMTAB
);
162 cxt
->flags
|= (fl
& MNT_FL_FAKE
);
163 cxt
->flags
|= (fl
& MNT_FL_SLOPPY
);
164 cxt
->flags
|= (fl
& MNT_FL_VERBOSE
);
165 cxt
->flags
|= (fl
& MNT_FL_NOHELPERS
);
166 cxt
->flags
|= (fl
& MNT_FL_LOOPDEL
);
167 cxt
->flags
|= (fl
& MNT_FL_LAZY
);
168 cxt
->flags
|= (fl
& MNT_FL_FORK
);
169 cxt
->flags
|= (fl
& MNT_FL_FORCE
);
170 cxt
->flags
|= (fl
& MNT_FL_NOCANONICALIZE
);
171 cxt
->flags
|= (fl
& MNT_FL_RDONLY_UMOUNT
);
172 cxt
->flags
|= (fl
& MNT_FL_NOSWAPMATCH
);
177 * mnt_context_reset_status:
180 * Resets mount(2) and mount.type statuses, so mnt_context_do_mount() or
181 * mnt_context_do_umount() could be again called with the same settings.
183 * BE CAREFUL -- after this soft reset the libmount will NOT parse mount
184 * options, evaluate permissions or apply stuff from fstab.
186 * Returns: 0 on success, negative number in case of error.
188 int mnt_context_reset_status(struct libmnt_context
*cxt
)
193 cxt
->syscall_status
= 1; /* means not called yet */
194 cxt
->helper_exec_status
= 1;
195 cxt
->helper_status
= 0;
199 static int set_flag(struct libmnt_context
*cxt
, int flag
, int enable
)
204 DBG(CXT
, mnt_debug_h(cxt
, "enabling flag %04x", flag
));
207 DBG(CXT
, mnt_debug_h(cxt
, "disabling flag %04x", flag
));
214 * mnt_context_is_restricted:
215 * @cxt: mount context
217 * Returns: 0 for unrestricted mount (user is root), or 1 for non-root mounts
219 int mnt_context_is_restricted(struct libmnt_context
*cxt
)
222 return cxt
->restricted
;
226 * mnt_context_set_optsmode
227 * @cxt: mount context
228 * @mode: MNT_OMASK_* flags
230 * Controls how to use mount optionsmsource and target paths from fstab/mtab.
232 * @MNT_OMODE_IGNORE: ignore mtab/fstab options
234 * @MNT_OMODE_APPEND: append mtab/fstab options to existing options
236 * @MNT_OMODE_PREPEND: prepend mtab/fstab options to existing options
238 * @MNT_OMODE_REPLACE: replace existing options with options from mtab/fstab
240 * @MNT_OMODE_FORCE: always read mtab/fstab (although source and target is defined)
242 * @MNT_OMODE_FSTAB: read from fstab
244 * @MNT_OMODE_MTAB: read from mtab if fstab not enabled or failed
246 * @MNT_OMODE_NOTAB: do not read fstab/mtab at all
248 * @MNT_OMODE_AUTO: default mode (MNT_OMODE_PREPEND | MNT_OMODE_FSTAB | MNT_OMODE_MTAB)
250 * @MNT_OMODE_USER: default for non-root users (MNT_OMODE_REPLACE | MNT_OMODE_FORCE | MNT_OMODE_FSTAB)
254 * - MNT_OMODE_USER is always used if mount context is in restricted mode
255 * - MNT_OMODE_AUTO is used if nothing other is defined
256 * - the flags are eavaluated in this order: MNT_OMODE_NOTAB, MNT_OMODE_FORCE,
257 * MNT_OMODE_FSTAB, MNT_OMODE_MTAB and then the mount options from fstab/mtab
258 * are set according to MNT_OMODE_{IGNORE,APPEND,PREPAND,REPLACE}
260 * Returns: 0 on success, negative number in case of error.
262 int mnt_context_set_optsmode(struct libmnt_context
*cxt
, int mode
)
266 cxt
->optsmode
= mode
;
271 * mnt_context_get_optsmode
272 * @cxt: mount context
274 * Returns: MNT_OMASK_* mask or zero.
277 int mnt_context_get_optsmode(struct libmnt_context
*cxt
)
279 return cxt
? cxt
->optsmode
: 0;
283 * mnt_context_disable_canonicalize:
284 * @cxt: mount context
285 * @disable: TRUE or FALSE
287 * Enable/disable paths canonicalization and tags evaluation. The libmount context
288 * canonicalies paths when search in fstab and when prepare source and target paths
289 * for mount(2) syscall.
291 * This fuction has effect to the private (within context) fstab instance only
292 * (see mnt_context_set_fstab()). If you want to use an external fstab then you
293 * need manage your private struct libmnt_cache (see mnt_table_set_cache(fstab,
296 * Returns: 0 on success, negative number in case of error.
298 int mnt_context_disable_canonicalize(struct libmnt_context
*cxt
, int disable
)
300 return set_flag(cxt
, MNT_FL_NOCANONICALIZE
, disable
);
304 * mnt_context_is_nocanonicalize:
305 * @cxt: mount context
307 * Returns: 1 if no-canonicalize mode enabled or 0.
309 int mnt_context_is_nocanonicalize(struct libmnt_context
*cxt
)
311 return cxt
&& (cxt
->flags
& MNT_FL_NOCANONICALIZE
) ? 1 : 0;
315 * mnt_context_enable_lazy:
316 * @cxt: mount context
317 * @enable: TRUE or FALSE
319 * Enable/disable lazy umount (see umount(8) man page, option -l).
321 * Returns: 0 on success, negative number in case of error.
323 int mnt_context_enable_lazy(struct libmnt_context
*cxt
, int enable
)
325 return set_flag(cxt
, MNT_FL_LAZY
, enable
);
329 * mnt_context_is_lazy:
330 * @cxt: mount context
332 * Returns: 1 if lazy umount is enabled or 0
334 int mnt_context_is_lazy(struct libmnt_context
*cxt
)
336 return cxt
&& (cxt
->flags
& MNT_FL_LAZY
) ? 1 : 0;
340 * mnt_context_enable_fork:
341 * @cxt: mount context
342 * @enable: TRUE or FALSE
344 * Enable/disable fork(2) call in mnt_context_next_mount() (see mount(8) man
347 * Returns: 0 on success, negative number in case of error.
349 int mnt_context_enable_fork(struct libmnt_context
*cxt
, int enable
)
351 return set_flag(cxt
, MNT_FL_FORK
, enable
);
355 * mnt_context_is_fork:
356 * @cxt: mount context
358 * Returns: 1 if fork (mount -F) is enabled or 0
360 int mnt_context_is_fork(struct libmnt_context
*cxt
)
362 return cxt
&& (cxt
->flags
& MNT_FL_FORK
) ? 1 : 0;
366 * mnt_context_is_parent:
367 * @cxt: mount context
369 * Return: 1 if mount -F enabled and the current context is parent, or 0
371 int mnt_context_is_parent(struct libmnt_context
*cxt
)
373 return mnt_context_is_fork(cxt
) && cxt
->pid
== 0;
377 * mnt_context_is_child:
378 * @cxt: mount context
380 * Return: 1 if mount -F enabled and the current context is child, or 0
382 int mnt_context_is_child(struct libmnt_context
*cxt
)
384 return !mnt_context_is_fork(cxt
) && cxt
->pid
;
388 * mnt_context_enable_rdonly_umount:
389 * @cxt: mount context
390 * @enable: TRUE or FALSE
392 * Enable/disable read-only remount on failed umount(2)
393 * (see umount(8) man page, option -r).
395 * Returns: 0 on success, negative number in case of error.
397 int mnt_context_enable_rdonly_umount(struct libmnt_context
*cxt
, int enable
)
399 return set_flag(cxt
, MNT_FL_RDONLY_UMOUNT
, enable
);
403 * mnt_context_is_rdonly_umount
404 * @cxt: mount context
406 * See also mnt_context_enable_rdonly_umount() and see umount(8) man page,
409 * Returns: 1 if read-only remount failed umount(2) is enables or 0
411 int mnt_context_is_rdonly_umount(struct libmnt_context
*cxt
)
413 return cxt
&& (cxt
->flags
& MNT_FL_RDONLY_UMOUNT
) ? 1 : 0;
417 * mnt_context_disable_helpers:
418 * @cxt: mount context
419 * @disable: TRUE or FALSE
421 * Enable/disable /sbin/[u]mount.* helpers (see mount(8) man page, option -i).
423 * Returns: 0 on success, negative number in case of error.
425 int mnt_context_disable_helpers(struct libmnt_context
*cxt
, int disable
)
427 return set_flag(cxt
, MNT_FL_NOHELPERS
, disable
);
431 * mnt_context_is_nohelpers
432 * @cxt: mount context
434 * Returns: 1 if helpers are disabled (mount -i) or 0
436 int mnt_context_is_nohelpers(struct libmnt_context
*cxt
)
438 return cxt
&& (cxt
->flags
& MNT_FL_NOHELPERS
) ? 1 : 0;
443 * mnt_context_enable_sloppy:
444 * @cxt: mount context
445 * @enable: TRUE or FALSE
447 * Set/unset sloppy mounting (see mount(8) man page, option -s).
449 * Returns: 0 on success, negative number in case of error.
451 int mnt_context_enable_sloppy(struct libmnt_context
*cxt
, int enable
)
453 return set_flag(cxt
, MNT_FL_SLOPPY
, enable
);
457 * mnt_context_is_sloppy:
458 * @cxt: mount context
460 * Returns: 1 if sloppy flag is enabled or 0
462 int mnt_context_is_sloppy(struct libmnt_context
*cxt
)
464 return cxt
&& (cxt
->flags
& MNT_FL_SLOPPY
) ? 1 : 0;
468 * mnt_context_enable_fake:
469 * @cxt: mount context
470 * @enable: TRUE or FALSE
472 * Enable/disable fake mounting (see mount(8) man page, option -f).
474 * Returns: 0 on success, negative number in case of error.
476 int mnt_context_enable_fake(struct libmnt_context
*cxt
, int enable
)
478 return set_flag(cxt
, MNT_FL_FAKE
, enable
);
482 * mnt_context_is_fake:
483 * @cxt: mount context
485 * Returns: 1 if fake flag is enabled or 0
487 int mnt_context_is_fake(struct libmnt_context
*cxt
)
489 return cxt
&& (cxt
->flags
& MNT_FL_FAKE
) ? 1 : 0;
493 * mnt_context_disable_mtab:
494 * @cxt: mount context
495 * @disable: TRUE or FALSE
497 * Disable/enable mtab update (see mount(8) man page, option -n).
499 * Returns: 0 on success, negative number in case of error.
501 int mnt_context_disable_mtab(struct libmnt_context
*cxt
, int disable
)
503 return set_flag(cxt
, MNT_FL_NOMTAB
, disable
);
507 * mnt_context_is_nomtab:
508 * @cxt: mount context
510 * Returns: 1 if no-mtab is enabled or 0
512 int mnt_context_is_nomtab(struct libmnt_context
*cxt
)
514 return cxt
&& (cxt
->flags
& MNT_FL_NOMTAB
) ? 1 : 0;
518 * mnt_context_disable_swapmatch:
519 * @cxt: mount context
520 * @disable: TRUE or FALSE
522 * Disable/enable swap between source and target for mount(8) if only one path
525 * Returns: 0 on success, negative number in case of error.
527 int mnt_context_disable_swapmatch(struct libmnt_context
*cxt
, int disable
)
529 return set_flag(cxt
, MNT_FL_NOSWAPMATCH
, disable
);
533 * mnt_context_is_swapmatch:
534 * @cxt: mount context
536 * Returns: 1 if swap between source and target is allowed (default is 1) or 0.
538 int mnt_context_is_swapmatch(struct libmnt_context
*cxt
)
540 return cxt
&& (cxt
->flags
& MNT_FL_NOSWAPMATCH
) ? 0 : 1;
544 * mnt_context_enable_force:
545 * @cxt: mount context
546 * @enable: TRUE or FALSE
548 * Enable/disable force umounting (see umount(8) man page, option -f).
550 * Returns: 0 on success, negative number in case of error.
552 int mnt_context_enable_force(struct libmnt_context
*cxt
, int enable
)
554 return set_flag(cxt
, MNT_FL_FORCE
, enable
);
558 * mnt_context_is_force
559 * @cxt: mount context
561 * Returns: 1 if force umounting flag is enabled or 0
563 int mnt_context_is_force(struct libmnt_context
*cxt
)
565 return cxt
&& (cxt
->flags
& MNT_FL_FORCE
) ? 1 : 0;
569 * mnt_context_enable_verbose:
570 * @cxt: mount context
571 * @enable: TRUE or FALSE
573 * Enable/disable verbose output (TODO: not implemented yet)
575 * Returns: 0 on success, negative number in case of error.
577 int mnt_context_enable_verbose(struct libmnt_context
*cxt
, int enable
)
579 return set_flag(cxt
, MNT_FL_VERBOSE
, enable
);
583 * mnt_context_is_verbose
584 * @cxt: mount context
586 * Returns: 1 if verbose flag is enabled or 0
588 int mnt_context_is_verbose(struct libmnt_context
*cxt
)
590 return cxt
&& (cxt
->flags
& MNT_FL_VERBOSE
) ? 1 : 0;
594 * mnt_context_enable_loopdel:
595 * @cxt: mount context
596 * @enable: TRUE or FALSE
598 * Enable/disable loop delete (destroy) after umount (see umount(8), option -d)
600 * Returns: 0 on success, negative number in case of error.
602 int mnt_context_enable_loopdel(struct libmnt_context
*cxt
, int enable
)
604 return set_flag(cxt
, MNT_FL_LOOPDEL
, enable
);
608 * mnt_context_is_loopdel:
609 * @cxt: mount context
611 * Returns: 1 if loop device should be deleted after umount (umount -d) or 0.
613 int mnt_context_is_loopdel(struct libmnt_context
*cxt
)
615 return cxt
&& (cxt
->flags
& MNT_FL_LOOPDEL
) ? 1 : 0;
619 * mnt_context_set_fs:
620 * @cxt: mount context
621 * @fs: filesystem description
623 * The mount context uses private @fs by default. This function allows to
624 * overwrite the private @fs with an external instance. Note that the external
625 * @fs instance is not deallocated by mnt_free_context() or mnt_reset_context().
627 * The @fs will be modified by mnt_context_set_{source,target,options,fstype}
628 * functions, If the @fs is NULL then all current FS specific setting (source,
629 * target, etc., exclude spec) is reseted.
631 * Returns: 0 on success, negative number in case of error.
633 int mnt_context_set_fs(struct libmnt_context
*cxt
, struct libmnt_fs
*fs
)
637 if (!(cxt
->flags
& MNT_FL_EXTERN_FS
))
638 mnt_free_fs(cxt
->fs
);
640 set_flag(cxt
, MNT_FL_EXTERN_FS
, fs
!= NULL
);
646 * mnt_context_get_fs:
647 * @cxt: mount context
649 * The FS contains the basic description of mountpoint, fs type and so on.
650 * Note that the FS is modified by mnt_context_set_{source,target,options,fstype}
653 * Returns: pointer to FS description or NULL in case of calloc() errrr.
655 struct libmnt_fs
*mnt_context_get_fs(struct libmnt_context
*cxt
)
660 cxt
->fs
= mnt_new_fs();
661 cxt
->flags
&= ~MNT_FL_EXTERN_FS
;
667 * mnt_context_set_source:
668 * @cxt: mount context
669 * @source: mount source (device, directory, UUID, LABEL, ...)
671 * Returns: 0 on success, negative number in case of error.
673 int mnt_context_set_source(struct libmnt_context
*cxt
, const char *source
)
675 return mnt_fs_set_source(mnt_context_get_fs(cxt
), source
);
679 * mnt_context_get_source:
680 * @cxt: mount context
682 * Returns: returns pointer or NULL in case of error pr if not set.
684 const char *mnt_context_get_source(struct libmnt_context
*cxt
)
686 return mnt_fs_get_source(mnt_context_get_fs(cxt
));
690 * mnt_context_set_target:
691 * @cxt: mount context
692 * @target: mountpoint
694 * Returns: 0 on success, negative number in case of error.
696 int mnt_context_set_target(struct libmnt_context
*cxt
, const char *target
)
698 return mnt_fs_set_target(mnt_context_get_fs(cxt
), target
);
702 * mnt_context_get_target:
703 * @cxt: mount context
705 * Returns: returns pointer or NULL in case of error pr if not set.
707 const char *mnt_context_get_target(struct libmnt_context
*cxt
)
709 return mnt_fs_get_target(mnt_context_get_fs(cxt
));
713 * mnt_context_set_fstype:
714 * @cxt: mount context
715 * @fstype: filesystem type
717 * Note that the @fstype has to be the real FS type. For patterns with
718 * comma-separated list of filesystems or for "nofs" notation use
719 * mnt_context_set_fstype_pattern().
721 * Returns: 0 on success, negative number in case of error.
723 int mnt_context_set_fstype(struct libmnt_context
*cxt
, const char *fstype
)
725 return mnt_fs_set_fstype(mnt_context_get_fs(cxt
), fstype
);
729 * mnt_context_get_fstype:
730 * @cxt: mount context
732 * Returns: pointer or NULL in case of error pr if not set.
734 const char *mnt_context_get_fstype(struct libmnt_context
*cxt
)
736 return mnt_fs_get_fstype(mnt_context_get_fs(cxt
));
740 * mnt_context_set_options:
741 * @cxt: mount context
742 * @optstr: comma delimited mount options
744 * Returns: 0 on success, negative number in case of error.
746 int mnt_context_set_options(struct libmnt_context
*cxt
, const char *optstr
)
748 return mnt_fs_set_options(mnt_context_get_fs(cxt
), optstr
);
752 * mnt_context_append_options:
753 * @cxt: mount context
754 * @optstr: comma delimited mount options
756 * Returns: 0 on success, negative number in case of error.
758 int mnt_context_append_options(struct libmnt_context
*cxt
, const char *optstr
)
760 return mnt_fs_append_options(mnt_context_get_fs(cxt
), optstr
);
764 * mnt_context_get_options:
765 * @cxt: mount context
767 * This function returns mount options set by mnt_context_set_options() or
768 * mnt_context_append_options().
770 * Note that *after* mnt_context_prepare_mount() may the mount options string
771 * also includes options set by mnt_context_set_mflags() or another options
772 * generated by this library.
774 * Returns: pointer or NULL
776 const char *mnt_context_get_options(struct libmnt_context
*cxt
)
778 return mnt_fs_get_options(mnt_context_get_fs(cxt
));
782 * mnt_context_set_fstype_pattern:
783 * @cxt: mount context
784 * @pattern: FS name pattern (or NULL to reset the current setting)
786 * See mount(8), option -t.
788 * Returns: 0 on success, negative number in case of error.
790 int mnt_context_set_fstype_pattern(struct libmnt_context
*cxt
, const char *pattern
)
801 free(cxt
->fstype_pattern
);
802 cxt
->fstype_pattern
= p
;
807 * mnt_context_set_options_pattern:
808 * @cxt: mount context
809 * @pattern: options pattern (or NULL to reset the current setting)
811 * See mount(8), option -O.
813 * Returns: 0 on success, negative number in case of error.
815 int mnt_context_set_options_pattern(struct libmnt_context
*cxt
, const char *pattern
)
826 free(cxt
->optstr_pattern
);
827 cxt
->optstr_pattern
= p
;
832 * mnt_context_set_fstab:
833 * @cxt: mount context
836 * The mount context reads /etc/fstab to the the private struct libmnt_table by default.
837 * This function allows to overwrite the private fstab with an external
838 * instance. Note that the external instance is not deallocated by mnt_free_context().
840 * The fstab is used read-only and is not modified, it should be possible to
841 * share the fstab between more mount contexts (TODO: tests it.)
843 * If the @tb argument is NULL then the current private fstab instance is
846 * Returns: 0 on success, negative number in case of error.
848 int mnt_context_set_fstab(struct libmnt_context
*cxt
, struct libmnt_table
*tb
)
852 if (!(cxt
->flags
& MNT_FL_EXTERN_FSTAB
))
853 mnt_free_table(cxt
->fstab
);
855 set_flag(cxt
, MNT_FL_EXTERN_FSTAB
, tb
!= NULL
);
861 * mnt_context_get_fstab:
862 * @cxt: mount context
865 * See also mnt_table_parse_fstab() for more details about fstab.
867 * Returns: 0 on success, negative number in case of error.
869 int mnt_context_get_fstab(struct libmnt_context
*cxt
, struct libmnt_table
**tb
)
871 struct libmnt_cache
*cache
;
879 cxt
->fstab
= mnt_new_table();
882 if (cxt
->table_errcb
)
883 mnt_table_set_parser_errcb(cxt
->fstab
, cxt
->table_errcb
);
884 cxt
->flags
&= ~MNT_FL_EXTERN_FSTAB
;
885 rc
= mnt_table_parse_fstab(cxt
->fstab
, NULL
);
890 cache
= mnt_context_get_cache(cxt
);
892 /* never touch an external fstab */
893 if (!(cxt
->flags
& MNT_FL_EXTERN_FSTAB
))
894 mnt_table_set_cache(cxt
->fstab
, cache
);
902 * mnt_context_get_mtab:
903 * @cxt: mount context
906 * See also mnt_table_parse_mtab() for more details about mtab/mountinfo. The
907 * result will deallocated by mnt_free_context(@cxt).
909 * Returns: 0 on success, negative number in case of error.
911 int mnt_context_get_mtab(struct libmnt_context
*cxt
, struct libmnt_table
**tb
)
913 struct libmnt_cache
*cache
;
921 cxt
->mtab
= mnt_new_table();
925 if (cxt
->table_errcb
)
926 mnt_table_set_parser_errcb(cxt
->mtab
, cxt
->table_errcb
);
927 if (cxt
->table_fltrcb
)
928 mnt_table_set_parser_fltrcb(cxt
->mtab
,
930 cxt
->table_fltrcb_data
);
932 rc
= mnt_table_parse_mtab(cxt
->mtab
, cxt
->mtab_path
);
937 cache
= mnt_context_get_cache(cxt
);
938 mnt_table_set_cache(cxt
->mtab
, cache
);
943 DBG(CXT
, mnt_debug_h(cxt
, "mtab requested [nents=%d]",
944 mnt_table_get_nents(cxt
->mtab
)));
949 * Allows to specify filter for tab file entries. The filter is called by
950 * table parser. Currently used for mtab and utab only.
952 int mnt_context_set_tabfilter(struct libmnt_context
*cxt
,
953 int (*fltr
)(struct libmnt_fs
*, void *),
959 cxt
->table_fltrcb
= fltr
;
960 cxt
->table_fltrcb_data
= data
;
963 mnt_table_set_parser_fltrcb(cxt
->mtab
,
965 cxt
->table_fltrcb_data
);
967 DBG(CXT
, mnt_debug_h(cxt
, "tabfiler %s", fltr
? "ENABLED!" : "disabled"));
972 * mnt_context_get_table:
973 * @cxt: mount context
974 * @filename: e.g. /proc/self/mountinfo
975 * @tb: returns the table
977 * This function allocates a new table and parses the @file. The parser error
978 * callback and cache for tags and paths is set according to the @cxt setting.
979 * See also mnt_table_parse_file().
981 * It's strongly recommended use mnt_context_get_mtab() and
982 * mnt_context_get_fstab() functions for mtab and fstab files. This function
983 * does not care about LIBMOUNT_* env.variables and does not merge userspace
986 * The result will NOT be deallocated by mnt_free_context(@cxt).
988 * Returns: 0 on success, negative number in case of error.
990 int mnt_context_get_table(struct libmnt_context
*cxt
,
991 const char *filename
, struct libmnt_table
**tb
)
993 struct libmnt_cache
*cache
;
999 *tb
= mnt_new_table();
1003 if (cxt
->table_errcb
)
1004 mnt_table_set_parser_errcb(*tb
, cxt
->table_errcb
);
1006 rc
= mnt_table_parse_file(*tb
, filename
);
1008 mnt_free_table(*tb
);
1012 cache
= mnt_context_get_cache(cxt
);
1014 mnt_table_set_cache(*tb
, cache
);
1020 * mnt_context_set_tables_errcb
1021 * @cxt: mount context
1022 * @cb: pointer to callback function
1024 * The error callback is used for all tab files (e.g. mtab, fstab)
1025 * parsed within the context.
1027 * See also mnt_context_get_mtab(),
1028 * mnt_context_get_fstab(),
1029 * mnt_table_set_parser_errcb().
1031 * Returns: 0 on success, negative number in case of error.
1033 int mnt_context_set_tables_errcb(struct libmnt_context
*cxt
,
1034 int (*cb
)(struct libmnt_table
*tb
, const char *filename
, int line
))
1039 cxt
->table_errcb
= cb
;
1044 * mnt_context_set_cache:
1045 * @cxt: mount context
1046 * @cache: cache instance or nULL
1048 * The mount context maintains a private struct libmnt_cache by default. This function
1049 * allows to overwrite the private cache with an external instance. Note that
1050 * the external instance is not deallocated by mnt_free_context().
1052 * If the @cache argument is NULL then the current private cache instance is
1055 * Returns: 0 on success, negative number in case of error.
1057 int mnt_context_set_cache(struct libmnt_context
*cxt
, struct libmnt_cache
*cache
)
1061 if (!(cxt
->flags
& MNT_FL_EXTERN_CACHE
))
1062 mnt_free_cache(cxt
->cache
);
1064 set_flag(cxt
, MNT_FL_EXTERN_CACHE
, cache
!= NULL
);
1070 * mnt_context_get_cache
1071 * @cxt: mount context
1073 * See also mnt_context_set_cache().
1075 * Returns: pointer to cache or NULL if canonicalization is disabled.
1077 struct libmnt_cache
*mnt_context_get_cache(struct libmnt_context
*cxt
)
1079 if (!cxt
|| mnt_context_is_nocanonicalize(cxt
))
1083 cxt
->cache
= mnt_new_cache();
1086 cxt
->flags
&= ~MNT_FL_EXTERN_CACHE
;
1092 * mnt_context_set_passwd_cb:
1093 * @cxt: mount context
1094 * @get: callback to get password
1095 * @release: callback to release (delallocate) password
1097 * Sets callbacks for encryption password (e.g encrypted loopdev). This
1098 * function is deprecated (encrypted loops are no ore supported).
1100 * Returns: 0 on success, negative number in case of error.
1102 int mnt_context_set_passwd_cb(struct libmnt_context
*cxt
,
1103 char *(*get
)(struct libmnt_context
*),
1104 void (*release
)(struct libmnt_context
*, char *))
1109 cxt
->pwd_get_cb
= get
;
1110 cxt
->pwd_release_cb
= release
;
1115 * mnt_context_get_lock:
1116 * @cxt: mount context
1118 * The libmount applications don't have to care about mtab locking, but with a
1119 * small exception: the application has to be able to remove the lock file when
1120 * interrupted by signal or signals have to be ignored when the lock is locked.
1122 * The default behavior is to ignore all signals (except SIGALRM and
1123 * SIGTRAP for mtab udate) when the lock is locked. If this behavior
1124 * is unacceptable then use:
1126 * lc = mnt_context_get_lock(cxt);
1128 * mnt_lock_block_signals(lc, FALSE);
1130 * and don't forget to call mnt_unlock_file(lc) before exit.
1132 * Returns: pointer to lock struct or NULL.
1134 struct libmnt_lock
*mnt_context_get_lock(struct libmnt_context
*cxt
)
1137 * DON'T call this function within libmount, it will always allocate
1138 * the lock. The mnt_update_* functions are able to allocate the lock
1139 * only when mtab/utab update is really necessary.
1141 if (!cxt
|| mnt_context_is_nomtab(cxt
))
1145 cxt
->lock
= mnt_new_lock(cxt
->mtab_writable
?
1146 cxt
->mtab_path
: cxt
->utab_path
, 0);
1148 mnt_lock_block_signals(cxt
->lock
, TRUE
);
1154 * mnt_context_set_mflags:
1155 * @cxt: mount context
1156 * @flags: mount(2) flags (MS_* flags)
1158 * Sets mount flags (see mount(2) man page).
1160 * Note that mount context allows to define mount options by mount flags. It
1161 * means you can for example use
1163 * mnt_context_set_mflags(cxt, MS_NOEXEC | MS_NOSUID);
1167 * mnt_context_set_options(cxt, "noexec,nosuid");
1169 * these both calls have the same effect.
1171 * Returns: 0 on success, negative number in case of error.
1173 int mnt_context_set_mflags(struct libmnt_context
*cxt
, unsigned long flags
)
1178 cxt
->mountflags
= flags
;
1180 if ((cxt
->flags
& MNT_FL_MOUNTOPTS_FIXED
) && cxt
->fs
)
1182 * the final mount options are already generated, refresh...
1184 return mnt_optstr_apply_flags(
1185 &cxt
->fs
->vfs_optstr
,
1187 mnt_get_builtin_optmap(MNT_LINUX_MAP
));
1193 * mnt_context_get_mflags:
1194 * @cxt: mount context
1195 * @flags: returns MS_* mount flags
1197 * Converts mount options string to MS_* flags and bitewise-OR the result with
1198 * already defined flags (see mnt_context_set_mflags()).
1200 * Returns: 0 on success, negative number in case of error.
1202 int mnt_context_get_mflags(struct libmnt_context
*cxt
, unsigned long *flags
)
1209 if (!(cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
) && cxt
->fs
) {
1210 const char *o
= mnt_fs_get_options(cxt
->fs
);
1212 rc
= mnt_optstr_get_flags(o
, flags
,
1213 mnt_get_builtin_optmap(MNT_LINUX_MAP
));
1216 *flags
|= cxt
->mountflags
;
1221 * mnt_context_set_user_mflags:
1222 * @cxt: mount context
1223 * @flags: mount(2) flags (MNT_MS_* flags, e.g. MNT_MS_LOOP)
1225 * Sets userspace mount flags.
1227 * See also notest for mnt_context_set_mflags().
1229 * Returns: 0 on success, negative number in case of error.
1231 int mnt_context_set_user_mflags(struct libmnt_context
*cxt
, unsigned long flags
)
1235 cxt
->user_mountflags
= flags
;
1240 * mnt_context_get_user_mflags:
1241 * @cxt: mount context
1242 * @flags: returns mount flags
1244 * Converts mount options string to MNT_MS_* flags and bitewise-OR the result
1245 * with already defined flags (see mnt_context_set_user_mflags()).
1247 * Returns: 0 on success, negative number in case of error.
1249 int mnt_context_get_user_mflags(struct libmnt_context
*cxt
, unsigned long *flags
)
1256 if (!(cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
) && cxt
->fs
) {
1257 const char *o
= mnt_fs_get_user_options(cxt
->fs
);
1259 rc
= mnt_optstr_get_flags(o
, flags
,
1260 mnt_get_builtin_optmap(MNT_USERSPACE_MAP
));
1263 *flags
|= cxt
->user_mountflags
;
1268 * mnt_context_set_mountdata:
1269 * @cxt: mount context
1270 * @data: mount(2) data
1272 * The mount context generates mountdata from mount options by default. This
1273 * function allows to overwrite this behavior, and @data will be used instead
1276 * The libmount does not deallocated the data by mnt_free_context(). Note that
1277 * NULL is also valid mount data.
1279 * Returns: 0 on success, negative number in case of error.
1281 int mnt_context_set_mountdata(struct libmnt_context
*cxt
, void *data
)
1285 cxt
->mountdata
= data
;
1286 cxt
->flags
|= MNT_FL_MOUNTDATA
;
1291 * Translates LABEL/UUID/path to mountable path
1293 int mnt_context_prepare_srcpath(struct libmnt_context
*cxt
)
1295 const char *path
= NULL
;
1296 struct libmnt_cache
*cache
;
1297 const char *t
, *v
, *src
;
1302 assert((cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
));
1304 if (!cxt
|| !cxt
->fs
)
1307 DBG(CXT
, mnt_debug_h(cxt
, "preparing source path"));
1309 src
= mnt_fs_get_source(cxt
->fs
);
1311 if (!src
&& (cxt
->mountflags
& MS_PROPAGATION
))
1312 /* mount --make-{shared,private,...} */
1313 return mnt_fs_set_source(cxt
->fs
, "none");
1315 /* ignore filesystems without source or filesystems
1316 * where the source is quasi-path (//foo/bar)
1318 if (!src
|| mnt_fs_is_netfs(cxt
->fs
))
1321 DBG(CXT
, mnt_debug_h(cxt
, "srcpath '%s'", src
));
1323 cache
= mnt_context_get_cache(cxt
);
1325 if (!mnt_fs_get_tag(cxt
->fs
, &t
, &v
)) {
1327 * Source is TAG (evaluate)
1330 path
= mnt_resolve_tag(t
, v
, cache
);
1332 rc
= path
? mnt_fs_set_source(cxt
->fs
, path
) : -MNT_ERR_NOSOURCE
;
1334 } else if (cache
&& !mnt_fs_is_pseudofs(cxt
->fs
)) {
1336 * Source is PATH (canonicalize)
1338 path
= mnt_resolve_path(src
, cache
);
1339 if (path
&& strcmp(path
, src
))
1340 rc
= mnt_fs_set_source(cxt
->fs
, path
);
1344 DBG(CXT
, mnt_debug_h(cxt
, "failed to prepare srcpath [rc=%d]", rc
));
1351 if ((cxt
->mountflags
& (MS_BIND
| MS_MOVE
| MS_PROPAGATION
| MS_REMOUNT
)) ||
1352 mnt_fs_is_pseudofs(cxt
->fs
)) {
1353 DBG(CXT
, mnt_debug_h(cxt
, "REMOUNT/BIND/MOVE/pseudo FS source: %s", path
));
1358 * Initialize loop device
1360 if (mnt_context_is_loopdev(cxt
)) {
1361 rc
= mnt_context_setup_loopdev(cxt
);
1366 DBG(CXT
, mnt_debug_h(cxt
, "final srcpath '%s'",
1367 mnt_fs_get_source(cxt
->fs
)));
1371 int mnt_context_prepare_target(struct libmnt_context
*cxt
)
1374 struct libmnt_cache
*cache
;
1379 assert((cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
));
1381 if (!cxt
|| !cxt
->fs
)
1384 DBG(CXT
, mnt_debug_h(cxt
, "preparing target path"));
1386 tgt
= mnt_fs_get_target(cxt
->fs
);
1390 cache
= mnt_context_get_cache(cxt
);
1392 char *path
= mnt_resolve_path(tgt
, cache
);
1393 if (path
&& strcmp(path
, tgt
) != 0)
1394 rc
= mnt_fs_set_target(cxt
->fs
, path
);
1398 DBG(CXT
, mnt_debug_h(cxt
, "failed to prepare target '%s'", tgt
));
1400 DBG(CXT
, mnt_debug_h(cxt
, "final target '%s'",
1401 mnt_fs_get_target(cxt
->fs
)));
1406 * It's usully no error when we're not able to detect filesystem type -- we
1407 * will try to use types from /{etc,proc}/filesystems.
1409 int mnt_context_guess_fstype(struct libmnt_context
*cxt
)
1417 assert((cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
));
1419 if (!cxt
|| !cxt
->fs
)
1422 if (cxt
->mountflags
& (MS_BIND
| MS_MOVE
| MS_PROPAGATION
))
1425 type
= (char *) mnt_fs_get_fstype(cxt
->fs
);
1426 if (type
&& !strcmp(type
, "auto")) {
1427 mnt_fs_set_fstype(cxt
->fs
, NULL
);
1433 if (cxt
->flags
& MS_REMOUNT
)
1435 if (cxt
->fstype_pattern
)
1438 dev
= mnt_fs_get_srcpath(cxt
->fs
);
1442 if (access(dev
, F_OK
) == 0) {
1443 struct libmnt_cache
*cache
= mnt_context_get_cache(cxt
);
1445 type
= mnt_get_fstype(dev
, &cxt
->ambi
, cache
);
1447 rc
= mnt_fs_set_fstype(cxt
->fs
, type
);
1449 free(type
); /* type is not cached */
1452 if (strchr(dev
, ':') != NULL
)
1453 rc
= mnt_fs_set_fstype(cxt
->fs
, "nfs");
1454 else if (!strncmp(dev
, "//", 2))
1455 rc
= mnt_fs_set_fstype(cxt
->fs
, "cifs");
1459 DBG(CXT
, mnt_debug_h(cxt
, "FS type: %s", mnt_fs_get_fstype(cxt
->fs
)));
1462 return mnt_fs_set_fstype(cxt
->fs
, "none");
1466 * The default is to use fstype from cxt->fs, this could be overwritten by
1467 * @type. The @act is MNT_ACT_{MOUNT,UMOUNT}.
1469 * Returns: 0 on success or negative number in case of error. Note that success
1470 * does not mean that there is any usable helper, you have to check cxt->helper.
1472 int mnt_context_prepare_helper(struct libmnt_context
*cxt
, const char *name
,
1475 char search_path
[] = FS_SEARCH_PATH
; /* from config.h */
1476 char *p
= NULL
, *path
;
1480 assert((cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
));
1483 type
= mnt_fs_get_fstype(cxt
->fs
);
1485 if (type
&& strchr(type
, ','))
1486 return 0; /* type is fstype pattern */
1488 if (mnt_context_is_nohelpers(cxt
)
1490 || !strcmp(type
, "none")
1491 || mnt_fs_is_swaparea(cxt
->fs
))
1494 path
= strtok_r(search_path
, ":", &p
);
1496 char helper
[PATH_MAX
];
1500 rc
= snprintf(helper
, sizeof(helper
), "%s/%s.%s",
1502 path
= strtok_r(NULL
, ":", &p
);
1504 if (rc
< 0 || (size_t) rc
>= sizeof(helper
))
1507 rc
= stat(helper
, &st
);
1508 if (rc
== -1 && errno
== ENOENT
&& strchr(type
, '.')) {
1509 /* If type ends with ".subtype" try without it */
1510 char *hs
= strrchr(helper
, '.');
1513 rc
= stat(helper
, &st
);
1516 DBG(CXT
, mnt_debug_h(cxt
, "%-25s ... %s", helper
,
1517 rc
? "not found" : "found"));
1522 cxt
->helper
= strdup(helper
);
1531 int mnt_context_merge_mflags(struct libmnt_context
*cxt
)
1533 unsigned long fl
= 0;
1538 DBG(CXT
, mnt_debug_h(cxt
, "merging mount flags"));
1540 rc
= mnt_context_get_mflags(cxt
, &fl
);
1543 cxt
->mountflags
= fl
;
1546 rc
= mnt_context_get_user_mflags(cxt
, &fl
);
1549 cxt
->user_mountflags
= fl
;
1551 DBG(CXT
, mnt_debug_h(cxt
, "final flags: VFS=%08lx user=%08lx",
1552 cxt
->mountflags
, cxt
->user_mountflags
));
1554 cxt
->flags
|= MNT_FL_MOUNTFLAGS_MERGED
;
1559 * Prepare /etc/mtab or /run/mount/utab
1561 int mnt_context_prepare_update(struct libmnt_context
*cxt
)
1568 assert(cxt
->action
);
1569 assert((cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
));
1571 DBG(CXT
, mnt_debug_h(cxt
, "prepare update"));
1573 if (cxt
->mountflags
& MS_PROPAGATION
) {
1574 DBG(CXT
, mnt_debug_h(cxt
, "skip update: MS_PROPAGATION"));
1578 target
= mnt_fs_get_target(cxt
->fs
);
1580 if (cxt
->action
== MNT_ACT_UMOUNT
&& target
&& !strcmp(target
, "/"))
1581 /* Don't try to touch mtab if umounting root FS */
1582 mnt_context_disable_mtab(cxt
, TRUE
);
1584 if (mnt_context_is_nomtab(cxt
)) {
1585 DBG(CXT
, mnt_debug_h(cxt
, "skip update: NOMTAB flag"));
1589 DBG(CXT
, mnt_debug_h(cxt
, "skip update: external helper"));
1592 if (!cxt
->mtab_writable
&& !cxt
->utab_writable
) {
1593 DBG(CXT
, mnt_debug_h(cxt
, "skip update: no writable destination"));
1596 /* 0 = success, 1 = not called yet */
1597 if (cxt
->syscall_status
!= 1 && cxt
->syscall_status
!= 0) {
1598 DBG(CXT
, mnt_debug_h(cxt
,
1599 "skip update: syscall failed [status=%d]",
1600 cxt
->syscall_status
));
1604 cxt
->update
= mnt_new_update();
1608 mnt_update_set_filename(cxt
->update
,
1609 cxt
->mtab_writable
? cxt
->mtab_path
: cxt
->utab_path
,
1610 !cxt
->mtab_writable
);
1613 if (cxt
->action
== MNT_ACT_UMOUNT
)
1614 rc
= mnt_update_set_fs(cxt
->update
, cxt
->mountflags
,
1615 mnt_context_get_target(cxt
), NULL
);
1617 rc
= mnt_update_set_fs(cxt
->update
, cxt
->mountflags
,
1620 return rc
< 0 ? rc
: 0;
1623 int mnt_context_update_tabs(struct libmnt_context
*cxt
)
1629 if (mnt_context_is_nomtab(cxt
)) {
1630 DBG(CXT
, mnt_debug_h(cxt
, "don't update: NOMTAB flag"));
1634 DBG(CXT
, mnt_debug_h(cxt
, "don't update: external helper"));
1637 if (!cxt
->update
|| !mnt_update_is_ready(cxt
->update
)) {
1638 DBG(CXT
, mnt_debug_h(cxt
, "don't update: no update prepared"));
1641 if (cxt
->syscall_status
) {
1642 DBG(CXT
, mnt_debug_h(cxt
, "don't update: syscall failed/not called"));
1646 fl
= mnt_update_get_mflags(cxt
->update
);
1647 if ((cxt
->mountflags
& MS_RDONLY
) != (fl
& MS_RDONLY
))
1649 * fix MS_RDONLY in options
1651 mnt_update_force_rdonly(cxt
->update
,
1652 cxt
->mountflags
& MS_RDONLY
);
1654 return mnt_update_table(cxt
->update
, cxt
->lock
);
1657 static int apply_table(struct libmnt_context
*cxt
, struct libmnt_table
*tb
,
1660 struct libmnt_fs
*fs
= NULL
;
1661 const char *src
= NULL
, *tgt
= NULL
;
1670 src
= mnt_fs_get_source(cxt
->fs
);
1671 tgt
= mnt_fs_get_target(cxt
->fs
);
1674 fs
= mnt_table_find_pair(tb
, src
, tgt
, direction
);
1677 fs
= mnt_table_find_source(tb
, src
, direction
);
1679 fs
= mnt_table_find_target(tb
, tgt
, direction
);
1681 if (!fs
&& mnt_context_is_swapmatch(cxt
)) {
1682 /* swap source and target (if @src is not LABEL/UUID),
1687 * the path could be a mountpoint as well as source (for
1688 * example bind mount, symlink to device, ...).
1690 if (src
&& !mnt_fs_get_tag(cxt
->fs
, NULL
, NULL
))
1691 fs
= mnt_table_find_target(tb
, src
, direction
);
1693 fs
= mnt_table_find_source(tb
, tgt
, direction
);
1698 return -MNT_ERR_NOFSTAB
; /* not found */
1700 DBG(CXT
, mnt_debug_h(cxt
, "apply entry:"));
1701 DBG(CXT
, mnt_fs_print_debug(fs
, stderr
));
1703 /* copy from tab to our FS description
1705 rc
= mnt_fs_set_source(cxt
->fs
, mnt_fs_get_source(fs
));
1707 rc
= mnt_fs_set_target(cxt
->fs
, mnt_fs_get_target(fs
));
1709 if (!rc
&& !mnt_fs_get_fstype(cxt
->fs
))
1710 rc
= mnt_fs_set_fstype(cxt
->fs
, mnt_fs_get_fstype(fs
));
1715 if (cxt
->optsmode
& MNT_OMODE_IGNORE
)
1717 else if (cxt
->optsmode
& MNT_OMODE_REPLACE
)
1718 rc
= mnt_fs_set_options(cxt
->fs
, mnt_fs_get_options(fs
));
1720 else if (cxt
->optsmode
& MNT_OMODE_APPEND
)
1721 rc
= mnt_fs_append_options(cxt
->fs
, mnt_fs_get_options(fs
));
1723 else if (cxt
->optsmode
& MNT_OMODE_PREPEND
)
1724 rc
= mnt_fs_prepend_options(cxt
->fs
, mnt_fs_get_options(fs
));
1727 cxt
->flags
|= MNT_FL_TAB_APPLIED
;
1732 * mnt_context_apply_fstab:
1733 * @cxt: mount context
1735 * This function is optional.
1737 * Returns: 0 on success, negative number in case of error.
1739 int mnt_context_apply_fstab(struct libmnt_context
*cxt
)
1742 struct libmnt_table
*tab
= NULL
;
1743 const char *src
= NULL
, *tgt
= NULL
;
1751 if (mnt_context_tab_applied(cxt
)) /* already applied */
1754 if (mnt_context_is_restricted(cxt
)) {
1755 DBG(CXT
, mnt_debug_h(cxt
, "force fstab usage for non-root users!"));
1756 cxt
->optsmode
= MNT_OMODE_USER
;
1757 } else if (cxt
->optsmode
== 0) {
1758 DBG(CXT
, mnt_debug_h(cxt
, "use default optmode"));
1759 cxt
->optsmode
= MNT_OMODE_AUTO
;
1760 } else if (cxt
->optsmode
& MNT_OMODE_NOTAB
) {
1761 cxt
->optsmode
&= ~MNT_OMODE_FSTAB
;
1762 cxt
->optsmode
&= ~MNT_OMODE_MTAB
;
1763 cxt
->optsmode
&= ~MNT_OMODE_FORCE
;
1767 src
= mnt_fs_get_source(cxt
->fs
);
1768 tgt
= mnt_fs_get_target(cxt
->fs
);
1771 DBG(CXT
, mnt_debug_h(cxt
, "OPTSMODE: ignore=%d, append=%d, prepend=%d, "
1772 "replace=%d, force=%d, fstab=%d, mtab=%d",
1773 cxt
->optsmode
& MNT_OMODE_IGNORE
? 1 : 0,
1774 cxt
->optsmode
& MNT_OMODE_APPEND
? 1 : 0,
1775 cxt
->optsmode
& MNT_OMODE_PREPEND
? 1 : 0,
1776 cxt
->optsmode
& MNT_OMODE_REPLACE
? 1 : 0,
1777 cxt
->optsmode
& MNT_OMODE_FORCE
? 1 : 0,
1778 cxt
->optsmode
& MNT_OMODE_FSTAB
? 1 : 0,
1779 cxt
->optsmode
& MNT_OMODE_MTAB
? 1 : 0));
1781 /* fstab is not required if source and target are specified */
1782 if (src
&& tgt
&& !(cxt
->optsmode
& MNT_OMODE_FORCE
)) {
1783 DBG(CXT
, mnt_debug_h(cxt
, "fstab not required -- skip"));
1788 && !(cxt
->optsmode
& MNT_OMODE_FSTAB
)
1789 && !(cxt
->optsmode
& MNT_OMODE_MTAB
)) {
1790 DBG(CXT
, mnt_debug_h(cxt
, "only target; fstab/mtab not required "
1791 "-- skip, probably MS_PROPAGATION"));
1795 DBG(CXT
, mnt_debug_h(cxt
,
1796 "trying to apply fstab (src=%s, target=%s)", src
, tgt
));
1798 /* let's initialize cxt->fs */
1799 ignore_result( mnt_context_get_fs(cxt
) );
1802 if (cxt
->optsmode
& MNT_OMODE_FSTAB
) {
1803 rc
= mnt_context_get_fstab(cxt
, &tab
);
1805 rc
= apply_table(cxt
, tab
, MNT_ITER_FORWARD
);
1809 if (rc
< 0 && (cxt
->optsmode
& MNT_OMODE_MTAB
)) {
1810 DBG(CXT
, mnt_debug_h(cxt
, "trying to apply from mtab"));
1811 rc
= mnt_context_get_mtab(cxt
, &tab
);
1813 rc
= apply_table(cxt
, tab
, MNT_ITER_BACKWARD
);
1816 DBG(CXT
, mnt_debug_h(cxt
, "failed to find entry in fstab/mtab"));
1821 * mnt_context_tab_applied:
1822 * @cxt: mount context
1824 * Returns: 1 if fstab (or mtab) has been applied to the context, or 0.
1826 int mnt_context_tab_applied(struct libmnt_context
*cxt
)
1828 return cxt
&& (cxt
->flags
& MNT_FL_TAB_APPLIED
);
1832 * mnt_context_get_status:
1833 * @cxt: mount context
1835 * Global libmount status.
1837 * The real exit code of the mount.type helper has to be tested by
1838 * mnt_context_get_helper_status(). The mnt_context_get_status() only inform
1839 * that exec() has been successful.
1841 * Returns: 1 if mount.type or mount(2) syscall has been successfully called.
1843 int mnt_context_get_status(struct libmnt_context
*cxt
)
1845 return cxt
&& (!cxt
->syscall_status
|| !cxt
->helper_exec_status
);
1849 * mnt_context_helper_executed:
1850 * @cxt: mount context
1852 * Returns: 1 if mount.type helper has been executed, or 0.
1854 int mnt_context_helper_executed(struct libmnt_context
*cxt
)
1856 return cxt
->helper_exec_status
!= 1;
1860 * mnt_context_get_helper_status:
1861 * @cxt: mount context
1863 * Return: mount.type helper exit status, result is reliable only if
1864 * mnt_context_helper_executed() returns 1.
1866 int mnt_context_get_helper_status(struct libmnt_context
*cxt
)
1868 return cxt
->helper_status
;
1872 * mnt_context_syscall_called:
1873 * @cxt: mount context
1875 * Returns: 1 if mount(2) syscall has been called, or 0.
1877 int mnt_context_syscall_called(struct libmnt_context
*cxt
)
1879 return cxt
->syscall_status
!= 1;
1883 * mnt_context_get_syscall_errno:
1884 * @cxt: mount context
1886 * The result from this function is reliable only if
1887 * mnt_context_syscall_called() returns 1.
1889 * Returns: mount(2) errno if the syscall failed or 0.
1891 int mnt_context_get_syscall_errno(struct libmnt_context
*cxt
)
1893 if (cxt
->syscall_status
< 0)
1894 return -cxt
->syscall_status
;
1900 * mnt_context_set_syscall_status:
1901 * @cxt: mount context
1902 * @status: mount(2) status
1904 * The @status should be 0 on success, or negative number on error (-errno).
1906 * This function should be used only if [u]mount(2) syscall is NOT called by
1909 * Returns: 0 or negative number in case of error.
1911 int mnt_context_set_syscall_status(struct libmnt_context
*cxt
, int status
)
1916 DBG(CXT
, mnt_debug_h(cxt
, "syscall status set to: %d", status
));
1917 cxt
->syscall_status
= status
;
1922 * mnt_context_strerror
1925 * @bufsiz: size of the buffer
1927 * Not implemented yet.
1929 * Returns: 0 or negative number in case of error.
1931 int mnt_context_strerror(struct libmnt_context
*cxt
__attribute__((__unused__
)),
1932 char *buf
__attribute__((__unused__
)),
1933 size_t bufsiz
__attribute__((__unused__
)))
1935 /* TODO: based on cxt->syscall_errno or cxt->helper_status */
1940 * mnt_context_init_helper
1941 * @cxt: mount context
1942 * @action: MNT_ACT_{UMOUNT,MOUNT}
1943 * @flags: not used now
1945 * This function infors libmount that used from [u]mount.type helper.
1947 * The function also calls mnt_context_disable_helpers() to avoid recursive
1948 * mount.type helpers calling. It you really want to call another
1949 * mount.type helper from your helper than you have to explicitly enable this
1952 * mnt_context_disable_helpers(cxt, FALSE);
1954 * Returns: 0 on success, negative number in case of error.
1956 int mnt_context_init_helper(struct libmnt_context
*cxt
, int action
,
1957 int flags
__attribute__((__unused__
)))
1959 int rc
= mnt_context_disable_helpers(cxt
, TRUE
);
1962 rc
= set_flag(cxt
, MNT_FL_HELPER
, 1);
1964 cxt
->action
= action
;
1966 DBG(CXT
, mnt_debug_h(cxt
, "initialized for [u]mount.<type> helper [rc=%d]", rc
));
1971 * mnt_context_helper_setopt:
1973 * @c: getopt() result
1974 * @arg: getopt() optarg
1976 * This function applies [u]mount.type command line option (for example parsed
1977 * by getopt or getopt_long) to @cxt. All unknown options are ignored and
1978 * then 1 is returned.
1980 * Returns: negative number on error, 1 if @c is unknown option, 0 on success.
1982 int mnt_context_helper_setopt(struct libmnt_context
*cxt
, int c
, char *arg
)
1985 switch(cxt
->action
) {
1987 return mnt_context_mount_setopt(cxt
, c
, arg
);
1988 case MNT_ACT_UMOUNT
:
1989 return mnt_context_umount_setopt(cxt
, c
, arg
);
1996 * mnt_context_is_fs_mounted:
1999 * @mounted: returns 1 for mounted and 0 for non-mounted filesystems
2001 * Please, read mnt_table_is_fs_mounted() description!
2003 * Returns: 0 on success and negative number in case of error.
2005 int mnt_context_is_fs_mounted(struct libmnt_context
*cxt
,
2006 struct libmnt_fs
*fs
, int *mounted
)
2008 struct libmnt_table
*mtab
;
2011 if (!cxt
|| !fs
|| !mounted
)
2014 rc
= mnt_context_get_mtab(cxt
, &mtab
);
2018 *mounted
= mnt_table_is_fs_mounted(mtab
, fs
);
2022 static int mnt_context_add_child(struct libmnt_context
*cxt
, pid_t pid
)
2029 pids
= realloc(cxt
->children
, sizeof(pid_t
) * cxt
->nchildren
+ 1);
2033 DBG(CXT
, mnt_debug_h(cxt
, "add new child %d", pid
));
2034 cxt
->children
= pids
;
2035 cxt
->children
[cxt
->nchildren
++] = pid
;
2040 int mnt_fork_context(struct libmnt_context
*cxt
)
2045 if (!mnt_context_is_parent(cxt
))
2048 DBG(CXT
, mnt_debug_h(cxt
, "forking context"));
2055 case -1: /* error */
2056 DBG(CXT
, mnt_debug_h(cxt
, "fork failed %m"));
2060 cxt
->pid
= getpid();
2061 mnt_context_enable_fork(cxt
, FALSE
);
2062 DBG(CXT
, mnt_debug_h(cxt
, "child created"));
2066 rc
= mnt_context_add_child(cxt
, pid
);
2073 int mnt_context_wait_for_children(struct libmnt_context
*cxt
,
2074 int *nchildren
, int *nerrs
)
2081 assert(mnt_context_is_parent(cxt
));
2083 for (i
= 0; i
< cxt
->nchildren
; i
++) {
2084 pid_t pid
= cxt
->children
[i
];
2085 int rc
= 0, ret
= 0;
2090 DBG(CXT
, mnt_debug_h(cxt
,
2091 "waiting for child (%d/%d): %d",
2092 i
+ 1, cxt
->nchildren
, pid
));
2094 rc
= waitpid(pid
, &ret
, 0);
2096 } while (rc
== -1 && errno
== EINTR
);
2101 if (rc
!= -1 && nerrs
) {
2103 (*nerrs
) += WEXITSTATUS(ret
) == 0 ? 0 : 1;
2107 cxt
->children
[i
] = 0;
2111 free(cxt
->children
);
2112 cxt
->children
= NULL
;
2120 struct libmnt_lock
*lock
;
2122 static void lock_fallback(void)
2125 mnt_unlock_file(lock
);
2128 int test_mount(struct libmnt_test
*ts
, int argc
, char *argv
[])
2130 int idx
= 1, rc
= 0;
2131 struct libmnt_context
*cxt
;
2136 cxt
= mnt_new_context();
2140 if (!strcmp(argv
[idx
], "-o")) {
2141 mnt_context_set_options(cxt
, argv
[idx
+ 1]);
2144 if (!strcmp(argv
[idx
], "-t")) {
2145 /* TODO: use mnt_context_set_fstype_pattern() */
2146 mnt_context_set_fstype(cxt
, argv
[idx
+ 1]);
2150 if (argc
== idx
+ 1)
2151 /* mount <mountpont>|<device> */
2152 mnt_context_set_target(cxt
, argv
[idx
++]);
2154 else if (argc
== idx
+ 2) {
2155 /* mount <device> <mountpoint> */
2156 mnt_context_set_source(cxt
, argv
[idx
++]);
2157 mnt_context_set_target(cxt
, argv
[idx
++]);
2160 /* this is unnecessary! -- libmount is able to internaly
2161 * create and manage the lock
2163 lock
= mnt_context_get_lock(cxt
);
2165 atexit(lock_fallback
);
2167 rc
= mnt_context_mount(cxt
);
2169 printf("failed to mount: %m\n");
2171 printf("successfully mounted\n");
2173 lock
= NULL
; /* because we use atexit lock_fallback */
2174 mnt_free_context(cxt
);
2178 int test_umount(struct libmnt_test
*ts
, int argc
, char *argv
[])
2180 int idx
= 1, rc
= 0;
2181 struct libmnt_context
*cxt
;
2186 cxt
= mnt_new_context();
2190 if (!strcmp(argv
[idx
], "-t")) {
2191 mnt_context_set_fstype(cxt
, argv
[idx
+ 1]);
2195 if (!strcmp(argv
[idx
], "-f")) {
2196 mnt_context_enable_force(cxt
, TRUE
);
2200 if (!strcmp(argv
[idx
], "-l")) {
2201 mnt_context_enable_lazy(cxt
, TRUE
);
2205 if (!strcmp(argv
[idx
], "-r")) {
2206 mnt_context_enable_rdonly_umount(cxt
, TRUE
);
2210 if (argc
== idx
+ 1) {
2211 /* mount <mountpont>|<device> */
2212 mnt_context_set_target(cxt
, argv
[idx
++]);
2218 lock
= mnt_context_get_lock(cxt
);
2220 atexit(lock_fallback
);
2222 rc
= mnt_context_umount(cxt
);
2224 printf("failed to umount\n");
2226 printf("successfully umounted\n");
2228 lock
= NULL
; /* because we use atexit lock_fallback */
2229 mnt_free_context(cxt
);
2233 int test_flags(struct libmnt_test
*ts
, int argc
, char *argv
[])
2235 int idx
= 1, rc
= 0;
2236 struct libmnt_context
*cxt
;
2237 const char *opt
= NULL
;
2238 unsigned long flags
= 0;
2243 cxt
= mnt_new_context();
2247 if (!strcmp(argv
[idx
], "-o")) {
2248 mnt_context_set_options(cxt
, argv
[idx
+ 1]);
2252 if (argc
== idx
+ 1)
2253 /* mount <mountpont>|<device> */
2254 mnt_context_set_target(cxt
, argv
[idx
++]);
2256 rc
= mnt_context_prepare_mount(cxt
);
2258 printf("failed to prepare mount %s\n", strerror(-rc
));
2260 opt
= mnt_fs_get_options(cxt
->fs
);
2262 fprintf(stdout
, "options: %s\n", opt
);
2264 mnt_context_get_mflags(cxt
, &flags
);
2265 fprintf(stdout
, "flags: %08lx\n", flags
);
2267 mnt_free_context(cxt
);
2271 int test_mountall(struct libmnt_test
*ts
, int argc
, char *argv
[])
2273 struct libmnt_context
*cxt
;
2274 struct libmnt_iter
*itr
;
2275 struct libmnt_fs
*fs
;
2276 int mntrc
, ignored
, idx
= 1;
2278 cxt
= mnt_new_context();
2279 itr
= mnt_new_iter(MNT_ITER_FORWARD
);
2285 if (!strcmp(argv
[idx
], "-O")) {
2286 mnt_context_set_options_pattern(cxt
, argv
[idx
+ 1]);
2289 if (!strcmp(argv
[idx
], "-t")) {
2290 mnt_context_set_fstype_pattern(cxt
, argv
[idx
+ 1]);
2295 while (mnt_context_next_mount(cxt
, itr
, &fs
, &mntrc
, &ignored
) == 0) {
2297 const char *tgt
= mnt_fs_get_target(fs
);
2300 printf("%s: ignored: not match\n", tgt
);
2301 else if (ignored
== 2)
2302 printf("%s: ignored: already mounted\n", tgt
);
2304 else if (!mnt_context_get_status(cxt
)) {
2307 warn("%s: mount failed", tgt
);
2309 warnx("%s: mount failed", tgt
);
2311 printf("%s: successfully mounted\n", tgt
);
2314 mnt_free_context(cxt
);
2318 int main(int argc
, char *argv
[])
2320 struct libmnt_test tss
[] = {
2321 { "--mount", test_mount
, "[-o <opts>] [-t <type>] <spec>|<src> <target>" },
2322 { "--umount", test_umount
, "[-t <type>] [-f][-l][-r] <src>|<target>" },
2323 { "--mount-all", test_mountall
, "[-O <pattern>] [-t <pattern] mount all filesystems from fstab" },
2324 { "--flags", test_flags
, "[-o <opts>] <spec>" },
2327 umask(S_IWGRP
|S_IWOTH
); /* to be compatible with mount(8) */
2329 return mnt_run_test(tss
, argc
, argv
);
2332 #endif /* TEST_PROGRAM */