]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - libmount/src/context.c
2 * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
4 * This file may be redistributed under the terms of the
5 * GNU Lesser General Public License.
10 * @title: Library high-level context
11 * @short_description: high-level API to mount/umount devices.
15 * struct libmnt_context *cxt = mnt_new_context();
17 * mnt_context_set_options(cxt, "aaa,bbb,ccc=CCC");
18 * mnt_context_set_mflags(cxt, MS_NOATIME|MS_NOEXEC);
19 * mnt_context_set_target(cxt, "/mnt/foo");
21 * if (!mnt_context_mount(cxt))
22 * printf("successfully mounted\n");
23 * mnt_free_context(cxt);
28 * This code is similar to:
30 * mount -o aaa,bbb,ccc=CCC,noatime,noexec /mnt/foo
39 * Returns: newly allocated mount context
41 struct libmnt_context
*mnt_new_context(void)
43 struct libmnt_context
*cxt
;
46 cxt
= calloc(1, sizeof(*cxt
));
53 cxt
->syscall_status
= 1; /* not called yet */
54 cxt
->helper_exec_status
= 1;
57 /* if we're really root and aren't running setuid */
58 cxt
->restricted
= (uid_t
) 0 == ruid
&& ruid
== euid
? 0 : 1;
60 DBG(CXT
, mnt_debug_h(cxt
, "----> allocate %s",
61 cxt
->restricted
? "[RESTRICTED]" : ""));
63 mnt_has_regular_mtab(&cxt
->mtab_path
, &cxt
->mtab_writable
);
65 if (!cxt
->mtab_writable
)
66 /* use /run/mount/utab if /etc/mtab is useless */
67 mnt_has_regular_utab(&cxt
->utab_path
, &cxt
->utab_writable
);
76 * Deallocates context struct.
78 void mnt_free_context(struct libmnt_context
*cxt
)
83 mnt_reset_context(cxt
);
85 free(cxt
->fstype_pattern
);
86 free(cxt
->optstr_pattern
);
88 if (!(cxt
->flags
& MNT_FL_EXTERN_FSTAB
))
89 mnt_free_table(cxt
->fstab
);
90 if (!(cxt
->flags
& MNT_FL_EXTERN_CACHE
))
91 mnt_free_cache(cxt
->cache
);
93 mnt_context_clear_loopdev(cxt
);
94 mnt_free_lock(cxt
->lock
);
95 mnt_free_update(cxt
->update
);
97 DBG(CXT
, mnt_debug_h(cxt
, "<---- free"));
103 * @cxt: mount context
105 * Resets all information in the context that are directly related to
106 * the latest mount (spec, source, target, mount options, ....)
108 * The match patters, cached fstab, cached canonicalized paths and tags and
109 * [e]uid are not reseted. You have to use
111 * mnt_context_set_fstab(cxt, NULL);
112 * mnt_context_set_cache(cxt, NULL);
113 * mnt_context_set_fstype_pattern(cxt, NULL);
114 * mnt_context_set_options_pattern(cxt, NULL);
117 * to reset these stuff.
119 * Returns: 0 on success, negative number in case of error.
121 int mnt_reset_context(struct libmnt_context
*cxt
)
128 DBG(CXT
, mnt_debug_h(cxt
, "<---- reset [status=%d] ---->",
129 mnt_context_get_status(cxt
)));
133 if (!(cxt
->flags
& MNT_FL_EXTERN_FS
))
134 mnt_free_fs(cxt
->fs
);
136 mnt_free_table(cxt
->mtab
);
139 free(cxt
->orig_user
);
145 cxt
->orig_user
= NULL
;
147 cxt
->user_mountflags
= 0;
148 cxt
->mountdata
= NULL
;
149 cxt
->flags
= MNT_FL_DEFAULT
;
150 cxt
->syscall_status
= 1;
151 cxt
->helper_exec_status
= 1;
152 cxt
->helper_status
= 0;
154 /* restore non-resetable flags */
155 cxt
->flags
|= (fl
& MNT_FL_EXTERN_FSTAB
);
156 cxt
->flags
|= (fl
& MNT_FL_EXTERN_CACHE
);
157 cxt
->flags
|= (fl
& MNT_FL_NOMTAB
);
158 cxt
->flags
|= (fl
& MNT_FL_FAKE
);
159 cxt
->flags
|= (fl
& MNT_FL_SLOPPY
);
160 cxt
->flags
|= (fl
& MNT_FL_VERBOSE
);
161 cxt
->flags
|= (fl
& MNT_FL_NOHELPERS
);
162 cxt
->flags
|= (fl
& MNT_FL_LOOPDEL
);
163 cxt
->flags
|= (fl
& MNT_FL_LAZY
);
164 cxt
->flags
|= (fl
& MNT_FL_FORCE
);
165 cxt
->flags
|= (fl
& MNT_FL_NOCANONICALIZE
);
166 cxt
->flags
|= (fl
& MNT_FL_RDONLY_UMOUNT
);
170 static int set_flag(struct libmnt_context
*cxt
, int flag
, int enable
)
182 * mnt_context_is_restricted:
183 * @cxt: mount context
185 * Returns: 0 for unrestricted mount (user is root), or 1 for non-root mounts
187 int mnt_context_is_restricted(struct libmnt_context
*cxt
)
190 return cxt
->restricted
;
194 * mnt_context_set_optsmode
195 * @cxt: mount context
196 * @mode: mask, see MNT_OMASK_* flags in libmount mount.h
198 * Controls how to use mount options from fstab/mtab.
200 * Returns: 0 on success, negative number in case of error.
202 int mnt_context_set_optsmode(struct libmnt_context
*cxt
, int mode
)
206 cxt
->optsmode
= mode
;
211 * mnt_context_get_optsmode
212 * @cxt: mount context
214 * Returns: MNT_OMASK_* mask or zero.
217 int mnt_context_get_optsmode(struct libmnt_context
*cxt
)
219 return cxt
? cxt
->optsmode
: 0;
223 * mnt_context_disable_canonicalize:
224 * @cxt: mount context
225 * @disable: TRUE or FALSE
227 * Enable/disable paths canonicalization and tags evaluation. The libmount context
228 * canonicalies paths when search in fstab and when prepare source and target paths
229 * for mount(2) syscall.
231 * This fuction has effect to the private fstab instance only (see
232 * mnt_context_set_fstab()). If you want to use an external fstab then you need
233 * manage your private struct libmnt_cache (see mnt_table_set_cache(fstab, NULL).
235 * Returns: 0 on success, negative number in case of error.
237 int mnt_context_disable_canonicalize(struct libmnt_context
*cxt
, int disable
)
239 return set_flag(cxt
, MNT_FL_NOCANONICALIZE
, disable
);
243 * mnt_context_enable_lazy:
244 * @cxt: mount context
245 * @enable: TRUE or FALSE
247 * Enable/disable lazy umount (see umount(8) man page, option -l).
249 * Returns: 0 on success, negative number in case of error.
251 int mnt_context_enable_lazy(struct libmnt_context
*cxt
, int enable
)
253 return set_flag(cxt
, MNT_FL_LAZY
, enable
);
257 * mnt_context_is_lazy:
258 * @cxt: mount context
260 * Returns: 1 if lazy umount is enabled or 0
262 int mnt_context_is_lazy(struct libmnt_context
*cxt
)
264 return cxt
&& (cxt
->flags
& MNT_FL_LAZY
) ? 1 : 0;
269 * mnt_context_enable_rdonly_umount:
270 * @cxt: mount context
271 * @enable: TRUE or FALSE
273 * Enable/disable read-only remount on failed umount(2)
274 * (see umount(8) man page, option -r).
276 * Returns: 0 on success, negative number in case of error.
278 int mnt_context_enable_rdonly_umount(struct libmnt_context
*cxt
, int enable
)
280 return set_flag(cxt
, MNT_FL_RDONLY_UMOUNT
, enable
);
284 * mnt_context_is_rdonly_umount
285 * @cxt: mount context
287 * See also mnt_context_enable_rdonly_umount() and see umount(8) man page,
290 * Returns: 1 if read-only remount failed umount(2) is enables or 0
292 int mnt_context_is_rdonly_umount(struct libmnt_context
*cxt
)
294 return cxt
&& (cxt
->flags
& MNT_FL_RDONLY_UMOUNT
) ? 1 : 0;
298 * mnt_context_disable_helpers:
299 * @cxt: mount context
300 * @disable: TRUE or FALSE
302 * Enable/disable /sbin/[u]mount.* helpers (see mount(8) man page, option -i).
304 * Returns: 0 on success, negative number in case of error.
306 int mnt_context_disable_helpers(struct libmnt_context
*cxt
, int disable
)
308 return set_flag(cxt
, MNT_FL_NOHELPERS
, disable
);
312 * mnt_context_enable_sloppy:
313 * @cxt: mount context
314 * @enable: TRUE or FALSE
316 * Set/unset sloppy mounting (see mount(8) man page, option -s).
318 * Returns: 0 on success, negative number in case of error.
320 int mnt_context_enable_sloppy(struct libmnt_context
*cxt
, int enable
)
322 return set_flag(cxt
, MNT_FL_SLOPPY
, enable
);
326 * mnt_context_is_sloppy:
327 * @cxt: mount context
329 * Returns: 1 if sloppy flag is enabled or 0
331 int mnt_context_is_sloppy(struct libmnt_context
*cxt
)
333 return cxt
&& (cxt
->flags
& MNT_FL_SLOPPY
) ? 1 : 0;
337 * mnt_context_enable_fake:
338 * @cxt: mount context
339 * @enable: TRUE or FALSE
341 * Enable/disable fake mounting (see mount(8) man page, option -f).
343 * Returns: 0 on success, negative number in case of error.
345 int mnt_context_enable_fake(struct libmnt_context
*cxt
, int enable
)
347 return set_flag(cxt
, MNT_FL_FAKE
, enable
);
351 * mnt_context_is_fake:
352 * @cxt: mount context
354 * Returns: 1 if fake flag is enabled or 0
356 int mnt_context_is_fake(struct libmnt_context
*cxt
)
358 return cxt
&& (cxt
->flags
& MNT_FL_FAKE
) ? 1 : 0;
362 * mnt_context_disable_mtab:
363 * @cxt: mount context
364 * @disable: TRUE or FALSE
366 * Disable/enable mtab update (see mount(8) man page, option -n).
368 * Returns: 0 on success, negative number in case of error.
370 int mnt_context_disable_mtab(struct libmnt_context
*cxt
, int disable
)
372 return set_flag(cxt
, MNT_FL_NOMTAB
, disable
);
376 * mnt_context_is_nomtab
377 * @cxt: mount context
379 * Returns: 1 if no-mtab is enabled or 0
381 int mnt_context_is_nomtab(struct libmnt_context
*cxt
)
383 return cxt
&& (cxt
->flags
& MNT_FL_NOMTAB
) ? 1 : 0;
387 * mnt_context_enable_force:
388 * @cxt: mount context
389 * @enable: TRUE or FALSE
391 * Enable/disable force umounting (see umount(8) man page, option -f).
393 * Returns: 0 on success, negative number in case of error.
395 int mnt_context_enable_force(struct libmnt_context
*cxt
, int enable
)
397 return set_flag(cxt
, MNT_FL_FORCE
, enable
);
401 * mnt_context_is_force
402 * @cxt: mount context
404 * Returns: 1 if force umounting flag is enabled or 0
406 int mnt_context_is_force(struct libmnt_context
*cxt
)
408 return cxt
&& (cxt
->flags
& MNT_FL_FORCE
) ? 1 : 0;
412 * mnt_context_enable_verbose:
413 * @cxt: mount context
414 * @enable: TRUE or FALSE
416 * Enable/disable verbose output (TODO: not implemented yet)
418 * Returns: 0 on success, negative number in case of error.
420 int mnt_context_enable_verbose(struct libmnt_context
*cxt
, int enable
)
422 return set_flag(cxt
, MNT_FL_VERBOSE
, enable
);
426 * mnt_context_is_verbose
427 * @cxt: mount context
429 * Returns: 1 if verbose flag is enabled or 0
431 int mnt_context_is_verbose(struct libmnt_context
*cxt
)
433 return cxt
&& (cxt
->flags
& MNT_FL_VERBOSE
) ? 1 : 0;
437 * mnt_context_enable_loopdel:
438 * @cxt: mount context
439 * @enable: TRUE or FALSE
441 * Enable/disable loop delete (destroy) after umount (see umount(8), option -d)
443 * Returns: 0 on success, negative number in case of error.
445 int mnt_context_enable_loopdel(struct libmnt_context
*cxt
, int enable
)
447 return set_flag(cxt
, MNT_FL_LOOPDEL
, enable
);
451 * mnt_context_set_fs:
452 * @cxt: mount context
453 * @fs: filesystem description
455 * The mount context uses private @fs by default. This function allows to
456 * overwrite the private @fs with an external instance. Note that the external
457 * @fs instance is not deallocated by mnt_free_context() or mnt_reset_context().
459 * The @fs will be modified by mnt_context_set_{source,target,options,fstype}
460 * functions, If the @fs is NULL then all current FS specific setting (source,
461 * target, etc., exclude spec) is reseted.
463 * Returns: 0 on success, negative number in case of error.
465 int mnt_context_set_fs(struct libmnt_context
*cxt
, struct libmnt_fs
*fs
)
469 if (!(cxt
->flags
& MNT_FL_EXTERN_FS
))
470 mnt_free_fs(cxt
->fs
);
472 set_flag(cxt
, MNT_FL_EXTERN_FS
, fs
!= NULL
);
478 * mnt_context_get_fs:
479 * @cxt: mount context
481 * The FS contains the basic description of mountpoint, fs type and so on.
482 * Note that the FS is modified by mnt_context_set_{source,target,options,fstype}
485 * Returns: pointer to FS description or NULL in case of calloc() errrr.
487 struct libmnt_fs
*mnt_context_get_fs(struct libmnt_context
*cxt
)
492 cxt
->fs
= mnt_new_fs();
493 cxt
->flags
&= ~MNT_FL_EXTERN_FS
;
499 * mnt_context_set_source:
500 * @cxt: mount context
501 * @source: mount source (device, directory, UUID, LABEL, ...)
503 * Returns: 0 on success, negative number in case of error.
505 int mnt_context_set_source(struct libmnt_context
*cxt
, const char *source
)
507 return mnt_fs_set_source(mnt_context_get_fs(cxt
), source
);
511 * mnt_context_get_source:
512 * @cxt: mount context
514 * Returns: returns pointer or NULL in case of error pr if not set.
516 const char *mnt_context_get_source(struct libmnt_context
*cxt
)
518 return mnt_fs_get_source(mnt_context_get_fs(cxt
));
522 * mnt_context_set_target:
523 * @cxt: mount context
524 * @target: mountpoint
526 * Returns: 0 on success, negative number in case of error.
528 int mnt_context_set_target(struct libmnt_context
*cxt
, const char *target
)
530 return mnt_fs_set_target(mnt_context_get_fs(cxt
), target
);
534 * mnt_context_get_target:
535 * @cxt: mount context
537 * Returns: returns pointer or NULL in case of error pr if not set.
539 const char *mnt_context_get_target(struct libmnt_context
*cxt
)
541 return mnt_fs_get_target(mnt_context_get_fs(cxt
));
545 * mnt_context_set_fstype:
546 * @cxt: mount context
547 * @fstype: filesystem type
549 * Note that the @fstype has to be the real FS type. For comma-separated list of
550 * filesystems or for "nofs" notation use mnt_context_set_fstype_pattern().
552 * Returns: 0 on success, negative number in case of error.
554 int mnt_context_set_fstype(struct libmnt_context
*cxt
, const char *fstype
)
556 if (fstype
&& strchr(fstype
, ','))
558 return mnt_fs_set_fstype(mnt_context_get_fs(cxt
), fstype
);
562 * mnt_context_get_fstype:
563 * @cxt: mount context
565 * Returns: returns pointer or NULL in case of error pr if not set.
567 const char *mnt_context_get_fstype(struct libmnt_context
*cxt
)
569 return mnt_fs_get_fstype(mnt_context_get_fs(cxt
));
573 * mnt_context_set_options:
574 * @cxt: mount context
575 * @optstr: comma delimited mount options
577 * Returns: 0 on success, negative number in case of error.
579 int mnt_context_set_options(struct libmnt_context
*cxt
, const char *optstr
)
581 return mnt_fs_set_options(mnt_context_get_fs(cxt
), optstr
);
585 * mnt_context_append_options:
586 * @cxt: mount context
587 * @optstr: comma delimited mount options
589 * Returns: 0 on success, negative number in case of error.
591 int mnt_context_append_options(struct libmnt_context
*cxt
, const char *optstr
)
593 return mnt_fs_append_options(mnt_context_get_fs(cxt
), optstr
);
597 * mnt_context_set_fstype_pattern:
598 * @cxt: mount context
599 * @pattern: FS name pattern (or NULL to reset the current setting)
601 * See mount(8), option -t.
603 * Returns: 0 on success, negative number in case of error.
605 int mnt_context_set_fstype_pattern(struct libmnt_context
*cxt
, const char *pattern
)
616 free(cxt
->fstype_pattern
);
617 cxt
->fstype_pattern
= p
;
622 * mnt_context_set_options_pattern:
623 * @cxt: mount context
624 * @pattern: options pattern (or NULL to reset the current setting)
626 * See mount(8), option -O.
628 * Returns: 0 on success, negative number in case of error.
630 int mnt_context_set_options_pattern(struct libmnt_context
*cxt
, const char *pattern
)
641 free(cxt
->optstr_pattern
);
642 cxt
->optstr_pattern
= p
;
647 * mnt_context_set_fstab:
648 * @cxt: mount context
651 * The mount context reads /etc/fstab to the the private struct libmnt_table by default.
652 * This function allows to overwrite the private fstab with an external
653 * instance. Note that the external instance is not deallocated by mnt_free_context().
655 * The fstab is used read-only and is not modified, it should be possible to
656 * share the fstab between more mount contexts (TODO: tests it.)
658 * If the @tb argument is NULL then the current private fstab instance is
661 * Returns: 0 on success, negative number in case of error.
663 int mnt_context_set_fstab(struct libmnt_context
*cxt
, struct libmnt_table
*tb
)
667 if (!(cxt
->flags
& MNT_FL_EXTERN_FSTAB
))
668 mnt_free_table(cxt
->fstab
);
670 set_flag(cxt
, MNT_FL_EXTERN_FSTAB
, tb
!= NULL
);
676 * mnt_context_get_fstab:
677 * @cxt: mount context
680 * See also mnt_table_parse_fstab() for more details about fstab.
682 * Returns: 0 on success, negative number in case of error.
684 int mnt_context_get_fstab(struct libmnt_context
*cxt
, struct libmnt_table
**tb
)
686 struct libmnt_cache
*cache
;
694 cxt
->fstab
= mnt_new_table();
697 if (cxt
->table_errcb
)
698 mnt_table_set_parser_errcb(cxt
->fstab
, cxt
->table_errcb
);
699 cxt
->flags
&= ~MNT_FL_EXTERN_FSTAB
;
700 rc
= mnt_table_parse_fstab(cxt
->fstab
, NULL
);
705 cache
= mnt_context_get_cache(cxt
);
707 /* never touch an external fstab */
708 if (!(cxt
->flags
& MNT_FL_EXTERN_FSTAB
))
709 mnt_table_set_cache(cxt
->fstab
, cache
);
717 * mnt_context_get_mtab:
718 * @cxt: mount context
721 * See also mnt_table_parse_mtab() for more details about mtab/mountinfo. The
722 * result will deallocated by mnt_free_context(@cxt).
724 * Returns: 0 on success, negative number in case of error.
726 int mnt_context_get_mtab(struct libmnt_context
*cxt
, struct libmnt_table
**tb
)
728 struct libmnt_cache
*cache
;
736 cxt
->mtab
= mnt_new_table();
740 if (cxt
->table_errcb
)
741 mnt_table_set_parser_errcb(cxt
->mtab
, cxt
->table_errcb
);
743 rc
= mnt_table_parse_mtab(cxt
->mtab
, cxt
->mtab_path
);
748 cache
= mnt_context_get_cache(cxt
);
749 mnt_table_set_cache(cxt
->mtab
, cache
);
757 * mnt_context_get_table:
758 * @cxt: mount context
759 * @filename: e.g. /proc/self/mountinfo
760 * @tb: returns the table
762 * This function allocates a new table and parses the @file. The parser error
763 * callback and cache for tags and paths is set according to the @cxt setting.
764 * See also mnt_table_parse_file().
766 * It's strongly recommended use mnt_context_get_mtab() and
767 * mnt_context_get_fstab() functions for mtab and fstab files. This function
768 * does not care about LIBMOUNT_* env.variables and does not merge userspace
771 * The result will NOT be deallocated by mnt_free_context(@cxt).
773 * Returns: 0 on success, negative number in case of error.
775 int mnt_context_get_table(struct libmnt_context
*cxt
,
776 const char *filename
, struct libmnt_table
**tb
)
778 struct libmnt_cache
*cache
;
784 *tb
= mnt_new_table();
788 if (cxt
->table_errcb
)
789 mnt_table_set_parser_errcb(*tb
, cxt
->table_errcb
);
791 rc
= mnt_table_parse_file(*tb
, filename
);
797 cache
= mnt_context_get_cache(cxt
);
799 mnt_table_set_cache(*tb
, cache
);
805 * mnt_context_set_tables_errcb
806 * @cxt: mount context
807 * @cb: pointer to callback function
809 * The error callback is used for all tab files (e.g. mtab, fstab)
810 * parsed within the context.
812 * See also mnt_context_get_mtab(),
813 * mnt_context_get_fstab(),
814 * mnt_table_set_parser_errcb().
816 * Returns: 0 on success, negative number in case of error.
818 int mnt_context_set_tables_errcb(struct libmnt_context
*cxt
,
819 int (*cb
)(struct libmnt_table
*tb
, const char *filename
, int line
))
824 cxt
->table_errcb
= cb
;
829 * mnt_context_set_cache:
830 * @cxt: mount context
831 * @cache: cache instance or nULL
833 * The mount context maintains a private struct libmnt_cache by default. This function
834 * allows to overwrite the private cache with an external instance. Note that
835 * the external instance is not deallocated by mnt_free_context().
837 * If the @cache argument is NULL then the current private cache instance is
840 * Returns: 0 on success, negative number in case of error.
842 int mnt_context_set_cache(struct libmnt_context
*cxt
, struct libmnt_cache
*cache
)
846 if (!(cxt
->flags
& MNT_FL_EXTERN_CACHE
))
847 mnt_free_cache(cxt
->cache
);
849 set_flag(cxt
, MNT_FL_EXTERN_CACHE
, cache
!= NULL
);
855 * mnt_context_get_cache
856 * @cxt: mount context
858 * See also mnt_context_set_cache().
860 * Returns: pointer to cache or NULL if canonicalization is disabled.
862 struct libmnt_cache
*mnt_context_get_cache(struct libmnt_context
*cxt
)
864 if (!cxt
|| (cxt
->flags
& MNT_FL_NOCANONICALIZE
))
868 cxt
->cache
= mnt_new_cache();
871 cxt
->flags
&= ~MNT_FL_EXTERN_CACHE
;
877 * mnt_context_get_lock:
878 * @cxt: mount context
880 * The libmount applications don't have to care about mtab locking, but with a
881 * small exception: the application has to be able to remove the lock file when
882 * interrupted by signal or signals have to be ignored when the lock is locked.
884 * The default behavior is to ignore all signals (except SIGALRM and
885 * SIGTRAP for mtab udate) when the lock is locked. If this behavior
886 * is unacceptable then use:
888 * lc = mnt_context_get_lock(cxt);
890 * mnt_lock_block_signals(lc, FALSE);
892 * and don't forget to call mnt_unlock_file(lc) before exit.
894 * Returns: pointer to lock struct or NULL.
896 struct libmnt_lock
*mnt_context_get_lock(struct libmnt_context
*cxt
)
899 * DON'T call this function within libmount, it will always allocate
900 * the lock. The mnt_update_* functions are able to allocate the lock
901 * only when mtab/utab update is really necessary.
903 if (!cxt
|| (cxt
->flags
& MNT_FL_NOMTAB
))
907 cxt
->lock
= mnt_new_lock(cxt
->mtab_writable
?
908 cxt
->mtab_path
: cxt
->utab_path
, 0);
910 mnt_lock_block_signals(cxt
->lock
, TRUE
);
916 * mnt_context_set_mflags:
917 * @cxt: mount context
918 * @flags: mount(2) flags (MS_* flags)
920 * Sets mount flags (see mount(2) man page).
922 * Note that mount context allows to define mount options by mount flags. It
923 * means you can for example use
925 * mnt_context_set_mflags(cxt, MS_NOEXEC | MS_NOSUID);
929 * mnt_context_set_options(cxt, "noexec,nosuid");
931 * these both calls have the same effect.
933 * Returns: 0 on success, negative number in case of error.
935 int mnt_context_set_mflags(struct libmnt_context
*cxt
, unsigned long flags
)
939 cxt
->mountflags
= flags
;
944 * mnt_context_get_mflags:
945 * @cxt: mount context
946 * @flags: returns MS_* mount flags
948 * Converts mount options string to MS_* flags and bitewise-OR the result with
949 * already defined flags (see mnt_context_set_mflags()).
951 * Returns: 0 on success, negative number in case of error.
953 int mnt_context_get_mflags(struct libmnt_context
*cxt
, unsigned long *flags
)
960 if (!(cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
) && cxt
->fs
) {
961 const char *o
= mnt_fs_get_options(cxt
->fs
);
963 rc
= mnt_optstr_get_flags(o
, flags
,
964 mnt_get_builtin_optmap(MNT_LINUX_MAP
));
967 *flags
|= cxt
->mountflags
;
972 * mnt_context_set_user_mflags:
973 * @cxt: mount context
974 * @flags: mount(2) flags (MNT_MS_* flags, e.g. MNT_MS_LOOP)
976 * Sets userspace mount flags.
978 * See also notest for mnt_context_set_mflags().
980 * Returns: 0 on success, negative number in case of error.
982 int mnt_context_set_user_mflags(struct libmnt_context
*cxt
, unsigned long flags
)
986 cxt
->user_mountflags
= flags
;
991 * mnt_context_get_user_mflags:
992 * @cxt: mount context
993 * @flags: returns mount flags
995 * Converts mount options string to MNT_MS_* flags and bitewise-OR the result
996 * with already defined flags (see mnt_context_set_user_mflags()).
998 * Returns: 0 on success, negative number in case of error.
1000 int mnt_context_get_user_mflags(struct libmnt_context
*cxt
, unsigned long *flags
)
1007 if (!(cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
) && cxt
->fs
) {
1008 const char *o
= mnt_fs_get_user_options(cxt
->fs
);
1010 rc
= mnt_optstr_get_flags(o
, flags
,
1011 mnt_get_builtin_optmap(MNT_USERSPACE_MAP
));
1014 *flags
|= cxt
->user_mountflags
;
1019 * mnt_context_set_mountdata:
1020 * @cxt: mount context
1021 * @data: mount(2) data
1023 * The mount context generates mountdata from mount options by default. This
1024 * function allows to overwrite this behavior, and @data will be used instead
1027 * The libmount does not deallocated the data by mnt_free_context(). Note that
1028 * NULL is also valid mount data.
1030 * Returns: 0 on success, negative number in case of error.
1032 int mnt_context_set_mountdata(struct libmnt_context
*cxt
, void *data
)
1036 cxt
->mountdata
= data
;
1037 cxt
->flags
|= MNT_FL_MOUNTDATA
;
1042 * Translates LABEL/UUID/path to mountable path
1044 int mnt_context_prepare_srcpath(struct libmnt_context
*cxt
)
1046 const char *path
= NULL
;
1047 struct libmnt_cache
*cache
;
1048 const char *t
, *v
, *src
;
1053 assert((cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
));
1055 if (!cxt
|| !cxt
->fs
)
1058 DBG(CXT
, mnt_debug_h(cxt
, "preparing source path"));
1060 src
= mnt_fs_get_source(cxt
->fs
);
1062 /* ignore filesystems without source or filesystems
1063 * where the source is quasi-path (//foo/bar)
1065 if (!src
|| (cxt
->fs
->flags
& MNT_FS_NET
))
1068 DBG(CXT
, mnt_debug_h(cxt
, "srcpath '%s'", src
));
1070 cache
= mnt_context_get_cache(cxt
);
1072 if (!mnt_fs_get_tag(cxt
->fs
, &t
, &v
)) {
1074 * Source is TAG (evaluate)
1077 path
= mnt_resolve_tag(t
, v
, cache
);
1079 rc
= path
? mnt_fs_set_source(cxt
->fs
, path
) : -EINVAL
;
1083 * Source is PATH (canonicalize)
1085 path
= mnt_resolve_path(src
, cache
);
1086 if (path
&& strcmp(path
, src
))
1087 rc
= mnt_fs_set_source(cxt
->fs
, path
);
1091 DBG(CXT
, mnt_debug_h(cxt
, "failed to prepare srcpath [rc=%d]", rc
));
1098 if ((cxt
->mountflags
& (MS_BIND
| MS_MOVE
| MS_PROPAGATION
)) ||
1099 (cxt
->fs
->flags
& MNT_FS_PSEUDO
)) {
1100 DBG(CXT
, mnt_debug_h(cxt
, "PROPAGATION/pseudo FS source: %s", path
));
1105 * Initialize loop device
1107 if (mnt_context_is_loopdev(cxt
)) {
1108 rc
= mnt_context_setup_loopdev(cxt
);
1113 DBG(CXT
, mnt_debug_h(cxt
, "final srcpath '%s'",
1114 mnt_fs_get_source(cxt
->fs
)));
1118 int mnt_context_prepare_target(struct libmnt_context
*cxt
)
1121 struct libmnt_cache
*cache
;
1126 assert((cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
));
1128 if (!cxt
|| !cxt
->fs
)
1131 DBG(CXT
, mnt_debug_h(cxt
, "preparing target path"));
1133 tgt
= mnt_fs_get_target(cxt
->fs
);
1137 cache
= mnt_context_get_cache(cxt
);
1139 char *path
= mnt_resolve_path(tgt
, cache
);
1140 if (strcmp(path
, tgt
))
1141 rc
= mnt_fs_set_target(cxt
->fs
, path
);
1145 DBG(CXT
, mnt_debug_h(cxt
, "failed to prepare target"));
1147 DBG(CXT
, mnt_debug_h(cxt
, "final target '%s'",
1148 mnt_fs_get_target(cxt
->fs
)));
1152 int mnt_context_guess_fstype(struct libmnt_context
*cxt
)
1160 assert((cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
));
1162 if (!cxt
|| !cxt
->fs
)
1165 if (cxt
->mountflags
& (MS_BIND
| MS_MOVE
| MS_PROPAGATION
))
1168 type
= (char *) mnt_fs_get_fstype(cxt
->fs
);
1169 if (type
&& !strcmp(type
, "auto")) {
1170 mnt_fs_set_fstype(cxt
->fs
, NULL
);
1176 if (cxt
->flags
& MS_REMOUNT
)
1178 if (cxt
->fstype_pattern
)
1181 dev
= mnt_fs_get_srcpath(cxt
->fs
);
1185 if (access(dev
, F_OK
) == 0) {
1186 struct libmnt_cache
*cache
= mnt_context_get_cache(cxt
);
1188 type
= mnt_get_fstype(dev
, &cxt
->ambi
, cache
);
1190 rc
= mnt_fs_set_fstype(cxt
->fs
, type
);
1192 free(type
); /* type is not cached */
1195 if (strchr(dev
, ':') != NULL
)
1196 rc
= mnt_fs_set_fstype(cxt
->fs
, "nfs");
1197 else if (!strncmp(dev
, "//", 2))
1198 rc
= mnt_fs_set_fstype(cxt
->fs
, "cifs");
1203 DBG(CXT
, mnt_debug_h(cxt
, "FS type: %s",
1204 mnt_fs_get_fstype(cxt
->fs
)));
1207 return mnt_fs_set_fstype(cxt
->fs
, "none");
1209 DBG(CXT
, mnt_debug_h(cxt
, "failed to detect FS type"));
1214 * The default is to use fstype from cxt->fs, this could be overwritten by
1215 * @type. The @act is MNT_ACT_{MOUNT,UMOUNT}.
1217 * Returns: 0 on success or negative number in case of error. Note that success
1218 * does not mean that there is any usable helper, you have to check cxt->helper.
1220 int mnt_context_prepare_helper(struct libmnt_context
*cxt
, const char *name
,
1223 char search_path
[] = FS_SEARCH_PATH
; /* from config.h */
1224 char *p
= NULL
, *path
;
1228 assert((cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
));
1231 type
= mnt_fs_get_fstype(cxt
->fs
);
1233 if ((cxt
->flags
& MNT_FL_NOHELPERS
) || !type
||
1234 !strcmp(type
, "none") || (cxt
->fs
->flags
& MNT_FS_SWAP
))
1237 path
= strtok_r(search_path
, ":", &p
);
1239 char helper
[PATH_MAX
];
1243 rc
= snprintf(helper
, sizeof(helper
), "%s/%s.%s",
1245 path
= strtok_r(NULL
, ":", &p
);
1247 if (rc
< 0 || (size_t) rc
>= sizeof(helper
))
1250 rc
= stat(helper
, &st
);
1251 if (rc
== -1 && errno
== ENOENT
&& strchr(type
, '.')) {
1252 /* If type ends with ".subtype" try without it */
1253 *strrchr(helper
, '.') = '\0';
1254 rc
= stat(helper
, &st
);
1257 DBG(CXT
, mnt_debug_h(cxt
, "%-25s ... %s", helper
,
1258 rc
? "not found" : "found"));
1263 cxt
->helper
= strdup(helper
);
1272 int mnt_context_merge_mflags(struct libmnt_context
*cxt
)
1274 unsigned long fl
= 0;
1279 DBG(CXT
, mnt_debug_h(cxt
, "merging mount flags"));
1281 rc
= mnt_context_get_mflags(cxt
, &fl
);
1284 cxt
->mountflags
= fl
;
1286 /* TODO: if cxt->fs->fs_optstr contains 'ro' then set the MS_RDONLY to
1287 * mount flags, it's possible that superblock is read-only, but VFS is
1292 rc
= mnt_context_get_user_mflags(cxt
, &fl
);
1295 cxt
->user_mountflags
= fl
;
1297 DBG(CXT
, mnt_debug_h(cxt
, "final flags: VFS=%08lx user=%08lx",
1298 cxt
->mountflags
, cxt
->user_mountflags
));
1300 cxt
->flags
|= MNT_FL_MOUNTFLAGS_MERGED
;
1305 * Prepare /etc/mtab or /run/mount/utab
1307 int mnt_context_prepare_update(struct libmnt_context
*cxt
)
1314 assert(cxt
->action
);
1315 assert((cxt
->flags
& MNT_FL_MOUNTFLAGS_MERGED
));
1317 DBG(CXT
, mnt_debug_h(cxt
, "prepare update"));
1319 if (cxt
->mountflags
& MS_PROPAGATION
) {
1320 DBG(CXT
, mnt_debug_h(cxt
, "skip update: MS_PROPAGATION"));
1324 target
= mnt_fs_get_target(cxt
->fs
);
1326 if (cxt
->action
== MNT_ACT_UMOUNT
&& target
&& !strcmp(target
, "/"))
1327 /* Don't try to touch mtab if umounting root FS */
1328 cxt
->flags
|= MNT_FL_NOMTAB
;
1330 if (cxt
->flags
& MNT_FL_NOMTAB
) {
1331 DBG(CXT
, mnt_debug_h(cxt
, "skip update: NOMTAB flag"));
1335 DBG(CXT
, mnt_debug_h(cxt
, "skip update: external helper"));
1338 if (!cxt
->mtab_writable
&& !cxt
->utab_writable
) {
1339 DBG(CXT
, mnt_debug_h(cxt
, "skip update: no writable destination"));
1342 /* 0 = success, 1 = not called yet */
1343 if (cxt
->syscall_status
!= 1 && cxt
->syscall_status
!= 0) {
1344 DBG(CXT
, mnt_debug_h(cxt
,
1345 "skip update: syscall failed [status=%d]",
1346 cxt
->syscall_status
));
1350 cxt
->update
= mnt_new_update();
1354 mnt_update_set_filename(cxt
->update
,
1355 cxt
->mtab_writable
? cxt
->mtab_path
: cxt
->utab_path
,
1356 !cxt
->mtab_writable
);
1359 if (cxt
->action
== MNT_ACT_UMOUNT
)
1360 rc
= mnt_update_set_fs(cxt
->update
, cxt
->mountflags
,
1361 mnt_fs_get_target(cxt
->fs
), NULL
);
1363 rc
= mnt_update_set_fs(cxt
->update
, cxt
->mountflags
,
1366 return rc
< 0 ? rc
: 0;
1369 int mnt_context_update_tabs(struct libmnt_context
*cxt
)
1375 if (cxt
->flags
& MNT_FL_NOMTAB
) {
1376 DBG(CXT
, mnt_debug_h(cxt
, "don't update: NOMTAB flag"));
1380 DBG(CXT
, mnt_debug_h(cxt
, "don't update: external helper"));
1383 if (!cxt
->update
|| !mnt_update_is_ready(cxt
->update
)) {
1384 DBG(CXT
, mnt_debug_h(cxt
, "don't update: no update prepared"));
1387 if (cxt
->syscall_status
) {
1388 DBG(CXT
, mnt_debug_h(cxt
, "don't update: syscall failed/not called"));
1392 fl
= mnt_update_get_mflags(cxt
->update
);
1393 if ((cxt
->mountflags
& MS_RDONLY
) != (fl
& MS_RDONLY
))
1395 * fix MS_RDONLY in options
1397 mnt_update_force_rdonly(cxt
->update
,
1398 cxt
->mountflags
& MS_RDONLY
);
1400 return mnt_update_table(cxt
->update
, cxt
->lock
);
1403 static int apply_table(struct libmnt_context
*cxt
, struct libmnt_table
*tb
,
1406 struct libmnt_fs
*fs
= NULL
;
1407 const char *src
= NULL
, *tgt
= NULL
;
1416 src
= mnt_fs_get_source(cxt
->fs
);
1417 tgt
= mnt_fs_get_target(cxt
->fs
);
1420 fs
= mnt_table_find_pair(tb
, src
, tgt
, direction
);
1423 fs
= mnt_table_find_source(tb
, src
, direction
);
1425 fs
= mnt_table_find_target(tb
, tgt
, direction
);
1428 /* swap source and target (if @src is not LABEL/UUID),
1433 * the path could be a mountpoint as well as source (for
1434 * example bind mount, symlink to device, ...).
1436 if (src
&& !mnt_fs_get_tag(cxt
->fs
, NULL
, NULL
))
1437 fs
= mnt_table_find_target(tb
, src
, direction
);
1439 fs
= mnt_table_find_source(tb
, tgt
, direction
);
1446 DBG(CXT
, mnt_debug_h(cxt
, "apply entry:"));
1447 DBG(CXT
, mnt_fs_print_debug(fs
, stderr
));
1449 /* copy from tab to our FS description
1451 rc
= mnt_fs_set_source(cxt
->fs
, mnt_fs_get_source(fs
));
1453 rc
= mnt_fs_set_target(cxt
->fs
, mnt_fs_get_target(fs
));
1455 if (!rc
&& !mnt_fs_get_fstype(cxt
->fs
))
1456 rc
= mnt_fs_set_fstype(cxt
->fs
, mnt_fs_get_fstype(fs
));
1461 if (cxt
->optsmode
& MNT_OMODE_IGNORE
)
1463 else if (cxt
->optsmode
& MNT_OMODE_REPLACE
)
1464 rc
= mnt_fs_set_options(cxt
->fs
, mnt_fs_get_options(fs
));
1466 else if (cxt
->optsmode
& MNT_OMODE_APPEND
)
1467 rc
= mnt_fs_append_options(cxt
->fs
, mnt_fs_get_options(fs
));
1469 else if (cxt
->optsmode
& MNT_OMODE_PREPEND
)
1470 rc
= mnt_fs_prepend_options(cxt
->fs
, mnt_fs_get_options(fs
));
1473 cxt
->flags
|= MNT_FL_TAB_APPLIED
;
1478 * mnt_context_apply_fstab:
1479 * @cxt: mount context
1481 * This function is optional.
1483 * Returns: 0 on success, negative number in case of error.
1485 int mnt_context_apply_fstab(struct libmnt_context
*cxt
)
1488 struct libmnt_table
*tab
= NULL
;
1489 const char *src
= NULL
, *tgt
= NULL
;
1497 if (cxt
->flags
& MNT_FL_TAB_APPLIED
)
1500 if (mnt_context_is_restricted(cxt
)) {
1501 DBG(CXT
, mnt_debug_h(cxt
, "force fstab usage for non-root users!"));
1502 cxt
->optsmode
= MNT_OMODE_USER
;
1503 } else if (cxt
->optsmode
== 0) {
1504 DBG(CXT
, mnt_debug_h(cxt
, "use default optmode"));
1505 cxt
->optsmode
= MNT_OMODE_AUTO
;
1510 src
= mnt_fs_get_source(cxt
->fs
);
1511 tgt
= mnt_fs_get_target(cxt
->fs
);
1514 DBG(CXT
, mnt_debug_h(cxt
, "OPTSMODE: ignore=%d, append=%d, prepend=%d, "
1515 "replace=%d, force=%d, fstab=%d, mtab=%d",
1516 cxt
->optsmode
& MNT_OMODE_IGNORE
? 1 : 0,
1517 cxt
->optsmode
& MNT_OMODE_APPEND
? 1 : 0,
1518 cxt
->optsmode
& MNT_OMODE_PREPEND
? 1 : 0,
1519 cxt
->optsmode
& MNT_OMODE_REPLACE
? 1 : 0,
1520 cxt
->optsmode
& MNT_OMODE_FORCE
? 1 : 0,
1521 cxt
->optsmode
& MNT_OMODE_FSTAB
? 1 : 0,
1522 cxt
->optsmode
& MNT_OMODE_MTAB
? 1 : 0));
1524 /* fstab is not required if source and target are specified */
1525 if (src
&& tgt
&& !(cxt
->optsmode
& MNT_OMODE_FORCE
)) {
1526 DBG(CXT
, mnt_debug_h(cxt
, "fstab not required -- skip"));
1530 DBG(CXT
, mnt_debug_h(cxt
,
1531 "trying to apply fstab (src=%s, target=%s)", src
, tgt
));
1533 /* let's initialize cxt->fs */
1534 mnt_context_get_fs(cxt
);
1537 if (cxt
->optsmode
& MNT_OMODE_FSTAB
) {
1538 rc
= mnt_context_get_fstab(cxt
, &tab
);
1540 rc
= apply_table(cxt
, tab
, MNT_ITER_FORWARD
);
1544 if (rc
< 0 && (cxt
->optsmode
& MNT_OMODE_MTAB
)) {
1545 DBG(CXT
, mnt_debug_h(cxt
, "trying to apply from mtab"));
1546 rc
= mnt_context_get_mtab(cxt
, &tab
);
1548 rc
= apply_table(cxt
, tab
, MNT_ITER_BACKWARD
);
1551 DBG(CXT
, mnt_debug_h(cxt
, "failed to find entry in fstab/mtab"));
1556 * mnt_context_get_status:
1557 * @cxt: mount context
1559 * Returns: 1 if /sbin/mount.type or mount(2) syscall was successfull.
1561 int mnt_context_get_status(struct libmnt_context
*cxt
)
1563 return cxt
&& (!cxt
->syscall_status
|| !cxt
->helper_exec_status
);
1567 * mnt_context_set_syscall_status:
1568 * @cxt: mount context
1569 * @status: mount(2) status
1571 * The @status should be 0 on succcess, or negative number on error (-1 or
1574 * This function should be used if [u]mount(2) syscall was NOT called by
1575 * libmount (by mnt_context_mount() or mnt_context_do_mount()) only.
1577 * Returns: 0 or negative number in case of error.
1579 int mnt_context_set_syscall_status(struct libmnt_context
*cxt
, int status
)
1584 DBG(CXT
, mnt_debug_h(cxt
, "syscall status set to: %d", status
));
1585 cxt
->syscall_status
= status
;
1590 * mnt_context_strerror
1593 * @bufsiz: size of the buffer
1595 * Returns: 0 or negative number in case of error.
1597 int mnt_context_strerror(struct libmnt_context
*cxt
__attribute__((__unused__
)),
1598 char *buf
__attribute__((__unused__
)),
1599 size_t bufsiz
__attribute__((__unused__
)))
1601 /* TODO: based on cxt->syscall_errno or cxt->helper_status */
1606 * mnt_context_init_helper
1607 * @cxt: mount context
1608 * @action: MNT_ACT_{UMOUNT,MOUNT}
1609 * @flags: not used now
1611 * This function infors libmount that used from [u]mount.type helper.
1613 * The function also calls mnt_context_disable_helpers() to avoid recursive
1614 * mount.type helpers calling. It you really want to call another
1615 * mount.type helper from your helper than you have to explicitly enable this
1618 * mnt_context_disable_helpers(cxt, FALSE);
1620 * Returns: 0 on success, negative number in case of error.
1622 int mnt_context_init_helper(struct libmnt_context
*cxt
, int action
,
1623 int flags
__attribute__((__unused__
)))
1625 int rc
= mnt_context_disable_helpers(cxt
, TRUE
);
1628 rc
= set_flag(cxt
, MNT_FL_HELPER
, 1);
1630 cxt
->action
= action
;
1632 DBG(CXT
, mnt_debug_h(cxt
, "initialized for [u]mount.<type> helper [rc=%d]", rc
));
1637 * mnt_context_helper_setopt:
1639 * @c: getopt() result
1640 * @arg: getopt() optarg
1642 * This function applies [u]mount.type command line option (for example parsed
1643 * by getopt or getopt_long) to @cxt. All unknown options are ignored and
1644 * then 1 is returned.
1646 * Returns: negative number on error, 1 if @c is unknown option, 0 on success.
1648 int mnt_context_helper_setopt(struct libmnt_context
*cxt
, int c
, char *arg
)
1651 switch(cxt
->action
) {
1653 return mnt_context_mount_setopt(cxt
, c
, arg
);
1654 case MNT_ACT_UMOUNT
:
1655 return mnt_context_umount_setopt(cxt
, c
, arg
);
1662 * mnt_context_is_fs_mounted:
1665 * @mounted: returns 1 for mounted and 0 for non-mounted filesystems
1667 * Returns: 0 on success and negative number in case of error.
1669 int mnt_context_is_fs_mounted(struct libmnt_context
*cxt
,
1670 struct libmnt_fs
*fs
, int *mounted
)
1672 struct libmnt_table
*mtab
;
1675 if (!cxt
|| !fs
|| !mounted
)
1678 rc
= mnt_context_get_mtab(cxt
, &mtab
);
1682 *mounted
= mnt_table_is_fs_mounted(mtab
, fs
);
1688 struct libmnt_lock
*lock
;
1690 static void lock_fallback(void)
1693 mnt_unlock_file(lock
);
1696 int test_mount(struct libmnt_test
*ts
, int argc
, char *argv
[])
1698 int idx
= 1, rc
= 0;
1699 struct libmnt_context
*cxt
;
1704 cxt
= mnt_new_context();
1708 if (!strcmp(argv
[idx
], "-o")) {
1709 mnt_context_set_options(cxt
, argv
[idx
+ 1]);
1712 if (!strcmp(argv
[idx
], "-t")) {
1713 /* TODO: use mnt_context_set_fstype_pattern() */
1714 mnt_context_set_fstype(cxt
, argv
[idx
+ 1]);
1718 if (argc
== idx
+ 1)
1719 /* mount <mountpont>|<device> */
1720 mnt_context_set_target(cxt
, argv
[idx
++]);
1722 else if (argc
== idx
+ 2) {
1723 /* mount <device> <mountpoint> */
1724 mnt_context_set_source(cxt
, argv
[idx
++]);
1725 mnt_context_set_target(cxt
, argv
[idx
++]);
1728 /* this is unnecessary -- libmount is able to internaly
1729 * create and manage the lock
1731 lock
= mnt_context_get_lock(cxt
);
1733 atexit(lock_fallback
);
1735 rc
= mnt_context_mount(cxt
);
1737 printf("failed to mount: %m\n");
1739 printf("successfully mounted\n");
1741 mnt_free_context(cxt
);
1745 int test_umount(struct libmnt_test
*ts
, int argc
, char *argv
[])
1747 int idx
= 1, rc
= 0;
1748 struct libmnt_context
*cxt
;
1753 cxt
= mnt_new_context();
1757 if (!strcmp(argv
[idx
], "-t")) {
1758 mnt_context_set_fstype(cxt
, argv
[idx
+ 1]);
1762 if (!strcmp(argv
[idx
], "-f")) {
1763 mnt_context_enable_force(cxt
, TRUE
);
1767 if (!strcmp(argv
[idx
], "-l")) {
1768 mnt_context_enable_lazy(cxt
, TRUE
);
1772 if (!strcmp(argv
[idx
], "-r")) {
1773 mnt_context_enable_rdonly_umount(cxt
, TRUE
);
1777 if (argc
== idx
+ 1) {
1778 /* mount <mountpont>|<device> */
1779 mnt_context_set_target(cxt
, argv
[idx
++]);
1785 lock
= mnt_context_get_lock(cxt
);
1787 atexit(lock_fallback
);
1789 rc
= mnt_context_umount(cxt
);
1791 printf("failed to umount\n");
1793 printf("successfully umounted\n");
1795 mnt_free_context(cxt
);
1799 int test_flags(struct libmnt_test
*ts
, int argc
, char *argv
[])
1801 int idx
= 1, rc
= 0;
1802 struct libmnt_context
*cxt
;
1803 const char *opt
= NULL
;
1804 unsigned long flags
= 0;
1809 cxt
= mnt_new_context();
1813 if (!strcmp(argv
[idx
], "-o")) {
1814 mnt_context_set_options(cxt
, argv
[idx
+ 1]);
1818 if (argc
== idx
+ 1)
1819 /* mount <mountpont>|<device> */
1820 mnt_context_set_target(cxt
, argv
[idx
++]);
1822 rc
= mnt_context_prepare_mount(cxt
);
1824 printf("failed to prepare mount %s\n", strerror(-rc
));
1826 opt
= mnt_fs_get_options(cxt
->fs
);
1828 fprintf(stdout
, "options: %s\n", opt
);
1830 mnt_context_get_mflags(cxt
, &flags
);
1831 fprintf(stdout
, "flags: %08lx\n", flags
);
1833 mnt_free_context(cxt
);
1837 int test_mountall(struct libmnt_test
*ts
, int argc
, char *argv
[])
1839 struct libmnt_context
*cxt
;
1840 struct libmnt_iter
*itr
;
1841 struct libmnt_fs
*fs
;
1842 int mntrc
, ignored
, idx
= 1;
1844 cxt
= mnt_new_context();
1845 itr
= mnt_new_iter(MNT_ITER_FORWARD
);
1851 if (!strcmp(argv
[idx
], "-O")) {
1852 mnt_context_set_options_pattern(cxt
, argv
[idx
+ 1]);
1855 if (!strcmp(argv
[idx
], "-t")) {
1856 mnt_context_set_fstype_pattern(cxt
, argv
[idx
+ 1]);
1861 while (mnt_context_next_mount(cxt
, itr
, &fs
, &mntrc
, &ignored
) == 0) {
1863 const char *tgt
= mnt_fs_get_target(fs
);
1866 printf("%s: ignored: not match\n", tgt
);
1867 else if (ignored
== 2)
1868 printf("%s: ignored: already mounted\n", tgt
);
1870 else if (!mnt_context_get_status(cxt
)) {
1873 warn("%s: mount failed", tgt
);
1875 warnx("%s: mount failed", tgt
);
1877 printf("%s: successfully mounted\n", tgt
);
1880 mnt_free_context(cxt
);
1884 int main(int argc
, char *argv
[])
1886 struct libmnt_test tss
[] = {
1887 { "--mount", test_mount
, "[-o <opts>] [-t <type>] <spec>|<src> <target>" },
1888 { "--umount", test_umount
, "[-t <type>] [-f][-l][-r] <src>|<target>" },
1889 { "--mount-all", test_mountall
, "[-O <pattern>] [-t <pattern] mount all filesystems from fstab" },
1890 { "--flags", test_flags
, "[-o <opts>] <spec>" },
1893 umask(S_IWGRP
|S_IWOTH
); /* to be compatible with mount(8) */
1895 return mnt_run_test(tss
, argc
, argv
);
1898 #endif /* TEST_PROGRAM */