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

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Steve Langasek
  • Date: 2011-06-20 22:31:50 UTC
  • mfrom: (1.6.3 upstream) (4.5.1 sid)
  • Revision ID: james.westby@ubuntu.com-20110620223150-lz8wrv0946ihcz3z
Tags: 2.19.1-2ubuntu1
* Merge from Debian unstable, remaining changes:
  - Build for multiarch.
  - Add pre-depends on multiarch-support.
  - configure.ac: don't try to be clever about extracting a path name from
    $libdir to append to /usr in a way that's not overridable; instead,
    reuse the built-in configurable libexecdir.
  - Fix up the .pc.in files to know about libexecdir, so our substitutions
    don't leave us with unusable pkg-config files.
  - Install custom blkid.conf to use /dev/.blkid.tab since we don't
    expect device names to survive a reboot
  - Mention mountall(8) in fstab(5) manpages, along with its special
    options.
  - Since upstart is required in Ubuntu, the hwclock.sh init script is not
    called on startup and the hwclockfirst.sh init script is removed.
  - Drop depends on initscripts for the above.
  - Replace hwclock udev rule with an Upstart job.
  - For the case where mount is called with a directory to mount, look
    that directory up in mountall's /lib/init/fstab if we couldn't find
    it mentioned anywhere else.  This means "mount /proc", "mount /sys",
    etc. work.
  - mount.8 points to the cifs-utils package, not the obsolete smbfs one. 
* Dropped changes:
  - mount.preinst: lsb_release has been fixed in lucid and above to be
    usable without configuration, so we don't have to diverge from Debian
    here anymore.
* Changes merged upstream:
  - sfdisk support for '+' with '-N'
  - mount/umount.c: fix a segfault on umount with empty mtab entry
  - Fix arbitrary unmount with fuse security issue

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