~ubuntu-branches/ubuntu/trusty/util-linux/trusty-proposed

« back to all changes in this revision

Viewing changes to shlibs/mount/src/context_mount.c

  • Committer: Package Import Robot
  • Author(s): LaMont Jones
  • Date: 2011-11-03 15:38:23 UTC
  • mto: (4.5.5 sid) (1.6.4)
  • mto: This revision was merged to the branch mainline in revision 85.
  • Revision ID: package-import@ubuntu.com-20111103153823-10sx16jprzxlhkqf
ImportĀ upstreamĀ versionĀ 2.20.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
3
 
 *
4
 
 * This file may be redistributed under the terms of the
5
 
 * GNU Lesser General Public License.
6
 
 */
7
 
 
8
 
#include <stdio.h>
9
 
#include <stdlib.h>
10
 
#include <sys/types.h>
11
 
#include <sys/stat.h>
12
 
#include <unistd.h>
13
 
#include <string.h>
14
 
#include <errno.h>
15
 
 
16
 
#ifdef HAVE_LIBSELINUX
17
 
#include <selinux/selinux.h>
18
 
#include <selinux/context.h>
19
 
#endif
20
 
 
21
 
#include <sys/wait.h>
22
 
#include <sys/mount.h>
23
 
 
24
 
#include "c.h"
25
 
#include "mountP.h"
26
 
 
27
 
/*
28
 
 * this has to be called after mnt_context_evaluate_permissions()
29
 
 */
30
 
static int fix_optstr(struct libmnt_context *cxt)
31
 
{
32
 
        int rc = 0, rem_se = 0;
33
 
        char *next;
34
 
        char *name, *val;
35
 
        size_t namesz, valsz;
36
 
        struct libmnt_fs *fs;
37
 
 
38
 
        assert(cxt);
39
 
        assert(cxt->fs);
40
 
        assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
41
 
 
42
 
        if (!cxt)
43
 
                return -EINVAL;
44
 
        if (!cxt->fs)
45
 
                return 0;
46
 
 
47
 
        DBG(CXT, mnt_debug_h(cxt, "mount: fixing optstr"));
48
 
 
49
 
        fs = cxt->fs;
50
 
 
51
 
        /* The propagation flags should not be used together with any other flags */
52
 
        if (cxt->mountflags & MS_PROPAGATION)
53
 
                cxt->mountflags &= MS_PROPAGATION;
54
 
 
55
 
        if (!mnt_optstr_get_option(fs->user_optstr, "user", &val, &valsz)) {
56
 
                if (val) {
57
 
                        cxt->orig_user = strndup(val, valsz);
58
 
                        if (!cxt->orig_user) {
59
 
                                rc = -ENOMEM;
60
 
                                goto done;
61
 
                        }
62
 
                }
63
 
                cxt->flags |= MNT_FL_SAVED_USER;
64
 
        }
65
 
 
66
 
        /*
67
 
         * Sync mount options with mount flags
68
 
         */
69
 
        rc = mnt_optstr_apply_flags(&fs->vfs_optstr, cxt->mountflags,
70
 
                                mnt_get_builtin_optmap(MNT_LINUX_MAP));
71
 
        if (rc)
72
 
                goto done;
73
 
 
74
 
        rc = mnt_optstr_apply_flags(&fs->user_optstr, cxt->user_mountflags,
75
 
                                mnt_get_builtin_optmap(MNT_USERSPACE_MAP));
76
 
        if (rc)
77
 
                goto done;
78
 
 
79
 
        next = fs->fs_optstr;
80
 
 
81
 
#ifdef HAVE_LIBSELINUX
82
 
        rem_se = (cxt->mountflags & MS_REMOUNT) || !is_selinux_enabled();
83
 
#endif
84
 
        while (!mnt_optstr_next_option(&next, &name, &namesz, &val, &valsz)) {
85
 
 
86
 
                if (namesz == 3 && !strncmp(name, "uid", 3))
87
 
                        rc = mnt_optstr_fix_uid(&fs->fs_optstr, val, valsz, &next);
88
 
                else if (namesz == 3 && !strncmp(name, "gid", 3))
89
 
                        rc = mnt_optstr_fix_gid(&fs->fs_optstr, val, valsz, &next);
90
 
#ifdef HAVE_LIBSELINUX
91
 
                else if (namesz >= 7 && (!strncmp(name, "context", 7) ||
92
 
                                         !strncmp(name, "fscontext", 9) ||
93
 
                                         !strncmp(name, "defcontext", 10) ||
94
 
                                         !strncmp(name, "rootcontext", 11))) {
95
 
                        if (rem_se) {
96
 
                                /* remove context= option */
97
 
                                next = name;
98
 
                                rc = mnt_optstr_remove_option_at(&fs->fs_optstr,
99
 
                                                        name, val + valsz);
100
 
                        } else
101
 
                                rc = mnt_optstr_fix_secontext(&fs->fs_optstr,
102
 
                                                        val, valsz, &next);
103
 
                }
104
 
#endif
105
 
                if (rc)
106
 
                        goto done;
107
 
        }
108
 
 
109
 
        if (!rc && cxt->user_mountflags && MNT_MS_USER)
110
 
                rc = mnt_optstr_fix_user(&fs->user_optstr);
111
 
 
112
 
done:
113
 
        DBG(CXT, mnt_debug_h(cxt, "fixed options [rc=%d]: "
114
 
                "vfs: '%s' fs: '%s' user: '%s'", rc,
115
 
                fs->vfs_optstr, fs->fs_optstr, fs->user_optstr));
116
 
        return rc;
117
 
}
118
 
 
119
 
