]>
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)
1099 * Returns: 0 on success, negative number in case of error.
1101 int mnt_context_set_passwd_cb(struct libmnt_context
*cxt
,
1102 char *(*get
)(struct libmnt_context
*),
1103 void (*release
)(struct libmnt_context
*, char *))
1108 cxt
->pwd_get_cb
= get
;
1109 cxt
->pwd_release_cb
= release
;
1114 * mnt_context_get_lock:
1115 * @cxt: mount context
1117 * The libmount applications don't have to care about mtab locking, but with a
1118 * small exception: the application has to be able to remove the lock file when
1119 * interrupted by signal or signals have to be ignored when the lock is locked.
1121 * The default behavior is to ignore all signals (except SIGALRM and
1122 * SIGTRAP for mtab udate) when the lock is locked. If this behavior
1123 * is unacceptable then use:
1125 * lc = mnt_context_get_lock(cxt);
1127 * mnt_lock_block_signals(lc, FALSE);
1129 * and don't forget to call mnt_unlock_file(lc) before exit.
1131 * Returns: pointer to lock struct or NULL.
1133 struct libmnt_lock
*mnt_context_get_lock(struct libmnt_context
*cxt
)
1136 * DON'T call this function within libmount, it will always allocate
1137 * the lock. The mnt_update_* functions are able to allocate the lock
1138 * only when mtab/utab update is really necessary.
1140 if (!cxt
|| mnt_context_is_nomtab(cxt
))
1144 cxt
->lock
= mnt_new_lock(cxt
->mtab_writable
?
1145 cxt
->mtab_path
: cxt
->utab_path
, 0);
1147 mnt_lock_block_signals(cxt
->lock
, TRUE
);
1153 * mnt_context_set_mflags:
1154 * @cxt: mount context
1155 * @flags: mount(2) flags (MS_* flags)
1157 * Sets mount flags (see mount(2) man page).
1159 * Note that mount context allows to define mount options by mount flags. It
1160 * means you can for example use
1162 * mnt_context_set_mflags(cxt, MS_NOEXEC | MS_NOSUID);
1166 * mnt_context_set_options(cxt, "noexec,nosuid");
1168 * these both calls have the same effect.
1170 * Returns: 0 on success, negative number in case of error.
1172 int mnt_context_set_mflags(struct libmnt_context
*cxt
, unsigned long flags
)
1177 cxt
->mountflags
= flags
;
1179 if ((cxt
->flags
& MNT_FL_MOUNTOPTS_FIXED
) && cxt
->fs
)
1181 * the final mount options are already generated, refresh...
1183 return mnt_optstr_apply_flags(
1184 &cxt
->fs
->vfs_optstr
,
1186 mnt_get_builtin_optmap(MNT_LINUX_MAP
));
1192 * mnt_context_get_mflags:
1193 * @cxt: mount context
1194 * @flags: returns MS_* mount flags
1196 * Converts mount options string to MS_* flags and bitewise-OR the result with
1197 * already defined flags (see mnt_context_set_mflags()).
1199 * Returns: 0 on success, negative number in case of error.
1201 int mnt_context_get_mflags(struct libmnt_context
*cxt
, unsigned long *flags
)
1208 if (!(cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
) && cxt
->fs
) {
1209 const char *o
= mnt_fs_get_options(cxt
->fs
);
1211 rc
= mnt_optstr_get_flags(o
, flags
,
1212 mnt_get_builtin_optmap(MNT_LINUX_MAP
));
1215 *flags
|= cxt
->mountflags
;
1220 * mnt_context_set_user_mflags:
1221 * @cxt: mount context
1222 * @flags: mount(2) flags (MNT_MS_* flags, e.g. MNT_MS_LOOP)
1224 * Sets userspace mount flags.
1226 * See also notest for mnt_context_set_mflags().
1228 * Returns: 0 on success, negative number in case of error.
1230 int mnt_context_set_user_mflags(struct libmnt_context
*cxt
, unsigned long flags
)
1234 cxt
->user_mountflags
= flags
;
1239 * mnt_context_get_user_mflags:
1240 * @cxt: mount context
1241 * @flags: returns mount flags
1243 * Converts mount options string to MNT_MS_* flags and bitewise-OR the result
1244 * with already defined flags (see mnt_context_set_user_mflags()).
1246 * Returns: 0 on success, negative number in case of error.
1248 int mnt_context_get_user_mflags(struct libmnt_context
*cxt
, unsigned long *flags
)
1255 if (!(cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
) && cxt
->fs
) {
1256 const char *o
= mnt_fs_get_user_options(cxt
->fs
);
1258 rc
= mnt_optstr_get_flags(o
, flags
,
1259 mnt_get_builtin_optmap(MNT_USERSPACE_MAP
));
1262 *flags
|= cxt
->user_mountflags
;
1267 * mnt_context_set_mountdata:
1268 * @cxt: mount context
1269 * @data: mount(2) data
1271 * The mount context generates mountdata from mount options by default. This
1272 * function allows to overwrite this behavior, and @data will be used instead
1275 * The libmount does not deallocated the data by mnt_free_context(). Note that
1276 * NULL is also valid mount data.
1278 * Returns: 0 on success, negative number in case of error.
1280 int mnt_context_set_mountdata(struct libmnt_context
*cxt
, void *data
)
1284 cxt
->mountdata
= data
;
1285 cxt
->flags
|= MNT_FL_MOUNTDATA
;
1290 * Translates LABEL/UUID/path to mountable path
1292 int mnt_context_prepare_srcpath(struct libmnt_context
*cxt
)
1294 const char *path
= NULL
;
1295 struct libmnt_cache
*cache
;
1296 const char *t
, *v
, *src
;
1301 assert((cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
));
1303 if (!cxt
|| !cxt
->fs
)
1306 DBG(CXT
, mnt_debug_h(cxt
, "preparing source path"));
1308 src
= mnt_fs_get_source(cxt
->fs
);
1310 if (!src
&& (cxt
->mountflags
& MS_PROPAGATION
))
1311 /* mount --make-{shared,private,...} */
1312 return mnt_fs_set_source(cxt
->fs
, "none");
1314 /* ignore filesystems without source or filesystems
1315 * where the source is quasi-path (//foo/bar)
1317 if (!src
|| mnt_fs_is_netfs(cxt
->fs
))
1320 DBG(CXT
, mnt_debug_h(cxt
, "srcpath '%s'", src
));
1322 cache
= mnt_context_get_cache(cxt
);
1324 if (!mnt_fs_get_tag(cxt
->fs
, &t
, &v
)) {
1326 * Source is TAG (evaluate)
1329 path
= mnt_resolve_tag(t
, v
, cache
);
1331 rc
= path
? mnt_fs_set_source(cxt
->fs
, path
) : -MNT_ERR_NOSOURCE
;
1333 } else if (cache
&& !mnt_fs_is_pseudofs(cxt
->fs
)) {
1335 * Source is PATH (canonicalize)
1337 path
= mnt_resolve_path(src
, cache
);
1338 if (path
&& strcmp(path
, src
))
1339 rc
= mnt_fs_set_source(cxt
->fs
, path
);
1343 DBG(CXT
, mnt_debug_h(cxt
, "failed to prepare srcpath [rc=%d]", rc
));
1350 if ((cxt
->mountflags
& (MS_BIND
| MS_MOVE
| MS_PROPAGATION
| MS_REMOUNT
)) ||
1351 mnt_fs_is_pseudofs(cxt
->fs
)) {
1352 DBG(CXT
, mnt_debug_h(cxt
, "REMOUNT/BIND/MOVE/pseudo FS source: %s", path
));
1357 * Initialize loop device
1359 if (mnt_context_is_loopdev(cxt
)) {
1360 rc
= mnt_context_setup_loopdev(cxt
);
1365 DBG(CXT
, mnt_debug_h(cxt
, "final srcpath '%s'",
1366 mnt_fs_get_source(cxt
->fs
)));
1370 int mnt_context_prepare_target(struct libmnt_context
*cxt
)
1373 struct libmnt_cache
*cache
;
1378 assert((cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
));
1380 if (!cxt
|| !cxt
->fs
)
1383 DBG(CXT
, mnt_debug_h(cxt
, "preparing target path"));
1385 tgt
= mnt_fs_get_target(cxt
->fs
);
1389 cache
= mnt_context_get_cache(cxt
);
1391 char *path
= mnt_resolve_path(tgt
, cache
);
1392 if (path
&& strcmp(path
, tgt
) != 0)
1393 rc
= mnt_fs_set_target(cxt
->fs
, path
);
1397 DBG(CXT
, mnt_debug_h(cxt
, "failed to prepare target '%s'", tgt
));
1399 DBG(CXT
, mnt_debug_h(cxt
, "final target '%s'",
1400 mnt_fs_get_target(cxt
->fs
)));
1405 * It's usully no error when we're not able to detect filesystem type -- we
1406 * will try to use types from /{etc,proc}/filesystems.
1408 int mnt_context_guess_fstype(struct libmnt_context
*cxt
)
1416 assert((cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
));
1418 if (!cxt
|| !cxt
->fs
)
1421 if (cxt
->mountflags
& (MS_BIND
| MS_MOVE
| MS_PROPAGATION
))
1424 type
= (char *) mnt_fs_get_fstype(cxt
->fs
);
1425 if (type
&& !strcmp(type
, "auto")) {
1426 mnt_fs_set_fstype(cxt
->fs
, NULL
);
1432 if (cxt
->flags
& MS_REMOUNT
)
1434 if (cxt
->fstype_pattern
)
1437 dev
= mnt_fs_get_srcpath(cxt
->fs
);
1441 if (access(dev
, F_OK
) == 0) {
1442 struct libmnt_cache
*cache
= mnt_context_get_cache(cxt
);
1444 type
= mnt_get_fstype(dev
, &cxt
->ambi
, cache
);
1446 rc
= mnt_fs_set_fstype(cxt
->fs
, type
);
1448 free(type
); /* type is not cached */
1451 if (strchr(dev
, ':') != NULL
)
1452 rc
= mnt_fs_set_fstype(cxt
->fs
, "nfs");
1453 else if (!strncmp(dev
, "//", 2))
1454 rc
= mnt_fs_set_fstype(cxt
->fs
, "cifs");
1458 DBG(CXT
, mnt_debug_h(cxt
, "FS type: %s", mnt_fs_get_fstype(cxt
->fs
)));
1461 return mnt_fs_set_fstype(cxt
->fs
, "none");
1465 * The default is to use fstype from cxt->fs, this could be overwritten by
1466 * @type. The @act is MNT_ACT_{MOUNT,UMOUNT}.
1468 * Returns: 0 on success or negative number in case of error. Note that success
1469 * does not mean that there is any usable helper, you have to check cxt->helper.
1471 int mnt_context_prepare_helper(struct libmnt_context
*cxt
, const char *name
,
1474 char search_path
[] = FS_SEARCH_PATH
; /* from config.h */
1475 char *p
= NULL
, *path
;
1479 assert((cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
));
1482 type
= mnt_fs_get_fstype(cxt
->fs
);
1484 if (type
&& strchr(type
, ','))
1485 return 0; /* type is fstype pattern */
1487 if (mnt_context_is_nohelpers(cxt
)
1489 || !strcmp(type
, "none")
1490 || mnt_fs_is_swaparea(cxt
->fs
))
1493 path
= strtok_r(search_path
, ":", &p
);
1495 char helper
[PATH_MAX
];
1499 rc
= snprintf(helper
, sizeof(helper
), "%s/%s.%s",
1501 path
= strtok_r(NULL
, ":", &p
);
1503 if (rc
< 0 || (size_t) rc
>= sizeof(helper
))
1506 rc
= stat(helper
, &st
);
1507 if (rc
== -1 && errno
== ENOENT
&& strchr(type
, '.')) {
1508 /* If type ends with ".subtype" try without it */
1509 char *hs
= strrchr(helper
, '.');
1512 rc
= stat(helper
, &st
);
1515 DBG(CXT
, mnt_debug_h(cxt
, "%-25s ... %s", helper
,
1516 rc
? "not found" : "found"));
1521 cxt
->helper
= strdup(helper
);
1530 int mnt_context_merge_mflags(struct libmnt_context
*cxt
)
1532 unsigned long fl
= 0;
1537 DBG(CXT
, mnt_debug_h(cxt
, "merging mount flags"));
1539 rc
= mnt_context_get_mflags(cxt
, &fl
);
1542 cxt
->mountflags
= fl
;
1545 rc
= mnt_context_get_user_mflags(cxt
, &fl
);
1548 cxt
->user_mountflags
= fl
;
1550 DBG(CXT
, mnt_debug_h(cxt
, "final flags: VFS=%08lx user=%08lx",
1551 cxt
->mountflags
, cxt
->user_mountflags
));
1553 cxt
->flags
|= MNT_FL_MOUNTFLAGS_MERGED
;
1558 * Prepare /etc/mtab or /run/mount/utab
1560 int mnt_context_prepare_update(struct libmnt_context
*cxt
)
1567 assert(cxt
->action
);
1568 assert((cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
));
1570 DBG(CXT
, mnt_debug_h(cxt
, "prepare update"));
1572 if (cxt
->mountflags
& MS_PROPAGATION
) {
1573 DBG(CXT
, mnt_debug_h(cxt
, "skip update: MS_PROPAGATION"));
1577 target
= mnt_fs_get_target(cxt
->fs
);
1579 if (cxt
->action
== MNT_ACT_UMOUNT
&& target
&& !strcmp(target
, "/"))
1580 /* Don't try to touch mtab if umounting root FS */
1581 mnt_context_disable_mtab(cxt
, TRUE
);
1583 if (mnt_context_is_nomtab(cxt
)) {
1584 DBG(CXT
, mnt_debug_h(cxt
, "skip update: NOMTAB flag"));
1588 DBG(CXT
, mnt_debug_h(cxt
, "skip update: external helper"));
1591 if (!cxt
->mtab_writable
&& !cxt
->utab_writable
) {
1592 DBG(CXT
, mnt_debug_h(cxt
, "skip update: no writable destination"));
1595 /* 0 = success, 1 = not called yet */
1596 if (cxt
->syscall_status
!= 1 && cxt
->syscall_status
!= 0) {
1597 DBG(CXT
, mnt_debug_h(cxt
,
1598 "skip update: syscall failed [status=%d]",
1599 cxt
->syscall_status
));
1603 cxt
->update
= mnt_new_update();
1607 mnt_update_set_filename(cxt
->update
,
1608 cxt
->mtab_writable
? cxt
->mtab_path
: cxt
->utab_path
,
1609 !cxt
->mtab_writable
);
1612 if (cxt
->action
== MNT_ACT_UMOUNT
)
1613 rc
= mnt_update_set_fs(cxt
->update
, cxt
->mountflags
,
1614 mnt_context_get_target(cxt
), NULL
);
1616 rc
= mnt_update_set_fs(cxt
->update
, cxt
->mountflags
,
1619 return rc
< 0 ? rc
: 0;
1622 int mnt_context_update_tabs(struct libmnt_context
*cxt
)
1628 if (mnt_context_is_nomtab(cxt
)) {
1629 DBG(CXT
, mnt_debug_h(cxt
, "don't update: NOMTAB flag"));
1633 DBG(CXT
, mnt_debug_h(cxt
, "don't update: external helper"));
1636 if (!cxt
->update
|| !mnt_update_is_ready(cxt
->update
)) {
1637 DBG(CXT
, mnt_debug_h(cxt
, "don't update: no update prepared"));
1640 if (cxt
->syscall_status
) {
1641 DBG(CXT
, mnt_debug_h(cxt
, "don't update: syscall failed/not called"));
1645 fl
= mnt_update_get_mflags(cxt
->update
);
1646 if ((cxt
->mountflags
& MS_RDONLY
) != (fl
& MS_RDONLY
))
1648 * fix MS_RDONLY in options
1650 mnt_update_force_rdonly(cxt
->update
,
1651 cxt
->mountflags
& MS_RDONLY
);
1653 return mnt_update_table(cxt
->update
, cxt
->lock
);
1656 static int apply_table(struct libmnt_context
*cxt
, struct libmnt_table
*tb
,
1659 struct libmnt_fs
*fs
= NULL
;
1660 const char *src
= NULL
, *tgt
= NULL
;
1669 src
= mnt_fs_get_source(cxt
->fs
);
1670 tgt
= mnt_fs_get_target(cxt
->fs
);
1673 fs
= mnt_table_find_pair(tb
, src
, tgt
, direction
);
1676 fs
= mnt_table_find_source(tb
, src
, direction
);
1678 fs
= mnt_table_find_target(tb
, tgt
, direction
);
1680 if (!fs
&& mnt_context_is_swapmatch(cxt
)) {
1681 /* swap source and target (if @src is not LABEL/UUID),
1686 * the path could be a mountpoint as well as source (for
1687 * example bind mount, symlink to device, ...).
1689 if (src
&& !mnt_fs_get_tag(cxt
->fs
, NULL
, NULL
))
1690 fs
= mnt_table_find_target(tb
, src
, direction
);
1692 fs
= mnt_table_find_source(tb
, tgt
, direction
);
1697 return -MNT_ERR_NOFSTAB
; /* not found */
1699 DBG(CXT
, mnt_debug_h(cxt
, "apply entry:"));
1700 DBG(CXT
, mnt_fs_print_debug(fs
, stderr
));
1702 /* copy from tab to our FS description
1704 rc
= mnt_fs_set_source(cxt
->fs
, mnt_fs_get_source(fs
));
1706 rc
= mnt_fs_set_target(cxt
->fs
, mnt_fs_get_target(fs
));
1708 if (!rc
&& !mnt_fs_get_fstype(cxt
->fs
))
1709 rc
= mnt_fs_set_fstype(cxt
->fs
, mnt_fs_get_fstype(fs
));
1714 if (cxt
->optsmode
& MNT_OMODE_IGNORE
)
1716 else if (cxt
->optsmode
& MNT_OMODE_REPLACE
)
1717 rc
= mnt_fs_set_options(cxt
->fs
, mnt_fs_get_options(fs
));
1719 else if (cxt
->optsmode
& MNT_OMODE_APPEND
)
1720 rc
= mnt_fs_append_options(cxt
->fs
, mnt_fs_get_options(fs
));
1722 else if (cxt
->optsmode
& MNT_OMODE_PREPEND
)
1723 rc
= mnt_fs_prepend_options(cxt
->fs
, mnt_fs_get_options(fs
));
1726 cxt
->flags
|= MNT_FL_TAB_APPLIED
;
1731 * mnt_context_apply_fstab:
1732 * @cxt: mount context
1734 * This function is optional.
1736 * Returns: 0 on success, negative number in case of error.
1738 int mnt_context_apply_fstab(struct libmnt_context
*cxt
)
1741 struct libmnt_table
*tab
= NULL
;
1742 const char *src
= NULL
, *tgt
= NULL
;
1750 if (mnt_context_tab_applied(cxt
)) /* already applied */
1753 if (mnt_context_is_restricted(cxt
)) {
1754 DBG(CXT
, mnt_debug_h(cxt
, "force fstab usage for non-root users!"));
1755 cxt
->optsmode
= MNT_OMODE_USER
;
1756 } else if (cxt
->optsmode
== 0) {
1757 DBG(CXT
, mnt_debug_h(cxt
, "use default optmode"));
1758 cxt
->optsmode
= MNT_OMODE_AUTO
;
1759 } else if (cxt
->optsmode
& MNT_OMODE_NOTAB
) {
1760 cxt
->optsmode
&= ~MNT_OMODE_FSTAB
;
1761 cxt
->optsmode
&= ~MNT_OMODE_MTAB
;
1762 cxt
->optsmode
&= ~MNT_OMODE_FORCE
;
1766 src
= mnt_fs_get_source(cxt
->fs
);
1767 tgt
= mnt_fs_get_target(cxt
->fs
);
1770 DBG(CXT
, mnt_debug_h(cxt
, "OPTSMODE: ignore=%d, append=%d, prepend=%d, "
1771 "replace=%d, force=%d, fstab=%d, mtab=%d",
1772 cxt
->optsmode
& MNT_OMODE_IGNORE
? 1 : 0,
1773 cxt
->optsmode
& MNT_OMODE_APPEND
? 1 : 0,
1774 cxt
->optsmode
& MNT_OMODE_PREPEND
? 1 : 0,
1775 cxt
->optsmode
& MNT_OMODE_REPLACE
? 1 : 0,
1776 cxt
->optsmode
& MNT_OMODE_FORCE
? 1 : 0,
1777 cxt
->optsmode
& MNT_OMODE_FSTAB
? 1 : 0,
1778 cxt
->optsmode
& MNT_OMODE_MTAB
? 1 : 0));
1780 /* fstab is not required if source and target are specified */
1781 if (src
&& tgt
&& !(cxt
->optsmode
& MNT_OMODE_FORCE
)) {
1782 DBG(CXT
, mnt_debug_h(cxt
, "fstab not required -- skip"));
1787 && !(cxt
->optsmode
& MNT_OMODE_FSTAB
)
1788 && !(cxt
->optsmode
& MNT_OMODE_MTAB
)) {
1789 DBG(CXT
, mnt_debug_h(cxt
, "only target; fstab/mtab not required "
1790 "-- skip, probably MS_PROPAGATION"));
1794 DBG(CXT
, mnt_debug_h(cxt
,
1795 "trying to apply fstab (src=%s, target=%s)", src
, tgt
));
1797 /* let's initialize cxt->fs */
1798 mnt_context_get_fs(cxt
);
1801 if (cxt
->optsmode
& MNT_OMODE_FSTAB
) {
1802 rc
= mnt_context_get_fstab(cxt
, &tab
);
1804 rc
= apply_table(cxt
, tab
, MNT_ITER_FORWARD
);
1808 if (rc
< 0 && (cxt
->optsmode
& MNT_OMODE_MTAB
)) {
1809 DBG(CXT
, mnt_debug_h(cxt
, "trying to apply from mtab"));
1810 rc
= mnt_context_get_mtab(cxt
, &tab
);
1812 rc
= apply_table(cxt
, tab
, MNT_ITER_BACKWARD
);
1815 DBG(CXT
, mnt_debug_h(cxt
, "failed to find entry in fstab/mtab"));
1820 * mnt_context_tab_applied:
1821 * @cxt: mount context
1823 * Returns: 1 if fstab (or mtab) has been applied to the context, or 0.
1825 int mnt_context_tab_applied(struct libmnt_context
*cxt
)
1827 return cxt
&& (cxt
->flags
& MNT_FL_TAB_APPLIED
);
1831 * mnt_context_get_status:
1832 * @cxt: mount context
1834 * Global libmount status.
1836 * The real exit code of the mount.type helper has to be tested by
1837 * mnt_context_get_helper_status(). The mnt_context_get_status() only inform
1838 * that exec() has been successful.
1840 * Returns: 1 if mount.type or mount(2) syscall has been successfully called.
1842 int mnt_context_get_status(struct libmnt_context
*cxt
)
1844 return cxt
&& (!cxt
->syscall_status
|| !cxt
->helper_exec_status
);
1848 * mnt_context_helper_executed:
1849 * @cxt: mount context
1851 * Returns: 1 if mount.type helper has been executed, or 0.
1853 int mnt_context_helper_executed(struct libmnt_context
*cxt
)
1855 return cxt
->helper_exec_status
!= 1;
1859 * mnt_context_get_helper_status:
1860 * @cxt: mount context
1862 * Return: mount.type helper exit status, result is reliable only if
1863 * mnt_context_helper_executed() returns 1.
1865 int mnt_context_get_helper_status(struct libmnt_context
*cxt
)
1867 return cxt
->helper_status
;
1871 * mnt_context_syscall_called:
1872 * @cxt: mount context
1874 * Returns: 1 if mount(2) syscall has been called, or 0.
1876 int mnt_context_syscall_called(struct libmnt_context
*cxt
)
1878 return cxt
->syscall_status
!= 1;
1882 * mnt_context_get_syscall_errno:
1883 * @cxt: mount context
1885 * The result from this function is reliable only if
1886 * mnt_context_syscall_called() returns 1.
1888 * Returns: mount(2) errno if the syscall failed or 0.
1890 int mnt_context_get_syscall_errno(struct libmnt_context
*cxt
)
1892 if (cxt
->syscall_status
< 0)
1893 return -cxt
->syscall_status
;
1899 * mnt_context_set_syscall_status:
1900 * @cxt: mount context
1901 * @status: mount(2) status
1903 * The @status should be 0 on success, or negative number on error (-errno).
1905 * This function should be used only if [u]mount(2) syscall is NOT called by
1908 * Returns: 0 or negative number in case of error.
1910 int mnt_context_set_syscall_status(struct libmnt_context
*cxt
, int status
)
1915 DBG(CXT
, mnt_debug_h(cxt
, "syscall status set to: %d", status
));
1916 cxt
->syscall_status
= status
;
1921 * mnt_context_strerror
1924 * @bufsiz: size of the buffer
1926 * Not implemented yet.
1928 * Returns: 0 or negative number in case of error.
1930 int mnt_context_strerror(struct libmnt_context
*cxt
__attribute__((__unused__
)),
1931 char *buf
__attribute__((__unused__
)),
1932 size_t bufsiz
__attribute__((__unused__
)))
1934 /* TODO: based on cxt->syscall_errno or cxt->helper_status */
1939 * mnt_context_init_helper
1940 * @cxt: mount context
1941 * @action: MNT_ACT_{UMOUNT,MOUNT}
1942 * @flags: not used now
1944 * This function infors libmount that used from [u]mount.type helper.
1946 * The function also calls mnt_context_disable_helpers() to avoid recursive
1947 * mount.type helpers calling. It you really want to call another
1948 * mount.type helper from your helper than you have to explicitly enable this
1951 * mnt_context_disable_helpers(cxt, FALSE);
1953 * Returns: 0 on success, negative number in case of error.
1955 int mnt_context_init_helper(struct libmnt_context
*cxt
, int action
,
1956 int flags
__attribute__((__unused__
)))
1958 int rc
= mnt_context_disable_helpers(cxt
, TRUE
);
1961 rc
= set_flag(cxt
, MNT_FL_HELPER
, 1);
1963 cxt
->action
= action
;
1965 DBG(CXT
, mnt_debug_h(cxt
, "initialized for [u]mount.<type> helper [rc=%d]", rc
));
1970 * mnt_context_helper_setopt:
1972 * @c: getopt() result
1973 * @arg: getopt() optarg
1975 * This function applies [u]mount.type command line option (for example parsed
1976 * by getopt or getopt_long) to @cxt. All unknown options are ignored and
1977 * then 1 is returned.
1979 * Returns: negative number on error, 1 if @c is unknown option, 0 on success.
1981 int mnt_context_helper_setopt(struct libmnt_context
*cxt
, int c
, char *arg
)
1984 switch(cxt
->action
) {
1986 return mnt_context_mount_setopt(cxt
, c
, arg
);
1987 case MNT_ACT_UMOUNT
:
1988 return mnt_context_umount_setopt(cxt
, c
, arg
);
1995 * mnt_context_is_fs_mounted:
1998 * @mounted: returns 1 for mounted and 0 for non-mounted filesystems
2000 * Please, read mnt_table_is_fs_mounted() description!
2002 * Returns: 0 on success and negative number in case of error.
2004 int mnt_context_is_fs_mounted(struct libmnt_context
*cxt
,
2005 struct libmnt_fs
*fs
, int *mounted
)
2007 struct libmnt_table
*mtab
;
2010 if (!cxt
|| !fs
|| !mounted
)
2013 rc
= mnt_context_get_mtab(cxt
, &mtab
);
2017 *mounted
= mnt_table_is_fs_mounted(mtab
, fs
);
2021 static int mnt_context_add_child(struct libmnt_context
*cxt
, pid_t pid
)
2028 pids
= realloc(cxt
->children
, sizeof(pid_t
) * cxt
->nchildren
+ 1);
2032 DBG(CXT
, mnt_debug_h(cxt
, "add new child %d", pid
));
2033 cxt
->children
= pids
;
2034 cxt
->children
[cxt
->nchildren
++] = pid
;
2039 int mnt_fork_context(struct libmnt_context
*cxt
)
2044 if (!mnt_context_is_parent(cxt
))
2047 DBG(CXT
, mnt_debug_h(cxt
, "forking context"));
2054 case -1: /* error */
2055 DBG(CXT
, mnt_debug_h(cxt
, "fork failed %m"));
2059 cxt
->pid
= getpid();
2060 mnt_context_enable_fork(cxt
, FALSE
);
2061 DBG(CXT
, mnt_debug_h(cxt
, "child created"));
2065 rc
= mnt_context_add_child(cxt
, pid
);
2072 int mnt_context_wait_for_children(struct libmnt_context
*cxt
,
2073 int *nchildren
, int *nerrs
)
2080 assert(mnt_context_is_parent(cxt
));
2082 for (i
= 0; i
< cxt
->nchildren
; i
++) {
2083 pid_t pid
= cxt
->children
[i
];
2084 int rc
= 0, ret
= 0;
2089 DBG(CXT
, mnt_debug_h(cxt
,
2090 "waiting for child (%d/%d): %d",
2091 i
+ 1, cxt
->nchildren
, pid
));
2093 rc
= waitpid(pid
, &ret
, 0);
2095 } while (rc
== -1 && errno
== EINTR
);
2100 if (rc
!= -1 && nerrs
) {
2102 (*nerrs
) += WEXITSTATUS(ret
) == 0 ? 0 : 1;
2106 cxt
->children
[i
] = 0;
2110 free(cxt
->children
);
2111 cxt
->children
= NULL
;
2119 struct libmnt_lock
*lock
;
2121 static void lock_fallback(void)
2124 mnt_unlock_file(lock
);
2127 int test_mount(struct libmnt_test
*ts
, int argc
, char *argv
[])
2129 int idx
= 1, rc
= 0;
2130 struct libmnt_context
*cxt
;
2135 cxt
= mnt_new_context();
2139 if (!strcmp(argv
[idx
], "-o")) {
2140 mnt_context_set_options(cxt
, argv
[idx
+ 1]);
2143 if (!strcmp(argv
[idx
], "-t")) {
2144 /* TODO: use mnt_context_set_fstype_pattern() */
2145 mnt_context_set_fstype(cxt
, argv
[idx
+ 1]);
2149 if (argc
== idx
+ 1)
2150 /* mount <mountpont>|<device> */
2151 mnt_context_set_target(cxt
, argv
[idx
++]);
2153 else if (argc
== idx
+ 2) {
2154 /* mount <device> <mountpoint> */
2155 mnt_context_set_source(cxt
, argv
[idx
++]);
2156 mnt_context_set_target(cxt
, argv
[idx
++]);
2159 /* this is unnecessary! -- libmount is able to internaly
2160 * create and manage the lock
2162 lock
= mnt_context_get_lock(cxt
);
2164 atexit(lock_fallback
);
2166 rc
= mnt_context_mount(cxt
);
2168 printf("failed to mount: %m\n");
2170 printf("successfully mounted\n");
2172 lock
= NULL
; /* because we use atexit lock_fallback */
2173 mnt_free_context(cxt
);
2177 int test_umount(struct libmnt_test
*ts
, int argc
, char *argv
[])
2179 int idx
= 1, rc
= 0;
2180 struct libmnt_context
*cxt
;
2185 cxt
= mnt_new_context();
2189 if (!strcmp(argv
[idx
], "-t")) {
2190 mnt_context_set_fstype(cxt
, argv
[idx
+ 1]);
2194 if (!strcmp(argv
[idx
], "-f")) {
2195 mnt_context_enable_force(cxt
, TRUE
);
2199 if (!strcmp(argv
[idx
], "-l")) {
2200 mnt_context_enable_lazy(cxt
, TRUE
);
2204 if (!strcmp(argv
[idx
], "-r")) {
2205 mnt_context_enable_rdonly_umount(cxt
, TRUE
);
2209 if (argc
== idx
+ 1) {
2210 /* mount <mountpont>|<device> */
2211 mnt_context_set_target(cxt
, argv
[idx
++]);
2217 lock
= mnt_context_get_lock(cxt
);
2219 atexit(lock_fallback
);
2221 rc
= mnt_context_umount(cxt
);
2223 printf("failed to umount\n");
2225 printf("successfully umounted\n");
2227 lock
= NULL
; /* because we use atexit lock_fallback */
2228 mnt_free_context(cxt
);
2232 int test_flags(struct libmnt_test
*ts
, int argc
, char *argv
[])
2234 int idx
= 1, rc
= 0;
2235 struct libmnt_context
*cxt
;
2236 const char *opt
= NULL
;
2237 unsigned long flags
= 0;
2242 cxt
= mnt_new_context();
2246 if (!strcmp(argv
[idx
], "-o")) {
2247 mnt_context_set_options(cxt
, argv
[idx
+ 1]);
2251 if (argc
== idx
+ 1)
2252 /* mount <mountpont>|<device> */
2253 mnt_context_set_target(cxt
, argv
[idx
++]);
2255 rc
= mnt_context_prepare_mount(cxt
);
2257 printf("failed to prepare mount %s\n", strerror(-rc
));
2259 opt
= mnt_fs_get_options(cxt
->fs
);
2261 fprintf(stdout
, "options: %s\n", opt
);
2263 mnt_context_get_mflags(cxt
, &flags
);
2264 fprintf(stdout
, "flags: %08lx\n", flags
);
2266 mnt_free_context(cxt
);
2270 int test_mountall(struct libmnt_test
*ts
, int argc
, char *argv
[])
2272 struct libmnt_context
*cxt
;
2273 struct libmnt_iter
*itr
;
2274 struct libmnt_fs
*fs
;
2275 int mntrc
, ignored
, idx
= 1;
2277 cxt
= mnt_new_context();
2278 itr
= mnt_new_iter(MNT_ITER_FORWARD
);
2284 if (!strcmp(argv
[idx
], "-O")) {
2285 mnt_context_set_options_pattern(cxt
, argv
[idx
+ 1]);
2288 if (!strcmp(argv
[idx
], "-t")) {
2289 mnt_context_set_fstype_pattern(cxt
, argv
[idx
+ 1]);
2294 while (mnt_context_next_mount(cxt
, itr
, &fs
, &mntrc
, &ignored
) == 0) {
2296 const char *tgt
= mnt_fs_get_target(fs
);
2299 printf("%s: ignored: not match\n", tgt
);
2300 else if (ignored
== 2)
2301 printf("%s: ignored: already mounted\n", tgt
);
2303 else if (!mnt_context_get_status(cxt
)) {
2306 warn("%s: mount failed", tgt
);
2308 warnx("%s: mount failed", tgt
);
2310 printf("%s: successfully mounted\n", tgt
);
2313 mnt_free_context(cxt
);
2317 int main(int argc
, char *argv
[])
2319 struct libmnt_test tss
[] = {
2320 { "--mount", test_mount
, "[-o <opts>] [-t <type>] <spec>|<src> <target>" },
2321 { "--umount", test_umount
, "[-t <type>] [-f][-l][-r] <src>|<target>" },
2322 { "--mount-all", test_mountall
, "[-O <pattern>] [-t <pattern] mount all filesystems from fstab" },
2323 { "--flags", test_flags
, "[-o <opts>] <spec>" },
2326 umask(S_IWGRP
|S_IWOTH
); /* to be compatible with mount(8) */
2328 return mnt_run_test(tss
, argc
, argv
);
2331 #endif /* TEST_PROGRAM */