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, "tring 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 %s\n", strerror(errno));
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 */