/*
120
 
 * Converts already evalulated and fixed options to the form that is compatible
121
 
 * with /sbin/mount.<type> helpers.
122
 
 */
123
 
static int generate_helper_optstr(struct libmnt_context *cxt, char **optstr)
124
 
{
125
 
        int rc = 0;
126
 
 
127
 
        assert(cxt);
128
 
        assert(cxt->fs);
129
 
        assert(optstr);
130
 
 
131
 
        *optstr = mnt_fs_strdup_options(cxt->fs);
132
 
        if (!*optstr)
133
 
                return -ENOMEM;
134
 
 
135
 
        if (cxt->flags & MNT_FL_SAVED_USER)
136
 
                rc = mnt_optstr_set_option(optstr, "user", cxt->orig_user);
137
 
        if (rc) {
138
 
                free(*optstr);
139
 
                *optstr = NULL;
140
 
        }
141
 
        return rc;
142
 
}
143
 
 
144
 
 
145
 
/*
146
 
 * this has to be called before fix_optstr()
147
 
 */
148
 
static int evaluate_permissions(struct libmnt_context *cxt)
149
 
{
150
 
        unsigned long u_flags = 0;
151
 
        const char *srcpath;
152
 
 
153
 
        assert(cxt);
154
 
        assert(cxt->fs);
155
 
        assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
156
 
 
157
 
        if (!cxt)
158
 
                return -EINVAL;
159
 
        if (!cxt->fs)
160
 
                return 0;
161
 
 
162
 
        DBG(CXT, mnt_debug_h(cxt, "mount: evaluating permissions"));
163
 
 
164
 
        mnt_context_get_user_mflags(cxt, &u_flags);
165
 
 
166
 
        if (!mnt_context_is_restricted(cxt)) {
167
 
                /*
168
 
                 * superuser mount
169
 
                 */
170
 
                cxt->user_mountflags &= ~MNT_MS_OWNER;
171
 
                cxt->user_mountflags &= ~MNT_MS_GROUP;
172
 
                cxt->user_mountflags &= ~MNT_MS_USER;
173
 
                cxt->user_mountflags &= ~MNT_MS_USERS;
174
 
        } else {
175
 
                /*
176
 
                 * user mount
177
 
                 */
178
 
                if (!(cxt->flags & MNT_FL_TAB_APPLIED))
179
 
                {
180
 
                        DBG(CXT, mnt_debug_h(cxt, "fstab not applied, ignore user mount"));
181
 
                        return -EPERM;
182
 
                }
183
 
 
184
 
                if (u_flags & (MNT_MS_OWNER | MNT_MS_GROUP))
185
 
                        cxt->mountflags |= MS_OWNERSECURE;
186
 
 
187
 
                if (u_flags & (MNT_MS_USER | MNT_MS_USERS))
188
 
                        cxt->mountflags |= MS_SECURE;
189
 
 
190
 
                srcpath = mnt_fs_get_srcpath(cxt->fs);
191
 
                if (!srcpath)
192
 
                        return -EINVAL;
193
 
 
194
 
                /*
195
 
                 * MS_OWNER: Allow owners to mount when fstab contains the
196
 
                 * owner option.  Note that this should never be used in a high
197
 
                 * security environment, but may be useful to give people at
198
 
                 * the console the possibility of mounting a floppy.  MS_GROUP:
199
 
                 * Allow members of device group to mount. (Martin Dickopp)
200
 
                 */
201
 
                if (u_flags & (MNT_MS_OWNER | MNT_MS_GROUP)) {
202
 
                        struct stat sb;
203
 
 
204
 
                        if (strncmp(srcpath, "/dev/", 5) == 0 &&
205
 
                            stat(srcpath, &sb) == 0 &&
206
 
                            (((u_flags & MNT_MS_OWNER) && getuid() == sb.st_uid) ||
207
 
                             ((u_flags & MNT_MS_GROUP) && mnt_in_group(sb.st_gid))))
208
 
 
209
 
                                cxt->user_mountflags |= MNT_MS_USER;
210
 
                }
211
 
 
212
 
                if (!(cxt->user_mountflags & (MNT_MS_USER | MNT_MS_USERS))) {
213
 
                        DBG(CXT, mnt_debug_h(cxt, "permissions evaluation ends with -EPERMS"));
214
 
                        return -EPERM;
215
 
                }
216
 
        }
217
 
 
218
 
        return 0;
219
 
}
220
 
 
221
 
/*
222
 
 * mnt_context_helper_setopt() backend
223
 
 *
224
 
 * This function applies mount.<type> command line option (for example parsed
225
 
 * by getopt() or getopt_long()) to @cxt. All unknown options are ignored and
226
 
 * then 1 is returned.
227
 
 *
228
 
 * Returns: negative number on error, 1 if @c is unknown option, 0 on success.
229
 
 */
230
 
int mnt_context_mount_setopt(struct libmnt_context *cxt, int c, char *arg)
231
 
{
232
 
        int rc = -EINVAL;
233
 
 
234
 
        assert(cxt);
235
 
        assert(cxt->action == MNT_ACT_MOUNT);
236
 
 
237
 
        switch(c) {
238
 
        case 'f':
239
 
                rc = mnt_context_enable_fake(cxt, TRUE);
240
 
                break;
241
 
        case 'n':
242
 
                rc = mnt_context_disable_mtab(cxt, TRUE);
243
 
                break;
244
 
        case 'r':
245
 
                rc = mnt_context_append_options(cxt, "ro");
246
 
                break;
247
 
        case 'v':
248
 
                rc = mnt_context_enable_verbose(cxt, TRUE);
249
 
                break;
250
 
        case 'w':
251
 
                rc = mnt_context_append_options(cxt, "rw");
252
 
                break;
253
 
        case 'o':
254
 
                if (arg)
255
 
                        rc = mnt_context_append_options(cxt, arg);
256
 
                break;
257
 
        case 's':
258
 
                rc = mnt_context_enable_sloppy(cxt, TRUE);
259
 
                break;
260
 
        case 't':
261
 
                if (arg)
262
 
                        rc = mnt_context_set_fstype(cxt, arg);
263
 
                break;
264
 
        default:
265
 
                return 1;
266
 
                break;
267
 
        }
268
 
 
269
 
        return rc;
270
 
}
271
 
 
272
 
static int exec_helper(struct libmnt_context *cxt)
273
 
{
274
 
        char *o = NULL;
275
 
        int rc;
276
 
 
277
 
        assert(cxt);
278
 
        assert(cxt->fs);
279
 
        assert(cxt->helper);
280
 
        assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
281
 
 
282
 
        DBG(CXT, mnt_debug_h(cxt, "mount: executing helper %s", cxt->helper));
283
 
 
284
 
        rc = generate_helper_optstr(cxt, &o);
285
 
        if (rc)
286
 
                return -EINVAL;
287
 
 
288
 
        DBG_FLUSH;
289
 
 
290
 
        switch (fork()) {
291
 
        case 0:
292
 
        {
293
 
                const char *args[12], *type;
294
 
                int i = 0;
295
 
 
296
 
                if (setgid(getgid()) < 0)
297
 
                        exit(EXIT_FAILURE);
298
 
 
299
 
                if (setuid(getuid()) < 0)
300
 
                        exit(EXIT_FAILURE);
301
 
 
302
 
                type = mnt_fs_get_fstype(cxt->fs);
303
 
 
304
 
                args[i++] = cxt->helper;                /* 1 */
305
 
                args[i++] = mnt_fs_get_srcpath(cxt->fs);/* 2 */
306
 
                args[i++] = mnt_fs_get_target(cxt->fs); /* 3 */
307
 
 
308
 
                if (mnt_context_is_sloppy(cxt))
309
 
                        args[i++] = "-s";               /* 4 */
310
 
                if (mnt_context_is_fake(cxt))
311
 
                        args[i++] = "-f";               /* 5 */
312
 
                if (mnt_context_is_nomtab(cxt))
313
 
                        args[i++] = "-n";               /* 6 */
314
 
                if (mnt_context_is_verbose(cxt))
315
 
                        args[i++] = "-v";               /* 7 */
316
 
                if (o) {
317
 
                        args[i++] = "-o";               /* 8 */
318
 
                        args[i++] = o;                  /* 9 */
319
 
                }
320
 
                if (type && !endswith(cxt->helper, type)) {
321
 
                        args[i++] = "-t";               /* 10 */
322
 
                        args[i++] = type;               /* 11 */
323
 
                }
324
 
                args[i] = NULL;                         /* 12 */
325
 
#ifdef CONFIG_LIBMOUNT_DEBUG
326
 
                i = 0;
327
 
                for (i = 0; args[i]; i++)
328
 
                        DBG(CXT, mnt_debug_h(cxt, "argv[%d] = \"%s\"",
329
 
                                                        i, args[i]));
330
 
#endif
331
 
                DBG_FLUSH;
332
 
                execv(cxt->helper, (char * const *) args);
333
 
                exit(EXIT_FAILURE);
334
 
        }
335
 
        default:
336
 
        {
337
 
                int st;
338
 
                wait(&st);
339
 
                cxt->helper_status = WIFEXITED(st) ? WEXITSTATUS(st) : -1;
340
 
 
341
 
                DBG(CXT, mnt_debug_h(cxt, "%s executed [status=%d]",
342
 
                                        cxt->helper, cxt->helper_status));
343
 
                cxt->helper_exec_status = rc = 0;
344
 
                break;
345
 
        }
346
 
 
347
 
        case -1:
348
 
                cxt->helper_exec_status = rc = -errno;
349
 
                DBG(CXT, mnt_debug_h(cxt, "fork() failed"));
350
 
                break;
351
 
        }
352
 
 
353
 
        return rc;
354
 
}
355
 
 
356
 
/*
357
 
 * The default is to use fstype from cxt->fs, this could be overwritten by
358
 
 * @try_type argument.
359
 
 */
360
 
static int do_mount(struct libmnt_context *cxt, const char *try_type)
361
 
{
362
 
        int rc = 0;
363
 
        const char *src, *target, *type;
364
 
        unsigned long flags;
365
 
 
366
 
        assert(cxt);
367
 
        assert(cxt->fs);
368
 
        assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
369
 
 
370
 
        if (try_type && !cxt->helper) {
371
 
                rc = mnt_context_prepare_helper(cxt, "mount", try_type);
372
 
                if (!rc)
373
 
                        return rc;
374
 
        }
375
 
        if (cxt->helper)
376
 
                return exec_helper(cxt);
377
 
 
378
 
        flags = cxt->mountflags;
379
 
        src = mnt_fs_get_srcpath(cxt->fs);
380
 
        target = mnt_fs_get_target(cxt->fs);
381
 
 
382
 
        if (!src || !target)
383
 
                return -EINVAL;
384
 
 
385
 
        type = try_type ? : mnt_fs_get_fstype(cxt->fs);
386
 
 
387
 
        if (!(flags & MS_MGC_MSK))
388
 
                flags |= MS_MGC_VAL;
389
 
 
390
 
        DBG(CXT, mnt_debug_h(cxt, "%smount(2) "
391
 
                        "[source=%s, target=%s, type=%s, "
392
 
                        " mountflags=%08lx, mountdata=%s]",
393
 
                        (cxt->flags & MNT_FL_FAKE) ? "(FAKE) " : "",
394
 
                        src, target, type,
395
 
                        flags, cxt->mountdata ? "yes" : "<none>"));
396
 
 
397
 
        if (cxt->flags & MNT_FL_FAKE)
398
 
                cxt->syscall_status = 0;
399
 
        else {
400
 
                if (mount(src, target, type, flags, cxt->mountdata)) {
401
 
                        cxt->syscall_status = -errno;
402
 
                        DBG(CXT, mnt_debug_h(cxt, "mount(2) failed [errno=%d %m]",
403
 
                                                        -cxt->syscall_status));
404
 
                        return -cxt->syscall_status;
405
 
                }
406
 
                DBG(CXT, mnt_debug_h(cxt, "mount(2) success"));
407
 
                cxt->syscall_status = 0;
408
 
        }
409
 
 
410
 
        if (try_type && cxt->update) {
411
 
                struct libmnt_fs *fs = mnt_update_get_fs(cxt->update);
412
 
                if (fs)
413
 
                        rc = mnt_fs_set_fstype(fs, try_type);
414
 
        }
415
 
 
416
 
        /* TODO: check if the result is really read-only/read-write
417
 
         *       and if necessary update cxt->mountflags
418
 
         */
419
 
 
420
 
        return rc;
421
 
}
422
 
 
423
 
static int do_mount_by_pattern(struct libmnt_context *cxt, const char *pattern)
424
 
{
425
 
        int neg = pattern && strncmp(pattern, "no", 2) == 0;
426
 
        int rc = -EINVAL;
427
 
        char **filesystems, **fp;
428
 
 
429
 
        assert(cxt);
430
 
        assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
431
 
 
432
 
        if (!neg && pattern) {
433
 
                /*
434
 
                 * try all types from the list
435
 
                 */
436
 
                char *p, *p0;
437
 
 
438
 
                DBG(CXT, mnt_debug_h(cxt, "tring mount by FS pattern list"));
439
 
 
440
 
                p0 = p = strdup(pattern);
441
 
                if (!p)
442
 
                        return -ENOMEM;
443
 
                do {
444
 
                        char *end = strchr(p, ',');
445
 
                        if (end)
446
 
                                *end = '\0';
447
 
                        rc = do_mount(cxt, p);
448
 
                        p = end ? end + 1 : NULL;
449
 
                } while (!mnt_context_get_status(cxt) && p);
450
 
 
451
 
                free(p0);
452
 
 
453
 
                if (mnt_context_get_status(cxt))
454
 
                        return rc;
455
 
        }
456
 
 
457
 
        /*
458
 
         * try /etc/filesystems and /proc/filesystems
459
 
         */
460
 
        DBG(CXT, mnt_debug_h(cxt, "tring mount by filesystems lists"));
461
 
 
462
 
        rc = mnt_get_filesystems(&filesystems, neg ? pattern : NULL);
463
 
        if (rc)
464
 
                return rc;
465
 
 
466
 
        for (fp = filesystems; *fp; fp++) {
467
 
                rc = do_mount(cxt, *fp);
468
 
                if (mnt_context_get_status(cxt))
469
 
                        break;
470
 
        }
471
 
        mnt_free_filesystems(filesystems);
472
 
        return rc;
473
 
}
474
 
 
475
 
/**
476
 
 * mnt_context_prepare_mount:
477
 
 * @cxt: context
478
 
 *
479
 
 * Prepare context for mounting, unnecessary for mnt_context_mount().
480
 
 *
481
 
 * Returns: negative number on error, zero on success
482
 
 */
483
 
int mnt_context_prepare_mount(struct libmnt_context *cxt)
484
 
{
485
 
        int rc = -EINVAL;
486
 
 
487
 
        assert(cxt);
488
 
        assert(cxt->fs);
489
 
        assert(cxt->helper_exec_status == 1);
490
 
        assert(cxt->syscall_status == 1);
491
 
 
492
 
        if (!cxt || !cxt->fs || (cxt->fs->flags & MNT_FS_SWAP))
493
 
                return -EINVAL;
494
 
        if (!mnt_fs_get_source(cxt->fs) && !mnt_fs_get_target(cxt->fs))
495
 
                return -EINVAL;
496
 
        if (cxt->flags & MNT_FL_PREPARED)
497
 
                return 0;
498
 
 
499
 
        cxt->action = MNT_ACT_MOUNT;
500
 
 
501
 
        DBG(CXT, mnt_debug_h(cxt, "mount: preparing"));
502
 
 
503
 
        /* TODO: fstab is unnecessary for MS_{MOVE,BIND,STARED,...} */
504
 
        rc = mnt_context_apply_fstab(cxt);
505
 
        if (!rc)
506
 
                rc = mnt_context_merge_mflags(cxt);
507
 
        if (!rc)
508
 
                rc = evaluate_permissions(cxt);
509
 
        if (!rc)
510
 
                rc = fix_optstr(cxt);
511
 
        if (!rc)
512
 
                rc = mnt_context_prepare_srcpath(cxt);
513
 
        if (!rc)
514
 
                rc = mnt_context_prepare_target(cxt);
515
 
        if (!rc)
516
 
                rc = mnt_context_guess_fstype(cxt);
517
 
        if (!rc)
518
 
                rc = mnt_context_prepare_helper(cxt, "mount", NULL);
519
 
        if (rc) {
520
 
                DBG(CXT, mnt_debug_h(cxt, "mount: preparing failed"));
521
 
                return rc;
522
 
        }
523
 
        cxt->flags |= MNT_FL_PREPARED;
524
 
        return rc;
525
 
}
526
 
 
527
 
/**
528
 
 * mnt_context_do_mount
529
 
 * @cxt: context
530
 
 *
531
 
 * Call mount(2) or mount.<type> helper. Unnecessary for mnt_context_mount().
532
 
 *
533
 
 * WARNING: non-zero return code does not mean that mount(2) syscall or
534
 
 *          umount.type helper wasn't sucessfully called.
535
 
 *
536
 
 *          Check mnt_context_get_status() after error!
537
 
*
538
 
 * Returns: 0 on success;
539
 
 *         >0 in case of mount(2) error (returns syscall errno),
540
 
 *         <0 in case of other errors.
541
 
 */
542
 
int mnt_context_do_mount(struct libmnt_context *cxt)
543
 
{
544
 
        const char *type;
545
 
 
546
 
        assert(cxt);
547
 
        assert(cxt->fs);
548
 
        assert(cxt->helper_exec_status == 1);
549
 
        assert(cxt->syscall_status == 1);
550
 
        assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
551
 
        assert((cxt->flags & MNT_FL_PREPARED));
552
 
        assert((cxt->action == MNT_ACT_MOUNT));
553
 
 
554
 
        DBG(CXT, mnt_debug_h(cxt, "mount: do mount"));
555
 
 
556
 
        if (!(cxt->flags & MNT_FL_MOUNTDATA))
557
 
                cxt->mountdata = (char *) mnt_fs_get_fs_options(cxt->fs);
558
 
 
559
 
        type = mnt_fs_get_fstype(cxt->fs);
560
 
        if (type)
561
 
                return do_mount(cxt, NULL);
562
 
 
563
 
        return do_mount_by_pattern(cxt, cxt->fstype_pattern);
564
 
}
565
 
 
566
 
/**
567
 
 * mnt_context_finalize_mount:
568
 
 * @cxt: context
569
 
 *
570
 
 * Mtab update, etc. Unnecessary for mnt_context_mount(), but should be called
571
 
 * after mnt_context_do_mount(). See also mnt_context_set_syscall_status().
572
 
 *
573
 
 * Returns: negative number on error, 0 on success.
574
 
 */
575
 
int mnt_context_finalize_mount(struct libmnt_context *cxt)
576
 
{
577
 
        int rc;
578
 
 
579
 
        assert(cxt);
580
 
        assert(cxt->fs);
581
 
        assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
582
 
        assert((cxt->flags & MNT_FL_PREPARED));
583
 
 
584
 
        rc = mnt_context_prepare_update(cxt);
585
 
        if (!rc)
586
 
                rc = mnt_context_update_tabs(cxt);;
587
 
        return rc;
588
 
}
589
 
 
590
 
/**
591
 
 * mnt_context_mount:
592
 
 * @cxt: mount context
593
 
 *
594
 
 * High-level, mounts filesystem by mount(2) or fork()+exec(/sbin/mount.type).
595
 
 *
596
 
 * This is similar to:
597
 
 *
598
 
 *      mnt_context_prepare_mount(cxt);
599
 
 *      mnt_context_do_mount(cxt);
600
 
 *      mnt_context_finalize_mount(cxt);
601
 
 *
602
 
 * See also mnt_context_disable_helpers().
603
 
 *
604
 
 * WARNING: non-zero return code does not mean that mount(2) syscall or
605
 
 *          mount.type helper wasn't sucessfully called.
606
 
 *
607
 
 *          Check mnt_context_get_status() after error!
608
 
*
609
 
 * Returns: 0 on success;
610
 
 *         >0 in case of mount(2) error (returns syscall errno),
611
 
 *         <0 in case of other errors.
612
 
 */
613
 
int mnt_context_mount(struct libmnt_context *cxt)
614
 
{
615
 
        int rc;
616
 
 
617
 
        assert(cxt);
618
 
        assert(cxt->fs);
619
 
        assert(cxt->helper_exec_status == 1);
620
 
        assert(cxt->syscall_status == 1);
621
 
 
622
 
        rc = mnt_context_prepare_mount(cxt);
623
 
        if (!rc)
624
 
                rc = mnt_context_prepare_update(cxt);
625
 
        if (!rc)
626
 
                rc = mnt_context_do_mount(cxt);
627
 
 
628
 
        /* TODO: if mtab update is expected then check if the
629
 
         * target is really mounted read-write to avoid 'ro' in
630
 
         * mtab and 'rw' in /proc/mounts.
631
 
         */
632
 
        if (!rc)
633
 
                rc = mnt_context_update_tabs(cxt);
634
 
        return rc;
635
 
}
636